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