📄 mediactrl.cpp
字号:
//// Volume ranges from -1.0 (gain but no sound), 0 (no sound and no gain) to// 1 (full gain and sound)//---------------------------------------------------------------------------bool wxQTMediaBackend::SetVolume(double dVolume){ ::SetMovieVolume(m_movie, (short) (dVolume * 256)); return true;}//---------------------------------------------------------------------------// wxQTMediaBackend::GetDuration//// Calls GetMovieDuration//---------------------------------------------------------------------------wxLongLong wxQTMediaBackend::GetDuration(){ return ::GetMovieDuration(m_movie);}//---------------------------------------------------------------------------// wxQTMediaBackend::GetState//// Determines the current state - the timer keeps track of whether or not// we are paused or stopped (if the timer is running we are playing)//---------------------------------------------------------------------------wxMediaState wxQTMediaBackend::GetState(){ // Could use // GetMovieActive/IsMovieDone/SetMovieActive // combo if implemented that way if (m_bPlaying) return wxMEDIASTATE_PLAYING; else if (!m_movie || wxQTMediaBackend::GetPosition() == 0) return wxMEDIASTATE_STOPPED; else return wxMEDIASTATE_PAUSED;}//---------------------------------------------------------------------------// wxQTMediaBackend::Cleanup//// Diposes of the movie timer, Control if native, and stops and disposes// of the QT movie//---------------------------------------------------------------------------void wxQTMediaBackend::Cleanup(){ m_bPlaying = false; if (m_timer) { delete m_timer; m_timer = NULL; } // Stop the movie: // Apple samples with CreateMovieControl typically // install a event handler and do this on the dispose // event, but we do it here for simplicity // (It might keep playing for several seconds after // control destruction if not) wxQTMediaBackend::Pause(); // Dispose of control or remove movie from MovieController Point thePoint; thePoint.h = thePoint.v = 0; ::MCSetVisible(m_mc, false); ::MCSetMovie(m_mc, NULL, NULL, thePoint); ::DisposeMovie(m_movie); m_movie = NULL;}//---------------------------------------------------------------------------// wxQTMediaBackend::GetVideoSize//// Returns the actual size of the QT movie//---------------------------------------------------------------------------wxSize wxQTMediaBackend::GetVideoSize() const{ return m_bestSize;}//---------------------------------------------------------------------------// wxQTMediaBackend::Move//// Move the movie controller or movie control// (we need to actually move the movie control manually...)// Top 10 things to do with quicktime in March 93's issue// of DEVELOP - very useful// http:// www.mactech.com/articles/develop/issue_13/031-033_QuickTime_column.html// OLD NOTE: Calling MCSetControllerBoundsRect without detaching// supposively resulted in a crash back then. Current code even// with CFM classic runs fine. If there is ever a problem,// take out the if 0 lines below//---------------------------------------------------------------------------void wxQTMediaBackend::Move(int x, int y, int w, int h){ if (m_timer) { m_ctrl->GetParent()->MacWindowToRootWindow(&x, &y); Rect theRect = {y, x, y + h, x + w};#if 0 // see note above ::MCSetControllerAttached(m_mc, false); wxASSERT(::GetMoviesError() == noErr);#endif ::MCSetControllerBoundsRect(m_mc, &theRect); wxASSERT(::GetMoviesError() == noErr);#if 0 // see note above if (m_interfaceflags) { ::MCSetVisible(m_mc, true); wxASSERT(::GetMoviesError() == noErr); }#endif }}//---------------------------------------------------------------------------// wxQTMediaBackend::DoSetControllerVisible//// Utility function that takes care of showing the moviecontroller// and showing/hiding the particular controls on it//---------------------------------------------------------------------------void wxQTMediaBackend::DoSetControllerVisible( wxMediaCtrlPlayerControls flags){ ::MCSetVisible(m_mc, true); // Take care of subcontrols if (::GetMoviesError() == noErr) { long mcFlags = 0; ::MCDoAction(m_mc, 39/*mcActionGetFlags*/, (void*)&mcFlags); if (::GetMoviesError() == noErr) { mcFlags |= ( //(1<<0)/*mcFlagSuppressMovieFrame*/ | (1 << 3)/*mcFlagsUseWindowPalette*/ | ((flags & wxMEDIACTRLPLAYERCONTROLS_STEP) ? 0 : (1 << 1)/*mcFlagSuppressStepButtons*/) | ((flags & wxMEDIACTRLPLAYERCONTROLS_VOLUME) ? 0 : (1 << 2)/*mcFlagSuppressSpeakerButton*/) //if we take care of repainting ourselves // | (1 << 4) /*mcFlagDontInvalidate*/ ); ::MCDoAction(m_mc, 38/*mcActionSetFlags*/, (void*)mcFlags); } } // Adjust height and width of best size for movie controller // if the user wants it shown m_bestSize.x = m_bestSize.x > wxMCWIDTH ? m_bestSize.x : wxMCWIDTH; m_bestSize.y += wxMCHEIGHT;}//---------------------------------------------------------------------------// wxQTMediaBackend::ShowPlayerControls//// Shows/Hides subcontrols on the media control//---------------------------------------------------------------------------bool wxQTMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags){ if (!m_mc) return false; // no movie controller... bool bSizeChanged = false; // if the controller is visible and we want to hide it do so if (m_interfaceflags && !flags) { bSizeChanged = true; DoLoadBestSize(); ::MCSetVisible(m_mc, false); } else if (!m_interfaceflags && flags) // show controller if hidden { bSizeChanged = true; DoSetControllerVisible(flags); } // readjust parent sizers if (bSizeChanged) { NotifyMovieSizeChanged(); // remember state in case of loading new media m_interfaceflags = flags; } return ::GetMoviesError() == noErr;}//---------------------------------------------------------------------------// wxQTMediaBackend::GetDataSizeFromStart//// Calls either GetMovieDataSize or GetMovieDataSize64 with a value// of 0 for the starting value//---------------------------------------------------------------------------wxLongLong wxQTMediaBackend::GetDataSizeFromStart(TimeValue end){#if 0 // old pre-qt4 way return ::GetMovieDataSize(m_movie, 0, end)#else // qt4 way wide llDataSize; ::GetMovieDataSize64(m_movie, 0, end, &llDataSize); return wxLongLong(llDataSize.hi, llDataSize.lo);#endif}//---------------------------------------------------------------------------// wxQTMediaBackend::GetDownloadProgress//---------------------------------------------------------------------------wxLongLong wxQTMediaBackend::GetDownloadProgress(){#if 0 // hackish and slow Handle hMovie = NewHandle(0); PutMovieIntoHandle(m_movie, hMovie); long lSize = GetHandleSize(hMovie); DisposeHandle(hMovie); return lSize;#else TimeValue tv; if (::GetMaxLoadedTimeInMovie(m_movie, &tv) != noErr) { wxLogDebug(wxT("GetMaxLoadedTimeInMovie failed")); return 0; } return wxQTMediaBackend::GetDataSizeFromStart(tv);#endif}//---------------------------------------------------------------------------// wxQTMediaBackend::GetDownloadTotal//---------------------------------------------------------------------------wxLongLong wxQTMediaBackend::GetDownloadTotal(){ return wxQTMediaBackend::GetDataSizeFromStart( ::GetMovieDuration(m_movie) );}//---------------------------------------------------------------------------// wxQTMediaBackend::MacVisibilityChanged//// The main problem here is that Windows quicktime, for example,// renders more directly to a HWND. Mac quicktime does not do this// and instead renders to the port of the WindowRef/WindowPtr on top// of everything else/all other windows.//// So, for example, if you were to have a CreateTabsControl/wxNotebook// and change pages, even if you called HIViewSetVisible/SetControlVisibility// directly the movie will still continue playing on top of everything else// if you went to a different tab.//// Note that another issue, and why we call MCSetControllerPort instead// of SetMovieGWorld directly, is that in addition to rendering on// top of everything else the last created controller steals mouse and// other input from everything else in the window, including other// controllers. Setting the port of it releases this behaviour.//---------------------------------------------------------------------------void wxQTMediaBackend::MacVisibilityChanged(){ if(!m_mc || !m_ctrl->m_bLoaded) return; //not initialized yet if(m_ctrl->MacIsReallyShown()) { //The window is being shown again, so set the GWorld of the //controller back to the port of the parent WindowRef WindowRef wrTLW = (WindowRef) m_ctrl->MacGetTopLevelWindowRef(); ::MCSetControllerPort(m_mc, (CGrafPtr) GetWindowPort(wrTLW)); wxASSERT(::GetMoviesError() == noErr); } else { //We are being hidden - set the GWorld of the controller //to the offscreen GWorld ::MCSetControllerPort(m_mc, m_movieWorld); wxASSERT(::GetMoviesError() == noErr); }}//---------------------------------------------------------------------------// wxQTMediaBackend::OnEraseBackground//// Suggestion from Greg Hazel to repaint the movie when idle// (on pause also)//---------------------------------------------------------------------------void wxQTMediaEvtHandler::OnEraseBackground(wxEraseEvent& evt){ // Work around Nasty OSX drawing bug: // http://lists.apple.com/archives/QuickTime-API/2002/Feb/msg00311.html WindowRef wrTLW = (WindowRef) m_qtb->m_ctrl->MacGetTopLevelWindowRef(); RgnHandle region = ::MCGetControllerBoundsRgn(m_qtb->m_mc); ::MCInvalidate(m_qtb->m_mc, wrTLW, region); ::MCIdle(m_qtb->m_mc);}//---------------------------------------------------------------------------// wxQTMediaBackend::PPRMProc (static)//// Called when done PrePrerolling the movie.// Note that in 99% of the cases this does nothing...// Anyway we set up the loading timer here to tell us when the movie is done//---------------------------------------------------------------------------pascal void wxQTMediaBackend::PPRMProc( Movie theMovie, OSErr WXUNUSED_UNLESS_DEBUG(theErr), void* theRefCon){ wxASSERT( theMovie ); wxASSERT( theRefCon ); wxASSERT( theErr == noErr ); wxQTMediaBackend* pBE = (wxQTMediaBackend*) theRefCon; long lTime = ::GetMovieTime(theMovie,NULL); Fixed rate = ::GetMoviePreferredRate(theMovie); ::PrerollMovie(theMovie,lTime,rate); pBE->m_timer = new wxQTMediaLoadTimer(pBE); pBE->m_timer->Start(MOVIE_DELAY);}//---------------------------------------------------------------------------// wxQTMediaBackend::MCFilterProc (static)//// Callback for when the movie controller recieves a message//---------------------------------------------------------------------------pascal Boolean wxQTMediaBackend::MCFilterProc( MovieController WXUNUSED(theController), short action, void * WXUNUSED(params), long refCon){ wxQTMediaBackend* pThis = (wxQTMediaBackend*)refCon; switch (action) { case 1: // don't process idle events break; case 8: // play button triggered - MC will set movie to opposite state // of current - playing ? paused : playing pThis->m_bPlaying = !(pThis->m_bPlaying); break; default: break; } return 0;}//---------------------------------------------------------------------------// wxQTMediaBackend::WindowEventHandler [static]//// Event callback for the top level window of our control that passes// messages to our moviecontroller so it can receive mouse clicks etc.//---------------------------------------------------------------------------pascal OSStatus wxQTMediaBackend::WindowEventHandler( EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData){ wxQTMediaBackend* be = (wxQTMediaBackend*) inUserData; // Only process keyboard messages on this window if it actually // has focus, otherwise it will steal keystrokes from other windows! // As well as when it is not loaded properly as it // will crash in MCIsPlayerEvent if((GetEventClass(inEvent) == kEventClassKeyboard && wxWindow::FindFocus() != be->m_ctrl) || !be->m_ctrl->m_bLoaded) return eventNotHandledErr; // Pass the event onto the movie controller EventRecord theEvent; ConvertEventRefToEventRecord( inEvent, &theEvent ); OSStatus err; // TODO: Apple says MCIsPlayerEvent is depreciated and // MCClick, MCKey, MCIdle etc. should be used // (RN: Of course that's what they say about // CreateMovieControl and HIMovieView as well, LOL!) err = ::MCIsPlayerEvent( be->m_mc, &theEvent ); // Pass on to other event handlers if not handled- i.e. wx if (err != noErr) return noErr; else return eventNotHandledErr;}// in source file that contains stuff you don't directly use#include "wx/html/forcelnk.h"FORCE_LINK_ME(basewxmediabackends)#endif // wxUSE_MEDIACTRL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -