OVIDEO.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. /*
  2. * Seven Kingdoms: Ancient Adversaries
  3. *
  4. * Copyright 1997,1998 Enlight Software Ltd.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. //Filename : OVIDEO.CPP
  21. //Description : Video for Windows playback class
  22. //Owner : Gilbert
  23. #ifdef ENABLE_INTRO_VIDEO
  24. // for some .h files to define some IIDs
  25. #include <windows.h>
  26. #include <windowsx.h>
  27. #include <commdlg.h>
  28. #include <string.h>
  29. #include <objbase.h>
  30. #include <strmif.h>
  31. #include <evcode.h>
  32. #include <control.h>
  33. #include <amvideo.h>
  34. #include <uuids.h>
  35. //#include <mmsystem.h>
  36. //#include <digitalv.h>
  37. #include <ALL.h>
  38. #include <OSTR.h>
  39. #include <OVIDEO.h>
  40. // --------- Define constant -------//
  41. // OATRUE and OAFALSE are defined in classes\base\ctlutil.h under active movie SDK
  42. #define OATRUE -1
  43. #define OAFALSE 0
  44. static long FAR PASCAL video_win_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
  45. static void create_dummy_window(HINSTANCE hInstance);
  46. // #define FULL_SCREEN_VIDEO
  47. #define CREATE_DUMMY_WINDOW
  48. /*
  49. //--------- Begin of function Video::play() ----------//
  50. //
  51. // <char*> aviFileName - the file name of the AVI file.
  52. // [DWORD] waitTime - no. of milli-seconds to wait still after
  53. // finishing playing the AVI.
  54. // (default: 0)
  55. //
  56. void Video::play(char* aviFileName, DWORD waitTime)
  57. {
  58. char resultStr[101];
  59. String str;
  60. str = "open ";
  61. str += aviFileName;
  62. str += " alias mov";
  63. mciSendString(str, NULL, 0, NULL);
  64. mciSendString("play mov fullscreen", NULL, 0, NULL);
  65. //------ wait until the whole video playback process is complete ------//
  66. while( 1 )
  67. {
  68. mciSendString( "status mov mode", resultStr, 100, NULL );
  69. if( strcmp(resultStr, "stopped")==0 )
  70. break;
  71. }
  72. //-------- wait still after playing the movie ------//
  73. DWORD curTime = m.get_time();
  74. while( m.get_time() < curTime+waitTime );
  75. //------------ close the MCI ---------------//
  76. mciSendString("close mov" , NULL, 0, NULL);
  77. mciSendString("close avivideo", NULL, 0, NULL);
  78. }
  79. //--------- End of function Video::play() ----------//
  80. */
  81. Video::Video()
  82. {
  83. CoInitialize(NULL);
  84. state = UNINITIALIZED;
  85. pGraph = NULL;
  86. hGraphNotifyEvent = NULL;
  87. init_success = 0;
  88. skip_on_fail_flag = 0;
  89. }
  90. Video::~Video()
  91. {
  92. CoUninitialize();
  93. }
  94. void Video::set_skip_on_fail()
  95. {
  96. skip_on_fail_flag = 1;
  97. }
  98. void Video::clear_skip_on_fail()
  99. {
  100. skip_on_fail_flag = 0;
  101. }
  102. void Video::init()
  103. {
  104. IMediaEvent *pME;
  105. HRESULT hr;
  106. init_success = 0;
  107. hwnd = NULL;
  108. if( ( hr = CoCreateInstance(CLSID_FilterGraph, // CLSID of object
  109. NULL, // Outer unknown
  110. CLSCTX_INPROC_SERVER, // Type of server
  111. IID_IGraphBuilder, // Interface wanted
  112. (void **) &pGraph) // Returned object
  113. ) == 0 )
  114. {
  115. // We use this to find out events sent by the filtergraph
  116. if( (hr = pGraph->QueryInterface(IID_IMediaEvent, (void **) &pME)) == 0)
  117. {
  118. if( (hr = pME->GetEventHandle( (OAEVENT*) &hGraphNotifyEvent)) == 0)
  119. {
  120. init_success = 1;
  121. state = STOPPED;
  122. }
  123. pME->Release();
  124. }
  125. }
  126. if( hr && !skip_on_fail_flag)
  127. {
  128. err.run("video.init error %ld", hr );
  129. }
  130. }
  131. void Video::deinit()
  132. {
  133. if( pGraph )
  134. {
  135. pGraph->Release();
  136. pGraph = NULL;
  137. }
  138. hGraphNotifyEvent = NULL;
  139. state = UNINITIALIZED;
  140. }
  141. void Video::play( char *fileName, DWORD )
  142. {
  143. WCHAR wPath[100];
  144. HRESULT hr;
  145. IMediaControl *pMC;
  146. if(!init_success)
  147. return;
  148. MultiByteToWideChar( CP_ACP, 0, fileName, -1, wPath, 100 );
  149. if( (hr = pGraph->RenderFile(wPath, NULL)) == 0)
  150. {
  151. // use full screen video interface
  152. // try to change display mode
  153. IVideoWindow *iVideoWindow = NULL;
  154. if( (hr = pGraph->QueryInterface(IID_IVideoWindow, (void **) &iVideoWindow)) == 0)
  155. {
  156. #ifdef CREATE_DUMMY_WINDOW
  157. if(hwnd)
  158. {
  159. HRESULT hr2 = iVideoWindow->put_MessageDrain((OAHWND) hwnd);
  160. hr2 = 0;
  161. }
  162. #endif
  163. #ifdef FULL_SCREEN_VIDEO
  164. IFilter *iFilter;
  165. if( pGraph->FindFilterByName(L"Video Renderer", &iFilter) == 0)
  166. {
  167. IBasicVideo *iBasicVideo;
  168. if( iFilter->QueryInterface(IID_IBasicVideo, (void **)&iBasicVideo) == 0)
  169. {
  170. IFullScreenVideo *iFullScreenVideo;
  171. IDirectDrawVideo *iDirectDrawVideo;
  172. if( iFilter->QueryInterface(IID_IFullScreenVideo, (void **)&iFullScreenVideo) == 0)
  173. {
  174. iFullScreenVideo->Release();
  175. }
  176. else if( iFilter->QueryInterface(IID_IDirectDrawVideo, (void **)&iDirectDrawVideo) == 0)
  177. {
  178. HRESULT hr2;
  179. hr2 = iDirectDrawVideo->UseWhenFullScreen(OATRUE);
  180. iDirectDrawVideo->Release();
  181. }
  182. iBasicVideo->Release();
  183. }
  184. iFilter->Release();
  185. }
  186. hr=iVideoWindow->put_FullScreenMode(OATRUE);
  187. #endif
  188. /* // code to find all filter in the filter graph
  189. {
  190. IEnumFilters *iEnumFilters;
  191. pGraph->EnumFilters(&iEnumFilters);
  192. ULONG filterCount = 16;
  193. IFilter *iFilters[16];
  194. iEnumFilters->Next(filterCount, iFilters, &filterCount);
  195. for( ULONG j = 0; j < filterCount; ++j )
  196. {
  197. FILTER_INFO filterInfo;
  198. iFilters[j]->QueryFilterInfo(&filterInfo);
  199. filterInfo.pGraph->Release();
  200. iFilters[j]->Release();
  201. }
  202. iEnumFilters->Release();
  203. }*/
  204. iVideoWindow->HideCursor(OATRUE);
  205. iVideoWindow->put_Visible( OAFALSE );
  206. iVideoWindow->put_AutoShow( OAFALSE );
  207. LONG windowStyle;
  208. iVideoWindow->get_WindowStyle( &windowStyle);
  209. windowStyle &= ~WS_BORDER & ~WS_CAPTION & ~WS_SIZEBOX & ~WS_THICKFRAME &
  210. ~WS_HSCROLL & ~WS_VSCROLL & ~WS_VISIBLE;
  211. iVideoWindow->put_WindowStyle( windowStyle);
  212. }
  213. else
  214. iVideoWindow = NULL;
  215. if( (hr = pGraph->QueryInterface(IID_IMediaControl, (void **) &pMC)) == 0)
  216. {
  217. pMC->Run(); // sometimes it returns 1, but still ok
  218. state = PLAYING;
  219. pMC->Release();
  220. }
  221. if( iVideoWindow )
  222. {
  223. iVideoWindow->put_Visible( OAFALSE );
  224. LONG windowStyle;
  225. iVideoWindow->get_WindowStyle( &windowStyle);
  226. windowStyle &= ~WS_BORDER & ~WS_CAPTION & ~WS_SIZEBOX & ~WS_THICKFRAME &
  227. ~WS_HSCROLL & ~WS_VSCROLL & ~WS_VISIBLE;
  228. iVideoWindow->put_WindowStyle( windowStyle);
  229. LONG maxWidth;
  230. LONG maxHeight;
  231. hr=iVideoWindow->GetMaxIdealImageSize( &maxWidth, &maxHeight);
  232. #ifdef FULL_SCREEN_VIDEO
  233. #else
  234. iVideoWindow->put_BorderColor( RGB(0,0,0) );
  235. iVideoWindow->put_WindowState(SW_MAXIMIZE);
  236. IBaseFilter *iFilter;
  237. if( pGraph->FindFilterByName((const WCHAR *)L"Video Renderer", &iFilter) == 0)
  238. {
  239. IBasicVideo *iBasicVideo;
  240. if( iFilter->QueryInterface(IID_IBasicVideo, (void **)&iBasicVideo) == 0)
  241. {
  242. LONG screenWidth;
  243. LONG screenHeight;
  244. LONG videoWidth;
  245. LONG videoHeight;
  246. if( iVideoWindow->get_Width(&screenWidth) == 0 &&
  247. iVideoWindow->get_Height(&screenHeight) == 0 &&
  248. iBasicVideo->GetVideoSize(&videoWidth, &videoHeight) == 0)
  249. {
  250. // zoom in by 2 if possible
  251. if( screenWidth >= videoWidth * 2 &&
  252. screenHeight >= videoHeight * 2)
  253. {
  254. videoWidth *= 2;
  255. videoHeight *= 2;
  256. }
  257. // center the video client area
  258. iBasicVideo->SetDestinationPosition(
  259. (screenWidth-videoWidth)/2, (screenHeight-videoHeight)/2,
  260. videoWidth, videoHeight);
  261. }
  262. iBasicVideo->Release();
  263. }
  264. iFilter->Release();
  265. }
  266. #endif
  267. iVideoWindow->HideCursor(OATRUE);
  268. iVideoWindow->SetWindowForeground(OATRUE);
  269. }
  270. if(iVideoWindow)
  271. {
  272. iVideoWindow->Release();
  273. iVideoWindow = NULL;
  274. }
  275. }
  276. if( hr && !skip_on_fail_flag)
  277. err.run("video.play error %d", hr );
  278. }
  279. void Video::play_until_end( char *fileName, HINSTANCE hInstance, DWORD t)
  280. {
  281. HANDLE ahObjects[1]; // Handles that need to be waited on
  282. const int cObjects = 1; // Number of objects that we have
  283. if(!init_success)
  284. return;
  285. hwnd = NULL;
  286. #ifdef CREATE_DUMMY_WINDOW
  287. create_dummy_window(hInstance);
  288. #endif
  289. play(fileName, t);
  290. while( state == PLAYING )
  291. {
  292. if( (ahObjects[ 0 ] = hGraphNotifyEvent) == NULL)
  293. {
  294. state = STOPPED;
  295. break;
  296. }
  297. DWORD Result = MsgWaitForMultipleObjects( cObjects, ahObjects,
  298. FALSE, INFINITE, QS_ALLINPUT);
  299. // Have we received an event notification
  300. if( Result >= WAIT_OBJECT_0 && Result < (WAIT_OBJECT_0 + cObjects) )
  301. {
  302. if( Result == WAIT_OBJECT_0 )
  303. on_graph_notify();
  304. }
  305. else if( Result == WAIT_OBJECT_0 + cObjects )
  306. {
  307. if( hwnd )
  308. {
  309. // message in the message queue
  310. MSG msg;
  311. while( PeekMessage(&msg, hwnd, 0, ~0UL, PM_NOREMOVE) )
  312. {
  313. if( !GetMessage(&msg, hwnd, 0, ~0UL) )
  314. break;
  315. TranslateMessage(&msg);
  316. DispatchMessage(&msg);
  317. }
  318. }
  319. }
  320. else
  321. {
  322. // other event to wait ...
  323. }
  324. }
  325. if( hwnd )
  326. {
  327. PostMessage( hwnd, WM_CLOSE, 0, 0 );
  328. //handle outstanding message
  329. MSG msg;
  330. while( GetMessage(&msg, hwnd, 0, ~0UL) )
  331. {
  332. TranslateMessage(&msg);
  333. DispatchMessage(&msg);
  334. }
  335. }
  336. hwnd = NULL;
  337. }
  338. void Video::stop()
  339. {
  340. HRESULT hr;
  341. IMediaControl *pMC;
  342. if(!init_success)
  343. return;
  344. // Obtain the interface to our filter graph
  345. if( (hr = pGraph->QueryInterface(IID_IMediaControl, (void **) &pMC))== 0 )
  346. {
  347. hr = pMC->Stop();
  348. pMC->Release();
  349. // rewind to the beginning
  350. IMediaPosition *pMP;
  351. if( (hr=pGraph->QueryInterface( IID_IMediaPosition, (void **) &pMP))==0)
  352. {
  353. pMP->put_CurrentPosition( 0);
  354. pMP->Release();
  355. }
  356. }
  357. // force it to stop
  358. state = STOPPED;
  359. if( hr && !skip_on_fail_flag)
  360. err.run("video.stop error %d", hr );
  361. }
  362. void Video::abort()
  363. {
  364. HRESULT hr;
  365. IMediaControl *pMC;
  366. if(!init_success)
  367. return;
  368. // Obtain the interface to our filter graph
  369. if( (hr = pGraph->QueryInterface(IID_IMediaControl, (void **) &pMC)) == 0)
  370. {
  371. // Ask the filter graph to stop and release the interface
  372. hr = pMC->Stop();
  373. pMC->Release();
  374. // rewind to the beginning
  375. IMediaPosition *pMP;
  376. if( (hr=pGraph->QueryInterface( IID_IMediaPosition, (void **) &pMP))==0)
  377. {
  378. pMP->put_CurrentPosition( 0);
  379. pMP->Release();
  380. }
  381. }
  382. state = STOPPED;
  383. if( hr && !skip_on_fail_flag)
  384. err.run("video.abort error %d", hr);
  385. }
  386. void Video::on_graph_notify()
  387. {
  388. IMediaEvent *pME;
  389. LONG lEventCode;
  390. LONG_PTR lParam1, lParam2;
  391. HRESULT hr;
  392. if( (hr=pGraph->QueryInterface(IID_IMediaEvent, (void **) &pME)) == 0)
  393. {
  394. if( (hr=pME->GetEvent(&lEventCode, &lParam1, &lParam2, 0)) == 0)
  395. {
  396. switch(lEventCode)
  397. {
  398. case EC_COMPLETE:
  399. stop();
  400. break;
  401. case EC_USERABORT:
  402. case EC_ERRORABORT:
  403. abort();
  404. break;
  405. }
  406. }
  407. pME->Release();
  408. }
  409. if( hr && !skip_on_fail_flag)
  410. err.run("video.on_graph_notify error %d", hr);
  411. }
  412. static void create_dummy_window(HINSTANCE hInstance)
  413. {
  414. //--------- register window class --------//
  415. WNDCLASS wc;
  416. BOOL rc;
  417. wc.style = CS_DBLCLKS;
  418. wc.lpfnWndProc = video_win_proc;
  419. wc.cbClsExtra = 0;
  420. wc.cbWndExtra = 0;
  421. wc.hInstance = hInstance;
  422. wc.hIcon = NULL; // LoadIcon( hInstance, MAKEINTATOM(IDI_ICON1));
  423. wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  424. wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
  425. wc.lpszMenuName = NULL;
  426. wc.lpszClassName = "Seven Kingdoms Video Window";
  427. rc = RegisterClass( &wc );
  428. if( !rc )
  429. return;
  430. video.hwnd = CreateWindowEx(
  431. WS_EX_APPWINDOW | WS_EX_TOPMOST,
  432. "Seven Kingdoms Video Window",
  433. "Seven Kingdoms",
  434. WS_POPUP,
  435. 0,
  436. 0,
  437. GetSystemMetrics(SM_CXSCREEN),
  438. GetSystemMetrics(SM_CYSCREEN),
  439. NULL,
  440. NULL,
  441. hInstance,
  442. NULL );
  443. if( !video.hwnd)
  444. return;
  445. UpdateWindow( video.hwnd );
  446. SetFocus( video.hwnd );
  447. return;
  448. }
  449. static long FAR PASCAL video_win_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  450. {
  451. switch( message )
  452. {
  453. case WM_CREATE:
  454. video.hwnd = hWnd;
  455. break;
  456. //case WM_SYSKEYUP:
  457. // if( (wParam==27 && lParam==0x80010001) || (wParam==9 && lParam==0xa00f0001) )
  458. // pause();
  459. // break;
  460. case WM_DESTROY:
  461. video.hwnd = NULL;
  462. PostQuitMessage( 0 );
  463. break;
  464. case WM_LBUTTONDOWN:
  465. video.stop();
  466. PostMessage(hWnd, WM_CLOSE, 0, 0);
  467. break;
  468. default:
  469. break;
  470. }
  471. return DefWindowProc(hWnd, message, wParam, lParam);
  472. }
  473. #endif // ENABLE_INTRO_VIDEO