1 /////////////////////////////////////////////////////////////////////////////
2 // Name: mac/cocoa/mediactrl.cpp
3 // Purpose: Built-in Media Backends for Cocoa
4 // Author: Ryan Norton <wxprojects@comcast.net>
8 // Copyright: (c) 2004-2005 Ryan Norton, (c) 2005 David Elliot
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 //===========================================================================
14 //===========================================================================
16 //---------------------------------------------------------------------------
17 // Pre-compiled header stuff
18 //---------------------------------------------------------------------------
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "mediactrl.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
31 //---------------------------------------------------------------------------
33 //---------------------------------------------------------------------------
34 #include "wx/mediactrl.h"
36 //---------------------------------------------------------------------------
38 //---------------------------------------------------------------------------
41 //===========================================================================
42 // BACKEND DECLARATIONS
43 //===========================================================================
45 //---------------------------------------------------------------------------
49 //---------------------------------------------------------------------------
51 //---------------------------------------------------------------------------
53 //---------------------------------------------------------------------------
54 #include <QuickTime/QuickTime.h>
56 #include "wx/cocoa/autorelease.h"
57 #include "wx/cocoa/string.h"
59 #import <AppKit/NSMovie.h>
60 #import <AppKit/NSMovieView.h>
63 class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackend
70 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
75 const wxValidator& validator,
76 const wxString& name);
82 virtual bool Load(const wxString& fileName);
83 virtual bool Load(const wxURI& location);
85 virtual wxMediaState GetState();
87 virtual bool SetPosition(wxLongLong where);
88 virtual wxLongLong GetPosition();
89 virtual wxLongLong GetDuration();
91 virtual void Move(int x, int y, int w, int h);
92 wxSize GetVideoSize() const;
94 virtual double GetPlaybackRate();
95 virtual bool SetPlaybackRate(double dRate);
100 wxSize m_bestSize; //Original movie size
101 Movie m_movie; //QT Movie handle/instance
102 NSMovieView* m_movieview; //NSMovieView instance
103 wxControl* m_ctrl; //Parent control
104 bool m_bVideo; //Whether or not we have video
106 DECLARE_DYNAMIC_CLASS(wxQTMediaBackend);
110 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
114 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
116 IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend);
118 //---------------------------------------------------------------------------
119 // wxQTMediaBackend Constructor
121 // Sets m_timer to NULL signifying we havn't loaded anything yet
122 //---------------------------------------------------------------------------
123 wxQTMediaBackend::wxQTMediaBackend()
127 //---------------------------------------------------------------------------
128 // wxQTMediaBackend Destructor
130 // 1) Cleans up the QuickTime movie instance
131 // 2) Decrements the QuickTime reference counter - if this reaches
132 // 0, QuickTime shuts down
133 // 3) Decrements the QuickTime Windows Media Layer reference counter -
134 // if this reaches 0, QuickTime shuts down the Windows Media Layer
135 //---------------------------------------------------------------------------
136 wxQTMediaBackend::~wxQTMediaBackend()
140 //Note that ExitMovies() is not neccessary...
144 //---------------------------------------------------------------------------
145 // wxQTMediaBackend::CreateControl
147 // 1) Intializes QuickTime
148 // 2) Creates the control window
149 //---------------------------------------------------------------------------
150 bool wxQTMediaBackend::CreateControl(wxControl* inctrl, wxWindow* parent,
155 const wxValidator& validator,
156 const wxString& name)
160 wxMediaCtrl* ctrl = (wxMediaCtrl*) inctrl;
162 //Create the control base
163 wxASSERT(ctrl->CreateBase(parent,wid,pos,size,style, validator, name));
165 //Create the NSMovieView
166 ctrl->SetNSView(NULL);
167 NSMovieView* theView = [[NSMovieView alloc] initWithFrame: ctrl->MakeDefaultNSRect(size)];
168 ctrl->SetNSView(theView);
173 parent->AddChild(ctrl);
174 parent->CocoaAddChild(ctrl);
175 ctrl->SetInitialFrameRect(pos,size);
178 [theView showController:false adjustingSize:true];
179 m_movieview = theView;
184 //---------------------------------------------------------------------------
185 // wxQTMediaBackend::Load (file version)
187 // Calls the URI version
188 //---------------------------------------------------------------------------
189 bool wxQTMediaBackend::Load(const wxString& fileName)
193 wxString( wxT("file://") ) + fileName
198 //---------------------------------------------------------------------------
199 // wxQTMediaBackend::Load (URL Version)
201 // 1) Build an escaped URI from location
203 //---------------------------------------------------------------------------
204 bool wxQTMediaBackend::Load(const wxURI& location)
208 wxString theURI = location.BuildURI();
210 [m_movieview setMovie:[[NSMovie alloc] initWithURL: [NSURL URLWithString: wxNSStringWithWxString(theURI)]
211 byReference: YES ] ];
213 m_movie = (Movie) [[m_movieview movie] QTMovie];
217 return ::GetMoviesError() == noErr;
220 //---------------------------------------------------------------------------
221 // wxQTMediaBackend::FinishLoad
222 //---------------------------------------------------------------------------
223 void wxQTMediaBackend::FinishLoad()
225 //get the real size of the movie
227 ::GetMovieNaturalBoundsRect (m_movie, &outRect);
228 wxASSERT(::GetMoviesError() == noErr);
230 m_bestSize.x = outRect.right - outRect.left;
231 m_bestSize.y = outRect.bottom - outRect.top;
233 //we want millisecond precision
234 ::SetMovieTimeScale(m_movie, 1000);
235 wxASSERT(::GetMoviesError() == noErr);
238 //Here, if the parent of the control has a sizer - we
239 //tell it to recalculate the size of this control since
240 //the user opened a seperate media file
242 m_ctrl->InvalidateBestSize();
243 m_ctrl->GetParent()->Layout();
244 m_ctrl->GetParent()->Refresh();
245 m_ctrl->GetParent()->Update();
248 //---------------------------------------------------------------------------
249 // wxQTMediaBackend::Play
251 // 1) Start the QT movie
252 // 2) Start the movie loading timer
253 //---------------------------------------------------------------------------
254 bool wxQTMediaBackend::Play()
256 [m_movieview start:NULL];
257 return ::GetMoviesError() == noErr;
260 //---------------------------------------------------------------------------
261 // wxQTMediaBackend::Pause
264 // 2) Stop the movie timer
265 //---------------------------------------------------------------------------
266 bool wxQTMediaBackend::Pause()
268 [m_movieview stop:NULL];
269 return ::GetMoviesError() == noErr;
272 //---------------------------------------------------------------------------
273 // wxQTMediaBackend::Stop
276 // 2) Stop the movie timer
277 // 3) Seek to the beginning of the movie
278 //---------------------------------------------------------------------------
279 bool wxQTMediaBackend::Stop()
281 [m_movieview stop:NULL];
282 [m_movieview gotoBeginning:NULL];
283 return ::GetMoviesError() == noErr;
286 //---------------------------------------------------------------------------
287 // wxQTMediaBackend::GetPlaybackRate
289 // 1) Get the movie playback rate from ::GetMovieRate
290 //---------------------------------------------------------------------------
291 double wxQTMediaBackend::GetPlaybackRate()
293 return ( ((double)::GetMovieRate(m_movie)) / 0x10000);
296 //---------------------------------------------------------------------------
297 // wxQTMediaBackend::SetPlaybackRate
299 // 1) Convert dRate to Fixed and Set the movie rate through SetMovieRate
300 //---------------------------------------------------------------------------
301 bool wxQTMediaBackend::SetPlaybackRate(double dRate)
303 ::SetMovieRate(m_movie, (Fixed) (dRate * 0x10000));
304 return ::GetMoviesError() == noErr;
307 //---------------------------------------------------------------------------
308 // wxQTMediaBackend::SetPosition
310 // 1) Create a time record struct (TimeRecord) with appropriate values
311 // 2) Pass struct to SetMovieTime
312 //---------------------------------------------------------------------------
313 bool wxQTMediaBackend::SetPosition(wxLongLong where)
315 TimeRecord theTimeRecord;
316 memset(&theTimeRecord, 0, sizeof(TimeRecord));
317 theTimeRecord.value.lo = where.GetValue();
318 theTimeRecord.scale = ::GetMovieTimeScale(m_movie);
319 theTimeRecord.base = ::GetMovieTimeBase(m_movie);
320 ::SetMovieTime(m_movie, &theTimeRecord);
322 if (::GetMoviesError() != noErr)
328 //---------------------------------------------------------------------------
329 // wxQTMediaBackend::GetPosition
331 // Calls GetMovieTime
332 //---------------------------------------------------------------------------
333 wxLongLong wxQTMediaBackend::GetPosition()
335 return ::GetMovieTime(m_movie, NULL);
338 //---------------------------------------------------------------------------
339 // wxQTMediaBackend::GetDuration
341 // Calls GetMovieDuration
342 //---------------------------------------------------------------------------
343 wxLongLong wxQTMediaBackend::GetDuration()
345 return ::GetMovieDuration(m_movie);
348 //---------------------------------------------------------------------------
349 // wxQTMediaBackend::GetState
351 // Determines the current state - the timer keeps track of whether or not
352 // we are paused or stopped (if the timer is running we are playing)
353 //---------------------------------------------------------------------------
354 wxMediaState wxQTMediaBackend::GetState()
356 if ( [m_movieview isPlaying] )
357 return wxMEDIASTATE_PLAYING;
359 if( wxQTMediaBackend::GetPosition() == 0 )
360 return wxMEDIASTATE_STOPPED;
362 return wxMEDIASTATE_PAUSED;
365 //---------------------------------------------------------------------------
366 // wxQTMediaBackend::Cleanup
368 // Diposes of the movie timer, Control if native, and stops and disposes
370 //---------------------------------------------------------------------------
371 void wxQTMediaBackend::Cleanup()
373 if([m_movieview movie])
375 [[m_movieview movie] release];
376 [m_movieview setMovie:NULL];
380 //---------------------------------------------------------------------------
381 // wxQTMediaBackend::GetVideoSize
383 // Returns the actual size of the QT movie
384 //---------------------------------------------------------------------------
385 wxSize wxQTMediaBackend::GetVideoSize() const
390 //---------------------------------------------------------------------------
391 // wxQTMediaBackend::Move
393 // Nothin... cocoa takes care of this for us
394 //---------------------------------------------------------------------------
395 void wxQTMediaBackend::Move(int x, int y, int w, int h)
400 //in source file that contains stuff you don't directly use
401 #include <wx/html/forcelnk.h>
402 FORCE_LINK_ME(basewxmediabackends);
404 #endif //wxUSE_MEDIACTRL