]> git.saurik.com Git - wxWidgets.git/blob - src/msw/mediactrl.cpp
1) fix border styles in wxMediaCtrl, 2) regenerate wx and mediaplayer samples bakefil...
[wxWidgets.git] / src / msw / mediactrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: msw/mediactrl.cpp
3 // Purpose: wxMediaCtrl MSW
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 //---------------------------------------------------------------------------
13 // Pre-wx includes
14 //---------------------------------------------------------------------------
15
16 //#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
17 //#pragma implementation "moviectrl.h"
18 //#endif
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #include "wx/mediactrl.h"
28
29 #if wxUSE_MEDIACTRL
30
31 //###########################################################################
32 // DECLARATIONS
33 //###########################################################################
34
35 IMPLEMENT_CLASS(wxMediaCtrl, wxControl);
36 IMPLEMENT_DYNAMIC_CLASS(wxMediaEvent, wxEvent);
37 DEFINE_EVENT_TYPE(wxEVT_MEDIA_FINISHED);
38
39 //---------------------------------------------------------------------------
40 // wxMediaCtrlImpl
41 //---------------------------------------------------------------------------
42
43 class wxMediaCtrlImpl
44 {
45 public:
46 wxMediaCtrlImpl() : m_bLoaded(false)
47 { }
48
49 virtual ~wxMediaCtrlImpl()
50 { }
51
52 virtual bool Create(wxMediaCtrl* WXUNUSED(ctrl))
53 { return false; }
54
55 virtual bool Play() { return false; }
56 virtual bool Pause() { return false; }
57 virtual bool Stop() { return false; }
58
59 virtual bool Load(const wxString&) { return false; }
60 virtual bool Load(const wxURI&) { return false; }
61
62 virtual wxMediaState GetState() { return wxMEDIASTATE_STOPPED; }
63
64 virtual bool SetPosition(long) { return 0; }
65 virtual long GetPosition() { return 0; }
66 virtual long GetDuration() { return 0; }
67
68 virtual void DoMoveWindow(int, int, int, int) { }
69 virtual wxSize DoGetBestSize() const { return wxSize(0,0); }
70
71 virtual double GetPlaybackRate() { return 0; }
72 virtual bool SetPlaybackRate(double) { return false; }
73
74 virtual bool MSWWindowProc(WXUINT, WXWPARAM, WXLPARAM) { return false; }
75
76 bool IsLoaded()
77 { return m_bLoaded; }
78
79 bool m_bLoaded;
80 };
81
82 //---------------------------------------------------------------------------
83 // wxDXMediaCtrlImpl
84 //---------------------------------------------------------------------------
85
86 #if wxUSE_DIRECTSHOW
87
88 #include <dshow.h>
89
90 #define WM_GRAPHNOTIFY WM_USER+13
91
92 #ifdef __WXDEBUG__
93 #define wxDSVERIFY(x) wxASSERT( SUCCEEDED ((x)) )
94 #else
95 #define wxDSVERIFY(x) (x)
96 #endif
97
98 class wxDXMediaCtrlImpl : public wxMediaCtrlImpl
99 {
100 public:
101 wxDXMediaCtrlImpl();
102
103 virtual ~wxDXMediaCtrlImpl();
104
105 virtual bool Create(wxMediaCtrl* ctrl);
106
107 virtual bool Play();
108 virtual bool Pause();
109 virtual bool Stop();
110
111 virtual bool Load(const wxString& fileName);
112 virtual bool Load(const wxURI& location);
113
114 virtual wxMediaState GetState();
115
116 virtual bool SetPosition(long where);
117 virtual long GetPosition();
118 virtual long GetDuration();
119
120 virtual void DoMoveWindow(int x, int y, int w, int h);
121 wxSize DoGetBestSize() const;
122
123 virtual double GetPlaybackRate();
124 virtual bool SetPlaybackRate(double);
125
126 void Cleanup();
127
128 bool m_bVideo;
129
130 bool MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);
131
132 wxMediaCtrl* m_ctrl;
133
134 IGraphBuilder* m_pGB;
135 IMediaControl* m_pMC;
136 IMediaEventEx* m_pME;
137 IVideoWindow* m_pVW;
138 IBasicAudio* m_pBA;
139 IBasicVideo* m_pBV;
140 IMediaSeeking* m_pMS;
141
142 wxSize m_bestSize;
143 };
144
145 #endif //wxUSE_DIRECTSHOW
146
147 //---------------------------------------------------------------------------
148 // wxWMMEMediaCtrlImpl
149 //---------------------------------------------------------------------------
150
151 #include <mmsystem.h>
152 #include <digitalv.h>
153
154 class wxWMMEMediaCtrlImpl : public wxMediaCtrlImpl
155 {
156 public:
157 /*
158 wxWMMEMediaCtrlImpl();
159 ~wxWMMEMediaCtrlImpl();
160
161
162 virtual bool Create(wxMediaCtrl* ctrl);
163
164 virtual bool Play();
165 virtual bool Pause();
166 virtual bool Stop();
167
168 virtual bool Load(const wxString& fileName);
169 virtual bool Load(const wxURI& location);
170
171 virtual wxMediaState GetState();
172
173 virtual bool SetPosition(long where);
174 virtual long GetPosition();
175 virtual long GetDuration();
176
177 virtual void DoMoveWindow(int x, int y, int w, int h);
178 wxSize DoGetBestSize() const;
179
180 virtual double GetPlaybackRate();
181 virtual bool SetPlaybackRate(double);
182 */
183 MCIDEVICEID m_hDev;
184 };
185
186
187 //###########################################################################
188 //
189 // IMPLEMENTATION
190 //
191 //###########################################################################
192
193 //---------------------------------------------------------------------------
194 //
195 // wxMediaCtrl
196 //
197 //---------------------------------------------------------------------------
198
199 bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id, const wxString& fileName,
200 const wxPoint& pos, const wxSize& size,
201 long style, long WXUNUSED(driver), const wxString& name)
202 {
203 //base create
204 if ( !wxControl::Create(parent, id, pos, size, (style | wxNO_BORDER) | wxCLIP_CHILDREN,
205 wxDefaultValidator, name) )
206 return false;
207
208 //Set our background color to black by default
209 SetBackgroundColour(*wxBLACK);
210
211 #if wxUSE_DIRECTSHOW
212 m_imp = new wxDXMediaCtrlImpl;
213 if(!m_imp->Create(this))
214 {
215 delete m_imp;
216 #endif
217 m_imp = new wxWMMEMediaCtrlImpl;
218 if(!m_imp->Create(this))
219 {
220 delete m_imp;
221 m_imp = NULL;
222 return false;
223 }
224 #if wxUSE_DIRECTSHOW
225 }
226 #endif
227
228 if(!fileName.empty())
229 {
230 if (!Load(fileName))
231 return false;
232 }
233
234 return true;
235 }
236
237 bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id, const wxURI& location,
238 const wxPoint& pos, const wxSize& size,
239 long style, long WXUNUSED(driver), const wxString& name)
240 {
241 //base create
242 if ( !wxControl::Create(parent, id, pos, size, (style | wxNO_BORDER) | wxCLIP_CHILDREN,
243 wxDefaultValidator, name) )
244 return false;
245
246 //Set our background color to black by default
247 SetBackgroundColour(*wxBLACK);
248
249 #if wxUSE_DIRECTSHOW
250 m_imp = new wxDXMediaCtrlImpl;
251 if(!m_imp->Create(this))
252 {
253 delete m_imp;
254 #endif
255 m_imp = new wxWMMEMediaCtrlImpl;
256 if(!m_imp->Create(this))
257 {
258 delete m_imp;
259 m_imp = NULL;
260 return false;
261 }
262 #if wxUSE_DIRECTSHOW
263 }
264 #endif
265
266 if (!Load(location))
267 return false;
268
269 return true;
270 }
271
272 bool wxMediaCtrl::Load(const wxString& fileName)
273 {
274 if(m_imp)
275 return m_imp->Load(fileName);
276 return false;
277 }
278
279 bool wxMediaCtrl::Load(const wxURI& location)
280 {
281 if(m_imp)
282 return m_imp->Load(location);
283 return false;
284 }
285
286 bool wxMediaCtrl::Play()
287 {
288 if(m_imp && m_imp->IsLoaded())
289 return m_imp->Play();
290 return false;
291 }
292
293 bool wxMediaCtrl::Pause()
294 {
295 if(m_imp && m_imp->IsLoaded())
296 return m_imp->Pause();
297 return false;
298 }
299
300 bool wxMediaCtrl::Stop()
301 {
302 if(m_imp && m_imp->IsLoaded())
303 return m_imp->Stop();
304 return false;
305 }
306
307 double wxMediaCtrl::GetPlaybackRate()
308 {
309 if(m_imp && m_imp->IsLoaded())
310 return m_imp->GetPlaybackRate();
311 return 0;
312 }
313
314 bool wxMediaCtrl::SetPlaybackRate(double dRate)
315 {
316 if(m_imp && m_imp->IsLoaded())
317 return m_imp->SetPlaybackRate(dRate);
318 return false;
319 }
320
321 bool wxMediaCtrl::SetPosition(long where)
322 {
323 if(m_imp && m_imp->IsLoaded())
324 return m_imp->SetPosition(where);
325 return false;
326 }
327
328 long wxMediaCtrl::GetPosition()
329 {
330 if(m_imp && m_imp->IsLoaded())
331 return m_imp->GetPosition();
332 return 0;
333 }
334
335 long wxMediaCtrl::GetDuration()
336 {
337 if(m_imp && m_imp->IsLoaded())
338 return m_imp->GetDuration();
339 return 0;
340 }
341
342 wxMediaState wxMediaCtrl::GetState()
343 {
344 if(m_imp && m_imp->IsLoaded())
345 return m_imp->GetState();
346 return wxMEDIASTATE_STOPPED;
347 }
348
349 WXLRESULT wxMediaCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
350 {
351 if(m_imp && m_imp->IsLoaded() && m_imp->MSWWindowProc(nMsg, wParam, lParam) )
352 return wxControl::MSWDefWindowProc(nMsg, wParam, lParam);
353 //pass the event to our parent
354 return wxControl::MSWWindowProc(nMsg, wParam, lParam);
355 }
356
357 wxSize wxMediaCtrl::DoGetBestSize() const
358 {
359 if(m_imp && m_imp->IsLoaded())
360 return m_imp->DoGetBestSize();
361 return wxSize(0,0);
362 }
363
364 void wxMediaCtrl::DoMoveWindow(int x, int y, int w, int h)
365 {
366 wxControl::DoMoveWindow(x,y,w,h);
367
368 if(m_imp && m_imp->IsLoaded())
369 m_imp->DoMoveWindow(x, y, w, h);
370 }
371
372 wxMediaCtrl::~wxMediaCtrl()
373 {
374 if (m_imp)
375 delete m_imp;
376 }
377
378
379 //---------------------------------------------------------------------------
380 //
381 // wxDXMediaCtrlImpl
382 //
383 //---------------------------------------------------------------------------
384
385 #if wxUSE_DIRECTSHOW
386
387 wxDXMediaCtrlImpl::wxDXMediaCtrlImpl() : m_pGB(NULL)
388 {
389 }
390
391 bool wxDXMediaCtrlImpl::Create(wxMediaCtrl* ctrl)
392 {
393 //create our filter graph
394 HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
395 IID_IGraphBuilder, (void**)&m_pGB);
396
397 //directshow not installed?
398 if ( FAILED(hr) )
399 return false;
400
401 m_ctrl = ctrl;
402
403 return true;
404 }
405
406 #define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
407
408 bool wxDXMediaCtrlImpl::Load(const wxString& fileName)
409 {
410 if(m_bLoaded)
411 Cleanup();
412
413 SAFE_RELEASE(m_pGB);
414
415 CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
416 IID_IGraphBuilder, (void**)&m_pGB);
417
418 //load the graph & render
419 if( FAILED(m_pGB->RenderFile(fileName.wc_str(wxConvLocal), NULL)) )
420 return false;
421
422 //get the interfaces, all of them
423 wxDSVERIFY( m_pGB->QueryInterface(IID_IMediaControl, (void**)&m_pMC) );
424 wxDSVERIFY( m_pGB->QueryInterface(IID_IMediaEventEx, (void**)&m_pME) );
425 wxDSVERIFY( m_pGB->QueryInterface(IID_IMediaSeeking, (void**)&m_pMS) );
426 wxDSVERIFY( m_pGB->QueryInterface(IID_IVideoWindow, (void**)&m_pVW) );
427 wxDSVERIFY( m_pGB->QueryInterface(IID_IBasicAudio, (void**)&m_pBA) );
428 wxDSVERIFY( m_pGB->QueryInterface(IID_IBasicVideo, (void**)&m_pBV) );
429
430 //long lVolume;
431 //pBA->get_Volume(&lVolume);
432 //E_NOTIMPL
433
434 //get the _actual_ size of the movie & remember it
435 long nX, nY, nSX, nSY;
436 if (FAILED(m_pVW->GetWindowPosition(&nX,&nY,&nSX,&nSY)))
437 {
438 m_bVideo = false;
439
440 nSX = nSY = 0;
441 }
442 else
443 {
444 m_bVideo = true;
445 }
446
447 m_bestSize.x = nSX;
448 m_bestSize.y = nSY;
449
450 if (m_bVideo)
451 {
452 wxDSVERIFY( m_pVW->put_Owner((OAHWND)m_ctrl->GetHandle()) );
453 wxDSVERIFY( m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS) );
454 wxDSVERIFY( m_pVW->put_Visible(OATRUE) ); //OATRUE == -1
455 }
456
457 //make it so that wxEVT_MOVIE_FINISHED works
458 wxDSVERIFY( m_pME->SetNotifyWindow((OAHWND)m_ctrl->GetHandle(), WM_GRAPHNOTIFY, 0) );
459
460 //set the time format
461 wxDSVERIFY( m_pMS->SetTimeFormat(&TIME_FORMAT_MEDIA_TIME) );
462
463 //work around refresh issues
464 wxSize size = m_ctrl->GetParent()->GetSize();
465 m_ctrl->GetParent()->SetSize(wxSize(size.x+1, size.y+1));
466 m_ctrl->GetParent()->Refresh();
467 m_ctrl->GetParent()->Update();
468 m_ctrl->GetParent()->SetSize(size);
469 m_ctrl->GetParent()->Refresh();
470 m_ctrl->GetParent()->Update();
471
472 m_bLoaded = true;
473 return true;
474 }
475
476 bool wxDXMediaCtrlImpl::Load(const wxURI& location)
477 {
478 return Load(location.BuildUnescapedURI());
479 }
480
481 bool wxDXMediaCtrlImpl::Play()
482 {
483 return SUCCEEDED( m_pMC->Run() );
484 }
485
486 bool wxDXMediaCtrlImpl::Pause()
487 {
488 return SUCCEEDED( m_pMC->Pause() );
489 }
490
491 bool wxDXMediaCtrlImpl::Stop()
492 {
493 return SUCCEEDED( m_pMC->Stop() ) && SetPosition(0);
494 }
495
496 bool wxDXMediaCtrlImpl::SetPosition(long where)
497 {
498 //DS uses 100 nanos - so we need a 10 mult
499 LONGLONG pos = ((LONGLONG)where) * 10000;
500
501 return SUCCEEDED( m_pMS->SetPositions(
502 &pos,
503 AM_SEEKING_AbsolutePositioning,
504 NULL,
505 AM_SEEKING_NoPositioning
506 ) );
507 }
508
509 long wxDXMediaCtrlImpl::GetPosition()
510 {
511 LONGLONG outCur, outStop;
512 wxDSVERIFY( m_pMS->GetPositions(&outCur, &outStop) );
513
514 //h,m,s,milli - outdur is in 100 nanos
515 return outCur/10000;
516 }
517
518 long wxDXMediaCtrlImpl::GetDuration()
519 {
520 LONGLONG outDuration;
521 wxDSVERIFY( m_pMS->GetDuration(&outDuration) );
522
523 //h,m,s,milli - outdur is in 100 nanos
524 return outDuration/10000;
525 }
526
527 wxMediaState wxDXMediaCtrlImpl::GetState()
528 {
529 //TODO: MS recommends against INFINITE here - do it in stages
530 HRESULT hr;
531 OAFilterState theState;
532 hr = m_pMC->GetState(INFINITE, &theState);
533
534 wxASSERT( SUCCEEDED(hr) );
535
536 //MSW state is the same as ours
537 //State_Stopped = 0,
538 //State_Paused = State_Stopped + 1,
539 //State_Running = State_Paused + 1
540
541 return (wxMediaState) theState;
542 }
543
544 double wxDXMediaCtrlImpl::GetPlaybackRate()
545 {
546 double dRate;
547 wxDSVERIFY( m_pMS->GetRate(&dRate) );
548 return dRate;
549 }
550
551 bool wxDXMediaCtrlImpl::SetPlaybackRate(double dRate)
552 {
553 return SUCCEEDED( m_pMS->SetRate(dRate) );
554 }
555
556 bool wxDXMediaCtrlImpl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
557 {
558 if (nMsg == WM_GRAPHNOTIFY)
559 {
560 LONG evCode, evParam1, evParam2;
561 HRESULT hr=S_OK;
562
563 // Process all queued events
564 while(SUCCEEDED(m_pME->GetEvent(&evCode, (LONG_PTR *) &evParam1,
565 (LONG_PTR *) &evParam2, 0)
566 )
567 )
568 {
569 // Free memory associated with callback, since we're not using it
570 hr = m_pME->FreeEventParams(evCode, evParam1, evParam2);
571
572 // If this is the end of the clip, notify handler
573 if(EC_COMPLETE == evCode)
574 {
575 #ifdef __WXDEBUG__
576 wxASSERT( Stop() );
577 #else
578 Stop();
579 #endif
580 wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED, m_ctrl->GetId());
581 m_ctrl->GetParent()->ProcessEvent(theEvent);
582 }
583 }
584 return true;
585 }
586 return false;
587 }
588
589 void wxDXMediaCtrlImpl::Cleanup()
590 {
591 // Hide then disown the window
592 if(m_pVW)
593 {
594 m_pVW->put_Visible(OAFALSE); //OSFALSE == 0
595 m_pVW->put_Owner(NULL);
596 }
597
598 // Release and zero DirectShow interfaces
599 SAFE_RELEASE(m_pME);
600 SAFE_RELEASE(m_pMS);
601 SAFE_RELEASE(m_pMC);
602 SAFE_RELEASE(m_pBA);
603 SAFE_RELEASE(m_pBV);
604 SAFE_RELEASE(m_pVW);
605 }
606
607 wxDXMediaCtrlImpl::~wxDXMediaCtrlImpl()
608 {
609 if (m_bLoaded)
610 Cleanup();
611
612 SAFE_RELEASE(m_pGB);
613 }
614
615 wxSize wxDXMediaCtrlImpl::DoGetBestSize() const
616 {
617 return m_bestSize;
618 }
619
620 void wxDXMediaCtrlImpl::DoMoveWindow(int x, int y, int w, int h)
621 {
622 if(m_bLoaded && m_bVideo)
623 {
624 wxDSVERIFY( m_pVW->SetWindowPosition(0, 0, w, h) );
625 }
626 }
627
628 #endif //wxUSE_DIRECTSHOW
629
630 //---------------------------------------------------------------------------
631 //
632 // wxWMMEMediaCtrlImpl
633 //
634 //---------------------------------------------------------------------------
635
636
637 #endif //wxUSE_MEDIACTRL