1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/cocoa/mediactrl.cpp
3 // Purpose: Built-in Media Backends for Cocoa
4 // Author: Ryan Norton <wxprojects@comcast.net>
7 // RCS-ID: $Id: mediactrl.mm 39285 2006-05-23 11:04:37Z ABX $
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 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
27 //---------------------------------------------------------------------------
29 //---------------------------------------------------------------------------
32 #include "wx/mediactrl.h"
38 #include "wx/osx/private.h"
40 //===========================================================================
41 // BACKEND DECLARATIONS
42 //===========================================================================
44 //---------------------------------------------------------------------------
48 //---------------------------------------------------------------------------
50 //---------------------------------------------------------------------------
52 //---------------------------------------------------------------------------
53 #include <QTKit/QTKit.h>
55 #include "wx/cocoa/autorelease.h"
56 #include "wx/cocoa/string.h"
58 #import <AppKit/NSMovie.h>
59 #import <AppKit/NSMovieView.h>
62 class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackend
69 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
74 const wxValidator& validator,
75 const wxString& name);
81 virtual bool Load(const wxString& fileName);
82 virtual bool Load(const wxURI& location);
84 virtual wxMediaState GetState();
86 virtual bool SetPosition(wxLongLong where);
87 virtual wxLongLong GetPosition();
88 virtual wxLongLong GetDuration();
90 virtual void Move(int x, int y, int w, int h);
91 wxSize GetVideoSize() const;
93 virtual double GetPlaybackRate();
94 virtual bool SetPlaybackRate(double dRate);
96 virtual double GetVolume();
97 virtual bool SetVolume(double dVolume);
102 virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags);
104 void DoShowPlayerControls(wxMediaCtrlPlayerControls flags);
106 wxSize m_bestSize; //Original movie size
107 QTMovie* m_movie; //QTMovie handle/instance
108 QTMovieView* m_movieview; //QTMovieView instance
109 wxControl* m_ctrl; //Parent control
111 wxMediaCtrlPlayerControls m_interfaceflags; // Saved interface flags
113 DECLARE_DYNAMIC_CLASS(wxQTMediaBackend);
117 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
121 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
123 IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend);
125 //Time between timer calls
126 #define MOVIE_DELAY 100
128 // --------------------------------------------------------------------------
129 // wxQTTimer - Handle Asyncronous Playing
130 // --------------------------------------------------------------------------
131 class _wxQTTimer : public wxTimer
134 _wxQTTimer(QTMovie movie, wxQTMediaBackend* parent) :
135 m_movie(movie), m_bPaused(false), m_parent(parent)
143 bool GetPaused() {return m_bPaused;}
144 void SetPaused(bool bPaused) {m_bPaused = bPaused;}
146 //-----------------------------------------------------------------------
147 // _wxQTTimer::Notify
149 // 1) Checks to see if the movie is done, and if not continues
150 // streaming the movie
151 // 2) Sends the wxEVT_MEDIA_STOP event if we have reached the end of
153 //-----------------------------------------------------------------------
159 if(!IsMovieDone(m_movie))
160 MoviesTask(m_movie, MOVIE_DELAY);
163 wxMediaEvent theEvent(wxEVT_MEDIA_STOP,
164 m_parent->m_ctrl->GetId());
165 m_parent->m_ctrl->GetEventHandler()->ProcessEvent(theEvent);
167 if(theEvent.IsAllowed())
171 wxASSERT(::GetMoviesError() == noErr);
173 //send the event to our child
174 wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED,
175 m_parent->m_ctrl->GetId());
176 m_parent->m_ctrl->GetEventHandler()->ProcessEvent(theEvent);
184 QTMovie m_movie; //Our movie instance
185 bool m_bPaused; //Whether we are paused or not
186 wxQTMediaBackend* m_parent; //Backend pointer
189 //---------------------------------------------------------------------------
190 // wxQTMediaBackend Constructor
192 // Sets m_timer to NULL signifying we havn't loaded anything yet
193 //---------------------------------------------------------------------------
194 wxQTMediaBackend::wxQTMediaBackend() :
195 m_interfaceflags(wxMEDIACTRLPLAYERCONTROLS_NONE),
196 m_movie(nil), m_movieview(nil), m_ctrl(NULL)
200 //---------------------------------------------------------------------------
201 // wxQTMediaBackend Destructor
203 // 1) Cleans up the QuickTime movie instance
204 // 2) Decrements the QuickTime reference counter - if this reaches
205 // 0, QuickTime shuts down
206 // 3) Decrements the QuickTime Windows Media Layer reference counter -
207 // if this reaches 0, QuickTime shuts down the Windows Media Layer
208 //---------------------------------------------------------------------------
209 wxQTMediaBackend::~wxQTMediaBackend()
214 //---------------------------------------------------------------------------
215 // wxQTMediaBackend::CreateControl
217 // 1) Intializes QuickTime
218 // 2) Creates the control window
219 //---------------------------------------------------------------------------
220 bool wxQTMediaBackend::CreateControl(wxControl* inctrl, wxWindow* parent,
225 const wxValidator& validator,
226 const wxString& name)
228 wxMediaCtrl* mediactrl = (wxMediaCtrl*) inctrl;
232 // By default wxWindow(s) is created with a border -
233 // so we need to get rid of those
235 // Since we don't have a child window like most other
236 // backends, we don't need wxCLIP_CHILDREN
238 if ( !mediactrl->wxControl::Create(
239 parent, wid, pos, size,
240 wxWindow::MacRemoveBordersFromStyle(style),
246 NSRect r = wxOSXGetFrameForControl( mediactrl, pos , size ) ;
247 QTMovieView* theView = [[QTMovieView alloc] initWithFrame: r];
249 wxWidgetCocoaImpl* impl = new wxWidgetCocoaImpl(mediactrl,theView);
250 mediactrl->SetPeer(impl);
252 m_movieview = theView;
253 // will be set up after load
254 [theView setControllerVisible:NO];
260 bool wxQTMediaBackend::Load(const wxString& fileName)
264 wxString( wxT("file://") ) + fileName
269 bool wxQTMediaBackend::Load(const wxURI& location)
271 wxString theURI = location.BuildURI();
273 QTMovie* movie = [[QTMovie alloc] initWithURL: [NSURL URLWithString: wxNSStringWithWxString(theURI)] error: nil ];
278 [m_movieview setMovie:movie];
280 DoShowPlayerControls(m_interfaceflags);
287 void wxQTMediaBackend::FinishLoad()
289 NSRect r =[m_movieview movieBounds];
290 m_bestSize.x = r.size.width;
291 m_bestSize.y = r.size.height;
293 m_ctrl->InvalidateBestSize();
294 m_ctrl->GetParent()->Layout();
295 m_ctrl->GetParent()->Refresh();
296 m_ctrl->GetParent()->Update();
299 bool wxQTMediaBackend::Play()
301 [m_movieview play:nil];
305 bool wxQTMediaBackend::Pause()
307 [m_movieview pause:nil];
311 bool wxQTMediaBackend::Stop()
313 [m_movieview pause:nil];
314 [m_movieview gotoBeginning:nil];
318 double wxQTMediaBackend::GetVolume()
320 return [m_movie volume];
323 bool wxQTMediaBackend::SetVolume(double dVolume)
325 [m_movie setVolume:dVolume];
328 double wxQTMediaBackend::GetPlaybackRate()
330 return [m_movie rate];
333 bool wxQTMediaBackend::SetPlaybackRate(double dRate)
335 [m_movie setRate:dRate];
339 bool wxQTMediaBackend::SetPosition(wxLongLong where)
342 position = [m_movie currentTime];
343 position.timeValue = (where.GetValue() / 1000.0) * position.timeScale;
344 [m_movie setCurrentTime:position];
348 wxLongLong wxQTMediaBackend::GetPosition()
350 QTTime position = [m_movie currentTime];
351 return ((double) position.timeValue) / position.timeScale * 1000;
354 wxLongLong wxQTMediaBackend::GetDuration()
356 QTTime duration = [m_movie duration];
357 return ((double) duration.timeValue) / duration.timeScale * 1000;
360 wxMediaState wxQTMediaBackend::GetState()
363 if ( !m_timer || (m_timer->IsRunning() == false &&
364 m_timer->GetPaused() == false) )
365 return wxMEDIASTATE_STOPPED;
367 if( m_timer->IsRunning() == true )
368 return wxMEDIASTATE_PLAYING;
371 return wxMEDIASTATE_PAUSED;
374 void wxQTMediaBackend::Cleanup()
376 [[m_movieview movie] release];
377 [m_movieview setMovie:NULL];
380 wxSize wxQTMediaBackend::GetVideoSize() const
385 void wxQTMediaBackend::Move(int x, int y, int w, int h)
389 bool wxQTMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
391 if ( m_interfaceflags != flags )
392 DoShowPlayerControls(flags);
394 m_interfaceflags = flags;
398 void wxQTMediaBackend::DoShowPlayerControls(wxMediaCtrlPlayerControls flags)
400 if (flags == wxMEDIACTRLPLAYERCONTROLS_NONE )
402 [m_movieview setControllerVisible:NO];
406 [m_movieview setStepButtonsVisible:(flags & wxMEDIACTRLPLAYERCONTROLS_STEP) ? YES:NO];
407 [m_movieview setVolumeButtonVisible:(flags & wxMEDIACTRLPLAYERCONTROLS_VOLUME) ? YES:NO];
411 //in source file that contains stuff you don't directly use
412 #include "wx/html/forcelnk.h"
413 FORCE_LINK_ME(basewxmediabackends);
415 #endif //wxUSE_MEDIACTRL