]> git.saurik.com Git - wxWidgets.git/blob - src/msw/moviectrl.cpp
50ef6b352e2865d0c8a6ffdf2e18f8dd62bb96e1
[wxWidgets.git] / src / msw / moviectrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: msw/moviectrl.cpp
3 // Purpose: wxMovieCtrl 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 //#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 //#pragma implementation "moviectrl.h"
14 //#endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #if wxUSE_MOVIECTRL
24
25 #include "wx/moviectrl.h"
26 #include "wx/msw/ole/oleutils.h" //for wxBasicString
27
28 #include <dshow.h>
29
30 IMPLEMENT_CLASS(wxMovieCtrl, wxControl);
31
32 #define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
33
34 #define WM_GRAPHNOTIFY WM_USER+13
35
36 #ifdef __WXDEBUG__
37 #define wxDSVERIFY(x) wxASSERT( SUCCEEDED ((x)) )
38 #else
39 #define wxDSVERIFY(x) (x)
40 #endif
41
42 BEGIN_EVENT_TABLE(wxMovieCtrl, wxControl)
43 EVT_SIZE(wxMovieCtrl::OnSize)
44 // EVT_ACTIVATE(wxMovieCtrl::OnActivate)
45 END_EVENT_TABLE()
46
47 //it's there someplace :)
48 extern "C" WXDLLIMPEXP_BASE HWND
49 wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc);
50
51 bool wxMovieCtrl::Create(wxWindow* parent, wxWindowID id, const wxString& fileName,
52 const wxString& label, const wxPoint& pos, const wxSize& size,
53 long style, const wxString& name)
54 {
55 //cast helpers
56 IGraphBuilder*& pGB = (IGraphBuilder*&) m_pGB;
57 IMediaControl*& pMC = (IMediaControl*&) m_pMC;
58 IMediaEventEx*& pME = (IMediaEventEx*&) m_pME;
59 IVideoWindow*& pVW = (IVideoWindow*&) m_pVW;
60 IBasicAudio*& pBA = (IBasicAudio*&) m_pBA;
61 IBasicVideo*& pBV = (IBasicVideo*&) m_pBV;
62 IMediaSeeking*& pMS = (IMediaSeeking*&) m_pMS;
63
64 //create our filter graph
65 CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
66 IID_IGraphBuilder, (void**)&pGB);
67
68 //load the graph & render
69 if (FAILED(pGB->RenderFile(fileName.wc_str(wxConvLocal), NULL)))
70 {
71 wxFAIL_MSG("Could not load movie!");
72 return false;
73 }
74
75 //get the interfaces, all of them
76 wxDSVERIFY( pGB->QueryInterface(IID_IMediaControl, (void**)&pMC) );
77 wxDSVERIFY( pGB->QueryInterface(IID_IMediaEventEx, (void**)&pME) );
78 wxDSVERIFY( pGB->QueryInterface(IID_IMediaSeeking, (void**)&pMS) );
79 wxDSVERIFY( pGB->QueryInterface(IID_IVideoWindow, (void**)&pVW) );
80 wxDSVERIFY( pGB->QueryInterface(IID_IBasicAudio, (void**)&pBA) );
81 wxDSVERIFY( pGB->QueryInterface(IID_IBasicVideo, (void**)&pBV) );
82
83 //get the _actual_ size of the movie & remember it
84 long nX, nY, nSX, nSY;
85 pVW->GetWindowPosition(&nX,&nY,&nSX,&nSY);
86
87 m_bestSize.x = nSX;
88 m_bestSize.y = nSY;
89
90 //do some window stuff - ORDER IS IMPORTANT
91 //base create
92 if ( !wxControl::Create(parent, id, pos, size, wxNO_BORDER | wxCLIP_CHILDREN, wxDefaultValidator, name) )
93 return false;
94
95 //Set our background color to black by default
96 SetBackgroundColour(*wxBLACK);
97
98 wxDSVERIFY( pVW->put_Owner((OAHWND)this->GetHandle()) );
99 wxDSVERIFY( pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS) );
100 // wxDSVERIFY( pME->SetNotifyWindow((OAHWND)this->GetHandle(), WM_GRAPHNOTIFY, 0) );
101 wxDSVERIFY( pVW->put_Visible(OATRUE) ); //OATRUE actually == -1 :)
102
103 //set the time format
104 wxDSVERIFY( pMS->SetTimeFormat(&TIME_FORMAT_MEDIA_TIME) );
105
106 SetLabel(label);
107 Play();
108
109 return true;
110 }
111
112 void wxMovieCtrl::SetLabel(const wxString& label)
113 {
114 wxControl::SetLabel(label);
115
116 IVideoWindow*& pVW = (IVideoWindow*&) m_pVW;
117
118 //wxBasicString will have a null string on an
119 //empty wxString - gotta love those workarounds!!
120 if(!label.empty())
121 {
122 wxBasicString theBasicString(label.mb_str());
123 wxDSVERIFY( pVW->put_Caption(theBasicString.Get()) );
124 }
125 }
126
127 bool wxMovieCtrl::Play()
128 {
129 return SUCCEEDED( ((IMediaControl*&)m_pMC)->Run() );
130 }
131
132 bool wxMovieCtrl::Pause()
133 {
134 return SUCCEEDED( ((IMediaControl*&)m_pMC)->Pause() );
135 }
136
137 bool wxMovieCtrl::Stop()
138 {
139 return SUCCEEDED( ((IMediaControl*&)m_pMC)->Stop() );
140 }
141
142 #if wxUSE_DATETIME
143
144 bool wxMovieCtrl::Seek(const wxTimeSpan& where)
145 {
146 //DS uses 100 nanos - so we need a 10 mult
147 LONGLONG pos = ((size_t)where.GetMilliseconds().ToLong()) * 10;
148
149 return SUCCEEDED( ((IMediaSeeking*&)m_pMS)->SetPositions(
150 &pos,
151 AM_SEEKING_AbsolutePositioning,
152 NULL,
153 AM_SEEKING_NoPositioning
154 ) );
155 }
156
157 #endif // wxUSE_DATETIME
158
159 wxMovieCtrlState wxMovieCtrl::GetState()
160 {
161 HRESULT hr;
162 OAFilterState theState;
163 hr = ((IMediaControl*&)m_pMC)->GetState(INFINITE, &theState);
164
165 wxASSERT( SUCCEEDED(hr) );
166
167 //MSW state is the same as ours
168 //State_Stopped = 0,
169 //State_Paused = State_Stopped + 1,
170 //State_Running = State_Paused + 1
171
172 return (wxMovieCtrlState) theState;
173 }
174
175 //WXLRESULT wxMovieCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
176 //{
177 /*
178 //cast helpers
179 IMediaControl*& pMC = (IMediaControl*&) m_pMC;
180 IMediaEventEx*& pME = (IMediaEventEx*&) m_pME;
181 IMediaSeeking*& pMS = (IMediaSeeking*&) m_pMS;
182
183 if (nMsg == WM_GRAPHNOTIFY)
184 {
185 LONG evCode, evParam1, evParam2;
186 HRESULT hr=S_OK;
187
188 //make sure we exist
189 if (!pME)
190 return S_OK;
191
192 // Process all queued events
193 while(SUCCEEDED(pME->GetEvent(&evCode, (LONG_PTR *) &evParam1,
194 (LONG_PTR *) &evParam2, 0)
195 )
196 )
197 {
198 // Free memory associated with callback, since we're not using it
199 hr = pME->FreeEventParams(evCode, evParam1, evParam2);
200
201 // If this is the end of the clip, reset to beginning
202 if(EC_COMPLETE == evCode)
203 {
204 LONGLONG pos=0;
205
206 // Reset to first frame of movie
207 hr = pMS->SetPositions(&pos, AM_SEEKING_AbsolutePositioning ,
208 NULL, AM_SEEKING_NoPositioning);
209 if (FAILED(hr))
210 {
211 hr = pMC->Stop();
212 // for filters that don't support seeking do a rewind
213 if (FAILED(hr))
214 {
215 wxFAIL_MSG(
216 wxString::Format(TEXT("Failed(0x%08lx) to stop media clip!\r\n"), hr)
217 );
218 break;
219 }
220
221 hr = hr = pMC->Run();
222
223 if (FAILED(hr))
224 {
225 wxFAIL_MSG(
226 wxString::Format(TEXT("Failed(0x%08lx) to reset media clip!\r\n"), hr)
227 );
228 break;
229 }
230 }
231 }
232 }
233 return wxControl::MSWDefWindowProc(nMsg, wParam, lParam);
234 }
235 */
236 //pass the event to our parent
237 // return wxControl::MSWWindowProc(nMsg, wParam, lParam);
238 //}
239
240 wxMovieCtrl::~wxMovieCtrl()
241 {
242 //cast helpers
243 IGraphBuilder*& pGB = (IGraphBuilder*&) m_pGB;
244 IMediaControl*& pMC = (IMediaControl*&) m_pMC;
245 IMediaEventEx*& pME = (IMediaEventEx*&) m_pME;
246 IVideoWindow*& pVW = (IVideoWindow*&) m_pVW;
247 IBasicAudio*& pBA = (IBasicAudio*&) m_pBA;
248 IBasicVideo*& pBV = (IBasicVideo*&) m_pBV;
249 IMediaSeeking*& pMS = (IMediaSeeking*&) m_pMS;
250
251 // Hide then disown the window
252 if(pVW)
253 {
254 pVW->put_Visible(OAFALSE); //OSFALSE == 0
255 pVW->put_Owner(NULL);
256 }
257
258 // Release and zero DirectShow interfaces
259 SAFE_RELEASE(pME);
260 SAFE_RELEASE(pMS);
261 SAFE_RELEASE(pMC);
262 SAFE_RELEASE(pBA);
263 SAFE_RELEASE(pBV);
264 SAFE_RELEASE(pVW);
265 SAFE_RELEASE(pGB);
266 }
267
268 wxSize wxMovieCtrl::DoGetBestSize() const
269 {
270 return m_bestSize;
271 }
272
273 //
274 //EVENT OVERRIDES
275 //
276
277 void wxMovieCtrl::OnSize(wxSizeEvent& evt)
278 {
279 IVideoWindow*& pVW = (IVideoWindow*&) m_pVW;
280 wxDSVERIFY( pVW->SetWindowPosition(0, 0, evt.GetSize().GetWidth(), evt.GetSize().GetHeight()) );
281
282 evt.Skip();
283 }
284 /*
285 void wxMovieCtrl::OnActivate(wxActivateEvent& evt)
286 {
287 if (evt.GetActive())
288 {
289 //HACK: Make the window show :)
290 SetSize(GetSize());
291 }
292 }
293 */
294
295 #endif //wxUSE_MOVIECTRL