Fix recursiveness on error...
[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;
112
113 while((classInfo = NextBackend()) != NULL)
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
136 m_imp = NULL;
137 return false;
138 }
139 }
140
141 bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id,
142 const wxURI& location,
143 const wxPoint& pos,
144 const wxSize& size,
145 long style,
146 const wxString& szBackend,
147 const wxValidator& validator,
148 const wxString& name)
149 {
150 if(!szBackend.empty())
151 {
152 if(!DoCreate(wxClassInfo::FindClass(szBackend), parent, id,
153 pos, size, style, validator, name))
154 {
155 m_imp = NULL;
156 return false;
157 }
158
159 if (!Load(location))
160 {
161 delete m_imp;
162 m_imp = NULL;
163 return false;
164 }
165
166 SetBestFittingSize(size);
167 return true;
168 }
169 else
170 {
171 wxClassInfo::sm_classTable->BeginFind();
172
173 wxClassInfo* classInfo;
174
175 while((classInfo = NextBackend()) != NULL)
176 {
177 if(!DoCreate(classInfo, parent, id,
178 pos, size, style, validator, name))
179 continue;
180
181 if (Load(location))
182 {
183 SetBestFittingSize(size);
184 return true;
185 }
186 else
187 delete m_imp;
188 }
189
190 m_imp = NULL;
191 return false;
192 }
193 }
194
195 //---------------------------------------------------------------------------
196 // wxMediaCtrl::DoCreate
197 //
198 // Attempts to create the control from a backend
199 //---------------------------------------------------------------------------
200 bool wxMediaCtrl::DoCreate(wxClassInfo* classInfo,
201 wxWindow* parent, wxWindowID id,
202 const wxPoint& pos,
203 const wxSize& size,
204 long style,
205 const wxValidator& validator,
206 const wxString& name)
207 {
208 m_imp = (wxMediaBackend*)classInfo->CreateObject();
209
210 if( m_imp->CreateControl(this, parent, id, pos, size,
211 style, validator, name) )
212 {
213 return true;
214 }
215
216 delete m_imp;
217 return false;
218 }
219
220 //---------------------------------------------------------------------------
221 // wxMediaCtrl::NextBackend
222 //
223 //
224 // Search through the RTTI hashmap one at a
225 // time, attempting to create each derivative
226 // of wxMediaBackend
227 //
228 //
229 // STL isn't compatable with and will have a compilation error
230 // on a wxNode, however, wxHashTable::compatibility_iterator is
231 // incompatible with the old 2.4 stable version - but since
232 // we're in 2.5 only we don't need to worry about this
233 // static
234 //---------------------------------------------------------------------------
235 wxClassInfo* wxMediaCtrl::NextBackend()
236 {
237 wxHashTable::compatibility_iterator
238 node = wxClassInfo::sm_classTable->Next();
239 while (node)
240 {
241 wxClassInfo* classInfo = (wxClassInfo *)node->GetData();
242 if ( classInfo->IsKindOf(CLASSINFO(wxMediaBackend)) &&
243 classInfo != CLASSINFO(wxMediaBackend) )
244 {
245 return classInfo;
246 }
247 node = wxClassInfo::sm_classTable->Next();
248 }
249
250 //
251 // Nope - couldn't successfully find one... fail
252 //
253 return NULL;
254 }
255
256
257 //---------------------------------------------------------------------------
258 // wxMediaCtrl Destructor
259 //
260 // Free up the backend if it exists
261 //---------------------------------------------------------------------------
262 wxMediaCtrl::~wxMediaCtrl()
263 {
264 if (m_imp)
265 delete m_imp;
266 }
267
268 //---------------------------------------------------------------------------
269 // wxMediaCtrl::Load (file version)
270 // wxMediaCtrl::Load (URL version)
271 //
272 // Here we call load of the backend - keeping
273 // track of whether it was successful or not - which
274 // will determine which later method calls work
275 //---------------------------------------------------------------------------
276 bool wxMediaCtrl::Load(const wxString& fileName)
277 {
278 if(m_imp)
279 return (m_bLoaded = m_imp->Load(fileName));
280 return false;
281 }
282
283 bool wxMediaCtrl::Load(const wxURI& location)
284 {
285 if(m_imp)
286 return (m_bLoaded = m_imp->Load(location));
287 return false;
288 }
289
290 //---------------------------------------------------------------------------
291 // wxMediaCtrl::Play
292 // wxMediaCtrl::Pause
293 // wxMediaCtrl::Stop
294 // wxMediaCtrl::GetPlaybackRate
295 // wxMediaCtrl::SetPlaybackRate
296 // wxMediaCtrl::Seek --> SetPosition
297 // wxMediaCtrl::Tell --> GetPosition
298 // wxMediaCtrl::Length --> GetDuration
299 // wxMediaCtrl::GetState
300 // wxMediaCtrl::DoGetBestSize
301 //
302 // 1) Check to see whether the backend exists and is loading
303 // 2) Call the backend's version of the method, returning success
304 // if the backend's version succeeds
305 //---------------------------------------------------------------------------
306 bool wxMediaCtrl::Play()
307 {
308 if(m_imp && m_bLoaded)
309 return m_imp->Play();
310 return 0;
311 }
312
313 bool wxMediaCtrl::Pause()
314 {
315 if(m_imp && m_bLoaded)
316 return m_imp->Pause();
317 return 0;
318 }
319
320 bool wxMediaCtrl::Stop()
321 {
322 if(m_imp && m_bLoaded)
323 return m_imp->Stop();
324 return 0;
325 }
326
327 double wxMediaCtrl::GetPlaybackRate()
328 {
329 if(m_imp && m_bLoaded)
330 return m_imp->GetPlaybackRate();
331 return 0;
332 }
333
334 bool wxMediaCtrl::SetPlaybackRate(double dRate)
335 {
336 if(m_imp && m_bLoaded)
337 return m_imp->SetPlaybackRate(dRate);
338 return false;
339 }
340
341 wxFileOffset wxMediaCtrl::Seek(wxFileOffset where, wxSeekMode mode)
342 {
343 wxFileOffset offset;
344
345 switch (mode)
346 {
347 case wxFromStart:
348 offset = where;
349 break;
350 case wxFromEnd:
351 offset = Length() - where;
352 break;
353 // case wxFromCurrent:
354 default:
355 offset = Tell() + where;
356 break;
357 }
358
359 if(m_imp && m_bLoaded && m_imp->SetPosition(offset))
360 return offset;
361 return wxInvalidOffset;
362 }
363
364 wxFileOffset wxMediaCtrl::Tell()
365 {
366 //FIXME
367 if(m_imp && m_bLoaded)
368 return (wxFileOffset) m_imp->GetPosition().ToLong();
369 return wxInvalidOffset;
370 }
371
372 wxFileOffset wxMediaCtrl::Length()
373 {
374 //FIXME
375 if(m_imp && m_bLoaded)
376 return (wxFileOffset) m_imp->GetDuration().ToLong();
377 return wxInvalidOffset;
378 }
379
380 wxMediaState wxMediaCtrl::GetState()
381 {
382 if(m_imp && m_bLoaded)
383 return m_imp->GetState();
384 return wxMEDIASTATE_STOPPED;
385 }
386
387 wxSize wxMediaCtrl::DoGetBestSize() const
388 {
389 if(m_imp)
390 return m_imp->GetVideoSize();
391 return wxSize(0,0);
392 }
393
394 //---------------------------------------------------------------------------
395 // wxMediaCtrl::DoMoveWindow
396 //
397 // 1) Call parent's version so that our control's window moves where
398 // it's supposed to
399 // 2) If the backend exists and is loaded, move the video
400 // of the media to where our control's window is now located
401 //---------------------------------------------------------------------------
402 void wxMediaCtrl::DoMoveWindow(int x, int y, int w, int h)
403 {
404 wxControl::DoMoveWindow(x,y,w,h);
405
406 if(m_imp)
407 m_imp->Move(x, y, w, h);
408 }
409
410 //DARWIN gcc compiler badly screwed up - needs destructor impl in source
411 wxMediaBackend::~wxMediaBackend()
412 { }
413 #include "wx/html/forcelnk.h"
414 FORCE_LINK(basewxmediabackends);
415
416 //---------------------------------------------------------------------------
417 // End of compilation guard and of file
418 //---------------------------------------------------------------------------
419 #endif //wxUSE_MEDIACTRL
420
421