File/dir dialog styles and other changes (patch 1488371):
[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 // Definitions
16 //===========================================================================
17
18 //---------------------------------------------------------------------------
19 // Pre-compiled header stuff
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 #endif
33
34 //---------------------------------------------------------------------------
35 // Includes
36 //---------------------------------------------------------------------------
37 #include "wx/mediactrl.h"
38
39 //===========================================================================
40 //
41 // Implementation
42 //
43 //===========================================================================
44
45 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
46 // RTTI and Event implementations
47 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
48
49 IMPLEMENT_CLASS(wxMediaCtrl, wxControl)
50 DEFINE_EVENT_TYPE(wxEVT_MEDIA_STATECHANGED)
51 DEFINE_EVENT_TYPE(wxEVT_MEDIA_PLAY)
52 DEFINE_EVENT_TYPE(wxEVT_MEDIA_PAUSE)
53 IMPLEMENT_CLASS(wxMediaBackend, wxObject)
54 IMPLEMENT_DYNAMIC_CLASS(wxMediaEvent, wxEvent)
55 DEFINE_EVENT_TYPE(wxEVT_MEDIA_FINISHED)
56 DEFINE_EVENT_TYPE(wxEVT_MEDIA_LOADED)
57 DEFINE_EVENT_TYPE(wxEVT_MEDIA_STOP)
58
59 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
60 //
61 // wxMediaCtrl
62 //
63 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
64
65 //---------------------------------------------------------------------------
66 // wxMediaBackend Destructor
67 //
68 // This is here because the DARWIN gcc compiler badly screwed up and
69 // needs the destructor implementation in the source
70 //---------------------------------------------------------------------------
71 wxMediaBackend::~wxMediaBackend()
72 {
73 }
74
75 //---------------------------------------------------------------------------
76 // wxMediaCtrl::Create (file version)
77 // wxMediaCtrl::Create (URL version)
78 //
79 // Searches for a backend that is installed on the system (backends
80 // starting with lower characters in the alphabet are given priority),
81 // and creates the control from it
82 //
83 // This searches by searching the global RTTI hashtable, class by class,
84 // attempting to call CreateControl on each one found that is a derivative
85 // of wxMediaBackend - if it succeeded Create returns true, otherwise
86 // it keeps iterating through the hashmap.
87 //---------------------------------------------------------------------------
88 bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id,
89 const wxString& fileName,
90 const wxPoint& pos,
91 const wxSize& size,
92 long style,
93 const wxString& szBackend,
94 const wxValidator& validator,
95 const wxString& name)
96 {
97 if(!szBackend.empty())
98 {
99 wxClassInfo* pClassInfo = wxClassInfo::FindClass(szBackend);
100
101 if(!pClassInfo || !DoCreate(pClassInfo, parent, id,
102 pos, size, style, validator, name))
103 {
104 m_imp = NULL;
105 return false;
106 }
107
108 if (!fileName.empty())
109 {
110 if (!Load(fileName))
111 {
112 delete m_imp;
113 m_imp = NULL;
114 return false;
115 }
116 }
117
118 SetBestFittingSize(size);
119 return true;
120 }
121 else
122 {
123 wxClassInfo::sm_classTable->BeginFind();
124
125 wxClassInfo* classInfo;
126
127 while((classInfo = NextBackend()) != NULL)
128 {
129 if(!DoCreate(classInfo, parent, id,
130 pos, size, style, validator, name))
131 continue;
132
133 if (!fileName.empty())
134 {
135 if (Load(fileName))
136 {
137 SetBestFittingSize(size);
138 return true;
139 }
140 else
141 delete m_imp;
142 }
143 else
144 {
145 SetBestFittingSize(size);
146 return true;
147 }
148 }
149
150 m_imp = NULL;
151 return false;
152 }
153 }
154
155 bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id,
156 const wxURI& location,
157 const wxPoint& pos,
158 const wxSize& size,
159 long style,
160 const wxString& szBackend,
161 const wxValidator& validator,
162 const wxString& name)
163 {
164 if(!szBackend.empty())
165 {
166 wxClassInfo* pClassInfo = wxClassInfo::FindClass(szBackend);
167 if(!pClassInfo || !DoCreate(pClassInfo, parent, id,
168 pos, size, style, validator, name))
169 {
170 m_imp = NULL;
171 return false;
172 }
173
174 if (!Load(location))
175 {
176 delete m_imp;
177 m_imp = NULL;
178 return false;
179 }
180
181 SetBestFittingSize(size);
182 return true;
183 }
184 else
185 {
186 wxClassInfo::sm_classTable->BeginFind();
187
188 wxClassInfo* classInfo;
189
190 while((classInfo = NextBackend()) != NULL)
191 {
192 if(!DoCreate(classInfo, parent, id,
193 pos, size, style, validator, name))
194 continue;
195
196 if (Load(location))
197 {
198 SetBestFittingSize(size);
199 return true;
200 }
201 else
202 delete m_imp;
203 }
204
205 m_imp = NULL;
206 return false;
207 }
208 }
209
210 //---------------------------------------------------------------------------
211 // wxMediaCtrl::DoCreate
212 //
213 // Attempts to create the control from a backend
214 //---------------------------------------------------------------------------
215 bool wxMediaCtrl::DoCreate(wxClassInfo* classInfo,
216 wxWindow* parent, wxWindowID id,
217 const wxPoint& pos,
218 const wxSize& size,
219 long style,
220 const wxValidator& validator,
221 const wxString& name)
222 {
223 m_imp = (wxMediaBackend*)classInfo->CreateObject();
224
225 if( m_imp->CreateControl(this, parent, id, pos, size,
226 style, validator, name) )
227 {
228 return true;
229 }
230
231 delete m_imp;
232 return false;
233 }
234
235 //---------------------------------------------------------------------------
236 // wxMediaCtrl::NextBackend (static)
237 //
238 //
239 // Search through the RTTI hashmap one at a
240 // time, attempting to create each derivative
241 // of wxMediaBackend
242 //
243 //
244 // STL isn't compatible with and will have a compilation error
245 // on a wxNode, however, wxHashTable::compatibility_iterator is
246 // incompatible with the old 2.4 stable version - but since
247 // we're in 2.5+ only we don't need to worry about the new version
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 // wxMediaCtrl::MacVisibilityChanged
473 //---------------------------------------------------------------------------
474 #ifdef __WXMAC__
475 void wxMediaCtrl::MacVisibilityChanged()
476 {
477 wxControl::MacVisibilityChanged();
478
479 if(m_imp)
480 m_imp->MacVisibilityChanged();
481 }
482 #endif
483
484 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
485 //
486 // wxMediaBackendCommonBase
487 //
488 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
489
490 void wxMediaBackendCommonBase::NotifyMovieSizeChanged()
491 {
492 // our best size changed after opening a new file
493 m_ctrl->InvalidateBestSize();
494 m_ctrl->SetSize(m_ctrl->GetSize());
495
496 // if the parent of the control has a sizer ask it to refresh our size
497 wxWindow * const parent = m_ctrl->GetParent();
498 if ( parent->GetSizer() )
499 {
500 m_ctrl->GetParent()->Layout();
501 m_ctrl->GetParent()->Refresh();
502 m_ctrl->GetParent()->Update();
503 }
504 }
505
506 void wxMediaBackendCommonBase::NotifyMovieLoaded()
507 {
508 NotifyMovieSizeChanged();
509
510 // notify about movie being fully loaded
511 QueueEvent(wxEVT_MEDIA_LOADED);
512 }
513
514 bool wxMediaBackendCommonBase::SendStopEvent()
515 {
516 wxMediaEvent theEvent(wxEVT_MEDIA_STOP, m_ctrl->GetId());
517
518 return !m_ctrl->ProcessEvent(theEvent) || theEvent.IsAllowed();
519 }
520
521 void wxMediaBackendCommonBase::QueueEvent(wxEventType evtType)
522 {
523 wxMediaEvent theEvent(evtType, m_ctrl->GetId());
524 m_ctrl->AddPendingEvent(theEvent);
525 }
526
527 void wxMediaBackendCommonBase::QueuePlayEvent()
528 {
529 QueueEvent(wxEVT_MEDIA_STATECHANGED);
530 QueueEvent(wxEVT_MEDIA_PLAY);
531 }
532
533 void wxMediaBackendCommonBase::QueuePauseEvent()
534 {
535 QueueEvent(wxEVT_MEDIA_STATECHANGED);
536 QueueEvent(wxEVT_MEDIA_PAUSE);
537 }
538
539 void wxMediaBackendCommonBase::QueueStopEvent()
540 {
541 QueueEvent(wxEVT_MEDIA_STATECHANGED);
542 QueueEvent(wxEVT_MEDIA_STOP);
543 }
544
545
546 //
547 // Force link default backends in -
548 // see http://wiki.wxwidgets.org/wiki.pl?RTTI
549 //
550 #include "wx/html/forcelnk.h"
551
552 #ifdef __WXMSW__ // MSW has huge backends so we do it seperately
553 FORCE_LINK(wxmediabackend_am)
554 FORCE_LINK(wxmediabackend_wmp10)
555 #else
556 FORCE_LINK(basewxmediabackends)
557 #endif
558
559 #endif //wxUSE_MEDIACTRL