When the path+filename of a file is really long, I've noticed that
PlaySound(fName.c_str(), NULL, SND_ASYNC);
works, but not
mciSendString((L"open \"" + fName + L"\" type waveaudio alias sample").c_str(), NULL, 0, NULL);
mciSendString(L"play sample", NULL, 0, NULL);
Example of failing command:
open "C:\qisdjqldlkjsqdjqdqjslkdjqlksjlkdjqsldjlqjsdjqdksq\dajdjqjdlqjdlkjazejoizajoijoifjoifjdsfjsfszjfoijdsjfoijdsoifoidsjfojdsofjdsoijfoisjfoijoisdjfosjfqsd\Windows Critical Stop.wav" type waveaudio alias sample
But:
I really need mciSendString instead of PlaySound(), because PlaySound() doesn't play certain files (48 khz audio files, sometimes 24-bit files, etc.)
I need to be able to play audio files with potentially long paths because the end user of my app might have such files
How to make mciSendString accept long filenames?
Notes:
I've also tried with this MSDN example using mciSendCommand, but it's the same.
The max path+filename length is 127 (127: working, 128+: not working)
If really it's impossible to make mci*
functions work with longer-than-127-char filenames, what could I use instead, just with winapi (without external libraries)? (PlaySound
is not an option because doesn't work realiably with all the wav files, such as 48 khz: non-working, etc.)
The 127 limit looks strange. I didn't find any information on MSDN about it.
There is an alternative syntax to open: open waveaudio!right.wav
An option You could try is to change the working directory to the directory of the file, then the limit only applies to filename. -> SetCurrentDiectory
To shorten the filename a Winapi function can be used GetShortPathName
But:
SMB 3.0 does not support short names on shares with continuous availability capability.
Resilient File System (ReFS) doesn't support short names. If you call GetShortPathName on a path that doesn't have any short names on-disk, the call will succeed, but will return the long-name path instead. This outcome is also possible with NTFS volumes because there's no guarantee that a short name will exist for a given long name.
Based on example from MSDN:
#include <string>
#include <Windows.h>
template<typename StringType>
std::pair<bool, StringType> shortPathName( const StringType& longPathName )
{
// First obtain the size needed by passing NULL and 0.
long length = GetShortPathName( longPathName.c_str(), NULL, 0 );
if (length == 0) return std::make_pair( false, StringType() );
// Dynamically allocate the correct size
// (terminating null char was included in length)
StringType shortName( length, ' ' );
// Now simply call again using same long path.
length = GetShortPathName( longPathName.c_str(), &shortName[ 0 ], length );
if (length == 0) return std::make_pair( false, StringType() );
return std::make_pair(true, shortName);
}
#include <locale>
#include <codecvt>
#include <iostream>
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
//std::string narrow = converter.to_bytes( wide_utf16_source_string );
//std::wstring wide = converter.from_bytes( narrow_utf8_source_string );
int main( int argc, char** argv )
{
std::wstring myPath = converter.from_bytes( argv[0] );
auto result = shortPathName( myPath );
if (result.first)
std::wcout << result.second ;
return 0;
}