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