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