Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmciavi.c
Go to the documentation of this file.
00001 /* 00002 * Digital video MCI Wine Driver 00003 * 00004 * Copyright 1999, 2000 Eric POUECH 00005 * Copyright 2003 Dmitry Timoshkov 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 00022 /* TODO list : 00023 * - handling of palettes 00024 * - recording (which input devices ?), a cam recorder ? 00025 * - lots of messages still need to be handled (cf FIXME) 00026 * - synchronization between audio and video (especially for interleaved 00027 * files) 00028 * - robustness when reading file can be enhanced 00029 * - reimplement the AVI handling part with avifile DLL because 00030 * "open @1122334 type avivideo alias a" expects an AVIFile/Stream 00031 * and MCI_DGV_SET|STATUS_SPEED maps to Rate/Scale 00032 * - some files appear to have more than one audio stream (we only play the 00033 * first one) 00034 * - some files contain an index of audio/video frame. Better use it, 00035 * instead of rebuilding it (AVIFile does that already) 00036 * - stopping while playing a file with sound blocks until all buffered 00037 * audio is played... still should be stopped ASAP 00038 */ 00039 00040 #include <string.h> 00041 #include "private_mciavi.h" 00042 #include "wine/debug.h" 00043 #include "wine/unicode.h" 00044 00045 WINE_DEFAULT_DEBUG_CHANNEL(mciavi); 00046 00047 static DWORD MCIAVI_mciStop(UINT, DWORD, LPMCI_GENERIC_PARMS); 00048 00049 /*======================================================================* 00050 * MCI AVI implementation * 00051 *======================================================================*/ 00052 00053 HINSTANCE MCIAVI_hInstance = 0; 00054 00055 /*********************************************************************** 00056 * DllMain (MCIAVI.0) 00057 */ 00058 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad) 00059 { 00060 switch (fdwReason) { 00061 case DLL_PROCESS_ATTACH: 00062 DisableThreadLibraryCalls(hInstDLL); 00063 MCIAVI_hInstance = hInstDLL; 00064 break; 00065 } 00066 return TRUE; 00067 } 00068 00069 /************************************************************************** 00070 * MCIAVI_drvOpen [internal] 00071 */ 00072 static DWORD MCIAVI_drvOpen(LPCWSTR str, LPMCI_OPEN_DRIVER_PARMSW modp) 00073 { 00074 WINE_MCIAVI* wma; 00075 static const WCHAR mciAviWStr[] = {'M','C','I','A','V','I',0}; 00076 00077 TRACE("%s, %p\n", debugstr_w(str), modp); 00078 00079 /* session instance */ 00080 if (!modp) return 0xFFFFFFFF; 00081 00082 if (!MCIAVI_RegisterClass()) return 0; 00083 00084 wma = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_MCIAVI)); 00085 if (!wma) 00086 return 0; 00087 00088 InitializeCriticalSection(&wma->cs); 00089 wma->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": WINE_MCIAVI.cs"); 00090 wma->ack_event = CreateEventW(NULL, FALSE, FALSE, NULL); 00091 wma->hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL); 00092 wma->wDevID = modp->wDeviceID; 00093 wma->wCommandTable = mciLoadCommandResource(MCIAVI_hInstance, mciAviWStr, 0); 00094 wma->dwStatus = MCI_MODE_NOT_READY; 00095 modp->wCustomCommandTable = wma->wCommandTable; 00096 modp->wType = MCI_DEVTYPE_DIGITAL_VIDEO; 00097 mciSetDriverData(wma->wDevID, (DWORD_PTR)wma); 00098 00099 return modp->wDeviceID; 00100 } 00101 00102 /************************************************************************** 00103 * MCIAVI_drvClose [internal] 00104 */ 00105 static DWORD MCIAVI_drvClose(DWORD dwDevID) 00106 { 00107 WINE_MCIAVI *wma; 00108 00109 TRACE("%04x\n", dwDevID); 00110 00111 /* finish all outstanding things */ 00112 MCIAVI_mciClose(dwDevID, MCI_WAIT, NULL); 00113 00114 wma = (WINE_MCIAVI*)mciGetDriverData(dwDevID); 00115 00116 if (wma) { 00117 MCIAVI_UnregisterClass(); 00118 00119 EnterCriticalSection(&wma->cs); 00120 00121 mciSetDriverData(dwDevID, 0); 00122 mciFreeCommandResource(wma->wCommandTable); 00123 00124 CloseHandle(wma->ack_event); 00125 CloseHandle(wma->hStopEvent); 00126 00127 LeaveCriticalSection(&wma->cs); 00128 wma->cs.DebugInfo->Spare[0] = 0; 00129 DeleteCriticalSection(&wma->cs); 00130 00131 HeapFree(GetProcessHeap(), 0, wma); 00132 return 1; 00133 } 00134 return (dwDevID == 0xFFFFFFFF) ? 1 : 0; 00135 } 00136 00137 /************************************************************************** 00138 * MCIAVI_drvConfigure [internal] 00139 */ 00140 static DWORD MCIAVI_drvConfigure(DWORD dwDevID) 00141 { 00142 WINE_MCIAVI *wma; 00143 00144 TRACE("%04x\n", dwDevID); 00145 00146 MCIAVI_mciStop(dwDevID, MCI_WAIT, NULL); 00147 00148 wma = (WINE_MCIAVI*)mciGetDriverData(dwDevID); 00149 00150 if (wma) { 00151 MessageBoxA(0, "Sample AVI Wine Driver !", "MM-Wine Driver", MB_OK); 00152 return 1; 00153 } 00154 return 0; 00155 } 00156 00157 /************************************************************************** 00158 * MCIAVI_mciGetOpenDev [internal] 00159 */ 00160 WINE_MCIAVI* MCIAVI_mciGetOpenDev(UINT wDevID) 00161 { 00162 WINE_MCIAVI* wma = (WINE_MCIAVI*)mciGetDriverData(wDevID); 00163 00164 if (wma == NULL || wma->nUseCount == 0) { 00165 WARN("Invalid wDevID=%u\n", wDevID); 00166 return 0; 00167 } 00168 return wma; 00169 } 00170 00171 static void MCIAVI_CleanUp(WINE_MCIAVI* wma) 00172 { 00173 /* to prevent handling in WindowProc */ 00174 wma->dwStatus = MCI_MODE_NOT_READY; 00175 if (wma->hFile) { 00176 mmioClose(wma->hFile, 0); 00177 wma->hFile = 0; 00178 00179 HeapFree(GetProcessHeap(), 0, wma->lpFileName); 00180 wma->lpFileName = NULL; 00181 00182 HeapFree(GetProcessHeap(), 0, wma->lpVideoIndex); 00183 wma->lpVideoIndex = NULL; 00184 HeapFree(GetProcessHeap(), 0, wma->lpAudioIndex); 00185 wma->lpAudioIndex = NULL; 00186 if (wma->hic) ICClose(wma->hic); 00187 wma->hic = 0; 00188 HeapFree(GetProcessHeap(), 0, wma->inbih); 00189 wma->inbih = NULL; 00190 HeapFree(GetProcessHeap(), 0, wma->outbih); 00191 wma->outbih = NULL; 00192 HeapFree(GetProcessHeap(), 0, wma->indata); 00193 wma->indata = NULL; 00194 HeapFree(GetProcessHeap(), 0, wma->outdata); 00195 wma->outdata = NULL; 00196 if (wma->hbmFrame) DeleteObject(wma->hbmFrame); 00197 wma->hbmFrame = 0; 00198 if (wma->hWnd) DestroyWindow(wma->hWnd); 00199 wma->hWnd = 0; 00200 00201 HeapFree(GetProcessHeap(), 0, wma->lpWaveFormat); 00202 wma->lpWaveFormat = 0; 00203 00204 memset(&wma->mah, 0, sizeof(wma->mah)); 00205 memset(&wma->ash_video, 0, sizeof(wma->ash_video)); 00206 memset(&wma->ash_audio, 0, sizeof(wma->ash_audio)); 00207 wma->dwCurrVideoFrame = wma->dwCurrAudioBlock = 0; 00208 wma->dwCachedFrame = -1; 00209 } 00210 } 00211 00212 /*************************************************************************** 00213 * MCIAVI_mciOpen [internal] 00214 */ 00215 static DWORD MCIAVI_mciOpen(UINT wDevID, DWORD dwFlags, 00216 LPMCI_DGV_OPEN_PARMSW lpOpenParms) 00217 { 00218 WINE_MCIAVI *wma; 00219 LRESULT dwRet = 0; 00220 00221 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpOpenParms); 00222 00223 if (lpOpenParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; 00224 00225 wma = (WINE_MCIAVI *)mciGetDriverData(wDevID); 00226 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; 00227 00228 EnterCriticalSection(&wma->cs); 00229 00230 if (wma->nUseCount > 0) { 00231 /* The driver is already open on this channel */ 00232 /* If the driver was opened shareable before and this open specifies */ 00233 /* shareable then increment the use count */ 00234 if (wma->fShareable && (dwFlags & MCI_OPEN_SHAREABLE)) 00235 ++wma->nUseCount; 00236 else 00237 { 00238 LeaveCriticalSection(&wma->cs); 00239 return MCIERR_MUST_USE_SHAREABLE; 00240 } 00241 } else { 00242 wma->nUseCount = 1; 00243 wma->fShareable = dwFlags & MCI_OPEN_SHAREABLE; 00244 } 00245 00246 wma->dwStatus = MCI_MODE_NOT_READY; 00247 00248 if (dwFlags & MCI_OPEN_ELEMENT) { 00249 if (dwFlags & MCI_OPEN_ELEMENT_ID) { 00250 /* could it be that (DWORD)lpOpenParms->lpstrElementName 00251 * contains the hFile value ? 00252 */ 00253 dwRet = MCIERR_UNRECOGNIZED_COMMAND; 00254 } else if (lpOpenParms->lpstrElementName && lpOpenParms->lpstrElementName[0]) { 00255 /* FIXME : what should be done id wma->hFile is already != 0, or the driver is playin' */ 00256 TRACE("MCI_OPEN_ELEMENT %s!\n", debugstr_w(lpOpenParms->lpstrElementName)); 00257 00258 wma->lpFileName = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpOpenParms->lpstrElementName) + 1) * sizeof(WCHAR)); 00259 strcpyW(wma->lpFileName, lpOpenParms->lpstrElementName); 00260 00261 if (lpOpenParms->lpstrElementName[0] == '@') { 00262 /* The file name @11223344 encodes an AVIFile handle in decimal notation 00263 * in Win3.1 and w2k/NT, but this feature is absent in win95 (KB140750). 00264 * wma->hFile = LongToHandle(strtolW(lpOpenParms->lpstrElementName+1, NULL, 10)); */ 00265 FIXME("Using AVIFile/Stream %s NIY\n", debugstr_w(lpOpenParms->lpstrElementName)); 00266 } 00267 wma->hFile = mmioOpenW(lpOpenParms->lpstrElementName, NULL, 00268 MMIO_ALLOCBUF | MMIO_DENYWRITE | MMIO_READ); 00269 00270 if (wma->hFile == 0) { 00271 WARN("can't find file=%s!\n", debugstr_w(lpOpenParms->lpstrElementName)); 00272 dwRet = MCIERR_FILE_NOT_FOUND; 00273 } else { 00274 if (!MCIAVI_GetInfo(wma)) 00275 dwRet = MCIERR_INVALID_FILE; 00276 else if (!MCIAVI_OpenVideo(wma)) 00277 dwRet = MCIERR_CANNOT_LOAD_DRIVER; 00278 else if (!MCIAVI_CreateWindow(wma, dwFlags, lpOpenParms)) 00279 dwRet = MCIERR_CREATEWINDOW; 00280 } 00281 } else { 00282 FIXME("Don't record yet\n"); 00283 dwRet = MCIERR_UNSUPPORTED_FUNCTION; 00284 } 00285 } 00286 00287 if (dwRet == 0) { 00288 TRACE("lpOpenParms->wDeviceID = %04x\n", lpOpenParms->wDeviceID); 00289 00290 wma->dwStatus = MCI_MODE_STOP; 00291 wma->dwMciTimeFormat = MCI_FORMAT_FRAMES; 00292 } else { 00293 MCIAVI_CleanUp(wma); 00294 } 00295 00296 LeaveCriticalSection(&wma->cs); 00297 00298 if (!dwRet && (dwFlags & MCI_NOTIFY)) { 00299 mciDriverNotify(HWND_32(LOWORD(lpOpenParms->dwCallback)), 00300 wDevID, MCI_NOTIFY_SUCCESSFUL); 00301 } 00302 return dwRet; 00303 } 00304 00305 /*************************************************************************** 00306 * MCIAVI_mciClose [internal] 00307 */ 00308 DWORD MCIAVI_mciClose(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms) 00309 { 00310 WINE_MCIAVI *wma; 00311 DWORD dwRet = 0; 00312 00313 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); 00314 00315 wma = MCIAVI_mciGetOpenDev(wDevID); 00316 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; 00317 00318 MCIAVI_mciStop(wDevID, MCI_WAIT, NULL); 00319 00320 EnterCriticalSection(&wma->cs); 00321 00322 if (wma->nUseCount == 1) { 00323 MCIAVI_CleanUp(wma); 00324 00325 if ((dwFlags & MCI_NOTIFY) && lpParms) { 00326 mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)), 00327 wDevID, 00328 MCI_NOTIFY_SUCCESSFUL); 00329 } 00330 LeaveCriticalSection(&wma->cs); 00331 return dwRet; 00332 } 00333 wma->nUseCount--; 00334 00335 LeaveCriticalSection(&wma->cs); 00336 return dwRet; 00337 } 00338 00339 static DWORD MCIAVI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms); 00340 00341 struct MCIAVI_play_data 00342 { 00343 MCIDEVICEID wDevID; 00344 DWORD flags; 00345 MCI_PLAY_PARMS params; 00346 }; 00347 00348 /* 00349 * MCIAVI_mciPlay_thread 00350 * 00351 * FIXME: probably should use a common worker thread created at the driver 00352 * load time and queue all async commands to it. 00353 */ 00354 static DWORD WINAPI MCIAVI_mciPlay_thread(LPVOID arg) 00355 { 00356 struct MCIAVI_play_data *data = (struct MCIAVI_play_data *)arg; 00357 DWORD ret; 00358 00359 TRACE("In thread before async play command (id %08x, flags %08x)\n", data->wDevID, data->flags); 00360 ret = MCIAVI_mciPlay(data->wDevID, data->flags | MCI_WAIT, &data->params); 00361 TRACE("In thread after async play command (id %08x, flags %08x)\n", data->wDevID, data->flags); 00362 00363 HeapFree(GetProcessHeap(), 0, data); 00364 return ret; 00365 } 00366 00367 /* 00368 * MCIAVI_mciPlay_async 00369 */ 00370 static DWORD MCIAVI_mciPlay_async(WINE_MCIAVI *wma, DWORD dwFlags, LPMCI_PLAY_PARMS lpParams) 00371 { 00372 HANDLE handle, ack_event = wma->ack_event; 00373 struct MCIAVI_play_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(struct MCIAVI_play_data)); 00374 00375 if (!data) return MCIERR_OUT_OF_MEMORY; 00376 00377 data->wDevID = wma->wDevID; 00378 data->flags = dwFlags; 00379 data->params = *lpParams; 00380 00381 if (!(handle = CreateThread(NULL, 0, MCIAVI_mciPlay_thread, data, 0, NULL))) 00382 { 00383 WARN("Couldn't create thread for async play, playing synchronously\n"); 00384 return MCIAVI_mciPlay_thread(data); 00385 } 00386 SetThreadPriority(handle, THREAD_PRIORITY_TIME_CRITICAL); 00387 CloseHandle(handle); 00388 /* wait until the thread starts up, so the app could see a changed status */ 00389 WaitForSingleObject(ack_event, INFINITE); 00390 TRACE("Async play has started\n"); 00391 return 0; 00392 } 00393 00394 /*************************************************************************** 00395 * MCIAVI_mciPlay [internal] 00396 */ 00397 static DWORD MCIAVI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms) 00398 { 00399 WINE_MCIAVI *wma; 00400 DWORD frameTime; 00401 DWORD dwRet; 00402 LPWAVEHDR waveHdr = NULL; 00403 unsigned i, nHdr = 0; 00404 DWORD dwFromFrame, dwToFrame; 00405 DWORD numEvents = 1; 00406 HANDLE events[2]; 00407 00408 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); 00409 00410 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; 00411 00412 wma = MCIAVI_mciGetOpenDev(wDevID); 00413 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; 00414 if (dwFlags & MCI_DGV_PLAY_REVERSE) return MCIERR_UNSUPPORTED_FUNCTION; 00415 if (dwFlags & MCI_TEST) return 0; 00416 00417 EnterCriticalSection(&wma->cs); 00418 00419 if (!wma->hFile) 00420 { 00421 LeaveCriticalSection(&wma->cs); 00422 return MCIERR_FILE_NOT_FOUND; 00423 } 00424 if (!wma->hWndPaint) 00425 { 00426 LeaveCriticalSection(&wma->cs); 00427 return MCIERR_NO_WINDOW; 00428 } 00429 00430 LeaveCriticalSection(&wma->cs); 00431 00432 if (!(dwFlags & MCI_WAIT)) 00433 return MCIAVI_mciPlay_async(wma, dwFlags, lpParms); 00434 00435 if (!(GetWindowLongW(wma->hWndPaint, GWL_STYLE) & WS_VISIBLE)) 00436 ShowWindow(wma->hWndPaint, SW_SHOWNA); 00437 00438 EnterCriticalSection(&wma->cs); 00439 00440 dwFromFrame = wma->dwCurrVideoFrame; 00441 dwToFrame = wma->dwPlayableVideoFrames - 1; 00442 00443 if (dwFlags & MCI_FROM) { 00444 dwFromFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwFrom); 00445 } 00446 if (dwFlags & MCI_TO) { 00447 dwToFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwTo); 00448 } 00449 if (dwToFrame >= wma->dwPlayableVideoFrames) 00450 dwToFrame = wma->dwPlayableVideoFrames - 1; 00451 00452 TRACE("Playing from frame=%u to frame=%u\n", dwFromFrame, dwToFrame); 00453 00454 wma->dwCurrVideoFrame = dwFromFrame; 00455 wma->dwToVideoFrame = dwToFrame; 00456 00457 /* if already playing exit */ 00458 if (wma->dwStatus == MCI_MODE_PLAY) 00459 { 00460 LeaveCriticalSection(&wma->cs); 00461 SetEvent(wma->ack_event); 00462 return 0; 00463 } 00464 00465 if (wma->dwToVideoFrame <= wma->dwCurrVideoFrame) 00466 { 00467 dwRet = 0; 00468 SetEvent(wma->ack_event); 00469 goto mci_play_done; 00470 } 00471 00472 wma->dwStatus = MCI_MODE_PLAY; 00473 /* signal the state change */ 00474 SetEvent(wma->ack_event); 00475 00476 if (dwFlags & (MCI_DGV_PLAY_REPEAT|MCI_MCIAVI_PLAY_WINDOW|MCI_MCIAVI_PLAY_FULLSCREEN)) 00477 FIXME("Unsupported flag %08x\n", dwFlags); 00478 00479 /* time is in microseconds, we should convert it to milliseconds */ 00480 frameTime = (wma->mah.dwMicroSecPerFrame + 500) / 1000; 00481 00482 events[0] = wma->hStopEvent; 00483 if (wma->lpWaveFormat) { 00484 if (MCIAVI_OpenAudio(wma, &nHdr, &waveHdr) != 0) 00485 { 00486 /* can't play audio */ 00487 HeapFree(GetProcessHeap(), 0, wma->lpWaveFormat); 00488 wma->lpWaveFormat = NULL; 00489 } 00490 else 00491 { 00492 /* fill the queue with as many wave headers as possible */ 00493 MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr); 00494 events[1] = wma->hEvent; 00495 numEvents = 2; 00496 } 00497 } 00498 00499 while (wma->dwStatus == MCI_MODE_PLAY) 00500 { 00501 HDC hDC; 00502 DWORD tc, delta; 00503 DWORD ret; 00504 00505 tc = GetTickCount(); 00506 00507 hDC = wma->hWndPaint ? GetDC(wma->hWndPaint) : 0; 00508 if (hDC) 00509 { 00510 MCIAVI_PaintFrame(wma, hDC); 00511 ReleaseDC(wma->hWndPaint, hDC); 00512 } 00513 00514 if (wma->lpWaveFormat) 00515 MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr); 00516 00517 delta = GetTickCount() - tc; 00518 if (delta < frameTime) 00519 delta = frameTime - delta; 00520 else 00521 delta = 0; 00522 00523 LeaveCriticalSection(&wma->cs); 00524 ret = WaitForMultipleObjects(numEvents, events, FALSE, delta); 00525 EnterCriticalSection(&wma->cs); 00526 if (ret == WAIT_OBJECT_0 || wma->dwStatus != MCI_MODE_PLAY) break; 00527 00528 if (wma->dwCurrVideoFrame < dwToFrame) 00529 wma->dwCurrVideoFrame++; 00530 else 00531 break; 00532 } 00533 00534 if (wma->lpWaveFormat) { 00535 while (wma->dwEventCount != nHdr - 1) 00536 { 00537 LeaveCriticalSection(&wma->cs); 00538 Sleep(100); 00539 EnterCriticalSection(&wma->cs); 00540 } 00541 00542 /* just to get rid of some race conditions between play, stop and pause */ 00543 LeaveCriticalSection(&wma->cs); 00544 waveOutReset(wma->hWave); 00545 EnterCriticalSection(&wma->cs); 00546 00547 for (i = 0; i < nHdr; i++) 00548 waveOutUnprepareHeader(wma->hWave, &waveHdr[i], sizeof(WAVEHDR)); 00549 } 00550 00551 dwRet = 0; 00552 00553 if (wma->lpWaveFormat) { 00554 HeapFree(GetProcessHeap(), 0, waveHdr); 00555 00556 if (wma->hWave) { 00557 LeaveCriticalSection(&wma->cs); 00558 waveOutClose(wma->hWave); 00559 EnterCriticalSection(&wma->cs); 00560 wma->hWave = 0; 00561 } 00562 CloseHandle(wma->hEvent); 00563 } 00564 00565 mci_play_done: 00566 wma->dwStatus = MCI_MODE_STOP; 00567 00568 if (dwFlags & MCI_NOTIFY) { 00569 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback); 00570 mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)), 00571 wDevID, MCI_NOTIFY_SUCCESSFUL); 00572 } 00573 LeaveCriticalSection(&wma->cs); 00574 return dwRet; 00575 } 00576 00577 /*************************************************************************** 00578 * MCIAVI_mciStop [internal] 00579 */ 00580 static DWORD MCIAVI_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms) 00581 { 00582 WINE_MCIAVI *wma; 00583 DWORD dwRet = 0; 00584 00585 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); 00586 00587 wma = MCIAVI_mciGetOpenDev(wDevID); 00588 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; 00589 if (dwFlags & MCI_TEST) return 0; 00590 00591 EnterCriticalSection(&wma->cs); 00592 00593 TRACE("current status %04x\n", wma->dwStatus); 00594 00595 switch (wma->dwStatus) { 00596 case MCI_MODE_PLAY: 00597 case MCI_MODE_RECORD: 00598 LeaveCriticalSection(&wma->cs); 00599 SetEvent(wma->hStopEvent); 00600 EnterCriticalSection(&wma->cs); 00601 /* fall through */ 00602 case MCI_MODE_PAUSE: 00603 /* Since our wave notification callback takes the lock, 00604 * we must release it before resetting the device */ 00605 LeaveCriticalSection(&wma->cs); 00606 dwRet = waveOutReset(wma->hWave); 00607 EnterCriticalSection(&wma->cs); 00608 /* fall through */ 00609 default: 00610 do /* one more chance for an async thread to finish */ 00611 { 00612 LeaveCriticalSection(&wma->cs); 00613 Sleep(10); 00614 EnterCriticalSection(&wma->cs); 00615 } while (wma->dwStatus != MCI_MODE_STOP); 00616 00617 break; 00618 00619 case MCI_MODE_NOT_READY: 00620 break; 00621 } 00622 00623 if ((dwFlags & MCI_NOTIFY) && lpParms) { 00624 mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)), 00625 wDevID, MCI_NOTIFY_SUCCESSFUL); 00626 } 00627 LeaveCriticalSection(&wma->cs); 00628 return dwRet; 00629 } 00630 00631 /*************************************************************************** 00632 * MCIAVI_mciPause [internal] 00633 */ 00634 static DWORD MCIAVI_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms) 00635 { 00636 WINE_MCIAVI *wma; 00637 00638 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); 00639 00640 wma = MCIAVI_mciGetOpenDev(wDevID); 00641 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; 00642 if (dwFlags & MCI_TEST) return 0; 00643 00644 EnterCriticalSection(&wma->cs); 00645 00646 if (wma->dwStatus == MCI_MODE_PLAY) 00647 wma->dwStatus = MCI_MODE_PAUSE; 00648 00649 if (wma->lpWaveFormat) { 00650 LeaveCriticalSection(&wma->cs); 00651 return waveOutPause(wma->hWave); 00652 } 00653 00654 LeaveCriticalSection(&wma->cs); 00655 return 0; 00656 } 00657 00658 /*************************************************************************** 00659 * MCIAVI_mciResume [internal] 00660 */ 00661 static DWORD MCIAVI_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms) 00662 { 00663 WINE_MCIAVI *wma; 00664 00665 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); 00666 00667 wma = MCIAVI_mciGetOpenDev(wDevID); 00668 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; 00669 if (dwFlags & MCI_TEST) return 0; 00670 00671 EnterCriticalSection(&wma->cs); 00672 00673 if (wma->dwStatus == MCI_MODE_PAUSE) 00674 wma->dwStatus = MCI_MODE_PLAY; 00675 00676 if (wma->lpWaveFormat) { 00677 LeaveCriticalSection(&wma->cs); 00678 return waveOutRestart(wma->hWave); 00679 } 00680 00681 LeaveCriticalSection(&wma->cs); 00682 return 0; 00683 } 00684 00685 /*************************************************************************** 00686 * MCIAVI_mciSeek [internal] 00687 */ 00688 static DWORD MCIAVI_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms) 00689 { 00690 WINE_MCIAVI *wma; 00691 DWORD position; 00692 00693 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); 00694 00695 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; 00696 00697 wma = MCIAVI_mciGetOpenDev(wDevID); 00698 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; 00699 00700 position = dwFlags & (MCI_SEEK_TO_START|MCI_SEEK_TO_END|MCI_TO); 00701 if (!position) return MCIERR_MISSING_PARAMETER; 00702 if (position&(position-1)) return MCIERR_FLAGS_NOT_COMPATIBLE; 00703 00704 if (dwFlags & MCI_TO) { 00705 position = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwTo); 00706 if (position >= wma->dwPlayableVideoFrames) 00707 return MCIERR_OUTOFRANGE; 00708 } else if (dwFlags & MCI_SEEK_TO_START) { 00709 position = 0; 00710 } else { 00711 position = wma->dwPlayableVideoFrames - 1; 00712 } 00713 if (dwFlags & MCI_TEST) return 0; 00714 00715 MCIAVI_mciStop(wDevID, MCI_WAIT, NULL); 00716 00717 EnterCriticalSection(&wma->cs); 00718 00719 wma->dwCurrVideoFrame = position; 00720 TRACE("Seeking to frame=%u\n", wma->dwCurrVideoFrame); 00721 00722 if (dwFlags & MCI_NOTIFY) { 00723 mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)), 00724 wDevID, MCI_NOTIFY_SUCCESSFUL); 00725 } 00726 LeaveCriticalSection(&wma->cs); 00727 return 0; 00728 } 00729 00730 /***************************************************************************** 00731 * MCIAVI_mciLoad [internal] 00732 */ 00733 static DWORD MCIAVI_mciLoad(UINT wDevID, DWORD dwFlags, LPMCI_DGV_LOAD_PARMSW lpParms) 00734 { 00735 WINE_MCIAVI *wma; 00736 00737 FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms); 00738 00739 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; 00740 00741 wma = MCIAVI_mciGetOpenDev(wDevID); 00742 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; 00743 00744 return MCIERR_UNSUPPORTED_FUNCTION; /* like w2k */ 00745 } 00746 00747 /****************************************************************************** 00748 * MCIAVI_mciRealize [internal] 00749 */ 00750 static DWORD MCIAVI_mciRealize(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms) 00751 { 00752 WINE_MCIAVI *wma; 00753 00754 FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms); 00755 00756 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; 00757 00758 wma = MCIAVI_mciGetOpenDev(wDevID); 00759 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; 00760 if (dwFlags & MCI_TEST) return 0; 00761 00762 return 0; 00763 } 00764 00765 /****************************************************************************** 00766 * MCIAVI_mciUpdate [internal] 00767 */ 00768 static DWORD MCIAVI_mciUpdate(UINT wDevID, DWORD dwFlags, LPMCI_DGV_UPDATE_PARMS lpParms) 00769 { 00770 WINE_MCIAVI *wma; 00771 00772 TRACE("%04x, %08x, %p\n", wDevID, dwFlags, lpParms); 00773 00774 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; 00775 00776 wma = MCIAVI_mciGetOpenDev(wDevID); 00777 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; 00778 /* Ignore MCI_TEST flag. */ 00779 00780 EnterCriticalSection(&wma->cs); 00781 00782 if (dwFlags & MCI_DGV_UPDATE_HDC) 00783 MCIAVI_PaintFrame(wma, lpParms->hDC); 00784 00785 LeaveCriticalSection(&wma->cs); 00786 00787 return 0; 00788 } 00789 00790 /****************************************************************************** 00791 * MCIAVI_mciStep [internal] 00792 */ 00793 static DWORD MCIAVI_mciStep(UINT wDevID, DWORD dwFlags, LPMCI_DGV_STEP_PARMS lpParms) 00794 { 00795 WINE_MCIAVI *wma; 00796 DWORD position; 00797 int delta = 1; 00798 00799 TRACE("(%04x, %08x, %p)\n", wDevID, dwFlags, lpParms); 00800 00801 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; 00802 00803 wma = MCIAVI_mciGetOpenDev(wDevID); 00804 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; 00805 00806 if (dwFlags & MCI_DGV_STEP_FRAMES) delta = lpParms->dwFrames; 00807 if (dwFlags & MCI_DGV_STEP_REVERSE) delta = -delta; 00808 position = wma->dwCurrVideoFrame + delta; 00809 if (position >= wma->dwPlayableVideoFrames) return MCIERR_OUTOFRANGE; 00810 if (dwFlags & MCI_TEST) return 0; 00811 00812 MCIAVI_mciStop(wDevID, MCI_WAIT, NULL); 00813 00814 EnterCriticalSection(&wma->cs); 00815 00816 wma->dwCurrVideoFrame = position; 00817 TRACE("Stepping to frame=%u\n", wma->dwCurrVideoFrame); 00818 00819 if (dwFlags & MCI_NOTIFY) { 00820 mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)), 00821 wDevID, MCI_NOTIFY_SUCCESSFUL); 00822 } 00823 LeaveCriticalSection(&wma->cs); 00824 return 0; 00825 } 00826 00827 /****************************************************************************** 00828 * MCIAVI_mciCue [internal] 00829 */ 00830 static DWORD MCIAVI_mciCue(UINT wDevID, DWORD dwFlags, LPMCI_DGV_CUE_PARMS lpParms) 00831 { 00832 WINE_MCIAVI *wma; 00833 00834 FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms); 00835 00836 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; 00837 00838 wma = MCIAVI_mciGetOpenDev(wDevID); 00839 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; 00840 if (dwFlags & MCI_DGV_CUE_INPUT) return MCIERR_UNSUPPORTED_FUNCTION; 00841 if (dwFlags & MCI_TEST) return 0; 00842 00843 return 0; 00844 } 00845 00846 /****************************************************************************** 00847 * MCIAVI_mciSetAudio [internal] 00848 */ 00849 static DWORD MCIAVI_mciSetAudio(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SETAUDIO_PARMSW lpParms) 00850 { 00851 WINE_MCIAVI *wma; 00852 00853 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; 00854 00855 FIXME("(%04x, %08x, %p) Item %04x: stub\n", wDevID, dwFlags, lpParms, dwFlags & MCI_DGV_SETAUDIO_ITEM ? lpParms->dwItem : 0); 00856 00857 wma = MCIAVI_mciGetOpenDev(wDevID); 00858 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; 00859 00860 return 0; 00861 } 00862 00863 /****************************************************************************** 00864 * MCIAVI_mciSignal [internal] 00865 */ 00866 static DWORD MCIAVI_mciSignal(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SIGNAL_PARMS lpParms) 00867 { 00868 WINE_MCIAVI *wma; 00869 00870 FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms); 00871 00872 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; 00873 00874 wma = MCIAVI_mciGetOpenDev(wDevID); 00875 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; 00876 00877 return 0; 00878 } 00879 00880 /****************************************************************************** 00881 * MCIAVI_mciSetVideo [internal] 00882 */ 00883 static DWORD MCIAVI_mciSetVideo(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SETVIDEO_PARMSW lpParms) 00884 { 00885 WINE_MCIAVI *wma; 00886 00887 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; 00888 00889 FIXME("(%04x, %08x, %p) Item %04x: stub\n", wDevID, dwFlags, lpParms, dwFlags & MCI_DGV_SETVIDEO_ITEM ? lpParms->dwItem : 0); 00890 00891 wma = MCIAVI_mciGetOpenDev(wDevID); 00892 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; 00893 00894 return 0; 00895 } 00896 00897 /****************************************************************************** 00898 * MCIAVI_mciConfigure [internal] 00899 */ 00900 static DWORD MCIAVI_mciConfigure(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms) 00901 { 00902 WINE_MCIAVI *wma; 00903 00904 FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms); 00905 00906 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; 00907 00908 wma = MCIAVI_mciGetOpenDev(wDevID); 00909 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; 00910 if (dwFlags & MCI_TEST) return 0; 00911 00912 return 0; 00913 } 00914 00915 /*======================================================================* 00916 * MCI AVI entry points * 00917 *======================================================================*/ 00918 00919 /************************************************************************** 00920 * DriverProc (MCIAVI.@) 00921 */ 00922 LRESULT CALLBACK MCIAVI_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg, 00923 LPARAM dwParam1, LPARAM dwParam2) 00924 { 00925 TRACE("(%08lX, %p, %08X, %08lX, %08lX)\n", 00926 dwDevID, hDriv, wMsg, dwParam1, dwParam2); 00927 00928 switch (wMsg) { 00929 case DRV_LOAD: return 1; 00930 case DRV_FREE: return 1; 00931 case DRV_OPEN: return MCIAVI_drvOpen((LPCWSTR)dwParam1, (LPMCI_OPEN_DRIVER_PARMSW)dwParam2); 00932 case DRV_CLOSE: return MCIAVI_drvClose(dwDevID); 00933 case DRV_ENABLE: return 1; 00934 case DRV_DISABLE: return 1; 00935 case DRV_QUERYCONFIGURE: return 1; 00936 case DRV_CONFIGURE: return MCIAVI_drvConfigure(dwDevID); 00937 case DRV_INSTALL: return DRVCNF_RESTART; 00938 case DRV_REMOVE: return DRVCNF_RESTART; 00939 } 00940 00941 /* session instance */ 00942 if (dwDevID == 0xFFFFFFFF) return 1; 00943 00944 switch (wMsg) { 00945 case MCI_OPEN_DRIVER: return MCIAVI_mciOpen (dwDevID, dwParam1, (LPMCI_DGV_OPEN_PARMSW) dwParam2); 00946 case MCI_CLOSE_DRIVER: return MCIAVI_mciClose (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2); 00947 case MCI_PLAY: return MCIAVI_mciPlay (dwDevID, dwParam1, (LPMCI_PLAY_PARMS) dwParam2); 00948 case MCI_STOP: return MCIAVI_mciStop (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2); 00949 case MCI_SET: return MCIAVI_mciSet (dwDevID, dwParam1, (LPMCI_DGV_SET_PARMS) dwParam2); 00950 case MCI_PAUSE: return MCIAVI_mciPause (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2); 00951 case MCI_RESUME: return MCIAVI_mciResume (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2); 00952 case MCI_STATUS: return MCIAVI_mciStatus (dwDevID, dwParam1, (LPMCI_DGV_STATUS_PARMSW) dwParam2); 00953 case MCI_GETDEVCAPS: return MCIAVI_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS) dwParam2); 00954 case MCI_INFO: return MCIAVI_mciInfo (dwDevID, dwParam1, (LPMCI_DGV_INFO_PARMSW) dwParam2); 00955 case MCI_SEEK: return MCIAVI_mciSeek (dwDevID, dwParam1, (LPMCI_SEEK_PARMS) dwParam2); 00956 case MCI_PUT: return MCIAVI_mciPut (dwDevID, dwParam1, (LPMCI_DGV_PUT_PARMS) dwParam2); 00957 case MCI_WINDOW: return MCIAVI_mciWindow (dwDevID, dwParam1, (LPMCI_DGV_WINDOW_PARMSW) dwParam2); 00958 case MCI_LOAD: return MCIAVI_mciLoad (dwDevID, dwParam1, (LPMCI_DGV_LOAD_PARMSW) dwParam2); 00959 case MCI_REALIZE: return MCIAVI_mciRealize (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2); 00960 case MCI_UPDATE: return MCIAVI_mciUpdate (dwDevID, dwParam1, (LPMCI_DGV_UPDATE_PARMS) dwParam2); 00961 case MCI_WHERE: return MCIAVI_mciWhere (dwDevID, dwParam1, (LPMCI_DGV_RECT_PARMS) dwParam2); 00962 case MCI_STEP: return MCIAVI_mciStep (dwDevID, dwParam1, (LPMCI_DGV_STEP_PARMS) dwParam2); 00963 case MCI_CUE: return MCIAVI_mciCue (dwDevID, dwParam1, (LPMCI_DGV_CUE_PARMS) dwParam2); 00964 /* Digital Video specific */ 00965 case MCI_SETAUDIO: return MCIAVI_mciSetAudio (dwDevID, dwParam1, (LPMCI_DGV_SETAUDIO_PARMSW) dwParam2); 00966 case MCI_SIGNAL: return MCIAVI_mciSignal (dwDevID, dwParam1, (LPMCI_DGV_SIGNAL_PARMS) dwParam2); 00967 case MCI_SETVIDEO: return MCIAVI_mciSetVideo (dwDevID, dwParam1, (LPMCI_DGV_SETVIDEO_PARMSW) dwParam2); 00968 case MCI_CONFIGURE: return MCIAVI_mciConfigure (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2); 00969 00970 /* no editing, recording, saving, locking without inputs */ 00971 case MCI_CAPTURE: 00972 case MCI_COPY: 00973 case MCI_CUT: 00974 case MCI_DELETE: 00975 case MCI_FREEZE: 00976 case MCI_LIST: 00977 case MCI_MONITOR: 00978 case MCI_PASTE: 00979 case MCI_QUALITY: 00980 case MCI_RECORD: 00981 case MCI_RESERVE: 00982 case MCI_RESTORE: 00983 case MCI_SAVE: 00984 case MCI_UNDO: 00985 case MCI_UNFREEZE: 00986 TRACE("Unsupported function [0x%x] flags=%08x\n", wMsg, (DWORD)dwParam1); 00987 return MCIERR_UNSUPPORTED_FUNCTION; 00988 case MCI_SPIN: 00989 case MCI_ESCAPE: 00990 WARN("Unsupported command [0x%x] %08x\n", wMsg, (DWORD)dwParam1); 00991 break; 00992 case MCI_OPEN: 00993 case MCI_CLOSE: 00994 FIXME("Shouldn't receive a MCI_OPEN or CLOSE message\n"); 00995 break; 00996 default: 00997 TRACE("Sending msg [%u] to default driver proc\n", wMsg); 00998 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2); 00999 } 01000 return MCIERR_UNRECOGNIZED_COMMAND; 01001 } Generated on Sat May 19 2012 04:22:21 for ReactOS by
1.7.6.1
|