]> git.saurik.com Git - wxWidgets.git/blame - src/common/mediactrlcmn.cpp
Merge in from trunk r64802 - r68625
[wxWidgets.git] / src / common / mediactrlcmn.cpp
CommitLineData
ff4aedc5 1/////////////////////////////////////////////////////////////////////////////
80fdcdb9 2// Name: src/common/mediactrlcmn.cpp
ff4aedc5
RN
3// Purpose: wxMediaCtrl common code
4// Author: Ryan Norton <wxprojects@comcast.net>
5// Modified by:
6// Created: 11/07/04
7// RCS-ID: $Id$
8// Copyright: (c) Ryan Norton
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
557002cf
VZ
12// TODO: Platform specific backend defaults?
13
ff4aedc5 14//===========================================================================
70eca0fa 15// Declarations
ff4aedc5
RN
16//===========================================================================
17
18//---------------------------------------------------------------------------
70eca0fa 19// Includes
ff4aedc5
RN
20//---------------------------------------------------------------------------
21
ff4aedc5
RN
22#include "wx/wxprec.h"
23
24#ifdef __BORLANDC__
32d4c30a
WS
25 #pragma hdrstop
26#endif
27
28#if wxUSE_MEDIACTRL
29
30#ifndef WX_PRECOMP
31 #include "wx/hash.h"
70eca0fa 32 #include "wx/log.h"
ff4aedc5
RN
33#endif
34
ff4aedc5 35#include "wx/mediactrl.h"
ff4aedc5
RN
36
37//===========================================================================
38//
39// Implementation
226ec5a7 40//
ff4aedc5
RN
41//===========================================================================
42
43//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
44// RTTI and Event implementations
45//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
46
f74fd79b 47IMPLEMENT_CLASS(wxMediaCtrl, wxControl)
9b11752c
VZ
48wxDEFINE_EVENT( wxEVT_MEDIA_STATECHANGED, wxMediaEvent );
49wxDEFINE_EVENT( wxEVT_MEDIA_PLAY, wxMediaEvent );
50wxDEFINE_EVENT( wxEVT_MEDIA_PAUSE, wxMediaEvent );
f74fd79b
VZ
51IMPLEMENT_CLASS(wxMediaBackend, wxObject)
52IMPLEMENT_DYNAMIC_CLASS(wxMediaEvent, wxEvent)
9b11752c
VZ
53wxDEFINE_EVENT( wxEVT_MEDIA_FINISHED, wxMediaEvent );
54wxDEFINE_EVENT( wxEVT_MEDIA_LOADED, wxMediaEvent );
55wxDEFINE_EVENT( wxEVT_MEDIA_STOP, wxMediaEvent );
ff4aedc5
RN
56
57//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
58//
59// wxMediaCtrl
60//
61//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
62
38647faa
WS
63//---------------------------------------------------------------------------
64// wxMediaBackend Destructor
65//
66// This is here because the DARWIN gcc compiler badly screwed up and
67// needs the destructor implementation in the source
68//---------------------------------------------------------------------------
69wxMediaBackend::~wxMediaBackend()
70{
71}
72
ff4aedc5
RN
73//---------------------------------------------------------------------------
74// wxMediaCtrl::Create (file version)
75// wxMediaCtrl::Create (URL version)
76//
77// Searches for a backend that is installed on the system (backends
78// starting with lower characters in the alphabet are given priority),
79// and creates the control from it
226ec5a7 80//
ff4aedc5
RN
81// This searches by searching the global RTTI hashtable, class by class,
82// attempting to call CreateControl on each one found that is a derivative
9180b535 83// of wxMediaBackend - if it succeeded Create returns true, otherwise
ff4aedc5
RN
84// it keeps iterating through the hashmap.
85//---------------------------------------------------------------------------
86bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id,
87 const wxString& fileName,
226ec5a7 88 const wxPoint& pos,
ff4aedc5 89 const wxSize& size,
226ec5a7 90 long style,
ff4aedc5
RN
91 const wxString& szBackend,
92 const wxValidator& validator,
93 const wxString& name)
94{
95 if(!szBackend.empty())
96 {
38647faa
WS
97 wxClassInfo* pClassInfo = wxClassInfo::FindClass(szBackend);
98
99 if(!pClassInfo || !DoCreate(pClassInfo, parent, id,
100 pos, size, style, validator, name))
ff4aedc5
RN
101 {
102 m_imp = NULL;
103 return false;
104 }
105
106 if (!fileName.empty())
107 {
4ac61319 108 if (!Load(fileName))
ff4aedc5 109 {
5276b0a5 110 wxDELETE(m_imp);
ff4aedc5
RN
111 return false;
112 }
113 }
114
170acdc9 115 SetInitialSize(size);
ff4aedc5
RN
116 return true;
117 }
118 else
119 {
644cb537 120 wxClassInfo::const_iterator it = wxClassInfo::begin_classinfo();
ff4aedc5 121
644cb537 122 const wxClassInfo* classInfo;
ff4aedc5 123
644cb537 124 while((classInfo = NextBackend(&it)) != NULL)
ff4aedc5
RN
125 {
126 if(!DoCreate(classInfo, parent, id,
127 pos, size, style, validator, name))
226ec5a7 128 continue;
ff4aedc5
RN
129
130 if (!fileName.empty())
131 {
4ac61319
RN
132 if (Load(fileName))
133 {
170acdc9 134 SetInitialSize(size);
ff4aedc5 135 return true;
4ac61319 136 }
ff4aedc5
RN
137 else
138 delete m_imp;
139 }
140 else
4ac61319 141 {
170acdc9 142 SetInitialSize(size);
ff4aedc5 143 return true;
4ac61319 144 }
ff4aedc5
RN
145 }
146
147 m_imp = NULL;
148 return false;
149 }
150}
151
152bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id,
38647faa
WS
153 const wxURI& location,
154 const wxPoint& pos,
155 const wxSize& size,
156 long style,
157 const wxString& szBackend,
158 const wxValidator& validator,
159 const wxString& name)
ff4aedc5
RN
160{
161 if(!szBackend.empty())
162 {
38647faa
WS
163 wxClassInfo* pClassInfo = wxClassInfo::FindClass(szBackend);
164 if(!pClassInfo || !DoCreate(pClassInfo, parent, id,
165 pos, size, style, validator, name))
ff4aedc5
RN
166 {
167 m_imp = NULL;
168 return false;
169 }
170
4ac61319 171 if (!Load(location))
ff4aedc5 172 {
5276b0a5 173 wxDELETE(m_imp);
ff4aedc5
RN
174 return false;
175 }
176
170acdc9 177 SetInitialSize(size);
ff4aedc5
RN
178 return true;
179 }
180 else
181 {
644cb537 182 wxClassInfo::const_iterator it = wxClassInfo::begin_classinfo();
ff4aedc5 183
644cb537 184 const wxClassInfo* classInfo;
ff4aedc5 185
644cb537 186 while((classInfo = NextBackend(&it)) != NULL)
ff4aedc5
RN
187 {
188 if(!DoCreate(classInfo, parent, id,
189 pos, size, style, validator, name))
226ec5a7 190 continue;
ff4aedc5 191
4ac61319
RN
192 if (Load(location))
193 {
170acdc9 194 SetInitialSize(size);
ff4aedc5 195 return true;
4ac61319 196 }
ff4aedc5
RN
197 else
198 delete m_imp;
ff4aedc5
RN
199 }
200
201 m_imp = NULL;
202 return false;
203 }
204}
205
206//---------------------------------------------------------------------------
207// wxMediaCtrl::DoCreate
208//
209// Attempts to create the control from a backend
210//---------------------------------------------------------------------------
644cb537 211bool wxMediaCtrl::DoCreate(const wxClassInfo* classInfo,
ff4aedc5 212 wxWindow* parent, wxWindowID id,
226ec5a7 213 const wxPoint& pos,
ff4aedc5 214 const wxSize& size,
226ec5a7 215 long style,
ff4aedc5
RN
216 const wxValidator& validator,
217 const wxString& name)
218{
219 m_imp = (wxMediaBackend*)classInfo->CreateObject();
226ec5a7 220
ff4aedc5
RN
221 if( m_imp->CreateControl(this, parent, id, pos, size,
222 style, validator, name) )
223 {
ff4aedc5
RN
224 return true;
225 }
226ec5a7 226
ff4aedc5
RN
227 delete m_imp;
228 return false;
229}
230
231//---------------------------------------------------------------------------
557002cf 232// wxMediaCtrl::NextBackend (static)
ff4aedc5
RN
233//
234//
235// Search through the RTTI hashmap one at a
236// time, attempting to create each derivative
237// of wxMediaBackend
226ec5a7 238//
ff4aedc5 239//
43e8916f 240// STL isn't compatible with and will have a compilation error
ff4aedc5
RN
241// on a wxNode, however, wxHashTable::compatibility_iterator is
242// incompatible with the old 2.4 stable version - but since
557002cf 243// we're in 2.5+ only we don't need to worry about the new version
ff4aedc5 244//---------------------------------------------------------------------------
644cb537 245const wxClassInfo* wxMediaCtrl::NextBackend(wxClassInfo::const_iterator* it)
ff4aedc5 246{
644cb537
MB
247 for ( wxClassInfo::const_iterator end = wxClassInfo::end_classinfo();
248 *it != end; ++(*it) )
ff4aedc5 249 {
644cb537 250 const wxClassInfo* classInfo = **it;
ff4aedc5
RN
251 if ( classInfo->IsKindOf(CLASSINFO(wxMediaBackend)) &&
252 classInfo != CLASSINFO(wxMediaBackend) )
253 {
ad877f92 254 ++(*it);
ff4aedc5
RN
255 return classInfo;
256 }
ff4aedc5
RN
257 }
258
259 //
260 // Nope - couldn't successfully find one... fail
261 //
262 return NULL;
263}
264
265
266//---------------------------------------------------------------------------
267// wxMediaCtrl Destructor
268//
269// Free up the backend if it exists
270//---------------------------------------------------------------------------
271wxMediaCtrl::~wxMediaCtrl()
272{
273 if (m_imp)
274 delete m_imp;
275}
276
277//---------------------------------------------------------------------------
278// wxMediaCtrl::Load (file version)
279// wxMediaCtrl::Load (URL version)
c5191fbd
VZ
280// wxMediaCtrl::Load (URL & Proxy version)
281// wxMediaCtrl::Load (wxInputStream version)
ff4aedc5
RN
282//
283// Here we call load of the backend - keeping
284// track of whether it was successful or not - which
285// will determine which later method calls work
286//---------------------------------------------------------------------------
287bool wxMediaCtrl::Load(const wxString& fileName)
288{
289 if(m_imp)
290 return (m_bLoaded = m_imp->Load(fileName));
291 return false;
292}
293
294bool wxMediaCtrl::Load(const wxURI& location)
295{
296 if(m_imp)
297 return (m_bLoaded = m_imp->Load(location));
298 return false;
299}
300
c5191fbd
VZ
301bool wxMediaCtrl::Load(const wxURI& location, const wxURI& proxy)
302{
303 if(m_imp)
304 return (m_bLoaded = m_imp->Load(location, proxy));
305 return false;
306}
307
ff4aedc5
RN
308//---------------------------------------------------------------------------
309// wxMediaCtrl::Play
310// wxMediaCtrl::Pause
311// wxMediaCtrl::Stop
312// wxMediaCtrl::GetPlaybackRate
313// wxMediaCtrl::SetPlaybackRate
9180b535
RN
314// wxMediaCtrl::Seek --> SetPosition
315// wxMediaCtrl::Tell --> GetPosition
316// wxMediaCtrl::Length --> GetDuration
ff4aedc5
RN
317// wxMediaCtrl::GetState
318// wxMediaCtrl::DoGetBestSize
6f8c67e7
JS
319// wxMediaCtrl::SetVolume
320// wxMediaCtrl::GetVolume
c5191fbd
VZ
321// wxMediaCtrl::ShowInterface
322// wxMediaCtrl::GetDownloadProgress
323// wxMediaCtrl::GetDownloadTotal
226ec5a7 324//
ff4aedc5
RN
325// 1) Check to see whether the backend exists and is loading
326// 2) Call the backend's version of the method, returning success
327// if the backend's version succeeds
328//---------------------------------------------------------------------------
329bool wxMediaCtrl::Play()
330{
331 if(m_imp && m_bLoaded)
332 return m_imp->Play();
333 return 0;
334}
335
336bool wxMediaCtrl::Pause()
337{
338 if(m_imp && m_bLoaded)
339 return m_imp->Pause();
340 return 0;
341}
342
343bool wxMediaCtrl::Stop()
344{
345 if(m_imp && m_bLoaded)
346 return m_imp->Stop();
347 return 0;
348}
349
350double wxMediaCtrl::GetPlaybackRate()
351{
352 if(m_imp && m_bLoaded)
353 return m_imp->GetPlaybackRate();
354 return 0;
355}
356
357bool wxMediaCtrl::SetPlaybackRate(double dRate)
358{
359 if(m_imp && m_bLoaded)
360 return m_imp->SetPlaybackRate(dRate);
361 return false;
362}
363
9180b535 364wxFileOffset wxMediaCtrl::Seek(wxFileOffset where, wxSeekMode mode)
ff4aedc5 365{
9180b535
RN
366 wxFileOffset offset;
367
368 switch (mode)
369 {
370 case wxFromStart:
371 offset = where;
372 break;
373 case wxFromEnd:
374 offset = Length() - where;
375 break;
376// case wxFromCurrent:
377 default:
378 offset = Tell() + where;
379 break;
380 }
381
382 if(m_imp && m_bLoaded && m_imp->SetPosition(offset))
383 return offset;
384 return wxInvalidOffset;
ff4aedc5
RN
385}
386
9180b535 387wxFileOffset wxMediaCtrl::Tell()
ff4aedc5
RN
388{
389 if(m_imp && m_bLoaded)
9180b535
RN
390 return (wxFileOffset) m_imp->GetPosition().ToLong();
391 return wxInvalidOffset;
ff4aedc5
RN
392}
393
9180b535 394wxFileOffset wxMediaCtrl::Length()
ff4aedc5
RN
395{
396 if(m_imp && m_bLoaded)
9180b535
RN
397 return (wxFileOffset) m_imp->GetDuration().ToLong();
398 return wxInvalidOffset;
ff4aedc5
RN
399}
400
401wxMediaState wxMediaCtrl::GetState()
402{
403 if(m_imp && m_bLoaded)
404 return m_imp->GetState();
405 return wxMEDIASTATE_STOPPED;
406}
407
408wxSize wxMediaCtrl::DoGetBestSize() const
409{
410 if(m_imp)
411 return m_imp->GetVideoSize();
c47addef 412 return wxSize(0,0);
ff4aedc5
RN
413}
414
32d4c30a 415double wxMediaCtrl::GetVolume()
6f8c67e7
JS
416{
417 if(m_imp && m_bLoaded)
418 return m_imp->GetVolume();
419 return 0.0;
420}
421
32d4c30a 422bool wxMediaCtrl::SetVolume(double dVolume)
6f8c67e7
JS
423{
424 if(m_imp && m_bLoaded)
425 return m_imp->SetVolume(dVolume);
426 return false;
427}
428
32d4c30a 429bool wxMediaCtrl::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
c5191fbd
VZ
430{
431 if(m_imp)
432 return m_imp->ShowPlayerControls(flags);
433 return false;
434}
435
436wxFileOffset wxMediaCtrl::GetDownloadProgress()
437{
438 if(m_imp && m_bLoaded)
439 return (wxFileOffset) m_imp->GetDownloadProgress().ToLong();
440 return wxInvalidOffset;
441}
442
443wxFileOffset wxMediaCtrl::GetDownloadTotal()
444{
445 if(m_imp && m_bLoaded)
446 return (wxFileOffset) m_imp->GetDownloadTotal().ToLong();
447 return wxInvalidOffset;
448}
449
ff4aedc5
RN
450//---------------------------------------------------------------------------
451// wxMediaCtrl::DoMoveWindow
226ec5a7 452//
ff4aedc5
RN
453// 1) Call parent's version so that our control's window moves where
454// it's supposed to
455// 2) If the backend exists and is loaded, move the video
456// of the media to where our control's window is now located
457//---------------------------------------------------------------------------
458void wxMediaCtrl::DoMoveWindow(int x, int y, int w, int h)
459{
460 wxControl::DoMoveWindow(x,y,w,h);
461
462 if(m_imp)
463 m_imp->Move(x, y, w, h);
464}
465
0c81ef7f
SC
466//---------------------------------------------------------------------------
467// wxMediaCtrl::MacVisibilityChanged
468//---------------------------------------------------------------------------
4954ee50 469#ifdef __WXOSX_CARBON__
0c81ef7f
SC
470void wxMediaCtrl::MacVisibilityChanged()
471{
472 wxControl::MacVisibilityChanged();
32d4c30a 473
0c81ef7f 474 if(m_imp)
32d4c30a 475 m_imp->MacVisibilityChanged();
0c81ef7f
SC
476}
477#endif
478
bf354396
VZ
479//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
480//
481// wxMediaBackendCommonBase
482//
483//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
484
485void wxMediaBackendCommonBase::NotifyMovieSizeChanged()
486{
487 // our best size changed after opening a new file
488 m_ctrl->InvalidateBestSize();
489 m_ctrl->SetSize(m_ctrl->GetSize());
490
491 // if the parent of the control has a sizer ask it to refresh our size
492 wxWindow * const parent = m_ctrl->GetParent();
493 if ( parent->GetSizer() )
494 {
495 m_ctrl->GetParent()->Layout();
496 m_ctrl->GetParent()->Refresh();
497 m_ctrl->GetParent()->Update();
498 }
499}
500
501void wxMediaBackendCommonBase::NotifyMovieLoaded()
502{
503 NotifyMovieSizeChanged();
504
505 // notify about movie being fully loaded
506 QueueEvent(wxEVT_MEDIA_LOADED);
507}
508
509bool wxMediaBackendCommonBase::SendStopEvent()
510{
511 wxMediaEvent theEvent(wxEVT_MEDIA_STOP, m_ctrl->GetId());
512
945eac79 513 return !m_ctrl->GetEventHandler()->ProcessEvent(theEvent) || theEvent.IsAllowed();
bf354396
VZ
514}
515
516void wxMediaBackendCommonBase::QueueEvent(wxEventType evtType)
517{
518 wxMediaEvent theEvent(evtType, m_ctrl->GetId());
945eac79 519 m_ctrl->GetEventHandler()->AddPendingEvent(theEvent);
bf354396
VZ
520}
521
557002cf
VZ
522void wxMediaBackendCommonBase::QueuePlayEvent()
523{
524 QueueEvent(wxEVT_MEDIA_STATECHANGED);
525 QueueEvent(wxEVT_MEDIA_PLAY);
526}
527
528void wxMediaBackendCommonBase::QueuePauseEvent()
529{
530 QueueEvent(wxEVT_MEDIA_STATECHANGED);
531 QueueEvent(wxEVT_MEDIA_PAUSE);
532}
533
534void wxMediaBackendCommonBase::QueueStopEvent()
535{
536 QueueEvent(wxEVT_MEDIA_STATECHANGED);
537 QueueEvent(wxEVT_MEDIA_STOP);
538}
539
540
541//
542// Force link default backends in -
543// see http://wiki.wxwidgets.org/wiki.pl?RTTI
544//
02250fa1 545#include "wx/html/forcelnk.h"
ff4aedc5 546
557002cf 547#ifdef __WXMSW__ // MSW has huge backends so we do it seperately
f74fd79b
VZ
548FORCE_LINK(wxmediabackend_am)
549FORCE_LINK(wxmediabackend_wmp10)
4954ee50 550#elif !defined(__WXOSX_COCOA__)
f74fd79b 551FORCE_LINK(basewxmediabackends)
557002cf 552#endif
ff4aedc5 553
32d4c30a 554#endif //wxUSE_MEDIACTRL