QuicktimeGraph.cpp

00001 /* 
00002  *      Copyright (C) 2003-2005 Gabest
00003  *      http://www.gabest.org
00004  *
00005  *  This Program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2, or (at your option)
00008  *  any later version.
00009  *   
00010  *  This Program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013  *  GNU General Public License for more details.
00014  *   
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with GNU Make; see the file COPYING.  If not, write to
00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
00018  *  http://www.gnu.org/copyleft/gpl.html
00019  *
00020  */
00021 
00022 #include "stdafx.h"
00023 #include <math.h>
00024 #include "QuicktimeGraph.h"
00025 #include "IQTVideoSurface.h"
00026 #include "mplayerc.h"
00027 #include "..\..\DSUtil\DSUtil.h"
00028 
00029 //
00030 // CQuicktimeGraph
00031 //
00032 
00033 #pragma warning(disable:4355) // 'this' : used in base member initializer list
00034 
00035 using namespace QT;
00036 
00037 CQuicktimeGraph::CQuicktimeGraph(HWND hWndParent, HRESULT& hr)
00038         : CBaseGraph()
00039         , m_wndDestFrame(this)
00040         , m_fQtInitialized(false)
00041 {
00042         hr = S_OK;
00043 
00044         DWORD dwStyle = WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN;
00045 
00046         AppSettings& s = AfxGetAppSettings();
00047 
00048         if(s.iQTVideoRendererType == VIDRNDT_QT_DX7)
00049         {
00050                 if(SUCCEEDED(CreateAP7(CLSID_QT7AllocatorPresenter, hWndParent, &m_pQTAP))) 
00051                         dwStyle &= ~WS_VISIBLE;
00052         }
00053         else if(s.iQTVideoRendererType == VIDRNDT_QT_DX9)
00054         {
00055                 if(SUCCEEDED(CreateAP9(CLSID_QT9AllocatorPresenter, hWndParent, &m_pQTAP))) 
00056             dwStyle &= ~WS_VISIBLE;
00057         }
00058 
00059         m_fQtInitialized = false;
00060         if(InitializeQTML(0) != 0) {hr = E_FAIL; return;}
00061         if(EnterMovies() != 0) {TerminateQTML(); hr = E_FAIL; return;}
00062         m_fQtInitialized = true;
00063 
00064         if(!m_wndWindowFrame.CreateEx(WS_EX_NOPARENTNOTIFY, NULL, NULL, dwStyle, CRect(0, 0, 0, 0), CWnd::FromHandle(hWndParent), 0))
00065         {
00066                 hr = E_FAIL;
00067                 return;
00068         }
00069 
00070         if(!m_wndDestFrame.Create(NULL, NULL, dwStyle, CRect(0, 0, 0, 0), &m_wndWindowFrame, 0))
00071         {
00072                 hr = E_FAIL;
00073                 return;
00074         }
00075 }
00076 
00077 CQuicktimeGraph::~CQuicktimeGraph()
00078 {
00079         m_wndDestFrame.DestroyWindow();
00080         m_wndWindowFrame.DestroyWindow();
00081 
00082         if(m_fQtInitialized)
00083         {
00084                 ExitMovies();
00085                 TerminateQTML();
00086         }
00087 }
00088 
00089 STDMETHODIMP CQuicktimeGraph::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00090 {
00091     CheckPointer(ppv, E_POINTER);
00092 
00093         return 
00094                 QI(IVideoFrameStep)
00095                 (m_pQTAP && (riid == __uuidof(ISubPicAllocatorPresenter) || riid == __uuidof(IQTVideoSurface))) ? m_pQTAP->QueryInterface(riid, ppv) : 
00096                 __super::NonDelegatingQueryInterface(riid, ppv);
00097 }
00098 
00099 // IGraphBuilder
00100 STDMETHODIMP CQuicktimeGraph::RenderFile(LPCWSTR lpcwstrFile, LPCWSTR lpcwstrPlayList)
00101 {
00102         bool fRet = m_wndDestFrame.OpenMovie(CString(lpcwstrFile));
00103 
00104         if(fRet)
00105         {
00106                 for(int i = 1, cnt = GetMovieTrackCount(m_wndDestFrame.theMovie); i <= cnt; i++)
00107                 {
00108                         Track aTrack = GetMovieIndTrack(m_wndDestFrame.theMovie, i);
00109                         Media aMedia = GetTrackMedia(aTrack);
00110 
00111                         OSType aTrackType;
00112                         GetMediaHandlerDescription(aMedia, &aTrackType, 0, 0);
00113                         if(aTrackType == SoundMediaType)
00114                         {
00115                                 SampleDescriptionHandle aDesc = (SampleDescriptionHandle)NewHandle(sizeof(aDesc));
00116                                 GetMediaSampleDescription(aMedia, 1, aDesc);
00117                                 if(GetMoviesError() == noErr)
00118                                 {
00119                                         SoundDescription& desc = **(SoundDescriptionHandle)aDesc;
00120                                         NotifyEvent(EC_BG_AUDIO_CHANGED, desc.numChannels, 0);
00121                                         i = cnt;
00122                                 }
00123                                 DisposeHandle((Handle)aDesc);
00124                         }
00125                 }
00126         }
00127 
00128         return fRet ? S_OK : E_FAIL;
00129 }
00130 
00131 // IMediaControl
00132 STDMETHODIMP CQuicktimeGraph::Run()
00133 {
00134         m_wndDestFrame.Run();
00135         return S_OK;
00136 }
00137 STDMETHODIMP CQuicktimeGraph::Pause()
00138 {       
00139         m_wndDestFrame.Pause();
00140         return S_OK;
00141 }
00142 STDMETHODIMP CQuicktimeGraph::Stop()
00143 {
00144         m_wndDestFrame.Stop();
00145         return S_OK;
00146 }
00147 STDMETHODIMP CQuicktimeGraph::GetState(LONG msTimeout, OAFilterState* pfs)
00148 {
00149         // TODO: this seems to deadlock when opening from the net
00150         return pfs ? *pfs = m_wndDestFrame.GetState(), S_OK : E_POINTER;
00151 }
00152 
00153 // IMediaSeeking
00154 STDMETHODIMP CQuicktimeGraph::GetDuration(LONGLONG* pDuration)
00155 {
00156         CheckPointer(pDuration, E_POINTER);
00157 
00158         *pDuration = 0;
00159 
00160         if(!m_wndDestFrame.theMovie) return E_UNEXPECTED;
00161 
00162         TimeScale ts = GetMovieTimeScale(m_wndDestFrame.theMovie);
00163         if(ts == 0) return E_FAIL;
00164 
00165         *pDuration = 10000i64*GetMovieDuration(m_wndDestFrame.theMovie)/ts*1000;
00166 
00167         return S_OK;
00168 }
00169 STDMETHODIMP CQuicktimeGraph::GetCurrentPosition(LONGLONG* pCurrent)
00170 {
00171         CheckPointer(pCurrent, E_POINTER);
00172 
00173         *pCurrent = 0;
00174 
00175         if(!m_wndDestFrame.theMovie) return E_UNEXPECTED;
00176 
00177         TimeScale ts = GetMovieTimeScale(m_wndDestFrame.theMovie);
00178         if(ts == 0) return E_FAIL;
00179 
00180         TimeRecord tr;
00181         *pCurrent = 10000i64*GetMovieTime(m_wndDestFrame.theMovie, &tr)/ts*1000;
00182 
00183         return S_OK;
00184 }
00185 STDMETHODIMP CQuicktimeGraph::SetPositions(LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags)
00186 {
00187         CheckPointer(pCurrent, E_POINTER);
00188 
00189         if(!(dwCurrentFlags&AM_SEEKING_AbsolutePositioning)) return E_INVALIDARG;
00190 
00191         if(!m_wndDestFrame.theMovie) return E_UNEXPECTED;
00192 
00193         TimeScale ts = GetMovieTimeScale(m_wndDestFrame.theMovie);
00194         if(ts == 0) return E_FAIL;
00195 
00196         SetMovieTimeValue(m_wndDestFrame.theMovie, (TimeValue)(*pCurrent*ts/1000/10000i64));
00197 
00198         if(!m_wndDestFrame.theMC) 
00199         {
00200                 UpdateMovie(m_wndDestFrame.theMovie);
00201                 MoviesTask(m_wndDestFrame.theMovie, 0L);
00202         }
00203 
00204         return S_OK;
00205 }
00206 STDMETHODIMP CQuicktimeGraph::SetRate(double dRate)
00207 {
00208         return m_wndDestFrame.theMovie ? SetMovieRate(m_wndDestFrame.theMovie, (Fixed)(dRate * 0x10000)), S_OK : E_UNEXPECTED;
00209 }
00210 STDMETHODIMP CQuicktimeGraph::GetRate(double* pdRate)
00211 {
00212         CheckPointer(pdRate, E_POINTER);
00213         *pdRate = 1.0;
00214         return m_wndDestFrame.theMovie ? *pdRate = (double)GetMovieRate(m_wndDestFrame.theMovie) / 0x10000, S_OK : E_UNEXPECTED;
00215 }
00216 
00217 // IVideoWindow
00218 STDMETHODIMP CQuicktimeGraph::SetWindowPosition(long Left, long Top, long Width, long Height)
00219 {
00220         if(IsWindow(m_wndWindowFrame.m_hWnd))
00221                 m_wndWindowFrame.MoveWindow(Left, Top, Width, Height);
00222 
00223         return S_OK;
00224 }
00225 
00226 // IBasicVideo
00227 STDMETHODIMP CQuicktimeGraph::SetDestinationPosition(long Left, long Top, long Width, long Height)// {return E_NOTIMPL;}
00228 {
00229         if(!m_pQTAP && IsWindow(m_wndDestFrame.m_hWnd))
00230         {
00231                 m_wndDestFrame.MoveWindow(Left, Top, Width, Height);
00232 
00233                 if(m_wndDestFrame.theMC)
00234                 {
00235                         Rect bounds = {0,0,(short)Height,(short)Width};
00236                         MCPositionController(m_wndDestFrame.theMC, &bounds, NULL, mcTopLeftMovie|mcScaleMovieToFit);
00237                 }
00238         }
00239 
00240         return S_OK;
00241 }
00242 STDMETHODIMP CQuicktimeGraph::GetVideoSize(long* pWidth, long* pHeight)
00243 {
00244         if(!pWidth || !pHeight) return E_POINTER;
00245 
00246         *pWidth = m_wndDestFrame.m_size.cx;
00247         *pHeight = m_wndDestFrame.m_size.cy;
00248 
00249         return S_OK;
00250 }
00251 
00252 // IBasicAudio
00253 STDMETHODIMP CQuicktimeGraph::put_Volume(long lVolume)
00254 {
00255         if(m_wndDestFrame.theMovie)
00256         {
00257                 lVolume = (lVolume == -10000) ? 0 : (int)pow(10.0, (double)lVolume/4152.41 + 2.41);
00258                 SetMovieVolume(m_wndDestFrame.theMovie, (short)max(min(lVolume, 256), 0));
00259                 return S_OK;
00260         }
00261 
00262         return E_UNEXPECTED;
00263 }
00264 STDMETHODIMP CQuicktimeGraph::get_Volume(long* plVolume)
00265 {
00266         CheckPointer(plVolume, E_POINTER);
00267 
00268         if(m_wndDestFrame.theMovie)
00269         {
00270                 long lVolume = (long)GetMovieVolume(m_wndDestFrame.theMovie);
00271                 *plVolume = (int)((log10(1.0*lVolume)-2.41)*4152.41);
00272                 *plVolume = max(min(*plVolume, 0), -10000);
00273                 return S_OK;
00274         }
00275 
00276         return E_UNEXPECTED;
00277 }
00278 
00279 // IVideoFrameStep
00280 STDMETHODIMP CQuicktimeGraph::Step(DWORD dwFrames, IUnknown* pStepObject)
00281 {
00282         if(pStepObject) return E_INVALIDARG;
00283         if(dwFrames == 0) return S_OK;
00284         if(!m_wndDestFrame.theMovie) return E_UNEXPECTED;
00285 
00286         // w/o m_wndDestFrame.theMC
00287 
00288         OSType myTypes[] = {VisualMediaCharacteristic};
00289         TimeValue myCurrTime = GetMovieTime(m_wndDestFrame.theMovie, NULL);
00290         Fixed theRate = (int)dwFrames > 0 ? 0x00010000 : 0xffff0000;
00291 
00292         for(int nSteps = abs((int)dwFrames); nSteps > 0; nSteps--)
00293         {
00294                 TimeValue myNextTime;
00295                 GetMovieNextInterestingTime(m_wndDestFrame.theMovie, nextTimeStep, 1, myTypes, myCurrTime, theRate, &myNextTime, NULL);
00296                 if(GetMoviesError() != noErr) return E_FAIL;
00297                 myCurrTime = myNextTime;
00298         }
00299 
00300         if(myCurrTime >= 0 && myCurrTime < GetMovieDuration(m_wndDestFrame.theMovie))
00301         {
00302         SetMovieTimeValue(m_wndDestFrame.theMovie, myCurrTime);
00303                 if(GetMoviesError() != noErr) return E_FAIL;
00304                 // the rest is not needed when we also have m_wndDestFrame.theMC:
00305                 UpdateMovie(m_wndDestFrame.theMovie);
00306                 if(GetMoviesError() != noErr) return E_FAIL;
00307                 MoviesTask(m_wndDestFrame.theMovie, 0L);
00308         }
00309 
00310         NotifyEvent(EC_STEP_COMPLETE);
00311 
00312         return S_OK;
00313 
00314 /*
00315         // w/ m_wndDestFrame.theMC
00316 
00317         short myStep = (short)(long)dwFrames;
00318         return noErr == MCDoAction(m_wndDestFrame.theMC, mcActionStep, (Ptr)myStep)
00319                 ? NotifyEvent(EC_STEP_COMPLETE), S_OK : E_FAIL;
00320 */
00321 }
00322 STDMETHODIMP CQuicktimeGraph::CanStep(long bMultiple, IUnknown* pStepObject)
00323 {
00324         return m_wndDestFrame.theMovie ? S_OK : S_FALSE;
00325 }
00326 STDMETHODIMP CQuicktimeGraph::CancelStep()
00327 {
00328         return E_NOTIMPL;
00329 }
00330 
00331 // IGraphEngine
00332 STDMETHODIMP_(engine_t) CQuicktimeGraph::GetEngine() {return QuickTime;}
00333 
00334 //
00335 // CQuicktimeWindow
00336 //
00337 
00338 CQuicktimeWindow::CQuicktimeWindow(CQuicktimeGraph* pGraph)
00339         : m_pGraph(pGraph)
00340         , theMovie(NULL)
00341         , theMC(NULL)
00342         , m_size(0, 0)
00343         , m_idEndPoller(0)
00344         , m_fs(State_Stopped)
00345         , m_offscreenGWorld(NULL)
00346 {
00347 }
00348 
00349 void CQuicktimeWindow::ProcessMovieEvent(unsigned int message, unsigned int wParam, long lParam) 
00350 {       
00351         if(message >= WM_MOUSEFIRST && message <= WM_MOUSELAST
00352         || message >= WM_KEYFIRST && message <= WM_KEYLAST)
00353                 return;
00354 
00355         // Convert the Windows event to a QTML event
00356         MSG                             theMsg;
00357         EventRecord             macEvent;
00358         LONG                    thePoints = GetMessagePos();
00359 
00360         theMsg.hwnd = m_hWnd;
00361         theMsg.message = message;
00362         theMsg.wParam = wParam;
00363         theMsg.lParam = lParam;
00364         theMsg.time = GetMessageTime();
00365         theMsg.pt.x = LOWORD(thePoints);
00366         theMsg.pt.y = HIWORD(thePoints);
00367 
00368         // tranlate a windows event to a mac event
00369         WinEventToMacEvent(&theMsg, &macEvent);
00370 
00371         // Pump messages as mac event
00372         MCIsPlayerEvent(theMC, (const EventRecord*)&macEvent);
00373 }
00374 
00375 LRESULT CQuicktimeWindow::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
00376 {
00377         if(message == WM_ERASEBKGND)
00378         {
00379                 LRESULT theResult = __super::WindowProc(message, wParam, lParam);
00380                 ProcessMovieEvent(message, wParam, lParam);     
00381                 return theResult;
00382         }
00383         else
00384         {
00385                 ProcessMovieEvent(message, wParam, lParam);
00386                 return __super::WindowProc(message, wParam, lParam);
00387         }
00388 }
00389 
00390 OSErr CQuicktimeWindow::MyMovieDrawingCompleteProc(Movie theMovie, long refCon)
00391 {
00392         CQuicktimeWindow* pQW = (CQuicktimeWindow*)refCon;
00393         if(!pQW) return noErr;
00394 
00395         CQuicktimeGraph* pGraph = pQW->m_pGraph;
00396         if(!pGraph) return noErr;
00397 
00398         if(CComQIPtr<IQTVideoSurface> pQTVS = (IUnknown*)(INonDelegatingUnknown*)pGraph)
00399         {
00400                 BITMAP bm;
00401                 pQW->m_bm.GetObject(sizeof(bm), &bm);
00402                 pQTVS->DoBlt(bm);
00403         }
00404         /*
00405         else
00406         {
00407                 pQW->Invalidate();
00408         }*/
00409 
00410         return(noErr);
00411 }
00412 
00413 bool CQuicktimeWindow::OpenMovie(CString fn)
00414 {
00415         CloseMovie();
00416 
00417         CComQIPtr<IQTVideoSurface> pQTVS = (IUnknown*)(INonDelegatingUnknown*)m_pGraph;
00418 
00419         if(!pQTVS)
00420         {
00421                 // Set the port 
00422                 SetGWorld((CGrafPtr)GetHWNDPort(m_hWnd), NULL);
00423         }
00424 
00425         if(fn.Find(_T("://")) > 0)
00426         {
00427                 Handle myHandle = NULL;
00428                 Size mySize = fn.GetLength()+1;
00429 
00430                 if(!(myHandle = NewHandleClear(mySize)))
00431                         return(false);
00432 
00433                 BlockMove((LPSTR)(LPCSTR)CStringA(fn), *myHandle, mySize);
00434 
00435         OSErr err = NewMovieFromDataRef(&theMovie, newMovieActive, NULL, myHandle, URLDataHandlerSubType);
00436 
00437                 DisposeHandle(myHandle);
00438 
00439                 if(err != noErr) return(false);
00440         }
00441         else
00442         {
00443                 if(!(fn.GetLength() > 0 && fn.GetLength() < 255))
00444                         return(false);
00445 
00446                 CHAR buff[MAX_PATH] = {0, 0};
00447 #ifdef UNICODE
00448                 WideCharToMultiByte(GetACP(), 0, fn, -1, buff+1, MAX_PATH-1, 0, 0);
00449 #else
00450                 strcpy(buff+1, fn);
00451 #endif
00452                 buff[0] = strlen(buff+1);
00453 
00454                 // Make a FSSpec with a pascal string filename
00455                 FSSpec sfFile;
00456                 FSMakeFSSpec(0, 0L, (BYTE*)buff, &sfFile);
00457 
00458                 // Open the movie file
00459                 short movieResFile;
00460                 OSErr err = OpenMovieFile(&sfFile, &movieResFile, fsRdPerm);
00461                 if(err == noErr)
00462                 {
00463                         err = NewMovieFromFile(&theMovie, movieResFile, 0, 0, newMovieActive, 0);
00464                         CloseMovieFile(movieResFile);
00465                 }
00466                 if(err != noErr) return(false);
00467         }
00468 
00469         Rect rect;
00470         GetMovieBox(theMovie, &rect);
00471         MacOffsetRect(&rect, -rect.left, -rect.top);
00472         SetMovieBox(theMovie, &rect);
00473         m_size.SetSize(rect.right - rect.left, rect.bottom - rect.top);
00474 
00475         Rect nrect;
00476         GetMovieNaturalBoundsRect(theMovie, &nrect);
00477 
00478         if(!pQTVS)
00479         {
00480                 theMC = NewMovieController(theMovie, &rect, mcTopLeftMovie|mcNotVisible);
00481         }
00482         else if(m_size.cx > 0 && m_size.cy > 0)
00483         {
00484                 SetMovieDrawingCompleteProc(theMovie, 
00485                         movieDrawingCallWhenChanged,//|movieDrawingCallAlways, 
00486                         MyMovieDrawingCompleteProc, (long)this);
00487 
00488                 if(CDC* pDC = GetDC())
00489                 {
00490                         m_dc.CreateCompatibleDC(pDC);
00491                         ReleaseDC(pDC);
00492 
00493                         struct
00494                         {   
00495                                 BITMAPINFOHEADER bmiHeader;
00496                                 long bmiColors[256];
00497                         } bmi;
00498 
00499                         memset(&bmi, 0, sizeof(bmi));
00500 
00501                         int bpp = m_dc.GetDeviceCaps(BITSPIXEL);
00502 
00503                         bmi.bmiHeader.biSize            = sizeof(BITMAPINFOHEADER);
00504                         bmi.bmiHeader.biCompression     = BI_BITFIELDS/*BI_RGB*/;
00505                         bmi.bmiHeader.biWidth           = m_size.cx;
00506                         bmi.bmiHeader.biHeight          = -m_size.cy;
00507                         bmi.bmiHeader.biPlanes          = 1;
00508                         bmi.bmiHeader.biBitCount        = 32/*bpp*/;
00509 
00510                         bmi.bmiColors[0] = /*bpp == 16 ? 0xf800 :*/ 0xff0000;
00511                         bmi.bmiColors[1] = /*bpp == 16 ? 0x07e0 :*/ 0x00ff00;
00512                         bmi.bmiColors[2] = /*bpp == 16 ? 0x001f :*/ 0x0000ff;
00513 
00514                         void* bits;
00515                         m_bm.Attach(CreateDIBSection(m_dc, (BITMAPINFO*)&bmi, DIB_RGB_COLORS, &bits, NULL, 0));
00516 
00517                         QDErr err = NewGWorldFromHBITMAP(&m_offscreenGWorld, NULL, NULL, 0, m_bm.m_hObject, m_dc.m_hDC);
00518 
00519                         SetMovieGWorld(theMovie, m_offscreenGWorld, GetGWorldDevice(m_offscreenGWorld));
00520 
00521                         BITMAP bm;
00522                         m_bm.GetObject(sizeof(bm), &bm);
00523                         pQTVS->BeginBlt(bm);
00524                 }
00525         }
00526 
00527         return(theMovie != NULL);
00528 }
00529 
00530 void CQuicktimeWindow::CloseMovie()
00531 {
00532         if(theMC) DisposeMovieController(theMC), theMC = NULL;
00533         if(theMovie) DisposeMovie(theMovie), theMovie = NULL;
00534         m_size.SetSize(0, 0);
00535         m_fs = State_Stopped;
00536 
00537         if(m_offscreenGWorld) DisposeGWorld(m_offscreenGWorld), m_offscreenGWorld = NULL;
00538         m_dc.DeleteDC();
00539         m_bm.DeleteObject();
00540 }
00541 
00542 void CQuicktimeWindow::Run()
00543 {
00544         if(theMovie)
00545         {
00546                 StartMovie(theMovie);
00547                 if(!m_idEndPoller) m_idEndPoller = SetTimer(1, 10, NULL); // 10ms -> 100fps max
00548         }
00549 
00550         m_fs = State_Running;
00551 }
00552 
00553 void CQuicktimeWindow::Pause()
00554 {
00555         if(theMovie)
00556         {
00557                 StopMovie(theMovie);
00558                 if(m_idEndPoller) KillTimer(m_idEndPoller), m_idEndPoller = 0;
00559         }
00560 
00561         m_fs = State_Paused;    
00562 }
00563 
00564 void CQuicktimeWindow::Stop()
00565 {
00566         if(theMovie)
00567         {
00568                 StopMovie(theMovie);
00569                 GoToBeginningOfMovie(theMovie);
00570                 if(m_idEndPoller) KillTimer(m_idEndPoller), m_idEndPoller = 0;
00571         }
00572 
00573         m_fs = State_Stopped;
00574 }
00575 
00576 FILTER_STATE CQuicktimeWindow::GetState()
00577 {
00578         return m_fs;
00579 }
00580 
00581 BEGIN_MESSAGE_MAP(CQuicktimeWindow, CPlayerWindow)
00582         ON_WM_CREATE()
00583         ON_WM_DESTROY()
00584         ON_WM_ERASEBKGND()
00585         ON_WM_TIMER()
00586 END_MESSAGE_MAP()
00587 
00588 int CQuicktimeWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
00589 {
00590         if(__super::OnCreate(lpCreateStruct) == -1)
00591                 return -1;
00592 
00593         CComQIPtr<IQTVideoSurface> pQTVS = (IUnknown*)(INonDelegatingUnknown*)m_pGraph;
00594 
00595         if(!pQTVS)
00596         {
00597                 // Create GrafPort <-> HWND association
00598                 CreatePortAssociation(m_hWnd, NULL, 0);
00599         }
00600 
00601         return 0;
00602 }
00603 
00604 void CQuicktimeWindow::OnDestroy()
00605 {
00606         CPlayerWindow::OnDestroy();
00607 
00608         // close any movies     before destroying PortAssocation
00609         CloseMovie();
00610 
00611         CComQIPtr<IQTVideoSurface> pQTVS = (IUnknown*)(INonDelegatingUnknown*)m_pGraph;
00612 
00613         if(!pQTVS)
00614         {
00615                 // Destroy the view's GrafPort <-> HWND association
00616                 if(m_hWnd)
00617                         if(CGrafPtr windowPort = (CGrafPtr)GetHWNDPort(m_hWnd))
00618                                 DestroyPortAssociation(windowPort);
00619         }
00620 }
00621 
00622 BOOL CQuicktimeWindow::OnEraseBkgnd(CDC* pDC)
00623 {
00624         return m_fs != State_Stopped && theMovie ? TRUE : __super::OnEraseBkgnd(pDC);
00625 }
00626 
00627 void CQuicktimeWindow::OnTimer(UINT nIDEvent)
00628 {
00629         if(nIDEvent == m_idEndPoller && theMovie)
00630         {
00631                 if(IsMovieDone(theMovie))
00632                 {
00633                         Pause();
00634                         m_pGraph->NotifyEvent(EC_COMPLETE);
00635                 }
00636                 else if(CComQIPtr<IQTVideoSurface> pQTVS = (IUnknown*)(INonDelegatingUnknown*)m_pGraph)
00637                 {
00638             MoviesTask(theMovie, 0);
00639 /*
00640                         long duration = 0, scale = 1000;
00641                         OSErr err = QTGetTimeUntilNextTask(&duration, scale);
00642 
00643                         // err is 0 but still doesn't seem to work... returns duration=0 always
00644                         TRACE(_T("%d\n"), duration);
00645                         KillTimer(m_idEndPoller);
00646                         m_idEndPoller = SetTimer(m_idEndPoller, duration, NULL);
00647 */
00648                 }
00649         }
00650 
00651         __super::OnTimer(nIDEvent);
00652 }

Generated on Tue Dec 13 14:47:03 2005 for guliverkli by  doxygen 1.4.5