Ryan's cumulative wxActiveX and media control patch (1427775)
[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 // TODO: Platform specific backend defaults?
13
14 //===========================================================================
15 // Definitions
16 //===========================================================================
17
18 //---------------------------------------------------------------------------
19 // Pre-compiled header stuff
20 //---------------------------------------------------------------------------
21
22 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
23 #pragma implementation "mediactrl.h"
24 #endif
25
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
46 //
47 //===========================================================================
48
49 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
50 // RTTI and Event implementations
51 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
52
53 IMPLEMENT_CLASS(wxMediaCtrl, wxControl);
54 DEFINE_EVENT_TYPE(wxEVT_MEDIA_STATECHANGED)
55 DEFINE_EVENT_TYPE(wxEVT_MEDIA_PLAY)
56 DEFINE_EVENT_TYPE(wxEVT_MEDIA_PAUSE)
57 IMPLEMENT_CLASS(wxMediaBackend, wxObject);
58 IMPLEMENT_DYNAMIC_CLASS(wxMediaEvent, wxEvent);
59 DEFINE_EVENT_TYPE(wxEVT_MEDIA_FINISHED);
60 DEFINE_EVENT_TYPE(wxEVT_MEDIA_LOADED);
61 DEFINE_EVENT_TYPE(wxEVT_MEDIA_STOP);
62
63 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
64 //
65 // wxMediaCtrl
66 //
67 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
68
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 //---------------------------------------------------------------------------
75 wxMediaBackend::~wxMediaBackend()
76 {
77 }
78
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
86 //
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
89 // of wxMediaBackend - if it succeeded Create returns true, otherwise
90 // it keeps iterating through the hashmap.
91 //---------------------------------------------------------------------------
92 bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id,
93 const wxString& fileName,
94 const wxPoint& pos,
95 const wxSize& size,
96 long style,
97 const wxString& szBackend,
98 const wxValidator& validator,
99 const wxString& name)
100 {
101 if(!szBackend.empty())
102 {
103 wxClassInfo* pClassInfo = wxClassInfo::FindClass(szBackend);
104
105 if(!pClassInfo || !DoCreate(pClassInfo, parent, id,
106 pos, size, style, validator, name))
107 {
108 m_imp = NULL;
109 return false;
110 }
111
112 if (!fileName.empty())
113 {
114 if (!Load(fileName))
115 {
116 delete m_imp;
117 m_imp = NULL;
118 return false;
119 }
120 }
121
122 SetBestFittingSize(size);
123 return true;
124 }
125 else
126 {
127 wxClassInfo::sm_classTable->BeginFind();
128
129 wxClassInfo* classInfo;
130
131 while((classInfo = NextBackend()) != NULL)
132 {
133 if(!DoCreate(classInfo, parent, id,
134 pos, size, style, validator, name))
135 continue;
136
137 if (!fileName.empty())
138 {
139 if (Load(fileName))
140 {
141 SetBestFittingSize(size);
142 return true;
143 }
144 else
145 delete m_imp;
146 }
147 else
148 {
149 SetBestFittingSize(size);
150 return true;
151 }
152 }
153
154 m_imp = NULL;
155 return false;
156 }
157 }
158
159 bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id,
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)
167 {
168 if(!szBackend.empty())
169 {
170 wxClassInfo* pClassInfo = wxClassInfo::FindClass(szBackend);
171 if(!pClassInfo || !DoCreate(pClassInfo, parent, id,
172 pos, size, style, validator, name))
173 {
174 m_imp = NULL;
175 return false;
176 }
177
178 if (!Load(location))
179 {
180 delete m_imp;
181 m_imp = NULL;
182 return false;
183 }
184
185 SetBestFittingSize(size);
186 return true;
187 }
188 else
189 {
190 wxClassInfo::sm_classTable->BeginFind();
191
192 wxClassInfo* classInfo;
193
194 while((classInfo = NextBackend()) != NULL)
195 {
196 if(!DoCreate(classInfo, parent, id,
197 pos, size, style, validator, name))
198 continue;
199
200 if (Load(location))
201 {
202 SetBestFittingSize(size);
203 return true;
204 }
205 else
206 delete m_imp;
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 //---------------------------------------------------------------------------
219 bool wxMediaCtrl::DoCreate(wxClassInfo* classInfo,
220 wxWindow* parent, wxWindowID id,
221 const wxPoint& pos,
222 const wxSize& size,
223 long style,
224 const wxValidator& validator,
225 const wxString& name)
226 {
227 m_imp = (wxMediaBackend*)classInfo->CreateObject();
228
229 if( m_imp->CreateControl(this, parent, id, pos, size,
230 style, validator, name) )
231 {
232 return true;
233 }
234
235 delete m_imp;
236 return false;
237 }
238
239 //---------------------------------------------------------------------------
240 // wxMediaCtrl::NextBackend (static)
241 //
242 //
243 // Search through the RTTI hashmap one at a
244 // time, attempting to create each derivative
245 // of wxMediaBackend
246 //
247 //
248 // STL isn't compatible with and will have a compilation error
249 // on a wxNode, however, wxHashTable::compatibility_iterator is
250 // incompatible with the old 2.4 stable version - but since
251 // we're in 2.5+ only we don't need to worry about the new version
252 //---------------------------------------------------------------------------
253 wxClassInfo* 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 //---------------------------------------------------------------------------
280 wxMediaCtrl::~wxMediaCtrl()
281 {
282 if (m_imp)
283 delete m_imp;
284 }
285
286 //---------------------------------------------------------------------------
287 // wxMediaCtrl::Load (file version)
288 // wxMediaCtrl::Load (URL version)
289 // wxMediaCtrl::Load (URL & Proxy version)
290 // wxMediaCtrl::Load (wxInputStream version)
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 //---------------------------------------------------------------------------
296 bool wxMediaCtrl::Load(const wxString& fileName)
297 {
298 if(m_imp)
299 return (m_bLoaded = m_imp->Load(fileName));
300 return false;
301 }
302
303 bool wxMediaCtrl::Load(const wxURI& location)
304 {
305 if(m_imp)
306 return (m_bLoaded = m_imp->Load(location));
307 return false;
308 }
309
310 bool 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
317 //---------------------------------------------------------------------------
318 // wxMediaCtrl::Play
319 // wxMediaCtrl::Pause
320 // wxMediaCtrl::Stop
321 // wxMediaCtrl::GetPlaybackRate
322 // wxMediaCtrl::SetPlaybackRate
323 // wxMediaCtrl::Seek --> SetPosition
324 // wxMediaCtrl::Tell --> GetPosition
325 // wxMediaCtrl::Length --> GetDuration
326 // wxMediaCtrl::GetState
327 // wxMediaCtrl::DoGetBestSize
328 // wxMediaCtrl::SetVolume
329 // wxMediaCtrl::GetVolume
330 // wxMediaCtrl::ShowInterface
331 // wxMediaCtrl::GetDownloadProgress
332 // wxMediaCtrl::GetDownloadTotal
333 //
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 //---------------------------------------------------------------------------
338 bool wxMediaCtrl::Play()
339 {
340 if(m_imp && m_bLoaded)
341 return m_imp->Play();
342 return 0;
343 }
344
345 bool wxMediaCtrl::Pause()
346 {
347 if(m_imp && m_bLoaded)
348 return m_imp->Pause();
349 return 0;
350 }
351
352 bool wxMediaCtrl::Stop()
353 {
354 if(m_imp && m_bLoaded)
355 return m_imp->Stop();
356 return 0;
357 }
358
359 double wxMediaCtrl::GetPlaybackRate()
360 {
361 if(m_imp && m_bLoaded)
362 return m_imp->GetPlaybackRate();
363 return 0;
364 }
365
366 bool wxMediaCtrl::SetPlaybackRate(double dRate)
367 {
368 if(m_imp && m_bLoaded)
369 return m_imp->SetPlaybackRate(dRate);
370 return false;
371 }
372
373 wxFileOffset wxMediaCtrl::Seek(wxFileOffset where, wxSeekMode mode)
374 {
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;
394 }
395
396 wxFileOffset wxMediaCtrl::Tell()
397 {
398 if(m_imp && m_bLoaded)
399 return (wxFileOffset) m_imp->GetPosition().ToLong();
400 return wxInvalidOffset;
401 }
402
403 wxFileOffset wxMediaCtrl::Length()
404 {
405 if(m_imp && m_bLoaded)
406 return (wxFileOffset) m_imp->GetDuration().ToLong();
407 return wxInvalidOffset;
408 }
409
410 wxMediaState wxMediaCtrl::GetState()
411 {
412 if(m_imp && m_bLoaded)
413 return m_imp->GetState();
414 return wxMEDIASTATE_STOPPED;
415 }
416
417 wxSize wxMediaCtrl::DoGetBestSize() const
418 {
419 if(m_imp)
420 return m_imp->GetVideoSize();
421 return wxSize(0,0);
422 }
423
424 double wxMediaCtrl::GetVolume()
425 {
426 if(m_imp && m_bLoaded)
427 return m_imp->GetVolume();
428 return 0.0;
429 }
430
431 bool wxMediaCtrl::SetVolume(double dVolume)
432 {
433 if(m_imp && m_bLoaded)
434 return m_imp->SetVolume(dVolume);
435 return false;
436 }
437
438 bool wxMediaCtrl::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
439 {
440 if(m_imp)
441 return m_imp->ShowPlayerControls(flags);
442 return false;
443 }
444
445 wxFileOffset wxMediaCtrl::GetDownloadProgress()
446 {
447 if(m_imp && m_bLoaded)
448 return (wxFileOffset) m_imp->GetDownloadProgress().ToLong();
449 return wxInvalidOffset;
450 }
451
452 wxFileOffset wxMediaCtrl::GetDownloadTotal()
453 {
454 if(m_imp && m_bLoaded)
455 return (wxFileOffset) m_imp->GetDownloadTotal().ToLong();
456 return wxInvalidOffset;
457 }
458
459 //---------------------------------------------------------------------------
460 // wxMediaCtrl::DoMoveWindow
461 //
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 //---------------------------------------------------------------------------
467 void 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
475 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
476 //
477 // wxMediaBackendCommonBase
478 //
479 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
480
481 void 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
497 void wxMediaBackendCommonBase::NotifyMovieLoaded()
498 {
499 NotifyMovieSizeChanged();
500
501 // notify about movie being fully loaded
502 QueueEvent(wxEVT_MEDIA_LOADED);
503 }
504
505 bool wxMediaBackendCommonBase::SendStopEvent()
506 {
507 wxMediaEvent theEvent(wxEVT_MEDIA_STOP, m_ctrl->GetId());
508
509 return !m_ctrl->ProcessEvent(theEvent) || theEvent.IsAllowed();
510 }
511
512 void wxMediaBackendCommonBase::QueueEvent(wxEventType evtType)
513 {
514 wxMediaEvent theEvent(evtType, m_ctrl->GetId());
515 m_ctrl->AddPendingEvent(theEvent);
516 }
517
518 void wxMediaBackendCommonBase::QueuePlayEvent()
519 {
520 QueueEvent(wxEVT_MEDIA_STATECHANGED);
521 QueueEvent(wxEVT_MEDIA_PLAY);
522 }
523
524 void wxMediaBackendCommonBase::QueuePauseEvent()
525 {
526 QueueEvent(wxEVT_MEDIA_STATECHANGED);
527 QueueEvent(wxEVT_MEDIA_PAUSE);
528 }
529
530 void 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 //
541 #include "wx/html/forcelnk.h"
542
543 #ifdef __WXMSW__ // MSW has huge backends so we do it seperately
544 FORCE_LINK(wxmediabackend_am);
545 FORCE_LINK(wxmediabackend_wmp10);
546 #else
547 FORCE_LINK(basewxmediabackends);
548 #endif
549 //---------------------------------------------------------------------------
550 // End of compilation guard and of file
551 //---------------------------------------------------------------------------
552 #endif //wxUSE_MEDIACTRL
553
554