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