make cocoa mediactrl usable. Some touchups to carbon mediactrl code. Add notebook...
[wxWidgets.git] / src / cocoa / mediactrl.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        mac/cocoa/mediactrl.cpp
3 // Purpose:     Built-in Media Backends for Cocoa
4 // Author:      Ryan Norton <wxprojects@comcast.net>
5 // Modified by:
6 // Created:     02/03/05
7 // RCS-ID:      $Id$
8 // Copyright:   (c) 2004-2005 Ryan Norton, (c) 2005 David Elliot
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 //===========================================================================
13 //  DECLARATIONS
14 //===========================================================================
15
16 //---------------------------------------------------------------------------
17 // Pre-compiled header stuff
18 //---------------------------------------------------------------------------
19
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "mediactrl.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 //---------------------------------------------------------------------------
32 // Includes
33 //---------------------------------------------------------------------------
34 #include "wx/mediactrl.h"
35
36 //---------------------------------------------------------------------------
37 // Compilation guard
38 //---------------------------------------------------------------------------
39 #if wxUSE_MEDIACTRL
40
41 //===========================================================================
42 //  BACKEND DECLARATIONS
43 //===========================================================================
44
45 //---------------------------------------------------------------------------
46 //
47 //  wxQTMediaBackend
48 //
49 //---------------------------------------------------------------------------
50
51 //---------------------------------------------------------------------------
52 //  QT Includes
53 //---------------------------------------------------------------------------
54 #include <QuickTime/QuickTime.h>
55
56 #include "wx/cocoa/autorelease.h"
57 #include "wx/cocoa/string.h"
58
59 #import <AppKit/NSMovie.h>
60 #import <AppKit/NSMovieView.h>
61
62
63 class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackend
64 {
65 public:
66
67     wxQTMediaBackend();
68     ~wxQTMediaBackend();
69
70     virtual bool CreateControl(wxControl* ctrl, wxWindow* parent, 
71                                      wxWindowID id,
72                                      const wxPoint& pos, 
73                                      const wxSize& size,
74                                      long style, 
75                                      const wxValidator& validator,
76                                      const wxString& name);
77
78     virtual bool Play();
79     virtual bool Pause();
80     virtual bool Stop();
81
82     virtual bool Load(const wxString& fileName);
83     virtual bool Load(const wxURI& location);
84
85     virtual wxMediaState GetState();
86
87     virtual bool SetPosition(wxLongLong where);
88     virtual wxLongLong GetPosition();
89     virtual wxLongLong GetDuration();
90
91     virtual void Move(int x, int y, int w, int h);
92     wxSize GetVideoSize() const;
93
94     virtual double GetPlaybackRate();
95     virtual bool SetPlaybackRate(double dRate);
96
97     void Cleanup();
98     void FinishLoad();
99
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
105
106     DECLARE_DYNAMIC_CLASS(wxQTMediaBackend);
107 };
108
109
110 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
111 //
112 // wxQTMediaBackend
113 // 
114 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
115
116 IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend);
117
118 //---------------------------------------------------------------------------
119 // wxQTMediaBackend Constructor
120 //
121 // Sets m_timer to NULL signifying we havn't loaded anything yet
122 //---------------------------------------------------------------------------
123 wxQTMediaBackend::wxQTMediaBackend()
124 {
125 }
126
127 //---------------------------------------------------------------------------
128 // wxQTMediaBackend Destructor
129 //
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()
137 {
138     Cleanup();
139
140     //Note that ExitMovies() is not neccessary...
141     ::ExitMovies();
142 }
143
144 //---------------------------------------------------------------------------
145 // wxQTMediaBackend::CreateControl
146 //
147 // 1) Intializes QuickTime
148 // 2) Creates the control window
149 //---------------------------------------------------------------------------
150 bool wxQTMediaBackend::CreateControl(wxControl* inctrl, wxWindow* parent, 
151                                      wxWindowID wid,
152                                      const wxPoint& pos, 
153                                      const wxSize& size,
154                                      long style, 
155                                      const wxValidator& validator,
156                                      const wxString& name)
157 {
158     EnterMovies();
159     
160     wxMediaCtrl* ctrl = (wxMediaCtrl*) inctrl;
161
162     //Create the control base
163     wxASSERT(ctrl->CreateBase(parent,wid,pos,size,style, validator, name));
164     
165     //Create the NSMovieView
166     ctrl->SetNSView(NULL);
167     NSMovieView* theView = [[NSMovieView alloc] initWithFrame: ctrl->MakeDefaultNSRect(size)];
168     ctrl->SetNSView(theView);
169     [theView release];
170
171     if (parent)
172     {
173         parent->AddChild(ctrl);
174         parent->CocoaAddChild(ctrl);
175         ctrl->SetInitialFrameRect(pos,size);
176     }
177     
178     [theView showController:false adjustingSize:true];
179     m_movieview = theView;
180     m_ctrl = ctrl;
181     return true;
182 }
183
184 //---------------------------------------------------------------------------
185 // wxQTMediaBackend::Load (file version)
186 //
187 // Calls the URI version
188 //---------------------------------------------------------------------------
189 bool wxQTMediaBackend::Load(const wxString& fileName)
190 {
191     return Load(
192                 wxURI(
193                     wxString( wxT("file://") ) + fileName 
194                      )
195                );
196 }
197
198 //---------------------------------------------------------------------------
199 // wxQTMediaBackend::Load (URL Version)
200 //
201 // 1) Build an escaped URI from location
202 // ...
203 //---------------------------------------------------------------------------
204 bool wxQTMediaBackend::Load(const wxURI& location)
205 {
206     Cleanup();
207
208     wxString theURI = location.BuildURI();
209
210     [m_movieview setMovie:[[NSMovie alloc] initWithURL: [NSURL URLWithString: wxNSStringWithWxString(theURI)]
211                                byReference: YES ] ];
212
213     m_movie = (Movie) [[m_movieview movie] QTMovie];
214
215     FinishLoad();
216
217     return ::GetMoviesError() == noErr;
218 }
219
220 //---------------------------------------------------------------------------
221 // wxQTMediaBackend::FinishLoad
222 //---------------------------------------------------------------------------
223 void wxQTMediaBackend::FinishLoad()
224 {
225     //get the real size of the movie
226     Rect outRect;
227     ::GetMovieNaturalBoundsRect (m_movie, &outRect);
228     wxASSERT(::GetMoviesError() == noErr);
229
230     m_bestSize.x = outRect.right - outRect.left;
231     m_bestSize.y = outRect.bottom - outRect.top;
232
233     //we want millisecond precision
234     ::SetMovieTimeScale(m_movie, 1000);
235     wxASSERT(::GetMoviesError() == noErr);
236
237     //
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
241     //
242     m_ctrl->InvalidateBestSize();
243     m_ctrl->GetParent()->Layout();
244     m_ctrl->GetParent()->Refresh();
245     m_ctrl->GetParent()->Update();
246 }
247
248 //---------------------------------------------------------------------------
249 // wxQTMediaBackend::Play
250 //
251 // 1) Start the QT movie
252 // 2) Start the movie loading timer
253 //---------------------------------------------------------------------------
254 bool wxQTMediaBackend::Play()
255 {
256     [m_movieview start:NULL];
257     return ::GetMoviesError() == noErr;
258 }
259
260 //---------------------------------------------------------------------------
261 // wxQTMediaBackend::Pause
262 //
263 // 1) Stop the movie
264 // 2) Stop the movie timer
265 //---------------------------------------------------------------------------
266 bool wxQTMediaBackend::Pause()
267 {
268     [m_movieview stop:NULL];
269     return ::GetMoviesError() == noErr;
270 }
271
272 //---------------------------------------------------------------------------
273 // wxQTMediaBackend::Stop
274 //
275 // 1) Stop the movie
276 // 2) Stop the movie timer
277 // 3) Seek to the beginning of the movie
278 //---------------------------------------------------------------------------
279 bool wxQTMediaBackend::Stop()
280 {
281     [m_movieview stop:NULL];
282     [m_movieview gotoBeginning:NULL];
283     return ::GetMoviesError() == noErr;
284 }
285
286 //---------------------------------------------------------------------------
287 // wxQTMediaBackend::GetPlaybackRate
288 //
289 // 1) Get the movie playback rate from ::GetMovieRate
290 //---------------------------------------------------------------------------
291 double wxQTMediaBackend::GetPlaybackRate()
292 {
293     return ( ((double)::GetMovieRate(m_movie)) / 0x10000);
294 }
295
296 //---------------------------------------------------------------------------
297 // wxQTMediaBackend::SetPlaybackRate
298 //
299 // 1) Convert dRate to Fixed and Set the movie rate through SetMovieRate
300 //---------------------------------------------------------------------------
301 bool wxQTMediaBackend::SetPlaybackRate(double dRate)
302 {
303     ::SetMovieRate(m_movie, (Fixed) (dRate * 0x10000));
304     return ::GetMoviesError() == noErr;
305 }
306
307 //---------------------------------------------------------------------------
308 // wxQTMediaBackend::SetPosition
309 //
310 // 1) Create a time record struct (TimeRecord) with appropriate values
311 // 2) Pass struct to SetMovieTime
312 //---------------------------------------------------------------------------
313 bool wxQTMediaBackend::SetPosition(wxLongLong where)
314 {
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);
321
322     if (::GetMoviesError() != noErr)
323         return false;
324
325     return true;
326 }
327
328 //---------------------------------------------------------------------------
329 // wxQTMediaBackend::GetPosition
330 //
331 // Calls GetMovieTime
332 //---------------------------------------------------------------------------
333 wxLongLong wxQTMediaBackend::GetPosition()
334 {
335     return ::GetMovieTime(m_movie, NULL);
336 }
337
338 //---------------------------------------------------------------------------
339 // wxQTMediaBackend::GetDuration
340 //
341 // Calls GetMovieDuration
342 //---------------------------------------------------------------------------
343 wxLongLong wxQTMediaBackend::GetDuration()
344 {
345     return ::GetMovieDuration(m_movie);
346 }
347
348 //---------------------------------------------------------------------------
349 // wxQTMediaBackend::GetState
350 //
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()
355 {
356     if ( [m_movieview isPlaying] )
357         return wxMEDIASTATE_PLAYING;
358
359     if( wxQTMediaBackend::GetPosition() == 0 )
360         return wxMEDIASTATE_STOPPED;
361     else
362         return wxMEDIASTATE_PAUSED;
363 }
364
365 //---------------------------------------------------------------------------
366 // wxQTMediaBackend::Cleanup
367 //
368 // Diposes of the movie timer, Control if native, and stops and disposes
369 // of the QT movie
370 //---------------------------------------------------------------------------
371 void wxQTMediaBackend::Cleanup()
372 {
373     if([m_movieview movie])
374     {
375         [[m_movieview movie] release];
376         [m_movieview setMovie:NULL];
377     }
378 }
379
380 //---------------------------------------------------------------------------
381 // wxQTMediaBackend::GetVideoSize
382 //
383 // Returns the actual size of the QT movie
384 //---------------------------------------------------------------------------
385 wxSize wxQTMediaBackend::GetVideoSize() const
386 {
387     return m_bestSize;
388 }
389
390 //---------------------------------------------------------------------------
391 // wxQTMediaBackend::Move
392 //
393 // Nothin... cocoa takes care of this for us
394 //---------------------------------------------------------------------------
395 void wxQTMediaBackend::Move(int x, int y, int w, int h)
396 {
397 }
398
399
400 //in source file that contains stuff you don't directly use
401 #include <wx/html/forcelnk.h>
402 FORCE_LINK_ME(basewxmediabackends);
403
404 #endif //wxUSE_MEDIACTRL
405
406
407
408
409