📄 mediactrl.cpp
字号:
OSErr err = noErr; short movieResFile; FSSpec sfFile; wxMacFilename2FSSpec( fileName, &sfFile ); if (OpenMovieFile( &sfFile, &movieResFile, fsRdPerm ) != noErr) return false; short movieResID = 0; Str255 movieName; err = NewMovieFromFile( &m_movie, movieResFile, &movieResID, movieName, newMovieActive, NULL); // wasChanged // Do not use ::GetMoviesStickyError() here because it returns -2009 // a.k.a. invalid track on valid mpegs if (err == noErr && ::GetMoviesError() == noErr) { ::CloseMovieFile(movieResFile); // Create movie controller/control DoNewMovieController(); FinishLoad(); return true; } return false;}//---------------------------------------------------------------------------// wxQTMediaBackend::Load (URL Version)//// 1) Build an escaped URI from location// 2) Create a handle to store the URI string// 3) Put the URI string inside the handle// 4) Make a QuickTime URL data ref from the handle with the URI in it// 5) Clean up the URI string handle// 6) Do some prerolling// 7) Finish Loading//---------------------------------------------------------------------------bool wxQTMediaBackend::Load(const wxURI& location){ if (m_movie) Cleanup(); ::ClearMoviesStickyError(); // clear previous errors so // GetMoviesStickyError is useful wxString theURI = location.BuildURI(); OSErr err; size_t len; const char* theURIString;#if wxUSE_UNICODE wxCharBuffer buf = wxConvLocal.cWC2MB(theURI, theURI.length(), &len); theURIString = buf;#else theURIString = theURI; len = theURI.length();#endif Handle theHandle = ::NewHandleClear(len + 1); wxASSERT(theHandle); ::BlockMoveData(theURIString, *theHandle, len + 1); // create the movie from the handle that refers to the URI err = ::NewMovieFromDataRef( &m_movie, newMovieActive | newMovieAsyncOK /* | newMovieIdleImportOK*/, NULL, theHandle, URLDataHandlerSubType); ::DisposeHandle(theHandle); if (err == noErr && ::GetMoviesStickyError() == noErr) { // Movie controller resets prerolling, so we must create first DoNewMovieController(); long timeNow; Fixed playRate; timeNow = ::GetMovieTime(m_movie, NULL); wxASSERT(::GetMoviesError() == noErr); playRate = ::GetMoviePreferredRate(m_movie); wxASSERT(::GetMoviesError() == noErr); // // Note that the callback here is optional, // but without it PrePrerollMovie can be buggy // (see Apple ml). Also, some may wonder // why we need this at all - this is because // Apple docs say QuickTime streamed movies // require it if you don't use a Movie Controller, // which we don't by default. // m_preprerollupp = wxQTMediaBackend::PPRMProc; ::PrePrerollMovie( m_movie, timeNow, playRate, m_preprerollupp, (void*)this); return true; } return false;}//---------------------------------------------------------------------------// wxQTMediaBackend::DoNewMovieController//// Attaches movie to moviecontroller or creates moviecontroller// if not created yet//---------------------------------------------------------------------------void wxQTMediaBackend::DoNewMovieController(){ if (!m_mc) { // Get top level window ref for some mac functions WindowRef wrTLW = (WindowRef) m_ctrl->MacGetTopLevelWindowRef(); // MovieController not set up yet, so we need to create a new one. // You have to pass a valid movie to NewMovieController, evidently ::SetMovieGWorld(m_movie, (CGrafPtr) GetWindowPort(wrTLW), NULL); wxASSERT(::GetMoviesError() == noErr); Rect bounds = wxMacGetBoundsForControl( m_ctrl, m_ctrl->GetPosition(), m_ctrl->GetSize()); m_mc = ::NewMovieController( m_movie, &bounds, mcTopLeftMovie | mcNotVisible /* | mcWithFrame */ ); wxASSERT(::GetMoviesError() == noErr); ::MCDoAction(m_mc, 32, (void*)true); // mcActionSetKeysEnabled wxASSERT(::GetMoviesError() == noErr); // Setup a callback so we can tell when the user presses // play on the player controls m_mcactionupp = wxQTMediaBackend::MCFilterProc; ::MCSetActionFilterWithRefCon( m_mc, m_mcactionupp, (long)this ); wxASSERT(::GetMoviesError() == noErr); // Part of a suggestion from Greg Hazel to repaint movie when idle m_ctrl->PushEventHandler(new wxQTMediaEvtHandler(this)); // Create offscreen GWorld for where to "show" when window is hidden Rect worldRect; worldRect.left = worldRect.top = 0; worldRect.right = worldRect.bottom = 1; ::NewGWorld(&m_movieWorld, 0, &worldRect, NULL, NULL, 0); // Catch window messages: // if we do not do this and if the user clicks the play // button on the controller, for instance, nothing will happen... EventTypeSpec theWindowEventTypes[] = { { kEventClassMouse, kEventMouseDown }, { kEventClassMouse, kEventMouseUp }, { kEventClassMouse, kEventMouseDragged }, { kEventClassKeyboard, kEventRawKeyDown }, { kEventClassKeyboard, kEventRawKeyRepeat }, { kEventClassKeyboard, kEventRawKeyUp }, { kEventClassWindow, kEventWindowUpdate }, { kEventClassWindow, kEventWindowActivated }, { kEventClassWindow, kEventWindowDeactivated } }; m_windowUPP = NewEventHandlerUPP( wxQTMediaBackend::WindowEventHandler ); InstallWindowEventHandler( wrTLW, m_windowUPP, GetEventTypeCount( theWindowEventTypes ), theWindowEventTypes, this, &m_windowEventHandler ); } else { // MovieController already created: // Just change the movie in it and we're good to go Point thePoint; thePoint.h = thePoint.v = 0; ::MCSetMovie(m_mc, m_movie, (WindowRef)m_ctrl->MacGetTopLevelWindowRef(), thePoint); wxASSERT(::GetMoviesError() == noErr); }}//---------------------------------------------------------------------------// wxQTMediaBackend::FinishLoad//// Performs operations after a movie ready to play/loaded.//---------------------------------------------------------------------------void wxQTMediaBackend::FinishLoad(){ // get the real size of the movie DoLoadBestSize(); // show the player controls if the user wants to if (m_interfaceflags) DoSetControllerVisible(m_interfaceflags); // we want millisecond precision ::SetMovieTimeScale(m_movie, 1000); wxASSERT(::GetMoviesError() == noErr); // start movie progress timer m_timer = new wxQTMediaPlayTimer(this); wxASSERT(m_timer); m_timer->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS); // send loaded event and refresh size NotifyMovieLoaded();}//---------------------------------------------------------------------------// wxQTMediaBackend::DoLoadBestSize//// Sets the best size of the control from the real size of the movie//---------------------------------------------------------------------------void wxQTMediaBackend::DoLoadBestSize(){ // get the real size of the movie Rect outRect; ::GetMovieNaturalBoundsRect(m_movie, &outRect); wxASSERT(::GetMoviesError() == noErr); // determine best size m_bestSize.x = outRect.right - outRect.left; m_bestSize.y = outRect.bottom - outRect.top;}//---------------------------------------------------------------------------// wxQTMediaBackend::Play//// Start the QT movie// (Apple recommends mcActionPrerollAndPlay but that's QT 4.1+)//---------------------------------------------------------------------------bool wxQTMediaBackend::Play(){ Fixed fixRate = (Fixed) (wxQTMediaBackend::GetPlaybackRate() * 0x10000); if (!fixRate) fixRate = ::GetMoviePreferredRate(m_movie); wxASSERT(fixRate != 0); if (!m_bPlaying) ::MCDoAction( m_mc, 8 /* mcActionPlay */, (void*) fixRate); bool result = (::GetMoviesError() == noErr); if (result) { m_bPlaying = true; QueuePlayEvent(); } return result;}//---------------------------------------------------------------------------// wxQTMediaBackend::Pause//// Stop the movie//---------------------------------------------------------------------------bool wxQTMediaBackend::DoPause(){ // Stop the movie A.K.A. ::StopMovie(m_movie); if (m_bPlaying) { ::MCDoAction( m_mc, 8 /*mcActionPlay*/, (void *) 0); m_bPlaying = false; return ::GetMoviesError() == noErr; } // already paused return true;}bool wxQTMediaBackend::Pause(){ bool bSuccess = DoPause(); if (bSuccess) this->QueuePauseEvent(); return bSuccess;}//---------------------------------------------------------------------------// wxQTMediaBackend::Stop//// 1) Stop the movie// 2) Seek to the beginning of the movie//---------------------------------------------------------------------------bool wxQTMediaBackend::DoStop(){ if (!wxQTMediaBackend::DoPause()) return false; ::GoToBeginningOfMovie(m_movie); return ::GetMoviesError() == noErr;}bool wxQTMediaBackend::Stop(){ bool bSuccess = DoStop(); if (bSuccess) QueueStopEvent(); return bSuccess;}//---------------------------------------------------------------------------// wxQTMediaBackend::GetPlaybackRate//// 1) Get the movie playback rate from ::GetMovieRate//---------------------------------------------------------------------------double wxQTMediaBackend::GetPlaybackRate(){ return ( ((double)::GetMovieRate(m_movie)) / 0x10000);}//---------------------------------------------------------------------------// wxQTMediaBackend::SetPlaybackRate//// 1) Convert dRate to Fixed and Set the movie rate through SetMovieRate//---------------------------------------------------------------------------bool wxQTMediaBackend::SetPlaybackRate(double dRate){ ::SetMovieRate(m_movie, (Fixed) (dRate * 0x10000)); return ::GetMoviesError() == noErr;}//---------------------------------------------------------------------------// wxQTMediaBackend::SetPosition//// 1) Create a time record struct (TimeRecord) with appropriate values// 2) Pass struct to SetMovieTime//---------------------------------------------------------------------------bool wxQTMediaBackend::SetPosition(wxLongLong where){ TimeRecord theTimeRecord; memset(&theTimeRecord, 0, sizeof(TimeRecord)); theTimeRecord.value.lo = where.GetValue(); theTimeRecord.scale = ::GetMovieTimeScale(m_movie); theTimeRecord.base = ::GetMovieTimeBase(m_movie); ::SetMovieTime(m_movie, &theTimeRecord); if (::GetMoviesError() != noErr) return false; return true;}//---------------------------------------------------------------------------// wxQTMediaBackend::GetPosition//// Calls GetMovieTime//---------------------------------------------------------------------------wxLongLong wxQTMediaBackend::GetPosition(){ return ::GetMovieTime(m_movie, NULL);}//---------------------------------------------------------------------------// wxQTMediaBackend::GetVolume//// Gets the volume through GetMovieVolume - which returns a 16 bit short -//// +--------+--------+// + (1) + (2) +// +--------+--------+//// (1) first 8 bits are value before decimal// (2) second 8 bits are value after decimal//// Volume ranges from -1.0 (gain but no sound), 0 (no sound and no gain) to// 1 (full gain and sound)//---------------------------------------------------------------------------double wxQTMediaBackend::GetVolume(){ short sVolume = ::GetMovieVolume(m_movie); if (sVolume & (128 << 8)) //negative - no sound return 0.0; return sVolume / 256.0;}//---------------------------------------------------------------------------// wxQTMediaBackend::SetVolume//// Sets the volume through SetMovieVolume - which takes a 16 bit short -//// +--------+--------+// + (1) + (2) +// +--------+--------+//// (1) first 8 bits are value before decimal// (2) second 8 bits are value after decimal
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -