我使用Windows MCI(“媒体控制界面”)编写了一些基本的C ++程序,特别是用于播放MIDI和MP3文件。他们曾经在Windows XP上完美运行。最近我搬到了Windows 10,现在他们有时工作(我不知道在什么条件下),但大多数情况下他们立即终止,而不播放MP3或MIDI文件。奇怪的是我没有错误指示(非零返回码)。 我确保在所有相关的调用中包含MCI_WAIT选项。这些程序是命令行程序,而不是图形程序。 请帮助!
好的,这是PLAYSIM(PLE)代码的更好的可读形式(抱歉,我不经常使用stackoverflow)。 你会注意到主线是非常基本的。此实现中的设备类型是从文件类型推断出来的 - 它总是非常有效(并且不正确或不受支持的文件类型会导致消息,而不是“静默失败”)。 我试图通过CLOSE在OPEN之前,但这是不允许的。 我也寻找某种“MCI(重新)初始化调用”,但没有找到它 - 以前从未需要它。
--->>>对于更简单的版本,请参见最后。该版本应该在任何Windows系统上都是“可编译的”。
如何提醒微软修复此错误?
// ╔══════════════════════════════════════════════╗
// ║..............................................║
// ║.┌────┐.┌┐.....┌────┐.┌┐..┌┐.┌────┐.┌┐.┌────┐.║
// ║.│┌──┐│.││.....│┌──┐│.││..││.│┌───┘.││.│┌┐┌┐│.║
// ║.│└──┘│.││.....│└──┘│.│└──┘│.│└───┐.││.││││││.║
// ║.│┌───┘.││.....│┌──┐│.└─┐┌─┘.└───┐│.││.││└┘││.║
// ║.││.....│└───┐.││..││...││...┌───┘│.││.││..││.║
// ║.└┘.....└────┘.└┘..└┘...└┘...└────┘.└┘.└┘..└┘.║ 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 ;
}
更简单:
// 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 ;
}