mciqtz32: Fix notify flag behavior.
This commit is contained in:
parent
e252489a98
commit
0221688cdd
|
@ -85,6 +85,7 @@ static DWORD MCIQTZ_drvOpen(LPCWSTR str, LPMCI_OPEN_DRIVER_PARMSW modp)
|
||||||
if (!wma)
|
if (!wma)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
wma->stop_event = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||||
modp->wType = MCI_DEVTYPE_DIGITAL_VIDEO;
|
modp->wType = MCI_DEVTYPE_DIGITAL_VIDEO;
|
||||||
wma->wDevID = modp->wDeviceID;
|
wma->wDevID = modp->wDeviceID;
|
||||||
modp->wCustomCommandTable = wma->command_table = mciLoadCommandResource(MCIQTZ_hInstance, mciAviWStr, 0);
|
modp->wCustomCommandTable = wma->command_table = mciLoadCommandResource(MCIQTZ_hInstance, mciAviWStr, 0);
|
||||||
|
@ -110,6 +111,7 @@ static DWORD MCIQTZ_drvClose(DWORD dwDevID)
|
||||||
|
|
||||||
mciFreeCommandResource(wma->command_table);
|
mciFreeCommandResource(wma->command_table);
|
||||||
mciSetDriverData(dwDevID, 0);
|
mciSetDriverData(dwDevID, 0);
|
||||||
|
CloseHandle(wma->stop_event);
|
||||||
HeapFree(GetProcessHeap(), 0, wma);
|
HeapFree(GetProcessHeap(), 0, wma);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -137,6 +139,20 @@ static DWORD MCIQTZ_drvConfigure(DWORD dwDevID)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* MCIQTZ_mciNotify [internal]
|
||||||
|
*
|
||||||
|
* Notifications in MCI work like a 1-element queue.
|
||||||
|
* Each new notification request supersedes the previous one.
|
||||||
|
*/
|
||||||
|
static void MCIQTZ_mciNotify(DWORD_PTR hWndCallBack, WINE_MCIQTZ* wma, UINT wStatus)
|
||||||
|
{
|
||||||
|
MCIDEVICEID wDevID = wma->notify_devid;
|
||||||
|
HANDLE old = InterlockedExchangePointer(&wma->callback, NULL);
|
||||||
|
if (old) mciDriverNotify(old, wDevID, MCI_NOTIFY_SUPERSEDED);
|
||||||
|
mciDriverNotify(HWND_32(LOWORD(hWndCallBack)), wDevID, wStatus);
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* MCIQTZ_mciOpen [internal]
|
* MCIQTZ_mciOpen [internal]
|
||||||
*/
|
*/
|
||||||
|
@ -306,6 +322,63 @@ static DWORD MCIQTZ_mciClose(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpP
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* MCIQTZ_notifyThread [internal]
|
||||||
|
*/
|
||||||
|
static DWORD CALLBACK MCIQTZ_notifyThread(LPVOID parm)
|
||||||
|
{
|
||||||
|
WINE_MCIQTZ* wma = (WINE_MCIQTZ *)parm;
|
||||||
|
HRESULT hr;
|
||||||
|
HANDLE handle[2];
|
||||||
|
DWORD n = 0, ret = 0;
|
||||||
|
|
||||||
|
handle[n++] = wma->stop_event;
|
||||||
|
IMediaEvent_GetEventHandle(wma->mevent, (OAEVENT *)&handle[n++]);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
DWORD r;
|
||||||
|
HANDLE old;
|
||||||
|
|
||||||
|
r = WaitForMultipleObjects(n, handle, FALSE, INFINITE);
|
||||||
|
if (r == WAIT_OBJECT_0) {
|
||||||
|
TRACE("got stop event\n");
|
||||||
|
old = InterlockedExchangePointer(&wma->callback, NULL);
|
||||||
|
if (old)
|
||||||
|
mciDriverNotify(old, wma->notify_devid, MCI_NOTIFY_ABORTED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (r == WAIT_OBJECT_0+1) {
|
||||||
|
LONG event_code;
|
||||||
|
LONG_PTR p1, p2;
|
||||||
|
do {
|
||||||
|
hr = IMediaEvent_GetEvent(wma->mevent, &event_code, &p1, &p2, 0);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
TRACE("got event_code = 0x%02x\n", event_code);
|
||||||
|
IMediaEvent_FreeEventParams(wma->mevent, event_code, p1, p2);
|
||||||
|
}
|
||||||
|
} while (hr == S_OK && event_code != EC_COMPLETE);
|
||||||
|
if (hr == S_OK && event_code == EC_COMPLETE) {
|
||||||
|
old = InterlockedExchangePointer(&wma->callback, NULL);
|
||||||
|
if (old)
|
||||||
|
mciDriverNotify(old, wma->notify_devid, MCI_NOTIFY_SUCCESSFUL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TRACE("Unknown error (%d)\n", (int)r);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = IMediaControl_Stop(wma->pmctrl);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
TRACE("Cannot stop filtergraph (hr = %x)\n", hr);
|
||||||
|
ret = MCIERR_INTERNAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* MCIQTZ_mciPlay [internal]
|
* MCIQTZ_mciPlay [internal]
|
||||||
*/
|
*/
|
||||||
|
@ -326,6 +399,14 @@ static DWORD MCIQTZ_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms
|
||||||
if (!wma)
|
if (!wma)
|
||||||
return MCIERR_INVALID_DEVICE_ID;
|
return MCIERR_INVALID_DEVICE_ID;
|
||||||
|
|
||||||
|
ResetEvent(wma->stop_event);
|
||||||
|
if (dwFlags & MCI_NOTIFY) {
|
||||||
|
HANDLE old;
|
||||||
|
old = InterlockedExchangePointer(&wma->callback, HWND_32(LOWORD(lpParms->dwCallback)));
|
||||||
|
if (old)
|
||||||
|
mciDriverNotify(old, wma->notify_devid, MCI_NOTIFY_ABORTED);
|
||||||
|
}
|
||||||
|
|
||||||
IMediaSeeking_GetTimeFormat(wma->seek, &format);
|
IMediaSeeking_GetTimeFormat(wma->seek, &format);
|
||||||
if (dwFlags & MCI_FROM) {
|
if (dwFlags & MCI_FROM) {
|
||||||
if (IsEqualGUID(&format, &TIME_FORMAT_MEDIA_TIME))
|
if (IsEqualGUID(&format, &TIME_FORMAT_MEDIA_TIME))
|
||||||
|
@ -352,8 +433,11 @@ static DWORD MCIQTZ_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms
|
||||||
|
|
||||||
IVideoWindow_put_Visible(wma->vidwin, OATRUE);
|
IVideoWindow_put_Visible(wma->vidwin, OATRUE);
|
||||||
|
|
||||||
if (dwFlags & MCI_NOTIFY)
|
wma->thread = CreateThread(NULL, 0, MCIQTZ_notifyThread, wma, 0, NULL);
|
||||||
mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)), wDevID, MCI_NOTIFY_SUCCESSFUL);
|
if (!wma->thread) {
|
||||||
|
TRACE("Can't create thread\n");
|
||||||
|
return MCIERR_INTERNAL;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,7 +481,7 @@ static DWORD MCIQTZ_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dwFlags & MCI_NOTIFY)
|
if (dwFlags & MCI_NOTIFY)
|
||||||
mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)), wDevID, MCI_NOTIFY_SUCCESSFUL);
|
MCIQTZ_mciNotify(lpParms->dwCallback, wma, MCI_NOTIFY_SUCCESSFUL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -408,7 +492,6 @@ static DWORD MCIQTZ_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms
|
||||||
static DWORD MCIQTZ_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
|
static DWORD MCIQTZ_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
|
||||||
{
|
{
|
||||||
WINE_MCIQTZ* wma;
|
WINE_MCIQTZ* wma;
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
|
TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
|
||||||
|
|
||||||
|
@ -419,10 +502,11 @@ static DWORD MCIQTZ_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpPa
|
||||||
if (!wma->opened)
|
if (!wma->opened)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
hr = IMediaControl_Stop(wma->pmctrl);
|
if (wma->thread) {
|
||||||
if (FAILED(hr)) {
|
SetEvent(wma->stop_event);
|
||||||
TRACE("Cannot stop filtergraph (hr = %x)\n", hr);
|
WaitForSingleObject(wma->thread, INFINITE);
|
||||||
return MCIERR_INTERNAL;
|
CloseHandle(wma->thread);
|
||||||
|
wma->thread = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wma->parent)
|
if (!wma->parent)
|
||||||
|
@ -676,19 +760,9 @@ static DWORD MCIQTZ_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_DGV_STATUS_PARMS
|
||||||
if (state == State_Stopped)
|
if (state == State_Stopped)
|
||||||
lpParms->dwReturn = MAKEMCIRESOURCE(MCI_MODE_STOP, MCI_MODE_STOP);
|
lpParms->dwReturn = MAKEMCIRESOURCE(MCI_MODE_STOP, MCI_MODE_STOP);
|
||||||
else if (state == State_Running) {
|
else if (state == State_Running) {
|
||||||
LONG code;
|
|
||||||
LONG_PTR p1, p2;
|
|
||||||
|
|
||||||
lpParms->dwReturn = MAKEMCIRESOURCE(MCI_MODE_PLAY, MCI_MODE_PLAY);
|
lpParms->dwReturn = MAKEMCIRESOURCE(MCI_MODE_PLAY, MCI_MODE_PLAY);
|
||||||
|
if (!wma->thread || WaitForSingleObject(wma->thread, 0) == WAIT_OBJECT_0)
|
||||||
do {
|
lpParms->dwReturn = MAKEMCIRESOURCE(MCI_MODE_STOP, MCI_MODE_STOP);
|
||||||
hr = IMediaEvent_GetEvent(wma->mevent, &code, &p1, &p2, 0);
|
|
||||||
if (hr == S_OK && code == EC_COMPLETE){
|
|
||||||
lpParms->dwReturn = MAKEMCIRESOURCE(MCI_MODE_STOP, MCI_MODE_STOP);
|
|
||||||
IMediaControl_Stop(wma->pmctrl);
|
|
||||||
}
|
|
||||||
} while (hr == S_OK);
|
|
||||||
|
|
||||||
} else if (state == State_Paused)
|
} else if (state == State_Paused)
|
||||||
lpParms->dwReturn = MAKEMCIRESOURCE(MCI_MODE_PAUSE, MCI_MODE_PAUSE);
|
lpParms->dwReturn = MAKEMCIRESOURCE(MCI_MODE_PAUSE, MCI_MODE_PAUSE);
|
||||||
ret = MCI_RESOURCE_RETURNED;
|
ret = MCI_RESOURCE_RETURNED;
|
||||||
|
@ -714,7 +788,7 @@ static DWORD MCIQTZ_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_DGV_STATUS_PARMS
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dwFlags & MCI_NOTIFY)
|
if (dwFlags & MCI_NOTIFY)
|
||||||
mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)), wDevID, MCI_NOTIFY_SUCCESSFUL);
|
MCIQTZ_mciNotify(lpParms->dwCallback, wma, MCI_NOTIFY_SUCCESSFUL);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,11 @@ typedef struct {
|
||||||
IBasicAudio* audio;
|
IBasicAudio* audio;
|
||||||
DWORD time_format;
|
DWORD time_format;
|
||||||
UINT command_table;
|
UINT command_table;
|
||||||
HWND parent;
|
HWND parent;
|
||||||
|
MCIDEVICEID notify_devid;
|
||||||
|
HANDLE callback;
|
||||||
|
HANDLE thread;
|
||||||
|
HANDLE stop_event;
|
||||||
} WINE_MCIQTZ;
|
} WINE_MCIQTZ;
|
||||||
|
|
||||||
#endif /* __WINE_PRIVATE_MCIQTZ_H */
|
#endif /* __WINE_PRIVATE_MCIQTZ_H */
|
||||||
|
|
|
@ -1376,7 +1376,7 @@ static void test_asyncWaveTypeMpegvideo(HWND hwnd)
|
||||||
err = mciSendStringA("status mysound mode notify", buf, sizeof(buf), hwnd);
|
err = mciSendStringA("status mysound mode notify", buf, sizeof(buf), hwnd);
|
||||||
ok(!err,"mci status mode returned %s\n", dbg_mcierr(err));
|
ok(!err,"mci status mode returned %s\n", dbg_mcierr(err));
|
||||||
if(!err) ok(!strcmp(buf,"paused"), "mci status mode: %s\n", buf);
|
if(!err) ok(!strcmp(buf,"paused"), "mci status mode: %s\n", buf);
|
||||||
todo_wine test_notification(hwnd,"play (superseded)",MCI_NOTIFY_SUPERSEDED);
|
test_notification(hwnd,"play (superseded)",MCI_NOTIFY_SUPERSEDED);
|
||||||
test_notification(hwnd,"status",MCI_NOTIFY_SUCCESSFUL);
|
test_notification(hwnd,"status",MCI_NOTIFY_SUCCESSFUL);
|
||||||
|
|
||||||
err = mciSendStringA("seek mysound to start wait", NULL, 0, NULL);
|
err = mciSendStringA("seek mysound to start wait", NULL, 0, NULL);
|
||||||
|
@ -1388,11 +1388,11 @@ static void test_asyncWaveTypeMpegvideo(HWND hwnd)
|
||||||
err = mciSendStringA("play mysound to 1500 notify", NULL, 0, hwnd);
|
err = mciSendStringA("play mysound to 1500 notify", NULL, 0, hwnd);
|
||||||
ok(!err,"mci play returned %s\n", dbg_mcierr(err));
|
ok(!err,"mci play returned %s\n", dbg_mcierr(err));
|
||||||
Sleep(200);
|
Sleep(200);
|
||||||
todo_wine test_notification(hwnd,"play",0);
|
test_notification(hwnd,"play",0);
|
||||||
|
|
||||||
err = mciSendStringA("close mysound wait", NULL, 0, NULL);
|
err = mciSendStringA("close mysound wait", NULL, 0, NULL);
|
||||||
ok(!err,"mci close wait returned %s\n", dbg_mcierr(err));
|
ok(!err,"mci close wait returned %s\n", dbg_mcierr(err));
|
||||||
todo_wine test_notification(hwnd,"play (aborted by close)",MCI_NOTIFY_ABORTED);
|
test_notification(hwnd,"play (aborted by close)",MCI_NOTIFY_ABORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
START_TEST(mci)
|
START_TEST(mci)
|
||||||
|
|
Loading…
Reference in New Issue