1
/////////////////////////////////////////////////////////////////////////////
2
// Name: src/cocoa/mediactrl.cpp
3
// Purpose: Built-in Media Backends for Cocoa
4
// Author: Ryan Norton <wxprojects@comcast.net>
7
// Copyright: (c) 2004-2005 Ryan Norton, (c) 2005 David Elliot
8
// Licence: wxWindows licence
9
/////////////////////////////////////////////////////////////////////////////
11
//===========================================================================
13
//===========================================================================
15
//---------------------------------------------------------------------------
16
// Pre-compiled header stuff
17
//---------------------------------------------------------------------------
19
// For compilers that support precompilation, includes "wx.h".
20
#include "wx/wxprec.h"
26
//---------------------------------------------------------------------------
28
//---------------------------------------------------------------------------
31
#include "wx/mediactrl.h"
37
#include "wx/osx/private.h"
39
//===========================================================================
40
// BACKEND DECLARATIONS
41
//===========================================================================
43
//---------------------------------------------------------------------------
47
//---------------------------------------------------------------------------
49
//---------------------------------------------------------------------------
51
//---------------------------------------------------------------------------
52
#include <QTKit/QTKit.h>
54
#include "wx/cocoa/autorelease.h"
55
#include "wx/cocoa/string.h"
57
class WXDLLIMPEXP_FWD_MEDIA wxQTMediaBackend;
59
@interface wxQTMovie : QTMovie {
61
wxQTMediaBackend* m_backend;
68
class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackendCommonBase
75
virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
80
const wxValidator& validator,
81
const wxString& name);
87
virtual bool Load(const wxString& fileName);
88
virtual bool Load(const wxURI& location);
90
virtual wxMediaState GetState();
92
virtual bool SetPosition(wxLongLong where);
93
virtual wxLongLong GetPosition();
94
virtual wxLongLong GetDuration();
96
virtual void Move(int x, int y, int w, int h);
97
wxSize GetVideoSize() const;
99
virtual double GetPlaybackRate();
100
virtual bool SetPlaybackRate(double dRate);
102
virtual double GetVolume();
103
virtual bool SetVolume(double dVolume);
108
virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags);
110
void DoShowPlayerControls(wxMediaCtrlPlayerControls flags);
112
wxSize m_bestSize; //Original movie size
113
wxQTMovie* m_movie; //QTMovie handle/instance
114
QTMovieView* m_movieview; //QTMovieView instance
116
wxMediaCtrlPlayerControls m_interfaceflags; // Saved interface flags
118
DECLARE_DYNAMIC_CLASS(wxQTMediaBackend);
121
// --------------------------------------------------------------------------
123
// --------------------------------------------------------------------------
125
@implementation wxQTMovie
127
- (id)initWithURL:(NSURL *)url error:(NSError **)errorPtr
129
if ( [super initWithURL:url error:errorPtr] != nil )
133
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
134
[nc addObserver:self selector:@selector(movieDidEnd:)
135
name:QTMovieDidEndNotification object:nil];
136
[nc addObserver:self selector:@selector(movieRateChanged:)
137
name:QTMovieRateDidChangeNotification object:nil];
138
[nc addObserver:self selector:@selector(loadStateChanged:)
139
name:QTMovieLoadStateDidChangeNotification object:nil];
149
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
150
[nc removeObserver:self];
155
-(wxQTMediaBackend*) backend;
160
-(void) setBackend:(wxQTMediaBackend*) backend
165
- (void)movieDidEnd:(NSNotification *)notification
169
if ( m_backend->SendStopEvent() )
170
m_backend->QueueFinishEvent();
174
- (void)movieRateChanged:(NSNotification *)notification
176
NSDictionary *userInfo = [notification userInfo];
178
NSNumber *newRate = [userInfo objectForKey:QTMovieRateDidChangeNotificationParameter];
180
if ([newRate intValue] == 0)
182
m_backend->QueuePauseEvent();
184
else if ( [self isPlaying] == NO )
186
m_backend->QueuePlayEvent();
190
-(void)loadStateChanged:(NSNotification *)notification
192
QTMovie *movie = [notification object];
193
long loadState = [[movie attributeForKey:QTMovieLoadStateAttribute] longValue];
194
if ( loadState == QTMovieLoadStateError )
198
else if (loadState >= QTMovieLoadStatePlayable)
200
// the movie has loaded enough media data to begin playing, but we don't have an event for that yet
202
else if (loadState >= QTMovieLoadStateComplete) // we might use QTMovieLoadStatePlaythroughOK
204
m_backend->FinishLoad();
210
if ([self rate] == 0)
220
// --------------------------------------------------------------------------
222
// --------------------------------------------------------------------------
224
IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend);
226
wxQTMediaBackend::wxQTMediaBackend() :
227
m_movie(nil), m_movieview(nil),
228
m_interfaceflags(wxMEDIACTRLPLAYERCONTROLS_NONE)
232
wxQTMediaBackend::~wxQTMediaBackend()
237
bool wxQTMediaBackend::CreateControl(wxControl* inctrl, wxWindow* parent,
242
const wxValidator& validator,
243
const wxString& name)
245
wxMediaCtrl* mediactrl = (wxMediaCtrl*) inctrl;
247
mediactrl->DontCreatePeer();
249
if ( !mediactrl->wxControl::Create(
250
parent, wid, pos, size,
251
wxWindow::MacRemoveBordersFromStyle(style),
257
NSRect r = wxOSXGetFrameForControl( mediactrl, pos , size ) ;
258
QTMovieView* theView = [[QTMovieView alloc] initWithFrame: r];
260
wxWidgetCocoaImpl* impl = new wxWidgetCocoaImpl(mediactrl,theView);
261
mediactrl->SetPeer(impl);
263
m_movieview = theView;
264
// will be set up after load
265
[theView setControllerVisible:NO];
271
bool wxQTMediaBackend::Load(const wxString& fileName)
275
wxString( wxT("file://") ) + fileName
280
bool wxQTMediaBackend::Load(const wxURI& location)
282
wxCFStringRef uri(location.BuildURI());
283
NSURL *url = [NSURL URLWithString: uri.AsNSString()];
285
if (! [wxQTMovie canInitWithURL:url])
289
wxQTMovie* movie = [[wxQTMovie alloc] initWithURL:url error: nil ];
294
[m_movie setBackend:this];
295
[m_movieview setMovie:movie];
297
// If the media file is able to be loaded quickly then there may not be
298
// any QTMovieLoadStateDidChangeNotification message sent, so we need to
299
// also check the load state here and finish our initialization if it has
301
long loadState = [[m_movie attributeForKey:QTMovieLoadStateAttribute] longValue];
302
if (loadState >= QTMovieLoadStateComplete)
311
void wxQTMediaBackend::FinishLoad()
313
DoShowPlayerControls(m_interfaceflags);
315
NSSize s = [[m_movie attributeForKey:QTMovieNaturalSizeAttribute] sizeValue];
316
m_bestSize = wxSize(s.width, s.height);
321
bool wxQTMediaBackend::Play()
323
[m_movieview play:nil];
327
bool wxQTMediaBackend::Pause()
329
[m_movieview pause:nil];
333
bool wxQTMediaBackend::Stop()
335
[m_movieview pause:nil];
336
[m_movieview gotoBeginning:nil];
340
double wxQTMediaBackend::GetVolume()
342
return [m_movie volume];
345
bool wxQTMediaBackend::SetVolume(double dVolume)
347
[m_movie setVolume:dVolume];
350
double wxQTMediaBackend::GetPlaybackRate()
352
return [m_movie rate];
355
bool wxQTMediaBackend::SetPlaybackRate(double dRate)
357
[m_movie setRate:dRate];
361
bool wxQTMediaBackend::SetPosition(wxLongLong where)
364
position = [m_movie currentTime];
365
position.timeValue = (where.GetValue() / 1000.0) * position.timeScale;
366
[m_movie setCurrentTime:position];
370
wxLongLong wxQTMediaBackend::GetPosition()
372
QTTime position = [m_movie currentTime];
373
return ((double) position.timeValue) / position.timeScale * 1000;
376
wxLongLong wxQTMediaBackend::GetDuration()
378
QTTime duration = [m_movie duration];
379
return ((double) duration.timeValue) / duration.timeScale * 1000;
382
wxMediaState wxQTMediaBackend::GetState()
384
if ( [m_movie isPlaying] )
385
return wxMEDIASTATE_PLAYING;
388
if ( GetPosition() == 0 )
389
return wxMEDIASTATE_STOPPED;
391
return wxMEDIASTATE_PAUSED;
395
void wxQTMediaBackend::Cleanup()
397
[m_movieview setMovie:NULL];
402
wxSize wxQTMediaBackend::GetVideoSize() const
407
void wxQTMediaBackend::Move(int x, int y, int w, int h)
409
// as we have a native player, no need to move the video area
412
bool wxQTMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
414
if ( m_interfaceflags != flags )
415
DoShowPlayerControls(flags);
417
m_interfaceflags = flags;
421
void wxQTMediaBackend::DoShowPlayerControls(wxMediaCtrlPlayerControls flags)
423
if (flags == wxMEDIACTRLPLAYERCONTROLS_NONE )
425
[m_movieview setControllerVisible:NO];
429
[m_movieview setControllerVisible:YES];
431
[m_movieview setStepButtonsVisible:(flags & wxMEDIACTRLPLAYERCONTROLS_STEP) ? YES:NO];
432
[m_movieview setVolumeButtonVisible:(flags & wxMEDIACTRLPLAYERCONTROLS_VOLUME) ? YES:NO];
436
//in source file that contains stuff you don't directly use
437
#include "wx/html/forcelnk.h"
438
FORCE_LINK_ME(basewxmediabackends);
440
#endif //wxUSE_MEDIACTRL