/* * Seven Kingdoms: Ancient Adversaries * * Copyright 1997,1998 Enlight Software Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //Filename : OVIDEO.CPP //Description : Video for Windows playback class //Owner : Gilbert #ifdef ENABLE_INTRO_VIDEO // for some .h files to define some IIDs #include #include #include #include #include #include #include #include #include #include //#include //#include #include #include #include // --------- Define constant -------// // OATRUE and OAFALSE are defined in classes\base\ctlutil.h under active movie SDK #define OATRUE -1 #define OAFALSE 0 static long FAR PASCAL video_win_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); static void create_dummy_window(HINSTANCE hInstance); // #define FULL_SCREEN_VIDEO #define CREATE_DUMMY_WINDOW /* //--------- Begin of function Video::play() ----------// // // aviFileName - the file name of the AVI file. // [DWORD] waitTime - no. of milli-seconds to wait still after // finishing playing the AVI. // (default: 0) // void Video::play(char* aviFileName, DWORD waitTime) { char resultStr[101]; String str; str = "open "; str += aviFileName; str += " alias mov"; mciSendString(str, NULL, 0, NULL); mciSendString("play mov fullscreen", NULL, 0, NULL); //------ wait until the whole video playback process is complete ------// while( 1 ) { mciSendString( "status mov mode", resultStr, 100, NULL ); if( strcmp(resultStr, "stopped")==0 ) break; } //-------- wait still after playing the movie ------// DWORD curTime = m.get_time(); while( m.get_time() < curTime+waitTime ); //------------ close the MCI ---------------// mciSendString("close mov" , NULL, 0, NULL); mciSendString("close avivideo", NULL, 0, NULL); } //--------- End of function Video::play() ----------// */ Video::Video() { CoInitialize(NULL); state = UNINITIALIZED; pGraph = NULL; hGraphNotifyEvent = NULL; init_success = 0; skip_on_fail_flag = 0; } Video::~Video() { CoUninitialize(); } void Video::set_skip_on_fail() { skip_on_fail_flag = 1; } void Video::clear_skip_on_fail() { skip_on_fail_flag = 0; } void Video::init() { IMediaEvent *pME; HRESULT hr; init_success = 0; hwnd = NULL; if( ( hr = CoCreateInstance(CLSID_FilterGraph, // CLSID of object NULL, // Outer unknown CLSCTX_INPROC_SERVER, // Type of server IID_IGraphBuilder, // Interface wanted (void **) &pGraph) // Returned object ) == 0 ) { // We use this to find out events sent by the filtergraph if( (hr = pGraph->QueryInterface(IID_IMediaEvent, (void **) &pME)) == 0) { if( (hr = pME->GetEventHandle( (OAEVENT*) &hGraphNotifyEvent)) == 0) { init_success = 1; state = STOPPED; } pME->Release(); } } if( hr && !skip_on_fail_flag) { err.run("video.init error %ld", hr ); } } void Video::deinit() { if( pGraph ) { pGraph->Release(); pGraph = NULL; } hGraphNotifyEvent = NULL; state = UNINITIALIZED; } void Video::play( char *fileName, DWORD ) { WCHAR wPath[100]; HRESULT hr; IMediaControl *pMC; if(!init_success) return; MultiByteToWideChar( CP_ACP, 0, fileName, -1, wPath, 100 ); if( (hr = pGraph->RenderFile(wPath, NULL)) == 0) { // use full screen video interface // try to change display mode IVideoWindow *iVideoWindow = NULL; if( (hr = pGraph->QueryInterface(IID_IVideoWindow, (void **) &iVideoWindow)) == 0) { #ifdef CREATE_DUMMY_WINDOW if(hwnd) { HRESULT hr2 = iVideoWindow->put_MessageDrain((OAHWND) hwnd); hr2 = 0; } #endif #ifdef FULL_SCREEN_VIDEO IFilter *iFilter; if( pGraph->FindFilterByName(L"Video Renderer", &iFilter) == 0) { IBasicVideo *iBasicVideo; if( iFilter->QueryInterface(IID_IBasicVideo, (void **)&iBasicVideo) == 0) { IFullScreenVideo *iFullScreenVideo; IDirectDrawVideo *iDirectDrawVideo; if( iFilter->QueryInterface(IID_IFullScreenVideo, (void **)&iFullScreenVideo) == 0) { iFullScreenVideo->Release(); } else if( iFilter->QueryInterface(IID_IDirectDrawVideo, (void **)&iDirectDrawVideo) == 0) { HRESULT hr2; hr2 = iDirectDrawVideo->UseWhenFullScreen(OATRUE); iDirectDrawVideo->Release(); } iBasicVideo->Release(); } iFilter->Release(); } hr=iVideoWindow->put_FullScreenMode(OATRUE); #endif /* // code to find all filter in the filter graph { IEnumFilters *iEnumFilters; pGraph->EnumFilters(&iEnumFilters); ULONG filterCount = 16; IFilter *iFilters[16]; iEnumFilters->Next(filterCount, iFilters, &filterCount); for( ULONG j = 0; j < filterCount; ++j ) { FILTER_INFO filterInfo; iFilters[j]->QueryFilterInfo(&filterInfo); filterInfo.pGraph->Release(); iFilters[j]->Release(); } iEnumFilters->Release(); }*/ iVideoWindow->HideCursor(OATRUE); iVideoWindow->put_Visible( OAFALSE ); iVideoWindow->put_AutoShow( OAFALSE ); LONG windowStyle; iVideoWindow->get_WindowStyle( &windowStyle); windowStyle &= ~WS_BORDER & ~WS_CAPTION & ~WS_SIZEBOX & ~WS_THICKFRAME & ~WS_HSCROLL & ~WS_VSCROLL & ~WS_VISIBLE; iVideoWindow->put_WindowStyle( windowStyle); } else iVideoWindow = NULL; if( (hr = pGraph->QueryInterface(IID_IMediaControl, (void **) &pMC)) == 0) { pMC->Run(); // sometimes it returns 1, but still ok state = PLAYING; pMC->Release(); } if( iVideoWindow ) { iVideoWindow->put_Visible( OAFALSE ); LONG windowStyle; iVideoWindow->get_WindowStyle( &windowStyle); windowStyle &= ~WS_BORDER & ~WS_CAPTION & ~WS_SIZEBOX & ~WS_THICKFRAME & ~WS_HSCROLL & ~WS_VSCROLL & ~WS_VISIBLE; iVideoWindow->put_WindowStyle( windowStyle); LONG maxWidth; LONG maxHeight; hr=iVideoWindow->GetMaxIdealImageSize( &maxWidth, &maxHeight); #ifdef FULL_SCREEN_VIDEO #else iVideoWindow->put_BorderColor( RGB(0,0,0) ); iVideoWindow->put_WindowState(SW_MAXIMIZE); IBaseFilter *iFilter; if( pGraph->FindFilterByName((const WCHAR *)L"Video Renderer", &iFilter) == 0) { IBasicVideo *iBasicVideo; if( iFilter->QueryInterface(IID_IBasicVideo, (void **)&iBasicVideo) == 0) { LONG screenWidth; LONG screenHeight; LONG videoWidth; LONG videoHeight; if( iVideoWindow->get_Width(&screenWidth) == 0 && iVideoWindow->get_Height(&screenHeight) == 0 && iBasicVideo->GetVideoSize(&videoWidth, &videoHeight) == 0) { // zoom in by 2 if possible if( screenWidth >= videoWidth * 2 && screenHeight >= videoHeight * 2) { videoWidth *= 2; videoHeight *= 2; } // center the video client area iBasicVideo->SetDestinationPosition( (screenWidth-videoWidth)/2, (screenHeight-videoHeight)/2, videoWidth, videoHeight); } iBasicVideo->Release(); } iFilter->Release(); } #endif iVideoWindow->HideCursor(OATRUE); iVideoWindow->SetWindowForeground(OATRUE); } if(iVideoWindow) { iVideoWindow->Release(); iVideoWindow = NULL; } } if( hr && !skip_on_fail_flag) err.run("video.play error %d", hr ); } void Video::play_until_end( char *fileName, HINSTANCE hInstance, DWORD t) { HANDLE ahObjects[1]; // Handles that need to be waited on const int cObjects = 1; // Number of objects that we have if(!init_success) return; hwnd = NULL; #ifdef CREATE_DUMMY_WINDOW create_dummy_window(hInstance); #endif play(fileName, t); while( state == PLAYING ) { if( (ahObjects[ 0 ] = hGraphNotifyEvent) == NULL) { state = STOPPED; break; } DWORD Result = MsgWaitForMultipleObjects( cObjects, ahObjects, FALSE, INFINITE, QS_ALLINPUT); // Have we received an event notification if( Result >= WAIT_OBJECT_0 && Result < (WAIT_OBJECT_0 + cObjects) ) { if( Result == WAIT_OBJECT_0 ) on_graph_notify(); } else if( Result == WAIT_OBJECT_0 + cObjects ) { if( hwnd ) { // message in the message queue MSG msg; while( PeekMessage(&msg, hwnd, 0, ~0UL, PM_NOREMOVE) ) { if( !GetMessage(&msg, hwnd, 0, ~0UL) ) break; TranslateMessage(&msg); DispatchMessage(&msg); } } } else { // other event to wait ... } } if( hwnd ) { PostMessage( hwnd, WM_CLOSE, 0, 0 ); //handle outstanding message MSG msg; while( GetMessage(&msg, hwnd, 0, ~0UL) ) { TranslateMessage(&msg); DispatchMessage(&msg); } } hwnd = NULL; } void Video::stop() { HRESULT hr; IMediaControl *pMC; if(!init_success) return; // Obtain the interface to our filter graph if( (hr = pGraph->QueryInterface(IID_IMediaControl, (void **) &pMC))== 0 ) { hr = pMC->Stop(); pMC->Release(); // rewind to the beginning IMediaPosition *pMP; if( (hr=pGraph->QueryInterface( IID_IMediaPosition, (void **) &pMP))==0) { pMP->put_CurrentPosition( 0); pMP->Release(); } } // force it to stop state = STOPPED; if( hr && !skip_on_fail_flag) err.run("video.stop error %d", hr ); } void Video::abort() { HRESULT hr; IMediaControl *pMC; if(!init_success) return; // Obtain the interface to our filter graph if( (hr = pGraph->QueryInterface(IID_IMediaControl, (void **) &pMC)) == 0) { // Ask the filter graph to stop and release the interface hr = pMC->Stop(); pMC->Release(); // rewind to the beginning IMediaPosition *pMP; if( (hr=pGraph->QueryInterface( IID_IMediaPosition, (void **) &pMP))==0) { pMP->put_CurrentPosition( 0); pMP->Release(); } } state = STOPPED; if( hr && !skip_on_fail_flag) err.run("video.abort error %d", hr); } void Video::on_graph_notify() { IMediaEvent *pME; LONG lEventCode; LONG_PTR lParam1, lParam2; HRESULT hr; if( (hr=pGraph->QueryInterface(IID_IMediaEvent, (void **) &pME)) == 0) { if( (hr=pME->GetEvent(&lEventCode, &lParam1, &lParam2, 0)) == 0) { switch(lEventCode) { case EC_COMPLETE: stop(); break; case EC_USERABORT: case EC_ERRORABORT: abort(); break; } } pME->Release(); } if( hr && !skip_on_fail_flag) err.run("video.on_graph_notify error %d", hr); } static void create_dummy_window(HINSTANCE hInstance) { //--------- register window class --------// WNDCLASS wc; BOOL rc; wc.style = CS_DBLCLKS; wc.lpfnWndProc = video_win_proc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; // LoadIcon( hInstance, MAKEINTATOM(IDI_ICON1)); wc.hCursor = LoadCursor( NULL, IDC_ARROW ); wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = "Seven Kingdoms Video Window"; rc = RegisterClass( &wc ); if( !rc ) return; video.hwnd = CreateWindowEx( WS_EX_APPWINDOW | WS_EX_TOPMOST, "Seven Kingdoms Video Window", "Seven Kingdoms", WS_POPUP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), NULL, NULL, hInstance, NULL ); if( !video.hwnd) return; UpdateWindow( video.hwnd ); SetFocus( video.hwnd ); return; } static long FAR PASCAL video_win_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch( message ) { case WM_CREATE: video.hwnd = hWnd; break; //case WM_SYSKEYUP: // if( (wParam==27 && lParam==0x80010001) || (wParam==9 && lParam==0xa00f0001) ) // pause(); // break; case WM_DESTROY: video.hwnd = NULL; PostQuitMessage( 0 ); break; case WM_LBUTTONDOWN: video.stop(); PostMessage(hWnd, WM_CLOSE, 0, 0); break; default: break; } return DefWindowProc(hWnd, message, wParam, lParam); } #endif // ENABLE_INTRO_VIDEO