replace wxDocument::GetPrintableName(wxString&) and wxDocManager::MakeDefaultName...
[wxWidgets.git] / src / common / mediactrlcmn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/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 // Declarations
16 //===========================================================================
17
18 //---------------------------------------------------------------------------
19 // Includes
20 //---------------------------------------------------------------------------
21
22 #include "wx/wxprec.h"
23
24 #ifdef __BORLANDC__
25 #pragma hdrstop
26 #endif
27
28 #if wxUSE_MEDIACTRL
29
30 #ifndef WX_PRECOMP
31 #include "wx/hash.h"
32 #include "wx/log.h"
33 #endif
34
35 #include "wx/mediactrl.h"
36
37 //===========================================================================
38 //
39 // Implementation
40 //
41 //===========================================================================
42
43 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
44 // RTTI and Event implementations
45 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
46
47 IMPLEMENT_CLASS(wxMediaCtrl, wxControl)
48 DEFINE_EVENT_TYPE(wxEVT_MEDIA_STATECHANGED)
49 DEFINE_EVENT_TYPE(wxEVT_MEDIA_PLAY)
50 DEFINE_EVENT_TYPE(wxEVT_MEDIA_PAUSE)
51 IMPLEMENT_CLASS(wxMediaBackend, wxObject)
52 IMPLEMENT_DYNAMIC_CLASS(wxMediaEvent, wxEvent)
53 DEFINE_EVENT_TYPE(wxEVT_MEDIA_FINISHED)
54 DEFINE_EVENT_TYPE(wxEVT_MEDIA_LOADED)
55 DEFINE_EVENT_TYPE(wxEVT_MEDIA_STOP)
56
57 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
58 //
59 // wxMediaCtrl
60 //
61 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
62
63 //---------------------------------------------------------------------------
64 // wxMediaBackend Destructor
65 //
66 // This is here because the DARWIN gcc compiler badly screwed up and
67 // needs the destructor implementation in the source
68 //---------------------------------------------------------------------------
69 wxMediaBackend::~wxMediaBackend()
70 {
71 }
72
73 //---------------------------------------------------------------------------
74 // wxMediaCtrl::Create (file version)
75 // wxMediaCtrl::Create (URL version)
76 //
77 // Searches for a backend that is installed on the system (backends
78 // starting with lower characters in the alphabet are given priority),
79 // and creates the control from it
80 //
81 // This searches by searching the global RTTI hashtable, class by class,
82 // attempting to call CreateControl on each one found that is a derivative
83 // of wxMediaBackend - if it succeeded Create returns true, otherwise
84 // it keeps iterating through the hashmap.
85 //---------------------------------------------------------------------------
86 bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id,
87 const wxString& fileName,
88 const wxPoint& pos,
89 const wxSize& size,
90 long style,
91 const wxString& szBackend,
92 const wxValidator& validator,
93 const wxString& name)
94 {
95 if(!szBackend.empty())
96 {
97 wxClassInfo* pClassInfo = wxClassInfo::FindClass(szBackend);
98
99 if(!pClassInfo || !DoCreate(pClassInfo, parent, id,
100 pos, size, style, validator, name))
101 {
102 m_imp = NULL;
103 return false;
104 }
105
106 if (!fileName.empty())
107 {
108 if (!Load(fileName))
109 {
110 delete m_imp;
111 m_imp = NULL;
112 return false;
113 }
114 }
115
116 SetInitialSize(size);
117 return true;
118 }
119 else
120 {
121 wxClassInfo::const_iterator it = wxClassInfo::begin_classinfo();
122
123 const wxClassInfo* classInfo;
124
125 while((classInfo = NextBackend(&it)) != NULL)
126 {
127 wxLogMessage( classInfo->GetClassName() );
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 SetInitialSize(size);
137 return true;
138 }
139 else
140 delete m_imp;
141 }
142 else
143 {
144 SetInitialSize(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 SetInitialSize(size);
181 return true;
182 }
183 else
184 {
185 wxClassInfo::const_iterator it = wxClassInfo::begin_classinfo();
186
187 const wxClassInfo* classInfo;
188
189 while((classInfo = NextBackend(&it)) != NULL)
190 {
191 if(!DoCreate(classInfo, parent, id,
192 pos, size, style, validator, name))
193 continue;
194
195 if (Load(location))
196 {
197 SetInitialSize(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(const 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 (static)
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 the new version
247 //---------------------------------------------------------------------------
248 const wxClassInfo* wxMediaCtrl::NextBackend(wxClassInfo::const_iterator* it)
249 {
250 for ( wxClassInfo::const_iterator end = wxClassInfo::end_classinfo();
251 *it != end; ++(*it) )
252 {
253 const wxClassInfo* classInfo = **it;
254 if ( classInfo->IsKindOf(CLASSINFO(wxMediaBackend)) &&
255 classInfo != CLASSINFO(wxMediaBackend) )
256 {
257 return classInfo;
258 }
259 }
260
261 //
262 // Nope - couldn't successfully find one... fail
263 //
264 return NULL;
265 }
266
267
268 //---------------------------------------------------------------------------
269 // wxMediaCtrl Destructor
270 //
271 // Free up the backend if it exists
272 //---------------------------------------------------------------------------
273 wxMediaCtrl::~wxMediaCtrl()
274 {
275 if (m_imp)
276 delete m_imp;
277 }
278
279 //---------------------------------------------------------------------------
280 // wxMediaCtrl::Load (file version)
281 // wxMediaCtrl::Load (URL version)
282 // wxMediaCtrl::Load (URL & Proxy version)
283 // wxMediaCtrl::Load (wxInputStream version)
284 //
285 // Here we call load of the backend - keeping
286 // track of whether it was successful or not - which
287 // will determine which later method calls work
288 //---------------------------------------------------------------------------
289 bool wxMediaCtrl::Load(const wxString& fileName)
290 {
291 if(m_imp)
292 return (m_bLoaded = m_imp->Load(fileName));
293 return false;
294 }
295
296 bool wxMediaCtrl::Load(const wxURI& location)
297 {
298 if(m_imp)
299 return (m_bLoaded = m_imp->Load(location));
300 return false;
301 }
302
303 bool wxMediaCtrl::Load(const wxURI& location, const wxURI& proxy)
304 {
305 if(m_imp)
306 return (m_bLoaded = m_imp->Load(location, proxy));
307 return false;
308 }
309
310 //---------------------------------------------------------------------------
311 // wxMediaCtrl::Play
312 // wxMediaCtrl::Pause
313 // wxMediaCtrl::Stop
314 // wxMediaCtrl::GetPlaybackRate
315 // wxMediaCtrl::SetPlaybackRate
316 // wxMediaCtrl::Seek --> SetPosition
317 // wxMediaCtrl::Tell --> GetPosition
318 // wxMediaCtrl::Length --> GetDuration
319 // wxMediaCtrl::GetState
320 // wxMediaCtrl::DoGetBestSize
321 // wxMediaCtrl::SetVolume
322 // wxMediaCtrl::GetVolume
323 // wxMediaCtrl::ShowInterface
324 // wxMediaCtrl::GetDownloadProgress
325 // wxMediaCtrl::GetDownloadTotal
326 //
327 // 1) Check to see whether the backend exists and is loading
328 // 2) Call the backend's version of the method, returning success
329 // if the backend's version succeeds
330 //---------------------------------------------------------------------------
331 bool wxMediaCtrl::Play()
332 {
333 if(m_imp && m_bLoaded)
334 return m_imp->Play();
335 return 0;
336 }
337
338 bool wxMediaCtrl::Pause()
339 {
340 if(m_imp && m_bLoaded)
341 return m_imp->Pause();
342 return 0;
343 }
344
345 bool wxMediaCtrl::Stop()
346 {
347 if(m_imp && m_bLoaded)
348 return m_imp->Stop();
349 return 0;
350 }
351
352 double wxMediaCtrl::GetPlaybackRate()
353 {
354 if(m_imp && m_bLoaded)
355 return m_imp->GetPlaybackRate();
356 return 0;
357 }
358
359 bool wxMediaCtrl::SetPlaybackRate(double dRate)
360 {
361 if(m_imp && m_bLoaded)
362 return m_imp->SetPlaybackRate(dRate);
363 return false;
364 }
365
366 wxFileOffset wxMediaCtrl::Seek(wxFileOffset where, wxSeekMode mode)
367 {
368 wxFileOffset offset;
369
370 switch (mode)
371 {
372 case wxFromStart:
373 offset = where;
374 break;
375 case wxFromEnd:
376 offset = Length() - where;
377 break;
378 // case wxFromCurrent:
379 default:
380 offset = Tell() + where;
381 break;
382 }
383
384 if(m_imp && m_bLoaded && m_imp->SetPosition(offset))
385 return offset;
386 return wxInvalidOffset;
387 }
388
389 wxFileOffset wxMediaCtrl::Tell()
390 {
391 if(m_imp && m_bLoaded)
392 return (wxFileOffset) m_imp->GetPosition().ToLong();
393 return wxInvalidOffset;
394 }
395
396 wxFileOffset wxMediaCtrl::Length()
397 {
398 if(m_imp && m_bLoaded)
399 return (wxFileOffset) m_imp->GetDuration().ToLong();
400 return wxInvalidOffset;
401 }
402
403 wxMediaState wxMediaCtrl::GetState()
404 {
405 if(m_imp && m_bLoaded)
406 return m_imp->GetState();
407 return wxMEDIASTATE_STOPPED;
408 }
409
410 wxSize wxMediaCtrl::DoGetBestSize() const
411 {
412 if(m_imp)
413 return m_imp->GetVideoSize();
414 return wxSize(0,0);
415 }
416
417 double wxMediaCtrl::GetVolume()
418 {
419 if(m_imp && m_bLoaded)
420 return m_imp->GetVolume();
421 return 0.0;
422 }
423
424 bool wxMediaCtrl::SetVolume(double dVolume)
425 {
426 if(m_imp && m_bLoaded)
427 return m_imp->SetVolume(dVolume);
428 return false;
429 }
430
431 bool wxMediaCtrl::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
432 {
433 if(m_imp)
434 return m_imp->ShowPlayerControls(flags);
435 return false;
436 }
437
438 wxFileOffset wxMediaCtrl::GetDownloadProgress()
439 {
440 if(m_imp && m_bLoaded)
441 return (wxFileOffset) m_imp->GetDownloadProgress().ToLong();
442 return wxInvalidOffset;
443 }
444
445 wxFileOffset wxMediaCtrl::GetDownloadTotal()
446 {
447 if(m_imp && m_bLoaded)
448 return (wxFileOffset) m_imp->GetDownloadTotal().ToLong();
449 return wxInvalidOffset;
450 }
451
452 //---------------------------------------------------------------------------
453 // wxMediaCtrl::DoMoveWindow
454 //
455 // 1) Call parent's version so that our control's window moves where
456 // it's supposed to
457 // 2) If the backend exists and is loaded, move the video
458 // of the media to where our control's window is now located
459 //---------------------------------------------------------------------------
460 void wxMediaCtrl::DoMoveWindow(int x, int y, int w, int h)
461 {
462 wxControl::DoMoveWindow(x,y,w,h);
463
464 if(m_imp)
465 m_imp->Move(x, y, w, h);
466 }
467
468 //---------------------------------------------------------------------------
469 // wxMediaCtrl::MacVisibilityChanged
470 //---------------------------------------------------------------------------
471 #ifdef __WXMAC__
472 void wxMediaCtrl::MacVisibilityChanged()
473 {
474 wxControl::MacVisibilityChanged();
475
476 if(m_imp)
477 m_imp->MacVisibilityChanged();
478 }
479 #endif
480
481 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
482 //
483 // wxMediaBackendCommonBase
484 //
485 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
486
487 void wxMediaBackendCommonBase::NotifyMovieSizeChanged()
488 {
489 // our best size changed after opening a new file
490 m_ctrl->InvalidateBestSize();
491 m_ctrl->SetSize(m_ctrl->GetSize());
492
493 // if the parent of the control has a sizer ask it to refresh our size
494 wxWindow * const parent = m_ctrl->GetParent();
495 if ( parent->GetSizer() )
496 {
497 m_ctrl->GetParent()->Layout();
498 m_ctrl->GetParent()->Refresh();
499 m_ctrl->GetParent()->Update();
500 }
501 }
502
503 void wxMediaBackendCommonBase::NotifyMovieLoaded()
504 {
505 NotifyMovieSizeChanged();
506
507 // notify about movie being fully loaded
508 QueueEvent(wxEVT_MEDIA_LOADED);
509 }
510
511 bool wxMediaBackendCommonBase::SendStopEvent()
512 {
513 wxMediaEvent theEvent(wxEVT_MEDIA_STOP, m_ctrl->GetId());
514
515 return !m_ctrl->ProcessEvent(theEvent) || theEvent.IsAllowed();
516 }
517
518 void wxMediaBackendCommonBase::QueueEvent(wxEventType evtType)
519 {
520 wxMediaEvent theEvent(evtType, m_ctrl->GetId());
521 m_ctrl->AddPendingEvent(theEvent);
522 }
523
524 void wxMediaBackendCommonBase::QueuePlayEvent()
525 {
526 QueueEvent(wxEVT_MEDIA_STATECHANGED);
527 QueueEvent(wxEVT_MEDIA_PLAY);
528 }
529
530 void wxMediaBackendCommonBase::QueuePauseEvent()
531 {
532 QueueEvent(wxEVT_MEDIA_STATECHANGED);
533 QueueEvent(wxEVT_MEDIA_PAUSE);
534 }
535
536 void wxMediaBackendCommonBase::QueueStopEvent()
537 {
538 QueueEvent(wxEVT_MEDIA_STATECHANGED);
539 QueueEvent(wxEVT_MEDIA_STOP);
540 }
541
542
543 //
544 // Force link default backends in -
545 // see http://wiki.wxwidgets.org/wiki.pl?RTTI
546 //
547 #include "wx/html/forcelnk.h"
548
549 #ifdef __WXMSW__ // MSW has huge backends so we do it seperately
550 FORCE_LINK(wxmediabackend_am)
551 FORCE_LINK(wxmediabackend_wmp10)
552 #else
553 FORCE_LINK(basewxmediabackends)
554 #endif
555
556 #endif //wxUSE_MEDIACTRL