wxMediaCtrl patch from Ryan:
[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_LOADED);
56 DEFINE_EVENT_TYPE(wxEVT_MEDIA_STOP);
57
58 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
59 //
60 // wxMediaCtrl
61 //
62 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
63
64 //---------------------------------------------------------------------------
65 // wxMediaBackend Destructor
66 //
67 // This is here because the DARWIN gcc compiler badly screwed up and
68 // needs the destructor implementation in the source
69 //---------------------------------------------------------------------------
70 wxMediaBackend::~wxMediaBackend()
71 {
72 }
73
74 //---------------------------------------------------------------------------
75 // wxMediaCtrl::Create (file version)
76 // wxMediaCtrl::Create (URL version)
77 //
78 // Searches for a backend that is installed on the system (backends
79 // starting with lower characters in the alphabet are given priority),
80 // and creates the control from it
81 //
82 // This searches by searching the global RTTI hashtable, class by class,
83 // attempting to call CreateControl on each one found that is a derivative
84 // of wxMediaBackend - if it succeeded Create returns true, otherwise
85 // it keeps iterating through the hashmap.
86 //---------------------------------------------------------------------------
87 bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id,
88 const wxString& fileName,
89 const wxPoint& pos,
90 const wxSize& size,
91 long style,
92 const wxString& szBackend,
93 const wxValidator& validator,
94 const wxString& name)
95 {
96 if(!szBackend.empty())
97 {
98 wxClassInfo* pClassInfo = wxClassInfo::FindClass(szBackend);
99
100 if(!pClassInfo || !DoCreate(pClassInfo, parent, id,
101 pos, size, style, validator, name))
102 {
103 m_imp = NULL;
104 return false;
105 }
106
107 if (!fileName.empty())
108 {
109 if (!Load(fileName))
110 {
111 delete m_imp;
112 m_imp = NULL;
113 return false;
114 }
115 }
116
117 SetBestFittingSize(size);
118 return true;
119 }
120 else
121 {
122 wxClassInfo::sm_classTable->BeginFind();
123
124 wxClassInfo* classInfo;
125
126 while((classInfo = NextBackend()) != NULL)
127 {
128 if(!DoCreate(classInfo, parent, id,
129 pos, size, style, validator, name))
130 continue;
131
132 if (!fileName.empty())
133 {
134 if (Load(fileName))
135 {
136 SetBestFittingSize(size);
137 return true;
138 }
139 else
140 delete m_imp;
141 }
142 else
143 {
144 SetBestFittingSize(size);
145 return true;
146 }
147 }
148
149 m_imp = NULL;
150 return false;
151 }
152 }
153
154 bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id,
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)
162 {
163 if(!szBackend.empty())
164 {
165 wxClassInfo* pClassInfo = wxClassInfo::FindClass(szBackend);
166 if(!pClassInfo || !DoCreate(pClassInfo, parent, id,
167 pos, size, style, validator, name))
168 {
169 m_imp = NULL;
170 return false;
171 }
172
173 if (!Load(location))
174 {
175 delete m_imp;
176 m_imp = NULL;
177 return false;
178 }
179
180 SetBestFittingSize(size);
181 return true;
182 }
183 else
184 {
185 wxClassInfo::sm_classTable->BeginFind();
186
187 wxClassInfo* classInfo;
188
189 while((classInfo = NextBackend()) != NULL)
190 {
191 if(!DoCreate(classInfo, parent, id,
192 pos, size, style, validator, name))
193 continue;
194
195 if (Load(location))
196 {
197 SetBestFittingSize(size);
198 return true;
199 }
200 else
201 delete m_imp;
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 //---------------------------------------------------------------------------
214 bool wxMediaCtrl::DoCreate(wxClassInfo* classInfo,
215 wxWindow* parent, wxWindowID id,
216 const wxPoint& pos,
217 const wxSize& size,
218 long style,
219 const wxValidator& validator,
220 const wxString& name)
221 {
222 m_imp = (wxMediaBackend*)classInfo->CreateObject();
223
224 if( m_imp->CreateControl(this, parent, id, pos, size,
225 style, validator, name) )
226 {
227 return true;
228 }
229
230 delete m_imp;
231 return false;
232 }
233
234 //---------------------------------------------------------------------------
235 // wxMediaCtrl::NextBackend
236 //
237 //
238 // Search through the RTTI hashmap one at a
239 // time, attempting to create each derivative
240 // of wxMediaBackend
241 //
242 //
243 // STL isn't compatible with and will have a compilation error
244 // on a wxNode, however, wxHashTable::compatibility_iterator is
245 // incompatible with the old 2.4 stable version - but since
246 // we're in 2.5 only we don't need to worry about this
247 // static
248 //---------------------------------------------------------------------------
249 wxClassInfo* 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 //---------------------------------------------------------------------------
276 wxMediaCtrl::~wxMediaCtrl()
277 {
278 if (m_imp)
279 delete m_imp;
280 }
281
282 //---------------------------------------------------------------------------
283 // wxMediaCtrl::Load (file version)
284 // wxMediaCtrl::Load (URL version)
285 // wxMediaCtrl::Load (URL & Proxy version)
286 // wxMediaCtrl::Load (wxInputStream version)
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 //---------------------------------------------------------------------------
292 bool wxMediaCtrl::Load(const wxString& fileName)
293 {
294 if(m_imp)
295 return (m_bLoaded = m_imp->Load(fileName));
296 return false;
297 }
298
299 bool wxMediaCtrl::Load(const wxURI& location)
300 {
301 if(m_imp)
302 return (m_bLoaded = m_imp->Load(location));
303 return false;
304 }
305
306 bool 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
313 //---------------------------------------------------------------------------
314 // wxMediaCtrl::Play
315 // wxMediaCtrl::Pause
316 // wxMediaCtrl::Stop
317 // wxMediaCtrl::GetPlaybackRate
318 // wxMediaCtrl::SetPlaybackRate
319 // wxMediaCtrl::Seek --> SetPosition
320 // wxMediaCtrl::Tell --> GetPosition
321 // wxMediaCtrl::Length --> GetDuration
322 // wxMediaCtrl::GetState
323 // wxMediaCtrl::DoGetBestSize
324 // wxMediaCtrl::SetVolume
325 // wxMediaCtrl::GetVolume
326 // wxMediaCtrl::ShowInterface
327 // wxMediaCtrl::GetDownloadProgress
328 // wxMediaCtrl::GetDownloadTotal
329 //
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 //---------------------------------------------------------------------------
334 bool wxMediaCtrl::Play()
335 {
336 if(m_imp && m_bLoaded)
337 return m_imp->Play();
338 return 0;
339 }
340
341 bool wxMediaCtrl::Pause()
342 {
343 if(m_imp && m_bLoaded)
344 return m_imp->Pause();
345 return 0;
346 }
347
348 bool wxMediaCtrl::Stop()
349 {
350 if(m_imp && m_bLoaded)
351 return m_imp->Stop();
352 return 0;
353 }
354
355 double wxMediaCtrl::GetPlaybackRate()
356 {
357 if(m_imp && m_bLoaded)
358 return m_imp->GetPlaybackRate();
359 return 0;
360 }
361
362 bool wxMediaCtrl::SetPlaybackRate(double dRate)
363 {
364 if(m_imp && m_bLoaded)
365 return m_imp->SetPlaybackRate(dRate);
366 return false;
367 }
368
369 wxFileOffset wxMediaCtrl::Seek(wxFileOffset where, wxSeekMode mode)
370 {
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;
390 }
391
392 wxFileOffset wxMediaCtrl::Tell()
393 {
394 if(m_imp && m_bLoaded)
395 return (wxFileOffset) m_imp->GetPosition().ToLong();
396 return wxInvalidOffset;
397 }
398
399 wxFileOffset wxMediaCtrl::Length()
400 {
401 if(m_imp && m_bLoaded)
402 return (wxFileOffset) m_imp->GetDuration().ToLong();
403 return wxInvalidOffset;
404 }
405
406 wxMediaState wxMediaCtrl::GetState()
407 {
408 if(m_imp && m_bLoaded)
409 return m_imp->GetState();
410 return wxMEDIASTATE_STOPPED;
411 }
412
413 wxSize wxMediaCtrl::DoGetBestSize() const
414 {
415 if(m_imp)
416 return m_imp->GetVideoSize();
417 return wxSize(0,0);
418 }
419
420 double wxMediaCtrl::GetVolume()
421 {
422 if(m_imp && m_bLoaded)
423 return m_imp->GetVolume();
424 return 0.0;
425 }
426
427 bool wxMediaCtrl::SetVolume(double dVolume)
428 {
429 if(m_imp && m_bLoaded)
430 return m_imp->SetVolume(dVolume);
431 return false;
432 }
433
434 bool wxMediaCtrl::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
435 {
436 if(m_imp)
437 return m_imp->ShowPlayerControls(flags);
438 return false;
439 }
440
441 wxFileOffset wxMediaCtrl::GetDownloadProgress()
442 {
443 if(m_imp && m_bLoaded)
444 return (wxFileOffset) m_imp->GetDownloadProgress().ToLong();
445 return wxInvalidOffset;
446 }
447
448 wxFileOffset wxMediaCtrl::GetDownloadTotal()
449 {
450 if(m_imp && m_bLoaded)
451 return (wxFileOffset) m_imp->GetDownloadTotal().ToLong();
452 return wxInvalidOffset;
453 }
454
455 //---------------------------------------------------------------------------
456 // wxMediaCtrl::DoMoveWindow
457 //
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 //---------------------------------------------------------------------------
463 void 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
471 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
472 //
473 // wxMediaBackendCommonBase
474 //
475 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
476
477 void 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
493 void wxMediaBackendCommonBase::NotifyMovieLoaded()
494 {
495 NotifyMovieSizeChanged();
496
497 // notify about movie being fully loaded
498 QueueEvent(wxEVT_MEDIA_LOADED);
499 }
500
501 bool wxMediaBackendCommonBase::SendStopEvent()
502 {
503 wxMediaEvent theEvent(wxEVT_MEDIA_STOP, m_ctrl->GetId());
504
505 return !m_ctrl->ProcessEvent(theEvent) || theEvent.IsAllowed();
506 }
507
508 void wxMediaBackendCommonBase::QueueEvent(wxEventType evtType)
509 {
510 wxMediaEvent theEvent(evtType, m_ctrl->GetId());
511 m_ctrl->AddPendingEvent(theEvent);
512 }
513
514 #include "wx/html/forcelnk.h"
515 FORCE_LINK(basewxmediabackends);
516
517 //---------------------------------------------------------------------------
518 // End of compilation guard and of file
519 //---------------------------------------------------------------------------
520 #endif //wxUSE_MEDIACTRL
521
522