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();
161 virtual bool Create(wxMediaCtrl
* ctrl
);
164 virtual bool Pause();
167 virtual bool Load(const wxString
& fileName
);
168 virtual bool Load(const wxURI
& location
);
170 virtual wxMediaState
GetState();
172 virtual bool SetPosition(long where
);
173 virtual long GetPosition();
174 virtual long GetDuration();
176 virtual void DoMoveWindow(int x
, int y
, int w
, int h
);
177 wxSize
DoGetBestSize() const;
179 virtual double GetPlaybackRate();
180 virtual bool SetPlaybackRate(double);
187 //---------------------------------------------------------------------------
188 // wxAVIFileMediaCtrlImpl
189 //---------------------------------------------------------------------------
193 //#pragma comment(lib, "vfw32.lib")
195 class wxAVIFileMediaCtrlImpl : public wxMediaCtrlImpl
199 wxAVIFileMediaCtrlImpl();
200 ~wxAVIFileMediaCtrlImpl();
202 virtual bool Create(wxMediaCtrl* ctrl);
205 virtual bool Pause();
208 virtual bool Load(const wxString& fileName);
209 virtual bool Load(const wxURI& location);
211 virtual wxMediaState GetState();
213 virtual bool SetPosition(long where);
214 virtual long GetPosition();
215 virtual long GetDuration();
217 virtual void DoMoveWindow(int x, int y, int w, int h);
218 wxSize DoGetBestSize() const;
220 virtual double GetPlaybackRate();
221 virtual bool SetPlaybackRate(double);
229 //###########################################################################
233 //###########################################################################
235 //---------------------------------------------------------------------------
239 //---------------------------------------------------------------------------
241 bool wxMediaCtrl::Create(wxWindow
* parent
, wxWindowID id
, const wxString
& fileName
,
242 const wxPoint
& pos
, const wxSize
& size
,
243 long style
, long WXUNUSED(driver
), const wxString
& name
)
246 if ( !wxControl::Create(parent
, id
, pos
, size
, (style
| wxNO_BORDER
) | wxCLIP_CHILDREN
,
247 wxDefaultValidator
, name
) )
250 //Set our background color to black by default
251 SetBackgroundColour(*wxBLACK
);
254 m_imp
= new wxDXMediaCtrlImpl
;
255 if(!m_imp
->Create(this))
259 m_imp
= new wxWMMEMediaCtrlImpl
;
260 if(!m_imp
->Create(this))
270 if(!fileName
.empty())
279 bool wxMediaCtrl::Create(wxWindow
* parent
, wxWindowID id
, const wxURI
& location
,
280 const wxPoint
& pos
, const wxSize
& size
,
281 long style
, long WXUNUSED(driver
), const wxString
& name
)
284 if ( !wxControl::Create(parent
, id
, pos
, size
, (style
| wxNO_BORDER
) | wxCLIP_CHILDREN
,
285 wxDefaultValidator
, name
) )
288 //Set our background color to black by default
289 SetBackgroundColour(*wxBLACK
);
292 m_imp
= new wxDXMediaCtrlImpl
;
293 if(!m_imp
->Create(this))
297 m_imp
= new wxWMMEMediaCtrlImpl
;
298 if(!m_imp
->Create(this))
314 bool wxMediaCtrl::Load(const wxString
& fileName
)
317 return m_imp
->Load(fileName
);
321 bool wxMediaCtrl::Load(const wxURI
& location
)
324 return m_imp
->Load(location
);
328 bool wxMediaCtrl::Play()
330 if(m_imp
&& m_imp
->IsLoaded())
331 return m_imp
->Play();
335 bool wxMediaCtrl::Pause()
337 if(m_imp
&& m_imp
->IsLoaded())
338 return m_imp
->Pause();
342 bool wxMediaCtrl::Stop()
344 if(m_imp
&& m_imp
->IsLoaded())
345 return m_imp
->Stop();
349 double wxMediaCtrl::GetPlaybackRate()
351 if(m_imp
&& m_imp
->IsLoaded())
352 return m_imp
->GetPlaybackRate();
356 bool wxMediaCtrl::SetPlaybackRate(double dRate
)
358 if(m_imp
&& m_imp
->IsLoaded())
359 return m_imp
->SetPlaybackRate(dRate
);
363 bool wxMediaCtrl::SetPosition(long where
)
365 if(m_imp
&& m_imp
->IsLoaded())
366 return m_imp
->SetPosition(where
);
370 long wxMediaCtrl::GetPosition()
372 if(m_imp
&& m_imp
->IsLoaded())
373 return m_imp
->GetPosition();
377 long wxMediaCtrl::GetDuration()
379 if(m_imp
&& m_imp
->IsLoaded())
380 return m_imp
->GetDuration();
384 wxMediaState
wxMediaCtrl::GetState()
386 if(m_imp
&& m_imp
->IsLoaded())
387 return m_imp
->GetState();
388 return wxMEDIASTATE_STOPPED
;
391 WXLRESULT
wxMediaCtrl::MSWWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
393 if(m_imp
&& m_imp
->IsLoaded() && m_imp
->MSWWindowProc(nMsg
, wParam
, lParam
) )
394 return wxControl::MSWDefWindowProc(nMsg
, wParam
, lParam
);
395 //pass the event to our parent
396 return wxControl::MSWWindowProc(nMsg
, wParam
, lParam
);
399 wxSize
wxMediaCtrl::DoGetBestSize() const
401 if(m_imp
&& m_imp
->IsLoaded())
402 return m_imp
->DoGetBestSize();
406 void wxMediaCtrl::DoMoveWindow(int x
, int y
, int w
, int h
)
408 wxControl::DoMoveWindow(x
,y
,w
,h
);
410 if(m_imp
&& m_imp
->IsLoaded())
411 m_imp
->DoMoveWindow(x
, y
, w
, h
);
414 wxMediaCtrl::~wxMediaCtrl()
421 //---------------------------------------------------------------------------
425 //---------------------------------------------------------------------------
429 wxDXMediaCtrlImpl::wxDXMediaCtrlImpl() : m_pGB(NULL
)
433 bool wxDXMediaCtrlImpl::Create(wxMediaCtrl
* ctrl
)
435 //create our filter graph
436 HRESULT hr
= CoCreateInstance(CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
,
437 IID_IGraphBuilder
, (void**)&m_pGB
);
439 //directshow not installed?
448 #define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
450 bool wxDXMediaCtrlImpl::Load(const wxString
& fileName
)
457 CoCreateInstance(CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
,
458 IID_IGraphBuilder
, (void**)&m_pGB
);
460 //load the graph & render
461 if( FAILED(m_pGB
->RenderFile(fileName
.wc_str(wxConvLocal
), NULL
)) )
464 //get the interfaces, all of them
465 wxDSVERIFY( m_pGB
->QueryInterface(IID_IMediaControl
, (void**)&m_pMC
) );
466 wxDSVERIFY( m_pGB
->QueryInterface(IID_IMediaEventEx
, (void**)&m_pME
) );
467 wxDSVERIFY( m_pGB
->QueryInterface(IID_IMediaSeeking
, (void**)&m_pMS
) );
468 wxDSVERIFY( m_pGB
->QueryInterface(IID_IVideoWindow
, (void**)&m_pVW
) );
469 wxDSVERIFY( m_pGB
->QueryInterface(IID_IBasicAudio
, (void**)&m_pBA
) );
470 wxDSVERIFY( m_pGB
->QueryInterface(IID_IBasicVideo
, (void**)&m_pBV
) );
473 //pBA->get_Volume(&lVolume);
476 //get the _actual_ size of the movie & remember it
477 long nX
, nY
, nSX
, nSY
;
478 if (FAILED(m_pVW
->GetWindowPosition(&nX
,&nY
,&nSX
,&nSY
)))
494 wxDSVERIFY( m_pVW
->put_Owner((OAHWND
)m_ctrl
->GetHandle()) );
495 wxDSVERIFY( m_pVW
->put_WindowStyle(WS_CHILD
| WS_CLIPSIBLINGS
) );
496 wxDSVERIFY( m_pVW
->put_Visible(OATRUE
) ); //OATRUE == -1
499 //make it so that wxEVT_MOVIE_FINISHED works
500 wxDSVERIFY( m_pME
->SetNotifyWindow((OAHWND
)m_ctrl
->GetHandle(), WM_GRAPHNOTIFY
, 0) );
502 //set the time format
503 wxDSVERIFY( m_pMS
->SetTimeFormat(&TIME_FORMAT_MEDIA_TIME
) );
505 //so that DoGetBestSize will work :)
508 //work around refresh issues
509 m_ctrl
->InvalidateBestSize();
510 m_ctrl
->GetParent()->Layout();
511 m_ctrl
->GetParent()->Refresh();
512 m_ctrl
->GetParent()->Update();
517 bool wxDXMediaCtrlImpl::Load(const wxURI
& location
)
519 return Load(location
.BuildUnescapedURI());
522 bool wxDXMediaCtrlImpl::Play()
524 return SUCCEEDED( m_pMC
->Run() );
527 bool wxDXMediaCtrlImpl::Pause()
529 return SUCCEEDED( m_pMC
->Pause() );
532 bool wxDXMediaCtrlImpl::Stop()
534 return SUCCEEDED( m_pMC
->Stop() ) && SetPosition(0);
537 bool wxDXMediaCtrlImpl::SetPosition(long where
)
539 //DS uses 100 nanos - so we need a 10 mult
540 LONGLONG pos
= ((LONGLONG
)where
) * 10000;
542 return SUCCEEDED( m_pMS
->SetPositions(
544 AM_SEEKING_AbsolutePositioning
,
546 AM_SEEKING_NoPositioning
550 long wxDXMediaCtrlImpl::GetPosition()
552 LONGLONG outCur
, outStop
;
553 wxDSVERIFY( m_pMS
->GetPositions(&outCur
, &outStop
) );
555 //h,m,s,milli - outdur is in 100 nanos
559 long wxDXMediaCtrlImpl::GetDuration()
561 LONGLONG outDuration
;
562 wxDSVERIFY( m_pMS
->GetDuration(&outDuration
) );
564 //h,m,s,milli - outdur is in 100 nanos
565 return outDuration
/10000;
568 wxMediaState
wxDXMediaCtrlImpl::GetState()
570 //TODO: MS recommends against INFINITE here - do it in stages
572 OAFilterState theState
;
573 hr
= m_pMC
->GetState(INFINITE
, &theState
);
575 wxASSERT( SUCCEEDED(hr
) );
577 //MSW state is the same as ours
579 //State_Paused = State_Stopped + 1,
580 //State_Running = State_Paused + 1
582 return (wxMediaState
) theState
;
585 double wxDXMediaCtrlImpl::GetPlaybackRate()
588 wxDSVERIFY( m_pMS
->GetRate(&dRate
) );
592 bool wxDXMediaCtrlImpl::SetPlaybackRate(double dRate
)
594 return SUCCEEDED( m_pMS
->SetRate(dRate
) );
597 bool wxDXMediaCtrlImpl::MSWWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
599 if (nMsg
== WM_GRAPHNOTIFY
)
601 LONG evCode
, evParam1
, evParam2
;
604 // Process all queued events
605 while(SUCCEEDED(m_pME
->GetEvent(&evCode
, (LONG_PTR
*) &evParam1
,
606 (LONG_PTR
*) &evParam2
, 0)
610 // Free memory associated with callback, since we're not using it
611 hr
= m_pME
->FreeEventParams(evCode
, evParam1
, evParam2
);
613 // If this is the end of the clip, notify handler
614 if(EC_COMPLETE
== evCode
)
621 wxMediaEvent
theEvent(wxEVT_MEDIA_FINISHED
, m_ctrl
->GetId());
622 m_ctrl
->GetParent()->ProcessEvent(theEvent
);
630 void wxDXMediaCtrlImpl::Cleanup()
632 // Hide then disown the window
635 m_pVW
->put_Visible(OAFALSE
); //OSFALSE == 0
636 m_pVW
->put_Owner(NULL
);
639 // Release and zero DirectShow interfaces
648 wxDXMediaCtrlImpl::~wxDXMediaCtrlImpl()
656 wxSize
wxDXMediaCtrlImpl::DoGetBestSize() const
661 void wxDXMediaCtrlImpl::DoMoveWindow(int x
, int y
, int w
, int h
)
663 if(m_bLoaded
&& m_bVideo
)
665 wxDSVERIFY( m_pVW
->SetWindowPosition(0, 0, w
, h
) );
669 #endif //wxUSE_DIRECTSHOW
671 //---------------------------------------------------------------------------
673 // wxWMMEMediaCtrlImpl
675 //---------------------------------------------------------------------------
677 wxWMMEMediaCtrlImpl::wxWMMEMediaCtrlImpl() : m_bVideo(false)
682 wxWMMEMediaCtrlImpl::~wxWMMEMediaCtrlImpl()
684 mciSendCommand(m_hDev
, MCI_CLOSE
, 0, 0);
687 bool wxWMMEMediaCtrlImpl::Create(wxMediaCtrl
* ctrl
)
693 bool wxWMMEMediaCtrlImpl::Play()
695 return (mciSendCommand(m_hDev
, MCI_PLAY
, 0, 0) == 0) ||
696 (mciSendCommand(m_hDev
, MCI_RESUME
, 0, 0) == 0);
699 bool wxWMMEMediaCtrlImpl::Pause()
701 return (mciSendCommand(m_hDev
, MCI_PAUSE
, MCI_WAIT
, 0) == 0);
704 bool wxWMMEMediaCtrlImpl::Stop()
706 return (mciSendCommand(m_hDev
, MCI_STOP
, MCI_WAIT
, 0) == 0);
711 bool wxWMMEMediaCtrlImpl::Load(const wxString
& fileName
)
714 mciSendCommand(m_hDev
, MCI_CLOSE
, 0, 0);
716 MCI_OPEN_PARMS openParms
;
717 MCI_SET_PARMS setParms
;
719 memset(&openParms
, 0, sizeof(MCI_DGV_OPEN_PARMS
));
720 openParms
.lpstrElementName
= (wxChar
*) fileName
.c_str();
724 for(size_t i
= MCI_DEVTYPE_FIRST
; i
<= MCI_DEVTYPE_LAST
; ++i
)
726 openParms
.lpstrDeviceType
= (LPSTR
)i
;
730 if ((nError
= mciSendCommand(0, MCI_OPEN
,
731 MCI_OPEN_ELEMENT
|MCI_OPEN_ELEMENT
|MCI_OPEN_TYPE
|MCI_OPEN_TYPE_ID
,
732 (DWORD
)(LPVOID
)&openParms
)) == 0)
742 m_hDev
= openParms
.wDeviceID
;
745 setParms
.dwCallback
= 0;
746 setParms
.dwTimeFormat
= MCI_FORMAT_MILLISECONDS
;
748 if (mciSendCommand(m_hDev
, MCI_SET
, MCI_SET_TIME_FORMAT
,
749 (DWORD
)(LPVOID
)&setParms
) != 0)
753 //TODO: Does this work?
755 MCI_DGV_WINDOW_PARMS windowParms;
757 windowParms.hWnd = (HWND)m_ctrl->GetHWND();
758 m_bVideo = (mciSendCommand(m_hDev, MCI_WINDOW,
759 MCI_DGV_WINDOW_HWND, (DWORD)(LPVOID)&windowParms) == 0);
766 bool wxWMMEMediaCtrlImpl::Load(const wxURI
& WXUNUSED(location
))
771 wxMediaState
wxWMMEMediaCtrlImpl::GetState()
773 MCI_STATUS_PARMS statusParms
;
774 statusParms
.dwItem
= MCI_STATUS_MODE
;
775 mciSendCommand(m_hDev
, MCI_STATUS
, MCI_STATUS_ITEM
,
776 (DWORD
)(LPVOID
)&statusParms
);
778 if(statusParms
.dwReturn
== MCI_MODE_PAUSE
)
779 return wxMEDIASTATE_PAUSED
;
780 else if(statusParms
.dwReturn
== MCI_MODE_PLAY
)
781 return wxMEDIASTATE_PLAYING
;
783 return wxMEDIASTATE_STOPPED
;
786 bool wxWMMEMediaCtrlImpl::SetPosition(long where
)
788 MCI_SEEK_PARMS seekParms
;
789 seekParms
.dwCallback
= 0;
790 seekParms
.dwTo
= where
;
792 bool bReplay
= GetState() == wxMEDIASTATE_PLAYING
;
794 if( mciSendCommand(m_hDev
, MCI_SEEK
, MCI_TO
, (DWORD
)(LPVOID
)&seekParms
) != 0)
797 mciGetErrorString(nError, sz, 5000);
798 wxMessageBox(wxString::Format(_T("Error:%s"), sz));
807 long wxWMMEMediaCtrlImpl::GetPosition()
809 MCI_STATUS_PARMS statusParms
;
811 statusParms
.dwItem
= MCI_STATUS_POSITION
;
812 if (mciSendCommand(m_hDev
, MCI_STATUS
, MCI_STATUS_ITEM
,
813 (DWORD
)(LPSTR
)&statusParms
) != 0)
816 return statusParms
.dwReturn
;
819 long wxWMMEMediaCtrlImpl::GetDuration()
821 MCI_STATUS_PARMS statusParms
;
823 statusParms
.dwItem
= MCI_STATUS_LENGTH
;
824 if (mciSendCommand(m_hDev
, MCI_STATUS
, MCI_STATUS_ITEM
,
825 (DWORD
)(LPSTR
)&statusParms
) != 0)
828 return statusParms
.dwReturn
;
831 void wxWMMEMediaCtrlImpl::DoMoveWindow(int, int, int, int)
835 wxSize
wxWMMEMediaCtrlImpl::DoGetBestSize() const
839 //TODO: Does this work?
841 MCI_DGV_RECT_PARMS rect;
843 mciSendCommand(m_hDev, MCI_WHERE, MCI_DGV_WHERE_SOURCE, (DWORD)(LPSTR)&rect);
844 return wxSize(rect.rc.right, rect.rc.bottom);
850 double wxWMMEMediaCtrlImpl::GetPlaybackRate()
855 bool wxWMMEMediaCtrlImpl::SetPlaybackRate(double)
860 //---------------------------------------------------------------------------
862 // wxAVIFileMediaCtrlImpl
864 //---------------------------------------------------------------------------
866 //---------------------------------------------------------------------------
867 // Functions located in msvfw32.dll
868 //---------------------------------------------------------------------------
872 typedef void (WINAPI *LPAVIFileInit) ();
873 typedef void (WINAPI *LPAVIFileExit) ();
875 typedef ULONG (WINAPI *LPAVIFileOpen) (
876 PAVIFILE FAR * ppfile,
877 const wxChar* szFile,
882 typedef ULONG (WINAPI *LPAVIFileRelease) (PAVIFILE pfile);
884 wxAVIFileMediaCtrlImpl::wxAVIFileMediaCtrlImpl()
888 wxAVIFileMediaCtrlImpl::~wxAVIFileMediaCtrlImpl()
892 bool wxAVIFileMediaCtrlImpl::Create(wxMediaCtrl* ctrl)
894 m_hDll = ::LoadLibrary(_T("avifil32.dll"));
899 LPAVIFileInit pAVIFileInit = (LPAVIFileInit) ::GetProcAddress(m_hDll, _T("AVIFileInit"));
911 bool wxAVIFileMediaCtrlImpl::Load(const wxString& fileName)
913 // if( AVIFileOpen(&m_hAVIFile, fileName.c_str(), OF_SHARE_DENY_WRITE, 0L) != 0)
921 bool wxAVIFileMediaCtrlImpl::Load(const wxURI& WXUNUSED(location))
926 bool wxAVIFileMediaCtrlImpl::Play()
931 bool wxAVIFileMediaCtrlImpl::Pause()
936 bool wxAVIFileMediaCtrlImpl::Stop()
941 wxMediaState wxAVIFileMediaCtrlImpl::GetState()
943 return wxMEDIASTATE_STOPPED;
946 bool wxAVIFileMediaCtrlImpl::SetPosition(long where)
951 long wxAVIFileMediaCtrlImpl::GetPosition()
956 long wxAVIFileMediaCtrlImpl::GetDuration()
961 void wxAVIFileMediaCtrlImpl::DoMoveWindow(int, int, int, int)
965 wxSize wxAVIFileMediaCtrlImpl::DoGetBestSize() const
970 double wxAVIFileMediaCtrlImpl::GetPlaybackRate()
975 bool wxAVIFileMediaCtrlImpl::SetPlaybackRate(double)
982 #endif //wxUSE_MEDIACTRL