]> git.saurik.com Git - wxWidgets.git/blob - src/common/mediactrlcmn.cpp
Add some asserts to ensure cols and rows are >= 0 to avoid crashes
[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 wxDEFINE_EVENT( wxEVT_MEDIA_STATECHANGED, wxMediaEvent );
49 wxDEFINE_EVENT( wxEVT_MEDIA_PLAY, wxMediaEvent );
50 wxDEFINE_EVENT( wxEVT_MEDIA_PAUSE, wxMediaEvent );
51 IMPLEMENT_CLASS(wxMediaBackend, wxObject)
52 IMPLEMENT_DYNAMIC_CLASS(wxMediaEvent, wxEvent)
53 wxDEFINE_EVENT( wxEVT_MEDIA_FINISHED, wxMediaEvent );
54 wxDEFINE_EVENT( wxEVT_MEDIA_LOADED, wxMediaEvent );
55 wxDEFINE_EVENT( wxEVT_MEDIA_STOP, wxMediaEvent );
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 wxDELETE(m_imp);
111 return false;
112 }
113 }
114
115 SetInitialSize(size);
116 return true;
117 }
118 else
119 {
120 wxClassInfo::const_iterator it = wxClassInfo::begin_classinfo();
121
122 const wxClassInfo* classInfo;
123
124 while((classInfo = NextBackend(&it)) != NULL)
125 {
126 if(!DoCreate(classInfo, parent, id,
127 pos, size, style, validator, name))
128 continue;
129
130 if (!fileName.empty())
131 {
132 if (Load(fileName))
133 {
134 SetInitialSize(size);
135 return true;
136 }
137 else
138 delete m_imp;
139 }
140 else
141 {
142 SetInitialSize(size);
143 return true;
144 }
145 }
146
147 m_imp = NULL;
148 return false;
149 }
150 }
151
152 bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id,
153 const wxURI& location,
154 const wxPoint& pos,
155 const wxSize& size,
156 long style,
157 const wxString& szBackend,
158 const wxValidator& validator,
159 const wxString& name)
160 {
161 if(!szBackend.empty())
162 {
163 wxClassInfo* pClassInfo = wxClassInfo::FindClass(szBackend);
164 if(!pClassInfo || !DoCreate(pClassInfo, parent, id,
165 pos, size, style, validator, name))
166 {
167 m_imp = NULL;
168 return false;
169 }
170
171 if (!Load(location))
172 {
173 wxDELETE(m_imp);
174 return false;
175 }
176
177 SetInitialSize(size);
178 return true;
179 }
180 else
181 {
182 wxClassInfo::const_iterator it = wxClassInfo::begin_classinfo();
183
184 const wxClassInfo* classInfo;
185
186 while((classInfo = NextBackend(&it)) != NULL)
187 {
188 if(!DoCreate(classInfo, parent, id,
189 pos, size, style, validator, name))
190 continue;
191
192 if (Load(location))
193 {
194 SetInitialSize(size);
195 return true;
196 }
197 else
198 delete m_imp;
199 }
200
201 m_imp = NULL;
202 return false;
203 }
204 }
205
206 //---------------------------------------------------------------------------
207 // wxMediaCtrl::DoCreate
208 //
209 // Attempts to create the control from a backend
210 //---------------------------------------------------------------------------
211 bool wxMediaCtrl::DoCreate(const wxClassInfo* classInfo,
212 wxWindow* parent, wxWindowID id,
213 const wxPoint& pos,
214 const wxSize& size,
215 long style,
216 const wxValidator& validator,
217 const wxString& name)
218 {
219 m_imp = (wxMediaBackend*)classInfo->CreateObject();
220
221 if( m_imp->CreateControl(this, parent, id, pos, size,
222 style, validator, name) )
223 {
224 return true;
225 }
226
227 delete m_imp;
228 return false;
229 }
230
231 //---------------------------------------------------------------------------
232 // wxMediaCtrl::NextBackend (static)
233 //
234 //
235 // Search through the RTTI hashmap one at a
236 // time, attempting to create each derivative
237 // of wxMediaBackend
238 //
239 //
240 // STL isn't compatible with and will have a compilation error
241 // on a wxNode, however, wxHashTable::compatibility_iterator is
242 // incompatible with the old 2.4 stable version - but since
243 // we're in 2.5+ only we don't need to worry about the new version
244 //---------------------------------------------------------------------------
245 const wxClassInfo* wxMediaCtrl::NextBackend(wxClassInfo::const_iterator* it)
246 {
247 for ( wxClassInfo::const_iterator end = wxClassInfo::end_classinfo();
248 *it != end; ++(*it) )
249 {
250 const wxClassInfo* classInfo = **it;
251 if ( classInfo->IsKindOf(CLASSINFO(wxMediaBackend)) &&
252 classInfo != CLASSINFO(wxMediaBackend) )
253 {
254 ++(*it);
255 return classInfo;
256 }
257 }
258
259 //
260 // Nope - couldn't successfully find one... fail
261 //
262 return NULL;
263 }
264
265
266 //---------------------------------------------------------------------------
267 // wxMediaCtrl Destructor
268 //
269 // Free up the backend if it exists
270 //---------------------------------------------------------------------------
271 wxMediaCtrl::~wxMediaCtrl()
272 {
273 if (m_imp)
274 delete m_imp;
275 }
276
277 //---------------------------------------------------------------------------
278 // wxMediaCtrl::Load (file version)
279 // wxMediaCtrl::Load (URL version)
280 // wxMediaCtrl::Load (URL & Proxy version)
281 // wxMediaCtrl::Load (wxInputStream version)
282 //
283 // Here we call load of the backend - keeping
284 // track of whether it was successful or not - which
285 // will determine which later method calls work
286 //---------------------------------------------------------------------------
287 bool wxMediaCtrl::Load(const wxString& fileName)
288 {
289 if(m_imp)
290 return (m_bLoaded = m_imp->Load(fileName));
291 return false;
292 }
293
294 bool wxMediaCtrl::Load(const wxURI& location)
295 {
296 if(m_imp)
297 return (m_bLoaded = m_imp->Load(location));
298 return false;
299 }
300
301 bool wxMediaCtrl::Load(const wxURI& location, const wxURI& proxy)
302 {
303 if(m_imp)
304 return (m_bLoaded = m_imp->Load(location, proxy));
305 return false;
306 }
307
308 //---------------------------------------------------------------------------
309 // wxMediaCtrl::Play
310 // wxMediaCtrl::Pause
311 // wxMediaCtrl::Stop
312 // wxMediaCtrl::GetPlaybackRate
313 // wxMediaCtrl::SetPlaybackRate
314 // wxMediaCtrl::Seek --> SetPosition
315 // wxMediaCtrl::Tell --> GetPosition
316 // wxMediaCtrl::Length --> GetDuration
317 // wxMediaCtrl::GetState
318 // wxMediaCtrl::DoGetBestSize
319 // wxMediaCtrl::SetVolume
320 // wxMediaCtrl::GetVolume
321 // wxMediaCtrl::ShowInterface
322 // wxMediaCtrl::GetDownloadProgress
323 // wxMediaCtrl::GetDownloadTotal
324 //
325 // 1) Check to see whether the backend exists and is loading
326 // 2) Call the backend's version of the method, returning success
327 // if the backend's version succeeds
328 //---------------------------------------------------------------------------
329 bool wxMediaCtrl::Play()
330 {
331 if(m_imp && m_bLoaded)
332 return m_imp->Play();
333 return 0;
334 }
335
336 bool wxMediaCtrl::Pause()
337 {
338 if(m_imp && m_bLoaded)
339 return m_imp->Pause();
340 return 0;
341 }
342
343 bool wxMediaCtrl::Stop()
344 {
345 if(m_imp && m_bLoaded)
346 return m_imp->Stop();
347 return 0;
348 }
349
350 double wxMediaCtrl::GetPlaybackRate()
351 {
352 if(m_imp && m_bLoaded)
353 return m_imp->GetPlaybackRate();
354 return 0;
355 }
356
357 bool wxMediaCtrl::SetPlaybackRate(double dRate)
358 {
359 if(m_imp && m_bLoaded)
360 return m_imp->SetPlaybackRate(dRate);
361 return false;
362 }
363
364 wxFileOffset wxMediaCtrl::Seek(wxFileOffset where, wxSeekMode mode)
365 {
366 wxFileOffset offset;
367
368 switch (mode)
369 {
370 case wxFromStart:
371 offset = where;
372 break;
373 case wxFromEnd:
374 offset = Length() - where;
375 break;
376 // case wxFromCurrent:
377 default:
378 offset = Tell() + where;
379 break;
380 }
381
382 if(m_imp && m_bLoaded && m_imp->SetPosition(offset))
383 return offset;
384 return wxInvalidOffset;
385 }
386
387 wxFileOffset wxMediaCtrl::Tell()
388 {
389 if(m_imp && m_bLoaded)
390 return (wxFileOffset) m_imp->GetPosition().ToLong();
391 return wxInvalidOffset;
392 }
393
394 wxFileOffset wxMediaCtrl::Length()
395 {
396 if(m_imp && m_bLoaded)
397 return (wxFileOffset) m_imp->GetDuration().ToLong();
398 return wxInvalidOffset;
399 }
400
401 wxMediaState wxMediaCtrl::GetState()
402 {
403 if(m_imp && m_bLoaded)
404 return m_imp->GetState();
405 return wxMEDIASTATE_STOPPED;
406 }
407
408 wxSize wxMediaCtrl::DoGetBestSize() const
409 {
410 if(m_imp)
411 return m_imp->GetVideoSize();
412 return wxSize(0,0);
413 }
414
415 double wxMediaCtrl::GetVolume()
416 {
417 if(m_imp && m_bLoaded)
418 return m_imp->GetVolume();
419 return 0.0;
420 }
421
422 bool wxMediaCtrl::SetVolume(double dVolume)
423 {
424 if(m_imp && m_bLoaded)
425 return m_imp->SetVolume(dVolume);
426 return false;
427 }
428
429 bool wxMediaCtrl::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
430 {
431 if(m_imp)
432 return m_imp->ShowPlayerControls(flags);
433 return false;
434 }
435
436 wxFileOffset wxMediaCtrl::GetDownloadProgress()
437 {
438 if(m_imp && m_bLoaded)
439 return (wxFileOffset) m_imp->GetDownloadProgress().ToLong();
440 return wxInvalidOffset;
441 }
442
443 wxFileOffset wxMediaCtrl::GetDownloadTotal()
444 {
445 if(m_imp && m_bLoaded)
446 return (wxFileOffset) m_imp->GetDownloadTotal().ToLong();
447 return wxInvalidOffset;
448 }
449
450 //---------------------------------------------------------------------------
451 // wxMediaCtrl::DoMoveWindow
452 //
453 // 1) Call parent's version so that our control's window moves where
454 // it's supposed to
455 // 2) If the backend exists and is loaded, move the video
456 // of the media to where our control's window is now located
457 //---------------------------------------------------------------------------
458 void wxMediaCtrl::DoMoveWindow(int x, int y, int w, int h)
459 {
460 wxControl::DoMoveWindow(x,y,w,h);
461
462 if(m_imp)
463 m_imp->Move(x, y, w, h);
464 }
465
466 //---------------------------------------------------------------------------
467 // wxMediaCtrl::MacVisibilityChanged
468 //---------------------------------------------------------------------------
469 #ifdef __WXOSX_CARBON__
470 void wxMediaCtrl::MacVisibilityChanged()
471 {
472 wxControl::MacVisibilityChanged();
473
474 if(m_imp)
475 m_imp->MacVisibilityChanged();
476 }
477 #endif
478
479 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
480 //
481 // wxMediaBackendCommonBase
482 //
483 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
484
485 void wxMediaBackendCommonBase::NotifyMovieSizeChanged()
486 {
487 // our best size changed after opening a new file
488 m_ctrl->InvalidateBestSize();
489 m_ctrl->SetSize(m_ctrl->GetSize());
490
491 // if the parent of the control has a sizer ask it to refresh our size
492 wxWindow * const parent = m_ctrl->GetParent();
493 if ( parent->GetSizer() )
494 {
495 m_ctrl->GetParent()->Layout();
496 m_ctrl->GetParent()->Refresh();
497 m_ctrl->GetParent()->Update();
498 }
499 }
500
501 void wxMediaBackendCommonBase::NotifyMovieLoaded()
502 {
503 NotifyMovieSizeChanged();
504
505 // notify about movie being fully loaded
506 QueueEvent(wxEVT_MEDIA_LOADED);
507 }
508
509 bool wxMediaBackendCommonBase::SendStopEvent()
510 {
511 wxMediaEvent theEvent(wxEVT_MEDIA_STOP, m_ctrl->GetId());
512
513 return !m_ctrl->GetEventHandler()->ProcessEvent(theEvent) || theEvent.IsAllowed();
514 }
515
516 void wxMediaBackendCommonBase::QueueEvent(wxEventType evtType)
517 {
518 wxMediaEvent theEvent(evtType, m_ctrl->GetId());
519 m_ctrl->GetEventHandler()->AddPendingEvent(theEvent);
520 }
521
522 void wxMediaBackendCommonBase::QueuePlayEvent()
523 {
524 QueueEvent(wxEVT_MEDIA_STATECHANGED);
525 QueueEvent(wxEVT_MEDIA_PLAY);
526 }
527
528 void wxMediaBackendCommonBase::QueuePauseEvent()
529 {
530 QueueEvent(wxEVT_MEDIA_STATECHANGED);
531 QueueEvent(wxEVT_MEDIA_PAUSE);
532 }
533
534 void wxMediaBackendCommonBase::QueueStopEvent()
535 {
536 QueueEvent(wxEVT_MEDIA_STATECHANGED);
537 QueueEvent(wxEVT_MEDIA_STOP);
538 }
539
540
541 //
542 // Force link default backends in -
543 // see http://wiki.wxwidgets.org/wiki.pl?RTTI
544 //
545 #include "wx/html/forcelnk.h"
546
547 #ifdef __WXMSW__ // MSW has huge backends so we do it seperately
548 FORCE_LINK(wxmediabackend_am)
549 FORCE_LINK(wxmediabackend_wmp10)
550 #elif !defined(__WXOSX_COCOA__)
551 FORCE_LINK(basewxmediabackends)
552 #endif
553
554 #endif //wxUSE_MEDIACTRL