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