X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e7b97da356f09e625a8aa526c5c41b3e00cf8202..101b4778087e78ba64e7dd700ea4b01b9c272f5b:/src/mac/carbon/mediactrl.cpp diff --git a/src/mac/carbon/mediactrl.cpp b/src/mac/carbon/mediactrl.cpp index e63626cbf8..d2eb4c053f 100644 --- a/src/mac/carbon/mediactrl.cpp +++ b/src/mac/carbon/mediactrl.cpp @@ -5,7 +5,7 @@ // Modified by: // Created: 11/07/04 // RCS-ID: $Id$ -// Copyright: (c) Ryan Norton +// Copyright: (c) 2004-2005 Ryan Norton, portions (c) 2004 Kevin Olliver // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -38,6 +38,18 @@ //--------------------------------------------------------------------------- #if wxUSE_MEDIACTRL +//--------------------------------------------------------------------------- +// Whether or not to use OSX 10.2's CreateMovieControl for native QuickTime +// control - i.e. native positioning and event handling etc.. +//--------------------------------------------------------------------------- +#ifndef wxUSE_CREATEMOVIECONTROL +# if defined( __WXMAC_OSX__ ) && ( MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_2 ) +# define wxUSE_CREATEMOVIECONTROL 1 +# else +# define wxUSE_CREATEMOVIECONTROL 0 +# endif +#endif + //=========================================================================== // BACKEND DECLARATIONS //=========================================================================== @@ -54,11 +66,15 @@ //uma is for wxMacFSSpec #include "wx/mac/uma.h" #include "wx/timer.h" +#ifndef __DARWIN__ #include #include #include //Standard QT stuff +#else +#include +#endif -//Determines whether version 6 of QT is installed +//Determines whether version 4 of QT is installed (Pretty much for classic only) Boolean _wxIsQuickTime4Installed (void) { short error; @@ -75,11 +91,11 @@ public: wxQTMediaBackend(); ~wxQTMediaBackend(); - virtual bool CreateControl(wxControl* ctrl, wxWindow* parent, + virtual bool CreateControl(wxControl* ctrl, wxWindow* parent, wxWindowID id, - const wxPoint& pos, + const wxPoint& pos, const wxSize& size, - long style, + long style, const wxValidator& validator, const wxString& name); @@ -102,25 +118,30 @@ public: virtual double GetPlaybackRate(); virtual bool SetPlaybackRate(double dRate); + virtual double GetVolume(); + virtual bool SetVolume(double); + void Cleanup(); void FinishLoad(); wxSize m_bestSize; //Original movie size +#ifdef __WXMAC_OSX__ struct MovieType** m_movie; //QT Movie handle/instance +#else + Movie m_movie ; +#endif wxControl* m_ctrl; //Parent control bool m_bVideo; //Whether or not we have video class _wxQTTimer* m_timer; //Timer for streaming the movie - DECLARE_DYNAMIC_CLASS(wxQTMediaBackend); + DECLARE_DYNAMIC_CLASS(wxQTMediaBackend) }; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // wxQTMediaBackend -// -// TODO: Use a less cludgy way to pause/get state/set state -// TODO: Dynamically load from qtml.dll +// //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend); @@ -159,10 +180,10 @@ public: if (!m_bPaused) { if(!IsMovieDone(m_movie)) - MoviesTask(m_movie, MOVIE_DELAY); + MoviesTask(m_movie, MOVIE_DELAY); else { - wxMediaEvent theEvent(wxEVT_MEDIA_STOP, + wxMediaEvent theEvent(wxEVT_MEDIA_STOP, m_parent->m_ctrl->GetId()); m_parent->m_ctrl->ProcessEvent(theEvent); @@ -173,7 +194,7 @@ public: wxASSERT(::GetMoviesError() == noErr); //send the event to our child - wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED, + wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED, m_parent->m_ctrl->GetId()); m_parent->m_ctrl->ProcessEvent(theEvent); } @@ -210,7 +231,7 @@ wxQTMediaBackend::~wxQTMediaBackend() if(m_timer) Cleanup(); - //Note that ExitMovies() is not neccessary... + //Note that ExitMovies() is not necessary... ExitMovies(); } @@ -220,16 +241,19 @@ wxQTMediaBackend::~wxQTMediaBackend() // 1) Intializes QuickTime // 2) Creates the control window //--------------------------------------------------------------------------- -bool wxQTMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent, +bool wxQTMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent, wxWindowID id, - const wxPoint& pos, + const wxPoint& pos, const wxSize& size, - long style, + long style, const wxValidator& validator, const wxString& name) { + //Don't bother in Native control mode +#if defined( __WXMAC__ ) && TARGET_API_MAC_OSX && ( MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_2 ) if (!_wxIsQuickTime4Installed()) return false; +#endif EnterMovies(); @@ -241,15 +265,23 @@ bool wxQTMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent, // Since we don't have a child window like most other // backends, we don't need wxCLIP_CHILDREN // - if ( !ctrl->wxControl::Create(parent, id, pos, size, - m_ctrl->MacRemoveBordersFromStyle(style), - validator, name) ) + if ( ! + +#if wxUSE_CREATEMOVIECONTROL + ctrl->wxWindow::Create(parent, id, pos, size, + wxWindow::MacRemoveBordersFromStyle(style), + name) +#else + ctrl->wxControl::Create(parent, id, pos, size, + wxWindow::MacRemoveBordersFromStyle(style), + validator, name) +#endif + ) return false; - // - //Set our background color to black by default - // - ctrl->SetBackgroundColour(*wxBLACK); +#if wxUSE_VALIDATORS + ctrl->SetValidator(validator); +#endif m_ctrl = ctrl; return true; @@ -261,7 +293,8 @@ bool wxQTMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent, // 1) Get an FSSpec from the Windows path name // 2) Open the movie // 3) Obtain the movie instance from the movie resource -// 4) +// 4) Close the movie resource +// 5) Finish loading //--------------------------------------------------------------------------- bool wxQTMediaBackend::Load(const wxString& fileName) { @@ -271,9 +304,15 @@ bool wxQTMediaBackend::Load(const wxString& fileName) OSErr err = noErr; short movieResFile; FSSpec sfFile; - + + //FIXME:wxMacFilename2FSSpec crashes on empty string - + //does it crash on other strings too and should this + //"fix" be put in the carbon wxSound? + if (fileName.empty()) + return false; + wxMacFilename2FSSpec( fileName , &sfFile ); - + if (OpenMovieFile (&sfFile, &movieResFile, fsRdPerm) != noErr) return false; @@ -299,9 +338,15 @@ bool wxQTMediaBackend::Load(const wxString& fileName) } //--------------------------------------------------------------------------- -// wxQTMediaBackend::Load +// wxQTMediaBackend::Load (URL Version) // -// TODO +// 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) { @@ -318,8 +363,8 @@ bool wxQTMediaBackend::Load(const wxURI& location) BlockMove(theURI.mb_str(), *theHandle, theURI.length() + 1); //create the movie from the handle that refers to the URI - err = NewMovieFromDataRef(&m_movie, newMovieActive, - NULL, theHandle, + err = NewMovieFromDataRef(&m_movie, newMovieActive, + NULL, theHandle, URLDataHandlerSubType); DisposeHandle(theHandle); @@ -328,7 +373,7 @@ bool wxQTMediaBackend::Load(const wxURI& location) return false; //preroll movie for streaming - //TODO:Async this? + //TODO:Async this using threads? TimeValue timeNow; Fixed playRate; timeNow = GetMovieTime(m_movie, NULL); @@ -345,7 +390,13 @@ bool wxQTMediaBackend::Load(const wxURI& location) //--------------------------------------------------------------------------- // wxQTMediaBackend::FinishLoad // -// TODO +// 1) Create the movie timer +// 2) Get real size of movie for GetBestSize/sizers +// 3) See if there is video in the movie, and if so then either +// SetMovieGWorld if < 10.2 or use Native CreateMovieControl +// 4) Set the movie time scale to something usable so that seeking +// etc. will work correctly +// 5) Refresh parent window //--------------------------------------------------------------------------- void wxQTMediaBackend::FinishLoad() { @@ -359,20 +410,61 @@ void wxQTMediaBackend::FinishLoad() m_bestSize.x = outRect.right - outRect.left; m_bestSize.y = outRect.bottom - outRect.top; - + //reparent movie/*AudioMediaCharacteristic*/ - if(GetMovieIndTrackType(m_movie, 1, - VisualMediaCharacteristic, - movieTrackCharacteristic | + if(GetMovieIndTrackType(m_movie, 1, + VisualMediaCharacteristic, + movieTrackCharacteristic | movieTrackEnabledOnly) != NULL) - { - SetMovieGWorld(m_movie, - (CGrafPtr) + { +#if wxUSE_CREATEMOVIECONTROL + // + //Native CreateMovieControl QT control (Thanks to Kevin Olliver's + //wxQTMovie for some of this). + // + #define GetControlPeer(whatever) ctrl->m_peer + wxMediaCtrl* ctrl = (wxMediaCtrl*) m_ctrl; + Rect bounds = wxMacGetBoundsForControl(m_ctrl, + m_ctrl->GetPosition(), + m_ctrl->GetSize()); + + //Dispose of old control for new one + if (GetControlPeer(m_ctrl) && GetControlPeer(m_ctrl)->Ok() ) + GetControlPeer(m_ctrl)->Dispose(); + + //Options- + //kMovieControlOptionXXX + //HideController - hide the movie controller + //LocateTopLeft - movie is pinned to top left rather than centered in the control + //EnableEditing - Allows programmatic editing and dragn'drop + //HandleEditingHI- Installs event stuff for edit menu - forces EnableEditing also + //SetKeysEnabled - Allows keyboard input + //ManuallyIdled - app handles movie idling rather than internal timer event loop + ::CreateMovieControl( + (WindowRef) + ctrl->MacGetTopLevelWindowRef(), //parent + &bounds, //control bounds + m_movie, //movie handle + kMovieControlOptionHideController + | kMovieControlOptionLocateTopLeft + | kMovieControlOptionSetKeysEnabled +// | kMovieControlOptionManuallyIdled + , //flags + ctrl->m_peer->GetControlRefAddr() ); + + ::EmbedControl(ctrl->m_peer->GetControlRef(), (ControlRef)ctrl->GetParent()->GetHandle()); +#else + // + //"Emulation" + // + SetMovieGWorld(m_movie, + (CGrafPtr) GetWindowPort( (WindowRef) m_ctrl->MacGetTopLevelWindowRef() - ), + ), nil); +#endif } //we want millisecond precision @@ -382,18 +474,24 @@ void wxQTMediaBackend::FinishLoad() // //Here, if the parent of the control has a sizer - we //tell it to recalculate the size of this control since - //the user opened a seperate media file + //the user opened a separate media file // m_ctrl->InvalidateBestSize(); m_ctrl->GetParent()->Layout(); m_ctrl->GetParent()->Refresh(); m_ctrl->GetParent()->Update(); + + //send loaded event + wxMediaEvent theEvent(wxEVT_MEDIA_LOADED, + m_ctrl->GetId()); + m_ctrl->AddPendingEvent(theEvent); } //--------------------------------------------------------------------------- // wxQTMediaBackend::Play // -// TODO +// 1) Start the QT movie +// 2) Start the movie loading timer //--------------------------------------------------------------------------- bool wxQTMediaBackend::Play() { @@ -406,7 +504,8 @@ bool wxQTMediaBackend::Play() //--------------------------------------------------------------------------- // wxQTMediaBackend::Pause // -// TODO +// 1) Stop the movie +// 2) Stop the movie timer //--------------------------------------------------------------------------- bool wxQTMediaBackend::Pause() { @@ -419,7 +518,9 @@ bool wxQTMediaBackend::Pause() //--------------------------------------------------------------------------- // wxQTMediaBackend::Stop // -// TODO +// 1) Stop the movie +// 2) Stop the movie timer +// 3) Seek to the beginning of the movie //--------------------------------------------------------------------------- bool wxQTMediaBackend::Stop() { @@ -429,7 +530,7 @@ bool wxQTMediaBackend::Stop() ::StopMovie(m_movie); if(::GetMoviesError() != noErr) return false; - + ::GoToBeginningOfMovie(m_movie); return ::GetMoviesError() == noErr; } @@ -437,7 +538,7 @@ bool wxQTMediaBackend::Stop() //--------------------------------------------------------------------------- // wxQTMediaBackend::GetPlaybackRate // -// TODO +// 1) Get the movie playback rate from ::GetMovieRate //--------------------------------------------------------------------------- double wxQTMediaBackend::GetPlaybackRate() { @@ -447,7 +548,7 @@ double wxQTMediaBackend::GetPlaybackRate() //--------------------------------------------------------------------------- // wxQTMediaBackend::SetPlaybackRate // -// TODO +// 1) Convert dRate to Fixed and Set the movie rate through SetMovieRate //--------------------------------------------------------------------------- bool wxQTMediaBackend::SetPlaybackRate(double dRate) { @@ -458,7 +559,8 @@ bool wxQTMediaBackend::SetPlaybackRate(double dRate) //--------------------------------------------------------------------------- // wxQTMediaBackend::SetPosition // -// TODO +// 1) Create a time record struct (TimeRecord) with appropriate values +// 2) Pass struct to SetMovieTime //--------------------------------------------------------------------------- bool wxQTMediaBackend::SetPosition(wxLongLong where) { @@ -478,7 +580,7 @@ bool wxQTMediaBackend::SetPosition(wxLongLong where) //--------------------------------------------------------------------------- // wxQTMediaBackend::GetPosition // -// TODO +// Calls GetMovieTime //--------------------------------------------------------------------------- wxLongLong wxQTMediaBackend::GetPosition() { @@ -486,9 +588,56 @@ wxLongLong wxQTMediaBackend::GetPosition() } //--------------------------------------------------------------------------- +// 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 & (127 << 8)) ? 1.0 : ((double)(sVolume & 255)) / 255.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 +// +// 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) +{ + short sVolume = (short) (dVolume >= .9999 ? 1 << 8 : (dVolume * 255) ); + SetMovieVolume(m_movie, sVolume); + return true; +} + + //--------------------------------------------------------------------------- // wxQTMediaBackend::GetDuration // -// TODO +// Calls GetMovieDuration //--------------------------------------------------------------------------- wxLongLong wxQTMediaBackend::GetDuration() { @@ -498,15 +647,16 @@ wxLongLong wxQTMediaBackend::GetDuration() //--------------------------------------------------------------------------- // wxQTMediaBackend::GetState // -// TODO +// 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() { - if ( !m_timer || (m_timer->IsRunning() == false && + if ( !m_timer || (m_timer->IsRunning() == false && m_timer->GetPaused() == false) ) return wxMEDIASTATE_STOPPED; - if( m_timer->IsRunning() == true ) + if( m_timer->IsRunning() ) return wxMEDIASTATE_PLAYING; else return wxMEDIASTATE_PAUSED; @@ -515,13 +665,18 @@ wxMediaState wxQTMediaBackend::GetState() //--------------------------------------------------------------------------- // wxQTMediaBackend::Cleanup // -// TODO +// Diposes of the movie timer, Control if native, and stops and disposes +// of the QT movie //--------------------------------------------------------------------------- void wxQTMediaBackend::Cleanup() { delete m_timer; m_timer = NULL; +#if wxUSE_CREATEMOVIECONTROL + DisposeControl(((wxMediaCtrl*)m_ctrl)->m_peer->GetControlRef()); +#endif + StopMovie(m_movie); DisposeMovie(m_movie); } @@ -529,7 +684,7 @@ void wxQTMediaBackend::Cleanup() //--------------------------------------------------------------------------- // wxQTMediaBackend::GetVideoSize // -// TODO +// Returns the actual size of the QT movie //--------------------------------------------------------------------------- wxSize wxQTMediaBackend::GetVideoSize() const { @@ -539,32 +694,39 @@ wxSize wxQTMediaBackend::GetVideoSize() const //--------------------------------------------------------------------------- // wxQTMediaBackend::Move // -// TODO +// We need to do this even when using native qt control because +// CreateMovieControl is broken in this regard... //--------------------------------------------------------------------------- void wxQTMediaBackend::Move(int x, int y, int w, int h) { +#if !wxUSE_CREATEMOVIECONTROL if(m_timer) { if ( m_ctrl ) { m_ctrl->GetParent()->MacWindowToRootWindow(&x, &y); } - + Rect theRect = {y, x, y+h, x+w}; ::SetMovieBox(m_movie, &theRect); wxASSERT(::GetMoviesError() == noErr); } +#else + if(m_timer && m_ctrl) + { + m_ctrl->GetParent()->MacWindowToRootWindow(&x, &y); + + ::MoveControl( (ControlRef) m_ctrl->GetHandle(), x, y ); + m_ctrl->GetParent()->Refresh(); + m_ctrl->GetParent()->Update(); + } +#endif } //in source file that contains stuff you don't directly use -#include +#include "wx/html/forcelnk.h" FORCE_LINK_ME(basewxmediabackends); #endif //wxUSE_MEDIACTRL - - - - -