00001
00002
00003
00004
00005
00006 #include <windows.h>
00007 #include <windowsx.h>
00008 #include <commdlg.h>
00009 #include <string.h>
00010 #include <objbase.h>
00011 #include <strmif.h>
00012 #include <evcode.h>
00013 #include <control.h>
00014
00015 #include <amvideo.h>
00016 #include <uuids.h>
00017
00018
00019
00020
00021 #include <ALL.H>
00022 #include <OSTR.H>
00023 #include <OVIDEO.H>
00024 #include <OVGA.H>
00025 #include <OSYS.H>
00026
00027
00028
00029 #define OATRUE -1
00030 #define OAFALSE 0
00031
00032 static long FAR PASCAL video_win_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
00033 static void create_dummy_window(HINSTANCE hInstance);
00034
00035 #define FULL_SCREEN_VIDEO
00036 #define CREATE_DUMMY_WINDOW
00037
00038
00039
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 Video::Video() {
00083 CoInitialize(NULL);
00084 state = UNINITIALIZED;
00085 pGraph = NULL;
00086 hGraphNotifyEvent = NULL;
00087 init_success = 0;
00088 skip_on_fail_flag = 0;
00089 }
00090
00091 Video::~Video() {
00092 CoUninitialize();
00093 }
00094
00095 void Video::set_skip_on_fail() {
00096 skip_on_fail_flag = 1;
00097 }
00098
00099 void Video::clear_skip_on_fail() {
00100 skip_on_fail_flag = 0;
00101 }
00102
00103 void Video::init() {
00104 IMediaEvent *pME;
00105 HRESULT hr;
00106
00107 init_success = 0;
00108 hwnd = NULL;
00109 if( ( hr = CoCreateInstance(CLSID_FilterGraph,
00110 NULL,
00111 CLSCTX_INPROC_SERVER,
00112 IID_IGraphBuilder,
00113 (void **) &pGraph)
00114 ) == 0 ) {
00115
00116 if( (hr = pGraph->QueryInterface(IID_IMediaEvent, (void **) &pME)) == 0) {
00117 if( (hr = pME->GetEventHandle( (OAEVENT*) &hGraphNotifyEvent)) == 0) {
00118 init_success = 1;
00119 state = STOPPED;
00120 }
00121 pME->Release();
00122 }
00123 }
00124
00125 if( hr && !skip_on_fail_flag) {
00126 err.run("video.init error %ld", hr );
00127 }
00128 }
00129
00130 void Video::deinit() {
00131 if( pGraph ) {
00132 pGraph->Release();
00133 pGraph = NULL;
00134 }
00135 hGraphNotifyEvent = NULL;
00136 state = UNINITIALIZED;
00137 }
00138
00139 void Video::play( char *fileName, DWORD ) {
00140 WCHAR wPath[100];
00141 HRESULT hr;
00142 IMediaControl *pMC;
00143
00144 if(!init_success)
00145 return;
00146
00147 MultiByteToWideChar( CP_ACP, 0, fileName, -1, wPath, 100 );
00148
00149 if( (hr = pGraph->RenderFile(wPath, NULL)) == 0) {
00150
00151
00152
00153 IVideoWindow *iVideoWindow = NULL;
00154 if( (hr = pGraph->QueryInterface(IID_IVideoWindow, (void **) &iVideoWindow)) == 0) {
00155 #ifdef CREATE_DUMMY_WINDOW
00156 if(hwnd) {
00157 HRESULT hr2 = iVideoWindow->put_MessageDrain((OAHWND) hwnd);
00158 hr2 = 0;
00159 }
00160 #endif
00161
00162 #ifdef FULL_SCREEN_VIDEO
00163 IBaseFilter *iFilter;
00164 if( pGraph->FindFilterByName(L"Video Renderer", &iFilter) == 0) {
00165 IBasicVideo *iBasicVideo;
00166 if( iFilter->QueryInterface(IID_IBasicVideo, (void **)&iBasicVideo) == 0) {
00167 IFullScreenVideo *iFullScreenVideo;
00168 IDirectDrawVideo *iDirectDrawVideo;
00169 if( iFilter->QueryInterface(IID_IFullScreenVideo, (void **)&iFullScreenVideo) == 0) {
00170 iFullScreenVideo->Release();
00171 }
00172 else if( iFilter->QueryInterface(IID_IDirectDrawVideo, (void **)&iDirectDrawVideo) == 0) {
00173 HRESULT hr2;
00174 hr2 = iDirectDrawVideo->UseWhenFullScreen(OATRUE);
00175
00176 iDirectDrawVideo->Release();
00177
00178 }
00179
00180 iBasicVideo->Release();
00181 }
00182 iFilter->Release();
00183 }
00184 hr=iVideoWindow->put_FullScreenMode(OATRUE);
00185 #endif
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 iVideoWindow->HideCursor(OATRUE);
00208 iVideoWindow->put_Visible( OAFALSE );
00209 iVideoWindow->put_AutoShow( OAFALSE );
00210 long windowStyle;
00211 iVideoWindow->get_WindowStyle( &windowStyle);
00212 windowStyle &= ~WS_BORDER & ~WS_CAPTION & ~WS_SIZEBOX & ~WS_THICKFRAME &
00213 ~WS_HSCROLL & ~WS_VSCROLL & ~WS_VISIBLE;
00214 iVideoWindow->put_WindowStyle( windowStyle);
00215 }
00216 else
00217 iVideoWindow = NULL;
00218
00219 if( (hr = pGraph->QueryInterface(IID_IMediaControl, (void **) &pMC)) == 0) {
00220 pMC->Run();
00221 state = PLAYING;
00222 pMC->Release();
00223 }
00224
00225 if( iVideoWindow ) {
00226 iVideoWindow->put_Visible( OAFALSE );
00227 long windowStyle;
00228 iVideoWindow->get_WindowStyle( &windowStyle);
00229 windowStyle &= ~WS_BORDER & ~WS_CAPTION & ~WS_SIZEBOX & ~WS_THICKFRAME &
00230 ~WS_HSCROLL & ~WS_VSCROLL & ~WS_VISIBLE;
00231 iVideoWindow->put_WindowStyle( windowStyle);
00232
00233 long maxWidth;
00234 long maxHeight;
00235 hr=iVideoWindow->GetMaxIdealImageSize( &maxWidth, &maxHeight);
00236 #ifdef FULL_SCREEN_VIDEO
00237 #else
00238 iVideoWindow->put_BorderColor( RGB(0,0,0) );
00239 iVideoWindow->put_WindowState(SW_MAXIMIZE);
00240
00241 IBaseFilter *iFilter;
00242 if( pGraph->FindFilterByName(L"Video Renderer", &iFilter) == 0) {
00243 IBasicVideo *iBasicVideo;
00244 if( iFilter->QueryInterface(IID_IBasicVideo, (void **)&iBasicVideo) == 0) {
00245 long screenWidth;
00246 long screenHeight;
00247 long videoWidth;
00248 long videoHeight;
00249 if( iVideoWindow->get_Width(&screenWidth) == 0 &&
00250 iVideoWindow->get_Height(&screenHeight) == 0 &&
00251 iBasicVideo->GetVideoSize(&videoWidth, &videoHeight) == 0) {
00252
00253 if( screenWidth >= videoWidth * 2 &&
00254 screenHeight >= videoHeight * 2) {
00255 videoWidth *= 2;
00256 videoHeight *= 2;
00257 }
00258
00259
00260 iBasicVideo->SetDestinationPosition(
00261 (screenWidth-videoWidth)/2, (screenHeight-videoHeight)/2,
00262 videoWidth, videoHeight);
00263 }
00264
00265 iBasicVideo->Release();
00266 }
00267 iFilter->Release();
00268 }
00269 #endif
00270 iVideoWindow->HideCursor(OATRUE);
00271 iVideoWindow->SetWindowForeground(OATRUE);
00272 }
00273
00274 if(iVideoWindow) {
00275 iVideoWindow->Release();
00276 iVideoWindow = NULL;
00277 }
00278 }
00279
00280 if( hr && !skip_on_fail_flag)
00281 err.run("video.play error %d", hr );
00282 }
00283
00284 void Video::play_until_end( char *fileName, HINSTANCE hInstance, DWORD t) {
00285 HANDLE ahObjects[1];
00286 const int cObjects = 1;
00287
00288 if(!init_success)
00289 return;
00290
00291 hwnd = NULL;
00292 #ifdef CREATE_DUMMY_WINDOW
00293 create_dummy_window(hInstance);
00294 #endif
00295
00296 play(fileName, t);
00297
00298 while( state == PLAYING ) {
00299 if( (ahObjects[ 0 ] = hGraphNotifyEvent) == NULL) {
00300 state = STOPPED;
00301 break;
00302 }
00303 DWORD Result = MsgWaitForMultipleObjects( cObjects, ahObjects,
00304 FALSE, INFINITE, QS_ALLINPUT);
00305
00306
00307 if( Result >= WAIT_OBJECT_0 && Result < (WAIT_OBJECT_0 + cObjects) ) {
00308 if( Result == WAIT_OBJECT_0 )
00309 on_graph_notify();
00310 }
00311 else if( Result == WAIT_OBJECT_0 + cObjects ) {
00312 if( hwnd ) {
00313
00314 MSG msg;
00315
00316 while( PeekMessage(&msg, hwnd, 0, 0, PM_NOREMOVE) ) {
00317 if( !GetMessage(&msg, hwnd, 0, 0) )
00318 break;
00319 TranslateMessage(&msg);
00320 DispatchMessage(&msg);
00321 }
00322
00323 }
00324 }
00325 else {
00326
00327 }
00328 }
00329
00330 if( hwnd ) {
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341 DestroyWindow(hwnd);
00342 }
00343 hwnd = NULL;
00344
00345
00346
00347 if(sys.main_hwnd ) {
00348 ShowWindow( sys.main_hwnd, SW_RESTORE );
00349 SetFocus( sys.main_hwnd );
00350 }
00351 }
00352
00353 void Video::stop() {
00354
00355 HRESULT hr;
00356 IMediaControl *pMC;
00357
00358 if(!init_success)
00359 return;
00360
00361
00362 if( (hr = pGraph->QueryInterface(IID_IMediaControl, (void **) &pMC))== 0 ) {
00363 hr = pMC->Stop();
00364 pMC->Release();
00365
00366
00367 IMediaPosition *pMP;
00368 if( (hr=pGraph->QueryInterface( IID_IMediaPosition, (void **) &pMP))==0) {
00369 pMP->put_CurrentPosition( 0);
00370 pMP->Release();
00371 }
00372 }
00373
00374 state = STOPPED;
00375
00376 if( hr && !skip_on_fail_flag)
00377 err.run("video.stop error %d", hr );
00378 }
00379
00380 void Video::abort() {
00381 HRESULT hr;
00382 IMediaControl *pMC;
00383
00384 if(!init_success)
00385 return;
00386
00387
00388 if( (hr = pGraph->QueryInterface(IID_IMediaControl, (void **) &pMC)) == 0) {
00389
00390 hr = pMC->Stop();
00391 pMC->Release();
00392
00393
00394 IMediaPosition *pMP;
00395 if( (hr=pGraph->QueryInterface( IID_IMediaPosition, (void **) &pMP))==0) {
00396 pMP->put_CurrentPosition( 0);
00397 pMP->Release();
00398 }
00399 }
00400 state = STOPPED;
00401
00402 if( hr && !skip_on_fail_flag)
00403 err.run("video.abort error %d", hr);
00404 }
00405
00406 void Video::on_graph_notify() {
00407 IMediaEvent *pME;
00408 long lEventCode, lParam1, lParam2;
00409 HRESULT hr;
00410
00411 if( (hr=pGraph->QueryInterface(IID_IMediaEvent, (void **) &pME)) == 0) {
00412 if( (hr=pME->GetEvent(&lEventCode, &lParam1, &lParam2, 0)) == 0) {
00413 switch(lEventCode) {
00414 case EC_COMPLETE:
00415 stop();
00416 break;
00417
00418 case EC_USERABORT:
00419 case EC_ERRORABORT:
00420 abort();
00421 break;
00422 }
00423 }
00424 pME->Release();
00425 }
00426
00427 if( hr && !skip_on_fail_flag)
00428 err.run("video.on_graph_notify error %d", hr);
00429 }
00430
00431 static void create_dummy_window(HINSTANCE hInstance) {
00432 static ATOM classRegistered = 0;
00433
00434 if( !classRegistered ) {
00435
00436
00437 WNDCLASS wc;
00438 ATOM rc;
00439
00440 wc.style = CS_DBLCLKS;
00441 wc.lpfnWndProc = video_win_proc;
00442 wc.cbClsExtra = 0;
00443 wc.cbWndExtra = 0;
00444 wc.hInstance = hInstance;
00445 wc.hIcon = NULL;
00446 wc.hCursor = LoadCursor( NULL, IDC_ARROW );
00447
00448 wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
00449
00450
00451
00452 wc.lpszMenuName = NULL;
00453 wc.lpszClassName = "Virtual U Video Window";
00454
00455 rc = RegisterClass( &wc );
00456
00457 if( rc != 0 )
00458 classRegistered = rc;
00459 else
00460 return;
00461 }
00462
00463 video.hwnd = CreateWindowEx(
00464
00465 #ifdef _DEBUG
00466 NULL,
00467 #else
00468 WS_EX_APPWINDOW | WS_EX_TOPMOST,
00469 #endif
00470
00471 "Virtual U Video Window",
00472 "Virtual U",
00473 WS_POPUP,
00474 0,
00475 0,
00476 GetSystemMetrics(SM_CXSCREEN),
00477 GetSystemMetrics(SM_CYSCREEN),
00478 NULL,
00479 NULL,
00480 hInstance,
00481 NULL );
00482
00483 if( !video.hwnd)
00484 return;
00485
00486 UpdateWindow( video.hwnd );
00487 SetFocus( video.hwnd );
00488
00489 return;
00490 }
00491
00492 static long FAR PASCAL video_win_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
00493 switch( message ) {
00494 case WM_CREATE:
00495 video.hwnd = hWnd;
00496 break;
00497
00498
00499
00500
00501
00502
00503 case WM_DESTROY:
00504 video.hwnd = NULL;
00505
00506 break;
00507
00508 case WM_LBUTTONDOWN:
00509 video.stop();
00510 PostMessage(hWnd, WM_CLOSE, 0, 0);
00511 break;
00512
00513 default:
00514 break;
00515 }
00516
00517 return DefWindowProc(hWnd, message, wParam, lParam);
00518 }