I have written some basic C++ programs using the Windows MCI ("Media Control Interface"), notably for playing MIDI and MP3 files. They used to work perfectly on Windows XP. Recently I moved to Windows 10 and now they sometimes work (I have no clue under what conditions), but mostly they terminate immediately, without playing the MP3 or MIDI file. The strange thing is that I get no error indication (nonzero return code). I made sure to include the MCI_WAIT option on all pertinent calls. The programs are command line programs, not graphical. PLEASE HELP!
OK, here is the PLAYSIM(PLE) code in a better readable form (sorry I do not use stackoverflow very often). You will note that the mainline is extremely basic. The type of device in this implementation is inferred from the file type - which always worked marvelously (and an incorrect or unsupported file type causes a message, not a "silent failure"). I tried to precede the OPEN by a CLOSE but that is not allowed. I also looked for some sort of "MCI (re-)initialization call", but did not find it - and it was never needed before.
--->>> For an even simpler version see at the end. That version should be "compileable" on any Windows system.
How can I alert Microsoft to fix this bug???
// ╔══════════════════════════════════════════════╗
// ║..............................................║
// ║.┌────┐.┌┐.....┌────┐.┌┐..┌┐.┌────┐.┌┐.┌────┐.║
// ║.│┌──┐│.││.....│┌──┐│.││..││.│┌───┘.││.│┌┐┌┐│.║
// ║.│└──┘│.││.....│└──┘│.│└──┘│.│└───┐.││.││││││.║
// ║.│┌───┘.││.....│┌──┐│.└─┐┌─┘.└───┐│.││.││└┘││.║
// ║.││.....│└───┐.││..││...││...┌───┘│.││.││..││.║
// ║.└┘.....└────┘.└┘..└┘...└┘...└────┘.└┘.└┘..└┘.║ Reinier Bakels
// ║..............................................║ 17 January 2016
// ╚══════════════════════════════════════════════╝
/*
\borland\bcc55\include\.h
\borland\bcc55\include\mmsystem.h
\borland\bcc55\include\winbase.h
*/
#define NAME_COMMANDS
#include "\rbb\boilerpl.h"
#include "\rbb\dis.h"
#include "\rbb\print.h"
#include "\rbb\ps.h"
#include "\rbb\gct.h" // getCurrentTime()
#include <windows>
#include <mmsystem>
#include <io>
#ifdef NAME_COMMANDS
const char * commandNames[] = {
"" , // 0x0800
"" , // 0x0801
"" , // 0x0802
"Open" , // 0x0803
"Close" , // 0x0804
"Escape" , // 0x0805
"Play" , // 0x0806
"Seek" , // 0x0807
"Stop" , // 0x0808
"Pause" , // 0x0809
"Info" , // 0x080A
"GetDevCaps" , // 0x080B
"Spin" , // 0x080C
"Set" , // 0x080D
"Step" , // 0x080E
"Record" , // 0x080F
"Sysinfo" , // 0x0810
"Break" , // 0x0811
"" , // 0x0812
"Save" , // 0x0813
"Status" // 0x0814
};
#endif
DWORD mci( MCIDEVICEID devID , UINT uCmd , void * parms , DWORD options = 0 )
{
DWORD rc ;
#ifdef NAME_COMMANDS
fputs( commandNames[ uCmd - DRV_MCI_FIRST ] , stdout ); putchar(' ');
#endif
if ( rc = mciSendCommand( devID , uCmd , options , (DWORD) parms )) {
disint( rc );
TCHAR errorMessage[MAXERRORLENGTH];
if ( mciGetErrorString( rc , errorMessage , sizeof errorMessage )) {
CharToOem( errorMessage , errorMessage );
puts( errorMessage );
} else {
puts( "(unknown)" );
} /* endif */
} else {
puts( "OK.");
} /* endif */
return rc ;
}
int main( int argc , char ** argv )
{
boilerPlate();
if ( argc < 2 ) { puts("no arg."); return 0 ; }
char * fileName = *++argv ; disstr( fileName ); if ( access( fileName ,0 )) { say(File does not exist); return 0 ; }
MCI_OPEN_PARMS openParms = {0};
MCI_PLAY_PARMS playParms = {0};
MCI_GENERIC_PARMS genericParms = {0}; // only contains dwCallback
openParms.lpstrElementName = fileName ;
mci(0, MCI_OPEN , & openParms , MCI_WAIT | MCI_OPEN_ELEMENT ); // MCI_OPEN_SHAREABLE not allowed!
MCIDEVICEID devID = openParms.wDeviceID ; if ( devID != 1 ) dishex( devID ); // don't know why, but it seems to be always one
__int64 before = getCurrentTime();
if (! mci( devID, MCI_PLAY , & playParms , MCI_WAIT ))
printf( "\tcompleted with zero return code in %G seconds.\n", 1e-7f * ( getCurrentTime() - before ));
mci( devID, MCI_CLOSE , & genericParms );
return 0 ;
}
Yet simpler:
// PLAYSIM even more simplified
#include <stdio>
#include <windows>
#include <mmsystem>
#include <io>
DWORD mci( const char * commandName , MCIDEVICEID devID , UINT uCmd , void * parms , DWORD options = 0 )
{
DWORD rc = mciSendCommand( devID , uCmd , options , (DWORD) parms );
fputs( commandName , stdout ); puts( rc ? " failed." : " OK." );
return rc ;
}
int main( int argc , char ** argv )
{
if ( argc < 2 ) { puts("no arg."); return 0 ; }
char * fileName = *++argv ; if ( access( fileName ,0 )) { puts( "File does not exist."); return 0 ; }
MCI_OPEN_PARMS openParms = {0};
MCI_PLAY_PARMS playParms = {0};
MCI_GENERIC_PARMS genericParms = {0}; // only contains dwCallback
openParms.lpstrElementName = fileName ;
mci( "Open ", 0 , MCI_OPEN , & openParms , MCI_WAIT | MCI_OPEN_ELEMENT );
mci( "Play " , openParms.wDeviceID , MCI_PLAY , & playParms , MCI_WAIT );
mci( "Close" , openParms.wDeviceID , MCI_CLOSE , & genericParms );
return 0 ;
}