* Fix refreshing bug with control not showing up intially and asserting on resize
[wxWidgets.git] / src / msw / mediactrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: msw/mediactrl.cpp
3 // Purpose: Built-in Media Backends for Windows
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 // DECLARATIONS
14 //===========================================================================
15
16 //---------------------------------------------------------------------------
17 // Pre-compiled header stuff
18 //---------------------------------------------------------------------------
19
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "mediactrl.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 //---------------------------------------------------------------------------
32 // Includes
33 //---------------------------------------------------------------------------
34 #include "wx/mediactrl.h"
35
36 //---------------------------------------------------------------------------
37 // Compilation guard
38 //---------------------------------------------------------------------------
39 #if wxUSE_MEDIACTRL
40
41 //---------------------------------------------------------------------------
42 // Externals (somewhere in src/msw/app.cpp)
43 //---------------------------------------------------------------------------
44 extern "C" WXDLLIMPEXP_BASE HINSTANCE wxGetInstance(void);
45 #ifdef __WXWINCE__
46 extern WXDLLIMPEXP_CORE wxChar *wxCanvasClassName;
47 #else
48 extern WXDLLIMPEXP_CORE const wxChar *wxCanvasClassName;
49 #endif
50
51 //===========================================================================
52 // BACKEND DECLARATIONS
53 //===========================================================================
54
55 //---------------------------------------------------------------------------
56 //
57 // wxAMMediaBackend
58 //
59 //---------------------------------------------------------------------------
60
61 //---------------------------------------------------------------------------
62 // Compilation guard for DirectShow
63 //---------------------------------------------------------------------------
64 #if wxUSE_DIRECTSHOW
65
66 //---------------------------------------------------------------------------
67 // COM includes
68 //---------------------------------------------------------------------------
69 #include "wx/msw/ole/oleutils.h" //wxBasicString, IID etc.
70 #include "wx/msw/ole/uuid.h" //IID etc..
71
72 //---------------------------------------------------------------------------
73 // IIDS - used by CoCreateInstance and IUnknown::QueryInterface
74 //---------------------------------------------------------------------------
75 const IID LIBID_QuartzTypeLib = {0x56A868B0,0x0AD4,0x11CE,{0xB0,0x3A,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
76 const IID IID_IAMCollection = {0x56A868B9,0x0AD4,0x11CE,{0xB0,0x3A,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
77 const IID IID_IMediaControl = {0x56A868B1,0x0AD4,0x11CE,{0xB0,0x3A,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
78 const IID IID_IMediaEvent = {0x56A868B6,0x0AD4,0x11CE,{0xB0,0x3A,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
79 const IID IID_IMediaEventEx = {0x56A868C0,0x0AD4,0x11CE,{0xB0,0x3A,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
80 const IID IID_IMediaPosition = {0x56A868B2,0x0AD4,0x11CE,{0xB0,0x3A,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
81 const IID IID_IBasicAudio = {0x56A868B3,0x0AD4,0x11CE,{0xB0,0x3A,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
82 const IID IID_IVideoWindow = {0x56A868B4,0x0AD4,0x11CE,{0xB0,0x3A,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
83 const IID IID_IBasicVideo = {0x56A868B5,0x0AD4,0x11CE,{0xB0,0x3A,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
84 const IID IID_IBasicVideo2 = {0x329BB360,0xF6EA,0x11D1,{0x90,0x38,0x00,0xA0,0xC9,0x69,0x72,0x98}};
85 const IID IID_IDeferredCommand = {0x56A868B8,0x0AD4,0x11CE,{0xB0,0x3A,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
86 const IID IID_IQueueCommand = {0x56A868B7,0x0AD4,0x11CE,{0xB0,0x3A,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
87 const IID IID_IFilterInfo = {0x56A868BA,0x0AD4,0x11CE,{0xB0,0x3A,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
88 const IID IID_IRegFilterInfo = {0x56A868BB,0x0AD4,0x11CE,{0xB0,0x3A,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
89 const IID IID_IMediaTypeInfo = {0x56A868BC,0x0AD4,0x11CE,{0xB0,0x3A,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
90 const IID IID_IPinInfo = {0x56A868BD,0x0AD4,0x11CE,{0xB0,0x3A,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
91 const IID IID_IAMStats = {0xBC9BCF80,0xDCD2,0x11D2,{0xAB,0xF6,0x00,0xA0,0xC9,0x05,0xF3,0x75}};
92
93 //TODO: These 4 lines needed?
94 #ifndef CLSID_DEFINED
95 #define CLSID_DEFINED
96 typedef IID CLSID;
97 #endif // CLSID_DEFINED
98
99 //COM Class Factory
100 const CLSID CLSID_FilgraphManager = {0xE436EBB3,0x524F,0x11CE,{0x9F,0x53,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
101
102 //---------------------------------------------------------------------------
103 // COM INTERFACES (dumped from midl from quartz.idl from MSVC COM Browser)
104 //---------------------------------------------------------------------------
105 MIDL_INTERFACE("56A868B9-0AD4-11CE-B03A-0020AF0BA770")
106 IAMCollection : public IDispatch
107 {
108 public:
109 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_Count(
110 /* [retval][out] */ long __RPC_FAR *plCount) = 0;
111
112 virtual /* [id] */ HRESULT STDMETHODCALLTYPE Item(
113 /* [in] */ long lItem,
114 /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk) = 0;
115
116 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get__NewEnum(
117 /* [retval][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk) = 0;
118
119 };
120
121 MIDL_INTERFACE("56A868B1-0AD4-11CE-B03A-0020AF0BA770")
122 IMediaControl : public IDispatch
123 {
124 public:
125 virtual /* [id] */ HRESULT STDMETHODCALLTYPE Run( void) = 0;
126
127 virtual /* [id] */ HRESULT STDMETHODCALLTYPE Pause( void) = 0;
128
129 virtual /* [id] */ HRESULT STDMETHODCALLTYPE Stop( void) = 0;
130
131 virtual /* [id] */ HRESULT STDMETHODCALLTYPE GetState(
132 /* [in] */ long msTimeout,
133 /* [out] */ long __RPC_FAR *pfs) = 0;
134
135 virtual /* [id] */ HRESULT STDMETHODCALLTYPE RenderFile(
136 /* [in] */ BSTR strFilename) = 0;
137
138 virtual /* [id] */ HRESULT STDMETHODCALLTYPE AddSourceFilter(
139 /* [in] */ BSTR strFilename,
140 /* [out] */ IDispatch __RPC_FAR *__RPC_FAR *ppUnk) = 0;
141
142 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_FilterCollection(
143 /* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppUnk) = 0;
144
145 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_RegFilterCollection(
146 /* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppUnk) = 0;
147
148 virtual /* [id] */ HRESULT STDMETHODCALLTYPE StopWhenReady( void) = 0;
149
150 };
151
152 MIDL_INTERFACE("56A868B6-0AD4-11CE-B03A-0020AF0BA770")
153 IMediaEvent : public IDispatch
154 {
155 public:
156 virtual /* [id] */ HRESULT STDMETHODCALLTYPE GetEventHandle(
157 /* [out] */ LONG_PTR __RPC_FAR *hEvent) = 0;
158
159 virtual /* [id] */ HRESULT STDMETHODCALLTYPE GetEvent(
160 /* [out] */ long __RPC_FAR *lEventCode,
161 /* [out] */ LONG_PTR __RPC_FAR *lParam1,
162 /* [out] */ LONG_PTR __RPC_FAR *lParam2,
163 /* [in] */ long msTimeout) = 0;
164
165 virtual /* [id] */ HRESULT STDMETHODCALLTYPE WaitForCompletion(
166 /* [in] */ long msTimeout,
167 /* [out] */ long __RPC_FAR *pEvCode) = 0;
168
169 virtual /* [id] */ HRESULT STDMETHODCALLTYPE CancelDefaultHandling(
170 /* [in] */ long lEvCode) = 0;
171
172 virtual /* [id] */ HRESULT STDMETHODCALLTYPE RestoreDefaultHandling(
173 /* [in] */ long lEvCode) = 0;
174
175 virtual /* [id] */ HRESULT STDMETHODCALLTYPE FreeEventParams(
176 /* [in] */ long lEvCode,
177 /* [in] */ LONG_PTR lParam1,
178 /* [in] */ LONG_PTR lParam2) = 0;
179
180 };
181
182 MIDL_INTERFACE("56A868C0-0AD4-11CE-B03A-0020AF0BA770")
183 IMediaEventEx : public IMediaEvent
184 {
185 public:
186 virtual HRESULT __stdcall SetNotifyWindow(
187 /* [in] */ LONG_PTR hwnd,
188 /* [in] */ long lMsg,
189 /* [in] */ LONG_PTR lInstanceData) = 0;
190
191 virtual HRESULT __stdcall SetNotifyFlags(
192 /* [in] */ long lNoNotifyFlags) = 0;
193
194 virtual HRESULT __stdcall GetNotifyFlags(
195 /* [out] */ long __RPC_FAR *lplNoNotifyFlags) = 0;
196
197 };
198
199 MIDL_INTERFACE("56A868B2-0AD4-11CE-B03A-0020AF0BA770")
200 IMediaPosition : public IDispatch
201 {
202 public:
203 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_Duration(
204 /* [retval][out] */ double __RPC_FAR *plength) = 0;
205
206 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_CurrentPosition(
207 /* [in] */ double pllTime) = 0;
208
209 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_CurrentPosition(
210 /* [retval][out] */ double __RPC_FAR *pllTime) = 0;
211
212 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_StopTime(
213 /* [retval][out] */ double __RPC_FAR *pllTime) = 0;
214
215 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_StopTime(
216 /* [in] */ double pllTime) = 0;
217
218 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_PrerollTime(
219 /* [retval][out] */ double __RPC_FAR *pllTime) = 0;
220
221 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_PrerollTime(
222 /* [in] */ double pllTime) = 0;
223
224 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_Rate(
225 /* [in] */ double pdRate) = 0;
226
227 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_Rate(
228 /* [retval][out] */ double __RPC_FAR *pdRate) = 0;
229
230 virtual /* [id] */ HRESULT STDMETHODCALLTYPE CanSeekForward(
231 /* [retval][out] */ long __RPC_FAR *pCanSeekForward) = 0;
232
233 virtual /* [id] */ HRESULT STDMETHODCALLTYPE CanSeekBackward(
234 /* [retval][out] */ long __RPC_FAR *pCanSeekBackward) = 0;
235
236 };
237
238 MIDL_INTERFACE("56A868B3-0AD4-11CE-B03A-0020AF0BA770")
239 IBasicAudio : public IDispatch
240 {
241 public:
242 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_Volume(
243 /* [in] */ long plVolume) = 0;
244
245 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_Volume(
246 /* [retval][out] */ long __RPC_FAR *plVolume) = 0;
247
248 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_Balance(
249 /* [in] */ long plBalance) = 0;
250
251 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_Balance(
252 /* [retval][out] */ long __RPC_FAR *plBalance) = 0;
253
254 };
255
256 MIDL_INTERFACE("56A868B4-0AD4-11CE-B03A-0020AF0BA770")
257 IVideoWindow : public IDispatch
258 {
259 public:
260 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_Caption(
261 /* [in] */ BSTR strCaption) = 0;
262
263 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_Caption(
264 /* [retval][out] */ BSTR __RPC_FAR *strCaption) = 0;
265
266 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_WindowStyle(
267 /* [in] */ long WindowStyle) = 0;
268
269 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_WindowStyle(
270 /* [retval][out] */ long __RPC_FAR *WindowStyle) = 0;
271
272 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_WindowStyleEx(
273 /* [in] */ long WindowStyleEx) = 0;
274
275 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_WindowStyleEx(
276 /* [retval][out] */ long __RPC_FAR *WindowStyleEx) = 0;
277
278 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_AutoShow(
279 /* [in] */ long AutoShow) = 0;
280
281 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_AutoShow(
282 /* [retval][out] */ long __RPC_FAR *AutoShow) = 0;
283
284 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_WindowState(
285 /* [in] */ long WindowState) = 0;
286
287 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_WindowState(
288 /* [retval][out] */ long __RPC_FAR *WindowState) = 0;
289
290 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_BackgroundPalette(
291 /* [in] */ long pBackgroundPalette) = 0;
292
293 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_BackgroundPalette(
294 /* [retval][out] */ long __RPC_FAR *pBackgroundPalette) = 0;
295
296 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_Visible(
297 /* [in] */ long pVisible) = 0;
298
299 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_Visible(
300 /* [retval][out] */ long __RPC_FAR *pVisible) = 0;
301
302 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_Left(
303 /* [in] */ long pLeft) = 0;
304
305 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_Left(
306 /* [retval][out] */ long __RPC_FAR *pLeft) = 0;
307
308 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_Width(
309 /* [in] */ long pWidth) = 0;
310
311 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_Width(
312 /* [retval][out] */ long __RPC_FAR *pWidth) = 0;
313
314 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_Top(
315 /* [in] */ long pTop) = 0;
316
317 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_Top(
318 /* [retval][out] */ long __RPC_FAR *pTop) = 0;
319
320 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_Height(
321 /* [in] */ long pHeight) = 0;
322
323 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_Height(
324 /* [retval][out] */ long __RPC_FAR *pHeight) = 0;
325
326 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_Owner(
327 /* [in] */ LONG_PTR Owner) = 0;
328
329 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_Owner(
330 /* [retval][out] */ LONG_PTR __RPC_FAR *Owner) = 0;
331
332 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_MessageDrain(
333 /* [in] */ LONG_PTR Drain) = 0;
334
335 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_MessageDrain(
336 /* [retval][out] */ LONG_PTR __RPC_FAR *Drain) = 0;
337
338 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_BorderColor(
339 /* [retval][out] */ long __RPC_FAR *Color) = 0;
340
341 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_BorderColor(
342 /* [in] */ long Color) = 0;
343
344 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_FullScreenMode(
345 /* [retval][out] */ long __RPC_FAR *FullScreenMode) = 0;
346
347 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_FullScreenMode(
348 /* [in] */ long FullScreenMode) = 0;
349
350 virtual /* [id] */ HRESULT STDMETHODCALLTYPE SetWindowForeground(
351 /* [in] */ long Focus) = 0;
352
353 virtual /* [id] */ HRESULT STDMETHODCALLTYPE NotifyOwnerMessage(
354 /* [in] */ LONG_PTR hwnd,
355 /* [in] */ long uMsg,
356 /* [in] */ LONG_PTR wParam,
357 /* [in] */ LONG_PTR lParam) = 0;
358
359 virtual /* [id] */ HRESULT STDMETHODCALLTYPE SetWindowPosition(
360 /* [in] */ long Left,
361 /* [in] */ long Top,
362 /* [in] */ long Width,
363 /* [in] */ long Height) = 0;
364
365 virtual /* [id] */ HRESULT STDMETHODCALLTYPE GetWindowPosition(
366 /* [out] */ long __RPC_FAR *pLeft,
367 /* [out] */ long __RPC_FAR *pTop,
368 /* [out] */ long __RPC_FAR *pWidth,
369 /* [out] */ long __RPC_FAR *pHeight) = 0;
370
371 virtual /* [id] */ HRESULT STDMETHODCALLTYPE GetMinIdealImageSize(
372 /* [out] */ long __RPC_FAR *pWidth,
373 /* [out] */ long __RPC_FAR *pHeight) = 0;
374
375 virtual /* [id] */ HRESULT STDMETHODCALLTYPE GetMaxIdealImageSize(
376 /* [out] */ long __RPC_FAR *pWidth,
377 /* [out] */ long __RPC_FAR *pHeight) = 0;
378
379 virtual /* [id] */ HRESULT STDMETHODCALLTYPE GetRestorePosition(
380 /* [out] */ long __RPC_FAR *pLeft,
381 /* [out] */ long __RPC_FAR *pTop,
382 /* [out] */ long __RPC_FAR *pWidth,
383 /* [out] */ long __RPC_FAR *pHeight) = 0;
384
385 virtual /* [id] */ HRESULT STDMETHODCALLTYPE HideCursor(
386 /* [in] */ long HideCursor) = 0;
387
388 virtual /* [id] */ HRESULT STDMETHODCALLTYPE IsCursorHidden(
389 /* [out] */ long __RPC_FAR *CursorHidden) = 0;
390
391 };
392
393 MIDL_INTERFACE("56A868B5-0AD4-11CE-B03A-0020AF0BA770")
394 IBasicVideo : public IDispatch
395 {
396 public:
397 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_AvgTimePerFrame(
398 /* [retval][out] */ double __RPC_FAR *pAvgTimePerFrame) = 0;
399
400 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_BitRate(
401 /* [retval][out] */ long __RPC_FAR *pBitRate) = 0;
402
403 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_BitErrorRate(
404 /* [retval][out] */ long __RPC_FAR *pBitErrorRate) = 0;
405
406 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_VideoWidth(
407 /* [retval][out] */ long __RPC_FAR *pVideoWidth) = 0;
408
409 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_VideoHeight(
410 /* [retval][out] */ long __RPC_FAR *pVideoHeight) = 0;
411
412 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_SourceLeft(
413 /* [in] */ long pSourceLeft) = 0;
414
415 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_SourceLeft(
416 /* [retval][out] */ long __RPC_FAR *pSourceLeft) = 0;
417
418 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_SourceWidth(
419 /* [in] */ long pSourceWidth) = 0;
420
421 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_SourceWidth(
422 /* [retval][out] */ long __RPC_FAR *pSourceWidth) = 0;
423
424 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_SourceTop(
425 /* [in] */ long pSourceTop) = 0;
426
427 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_SourceTop(
428 /* [retval][out] */ long __RPC_FAR *pSourceTop) = 0;
429
430 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_SourceHeight(
431 /* [in] */ long pSourceHeight) = 0;
432
433 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_SourceHeight(
434 /* [retval][out] */ long __RPC_FAR *pSourceHeight) = 0;
435
436 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_DestinationLeft(
437 /* [in] */ long pDestinationLeft) = 0;
438
439 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_DestinationLeft(
440 /* [retval][out] */ long __RPC_FAR *pDestinationLeft) = 0;
441
442 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_DestinationWidth(
443 /* [in] */ long pDestinationWidth) = 0;
444
445 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_DestinationWidth(
446 /* [retval][out] */ long __RPC_FAR *pDestinationWidth) = 0;
447
448 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_DestinationTop(
449 /* [in] */ long pDestinationTop) = 0;
450
451 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_DestinationTop(
452 /* [retval][out] */ long __RPC_FAR *pDestinationTop) = 0;
453
454 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_DestinationHeight(
455 /* [in] */ long pDestinationHeight) = 0;
456
457 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_DestinationHeight(
458 /* [retval][out] */ long __RPC_FAR *pDestinationHeight) = 0;
459
460 virtual /* [id] */ HRESULT STDMETHODCALLTYPE SetSourcePosition(
461 /* [in] */ long Left,
462 /* [in] */ long Top,
463 /* [in] */ long Width,
464 /* [in] */ long Height) = 0;
465
466 virtual /* [id] */ HRESULT STDMETHODCALLTYPE GetSourcePosition(
467 /* [out] */ long __RPC_FAR *pLeft,
468 /* [out] */ long __RPC_FAR *pTop,
469 /* [out] */ long __RPC_FAR *pWidth,
470 /* [out] */ long __RPC_FAR *pHeight) = 0;
471
472 virtual /* [id] */ HRESULT STDMETHODCALLTYPE SetDefaultSourcePosition( void) = 0;
473
474 virtual /* [id] */ HRESULT STDMETHODCALLTYPE SetDestinationPosition(
475 /* [in] */ long Left,
476 /* [in] */ long Top,
477 /* [in] */ long Width,
478 /* [in] */ long Height) = 0;
479
480 virtual /* [id] */ HRESULT STDMETHODCALLTYPE GetDestinationPosition(
481 /* [out] */ long __RPC_FAR *pLeft,
482 /* [out] */ long __RPC_FAR *pTop,
483 /* [out] */ long __RPC_FAR *pWidth,
484 /* [out] */ long __RPC_FAR *pHeight) = 0;
485
486 virtual /* [id] */ HRESULT STDMETHODCALLTYPE SetDefaultDestinationPosition( void) = 0;
487
488 virtual /* [id] */ HRESULT STDMETHODCALLTYPE GetVideoSize(
489 /* [out] */ long __RPC_FAR *pWidth,
490 /* [out] */ long __RPC_FAR *pHeight) = 0;
491
492 virtual /* [id] */ HRESULT STDMETHODCALLTYPE GetVideoPaletteEntries(
493 /* [in] */ long StartIndex,
494 /* [in] */ long Entries,
495 /* [out] */ long __RPC_FAR *pRetrieved,
496 /* [out] */ long __RPC_FAR *pPalette) = 0;
497
498 virtual /* [id] */ HRESULT STDMETHODCALLTYPE GetCurrentImage(
499 /* [out][in] */ long __RPC_FAR *pBufferSize,
500 /* [out] */ long __RPC_FAR *pDIBImage) = 0;
501
502 virtual /* [id] */ HRESULT STDMETHODCALLTYPE IsUsingDefaultSource( void) = 0;
503
504 virtual /* [id] */ HRESULT STDMETHODCALLTYPE IsUsingDefaultDestination( void) = 0;
505
506 };
507
508 MIDL_INTERFACE("329BB360-F6EA-11D1-9038-00A0C9697298")
509 IBasicVideo2 : public IBasicVideo
510 {
511 public:
512 virtual HRESULT __stdcall GetPreferredAspectRatio(
513 /* [out] */ long __RPC_FAR *plAspectX,
514 /* [out] */ long __RPC_FAR *plAspectY) = 0;
515
516 };
517
518 MIDL_INTERFACE("56A868B8-0AD4-11CE-B03A-0020AF0BA770")
519 IDeferredCommand : public IUnknown
520 {
521 public:
522 virtual HRESULT __stdcall Cancel( void) = 0;
523
524 virtual HRESULT __stdcall Confidence(
525 /* [out] */ long __RPC_FAR *pConfidence) = 0;
526
527 virtual HRESULT __stdcall Postpone(
528 /* [in] */ double newtime) = 0;
529
530 virtual HRESULT __stdcall GetHResult(
531 /* [out] */ HRESULT __RPC_FAR *phrResult) = 0;
532
533 };
534
535 MIDL_INTERFACE("56A868B7-0AD4-11CE-B03A-0020AF0BA770")
536 IQueueCommand : public IUnknown
537 {
538 public:
539 virtual HRESULT __stdcall InvokeAtStreamTime(
540 /* [out] */ IDeferredCommand __RPC_FAR *__RPC_FAR *pCmd,
541 /* [in] */ double time,
542 /* [in] */ GUID __RPC_FAR *iid,
543 /* [in] */ long dispidMethod,
544 /* [in] */ short wFlags,
545 /* [in] */ long cArgs,
546 /* [in] */ VARIANT __RPC_FAR *pDispParams,
547 /* [out][in] */ VARIANT __RPC_FAR *pvarResult,
548 /* [out] */ short __RPC_FAR *puArgErr) = 0;
549
550 virtual HRESULT __stdcall InvokeAtPresentationTime(
551 /* [out] */ IDeferredCommand __RPC_FAR *__RPC_FAR *pCmd,
552 /* [in] */ double time,
553 /* [in] */ GUID __RPC_FAR *iid,
554 /* [in] */ long dispidMethod,
555 /* [in] */ short wFlags,
556 /* [in] */ long cArgs,
557 /* [in] */ VARIANT __RPC_FAR *pDispParams,
558 /* [out][in] */ VARIANT __RPC_FAR *pvarResult,
559 /* [out] */ short __RPC_FAR *puArgErr) = 0;
560
561 };
562
563 MIDL_INTERFACE("56A868BA-0AD4-11CE-B03A-0020AF0BA770")
564 IFilterInfo : public IDispatch
565 {
566 public:
567 virtual /* [id] */ HRESULT STDMETHODCALLTYPE FindPin(
568 /* [in] */ BSTR strPinID,
569 /* [out] */ IDispatch __RPC_FAR *__RPC_FAR *ppUnk) = 0;
570
571 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_Name(
572 /* [retval][out] */ BSTR __RPC_FAR *strName) = 0;
573
574 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_VendorInfo(
575 /* [retval][out] */ BSTR __RPC_FAR *strVendorInfo) = 0;
576
577 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_Filter(
578 /* [retval][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk) = 0;
579
580 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_Pins(
581 /* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppUnk) = 0;
582
583 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_IsFileSource(
584 /* [retval][out] */ long __RPC_FAR *pbIsSource) = 0;
585
586 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_Filename(
587 /* [retval][out] */ BSTR __RPC_FAR *pstrFilename) = 0;
588
589 virtual /* [propput][id] */ HRESULT STDMETHODCALLTYPE put_Filename(
590 /* [in] */ BSTR pstrFilename) = 0;
591
592 };
593
594 MIDL_INTERFACE("56A868BB-0AD4-11CE-B03A-0020AF0BA770")
595 IRegFilterInfo : public IDispatch
596 {
597 public:
598 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_Name(
599 /* [retval][out] */ BSTR __RPC_FAR *strName) = 0;
600
601 virtual /* [id] */ HRESULT STDMETHODCALLTYPE Filter(
602 /* [out] */ IDispatch __RPC_FAR *__RPC_FAR *ppUnk) = 0;
603
604 };
605
606 MIDL_INTERFACE("56A868BC-0AD4-11CE-B03A-0020AF0BA770")
607 IMediaTypeInfo : public IDispatch
608 {
609 public:
610 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_Type(
611 /* [retval][out] */ BSTR __RPC_FAR *strType) = 0;
612
613 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_Subtype(
614 /* [retval][out] */ BSTR __RPC_FAR *strType) = 0;
615
616 };
617
618 MIDL_INTERFACE("56A868BD-0AD4-11CE-B03A-0020AF0BA770")
619 IPinInfo : public IDispatch
620 {
621 public:
622 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_Pin(
623 /* [retval][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk) = 0;
624
625 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_ConnectedTo(
626 /* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppUnk) = 0;
627
628 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_ConnectionMediaType(
629 /* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppUnk) = 0;
630
631 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_FilterInfo(
632 /* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppUnk) = 0;
633
634 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_Name(
635 /* [retval][out] */ BSTR __RPC_FAR *ppUnk) = 0;
636
637 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_Direction(
638 /* [retval][out] */ long __RPC_FAR *ppDirection) = 0;
639
640 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_PinID(
641 /* [retval][out] */ BSTR __RPC_FAR *strPinID) = 0;
642
643 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_MediaTypes(
644 /* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppUnk) = 0;
645
646 virtual /* [id] */ HRESULT STDMETHODCALLTYPE Connect(
647 /* [in] */ IUnknown __RPC_FAR *pPin) = 0;
648
649 virtual /* [id] */ HRESULT STDMETHODCALLTYPE ConnectDirect(
650 /* [in] */ IUnknown __RPC_FAR *pPin) = 0;
651
652 virtual /* [id] */ HRESULT STDMETHODCALLTYPE ConnectWithType(
653 /* [in] */ IUnknown __RPC_FAR *pPin,
654 /* [in] */ IDispatch __RPC_FAR *pMediaType) = 0;
655
656 virtual /* [id] */ HRESULT STDMETHODCALLTYPE Disconnect( void) = 0;
657
658 virtual /* [id] */ HRESULT STDMETHODCALLTYPE Render( void) = 0;
659
660 };
661
662 MIDL_INTERFACE("BC9BCF80-DCD2-11D2-ABF6-00A0C905F375")
663 IAMStats : public IDispatch
664 {
665 public:
666 virtual /* [id] */ HRESULT STDMETHODCALLTYPE Reset( void) = 0;
667
668 virtual /* [propget][id] */ HRESULT STDMETHODCALLTYPE get_Count(
669 /* [retval][out] */ long __RPC_FAR *plCount) = 0;
670
671 virtual /* [id] */ HRESULT STDMETHODCALLTYPE GetValueByIndex(
672 /* [in] */ long lIndex,
673 /* [out] */ BSTR __RPC_FAR *szName,
674 /* [out] */ long __RPC_FAR *lCount,
675 /* [out] */ double __RPC_FAR *dLast,
676 /* [out] */ double __RPC_FAR *dAverage,
677 /* [out] */ double __RPC_FAR *dStdDev,
678 /* [out] */ double __RPC_FAR *dMin,
679 /* [out] */ double __RPC_FAR *dMax) = 0;
680
681 virtual /* [id] */ HRESULT STDMETHODCALLTYPE GetValueByName(
682 /* [in] */ BSTR szName,
683 /* [out] */ long __RPC_FAR *lIndex,
684 /* [out] */ long __RPC_FAR *lCount,
685 /* [out] */ double __RPC_FAR *dLast,
686 /* [out] */ double __RPC_FAR *dAverage,
687 /* [out] */ double __RPC_FAR *dStdDev,
688 /* [out] */ double __RPC_FAR *dMin,
689 /* [out] */ double __RPC_FAR *dMax) = 0;
690
691 virtual /* [id] */ HRESULT STDMETHODCALLTYPE GetIndex(
692 /* [in] */ BSTR szName,
693 /* [in] */ long lCreate,
694 /* [out] */ long __RPC_FAR *plIndex) = 0;
695
696 virtual /* [id] */ HRESULT STDMETHODCALLTYPE AddValue(
697 /* [in] */ long lIndex,
698 /* [in] */ double dValue) = 0;
699
700 };
701
702 //------------------------------------------------------------------
703 // wxAMMediaBackend (Active Movie)
704 //------------------------------------------------------------------
705 class WXDLLIMPEXP_MEDIA wxAMMediaBackend : public wxMediaBackend
706 {
707 public:
708 wxAMMediaBackend();
709
710 virtual ~wxAMMediaBackend();
711
712 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
713 wxWindowID id,
714 const wxPoint& pos,
715 const wxSize& size,
716 long style,
717 const wxValidator& validator,
718 const wxString& name);
719
720 virtual bool Play();
721 virtual bool Pause();
722 virtual bool Stop();
723
724 virtual bool Load(const wxString& fileName);
725 virtual bool Load(const wxURI& location);
726
727 virtual wxMediaState GetState();
728
729 virtual bool SetPosition(wxLongLong where);
730 virtual wxLongLong GetPosition();
731 virtual wxLongLong GetDuration();
732
733 virtual void Move(int x, int y, int w, int h);
734 wxSize GetVideoSize() const;
735
736 virtual double GetPlaybackRate();
737 virtual bool SetPlaybackRate(double);
738
739 void Cleanup();
740
741 bool m_bVideo;
742
743 static LRESULT CALLBACK NotifyWndProc(HWND hWnd, UINT nMsg,
744 WPARAM wParam, LPARAM lParam);
745
746 LRESULT CALLBACK OnNotifyWndProc(HWND hWnd, UINT nMsg,
747 WPARAM wParam, LPARAM lParam);
748
749 wxControl* m_ctrl;
750
751 IBasicAudio* m_pBA;
752 IBasicVideo* m_pBV;
753 IMediaControl* m_pMC;
754 IMediaEventEx* m_pME;
755 IMediaPosition* m_pMS;
756 IVideoWindow* m_pVW;
757
758 HWND m_hNotifyWnd;
759 wxSize m_bestSize;
760
761 DECLARE_DYNAMIC_CLASS(wxAMMediaBackend);
762 };
763
764 #endif //wxUSE_DIRECTSHOW
765
766 //---------------------------------------------------------------------------
767 //
768 // wxMCIMediaBackend
769 //
770 //---------------------------------------------------------------------------
771
772 //---------------------------------------------------------------------------
773 // MCI Includes
774 //---------------------------------------------------------------------------
775 #include <mmsystem.h>
776
777 class WXDLLIMPEXP_MEDIA wxMCIMediaBackend : public wxMediaBackend
778 {
779 public:
780
781 wxMCIMediaBackend();
782 ~wxMCIMediaBackend();
783
784 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
785 wxWindowID id,
786 const wxPoint& pos,
787 const wxSize& size,
788 long style,
789 const wxValidator& validator,
790 const wxString& name);
791
792 virtual bool Play();
793 virtual bool Pause();
794 virtual bool Stop();
795
796 virtual bool Load(const wxString& fileName);
797 virtual bool Load(const wxURI& location);
798
799 virtual wxMediaState GetState();
800
801 virtual bool SetPosition(wxLongLong where);
802 virtual wxLongLong GetPosition();
803 virtual wxLongLong GetDuration();
804
805 virtual void Move(int x, int y, int w, int h);
806 wxSize GetVideoSize() const;
807
808 virtual double GetPlaybackRate();
809 virtual bool SetPlaybackRate(double dRate);
810
811 static LRESULT CALLBACK NotifyWndProc(HWND hWnd, UINT nMsg,
812 WPARAM wParam, LPARAM lParam);
813
814 LRESULT CALLBACK OnNotifyWndProc(HWND hWnd, UINT nMsg,
815 WPARAM wParam, LPARAM lParam);
816
817 MCIDEVICEID m_hDev; //Our MCI Device ID/Handler
818 wxControl* m_ctrl; //Parent control
819 HWND m_hNotifyWnd; //Window to use for MCI events
820 bool m_bVideo; //Whether or not we have video
821
822 DECLARE_DYNAMIC_CLASS(wxMCIMediaBackend)
823 };
824
825 //---------------------------------------------------------------------------
826 //
827 // wxQTMediaBackend
828 //
829 //---------------------------------------------------------------------------
830
831 //---------------------------------------------------------------------------
832 // QT Compilation Guard
833 //---------------------------------------------------------------------------
834 #if wxUSE_QUICKTIME
835
836 //---------------------------------------------------------------------------
837 // QT Includes
838 //---------------------------------------------------------------------------
839 #include <qtml.h> //Windoze QT include
840 #include <QuickTimeComponents.h> //Standard QT stuff
841
842 class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackend
843 {
844 public:
845
846 wxQTMediaBackend();
847 ~wxQTMediaBackend();
848
849 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
850 wxWindowID id,
851 const wxPoint& pos,
852 const wxSize& size,
853 long style,
854 const wxValidator& validator,
855 const wxString& name);
856
857 virtual bool Play();
858 virtual bool Pause();
859 virtual bool Stop();
860
861 virtual bool Load(const wxString& fileName);
862 virtual bool Load(const wxURI& location);
863
864 virtual wxMediaState GetState();
865
866 virtual bool SetPosition(wxLongLong where);
867 virtual wxLongLong GetPosition();
868 virtual wxLongLong GetDuration();
869
870 virtual void Move(int x, int y, int w, int h);
871 wxSize GetVideoSize() const;
872
873 virtual double GetPlaybackRate();
874 virtual bool SetPlaybackRate(double dRate);
875
876 void Cleanup();
877 void FinishLoad();
878
879 wxSize m_bestSize; //Original movie size
880 struct MovieRecord* m_movie; //QT Movie handle/instance
881 wxControl* m_ctrl; //Parent control
882 bool m_bVideo; //Whether or not we have video
883 class _wxQTTimer* m_timer; //Timer for streaming the movie
884
885 DECLARE_DYNAMIC_CLASS(wxQTMediaBackend);
886 };
887
888 //---------------------------------------------------------------------------
889 // End QT Compilation Guard
890 //---------------------------------------------------------------------------
891 #endif //wxUSE_QUICKTIME
892
893 //===========================================================================
894 // IMPLEMENTATION
895 //===========================================================================
896
897 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
898 //
899 // wxAMMediaBackend
900 //
901 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
902
903 //---------------------------------------------------------------------------
904 // Only use if user wants it -
905 //---------------------------------------------------------------------------
906 #if wxUSE_DIRECTSHOW
907
908 IMPLEMENT_DYNAMIC_CLASS(wxAMMediaBackend, wxMediaBackend);
909
910 // Numerical value for when the graph reaches the stop position
911 #define WM_GRAPHNOTIFY WM_USER+13
912
913 //---------------------------------------------------------------------------
914 // Usual debugging macros
915 //---------------------------------------------------------------------------
916 #ifdef __WXDEBUG__
917 #define wxAMVERIFY(x) \
918 { \
919 HRESULT hrdsv = (x); \
920 if ( FAILED(hrdsv) ) \
921 { \
922 /*TCHAR szError[MAX_ERROR_TEXT_LEN];*/ \
923 /*if( AMGetErrorText(hrdsv, szError, MAX_ERROR_TEXT_LEN) == 0)*/ \
924 /*{*/ \
925 /*wxFAIL_MSG( wxString::Format(wxT("DirectShow error \"%s\" ")*/\
926 /*wxT("occured at line %i in ")*/ \
927 /*wxT("mediactrl.cpp"),*/ \
928 /*szError, __LINE__) );*/ \
929 /*}*/ \
930 /*else*/ \
931 wxFAIL_MSG( wxString::Format(wxT("Unknown error (%i) ") \
932 wxT("occured at") \
933 wxT(" line %i in mediactrl.cpp."), \
934 (int)hrdsv, __LINE__) ); \
935 } \
936 }
937 #define wxVERIFY(x) wxASSERT((x))
938 #else
939 #define wxAMVERIFY(x) (x)
940 #define wxVERIFY(x) (x)
941 #endif
942
943 //---------------------------------------------------------------------------
944 // Standard macros for ease of use
945 //---------------------------------------------------------------------------
946 #define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
947
948 //---------------------------------------------------------------------------
949 // wxAMMediaBackend Constructor
950 //
951 // Sets m_hNotifyWnd to NULL to signify that we haven't loaded anything yet
952 //---------------------------------------------------------------------------
953 wxAMMediaBackend::wxAMMediaBackend() : m_hNotifyWnd(NULL)
954 {
955 }
956
957 //---------------------------------------------------------------------------
958 // wxAMMediaBackend Destructor
959 //
960 // Cleans up everything
961 //---------------------------------------------------------------------------
962 wxAMMediaBackend::~wxAMMediaBackend()
963 {
964 if (m_hNotifyWnd)
965 Cleanup();
966 }
967
968 //---------------------------------------------------------------------------
969 // wxAMMediaBackend::CreateControl
970 //
971 // ActiveMovie does not really have any native control to speak of,
972 // so we just create a normal control.
973 //
974 // We also check to see if ActiveMovie is installed
975 //---------------------------------------------------------------------------
976 bool wxAMMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
977 wxWindowID id,
978 const wxPoint& pos,
979 const wxSize& size,
980 long style,
981 const wxValidator& validator,
982 const wxString& name)
983 {
984 //create our filter graph - the beuty of COM is that it loads
985 //quartz.dll for us :)
986 HRESULT hr = CoCreateInstance(CLSID_FilgraphManager, NULL, CLSCTX_INPROC_SERVER,
987 IID_IMediaControl, (void**)&m_pMC);
988
989 //directshow not installed?
990 if ( FAILED(hr) )
991 return false;
992
993 //release the filter graph - we don't need it yet
994 m_pMC->Release();
995 m_pMC = NULL;
996
997 //
998 // Create window
999 // By default wxWindow(s) is created with a border -
1000 // so we need to get rid of those, and create with
1001 // wxCLIP_CHILDREN, so that if the driver/backend
1002 // is a child window, it refereshes properly
1003 //
1004 if ( !ctrl->wxControl::Create(parent, id, pos, size,
1005 (style & ~wxBORDER_MASK) | wxBORDER_NONE | wxCLIP_CHILDREN,
1006 validator, name) )
1007 return false;
1008
1009 m_ctrl = ctrl;
1010 return true;
1011 }
1012
1013
1014 //---------------------------------------------------------------------------
1015 // wxAMMediaBackend::Load (file version)
1016 //
1017 // Creates an Active Movie filter graph from a file or url
1018 //---------------------------------------------------------------------------
1019 bool wxAMMediaBackend::Load(const wxString& fileName)
1020 {
1021 //if previously loaded cleanup
1022 if(m_hNotifyWnd)
1023 Cleanup();
1024
1025 //We already checked for success in CreateControl
1026 CoCreateInstance(CLSID_FilgraphManager, NULL, CLSCTX_INPROC_SERVER,
1027 IID_IMediaControl, (void**)&m_pMC);
1028
1029 //load the graph & render
1030 if( FAILED(m_pMC->RenderFile(wxBasicString(fileName).Get())) )
1031 return false;
1032
1033 //get the interfaces, all of them
1034 wxAMVERIFY( m_pMC->QueryInterface(IID_IMediaEventEx, (void**)&m_pME) );
1035 wxAMVERIFY( m_pMC->QueryInterface(IID_IMediaPosition, (void**)&m_pMS) );
1036 wxAMVERIFY( m_pMC->QueryInterface(IID_IVideoWindow, (void**)&m_pVW) );
1037 wxAMVERIFY( m_pMC->QueryInterface(IID_IBasicAudio, (void**)&m_pBA) );
1038 wxAMVERIFY( m_pMC->QueryInterface(IID_IBasicVideo, (void**)&m_pBV) );
1039
1040 //We could tell if the media has audio or not by
1041 //something like
1042 //-----
1043 //long lVolume;
1044 //pBA->get_Volume(&lVolume) == E_NOTIMPL
1045 //-----
1046 //here...
1047
1048 //
1049 //Obtain the _actual_ size of the movie & remember it
1050 //
1051 long nX,
1052 nY;
1053
1054 m_bestSize.x = m_bestSize.y = 0;
1055
1056 m_bVideo = SUCCEEDED( m_pVW->GetWindowPosition( &nX,
1057 &nY,
1058 (long*)&m_bestSize.x,
1059 (long*)&m_bestSize.y) );
1060
1061 //
1062 //If we have video in the media - set it up so that
1063 //its a child window of the control, its visible,
1064 //and that the control is the owner of the video window
1065 //
1066 if (m_bVideo)
1067 {
1068 wxAMVERIFY( m_pVW->put_Owner((LONG_PTR)m_ctrl->GetHandle()) );
1069 wxAMVERIFY( m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS) );
1070 wxAMVERIFY( m_pVW->put_Visible(-1) ); //OATRUE == -1
1071 }
1072
1073 //
1074 // Create a hidden window and register to handle
1075 // directshow events for this graph
1076 // Note that wxCanvasClassName is already registered
1077 // and used by all wxWindows and normal wxControls
1078 //
1079 m_hNotifyWnd = ::CreateWindow
1080 (
1081 wxCanvasClassName,
1082 NULL,
1083 0, 0, 0, 0,
1084 0,
1085 (HWND) NULL,
1086 (HMENU)NULL,
1087 wxGetInstance(),
1088 (LPVOID) NULL
1089 );
1090
1091 if(!m_hNotifyWnd)
1092 {
1093 wxLogSysError( wxT("Could not create hidden needed for ")
1094 wxT("registering for DirectShow events!") );
1095
1096 return false;
1097 }
1098
1099 ::SetWindowLongPtr(m_hNotifyWnd, GWLP_WNDPROC,
1100 (LONG_PTR)wxAMMediaBackend::NotifyWndProc);
1101
1102 ::SetWindowLong(m_hNotifyWnd, GWL_USERDATA,
1103 (LONG) this);
1104
1105 wxAMVERIFY( m_pME->SetNotifyWindow((LONG_PTR)m_hNotifyWnd,
1106 WM_GRAPHNOTIFY, 0) );
1107
1108 //
1109 // Force the parent window of this control to recalculate
1110 // the size of this if sizers are being used
1111 // and render the results immediately
1112 //
1113 m_ctrl->InvalidateBestSize();
1114 m_ctrl->GetParent()->Layout();
1115 m_ctrl->GetParent()->Refresh();
1116 m_ctrl->GetParent()->Update();
1117
1118 return true;
1119 }
1120
1121 //---------------------------------------------------------------------------
1122 // wxAMMediaBackend::Load (URL Version)
1123 //
1124 // Loads media from a URL. Interestingly enough DirectShow
1125 // appears (?) to escape the URL for us, at least on normal
1126 // files
1127 //---------------------------------------------------------------------------
1128 bool wxAMMediaBackend::Load(const wxURI& location)
1129 {
1130 return Load(location.BuildUnescapedURI());
1131 }
1132
1133 //---------------------------------------------------------------------------
1134 // wxAMMediaBackend::Play
1135 //
1136 // Plays the stream. If it is non-seekable, it will restart it.
1137 //---------------------------------------------------------------------------
1138 bool wxAMMediaBackend::Play()
1139 {
1140 return SUCCEEDED( m_pMC->Run() );
1141 }
1142
1143 //---------------------------------------------------------------------------
1144 // wxAMMediaBackend::Pause
1145 //
1146 // Pauses the stream.
1147 //---------------------------------------------------------------------------
1148 bool wxAMMediaBackend::Pause()
1149 {
1150 return SUCCEEDED( m_pMC->Pause() );
1151 }
1152
1153 //---------------------------------------------------------------------------
1154 // wxAMMediaBackend::Stop
1155 //
1156 // Stops the stream.
1157 //---------------------------------------------------------------------------
1158 bool wxAMMediaBackend::Stop()
1159 {
1160 bool bOK = SUCCEEDED( m_pMC->Stop() );
1161
1162 //We don't care if it can't get to the beginning in directshow -
1163 //it could be a non-seeking filter (wince midi) in which case playing
1164 //starts all over again
1165 SetPosition(0);
1166 return bOK;
1167 }
1168
1169 //---------------------------------------------------------------------------
1170 // wxAMMediaBackend::SetPosition
1171 //
1172 // 1) Translates the current position's time to directshow time,
1173 // which is in a scale of 1 second (in a double)
1174 // 2) Sets the play position of the IMediaSeeking interface -
1175 // passing NULL as the stop position means to keep the old
1176 // stop position
1177 //---------------------------------------------------------------------------
1178 bool wxAMMediaBackend::SetPosition(wxLongLong where)
1179 {
1180 return SUCCEEDED( m_pMS->put_CurrentPosition(
1181 ((LONGLONG)where.GetValue()) / 1000
1182 )
1183 );
1184 }
1185
1186 //---------------------------------------------------------------------------
1187 // wxAMMediaBackend::GetPosition
1188 //
1189 // 1) Obtains the current play and stop positions from IMediaSeeking
1190 // 2) Returns the play position translated to our time base
1191 //---------------------------------------------------------------------------
1192 wxLongLong wxAMMediaBackend::GetPosition()
1193 {
1194 double outCur;
1195 wxAMVERIFY( m_pMS->get_CurrentPosition(&outCur) );
1196
1197 //h,m,s,milli - outdur is in 1 second (double)
1198 return (outCur*1000);
1199 }
1200
1201 //---------------------------------------------------------------------------
1202 // wxAMMediaBackend::GetDuration
1203 //
1204 // 1) Obtains the duration of the media from the IMediaSeeking interface
1205 // 2) Converts that value to our time base, and returns it
1206 //---------------------------------------------------------------------------
1207 wxLongLong wxAMMediaBackend::GetDuration()
1208 {
1209 double outDuration;
1210 wxAMVERIFY( m_pMS->get_Duration(&outDuration) );
1211
1212 //h,m,s,milli - outdur is in 1 second (double)
1213 return (outDuration*1000);
1214 }
1215
1216 //---------------------------------------------------------------------------
1217 // wxAMMediaBackend::GetState
1218 //
1219 // Obtains the state from the IMediaControl interface.
1220 // Note that it's enumeration values for stopping/playing
1221 // etc. are the same as ours, so we just do a straight cast.
1222 // TODO: MS recommends against INFINITE here for
1223 // IMediaControl::GetState- do it in stages
1224 //---------------------------------------------------------------------------
1225 wxMediaState wxAMMediaBackend::GetState()
1226 {
1227 HRESULT hr;
1228 long theState; //OAFilterState
1229 hr = m_pMC->GetState(INFINITE, &theState);
1230
1231 wxASSERT( SUCCEEDED(hr) );
1232
1233 //MSW state is the same as ours
1234 //State_Stopped = 0,
1235 //State_Paused = State_Stopped + 1,
1236 //State_Running = State_Paused + 1
1237
1238 return (wxMediaState) theState;
1239 }
1240
1241 //---------------------------------------------------------------------------
1242 // wxAMMediaBackend::GetPlaybackRate
1243 //
1244 // Pretty simple way of obtaining the playback rate from
1245 // the IMediaSeeking interface
1246 //---------------------------------------------------------------------------
1247 double wxAMMediaBackend::GetPlaybackRate()
1248 {
1249 double dRate;
1250 wxAMVERIFY( m_pMS->get_Rate(&dRate) );
1251 return dRate;
1252 }
1253
1254 //---------------------------------------------------------------------------
1255 // wxAMMediaBackend::SetPlaybackRate
1256 //
1257 // Sets the playback rate of the media - DirectShow is pretty good
1258 // about this, actually
1259 //---------------------------------------------------------------------------
1260 bool wxAMMediaBackend::SetPlaybackRate(double dRate)
1261 {
1262 return SUCCEEDED( m_pMS->put_Rate(dRate) );
1263 }
1264
1265 //---------------------------------------------------------------------------
1266 // wxAMMediaBackend::NotifyWndProc
1267 //
1268 // Here we check to see if DirectShow tells us we've reached the stop
1269 // position in our stream - if it has, it may not actually stop
1270 // the stream - which we need to do...
1271 //---------------------------------------------------------------------------
1272 LRESULT CALLBACK wxAMMediaBackend::NotifyWndProc(HWND hWnd, UINT nMsg,
1273 WPARAM wParam,
1274 LPARAM lParam)
1275 {
1276 wxAMMediaBackend* backend = (wxAMMediaBackend*)
1277 ::GetWindowLong(hWnd, GWL_USERDATA);
1278
1279 return backend->OnNotifyWndProc(hWnd, nMsg, wParam, lParam);
1280 }
1281
1282 LRESULT CALLBACK wxAMMediaBackend::OnNotifyWndProc(HWND hWnd, UINT nMsg,
1283 WPARAM wParam,
1284 LPARAM lParam)
1285 {
1286 if (nMsg == WM_GRAPHNOTIFY)
1287 {
1288 LONG evCode,
1289 evParam1,
1290 evParam2;
1291
1292 //
1293 // DirectShow keeps a list of queued events, and we need
1294 // to go through them one by one, stopping at (Hopefully only one)
1295 // EC_COMPLETE message
1296 //
1297 while(SUCCEEDED(m_pME->GetEvent(&evCode, (LONG_PTR *) &evParam1,
1298 (LONG_PTR *) &evParam2, 0)
1299 )
1300 )
1301 {
1302 // Cleanup memory that GetEvent allocated
1303 wxAMVERIFY( m_pME->FreeEventParams(evCode, evParam1, evParam2) );
1304
1305 // If this is the end of the clip, notify handler
1306 if(1 == evCode) //EC_COMPLETE
1307 {
1308 //send the event to our child
1309 wxMediaEvent theEvent(wxEVT_MEDIA_STOP, m_ctrl->GetId());
1310 m_ctrl->ProcessEvent(theEvent);
1311
1312 //if the user didn't veto it, stop the stream
1313 if (theEvent.IsAllowed())
1314 {
1315 //Interestingly enough, DirectShow does not actually stop
1316 //the filters - even when it reaches the end!
1317 wxVERIFY( Stop() );
1318
1319 //send the event to our child
1320 wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED,
1321 m_ctrl->GetId());
1322 m_ctrl->ProcessEvent(theEvent);
1323 }
1324 }
1325 }
1326 }
1327 return DefWindowProc(hWnd, nMsg, wParam, lParam);
1328 }
1329
1330 //---------------------------------------------------------------------------
1331 // wxAMMediaBackend::Cleanup
1332 //
1333 // 1) Hide/disowns the video window (MS says bad things will happen if
1334 // you don't)
1335 // 2) Releases all the directshow interfaces we use
1336 // TODO: Maybe there's a way to redirect the IMediaControl each time
1337 // we load, rather then creating and destroying the interfaces
1338 // each time?
1339 //---------------------------------------------------------------------------
1340 void wxAMMediaBackend::Cleanup()
1341 {
1342 // Hide then disown the window
1343 if(m_pVW)
1344 {
1345 m_pVW->put_Visible(0); //OSFALSE == 0
1346 m_pVW->put_Owner(NULL);
1347 }
1348
1349 // Release and zero DirectShow interfaces
1350 SAFE_RELEASE(m_pME);
1351 SAFE_RELEASE(m_pMS);
1352 SAFE_RELEASE(m_pBA);
1353 SAFE_RELEASE(m_pBV);
1354 SAFE_RELEASE(m_pVW);
1355 SAFE_RELEASE(m_pMC);
1356
1357 // Get rid of our hidden Window
1358 DestroyWindow(m_hNotifyWnd);
1359 m_hNotifyWnd = NULL;
1360 }
1361
1362
1363 //---------------------------------------------------------------------------
1364 // wxAMMediaBackend::GetVideoSize
1365 //
1366 // Obtains the cached original video size
1367 //---------------------------------------------------------------------------
1368 wxSize wxAMMediaBackend::GetVideoSize() const
1369 {
1370 return m_bestSize;
1371 }
1372
1373 //---------------------------------------------------------------------------
1374 // wxAMMediaBackend::Move
1375 //
1376 // Resizes the IVideoWindow to the size of the control window
1377 //---------------------------------------------------------------------------
1378 void wxAMMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y), int w, int h)
1379 {
1380 if(m_hNotifyWnd && m_bVideo)
1381 {
1382 wxAMVERIFY( m_pVW->SetWindowPosition(0, 0, w, h) );
1383 }
1384 }
1385
1386 //---------------------------------------------------------------------------
1387 // End of wxAMMediaBackend
1388 //---------------------------------------------------------------------------
1389 #endif //wxUSE_DIRECTSHOW
1390
1391 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1392 //
1393 // wxMCIMediaBackend
1394 //
1395 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1396
1397
1398 IMPLEMENT_DYNAMIC_CLASS(wxMCIMediaBackend, wxMediaBackend);
1399
1400 //---------------------------------------------------------------------------
1401 // Usual debugging macros for MCI returns
1402 //---------------------------------------------------------------------------
1403
1404 #ifdef __WXDEBUG__
1405 #define wxMCIVERIFY(arg) \
1406 { \
1407 DWORD nRet; \
1408 if ( (nRet = (arg)) != 0) \
1409 { \
1410 TCHAR sz[5000]; \
1411 mciGetErrorString(nRet, sz, 5000); \
1412 wxFAIL_MSG(wxString::Format(_T("MCI Error:%s"), sz)); \
1413 } \
1414 }
1415 #else
1416 #define wxMCIVERIFY(arg) (arg);
1417 #endif
1418
1419 //---------------------------------------------------------------------------
1420 // Simulation for <digitalv.h>
1421 //
1422 // Mingw and possibly other compilers don't have the digitalv.h header
1423 // that is needed to have some essential features of mci work with
1424 // windows - so we provide the declarations for the types we use here
1425 //---------------------------------------------------------------------------
1426
1427 typedef struct {
1428 DWORD_PTR dwCallback;
1429 #ifdef MCI_USE_OFFEXT
1430 POINT ptOffset;
1431 POINT ptExtent;
1432 #else
1433 RECT rc;
1434 #endif
1435 } MCI_DGV_RECT_PARMS;
1436
1437 typedef struct {
1438 DWORD_PTR dwCallback;
1439 HWND hWnd;
1440 #ifndef _WIN32
1441 WORD wReserved1;
1442 #endif
1443 UINT nCmdShow;
1444 #ifndef _WIN32
1445 WORD wReserved2;
1446 #endif
1447 wxChar* lpstrText;
1448 } MCI_DGV_WINDOW_PARMS;
1449
1450 typedef struct {
1451 DWORD_PTR dwCallback;
1452 DWORD dwTimeFormat;
1453 DWORD dwAudio;
1454 DWORD dwFileFormat;
1455 DWORD dwSpeed;
1456 } MCI_DGV_SET_PARMS;
1457
1458 //---------------------------------------------------------------------------
1459 // wxMCIMediaBackend Constructor
1460 //
1461 // Here we don't need to do much except say we don't have any video :)
1462 //---------------------------------------------------------------------------
1463 wxMCIMediaBackend::wxMCIMediaBackend() : m_hNotifyWnd(NULL), m_bVideo(false)
1464 {
1465 }
1466
1467 //---------------------------------------------------------------------------
1468 // wxMCIMediaBackend Destructor
1469 //
1470 // We close the mci device - note that there may not be an mci device here,
1471 // or it may fail - but we don't really care, since we're destructing
1472 //---------------------------------------------------------------------------
1473 wxMCIMediaBackend::~wxMCIMediaBackend()
1474 {
1475 if(m_hNotifyWnd)
1476 {
1477 mciSendCommand(m_hDev, MCI_CLOSE, 0, 0);
1478 DestroyWindow(m_hNotifyWnd);
1479 m_hNotifyWnd = NULL;
1480 }
1481 }
1482
1483 //---------------------------------------------------------------------------
1484 // wxMCIMediaBackend::Create
1485 //
1486 // Here we just tell wxMediaCtrl that mci does exist (which it does, on all
1487 // msw systems, at least in some form dating back to win16 days)
1488 //---------------------------------------------------------------------------
1489 bool wxMCIMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
1490 wxWindowID id,
1491 const wxPoint& pos,
1492 const wxSize& size,
1493 long style,
1494 const wxValidator& validator,
1495 const wxString& name)
1496 {
1497 //
1498 // Create window
1499 // By default wxWindow(s) is created with a border -
1500 // so we need to get rid of those, and create with
1501 // wxCLIP_CHILDREN, so that if the driver/backend
1502 // is a child window, it refereshes properly
1503 //
1504 if ( !ctrl->wxControl::Create(parent, id, pos, size,
1505 (style & ~wxBORDER_MASK) | wxBORDER_NONE | wxCLIP_CHILDREN,
1506 validator, name) )
1507 return false;
1508
1509 m_ctrl = ctrl;
1510 return true;
1511 }
1512
1513 //---------------------------------------------------------------------------
1514 // wxMCIMediaBackend::Load (file version)
1515 //
1516 // Here we have MCI load a file and device, set the time format to our
1517 // default (milliseconds), and set the video (if any) to play in the control
1518 //---------------------------------------------------------------------------
1519 bool wxMCIMediaBackend::Load(const wxString& fileName)
1520 {
1521 //
1522 //if the user already called load close the previous MCI device
1523 //
1524 if(m_hNotifyWnd)
1525 {
1526 mciSendCommand(m_hDev, MCI_CLOSE, 0, 0);
1527 DestroyWindow(m_hNotifyWnd);
1528 m_hNotifyWnd = NULL;
1529 }
1530
1531 //
1532 //Opens a file and has MCI select a device. Normally you'd put
1533 //MCI_OPEN_TYPE in addition to MCI_OPEN_ELEMENT - however if you
1534 //omit this it tells MCI to select the device instead. This is
1535 //good because we have no reliable way of "enumerating" the devices
1536 //in MCI
1537 //
1538 MCI_OPEN_PARMS openParms;
1539 openParms.lpstrElementName = (wxChar*) fileName.c_str();
1540
1541 if ( mciSendCommand(0, MCI_OPEN, MCI_OPEN_ELEMENT,
1542 (DWORD)(LPVOID)&openParms) != 0)
1543 return false;
1544
1545 m_hDev = openParms.wDeviceID;
1546
1547 //
1548 //Now set the time format for the device to milliseconds
1549 //
1550 MCI_SET_PARMS setParms;
1551 setParms.dwCallback = 0;
1552 setParms.dwTimeFormat = MCI_FORMAT_MILLISECONDS;
1553
1554 if (mciSendCommand(m_hDev, MCI_SET, MCI_SET_TIME_FORMAT,
1555 (DWORD)(LPVOID)&setParms) != 0)
1556 return false;
1557
1558 //
1559 //Now tell the MCI device to display the video in our wxMediaCtrl
1560 //
1561 MCI_DGV_WINDOW_PARMS windowParms;
1562 windowParms.hWnd = (HWND)m_ctrl->GetHandle();
1563
1564 m_bVideo = (mciSendCommand(m_hDev, MCI_WINDOW,
1565 0x00010000L, //MCI_DGV_WINDOW_HWND
1566 (DWORD)(LPVOID)&windowParms) == 0);
1567
1568 //
1569 // Create a hidden window and register to handle
1570 // MCI events
1571 // Note that wxCanvasClassName is already registered
1572 // and used by all wxWindows and normal wxControls
1573 //
1574 m_hNotifyWnd = ::CreateWindow
1575 (
1576 wxCanvasClassName,
1577 NULL,
1578 0, 0, 0, 0,
1579 0,
1580 (HWND) NULL,
1581 (HMENU)NULL,
1582 wxGetInstance(),
1583 (LPVOID) NULL
1584 );
1585
1586 if(!m_hNotifyWnd)
1587 {
1588 wxLogSysError( wxT("Could not create hidden needed for ")
1589 wxT("registering for DirectShow events!") );
1590
1591 return false;
1592 }
1593
1594 ::SetWindowLong(m_hNotifyWnd, GWL_WNDPROC,
1595 (LONG)wxMCIMediaBackend::NotifyWndProc);
1596
1597 ::SetWindowLong(m_hNotifyWnd, GWL_USERDATA,
1598 (LONG) this);
1599
1600 //
1601 //Here, if the parent of the control has a sizer - we
1602 //tell it to recalculate the size of this control since
1603 //the user opened a seperate media file
1604 //
1605 m_ctrl->InvalidateBestSize();
1606 m_ctrl->GetParent()->Layout();
1607 m_ctrl->GetParent()->Refresh();
1608 m_ctrl->GetParent()->Update();
1609
1610 return true;
1611 }
1612
1613 //---------------------------------------------------------------------------
1614 // wxMCIMediaBackend::Load (URL version)
1615 //
1616 // MCI doesn't support URLs directly (?)
1617 //
1618 // TODO: Use wxURL/wxFileSystem and mmioInstallProc
1619 //---------------------------------------------------------------------------
1620 bool wxMCIMediaBackend::Load(const wxURI& WXUNUSED(location))
1621 {
1622 return false;
1623 }
1624
1625 //---------------------------------------------------------------------------
1626 // wxMCIMediaBackend::Play
1627 //
1628 // Plays/Resumes the MCI device... a couple notes:
1629 // 1) Certain drivers will crash and burn if we don't pass them an
1630 // MCI_PLAY_PARMS, despite the documentation that says otherwise...
1631 // 2) There is a MCI_RESUME command, but MCI_PLAY does the same thing
1632 // and will resume from a stopped state also, so there's no need to
1633 // call both, for example
1634 //---------------------------------------------------------------------------
1635 bool wxMCIMediaBackend::Play()
1636 {
1637 MCI_PLAY_PARMS playParms;
1638 playParms.dwCallback = (DWORD)m_hNotifyWnd;
1639
1640 bool bOK = ( mciSendCommand(m_hDev, MCI_PLAY, MCI_NOTIFY,
1641 (DWORD)(LPVOID)&playParms) == 0 );
1642
1643 if(bOK)
1644 m_ctrl->Show(m_bVideo);
1645
1646 return bOK;
1647 }
1648
1649 //---------------------------------------------------------------------------
1650 // wxMCIMediaBackend::Pause
1651 //
1652 // Pauses the MCI device - nothing special
1653 //---------------------------------------------------------------------------
1654 bool wxMCIMediaBackend::Pause()
1655 {
1656 return (mciSendCommand(m_hDev, MCI_PAUSE, MCI_WAIT, 0) == 0);
1657 }
1658
1659 //---------------------------------------------------------------------------
1660 // wxMCIMediaBackend::Stop
1661 //
1662 // Stops the MCI device & seeks to the beginning as wxMediaCtrl docs outline
1663 //---------------------------------------------------------------------------
1664 bool wxMCIMediaBackend::Stop()
1665 {
1666 return (mciSendCommand(m_hDev, MCI_STOP, MCI_WAIT, 0) == 0) &&
1667 (mciSendCommand(m_hDev, MCI_SEEK, MCI_SEEK_TO_START, 0) == 0);
1668 }
1669
1670 //---------------------------------------------------------------------------
1671 // wxMCIMediaBackend::GetState
1672 //
1673 // Here we get the state and convert it to a wxMediaState -
1674 // since we use direct comparisons with MCI_MODE_PLAY and
1675 // MCI_MODE_PAUSE, we don't care if the MCI_STATUS call
1676 // fails or not
1677 //---------------------------------------------------------------------------
1678 wxMediaState wxMCIMediaBackend::GetState()
1679 {
1680 MCI_STATUS_PARMS statusParms;
1681 statusParms.dwItem = MCI_STATUS_MODE;
1682
1683 mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
1684 (DWORD)(LPVOID)&statusParms);
1685
1686 if(statusParms.dwReturn == MCI_MODE_PAUSE)
1687 return wxMEDIASTATE_PAUSED;
1688 else if(statusParms.dwReturn == MCI_MODE_PLAY)
1689 return wxMEDIASTATE_PLAYING;
1690 else
1691 return wxMEDIASTATE_STOPPED;
1692 }
1693
1694 //---------------------------------------------------------------------------
1695 // wxMCIMediaBackend::SetPosition
1696 //
1697 // Here we set the position of the device in the stream.
1698 // Note that MCI actually stops the device after you seek it if the
1699 // device is playing/paused, so we need to play the file after
1700 // MCI seeks like normal APIs would
1701 //---------------------------------------------------------------------------
1702 bool wxMCIMediaBackend::SetPosition(wxLongLong where)
1703 {
1704 MCI_SEEK_PARMS seekParms;
1705 seekParms.dwCallback = 0;
1706 #if wxUSE_LONGLONG_NATIVE && !wxUSE_LONGLONG_WX
1707 seekParms.dwTo = (DWORD)where.GetValue();
1708 #else /* wxUSE_LONGLONG_WX */
1709 /* no way to return it in one piece */
1710 wxASSERT( where.GetHi()==0 );
1711 seekParms.dwTo = (DWORD)where.GetLo();
1712 #endif /* wxUSE_LONGLONG_* */
1713
1714 //device was playing?
1715 bool bReplay = GetState() == wxMEDIASTATE_PLAYING;
1716
1717 if( mciSendCommand(m_hDev, MCI_SEEK, MCI_TO,
1718 (DWORD)(LPVOID)&seekParms) != 0)
1719 return false;
1720
1721 //If the device was playing, resume it
1722 if (bReplay)
1723 return Play();
1724 else
1725 return true;
1726 }
1727
1728 //---------------------------------------------------------------------------
1729 // wxMCIMediaBackend::GetPosition
1730 //
1731 // Gets the position of the device in the stream using the current
1732 // time format... nothing special here...
1733 //---------------------------------------------------------------------------
1734 wxLongLong wxMCIMediaBackend::GetPosition()
1735 {
1736 MCI_STATUS_PARMS statusParms;
1737 statusParms.dwItem = MCI_STATUS_POSITION;
1738
1739 if (mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
1740 (DWORD)(LPSTR)&statusParms) != 0)
1741 return 0;
1742
1743 return statusParms.dwReturn;
1744 }
1745
1746 //---------------------------------------------------------------------------
1747 // wxMCIMediaBackend::GetDuration
1748 //
1749 // Gets the duration of the stream... nothing special
1750 //---------------------------------------------------------------------------
1751 wxLongLong wxMCIMediaBackend::GetDuration()
1752 {
1753 MCI_STATUS_PARMS statusParms;
1754 statusParms.dwItem = MCI_STATUS_LENGTH;
1755
1756 if (mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
1757 (DWORD)(LPSTR)&statusParms) != 0)
1758 return 0;
1759
1760 return statusParms.dwReturn;
1761 }
1762
1763 //---------------------------------------------------------------------------
1764 // wxMCIMediaBackend::Move
1765 //
1766 // Moves the window to a location
1767 //---------------------------------------------------------------------------
1768 void wxMCIMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y),
1769 int w, int h)
1770 {
1771 if (m_hNotifyWnd && m_bVideo)
1772 {
1773 MCI_DGV_RECT_PARMS putParms; //ifdefed MCI_DGV_PUT_PARMS
1774 putParms.rc.top = 0;
1775 putParms.rc.bottom = 0;
1776 putParms.rc.right = w;
1777 putParms.rc.bottom = h;
1778
1779 wxMCIVERIFY( mciSendCommand(m_hDev, MCI_PUT,
1780 0x00040000L, //MCI_DGV_PUT_DESTINATION
1781 (DWORD)(LPSTR)&putParms) );
1782 }
1783 }
1784
1785 //---------------------------------------------------------------------------
1786 // wxMCIMediaBackend::GetVideoSize
1787 //
1788 // Gets the original size of the movie for sizers
1789 //---------------------------------------------------------------------------
1790 wxSize wxMCIMediaBackend::GetVideoSize() const
1791 {
1792 if(m_bVideo)
1793 {
1794 MCI_DGV_RECT_PARMS whereParms; //ifdefed MCI_DGV_WHERE_PARMS
1795
1796 wxMCIVERIFY( mciSendCommand(m_hDev, MCI_WHERE,
1797 0x00020000L, //MCI_DGV_WHERE_SOURCE
1798 (DWORD)(LPSTR)&whereParms) );
1799
1800 return wxSize(whereParms.rc.right, whereParms.rc.bottom);
1801 }
1802 return wxSize(0,0);
1803 }
1804
1805 //---------------------------------------------------------------------------
1806 // wxMCIMediaBackend::GetPlaybackRate
1807 //
1808 // TODO
1809 //---------------------------------------------------------------------------
1810 double wxMCIMediaBackend::GetPlaybackRate()
1811 {
1812 return 1.0;
1813 }
1814
1815 //---------------------------------------------------------------------------
1816 // wxMCIMediaBackend::SetPlaybackRate
1817 //
1818 // TODO
1819 //---------------------------------------------------------------------------
1820 bool wxMCIMediaBackend::SetPlaybackRate(double WXUNUSED(dRate))
1821 {
1822 /*
1823 MCI_WAVE_SET_SAMPLESPERSEC
1824 MCI_DGV_SET_PARMS setParms;
1825 setParms.dwSpeed = (DWORD) (dRate * 1000.0);
1826
1827 return (mciSendCommand(m_hDev, MCI_SET,
1828 0x00020000L, //MCI_DGV_SET_SPEED
1829 (DWORD)(LPSTR)&setParms) == 0);
1830 */
1831 return false;
1832 }
1833
1834 //---------------------------------------------------------------------------
1835 // [static] wxMCIMediaBackend::MSWWindowProc
1836 //
1837 // Here we process a message when MCI reaches the stopping point
1838 // in the stream
1839 //---------------------------------------------------------------------------
1840 LRESULT CALLBACK wxMCIMediaBackend::NotifyWndProc(HWND hWnd, UINT nMsg,
1841 WPARAM wParam,
1842 LPARAM lParam)
1843 {
1844 wxMCIMediaBackend* backend = (wxMCIMediaBackend*)
1845 ::GetWindowLong(hWnd, GWL_USERDATA);
1846 wxASSERT(backend);
1847
1848 return backend->OnNotifyWndProc(hWnd, nMsg, wParam, lParam);
1849 }
1850
1851 LRESULT CALLBACK wxMCIMediaBackend::OnNotifyWndProc(HWND hWnd, UINT nMsg,
1852 WPARAM wParam,
1853 LPARAM lParam)
1854 {
1855 if(nMsg == MM_MCINOTIFY)
1856 {
1857 wxASSERT(lParam == (LPARAM) m_hDev);
1858 if(wParam == MCI_NOTIFY_SUCCESSFUL && lParam == (LPARAM)m_hDev)
1859 {
1860 wxMediaEvent theEvent(wxEVT_MEDIA_STOP, m_ctrl->GetId());
1861 m_ctrl->ProcessEvent(theEvent);
1862
1863 if(theEvent.IsAllowed())
1864 {
1865 wxMCIVERIFY( mciSendCommand(m_hDev, MCI_SEEK,
1866 MCI_SEEK_TO_START, 0) );
1867
1868 //send the event to our child
1869 wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED,
1870 m_ctrl->GetId());
1871 m_ctrl->ProcessEvent(theEvent);
1872 }
1873 }
1874 }
1875 return DefWindowProc(hWnd, nMsg, wParam, lParam);
1876 }
1877 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1878 //
1879 // wxQTMediaBackend
1880 //
1881 // TODO: Use a less cludgy way to pause/get state/set state
1882 // TODO: Dynamically load from qtml.dll
1883 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1884
1885 #if wxUSE_QUICKTIME
1886
1887 IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend);
1888
1889 //Time between timer calls
1890 #define MOVIE_DELAY 100
1891
1892 #include "wx/timer.h"
1893
1894 // --------------------------------------------------------------------------
1895 // wxQTTimer - Handle Asyncronous Playing
1896 // --------------------------------------------------------------------------
1897 class _wxQTTimer : public wxTimer
1898 {
1899 public:
1900 _wxQTTimer(Movie movie, wxQTMediaBackend* parent) :
1901 m_movie(movie), m_bPaused(false), m_parent(parent)
1902 {
1903 }
1904
1905 ~_wxQTTimer()
1906 {
1907 }
1908
1909 bool GetPaused() {return m_bPaused;}
1910 void SetPaused(bool bPaused) {m_bPaused = bPaused;}
1911
1912 //-----------------------------------------------------------------------
1913 // _wxQTTimer::Notify
1914 //
1915 // 1) Checks to see if the movie is done, and if not continues
1916 // streaming the movie
1917 // 2) Sends the wxEVT_MEDIA_STOP event if we have reached the end of
1918 // the movie.
1919 //-----------------------------------------------------------------------
1920 void Notify()
1921 {
1922 if (!m_bPaused)
1923 {
1924 if(!IsMovieDone(m_movie))
1925 MoviesTask(m_movie, MOVIE_DELAY);
1926 else
1927 {
1928 wxMediaEvent theEvent(wxEVT_MEDIA_STOP,
1929 m_parent->m_ctrl->GetId());
1930 m_parent->m_ctrl->ProcessEvent(theEvent);
1931
1932 if(theEvent.IsAllowed())
1933 {
1934 Stop();
1935 m_parent->Stop();
1936 wxASSERT(::GetMoviesError() == noErr);
1937
1938 //send the event to our child
1939 wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED,
1940 m_parent->m_ctrl->GetId());
1941 m_parent->m_ctrl->ProcessEvent(theEvent);
1942 }
1943 }
1944 }
1945 }
1946
1947 protected:
1948 Movie m_movie; //Our movie instance
1949 bool m_bPaused; //Whether we are paused or not
1950 wxQTMediaBackend* m_parent; //Backend pointer
1951 };
1952
1953 //---------------------------------------------------------------------------
1954 // wxQTMediaBackend Destructor
1955 //
1956 // Sets m_timer to NULL signifying we havn't loaded anything yet
1957 //---------------------------------------------------------------------------
1958 wxQTMediaBackend::wxQTMediaBackend() : m_timer(NULL)
1959 {
1960 }
1961
1962 //---------------------------------------------------------------------------
1963 // wxQTMediaBackend Destructor
1964 //
1965 // 1) Cleans up the QuickTime movie instance
1966 // 2) Decrements the QuickTime reference counter - if this reaches
1967 // 0, QuickTime shuts down
1968 // 3) Decrements the QuickTime Windows Media Layer reference counter -
1969 // if this reaches 0, QuickTime shuts down the Windows Media Layer
1970 //---------------------------------------------------------------------------
1971 wxQTMediaBackend::~wxQTMediaBackend()
1972 {
1973 if(m_timer)
1974 Cleanup();
1975
1976 //Note that ExitMovies() is not neccessary, but
1977 //the docs are fuzzy on whether or not TerminateQTML is
1978 ExitMovies();
1979 TerminateQTML();
1980 }
1981
1982 //---------------------------------------------------------------------------
1983 // wxQTMediaBackend::CreateControl
1984 //
1985 // 1) Intializes QuickTime
1986 // 2) Creates the control window
1987 //---------------------------------------------------------------------------
1988 bool wxQTMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
1989 wxWindowID id,
1990 const wxPoint& pos,
1991 const wxSize& size,
1992 long style,
1993 const wxValidator& validator,
1994 const wxString& name)
1995 {
1996 int nError;
1997 if ((nError = InitializeQTML(0)) != noErr) //-2093 no dll
1998 {
1999 wxFAIL_MSG(wxString::Format(wxT("Couldn't Initialize Quicktime-%i"), nError));
2000 return false;
2001 }
2002 EnterMovies();
2003
2004 //
2005 // Create window
2006 // By default wxWindow(s) is created with a border -
2007 // so we need to get rid of those
2008 //
2009 // Since we don't have a child window like most other
2010 // backends, we don't need wxCLIP_CHILDREN
2011 //
2012 if ( !ctrl->wxControl::Create(parent, id, pos, size,
2013 (style & ~wxBORDER_MASK) | wxBORDER_NONE,
2014 validator, name) )
2015 return false;
2016
2017 m_ctrl = ctrl;
2018 return true;
2019 }
2020
2021 //---------------------------------------------------------------------------
2022 // wxQTMediaBackend::Load (file version)
2023 //
2024 // 1) Get an FSSpec from the Windows path name
2025 // 2) Open the movie
2026 // 3) Obtain the movie instance from the movie resource
2027 // 4)
2028 //---------------------------------------------------------------------------
2029 bool wxQTMediaBackend::Load(const wxString& fileName)
2030 {
2031 if(m_timer)
2032 Cleanup();
2033
2034 OSErr err = noErr;
2035 short movieResFile;
2036 FSSpec sfFile;
2037
2038 if (NativePathNameToFSSpec ((char*) (const char*) fileName.mb_str(),
2039 &sfFile, 0) != noErr)
2040 return false;
2041
2042 if (OpenMovieFile (&sfFile, &movieResFile, fsRdPerm) != noErr)
2043 return false;
2044
2045 short movieResID = 0;
2046 Str255 movieName;
2047
2048 err = NewMovieFromFile (
2049 &m_movie,
2050 movieResFile,
2051 &movieResID,
2052 movieName,
2053 newMovieActive,
2054 NULL); //wasChanged
2055
2056 CloseMovieFile (movieResFile);
2057
2058 if (err != noErr)
2059 return false;
2060
2061 FinishLoad();
2062
2063 return ::GetMoviesError() == noErr;
2064 }
2065
2066 //---------------------------------------------------------------------------
2067 // wxQTMediaBackend::Move
2068 //
2069 // TODO
2070 //---------------------------------------------------------------------------
2071 bool wxQTMediaBackend::Load(const wxURI& location)
2072 {
2073 if(m_timer)
2074 Cleanup();
2075
2076 wxString theURI = location.BuildURI();
2077
2078 OSErr err = noErr;
2079
2080 Handle theHandle = NewHandleClear(theURI.length() + 1);
2081 wxASSERT(theHandle);
2082
2083 BlockMove(theURI.mb_str(), *theHandle, theURI.length() + 1);
2084
2085 //create the movie from the handle that refers to the URI
2086 err = NewMovieFromDataRef(&m_movie, newMovieActive,
2087 NULL, theHandle,
2088 URLDataHandlerSubType);
2089
2090 DisposeHandle(theHandle);
2091
2092 if (err != noErr)
2093 return false;
2094
2095 //preroll movie for streaming
2096 //TODO:Async this?
2097 TimeValue timeNow;
2098 Fixed playRate;
2099 timeNow = GetMovieTime(m_movie, NULL);
2100 playRate = GetMoviePreferredRate(m_movie);
2101 PrePrerollMovie(m_movie, timeNow, playRate, NULL, NULL);
2102 PrerollMovie(m_movie, timeNow, playRate);
2103 SetMovieRate(m_movie, playRate);
2104
2105 FinishLoad();
2106
2107 return ::GetMoviesError() == noErr;
2108 }
2109
2110 //---------------------------------------------------------------------------
2111 // wxQTMediaBackend::Move
2112 //
2113 // TODO
2114 //---------------------------------------------------------------------------
2115 void wxQTMediaBackend::FinishLoad()
2116 {
2117 m_timer = new _wxQTTimer(m_movie, (wxQTMediaBackend*) this);
2118 wxASSERT(m_timer);
2119
2120 //get the real size of the movie
2121 Rect outRect;
2122 ::GetMovieNaturalBoundsRect (m_movie, &outRect);
2123 wxASSERT(::GetMoviesError() == noErr);
2124
2125 m_bestSize.x = outRect.right - outRect.left;
2126 m_bestSize.y = outRect.bottom - outRect.top;
2127
2128 //reparent movie/*AudioMediaCharacteristic*/
2129 if(GetMovieIndTrackType(m_movie, 1,
2130 VisualMediaCharacteristic,
2131 movieTrackCharacteristic |
2132 movieTrackEnabledOnly) != NULL)
2133 {
2134 CreatePortAssociation(m_ctrl->GetHWND(), NULL, 0L);
2135
2136 SetMovieGWorld(m_movie,
2137 (CGrafPtr) GetNativeWindowPort(m_ctrl->GetHWND()),
2138 nil);
2139 }
2140
2141 //we want millisecond precision
2142 ::SetMovieTimeScale(m_movie, 1000);
2143 wxASSERT(::GetMoviesError() == noErr);
2144
2145 //
2146 //Here, if the parent of the control has a sizer - we
2147 //tell it to recalculate the size of this control since
2148 //the user opened a seperate media file
2149 //
2150 m_ctrl->InvalidateBestSize();
2151 m_ctrl->GetParent()->Layout();
2152 m_ctrl->GetParent()->Refresh();
2153 m_ctrl->GetParent()->Update();
2154 }
2155
2156 //---------------------------------------------------------------------------
2157 // wxQTMediaBackend::Move
2158 //
2159 // TODO
2160 //---------------------------------------------------------------------------
2161 bool wxQTMediaBackend::Play()
2162 {
2163 ::StartMovie(m_movie);
2164 m_timer->SetPaused(false);
2165 m_timer->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS);
2166 return ::GetMoviesError() == noErr;
2167 }
2168
2169 //---------------------------------------------------------------------------
2170 // wxQTMediaBackend::Move
2171 //
2172 // TODO
2173 //---------------------------------------------------------------------------
2174 bool wxQTMediaBackend::Pause()
2175 {
2176 ::StopMovie(m_movie);
2177 m_timer->SetPaused(true);
2178 m_timer->Stop();
2179 return ::GetMoviesError() == noErr;
2180 }
2181
2182 //---------------------------------------------------------------------------
2183 // wxQTMediaBackend::Move
2184 //
2185 // TODO
2186 //---------------------------------------------------------------------------
2187 bool wxQTMediaBackend::Stop()
2188 {
2189 m_timer->SetPaused(false);
2190 m_timer->Stop();
2191
2192 ::StopMovie(m_movie);
2193 if(::GetMoviesError() != noErr)
2194 return false;
2195
2196 ::GoToBeginningOfMovie(m_movie);
2197 return ::GetMoviesError() == noErr;
2198 }
2199
2200 //---------------------------------------------------------------------------
2201 // wxQTMediaBackend::Move
2202 //
2203 // TODO
2204 //---------------------------------------------------------------------------
2205 double wxQTMediaBackend::GetPlaybackRate()
2206 {
2207 return ( ((double)::GetMovieRate(m_movie)) / 0x10000);
2208 }
2209
2210 //---------------------------------------------------------------------------
2211 // wxQTMediaBackend::Move
2212 //
2213 // TODO
2214 //---------------------------------------------------------------------------
2215 bool wxQTMediaBackend::SetPlaybackRate(double dRate)
2216 {
2217 ::SetMovieRate(m_movie, (Fixed) (dRate * 0x10000));
2218 return ::GetMoviesError() == noErr;
2219 }
2220
2221 //---------------------------------------------------------------------------
2222 // wxQTMediaBackend::Move
2223 //
2224 // TODO
2225 //---------------------------------------------------------------------------
2226 bool wxQTMediaBackend::SetPosition(wxLongLong where)
2227 {
2228 TimeRecord theTimeRecord;
2229 memset(&theTimeRecord, 0, sizeof(TimeRecord));
2230 theTimeRecord.value.lo = where.GetValue();
2231 theTimeRecord.scale = ::GetMovieTimeScale(m_movie);
2232 theTimeRecord.base = ::GetMovieTimeBase(m_movie);
2233 ::SetMovieTime(m_movie, &theTimeRecord);
2234
2235 if (::GetMoviesError() != noErr)
2236 return false;
2237
2238 return true;
2239 }
2240
2241 //---------------------------------------------------------------------------
2242 // wxQTMediaBackend::GetPosition
2243 //
2244 // 1) Calls GetMovieTime to get the position we are in in the movie
2245 // in milliseconds (we called
2246 //---------------------------------------------------------------------------
2247 wxLongLong wxQTMediaBackend::GetPosition()
2248 {
2249 return ::GetMovieTime(m_movie, NULL);
2250 }
2251
2252 //---------------------------------------------------------------------------
2253 // wxQTMediaBackend::Move
2254 //
2255 // TODO
2256 //---------------------------------------------------------------------------
2257 wxLongLong wxQTMediaBackend::GetDuration()
2258 {
2259 return ::GetMovieDuration(m_movie);
2260 }
2261
2262 //---------------------------------------------------------------------------
2263 // wxQTMediaBackend::Move
2264 //
2265 // TODO
2266 //---------------------------------------------------------------------------
2267 wxMediaState wxQTMediaBackend::GetState()
2268 {
2269 if ( !m_timer || (m_timer->IsRunning() == false &&
2270 m_timer->GetPaused() == false) )
2271 return wxMEDIASTATE_STOPPED;
2272
2273 if( m_timer->IsRunning() == true )
2274 return wxMEDIASTATE_PLAYING;
2275 else
2276 return wxMEDIASTATE_PAUSED;
2277 }
2278
2279 //---------------------------------------------------------------------------
2280 // wxQTMediaBackend::Move
2281 //
2282 // TODO
2283 //---------------------------------------------------------------------------
2284 void wxQTMediaBackend::Cleanup()
2285 {
2286 delete m_timer;
2287 m_timer = NULL;
2288
2289 StopMovie(m_movie);
2290 DisposeMovie(m_movie);
2291 }
2292
2293 //---------------------------------------------------------------------------
2294 // wxQTMediaBackend::Move
2295 //
2296 // TODO
2297 //---------------------------------------------------------------------------
2298 wxSize wxQTMediaBackend::GetVideoSize() const
2299 {
2300 return m_bestSize;
2301 }
2302
2303 //---------------------------------------------------------------------------
2304 // wxQTMediaBackend::Move
2305 //
2306 // TODO
2307 //---------------------------------------------------------------------------
2308 void wxQTMediaBackend::Move(int x, int y, int w, int h)
2309 {
2310 if(m_timer)
2311 {
2312 Rect theRect = {0, 0, h, w};
2313
2314 ::SetMovieBox(m_movie, &theRect);
2315 wxASSERT(::GetMoviesError() == noErr);
2316 }
2317 }
2318
2319 //---------------------------------------------------------------------------
2320 // End QT Compilation Guard
2321 //---------------------------------------------------------------------------
2322 #endif //wxUSE_QUICKTIME
2323
2324 //in source file that contains stuff you don't directly use
2325 #include <wx/html/forcelnk.h>
2326 FORCE_LINK_ME(basewxmediabackends);
2327
2328 //---------------------------------------------------------------------------
2329 // End wxMediaCtrl Compilation Guard and this file
2330 //---------------------------------------------------------------------------
2331 #endif //wxUSE_MEDIACTRL
2332
2333