wxMediaCtrl API changes for 2.5.x/2.6
[wxWidgets.git] / src / common / mediactrlcmn.cpp
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
12 //===========================================================================
13 // Definitions
14 //===========================================================================
15
16 //---------------------------------------------------------------------------
17 // Pre-compiled header stuff
18 //---------------------------------------------------------------------------
19
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "mediactrl.h"
22 #endif
23
24 #include "wx/wxprec.h"
25
26 #ifdef __BORLANDC__
27 #pragma hdrstop
28 #endif
29
30 //---------------------------------------------------------------------------
31 // Includes
32 //---------------------------------------------------------------------------
33 #include "wx/mediactrl.h"
34 #include "wx/hash.h"
35
36 //---------------------------------------------------------------------------
37 // Compilation guard
38 //---------------------------------------------------------------------------
39 #if wxUSE_MEDIACTRL
40
41 //===========================================================================
42 //
43 // Implementation
44 //
45 //===========================================================================
46
47 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
48 // RTTI and Event implementations
49 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
50
51 IMPLEMENT_CLASS(wxMediaCtrl, wxControl);
52 IMPLEMENT_CLASS(wxMediaBackend, wxObject);
53 IMPLEMENT_DYNAMIC_CLASS(wxMediaEvent, wxEvent);
54 DEFINE_EVENT_TYPE(wxEVT_MEDIA_FINISHED);
55 DEFINE_EVENT_TYPE(wxEVT_MEDIA_STOP);
56
57 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
58 //
59 // wxMediaCtrl
60 //
61 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
62
63 //---------------------------------------------------------------------------
64 // wxMediaCtrl::Create (file version)
65 // wxMediaCtrl::Create (URL version)
66 //
67 // Searches for a backend that is installed on the system (backends
68 // starting with lower characters in the alphabet are given priority),
69 // and creates the control from it
70 //
71 // This searches by searching the global RTTI hashtable, class by class,
72 // attempting to call CreateControl on each one found that is a derivative
73 // of wxMediaBackend - if it succeeded Create returns true, otherwise
74 // it keeps iterating through the hashmap.
75 //---------------------------------------------------------------------------
76 bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id,
77 const wxString& fileName,
78 const wxPoint& pos,
79 const wxSize& size,
80 long style,
81 const wxString& szBackend,
82 const wxValidator& validator,
83 const wxString& name)
84 {
85 if(!szBackend.empty())
86 {
87 if(!DoCreate(wxClassInfo::FindClass(szBackend), parent, id,
88 pos, size, style, validator, name))
89 {
90 m_imp = NULL;
91 return false;
92 }
93
94 if (!fileName.empty())
95 {
96 if (!Load(fileName))
97 {
98 delete m_imp;
99 m_imp = NULL;
100 return false;
101 }
102 }
103
104 SetBestFittingSize(size);
105 return true;
106 }
107 else
108 {
109 wxClassInfo::sm_classTable->BeginFind();
110
111 wxClassInfo* classInfo = NextBackend();
112
113 while(classInfo)
114 {
115 if(!DoCreate(classInfo, parent, id,
116 pos, size, style, validator, name))
117 continue;
118
119 if (!fileName.empty())
120 {
121 if (Load(fileName))
122 {
123 SetBestFittingSize(size);
124 return true;
125 }
126 else
127 delete m_imp;
128 }
129 else
130 {
131 SetBestFittingSize(size);
132 return true;
133 }
134
135 classInfo = NextBackend();
136 }
137
138 m_imp = NULL;
139 return false;
140 }
141 }
142
143 bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id,
144 const wxURI& location,
145 const wxPoint& pos,
146 const wxSize& size,
147 long style,
148 const wxString& szBackend,
149 const wxValidator& validator,
150 const wxString& name)
151 {
152 if(!szBackend.empty())
153 {
154 if(!DoCreate(wxClassInfo::FindClass(szBackend), parent, id,
155 pos, size, style, validator, name))
156 {
157 m_imp = NULL;
158 return false;
159 }
160
161 if (!Load(location))
162 {
163 delete m_imp;
164 m_imp = NULL;
165 return false;
166 }
167
168 SetBestFittingSize(size);
169 return true;
170 }
171 else
172 {
173 wxClassInfo::sm_classTable->BeginFind();
174
175 wxClassInfo* classInfo = NextBackend();
176
177 while(classInfo)
178 {
179 if(!DoCreate(classInfo, parent, id,
180 pos, size, style, validator, name))
181 continue;
182
183 if (Load(location))
184 {
185 SetBestFittingSize(size);
186 return true;
187 }
188 else
189 delete m_imp;
190
191 classInfo = NextBackend();
192 }
193
194 m_imp = NULL;
195 return false;
196 }
197 }
198
199 //---------------------------------------------------------------------------
200 // wxMediaCtrl::DoCreate
201 //
202 // Attempts to create the control from a backend
203 //---------------------------------------------------------------------------
204 bool wxMediaCtrl::DoCreate(wxClassInfo* classInfo,
205 wxWindow* parent, wxWindowID id,
206 const wxPoint& pos,
207 const wxSize& size,
208 long style,
209 const wxValidator& validator,
210 const wxString& name)
211 {
212 m_imp = (wxMediaBackend*)classInfo->CreateObject();
213
214 if( m_imp->CreateControl(this, parent, id, pos, size,
215 style, validator, name) )
216 {
217 this->Connect(GetId(), wxEVT_MEDIA_FINISHED,
218 (wxObjectEventFunction) (wxEventFunction)
219 (wxMediaEventFunction)
220 &wxMediaCtrl::OnMediaFinished);
221 return true;
222 }
223
224 delete m_imp;
225 return false;
226 }
227
228 //---------------------------------------------------------------------------
229 // wxMediaCtrl::NextBackend
230 //
231 //
232 // Search through the RTTI hashmap one at a
233 // time, attempting to create each derivative
234 // of wxMediaBackend
235 //
236 //
237 // STL isn't compatable with and will have a compilation error
238 // on a wxNode, however, wxHashTable::compatibility_iterator is
239 // incompatible with the old 2.4 stable version - but since
240 // we're in 2.5 only we don't need to worry about this
241 // static
242 //---------------------------------------------------------------------------
243 wxClassInfo* wxMediaCtrl::NextBackend()
244 {
245 wxHashTable::compatibility_iterator
246 node = wxClassInfo::sm_classTable->Next();
247 while (node)
248 {
249 wxClassInfo* classInfo = (wxClassInfo *)node->GetData();
250 if ( classInfo->IsKindOf(CLASSINFO(wxMediaBackend)) &&
251 classInfo != CLASSINFO(wxMediaBackend) )
252 {
253 return classInfo;
254 }
255 node = wxClassInfo::sm_classTable->Next();
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 //---------------------------------------------------------------------------
270 wxMediaCtrl::~wxMediaCtrl()
271 {
272 if (m_imp)
273 delete m_imp;
274 }
275
276 //---------------------------------------------------------------------------
277 // wxMediaCtrl::Load (file version)
278 // wxMediaCtrl::Load (URL version)
279 //
280 // Here we call load of the backend - keeping
281 // track of whether it was successful or not - which
282 // will determine which later method calls work
283 //---------------------------------------------------------------------------
284 bool wxMediaCtrl::Load(const wxString& fileName)
285 {
286 if(m_imp)
287 return (m_bLoaded = m_imp->Load(fileName));
288 return false;
289 }
290
291 bool wxMediaCtrl::Load(const wxURI& location)
292 {
293 if(m_imp)
294 return (m_bLoaded = m_imp->Load(location));
295 return false;
296 }
297
298 //---------------------------------------------------------------------------
299 // wxMediaCtrl::Play
300 // wxMediaCtrl::Pause
301 // wxMediaCtrl::Stop
302 // wxMediaCtrl::GetPlaybackRate
303 // wxMediaCtrl::SetPlaybackRate
304 // wxMediaCtrl::Seek --> SetPosition
305 // wxMediaCtrl::Tell --> GetPosition
306 // wxMediaCtrl::Length --> GetDuration
307 // wxMediaCtrl::GetState
308 // wxMediaCtrl::DoGetBestSize
309 //
310 // 1) Check to see whether the backend exists and is loading
311 // 2) Call the backend's version of the method, returning success
312 // if the backend's version succeeds
313 //---------------------------------------------------------------------------
314 bool wxMediaCtrl::Play()
315 {
316 if(m_imp && m_bLoaded)
317 return m_imp->Play();
318 return 0;
319 }
320
321 bool wxMediaCtrl::Pause()
322 {
323 if(m_imp && m_bLoaded)
324 return m_imp->Pause();
325 return 0;
326 }
327
328 bool wxMediaCtrl::Stop()
329 {
330 if(m_imp && m_bLoaded)
331 return m_imp->Stop();
332 return 0;
333 }
334
335 double wxMediaCtrl::GetPlaybackRate()
336 {
337 if(m_imp && m_bLoaded)
338 return m_imp->GetPlaybackRate();
339 return 0;
340 }
341
342 bool wxMediaCtrl::SetPlaybackRate(double dRate)
343 {
344 if(m_imp && m_bLoaded)
345 return m_imp->SetPlaybackRate(dRate);
346 return false;
347 }
348
349 wxFileOffset wxMediaCtrl::Seek(wxFileOffset where, wxSeekMode mode)
350 {
351 wxFileOffset offset;
352
353 switch (mode)
354 {
355 case wxFromStart:
356 offset = where;
357 break;
358 case wxFromEnd:
359 offset = Length() - where;
360 break;
361 // case wxFromCurrent:
362 default:
363 offset = Tell() + where;
364 break;
365 }
366
367 if(m_imp && m_bLoaded && m_imp->SetPosition(offset))
368 return offset;
369 return wxInvalidOffset;
370 }
371
372 wxFileOffset wxMediaCtrl::Tell()
373 {
374 //FIXME
375 if(m_imp && m_bLoaded)
376 return (wxFileOffset) m_imp->GetPosition().ToLong();
377 return wxInvalidOffset;
378 }
379
380 wxFileOffset wxMediaCtrl::Length()
381 {
382 //FIXME
383 if(m_imp && m_bLoaded)
384 return (wxFileOffset) m_imp->GetDuration().ToLong();
385 return wxInvalidOffset;
386 }
387
388 wxMediaState wxMediaCtrl::GetState()
389 {
390 if(m_imp && m_bLoaded)
391 return m_imp->GetState();
392 return wxMEDIASTATE_STOPPED;
393 }
394
395 wxSize wxMediaCtrl::DoGetBestSize() const
396 {
397 if(m_imp)
398 return m_imp->GetVideoSize();
399 return wxSize(0,0);
400 }
401
402 //---------------------------------------------------------------------------
403 // wxMediaCtrl::DoMoveWindow
404 //
405 // 1) Call parent's version so that our control's window moves where
406 // it's supposed to
407 // 2) If the backend exists and is loaded, move the video
408 // of the media to where our control's window is now located
409 //---------------------------------------------------------------------------
410 void wxMediaCtrl::DoMoveWindow(int x, int y, int w, int h)
411 {
412 wxControl::DoMoveWindow(x,y,w,h);
413
414 if(m_imp)
415 m_imp->Move(x, y, w, h);
416 }
417
418 void wxMediaCtrl::Loop(bool bLoop)
419 {
420 m_bLoop = bLoop;
421 }
422
423 bool wxMediaCtrl::IsLooped()
424 {
425 return m_bLoop;
426 }
427
428 void wxMediaCtrl::OnMediaFinished(wxMediaEvent& WXUNUSED(evt))
429 {
430 if(m_bLoop)
431 {
432 #ifdef __WXDEBUG__
433 wxASSERT( Play() );
434 #else
435 Play();
436 #endif
437 }
438 }
439
440 //DARWIN gcc compiler badly screwed up - needs destructor impl in source
441 wxMediaBackend::~wxMediaBackend()
442 { }
443 #include <wx/html/forcelnk.h>
444 FORCE_LINK(basewxmediabackends);
445
446 //---------------------------------------------------------------------------
447 // End of compilation guard and of file
448 //---------------------------------------------------------------------------
449 #endif //wxUSE_MEDIACTRL
450
451