1 /////////////////////////////////////////////////////////////////////////////
2 // Name: msw/mediactrl.cpp
3 // Purpose: wxMediaCtrl MSW
4 // Author: Ryan Norton <wxprojects@comcast.net>
8 // Copyright: (c) Ryan Norton
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 //---------------------------------------------------------------------------
14 //---------------------------------------------------------------------------
16 //#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
17 //#pragma implementation "moviectrl.h"
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
27 #include "wx/mediactrl.h"
31 //###########################################################################
33 //###########################################################################
35 IMPLEMENT_CLASS(wxMediaCtrl
, wxControl
);
36 IMPLEMENT_DYNAMIC_CLASS(wxMediaEvent
, wxEvent
);
37 DEFINE_EVENT_TYPE(wxEVT_MEDIA_FINISHED
);
39 //---------------------------------------------------------------------------
41 //---------------------------------------------------------------------------
46 wxMediaCtrlImpl() : m_bLoaded(false)
49 virtual ~wxMediaCtrlImpl()
52 virtual bool Create(wxMediaCtrl
* WXUNUSED(ctrl
))
55 virtual bool Play() { return false; }
56 virtual bool Pause() { return false; }
57 virtual bool Stop() { return false; }
59 virtual bool Load(const wxString
&) { return false; }
60 virtual bool Load(const wxURI
&) { return false; }
62 virtual wxMediaState
GetState() { return wxMEDIASTATE_STOPPED
; }
64 virtual bool SetPosition(long) { return 0; }
65 virtual long GetPosition() { return 0; }
66 virtual long GetDuration() { return 0; }
68 virtual void DoMoveWindow(int, int, int, int) { }
69 virtual wxSize
DoGetBestSize() const { return wxSize(0,0); }
71 virtual double GetPlaybackRate() { return 0; }
72 virtual bool SetPlaybackRate(double) { return false; }
74 virtual bool MSWWindowProc(WXUINT
, WXWPARAM
, WXLPARAM
) { return false; }
82 //---------------------------------------------------------------------------
84 //---------------------------------------------------------------------------
90 #define WM_GRAPHNOTIFY WM_USER+13
93 #define wxDSVERIFY(x) wxASSERT( SUCCEEDED ((x)) )
95 #define wxDSVERIFY(x) (x)
98 class wxDXMediaCtrlImpl
: public wxMediaCtrlImpl
103 virtual ~wxDXMediaCtrlImpl();
105 virtual bool Create(wxMediaCtrl
* ctrl
);
108 virtual bool Pause();
111 virtual bool Load(const wxString
& fileName
);
112 virtual bool Load(const wxURI
& location
);
114 virtual wxMediaState
GetState();
116 virtual bool SetPosition(long where
);
117 virtual long GetPosition();
118 virtual long GetDuration();
120 virtual void DoMoveWindow(int x
, int y
, int w
, int h
);
121 wxSize
DoGetBestSize() const;
123 virtual double GetPlaybackRate();
124 virtual bool SetPlaybackRate(double);
130 bool MSWWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
);
134 IGraphBuilder
* m_pGB
;
135 IMediaControl
* m_pMC
;
136 IMediaEventEx
* m_pME
;
140 IMediaSeeking
* m_pMS
;
145 #endif //wxUSE_DIRECTSHOW
147 //---------------------------------------------------------------------------
148 // wxWMMEMediaCtrlImpl
149 //---------------------------------------------------------------------------
151 #include <mmsystem.h>
152 #include <digitalv.h>
154 class wxWMMEMediaCtrlImpl
: public wxMediaCtrlImpl
158 wxWMMEMediaCtrlImpl();
159 ~wxWMMEMediaCtrlImpl();
162 virtual bool Create(wxMediaCtrl* ctrl);
165 virtual bool Pause();
168 virtual bool Load(const wxString& fileName);
169 virtual bool Load(const wxURI& location);
171 virtual wxMediaState GetState();
173 virtual bool SetPosition(long where);
174 virtual long GetPosition();
175 virtual long GetDuration();
177 virtual void DoMoveWindow(int x, int y, int w, int h);
178 wxSize DoGetBestSize() const;
180 virtual double GetPlaybackRate();
181 virtual bool SetPlaybackRate(double);
187 //###########################################################################
191 //###########################################################################
193 //---------------------------------------------------------------------------
197 //---------------------------------------------------------------------------
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
)
204 if ( !wxControl::Create(parent
, id
, pos
, size
, (style
| wxNO_BORDER
) | wxCLIP_CHILDREN
,
205 wxDefaultValidator
, name
) )
208 //Set our background color to black by default
209 SetBackgroundColour(*wxBLACK
);
212 m_imp
= new wxDXMediaCtrlImpl
;
213 if(!m_imp
->Create(this))
217 m_imp
= new wxWMMEMediaCtrlImpl
;
218 if(!m_imp
->Create(this))
228 if(!fileName
.empty())
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
)
242 if ( !wxControl::Create(parent
, id
, pos
, size
, (style
| wxNO_BORDER
) | wxCLIP_CHILDREN
,
243 wxDefaultValidator
, name
) )
246 //Set our background color to black by default
247 SetBackgroundColour(*wxBLACK
);
250 m_imp
= new wxDXMediaCtrlImpl
;
251 if(!m_imp
->Create(this))
255 m_imp
= new wxWMMEMediaCtrlImpl
;
256 if(!m_imp
->Create(this))
272 bool wxMediaCtrl::Load(const wxString
& fileName
)
275 return m_imp
->Load(fileName
);
279 bool wxMediaCtrl::Load(const wxURI
& location
)
282 return m_imp
->Load(location
);
286 bool wxMediaCtrl::Play()
288 if(m_imp
&& m_imp
->IsLoaded())
289 return m_imp
->Play();
293 bool wxMediaCtrl::Pause()
295 if(m_imp
&& m_imp
->IsLoaded())
296 return m_imp
->Pause();
300 bool wxMediaCtrl::Stop()
302 if(m_imp
&& m_imp
->IsLoaded())
303 return m_imp
->Stop();
307 double wxMediaCtrl::GetPlaybackRate()
309 if(m_imp
&& m_imp
->IsLoaded())
310 return m_imp
->GetPlaybackRate();
314 bool wxMediaCtrl::SetPlaybackRate(double dRate
)
316 if(m_imp
&& m_imp
->IsLoaded())
317 return m_imp
->SetPlaybackRate(dRate
);
321 bool wxMediaCtrl::SetPosition(long where
)
323 if(m_imp
&& m_imp
->IsLoaded())
324 return m_imp
->SetPosition(where
);
328 long wxMediaCtrl::GetPosition()
330 if(m_imp
&& m_imp
->IsLoaded())
331 return m_imp
->GetPosition();
335 long wxMediaCtrl::GetDuration()
337 if(m_imp
&& m_imp
->IsLoaded())
338 return m_imp
->GetDuration();
342 wxMediaState
wxMediaCtrl::GetState()
344 if(m_imp
&& m_imp
->IsLoaded())
345 return m_imp
->GetState();
346 return wxMEDIASTATE_STOPPED
;
349 WXLRESULT
wxMediaCtrl::MSWWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
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
);
357 wxSize
wxMediaCtrl::DoGetBestSize() const
359 if(m_imp
&& m_imp
->IsLoaded())
360 return m_imp
->DoGetBestSize();
364 void wxMediaCtrl::DoMoveWindow(int x
, int y
, int w
, int h
)
366 wxControl::DoMoveWindow(x
,y
,w
,h
);
368 if(m_imp
&& m_imp
->IsLoaded())
369 m_imp
->DoMoveWindow(x
, y
, w
, h
);
372 wxMediaCtrl::~wxMediaCtrl()
379 //---------------------------------------------------------------------------
383 //---------------------------------------------------------------------------
387 wxDXMediaCtrlImpl::wxDXMediaCtrlImpl() : m_pGB(NULL
)
391 bool wxDXMediaCtrlImpl::Create(wxMediaCtrl
* ctrl
)
393 //create our filter graph
394 HRESULT hr
= CoCreateInstance(CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
,
395 IID_IGraphBuilder
, (void**)&m_pGB
);
397 //directshow not installed?
406 #define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
408 bool wxDXMediaCtrlImpl::Load(const wxString
& fileName
)
415 CoCreateInstance(CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
,
416 IID_IGraphBuilder
, (void**)&m_pGB
);
418 //load the graph & render
419 if( FAILED(m_pGB
->RenderFile(fileName
.wc_str(wxConvLocal
), NULL
)) )
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
) );
431 //pBA->get_Volume(&lVolume);
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
)))
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
457 //make it so that wxEVT_MOVIE_FINISHED works
458 wxDSVERIFY( m_pME
->SetNotifyWindow((OAHWND
)m_ctrl
->GetHandle(), WM_GRAPHNOTIFY
, 0) );
460 //set the time format
461 wxDSVERIFY( m_pMS
->SetTimeFormat(&TIME_FORMAT_MEDIA_TIME
) );
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();
476 bool wxDXMediaCtrlImpl::Load(const wxURI
& location
)
478 return Load(location
.BuildUnescapedURI());
481 bool wxDXMediaCtrlImpl::Play()
483 return SUCCEEDED( m_pMC
->Run() );
486 bool wxDXMediaCtrlImpl::Pause()
488 return SUCCEEDED( m_pMC
->Pause() );
491 bool wxDXMediaCtrlImpl::Stop()
493 return SUCCEEDED( m_pMC
->Stop() ) && SetPosition(0);
496 bool wxDXMediaCtrlImpl::SetPosition(long where
)
498 //DS uses 100 nanos - so we need a 10 mult
499 LONGLONG pos
= ((LONGLONG
)where
) * 10000;
501 return SUCCEEDED( m_pMS
->SetPositions(
503 AM_SEEKING_AbsolutePositioning
,
505 AM_SEEKING_NoPositioning
509 long wxDXMediaCtrlImpl::GetPosition()
511 LONGLONG outCur
, outStop
;
512 wxDSVERIFY( m_pMS
->GetPositions(&outCur
, &outStop
) );
514 //h,m,s,milli - outdur is in 100 nanos
518 long wxDXMediaCtrlImpl::GetDuration()
520 LONGLONG outDuration
;
521 wxDSVERIFY( m_pMS
->GetDuration(&outDuration
) );
523 //h,m,s,milli - outdur is in 100 nanos
524 return outDuration
/10000;
527 wxMediaState
wxDXMediaCtrlImpl::GetState()
529 //TODO: MS recommends against INFINITE here - do it in stages
531 OAFilterState theState
;
532 hr
= m_pMC
->GetState(INFINITE
, &theState
);
534 wxASSERT( SUCCEEDED(hr
) );
536 //MSW state is the same as ours
538 //State_Paused = State_Stopped + 1,
539 //State_Running = State_Paused + 1
541 return (wxMediaState
) theState
;
544 double wxDXMediaCtrlImpl::GetPlaybackRate()
547 wxDSVERIFY( m_pMS
->GetRate(&dRate
) );
551 bool wxDXMediaCtrlImpl::SetPlaybackRate(double dRate
)
553 return SUCCEEDED( m_pMS
->SetRate(dRate
) );
556 bool wxDXMediaCtrlImpl::MSWWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
558 if (nMsg
== WM_GRAPHNOTIFY
)
560 LONG evCode
, evParam1
, evParam2
;
563 // Process all queued events
564 while(SUCCEEDED(m_pME
->GetEvent(&evCode
, (LONG_PTR
*) &evParam1
,
565 (LONG_PTR
*) &evParam2
, 0)
569 // Free memory associated with callback, since we're not using it
570 hr
= m_pME
->FreeEventParams(evCode
, evParam1
, evParam2
);
572 // If this is the end of the clip, notify handler
573 if(EC_COMPLETE
== evCode
)
580 wxMediaEvent
theEvent(wxEVT_MEDIA_FINISHED
, m_ctrl
->GetId());
581 m_ctrl
->GetParent()->ProcessEvent(theEvent
);
589 void wxDXMediaCtrlImpl::Cleanup()
591 // Hide then disown the window
594 m_pVW
->put_Visible(OAFALSE
); //OSFALSE == 0
595 m_pVW
->put_Owner(NULL
);
598 // Release and zero DirectShow interfaces
607 wxDXMediaCtrlImpl::~wxDXMediaCtrlImpl()
615 wxSize
wxDXMediaCtrlImpl::DoGetBestSize() const
620 void wxDXMediaCtrlImpl::DoMoveWindow(int x
, int y
, int w
, int h
)
622 if(m_bLoaded
&& m_bVideo
)
624 wxDSVERIFY( m_pVW
->SetWindowPosition(0, 0, w
, h
) );
628 #endif //wxUSE_DIRECTSHOW
630 //---------------------------------------------------------------------------
632 // wxWMMEMediaCtrlImpl
634 //---------------------------------------------------------------------------
637 #endif //wxUSE_MEDIACTRL