]> git.saurik.com Git - wxWidgets.git/blobdiff - src/mac/carbon/mediactrl.cpp
Hopefully fixed library names generated by wx-config for OS/2's PM port.
[wxWidgets.git] / src / mac / carbon / mediactrl.cpp
index b5d21a3b83ad224a36d0c9e087adcc0f39b28754..7a1dd947f75e4c81305e231d6ab1e39a3acdfd27 100644 (file)
@@ -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
 /////////////////////////////////////////////////////////////////////////////
 
 //---------------------------------------------------------------------------
 #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
 //===========================================================================
@@ -58,7 +70,7 @@
 #include <Gestalt.h>
 #include <QuickTimeComponents.h>    //Standard QT stuff
 
-//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;
@@ -68,7 +80,7 @@ Boolean _wxIsQuickTime4Installed (void)
     return (error == noErr) && (((result >> 16) & 0xffff) >= 0x0400);
 }
 
-class wxQTMediaBackend : public wxMediaBackend
+class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackend
 {
 public:
 
@@ -106,7 +118,11 @@ public:
     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
@@ -119,8 +135,6 @@ public:
 //
 // wxQTMediaBackend
 // 
-// TODO: Use a less cludgy way to pause/get state/set state
-// TODO: Dynamically load from qtml.dll
 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend);
@@ -188,7 +202,7 @@ protected:
 };
 
 //---------------------------------------------------------------------------
-// wxQTMediaBackend Destructor
+// wxQTMediaBackend Constructor
 //
 // Sets m_timer to NULL signifying we havn't loaded anything yet
 //---------------------------------------------------------------------------
@@ -210,7 +224,7 @@ wxQTMediaBackend::~wxQTMediaBackend()
     if(m_timer)
         Cleanup();
 
-    //Note that ExitMovies() is not neccessary...
+    //Note that ExitMovies() is not necessary...
     ExitMovies();
 }
 
@@ -228,8 +242,11 @@ bool wxQTMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
                                      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 +258,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,
+    if ( !
+    
+#if wxUSE_CREATEMOVIECONTROL    
+    ctrl->wxWindow::Create(parent, id, pos, size,
+                            m_ctrl->MacRemoveBordersFromStyle(style),
+                            name)
+#else
+    ctrl->wxControl::Create(parent, id, pos, size,
                             m_ctrl->MacRemoveBordersFromStyle(style),
-                            validator, name) )
+                            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 +286,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)
 {
@@ -272,6 +298,12 @@ bool wxQTMediaBackend::Load(const wxString& fileName)
     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)
@@ -299,9 +331,15 @@ bool wxQTMediaBackend::Load(const wxString& fileName)
 }
 
 //---------------------------------------------------------------------------
-// wxQTMediaBackend::Move
+// 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)
 {
@@ -328,7 +366,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);
@@ -343,9 +381,15 @@ bool wxQTMediaBackend::Load(const wxURI& location)
 }
 
 //---------------------------------------------------------------------------
-// wxQTMediaBackend::Move
+// 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,13 +403,53 @@ 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 | 
                                 movieTrackEnabledOnly) != NULL)
     {        
+#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(
@@ -373,6 +457,7 @@ void wxQTMediaBackend::FinishLoad()
                        m_ctrl->MacGetTopLevelWindowRef()
                        ), 
                        nil);
+#endif
     }
 
     //we want millisecond precision
@@ -382,7 +467,7 @@ 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();
@@ -391,9 +476,10 @@ void wxQTMediaBackend::FinishLoad()
 }
 
 //---------------------------------------------------------------------------
-// wxQTMediaBackend::Move
+// wxQTMediaBackend::Play
 //
-// TODO
+// 1) Start the QT movie
+// 2) Start the movie loading timer
 //---------------------------------------------------------------------------
 bool wxQTMediaBackend::Play()
 {
@@ -404,9 +490,10 @@ bool wxQTMediaBackend::Play()
 }
 
 //---------------------------------------------------------------------------
-// wxQTMediaBackend::Move
+// wxQTMediaBackend::Pause
 //
-// TODO
+// 1) Stop the movie
+// 2) Stop the movie timer
 //---------------------------------------------------------------------------
 bool wxQTMediaBackend::Pause()
 {
@@ -417,9 +504,11 @@ bool wxQTMediaBackend::Pause()
 }
 
 //---------------------------------------------------------------------------
-// wxQTMediaBackend::Move
+// wxQTMediaBackend::Stop
 //
-// TODO
+// 1) Stop the movie
+// 2) Stop the movie timer
+// 3) Seek to the beginning of the movie
 //---------------------------------------------------------------------------
 bool wxQTMediaBackend::Stop()
 {
@@ -435,9 +524,9 @@ bool wxQTMediaBackend::Stop()
 }
 
 //---------------------------------------------------------------------------
-// wxQTMediaBackend::Move
+// wxQTMediaBackend::GetPlaybackRate
 //
-// TODO
+// 1) Get the movie playback rate from ::GetMovieRate
 //---------------------------------------------------------------------------
 double wxQTMediaBackend::GetPlaybackRate()
 {
@@ -445,9 +534,9 @@ double wxQTMediaBackend::GetPlaybackRate()
 }
 
 //---------------------------------------------------------------------------
-// wxQTMediaBackend::Move
+// wxQTMediaBackend::SetPlaybackRate
 //
-// TODO
+// 1) Convert dRate to Fixed and Set the movie rate through SetMovieRate
 //---------------------------------------------------------------------------
 bool wxQTMediaBackend::SetPlaybackRate(double dRate)
 {
@@ -456,9 +545,10 @@ bool wxQTMediaBackend::SetPlaybackRate(double dRate)
 }
 
 //---------------------------------------------------------------------------
-// wxQTMediaBackend::Move
+// wxQTMediaBackend::SetPosition
 //
-// TODO
+// 1) Create a time record struct (TimeRecord) with appropriate values
+// 2) Pass struct to SetMovieTime
 //---------------------------------------------------------------------------
 bool wxQTMediaBackend::SetPosition(wxLongLong where)
 {
@@ -476,9 +566,9 @@ bool wxQTMediaBackend::SetPosition(wxLongLong where)
 }
 
 //---------------------------------------------------------------------------
-// wxQTMediaBackend::Move
+// wxQTMediaBackend::GetPosition
 //
-// TODO
+// Calls GetMovieTime
 //---------------------------------------------------------------------------
 wxLongLong wxQTMediaBackend::GetPosition()
 {
@@ -486,9 +576,9 @@ wxLongLong wxQTMediaBackend::GetPosition()
 }
 
 //---------------------------------------------------------------------------
-// wxQTMediaBackend::Move
+// wxQTMediaBackend::GetDuration
 //
-// TODO
+// Calls GetMovieDuration
 //---------------------------------------------------------------------------
 wxLongLong wxQTMediaBackend::GetDuration()
 {
@@ -496,9 +586,10 @@ wxLongLong wxQTMediaBackend::GetDuration()
 }
 
 //---------------------------------------------------------------------------
-// wxQTMediaBackend::Move
+// 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()
 {
@@ -513,23 +604,28 @@ wxMediaState wxQTMediaBackend::GetState()
 }
 
 //---------------------------------------------------------------------------
-// wxQTMediaBackend::Move
+// 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);
 }
 
 //---------------------------------------------------------------------------
-// wxQTMediaBackend::Move
+// wxQTMediaBackend::GetVideoSize
 //
-// TODO
+// Returns the actual size of the QT movie
 //---------------------------------------------------------------------------
 wxSize wxQTMediaBackend::GetVideoSize() const
 {
@@ -539,22 +635,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 <wx/html/forcelnk.h>
+#include "wx/html/forcelnk.h"
 FORCE_LINK_ME(basewxmediabackends);
 
 #endif //wxUSE_MEDIACTRL