GithubHelp home page GithubHelp logo

jpcima / smf-dsp Goto Github PK

View Code? Open in Web Editor NEW
45.0 6.0 5.0 3.41 MB

Advanced MIDI file player

License: Boost Software License 1.0

C++ 99.52% C 0.08% CMake 0.31% Shell 0.01% Faust 0.09%
midi-player midi midi-file synthesizer general-midi realtime chiptune frequency-modulation soundfont ymf262

smf-dsp's Introduction

smf-dsp

Advanced MIDI file player for desktop computer

Build Status

screenshot

Usage

Press F1 for help screen. Press F12 to access advanced options, which can be edited in configuration files.

The changes made in configuration files are effective after restarting.

Some synthesizers require a ROM or SoundFont to be provided, and specified in the configuration.

Keys

The keys are recognized by physical location and not label.

The listed key names are based on the QWERTY keyboard type, it will vary for a different type of layout.

Key Function
F1 Open the help screen
F2 Select a MIDI device for playback
F3 Select a synthesizer device for playback
F4 Configure global audio effects
F9 Select a theme for the user interface
F12 Open the configuration directory
Tab Switch between file browser and track info
Esc Quit the program
- Decrement the proportional window size
= Increment the proportional window size
Page ↑ Go to previous track in playlist/folder
Page ↓ Go to next track in playlist/folder
Space Pause or unpause
Home Seek to beginning of current track
End Seek to end of current track
←↕→ Navigate in the file browser
←→ In track info view, seek track by ± 5 seconds
Shift + ←→ In any view, seek track by ± 10 seconds
[ Decrease speed by 1%
] Increase speed by 1%
` Switch between repeat modes: On/Off, and Single/Multi
/ Scan songs in the current folder of the file browser and play them at random

Building

To build the software, type these commands in the source directory.

  • mkdir build
  • cd build
  • cmake -DCMAKE_BUILD_TYPE=Release ..
  • cmake --build .

Install following packages on Debian/LibraZiK/Mint:

  • build-essential git pkg-config libsdl2-dev libsdl2-image-dev libasound2-dev libpulse-dev libjack-jackd2-dev libuv1-dev libuchardet-dev libglib2.0-dev libapr1-dev libaprutil1-dev

(in case JACK 1 is preferred over JACK 2, replace libjack-jackd2-dev with libjack-dev)

Immediately after building, the program is available by starting ./smf-dsp.

Building synthesizers

The optional synthesizers have additional requirements, and they are built only if these are present.

  • Fluidsynth: check out the thirdparty/fluidlite submodule.
  • FM-OPL3 (ADLMIDI): check out the thirdparty/libADLMIDI submodule.
  • FM-OPN2 (OPNMIDI): check out the thirdparty/libOPNMIDI submodule.
  • SCC (emidi): check out the thirdparty/scc submodule.
  • MT32EMU: check out the thirdparty/munt submodule.

Copyright

The bitmap fonts use glyphs which originate from the following sources.

  • Ths public domain Shinonome font by Yasuyuki Furukawa
  • xorg-fonts-cyrillic and xorg-fonts-misc, for the Cyrillic subset
  • fmplayer by Takamichi Horikawa, for the small font, the digit font, and the logo characters

smf-dsp's People

Contributors

jpcima avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

smf-dsp's Issues

MIDI timestamping

Use a timestamp on MIDI events, which permits to operate nicely at higher latencies.

Theming

Add a theme file which changes style elements.

  • color palette items
  • background BMP

Documentation

Write documentation on controlling the software.
Provide a key description in the software, and also figure out correct usage of keyboard layout with SDL. (currently scancodes are used)

Unable to build under Arch Linux/AUR failure

[ 80%] Building CXX object CMakeFiles/smf-dsp.dir/sources/player/seeker.cc.o
In file included from /home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc:6:
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.h:27:22: error: ‘size_t’ has not been declared
   27 |         void reserve(size_t capacity);
      |                      ^~~~~~
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.h:38:49: error: ‘size_t’ was not declared in this scope; did you mean ‘std::size_t’?
   38 |         std::unordered_map<uint32_t /*raw_id*/, size_t /*index*/> index_of;
      |                                                 ^~~~~~
      |                                                 std::size_t
In file included from /usr/include/c++/11.1.0/type_traits:38,
                 from /usr/include/c++/11.1.0/unordered_map:38,
                 from /home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.h:7,
                 from /home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc:6:
/usr/include/c++/11.1.0/x86_64-pc-linux-gnu/bits/c++config.h:280:33: note: ‘std::size_t’ declared here
  280 |   typedef __SIZE_TYPE__         size_t;
      |                                 ^~~~~~
In file included from /home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc:6:
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.h:38:65: error: template argument 2 is invalid
   38 |     std::unordered_map<uint32_t /*raw_id*/, size_t /*index*/> index_of;
      |                                                             ^

/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.h:38:65: error: template argument 5 is invalid
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc:34:18: error: ‘size_t’ does not name a type
   34 | static constexpr size_t initial_capacity = 256;
      |                  ^~~~~~
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc:7:1: note: ‘size_t’ is defined in header ‘<cstddef>’; did you forget to ‘#include <cstddef>’?
    6 | #include "seeker.h"
  +++ |+#include <cstddef>
    7 | 
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc: In constructor ‘Seek_State::Seek_State()’:
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc:38:22: error: ‘initial_capacity’ was not declared in this scope
   38 |     storage_.reserve(initial_capacity);
      |                      ^~~~~~~~~~~~~~~~
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc: In member function ‘void Seek_State::add_reset_all_controllers(unsigned int)’:
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc:149:18: error: ‘initial_capacity’ was not declared in this scope
  149 |     temp.reserve(initial_capacity);
      |                  ^~~~~~~~~~~~~~~~
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc: In member function ‘void Seek_State::Storage::clear()’:
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc:323:14: error: request for member ‘clear’ in ‘((Seek_State::Storage*)this)->Seek_State::Storage::index_of’, which is of non-class type ‘int’
  323 |     index_of.clear();
      |              ^~~~~
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc: At global scope:
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc:326:6: error: variable or field ‘reserve’ declared void
  326 | void Seek_State::Storage::reserve(size_t capacity)
      |      ^~~~~~~~~~
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc:326:6: error: ‘struct Seek_State::Storage’ is private within this context
In file included from /home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc:6:
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.h:25:12: note: declared private here
   25 |     struct Storage {
      |            ^~~~~~~
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc:326:35: error: ‘size_t’ was not declared in this scope; did you mean ‘std::size_t’?
  326 | void Seek_State::Storage::reserve(size_t capacity)
      |                                   ^~~~~~
      |                                   std::size_t
In file included from /usr/include/c++/11.1.0/type_traits:38,
                 from /usr/include/c++/11.1.0/unordered_map:38,
                 from /home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.h:7,
                 from /home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc:6:
/usr/include/c++/11.1.0/x86_64-pc-linux-gnu/bits/c++config.h:280:33: note: ‘std::size_t’ declared here
  280 |   typedef __SIZE_TYPE__         size_t;
      |                                 ^~~~~~
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc: In member function ‘void Seek_State::Storage::put(uint32_t, uint32_t)’:
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc:336:24: error: request for member ‘find’ in ‘((Seek_State::Storage*)this)->Seek_State::Storage::index_of’, which is of non-class type ‘int’
  336 |     auto it = index_of.find(raw_id);
      |                        ^~~~
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc:337:24: error: request for member ‘end’ in ‘((Seek_State::Storage*)this)->Seek_State::Storage::index_of’, which is of non-class type ‘int’
  337 |     if (it != index_of.end())
      |                        ^~~
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc:340:9: error: ‘size_t’ was not declared in this scope; did you mean ‘std::size_t’?
  340 |         size_t index = assoc.size();
      |         ^~~~~~
      |         std::size_t
In file included from /usr/include/c++/11.1.0/type_traits:38,
                 from /usr/include/c++/11.1.0/unordered_map:38,
                 from /home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.h:7,
                 from /home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc:6:
/usr/include/c++/11.1.0/x86_64-pc-linux-gnu/bits/c++config.h:280:33: note: ‘std::size_t’ declared here
  280 |   typedef __SIZE_TYPE__         size_t;
      |                                 ^~~~~~
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc:342:17: error: invalid types ‘int[uint32_t {aka unsigned int}]’ for array subscript
  342 |         index_of[raw_id] = index;
      |                 ^
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc:342:28: error: ‘index’ was not declared in this scope
  342 |         index_of[raw_id] = index;
      |                            ^~~~~
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc: In member function ‘const uint32_t* Seek_State::Storage::find(uint32_t) const’:
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc:358:24: error: request for member ‘find’ in ‘((const Seek_State::Storage*)this)->Seek_State::Storage::index_of’, which is of non-class type ‘const int’
  358 |     auto it = index_of.find(raw_id);
      |                        ^~~~
/home/anon/smf-dsp-git/src/smf-dsp/sources/player/seeker.cc:359:28: error: request for member ‘end’ in ‘((const Seek_State::Storage*)this)->Seek_State::Storage::index_of’, which is of non-class type ‘const int’
  359 |     return (it != index_of.end()) ? &assoc[it->second].value : nullptr;
      |                            ^~~
make[2]: *** [CMakeFiles/smf-dsp.dir/build.make:188: CMakeFiles/smf-dsp.dir/sources/player/seeker.cc.o] Błąd 1

[Feature request] Ability to use two MIDI synths at once

OPN2, provided by libOPNMIDI, has a very low polyphony. Even with 2 cores, it's just 12 channels. Some MIDIs, most often these written for SC-88Pro synth, require up to 40 channels. While you can raise the amount of cores, at some point, MIDI playback may become heavy for some weaker devices. Also, some MIDI timbres, like drums, would sound somewhat better with PCM-based device.

Since this player supports multiple synths, also sf2 based like Fluidsynth, would it be possible to "mix" two midi snth instances. One synth would play some MIDI channels (specified in config file), other the rest. That would also allow for some kind of Sound Blaster 16 PCM emulation when mixed with libADLMIDI. Is it feasible, or in scope of this program?

Segmentation fault at start (Arch Linux)

22:18:44.976 [*] success New window: 0x5584795d6e80
22:18:44.976 [-] info Creating renderer
22:17:53.438 [x] error Could not open synth:
Naruszenie ochrony pamięci (zrzut pamięci)
malloc(): unaligned tcache chunk detected, followed by segmentation fault.

[Feature request] Ability to convert MIDI to WAV

Two submodules (libADLMIDI and OPNMIDI) already support WAV logging as a part of their libraries iirc. VGM logging is realized by utility that's part of their respective projects. Would it be possible to add such options?

Add more GS MIDI resets

The sequel to #24 - sometimes, MIDI program names still won't appear.
GSMIDI.zip - contain a few examples of such songs. Most of these should be Edirol SD-20/SC-8820, however PASSPORT.MID and CANYON.MID... aren't they plain SC-55 songs? Why is one instrument name not recognized?

[Feature idea] Ability to change OPL/OPN emulation core

Currently, there is no way for that, it uses ADL/OPNMIDI default it seems, while:

ADLMIDI supports three usable emus: Nuked 1.8, DOSBox and JavaOPL3;
OPNMIDI has Nuked OPN2, MAME YM2612, Genesis Plus GX MAME fork, and OPNA FM cores from MAME and Neko Project 2.

Initial delay

When a track playback emits events very early as it starts, a series of events are going to play in immediate succession in a short time frame, disregarding the deltas.

It's because of the voluntary MIDI delay of 1 audio buffer, which serves to give room to process the timestamps.

MUS support?

Great player, thanks for it.

Yet one thing it lacks is .mus support, since both libADL and libOPNMIDI can handle it. Would it be possible to add that?

Program is very laggy and unstable under Windows

Under Linux, SMF-DSP works fine, without any problems whatsoever. Under Windows 10 x64, with same hardware, it is unusable:

  • up to 14 seconds delay between selecting the midi file and any sound starting to play
  • no sync between piano display and audio
  • extreme lag, songs are played back at fraction of their speed
  • player often ends up unresponding, mostly when trying to close it

What's weird it doesn't use more than 5% of CPU 🤔 Version I downloaded is 32-bit Windows artifact from Github Actions.

[Feature idea] Ability to change OPL3 volume model

libADLMIDI has support for several volume models that were featured in different sound drivers. Now that work has resumed, these volume models were fixed and new are now implemented. Therefore, it is needed to update submodule.

Volume models:

  • linear "Generic"
  • logarithmic, native OPL3
  • indexed "DMX" (translates MIDI volume into OPL3 volume)
  • semi-logarithmic "Apogee"
  • Win9x (short, only 32 steps)
  • new "Fixed DMX" that fixes bug in original DMX driver where AM instruments had broken AM instrument processing (carrier 2 always had TL=63 IIRC)
  • new "Fixed Apogee" that fixes bug where OP1 on AM instruments was silent

ERROR

~/smf-dsp/build$ cmake -DCMAKE_BUILD_TYPE=Release ..
-- Cannot find soundio
-- Configuring done (0.2s)
CMake Error at CMakeLists.deps.txt:262 (add_library):
Cannot find source file:

thirdparty/fluidlite/src/fluid_chan.c

Tried extensions .c .C .c++ .cc .cpp .cxx .cu .mpp .m .M .mm .ixx .cppm
.ccm .cxxm .c++m .h .hh .h++ .hm .hpp .hxx .in .txx .f .F .for .f77 .f90
.f95 .f03 .hip .ispc
Call Stack (most recent call first):
CMakeLists.txt:102 (include)

CMake Error at CMakeLists.deps.txt:286 (add_library):
Cannot find source file:

thirdparty/libADLMIDI/src/adlmidi.cpp

Tried extensions .c .C .c++ .cc .cpp .cxx .cu .mpp .m .M .mm .ixx .cppm
.ccm .cxxm .c++m .h .hh .h++ .hm .hpp .hxx .in .txx .f .F .for .f77 .f90
.f95 .f03 .hip .ispc
Call Stack (most recent call first):
CMakeLists.txt:102 (include)

CMake Error at CMakeLists.deps.txt:311 (add_library):
Cannot find source file:

thirdparty/libOPNMIDI/src/opnmidi.cpp

Tried extensions .c .C .c++ .cc .cpp .cxx .cu .mpp .m .M .mm .ixx .cppm
.ccm .cxxm .c++m .h .hh .h++ .hm .hpp .hxx .in .txx .f .F .for .f77 .f90
.f95 .f03 .hip .ispc
Call Stack (most recent call first):
CMakeLists.txt:102 (include)

CMake Error at CMakeLists.deps.txt:351 (add_library):
Cannot find source file:

thirdparty/scc/emidi_alpha/CEnvelope.cpp

Tried extensions .c .C .c++ .cc .cpp .cxx .cu .mpp .m .M .mm .ixx .cppm
.ccm .cxxm .c++m .h .hh .h++ .hm .hpp .hxx .in .txx .f .F .for .f77 .f90
.f95 .f03 .hip .ispc
Call Stack (most recent call first):
CMakeLists.txt:102 (include)

CMake Error at CMakeLists.deps.txt:367 (add_library):
Cannot find source file:

thirdparty/munt/mt32emu/src/Analog.cpp

Tried extensions .c .C .c++ .cc .cpp .cxx .cu .mpp .m .M .mm .ixx .cppm
.ccm .cxxm .c++m .h .hh .h++ .hm .hpp .hxx .in .txx .f .F .for .f77 .f90
.f95 .f03 .hip .ispc
Call Stack (most recent call first):
CMakeLists.txt:102 (include)

CMake Error at CMakeLists.deps.txt:415 (add_library):
Cannot find source file:

thirdparty/timidityplus/common.cpp

Tried extensions .c .C .c++ .cc .cpp .cxx .cu .mpp .m .M .mm .ixx .cppm
.ccm .cxxm .c++m .h .hh .h++ .hm .hpp .hxx .in .txx .f .F .for .f77 .f90
.f95 .f03 .hip .ispc
Call Stack (most recent call first):
CMakeLists.txt:102 (include)

CMake Error at CMakeLists.deps.txt:262 (add_library):
No SOURCES given to target: fluidsynth
Call Stack (most recent call first):
CMakeLists.txt:102 (include)

CMake Error at CMakeLists.deps.txt:286 (add_library):
No SOURCES given to target: adlmidi
Call Stack (most recent call first):
CMakeLists.txt:102 (include)

CMake Error at CMakeLists.deps.txt:311 (add_library):
No SOURCES given to target: opnmidi
Call Stack (most recent call first):
CMakeLists.txt:102 (include)

CMake Error at CMakeLists.deps.txt:351 (add_library):
No SOURCES given to target: scc
Call Stack (most recent call first):
CMakeLists.txt:102 (include)

CMake Error at CMakeLists.deps.txt:367 (add_library):
No SOURCES given to target: mt32emu
Call Stack (most recent call first):
CMakeLists.txt:102 (include)

CMake Error at CMakeLists.deps.txt:415 (add_library):
No SOURCES given to target: timiditypp
Call Stack (most recent call first):
CMakeLists.txt:102 (include)

CMake Generate step failed. Build files cannot be regenerated correctly.

Windows build from GHA doesn't work

On startup, error message shows up:
Entry Point Not Found _ZSt14_once_functor in library \pathtosmfdsp\icuuc70.dll

File is present in the folder. OS is Windows 10 Enterprise 21H2 x64.

Text with special characters

The path to the right of the FILE: label cannot display a special character, because the font does not have it. (eg É)

In this case of unmatched character, make the unicode decomposition, and pick the non-accented character as replacement.

Synth plugin support

Provide synthesizers as plugin directly into the program.

  • interface of synth plugins
  • settings file: for defining soundfont, bank, etc

Synthesizer list

  • Fluidsynth
  • libADLMIDI
  • libOPNMIDI
  • SCC EmuDeMidi
  • MT32Emu
    etc

Unable to build under Linux Mint 20.1

Running cmake -DCMAKE_BUILD_TYPE=Release .. produces:

-- The C compiler identification is GNU 9.3.0
-- The CXX compiler identification is GNU 9.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.1")
-- Checking for module 'alsa'
-- Found alsa, version 1.2.2
-- Checking for module 'libpulse-simple'
-- Found libpulse-simple, version 13.99.1
-- Cannot find soundio
-- Checking for module 'jack'
-- Found jack, version 1.9.12
CMake Warning at CMakeLists.deps.txt:159 (message):
Cannot find library SDL2_image
Call Stack (most recent call first):
CMakeLists.txt:55 (include)

-- Checking for module 'glib-2.0'
-- Found glib-2.0, version 2.64.6
-- Checking for module 'gio-2.0'
-- Found gio-2.0, version 2.64.6
CMake Error at CMakeLists.deps.txt:175 (add_library):
add_library cannot create ALIAS target "sys::glib" because target
"PkgConfig::glib" is imported but not globally visible.
Call Stack (most recent call first):
CMakeLists.txt:55 (include)

CMake Error at CMakeLists.deps.txt:176 (add_library):
add_library cannot create ALIAS target "sys::gio" because target
"PkgConfig::gio" is imported but not globally visible.
Call Stack (most recent call first):
CMakeLists.txt:55 (include)

-- Checking for module 'libuv'
-- Found libuv, version 1.34.2
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Configuring incomplete, errors occurred!
See also "/home/anon/smf-dsp/build/CMakeFiles/CMakeOutput.log".
See also "/home/anon/smf-dsp/build/CMakeFiles/CMakeError.log".

Every dependency listed in README has been installed.

Support of Haiku OS

  • audio
  • midi

Thing to do:

  • implement support this OS in RtMidi (& RtAudio) also

A segmentation fault

#11 0x0000561c765115db in Midi_Synth_Instrument::audio_callback(float*, unsigned int, void*)
    (output=0x40, nframes=2348887296, user_data=0x7fda8c03ab80) at sources/player/instrument.cc:284
#12 0x0000561c76514c64 in Audio_Device::process_cycle(float*, unsigned int)
    (this=0x7fda8c0021b0, output=0x7fda8c012010, nframes=512) at sources/player/adev/adev.cc:45
#13 0x0000561c76515201 in Audio_Device_Jack::jack_audio_callback(unsigned int, void*) (nframes=512, user_data=0x7fda8c0021b0)
    at sources/player/adev/adev_jack.cc:81

`make_path_absolute` can be wrong when path contains symlinks

It will be wrong to simplify a path by elimination of foo/../ kind of patterns, in case foo is a symlink.

The directory part of path may be resolved by file system API:

  • POSIX realpath
  • Windows GetFinalPathNameByHandleA (_WIN32_WINNT >= 0x0600)
  • Older Windows has no symlinks, so it's fine to use the old method.
HANDLE hDirectory = CreateFile(
    path,
    0,
    FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
    nullptr,
    OPEN_EXISTING,
    FILE_FLAG_BACKUP_SEMANTICS,
    nullptr);

GetFinalPathNameByHandleA(
    hDirectory,
    path,
    pathlen,
    VOLUME_NAME_DOS|FILE_NAME_NORMALIZED);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.