Commit e1fe9e4f authored by Jörg Höhle's avatar Jörg Höhle Committed by Alexandre Julliard

winmm: Close MCI device after immediate auto-open commands.

parent ef372e25
...@@ -1214,12 +1214,13 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet, ...@@ -1214,12 +1214,13 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet,
{ {
LPWSTR verb, dev, args; LPWSTR verb, dev, args;
LPWINE_MCIDRIVER wmd = 0; LPWINE_MCIDRIVER wmd = 0;
MCIDEVICEID uDevID; MCIDEVICEID uDevID, auto_open = 0;
DWORD dwFlags = 0, dwRet = 0; DWORD dwFlags = 0, dwRet = 0;
int offset = 0; int offset = 0;
DWORD_PTR data[MCI_DATA_SIZE]; DWORD_PTR data[MCI_DATA_SIZE];
DWORD retType; DWORD retType;
LPCWSTR lpCmd = 0; LPCWSTR lpCmd = 0;
WORD wMsg = 0;
static const WCHAR wszNew[] = {'n','e','w',0}; static const WCHAR wszNew[] = {'n','e','w',0};
static const WCHAR wszSAliasS[] = {' ','a','l','i','a','s',' ',0}; static const WCHAR wszSAliasS[] = {' ','a','l','i','a','s',' ',0};
static const WCHAR wszTypeS[] = {'t','y','p','e',' ',0}; static const WCHAR wszTypeS[] = {'t','y','p','e',' ',0};
...@@ -1229,6 +1230,7 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet, ...@@ -1229,6 +1230,7 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet,
TRACE("(%s, %p, %d, %p)\n", TRACE("(%s, %p, %d, %p)\n",
debugstr_w(lpstrCommand), lpstrRet, uRetLen, hwndCallback); debugstr_w(lpstrCommand), lpstrRet, uRetLen, hwndCallback);
if (lpstrRet && uRetLen) *lpstrRet = '\0';
/* format is <command> <device> <optargs> */ /* format is <command> <device> <optargs> */
if (!(verb = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpstrCommand)+1) * sizeof(WCHAR)))) if (!(verb = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpstrCommand)+1) * sizeof(WCHAR))))
...@@ -1338,15 +1340,19 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet, ...@@ -1338,15 +1340,19 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet,
} else if ((MCI_ALL_DEVICE_ID != uDevID) && !(wmd = MCI_GetDriver(mciGetDeviceIDW(dev)))) { } else if ((MCI_ALL_DEVICE_ID != uDevID) && !(wmd = MCI_GetDriver(mciGetDeviceIDW(dev)))) {
/* auto open */ /* auto open */
static const WCHAR wszOpenWait[] = {'o','p','e','n',' ','%','s',' ','w','a','i','t',0}; static const WCHAR wszOpenWait[] = {'o','p','e','n',' ','%','s',' ','w','a','i','t',0};
WCHAR buf[128]; WCHAR buf[138], retbuf[6];
sprintfW(buf, wszOpenWait, dev); snprintfW(buf, sizeof(buf)/sizeof(WCHAR), wszOpenWait, dev);
/* open via mciSendString handles quoting, dev!file syntax and alias creation */
if ((dwRet = mciSendStringW(buf, NULL, 0, 0)) != 0) if ((dwRet = mciSendStringW(buf, retbuf, sizeof(retbuf)/sizeof(WCHAR), 0)) != 0)
goto errCleanUp; goto errCleanUp;
auto_open = strtoulW(retbuf, NULL, 10);
TRACE("auto-opened %u\n", auto_open);
wmd = MCI_GetDriver(mciGetDeviceIDW(dev)); /* FIXME: test for notify flag (how to preparse?) before opening */
/* FIXME: Accept only core commands yet parse them with the specific table */
wmd = MCI_GetDriver(auto_open);
if (!wmd) { if (!wmd) {
/* FIXME: memory leak, MCI driver is not closed */ ERR("No auto-open device %d for %s\n", auto_open, debugstr_w(dev));
dwRet = MCIERR_INVALID_DEVICE_ID; dwRet = MCIERR_INVALID_DEVICE_ID;
goto errCleanUp; goto errCleanUp;
} }
...@@ -1372,6 +1378,7 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet, ...@@ -1372,6 +1378,7 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet,
dwRet = MCIERR_UNRECOGNIZED_COMMAND; dwRet = MCIERR_UNRECOGNIZED_COMMAND;
goto errCleanUp; goto errCleanUp;
} }
wMsg = MCI_GetMessage(lpCmd);
/* set return information */ /* set return information */
switch (retType = MCI_GetReturnType(lpCmd)) { switch (retType = MCI_GetReturnType(lpCmd)) {
...@@ -1389,17 +1396,23 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet, ...@@ -1389,17 +1396,23 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet,
goto errCleanUp; goto errCleanUp;
/* set up call back */ /* set up call back */
if (auto_open) {
if (dwFlags & MCI_NOTIFY) {
dwRet = MCIERR_NOTIFY_ON_AUTO_OPEN;
goto errCleanUp;
}
/* FIXME: the command should get its own notification window set up and
* ask for device closing while processing the notification mechanism.
* hwndCallback = ...
* dwFlags |= MCI_NOTIFY;
* In the meantime special-case all commands but PLAY and RECORD below. */
}
if (dwFlags & MCI_NOTIFY) { if (dwFlags & MCI_NOTIFY) {
data[0] = (DWORD_PTR)hwndCallback; data[0] = (DWORD_PTR)hwndCallback;
} }
/* FIXME: the command should get it's own notification window set up and
* ask for device closing while processing the notification mechanism
*/
if (lpstrRet && uRetLen) *lpstrRet = '\0';
TRACE("[%d, %s, %08x, %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx]\n", TRACE("[%d, %s, %08x, %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx]\n",
wmd ? wmd->wDeviceID : uDevID, MCI_MessageToString(MCI_GetMessage(lpCmd)), dwFlags, wmd ? wmd->wDeviceID : uDevID, MCI_MessageToString(wMsg), dwFlags,
data[0], data[1], data[2], data[3], data[4], data[0], data[1], data[2], data[3], data[4],
data[5], data[6], data[7], data[8], data[9]); data[5], data[6], data[7], data[8], data[9]);
...@@ -1408,13 +1421,20 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet, ...@@ -1408,13 +1421,20 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet,
MCI_UnLoadMciDriver(wmd); MCI_UnLoadMciDriver(wmd);
/* FIXME: notification is not properly shared across two opens */ /* FIXME: notification is not properly shared across two opens */
} else { } else {
dwRet = MCI_SendCommand(wmd ? wmd->wDeviceID : uDevID, MCI_GetMessage(lpCmd), dwFlags, (DWORD_PTR)data); dwRet = MCI_SendCommand(wmd ? wmd->wDeviceID : uDevID, wMsg, dwFlags, (DWORD_PTR)data);
} }
TRACE("=> 1/ %x (%s)\n", dwRet, debugstr_w(lpstrRet)); TRACE("=> 1/ %x (%s)\n", dwRet, debugstr_w(lpstrRet));
dwRet = MCI_HandleReturnValues(dwRet, wmd, retType, data, lpstrRet, uRetLen); dwRet = MCI_HandleReturnValues(dwRet, wmd, retType, data, lpstrRet, uRetLen);
TRACE("=> 2/ %x (%s)\n", dwRet, debugstr_w(lpstrRet)); TRACE("=> 2/ %x (%s)\n", dwRet, debugstr_w(lpstrRet));
errCleanUp: errCleanUp:
if (auto_open) {
/* PLAY and RECORD are the only known non-immediate commands */
if (LOWORD(dwRet) || !(wMsg == MCI_PLAY || wMsg == MCI_RECORD))
MCI_SendCommand(auto_open, MCI_CLOSE, 0, 0);
else
FIXME("leaking auto-open device %u\n", auto_open);
}
HeapFree(GetProcessHeap(), 0, verb); HeapFree(GetProcessHeap(), 0, verb);
return dwRet; return dwRet;
} }
......
...@@ -851,16 +851,13 @@ static void test_AutoOpenWAVE(HWND hwnd) ...@@ -851,16 +851,13 @@ static void test_AutoOpenWAVE(HWND hwnd)
test_notification(hwnd, "sysinfo name outofrange\n", err ? 0 : MCI_NOTIFY_SUCCESSFUL); test_notification(hwnd, "sysinfo name outofrange\n", err ? 0 : MCI_NOTIFY_SUCCESSFUL);
err = mciSendString("play no-such-file-exists.wav notify", buf, sizeof(buf), NULL); err = mciSendString("play no-such-file-exists.wav notify", buf, sizeof(buf), NULL);
if(err==MCIERR_FILE_NOT_FOUND) { /* a Wine detector */ todo_wine ok(err==MCIERR_NOTIFY_ON_AUTO_OPEN,"mci auto-open notify returned %s\n", dbg_mcierr(err));
/* Unsupported auto-open leaves the file open, preventing clean-up */ /* FILE_NOT_FOUND in Wine because auto-open fails before testing the notify flag */
skip("Skipping auto-open tests in Wine\n");
return;
}
test_notification(hwnd, "-prior to auto-open-", 0); test_notification(hwnd, "-prior to auto-open-", 0);
err = mciSendString("play tempfile.wav notify", buf, sizeof(buf), hwnd); err = mciSendString("play tempfile.wav notify", buf, sizeof(buf), hwnd);
todo_wine ok(err==MCIERR_NOTIFY_ON_AUTO_OPEN,"mci auto-open play notify returned %s\n", dbg_mcierr(err)); ok(err==MCIERR_NOTIFY_ON_AUTO_OPEN,"mci auto-open play notify returned %s\n", dbg_mcierr(err));
if(err) /* FIXME: don't open twice yet, it confuses Wine. */ if(err) /* FIXME: don't open twice yet, it confuses Wine. */
err = mciSendString("play tempfile.wav", buf, sizeof(buf), hwnd); err = mciSendString("play tempfile.wav", buf, sizeof(buf), hwnd);
...@@ -874,7 +871,7 @@ static void test_AutoOpenWAVE(HWND hwnd) ...@@ -874,7 +871,7 @@ static void test_AutoOpenWAVE(HWND hwnd)
buf[0]=0; buf[0]=0;
err = mciSendString("sysinfo waveaudio quantity open", buf, sizeof(buf), NULL); err = mciSendString("sysinfo waveaudio quantity open", buf, sizeof(buf), NULL);
ok(!err,"mci sysinfo waveaudio quantity after auto-open returned %s\n", dbg_mcierr(err)); ok(!err,"mci sysinfo waveaudio quantity after auto-open returned %s\n", dbg_mcierr(err));
if(!err) todo_wine ok(!strcmp(buf,"1"), "sysinfo quantity open expected 1, got: %s\n", buf); if(!err) ok(!strcmp(buf,"1"), "sysinfo quantity open expected 1, got: %s\n", buf);
parm.sys.lpstrReturn = (LPSTR)&intbuf[1]; parm.sys.lpstrReturn = (LPSTR)&intbuf[1];
parm.sys.dwRetSize = 2*sizeof(DWORD); /* only one DWORD is used */ parm.sys.dwRetSize = 2*sizeof(DWORD); /* only one DWORD is used */
...@@ -907,9 +904,10 @@ static void test_AutoOpenWAVE(HWND hwnd) ...@@ -907,9 +904,10 @@ static void test_AutoOpenWAVE(HWND hwnd)
ok(!err,"mci status tempfile.wav mode returned %s\n", dbg_mcierr(err)); ok(!err,"mci status tempfile.wav mode returned %s\n", dbg_mcierr(err));
if(!err) ok(!strcmp(buf,"playing"), "mci auto-open status mode, got: %s\n", buf); if(!err) ok(!strcmp(buf,"playing"), "mci auto-open status mode, got: %s\n", buf);
if (0) { /* FIXME: wait until this no more confuses Wine */
err = mciSendString("open tempfile.wav", buf, sizeof(buf), NULL); err = mciSendString("open tempfile.wav", buf, sizeof(buf), NULL);
todo_wine ok(err==MCIERR_DEVICE_OPEN, "mci open from auto-open returned %s\n", dbg_mcierr(err)); todo_wine ok(err==MCIERR_DEVICE_OPEN, "mci open from auto-open returned %s\n", dbg_mcierr(err));
}
/* w2k/xp and Wine differ. While the device is busy playing, it is /* w2k/xp and Wine differ. While the device is busy playing, it is
* regularly open and accessible via the filename: subsequent * regularly open and accessible via the filename: subsequent
* commands must not cause auto-open each. In Wine, a subsequent * commands must not cause auto-open each. In Wine, a subsequent
...@@ -927,11 +925,15 @@ static void test_AutoOpenWAVE(HWND hwnd) ...@@ -927,11 +925,15 @@ static void test_AutoOpenWAVE(HWND hwnd)
trace("Wine style MCI auto-close upon notification\n"); trace("Wine style MCI auto-close upon notification\n");
/* "playing" because auto-close comes after the status call. */ /* "playing" because auto-close comes after the status call. */
todo_wine ok(!strcmp(buf,"playing"), "mci auto-open status mode notify, got: %s\n", buf); ok(!strcmp(buf,"playing"), "mci auto-open status mode notify, got: %s\n", buf);
/* fixme:winmm:MMDRV_Exit Closing while ll-driver open /* fixme:winmm:MMDRV_Exit Closing while ll-driver open
* is explained by failure to auto-close a device. */ * is explained by failure to auto-close a device. */
test_notification(hwnd,"status notify",MCI_NOTIFY_SUCCESSFUL); test_notification(hwnd,"status notify",MCI_NOTIFY_SUCCESSFUL);
/* MCI received NOTIFY_SUPERSEDED and auto-closed the device. */ /* MCI received NOTIFY_SUPERSEDED and auto-closed the device. */
/* Until this is implemented, force closing the device */
err = mciSendString("close tempfile.wav", NULL, 0, hwnd);
ok(!err,"mci auto-still-open stop returned %s\n", dbg_mcierr(err));
Sleep(16); Sleep(16);
test_notification(hwnd,"auto-open",0); test_notification(hwnd,"auto-open",0);
} else if(err==MCIERR_NOTIFY_ON_AUTO_OPEN) { /* MS style */ } else if(err==MCIERR_NOTIFY_ON_AUTO_OPEN) { /* MS style */
...@@ -945,14 +947,14 @@ static void test_AutoOpenWAVE(HWND hwnd) ...@@ -945,14 +947,14 @@ static void test_AutoOpenWAVE(HWND hwnd)
if(!err) ok(!strcmp(buf,"paused"), "mci auto-open status mode, got: %s\n", buf); if(!err) ok(!strcmp(buf,"paused"), "mci auto-open status mode, got: %s\n", buf);
/* Auto-close */ /* Auto-close */
err = mciSendString("stop tempfile.wav", NULL, 0, hwnd); err = mciSendString("stop tempfile.wav wait", NULL, 0, hwnd);
ok(!err,"mci auto-still-open stop returned %s\n", dbg_mcierr(err)); ok(!err,"mci auto-still-open stop returned %s\n", dbg_mcierr(err));
Sleep(16); /* makes sysinfo quantity open below succeed */ Sleep(16); /* makes sysinfo quantity open below succeed */
} }
err = mciSendString("sysinfo waveaudio quantity open", buf, sizeof(buf), NULL); err = mciSendString("sysinfo waveaudio quantity open", buf, sizeof(buf), NULL);
ok(!err,"mci sysinfo waveaudio quantity open after close returned %s\n", dbg_mcierr(err)); ok(!err,"mci sysinfo waveaudio quantity open after close returned %s\n", dbg_mcierr(err));
if(!err) todo_wine ok(!strcmp(buf,"0"), "sysinfo quantity open expected 0 after auto-close, got: %s\n", buf); if(!err) ok(!strcmp(buf,"0"), "sysinfo quantity open expected 0 after auto-close, got: %s\n", buf);
/* w95-WinME (not w2k/XP) switch to C:\ after auto-playing once. Prevent /* w95-WinME (not w2k/XP) switch to C:\ after auto-playing once. Prevent
* MCIERR_FILE_NOT_FOUND by using the full path name from the Info file command. * MCIERR_FILE_NOT_FOUND by using the full path name from the Info file command.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment