📄 mediactrl.cpp
字号:
/////////////////////////////////////////////////////////////////////////////// Name: src/mac/carbon/mediactrl.cpp// Purpose: Built-in Media Backends for Mac// Author: Ryan Norton <wxprojects@comcast.net>// Modified by:// Created: 11/07/04// RCS-ID: $Id: mediactrl.cpp,v 1.31 2006/11/08 22:26:44 KO Exp $// Copyright: (c) 2004-2006 Ryan Norton// Licence: wxWindows licence///////////////////////////////////////////////////////////////////////////////%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%// OK, a casual overseer of this file may wonder why we don't use// either CreateMovieControl or HIMovieView...//// CreateMovieControl// 1) Need to dispose and create each time a new movie is loaded// 2) Not that many real advantages// 3) Progressively buggier in higher OSX versions// (see main.c of QTCarbonShell sample for details)// HIMovieView// 1) Crashes on destruction in ALL cases on quite a few systems!// (With the only real "alternative" is to simply not// dispose of it and let it leak...)// 2) Massive refreshing bugs with its movie controller between// movies//// At one point we had a complete implementation for CreateMovieControl// and on my (RN) local copy I had one for HIMovieView - but they// were simply deemed to be too buggy/unuseful. HIMovieView could// have been useful as well because it uses OpenGL contexts instead// of GWorlds. Perhaps someday when someone comes out with some// ingenious workarounds :).//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%// For compilers that support precompilation, includes "wx.h".#include "wx/wxprec.h"#if wxUSE_MEDIACTRL#include "wx/mediactrl.h"#ifndef WX_PRECOMP #include "wx/log.h" #include "wx/timer.h"#endif// uma is for wxMacFSSpec#include "wx/mac/uma.h"// standard QT stuff#ifndef __DARWIN__#include <Movies.h>#include <Gestalt.h>#include <QuickTimeComponents.h>#else#include <QuickTime/QuickTimeComponents.h>#endif//---------------------------------------------------------------------------// Height and Width of movie controller in the movie control (apple samples)//---------------------------------------------------------------------------#define wxMCWIDTH 320#define wxMCHEIGHT 16//===========================================================================// BACKEND DECLARATIONS//===========================================================================//---------------------------------------------------------------------------// wxQTMediaBackend//---------------------------------------------------------------------------class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackendCommonBase{public: wxQTMediaBackend(); virtual ~wxQTMediaBackend(); virtual bool CreateControl(wxControl* ctrl, wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator, const wxString& name); virtual bool Load(const wxString& fileName); virtual bool Load(const wxURI& location); virtual bool Play(); virtual bool Pause(); virtual bool Stop(); virtual wxMediaState GetState(); virtual bool SetPosition(wxLongLong where); virtual wxLongLong GetPosition(); virtual wxLongLong GetDuration(); virtual void Move(int x, int y, int w, int h); wxSize GetVideoSize() const; virtual double GetPlaybackRate(); virtual bool SetPlaybackRate(double dRate); virtual double GetVolume(); virtual bool SetVolume(double); void Cleanup(); void FinishLoad(); virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags); virtual wxLongLong GetDownloadProgress(); virtual wxLongLong GetDownloadTotal(); virtual void MacVisibilityChanged(); // // ------ Implementation from now on -------- // bool DoPause(); bool DoStop(); void DoLoadBestSize(); void DoSetControllerVisible(wxMediaCtrlPlayerControls flags); wxLongLong GetDataSizeFromStart(TimeValue end); Boolean IsQuickTime4Installed(); void DoNewMovieController(); static pascal void PPRMProc( Movie theMovie, OSErr theErr, void* theRefCon); //TODO: Last param actually long - does this work on 64bit machines? static pascal Boolean MCFilterProc(MovieController theController, short action, void *params, long refCon); static pascal OSStatus WindowEventHandler( EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData ); wxSize m_bestSize; // Original movie size Movie m_movie; // Movie instance bool m_bPlaying; // Whether media is playing or not class wxTimer* m_timer; // Timer for streaming the movie MovieController m_mc; // MovieController instance wxMediaCtrlPlayerControls m_interfaceflags; // Saved interface flags // Event handlers and UPPs/Callbacks EventHandlerRef m_windowEventHandler; EventHandlerUPP m_windowUPP; MoviePrePrerollCompleteUPP m_preprerollupp; MCActionFilterWithRefConUPP m_mcactionupp; GWorldPtr m_movieWorld; //Offscreen movie GWorld friend class wxQTMediaEvtHandler; DECLARE_DYNAMIC_CLASS(wxQTMediaBackend)};// helper to hijack background erasing for the QT windowclass WXDLLIMPEXP_MEDIA wxQTMediaEvtHandler : public wxEvtHandler{public: wxQTMediaEvtHandler(wxQTMediaBackend *qtb) { m_qtb = qtb; qtb->m_ctrl->Connect( qtb->m_ctrl->GetId(), wxEVT_ERASE_BACKGROUND, wxEraseEventHandler(wxQTMediaEvtHandler::OnEraseBackground), NULL, this); } void OnEraseBackground(wxEraseEvent& event);private: wxQTMediaBackend *m_qtb; DECLARE_NO_COPY_CLASS(wxQTMediaEvtHandler)};//===========================================================================// IMPLEMENTATION//===========================================================================//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//// wxQTMediaBackend////+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend)//Time between timer calls - this is the Apple recommondation to the TCL//team I believe#define MOVIE_DELAY 20//---------------------------------------------------------------------------// wxQTMediaLoadTimer//// QT, esp. QT for Windows is very picky about how you go about// async loading. If you were to go through a Windows message loop// or a MoviesTask or both and then check the movie load state// it would still return 1000 (loading)... even (pre)prerolling doesn't// help. However, making a load timer like this works//---------------------------------------------------------------------------class wxQTMediaLoadTimer : public wxTimer{public: wxQTMediaLoadTimer(wxQTMediaBackend* parent) : m_parent(parent) {} void Notify() { ::MCIdle(m_parent->m_mc); // kMovieLoadStatePlayable is not enough on MAC: // it plays, but IsMovieDone might return true (!) // sure we need to wait until kMovieLoadStatePlaythroughOK if (::GetMovieLoadState(m_parent->m_movie) >= 20000) { m_parent->FinishLoad(); delete this; } }protected: wxQTMediaBackend *m_parent; // Backend pointer};// --------------------------------------------------------------------------// wxQTMediaPlayTimer - Handle Asyncronous Playing//// 1) Checks to see if the movie is done, and if not continues// streaming the movie// 2) Sends the wxEVT_MEDIA_STOP event if we have reached the end of// the movie.// --------------------------------------------------------------------------class wxQTMediaPlayTimer : public wxTimer{public: wxQTMediaPlayTimer(wxQTMediaBackend* parent) : m_parent(parent) {} void Notify() { // // OK, a little explaining - basically originally // we only called MoviesTask if the movie was actually // playing (not paused or stopped)... this was before // we realized MoviesTask actually handles repainting // of the current frame - so if you were to resize // or something it would previously not redraw that // portion of the movie. // // So now we call MoviesTask always so that it repaints // correctly. // ::MCIdle(m_parent->m_mc); // // Handle the stop event - if the movie has reached // the end, notify our handler // if (::IsMovieDone(m_parent->m_movie)) { if ( m_parent->SendStopEvent() ) { m_parent->Stop(); wxASSERT(::GetMoviesError() == noErr); m_parent->QueueFinishEvent(); } } }protected: wxQTMediaBackend* m_parent; // Backend pointer};//---------------------------------------------------------------------------// wxQTMediaBackend Constructor//// Sets m_timer to NULL signifying we havn't loaded anything yet//---------------------------------------------------------------------------wxQTMediaBackend::wxQTMediaBackend() : m_movie(NULL), m_bPlaying(false), m_timer(NULL) , m_mc(NULL), m_interfaceflags(wxMEDIACTRLPLAYERCONTROLS_NONE) , m_preprerollupp(NULL), m_movieWorld(NULL){}//---------------------------------------------------------------------------// wxQTMediaBackend Destructor//// 1) Cleans up the QuickTime movie instance// 2) Decrements the QuickTime reference counter - if this reaches// 0, QuickTime shuts down// 3) Decrements the QuickTime Windows Media Layer reference counter -// if this reaches 0, QuickTime shuts down the Windows Media Layer//---------------------------------------------------------------------------wxQTMediaBackend::~wxQTMediaBackend(){ if (m_movie) Cleanup(); // Cleanup for moviecontroller if (m_mc) { // destroy wxQTMediaEvtHandler we pushed on it m_ctrl->PopEventHandler(true); RemoveEventHandler(m_windowEventHandler); DisposeEventHandlerUPP(m_windowUPP); // Dispose of the movie controller ::DisposeMovieController(m_mc); m_mc = NULL; // Dispose of offscreen GWorld ::DisposeGWorld(m_movieWorld); } // Note that ExitMovies() is not necessary... ExitMovies();}//---------------------------------------------------------------------------// wxQTMediaBackend::CreateControl//// 1) Intializes QuickTime// 2) Creates the control window//---------------------------------------------------------------------------bool wxQTMediaBackend::CreateControl( wxControl* ctrl, wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator, const wxString& name){ if (!IsQuickTime4Installed()) return false; EnterMovies(); wxMediaCtrl* mediactrl = (wxMediaCtrl*)ctrl; // // Create window // By default wxWindow(s) is created with a border - // so we need to get rid of those // // Since we don't have a child window like most other // backends, we don't need wxCLIP_CHILDREN // if ( !mediactrl->wxControl::Create( parent, id, pos, size, wxWindow::MacRemoveBordersFromStyle(style), validator, name)) { return false; }#if wxUSE_VALIDATORS mediactrl->SetValidator(validator);#endif m_ctrl = mediactrl; return true;}//---------------------------------------------------------------------------// wxQTMediaBackend::IsQuickTime4Installed//// Determines whether version 4 of QT is installed// (Pretty much for Classic only)//---------------------------------------------------------------------------Boolean wxQTMediaBackend::IsQuickTime4Installed(){ OSErr error; long result; error = Gestalt(gestaltQuickTime, &result); return (error == noErr) && (((result >> 16) & 0xffff) >= 0x0400);}//---------------------------------------------------------------------------// wxQTMediaBackend::Load (file version)//// 1) Get an FSSpec from the Windows path name// 2) Open the movie// 3) Obtain the movie instance from the movie resource// 4) Close the movie resource// 5) Finish loading//---------------------------------------------------------------------------bool wxQTMediaBackend::Load(const wxString& fileName){ if (m_movie) Cleanup(); ::ClearMoviesStickyError(); // clear previous errors so // GetMoviesStickyError is useful
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -