]> git.saurik.com Git - wxWidgets.git/blob - src/msw/mediactrl.cpp
b8fd0d369d6fd8686e8f92828fcd4d4b430bbe97
[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 virtual double GetVolume();
740 virtual bool SetVolume(double);
741
742 void Cleanup();
743
744 bool m_bVideo;
745
746 static LRESULT CALLBACK NotifyWndProc(HWND hWnd, UINT nMsg,
747 WPARAM wParam, LPARAM lParam);
748
749 LRESULT CALLBACK OnNotifyWndProc(HWND hWnd, UINT nMsg,
750 WPARAM wParam, LPARAM lParam);
751
752 wxControl* m_ctrl;
753
754 IBasicAudio* m_pBA;
755 IBasicVideo* m_pBV;
756 IMediaControl* m_pMC;
757 IMediaEventEx* m_pME;
758 IMediaPosition* m_pMS;
759 IVideoWindow* m_pVW;
760
761 HWND m_hNotifyWnd;
762 wxSize m_bestSize;
763
764 DECLARE_DYNAMIC_CLASS(wxAMMediaBackend);
765 };
766
767 #endif //wxUSE_DIRECTSHOW
768
769 //---------------------------------------------------------------------------
770 //
771 // wxMCIMediaBackend
772 //
773 //---------------------------------------------------------------------------
774
775 //---------------------------------------------------------------------------
776 // MCI Includes
777 //---------------------------------------------------------------------------
778 #include <mmsystem.h>
779
780 class WXDLLIMPEXP_MEDIA wxMCIMediaBackend : public wxMediaBackend
781 {
782 public:
783
784 wxMCIMediaBackend();
785 ~wxMCIMediaBackend();
786
787 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
788 wxWindowID id,
789 const wxPoint& pos,
790 const wxSize& size,
791 long style,
792 const wxValidator& validator,
793 const wxString& name);
794
795 virtual bool Play();
796 virtual bool Pause();
797 virtual bool Stop();
798
799 virtual bool Load(const wxString& fileName);
800 virtual bool Load(const wxURI& location);
801
802 virtual wxMediaState GetState();
803
804 virtual bool SetPosition(wxLongLong where);
805 virtual wxLongLong GetPosition();
806 virtual wxLongLong GetDuration();
807
808 virtual void Move(int x, int y, int w, int h);
809 wxSize GetVideoSize() const;
810
811 virtual double GetPlaybackRate();
812 virtual bool SetPlaybackRate(double dRate);
813
814 virtual double GetVolume();
815 virtual bool SetVolume(double);
816
817 static LRESULT CALLBACK NotifyWndProc(HWND hWnd, UINT nMsg,
818 WPARAM wParam, LPARAM lParam);
819
820 LRESULT CALLBACK OnNotifyWndProc(HWND hWnd, UINT nMsg,
821 WPARAM wParam, LPARAM lParam);
822
823 MCIDEVICEID m_hDev; //Our MCI Device ID/Handler
824 wxControl* m_ctrl; //Parent control
825 HWND m_hNotifyWnd; //Window to use for MCI events
826 bool m_bVideo; //Whether or not we have video
827
828 DECLARE_DYNAMIC_CLASS(wxMCIMediaBackend)
829 };
830
831 //---------------------------------------------------------------------------
832 //
833 // wxQTMediaBackend
834 //
835 //---------------------------------------------------------------------------
836
837 //---------------------------------------------------------------------------
838 // QT Compilation Guard
839 //---------------------------------------------------------------------------
840 #if wxUSE_QUICKTIME
841
842 //---------------------------------------------------------------------------
843 // QT Includes
844 //---------------------------------------------------------------------------
845 //#include <qtml.h> //Windoze QT include
846 //#include <QuickTimeComponents.h> //Standard QT stuff
847 #include "wx/dynlib.h"
848
849 //---------------------------------------------------------------------------
850 // QT Types
851 //---------------------------------------------------------------------------
852 typedef struct MovieRecord* Movie;
853 typedef wxInt16 OSErr;
854 typedef wxInt32 OSStatus;
855 #define noErr 0
856 #define fsRdPerm 1
857 typedef unsigned char Str255[256];
858 #define StringPtr unsigned char*
859 #define newMovieActive 1
860 #define Ptr char*
861 #define Handle Ptr*
862 #define Fixed long
863 #define OSType unsigned long
864 #define CGrafPtr struct GrafPort *
865 #define TimeScale long
866 #define TimeBase struct TimeBaseRecord *
867
868 struct FSSpec {
869 short vRefNum;
870 long parID;
871 Str255 name; /*Str63 on mac, Str255 on msw */
872 };
873
874 struct Rect {
875 short top;
876 short left;
877 short bottom;
878 short right;
879 };
880
881 struct wide {
882 wxInt32 hi;
883 wxUint32 lo;
884 };
885
886 struct TimeRecord {
887 wide value; /* units */
888 TimeScale scale; /* units per second */
889 TimeBase base;
890 };
891
892 //---------------------------------------------------------------------------
893 // QT Library
894 //---------------------------------------------------------------------------
895 #define wxDL_METHOD_DEFINE( rettype, name, args, shortargs, defret ) \
896 typedef rettype (* name ## Type) args ; \
897 name ## Type pfn_ ## name; \
898 rettype name args \
899 { if (m_ok) return pfn_ ## name shortargs ; return defret; }
900
901 #define wxDL_VOIDMETHOD_DEFINE( name, args, shortargs ) \
902 typedef void (* name ## Type) args ; \
903 name ## Type pfn_ ## name; \
904 void name args \
905 { if (m_ok) pfn_ ## name shortargs ; }
906
907 #define wxDL_METHOD_LOAD( lib, name, success ) \
908 pfn_ ## name = (name ## Type) lib.GetSymbol( wxT(#name), &success ); \
909 if (!success) return false;
910
911 //Class that utilizes Robert Roeblings Dynamic Library Macros
912 class wxQuickTimeLibrary
913 {
914 public:
915 ~wxQuickTimeLibrary()
916 {
917 if(m_dll.IsLoaded())
918 m_dll.Unload();
919 }
920
921 bool Initialize();
922 bool IsOk() const {return m_ok;}
923
924 protected:
925 wxDynamicLibrary m_dll;
926 bool m_ok;
927
928 public:
929 wxDL_VOIDMETHOD_DEFINE( StartMovie, (Movie m), (m) );
930 wxDL_VOIDMETHOD_DEFINE( StopMovie, (Movie m), (m) );
931 wxDL_METHOD_DEFINE( bool, IsMovieDone, (Movie m), (m), false);
932 wxDL_VOIDMETHOD_DEFINE( GoToBeginningOfMovie, (Movie m), (m) );
933 wxDL_METHOD_DEFINE( OSErr, GetMoviesError, (), (), -1);
934 wxDL_METHOD_DEFINE( OSErr, EnterMovies, (), (), -1);
935 wxDL_VOIDMETHOD_DEFINE( ExitMovies, (), () );
936 wxDL_METHOD_DEFINE( OSErr, InitializeQTML, (long flags), (flags), -1);
937 wxDL_VOIDMETHOD_DEFINE( TerminateQTML, (), () );
938
939 wxDL_METHOD_DEFINE( OSErr, NativePathNameToFSSpec,
940 (char* inName, FSSpec* outFile, long flags),
941 (inName, outFile, flags), -1);
942
943 wxDL_METHOD_DEFINE( OSErr, OpenMovieFile,
944 (const FSSpec * fileSpec, short * resRefNum, wxInt8 permission),
945 (fileSpec, resRefNum, permission), -1 );
946
947 wxDL_METHOD_DEFINE( OSErr, CloseMovieFile,
948 (short resRefNum), (resRefNum), -1);
949
950 wxDL_METHOD_DEFINE( OSErr, NewMovieFromFile,
951 (Movie * theMovie, short resRefNum, short * resId,
952 StringPtr resName, short newMovieFlags,
953 bool * dataRefWasChanged),
954 (theMovie, resRefNum, resId, resName, newMovieFlags,
955 dataRefWasChanged), -1);
956
957 wxDL_VOIDMETHOD_DEFINE( SetMovieRate, (Movie m, Fixed rate), (m, rate) );
958 wxDL_METHOD_DEFINE( Fixed, GetMovieRate, (Movie m), (m), 0);
959 wxDL_VOIDMETHOD_DEFINE( MoviesTask, (Movie m, long maxms), (m, maxms) );
960 wxDL_VOIDMETHOD_DEFINE( BlockMove,
961 (const char* p1, const char* p2, long s), (p1,p2,s) );
962 wxDL_METHOD_DEFINE( Handle, NewHandleClear, (long s), (s), NULL );
963
964 wxDL_METHOD_DEFINE( OSErr, NewMovieFromDataRef,
965 (Movie * m, short flags, short * id,
966 Handle dataRef, OSType dataRefType),
967 (m,flags,id,dataRef,dataRefType), -1 );
968
969 wxDL_VOIDMETHOD_DEFINE( DisposeHandle, (Handle h), (h) );
970 wxDL_VOIDMETHOD_DEFINE( GetMovieNaturalBoundsRect, (Movie m, Rect* r), (m,r) );
971 wxDL_METHOD_DEFINE( void*, GetMovieIndTrackType,
972 (Movie m, long index, OSType type, long flags),
973 (m,index,type,flags), NULL );
974 wxDL_VOIDMETHOD_DEFINE( CreatePortAssociation,
975 (void* hWnd, void* junk, long morejunk), (hWnd, junk, morejunk) );
976 wxDL_METHOD_DEFINE(void*, GetNativeWindowPort, (void* hWnd), (hWnd), NULL);
977 wxDL_VOIDMETHOD_DEFINE(SetMovieGWorld, (Movie m, CGrafPtr port, void* whatever),
978 (m, port, whatever) );
979 wxDL_VOIDMETHOD_DEFINE(DisposeMovie, (Movie m), (m) );
980 wxDL_VOIDMETHOD_DEFINE(SetMovieBox, (Movie m, Rect* r), (m,r));
981 wxDL_VOIDMETHOD_DEFINE(SetMovieTimeScale, (Movie m, long s), (m,s));
982 wxDL_METHOD_DEFINE(long, GetMovieDuration, (Movie m), (m), 0);
983 wxDL_METHOD_DEFINE(TimeBase, GetMovieTimeBase, (Movie m), (m), 0);
984 wxDL_METHOD_DEFINE(TimeScale, GetMovieTimeScale, (Movie m), (m), 0);
985 wxDL_METHOD_DEFINE(long, GetMovieTime, (Movie m, void* cruft), (m,cruft), 0);
986 wxDL_VOIDMETHOD_DEFINE(SetMovieTime, (Movie m, TimeRecord* tr), (m,tr) );
987 wxDL_METHOD_DEFINE(short, GetMovieVolume, (Movie m), (m), 0);
988 wxDL_VOIDMETHOD_DEFINE(SetMovieVolume, (Movie m, short sVolume), (m,sVolume) );
989 };
990
991 bool wxQuickTimeLibrary::Initialize()
992 {
993 m_ok = false;
994
995 if(!m_dll.Load(wxT("qtmlClient.dll")))
996 return false;
997
998 bool bOk;
999
1000 wxDL_METHOD_LOAD( m_dll, StartMovie, bOk );
1001 wxDL_METHOD_LOAD( m_dll, StopMovie, bOk );
1002 wxDL_METHOD_LOAD( m_dll, IsMovieDone, bOk );
1003 wxDL_METHOD_LOAD( m_dll, GoToBeginningOfMovie, bOk );
1004 wxDL_METHOD_LOAD( m_dll, GetMoviesError, bOk );
1005 wxDL_METHOD_LOAD( m_dll, EnterMovies, bOk );
1006 wxDL_METHOD_LOAD( m_dll, ExitMovies, bOk );
1007 wxDL_METHOD_LOAD( m_dll, InitializeQTML, bOk );
1008 wxDL_METHOD_LOAD( m_dll, TerminateQTML, bOk );
1009 wxDL_METHOD_LOAD( m_dll, NativePathNameToFSSpec, bOk );
1010 wxDL_METHOD_LOAD( m_dll, OpenMovieFile, bOk );
1011 wxDL_METHOD_LOAD( m_dll, CloseMovieFile, bOk );
1012 wxDL_METHOD_LOAD( m_dll, NewMovieFromFile, bOk );
1013 wxDL_METHOD_LOAD( m_dll, GetMovieRate, bOk );
1014 wxDL_METHOD_LOAD( m_dll, SetMovieRate, bOk );
1015 wxDL_METHOD_LOAD( m_dll, MoviesTask, bOk );
1016 wxDL_METHOD_LOAD( m_dll, BlockMove, bOk );
1017 wxDL_METHOD_LOAD( m_dll, NewHandleClear, bOk );
1018 wxDL_METHOD_LOAD( m_dll, NewMovieFromDataRef, bOk );
1019 wxDL_METHOD_LOAD( m_dll, DisposeHandle, bOk );
1020 wxDL_METHOD_LOAD( m_dll, GetMovieNaturalBoundsRect, bOk );
1021 wxDL_METHOD_LOAD( m_dll, GetMovieIndTrackType, bOk );
1022 wxDL_METHOD_LOAD( m_dll, CreatePortAssociation, bOk );
1023 wxDL_METHOD_LOAD( m_dll, GetNativeWindowPort, bOk );
1024 wxDL_METHOD_LOAD( m_dll, SetMovieGWorld, bOk );
1025 wxDL_METHOD_LOAD( m_dll, DisposeMovie, bOk );
1026 wxDL_METHOD_LOAD( m_dll, SetMovieBox, bOk );
1027 wxDL_METHOD_LOAD( m_dll, SetMovieTimeScale, bOk );
1028 wxDL_METHOD_LOAD( m_dll, GetMovieDuration, bOk );
1029 wxDL_METHOD_LOAD( m_dll, GetMovieTimeBase, bOk );
1030 wxDL_METHOD_LOAD( m_dll, GetMovieTimeScale, bOk );
1031 wxDL_METHOD_LOAD( m_dll, GetMovieTime, bOk );
1032 wxDL_METHOD_LOAD( m_dll, SetMovieTime, bOk );
1033 wxDL_METHOD_LOAD( m_dll, GetMovieVolume, bOk );
1034 wxDL_METHOD_LOAD( m_dll, SetMovieVolume, bOk );
1035
1036 m_ok = true;
1037
1038 return true;
1039 }
1040
1041 class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackend
1042 {
1043 public:
1044
1045 wxQTMediaBackend();
1046 ~wxQTMediaBackend();
1047
1048 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
1049 wxWindowID id,
1050 const wxPoint& pos,
1051 const wxSize& size,
1052 long style,
1053 const wxValidator& validator,
1054 const wxString& name);
1055
1056 virtual bool Play();
1057 virtual bool Pause();
1058 virtual bool Stop();
1059
1060 virtual bool Load(const wxString& fileName);
1061 virtual bool Load(const wxURI& location);
1062
1063 virtual wxMediaState GetState();
1064
1065 virtual bool SetPosition(wxLongLong where);
1066 virtual wxLongLong GetPosition();
1067 virtual wxLongLong GetDuration();
1068
1069 virtual void Move(int x, int y, int w, int h);
1070 wxSize GetVideoSize() const;
1071
1072 virtual double GetPlaybackRate();
1073 virtual bool SetPlaybackRate(double dRate);
1074
1075 virtual double GetVolume();
1076 virtual bool SetVolume(double);
1077
1078 void Cleanup();
1079 void FinishLoad();
1080
1081 wxSize m_bestSize; //Original movie size
1082 Movie m_movie; //QT Movie handle/instance
1083 wxControl* m_ctrl; //Parent control
1084 bool m_bVideo; //Whether or not we have video
1085 class _wxQTTimer* m_timer; //Timer for streaming the movie
1086 wxQuickTimeLibrary m_lib;
1087
1088
1089 DECLARE_DYNAMIC_CLASS(wxQTMediaBackend);
1090 };
1091
1092 //---------------------------------------------------------------------------
1093 // End QT Compilation Guard
1094 //---------------------------------------------------------------------------
1095 #endif //wxUSE_QUICKTIME
1096
1097 //===========================================================================
1098 // IMPLEMENTATION
1099 //===========================================================================
1100
1101 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1102 //
1103 // wxAMMediaBackend
1104 //
1105 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1106
1107 //---------------------------------------------------------------------------
1108 // Only use if user wants it -
1109 //---------------------------------------------------------------------------
1110 #if wxUSE_DIRECTSHOW
1111
1112 IMPLEMENT_DYNAMIC_CLASS(wxAMMediaBackend, wxMediaBackend);
1113
1114 // Numerical value for when the graph reaches the stop position
1115 #define WM_GRAPHNOTIFY WM_USER+13
1116
1117 //---------------------------------------------------------------------------
1118 // Usual debugging macros
1119 //---------------------------------------------------------------------------
1120 #ifdef __WXDEBUG__
1121 #define wxAMVERIFY(x) \
1122 { \
1123 HRESULT hrdsv = (x); \
1124 if ( FAILED(hrdsv) ) \
1125 { \
1126 /*TCHAR szError[MAX_ERROR_TEXT_LEN];*/ \
1127 /*if( AMGetErrorText(hrdsv, szError, MAX_ERROR_TEXT_LEN) == 0)*/ \
1128 /*{*/ \
1129 /*wxFAIL_MSG( wxString::Format(wxT("DirectShow error \"%s\" ")*/\
1130 /*wxT("occured at line %i in ")*/ \
1131 /*wxT("mediactrl.cpp"),*/ \
1132 /*szError, __LINE__) );*/ \
1133 /*}*/ \
1134 /*else*/ \
1135 wxFAIL_MSG( wxString::Format(wxT("Unknown error (%i) ") \
1136 wxT("occured at") \
1137 wxT(" line %i in mediactrl.cpp."), \
1138 (int)hrdsv, __LINE__) ); \
1139 } \
1140 }
1141 #define wxVERIFY(x) wxASSERT((x))
1142 #else
1143 #define wxAMVERIFY(x) (x)
1144 #define wxVERIFY(x) (x)
1145 #endif
1146
1147 //---------------------------------------------------------------------------
1148 // Standard macros for ease of use
1149 //---------------------------------------------------------------------------
1150 #define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
1151
1152 //---------------------------------------------------------------------------
1153 // wxAMMediaBackend Constructor
1154 //
1155 // Sets m_hNotifyWnd to NULL to signify that we haven't loaded anything yet
1156 //---------------------------------------------------------------------------
1157 wxAMMediaBackend::wxAMMediaBackend() : m_hNotifyWnd(NULL)
1158 {
1159 }
1160
1161 //---------------------------------------------------------------------------
1162 // wxAMMediaBackend Destructor
1163 //
1164 // Cleans up everything
1165 //---------------------------------------------------------------------------
1166 wxAMMediaBackend::~wxAMMediaBackend()
1167 {
1168 if (m_hNotifyWnd)
1169 Cleanup();
1170 }
1171
1172 //---------------------------------------------------------------------------
1173 // wxAMMediaBackend::CreateControl
1174 //
1175 // ActiveMovie does not really have any native control to speak of,
1176 // so we just create a normal control.
1177 //
1178 // We also check to see if ActiveMovie is installed
1179 //---------------------------------------------------------------------------
1180 bool wxAMMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
1181 wxWindowID id,
1182 const wxPoint& pos,
1183 const wxSize& size,
1184 long style,
1185 const wxValidator& validator,
1186 const wxString& name)
1187 {
1188 //create our filter graph - the beuty of COM is that it loads
1189 //quartz.dll for us :)
1190 HRESULT hr = CoCreateInstance(CLSID_FilgraphManager, NULL, CLSCTX_INPROC_SERVER,
1191 IID_IMediaControl, (void**)&m_pMC);
1192
1193 //directshow not installed?
1194 if ( FAILED(hr) )
1195 return false;
1196
1197 //release the filter graph - we don't need it yet
1198 m_pMC->Release();
1199 m_pMC = NULL;
1200
1201 //
1202 // Create window
1203 // By default wxWindow(s) is created with a border -
1204 // so we need to get rid of those, and create with
1205 // wxCLIP_CHILDREN, so that if the driver/backend
1206 // is a child window, it refereshes properly
1207 //
1208 if ( !ctrl->wxControl::Create(parent, id, pos, size,
1209 (style & ~wxBORDER_MASK) | wxBORDER_NONE | wxCLIP_CHILDREN,
1210 validator, name) )
1211 return false;
1212
1213 m_ctrl = ctrl;
1214 return true;
1215 }
1216
1217
1218 //---------------------------------------------------------------------------
1219 // wxAMMediaBackend::Load (file version)
1220 //
1221 // Creates an Active Movie filter graph from a file or url
1222 //---------------------------------------------------------------------------
1223 bool wxAMMediaBackend::Load(const wxString& fileName)
1224 {
1225 //if previously loaded cleanup
1226 if(m_hNotifyWnd)
1227 Cleanup();
1228
1229 //We already checked for success in CreateControl
1230 CoCreateInstance(CLSID_FilgraphManager, NULL, CLSCTX_INPROC_SERVER,
1231 IID_IMediaControl, (void**)&m_pMC);
1232
1233 //load the graph & render
1234 if( FAILED(m_pMC->RenderFile(wxBasicString(fileName).Get())) )
1235 return false;
1236
1237 //get the interfaces, all of them
1238 wxAMVERIFY( m_pMC->QueryInterface(IID_IMediaEventEx, (void**)&m_pME) );
1239 wxAMVERIFY( m_pMC->QueryInterface(IID_IMediaPosition, (void**)&m_pMS) );
1240 wxAMVERIFY( m_pMC->QueryInterface(IID_IVideoWindow, (void**)&m_pVW) );
1241 wxAMVERIFY( m_pMC->QueryInterface(IID_IBasicAudio, (void**)&m_pBA) );
1242 wxAMVERIFY( m_pMC->QueryInterface(IID_IBasicVideo, (void**)&m_pBV) );
1243
1244 //We could tell if the media has audio or not by
1245 //something like
1246 //-----
1247 //long lVolume;
1248 //pBA->get_Volume(&lVolume) == E_NOTIMPL
1249 //-----
1250 //here...
1251
1252 //
1253 //Obtain the _actual_ size of the movie & remember it
1254 //
1255 long nX,
1256 nY;
1257
1258 m_bestSize.x = m_bestSize.y = 0;
1259
1260 m_bVideo = SUCCEEDED( m_pVW->GetWindowPosition( &nX,
1261 &nY,
1262 (long*)&m_bestSize.x,
1263 (long*)&m_bestSize.y) );
1264
1265 //
1266 //If we have video in the media - set it up so that
1267 //its a child window of the control, its visible,
1268 //and that the control is the owner of the video window
1269 //
1270 if (m_bVideo)
1271 {
1272 wxAMVERIFY( m_pVW->put_Owner((LONG_PTR)m_ctrl->GetHandle()) );
1273 wxAMVERIFY( m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS) );
1274 wxAMVERIFY( m_pVW->put_Visible(-1) ); //OATRUE == -1
1275 }
1276
1277 //
1278 // Create a hidden window and register to handle
1279 // directshow events for this graph
1280 // Note that wxCanvasClassName is already registered
1281 // and used by all wxWindows and normal wxControls
1282 //
1283 m_hNotifyWnd = ::CreateWindow
1284 (
1285 wxCanvasClassName,
1286 NULL,
1287 0, 0, 0, 0,
1288 0,
1289 (HWND) NULL,
1290 (HMENU)NULL,
1291 wxGetInstance(),
1292 (LPVOID) NULL
1293 );
1294
1295 if(!m_hNotifyWnd)
1296 {
1297 wxLogSysError( wxT("Could not create hidden needed for ")
1298 wxT("registering for DirectShow events!") );
1299
1300 return false;
1301 }
1302
1303 #if defined(_WIN32)
1304 ::SetWindowLong(m_hNotifyWnd, GWL_WNDPROC,
1305 (LONG)wxAMMediaBackend::NotifyWndProc);
1306 #else
1307 ::SetWindowLongPtr(m_hNotifyWnd, GWLP_WNDPROC,
1308 (LONG_PTR)wxAMMediaBackend::NotifyWndProc);
1309 #endif
1310
1311 ::SetWindowLong(m_hNotifyWnd, GWL_USERDATA,
1312 (LONG) this);
1313
1314 wxAMVERIFY( m_pME->SetNotifyWindow((LONG_PTR)m_hNotifyWnd,
1315 WM_GRAPHNOTIFY, 0) );
1316
1317 //
1318 // Force the parent window of this control to recalculate
1319 // the size of this if sizers are being used
1320 // and render the results immediately
1321 //
1322 m_ctrl->InvalidateBestSize();
1323 m_ctrl->GetParent()->Layout();
1324 m_ctrl->GetParent()->Refresh();
1325 m_ctrl->GetParent()->Update();
1326 m_ctrl->SetSize(m_ctrl->GetSize());
1327
1328 return true;
1329 }
1330
1331 //---------------------------------------------------------------------------
1332 // wxAMMediaBackend::Load (URL Version)
1333 //
1334 // Loads media from a URL. Interestingly enough DirectShow
1335 // appears (?) to escape the URL for us, at least on normal
1336 // files
1337 //---------------------------------------------------------------------------
1338 bool wxAMMediaBackend::Load(const wxURI& location)
1339 {
1340 return Load(location.BuildUnescapedURI());
1341 }
1342
1343 //---------------------------------------------------------------------------
1344 // wxAMMediaBackend::Play
1345 //
1346 // Plays the stream. If it is non-seekable, it will restart it.
1347 //---------------------------------------------------------------------------
1348 bool wxAMMediaBackend::Play()
1349 {
1350 return SUCCEEDED( m_pMC->Run() );
1351 }
1352
1353 //---------------------------------------------------------------------------
1354 // wxAMMediaBackend::Pause
1355 //
1356 // Pauses the stream.
1357 //---------------------------------------------------------------------------
1358 bool wxAMMediaBackend::Pause()
1359 {
1360 return SUCCEEDED( m_pMC->Pause() );
1361 }
1362
1363 //---------------------------------------------------------------------------
1364 // wxAMMediaBackend::Stop
1365 //
1366 // Stops the stream.
1367 //---------------------------------------------------------------------------
1368 bool wxAMMediaBackend::Stop()
1369 {
1370 bool bOK = SUCCEEDED( m_pMC->Stop() );
1371
1372 //We don't care if it can't get to the beginning in directshow -
1373 //it could be a non-seeking filter (wince midi) in which case playing
1374 //starts all over again
1375 SetPosition(0);
1376 return bOK;
1377 }
1378
1379 //---------------------------------------------------------------------------
1380 // wxAMMediaBackend::SetPosition
1381 //
1382 // 1) Translates the current position's time to directshow time,
1383 // which is in a scale of 1 second (in a double)
1384 // 2) Sets the play position of the IMediaSeeking interface -
1385 // passing NULL as the stop position means to keep the old
1386 // stop position
1387 //---------------------------------------------------------------------------
1388 bool wxAMMediaBackend::SetPosition(wxLongLong where)
1389 {
1390 return SUCCEEDED( m_pMS->put_CurrentPosition(
1391 ((LONGLONG)where.GetValue()) / 1000
1392 )
1393 );
1394 }
1395
1396 //---------------------------------------------------------------------------
1397 // wxAMMediaBackend::GetPosition
1398 //
1399 // 1) Obtains the current play and stop positions from IMediaSeeking
1400 // 2) Returns the play position translated to our time base
1401 //---------------------------------------------------------------------------
1402 wxLongLong wxAMMediaBackend::GetPosition()
1403 {
1404 double outCur;
1405 wxAMVERIFY( m_pMS->get_CurrentPosition(&outCur) );
1406
1407 //h,m,s,milli - outdur is in 1 second (double)
1408 return (outCur*1000);
1409 }
1410
1411 //---------------------------------------------------------------------------
1412 // wxAMMediaBackend::SetVolume
1413 //
1414 // Sets the volume through the IBasicAudio interface -
1415 // value ranges from 0 (MAX volume) to -10000 (minimum volume).
1416 // -100 per decibel.
1417 //---------------------------------------------------------------------------
1418 bool wxAMMediaBackend::SetVolume(double dVolume)
1419 {
1420 return SUCCEEDED(m_pBA->put_Volume( (long) ((dVolume-1.0) * 10000.0) ));
1421 }
1422
1423 //---------------------------------------------------------------------------
1424 // wxAMMediaBackend::GetVolume
1425 //
1426 // Gets the volume through the IBasicAudio interface -
1427 // value ranges from 0 (MAX volume) to -10000 (minimum volume).
1428 // -100 per decibel.
1429 //---------------------------------------------------------------------------
1430 double wxAMMediaBackend::GetVolume()
1431 {
1432 long lVolume;
1433 if ( SUCCEEDED(m_pBA->get_Volume(&lVolume)) )
1434 return (((double)(lVolume + 10000)) / 10000.0);
1435 return 0.0;
1436 }
1437
1438 //---------------------------------------------------------------------------
1439 // wxAMMediaBackend::GetDuration
1440 //
1441 // 1) Obtains the duration of the media from the IMediaSeeking interface
1442 // 2) Converts that value to our time base, and returns it
1443 //---------------------------------------------------------------------------
1444 wxLongLong wxAMMediaBackend::GetDuration()
1445 {
1446 double outDuration;
1447 wxAMVERIFY( m_pMS->get_Duration(&outDuration) );
1448
1449 //h,m,s,milli - outdur is in 1 second (double)
1450 return (outDuration*1000);
1451 }
1452
1453 //---------------------------------------------------------------------------
1454 // wxAMMediaBackend::GetState
1455 //
1456 // Obtains the state from the IMediaControl interface.
1457 // Note that it's enumeration values for stopping/playing
1458 // etc. are the same as ours, so we just do a straight cast.
1459 // TODO: MS recommends against INFINITE here for
1460 // IMediaControl::GetState- do it in stages
1461 //---------------------------------------------------------------------------
1462 wxMediaState wxAMMediaBackend::GetState()
1463 {
1464 HRESULT hr;
1465 long theState; //OAFilterState
1466 hr = m_pMC->GetState(INFINITE, &theState);
1467
1468 wxASSERT( SUCCEEDED(hr) );
1469
1470 //MSW state is the same as ours
1471 //State_Stopped = 0,
1472 //State_Paused = State_Stopped + 1,
1473 //State_Running = State_Paused + 1
1474
1475 return (wxMediaState) theState;
1476 }
1477
1478 //---------------------------------------------------------------------------
1479 // wxAMMediaBackend::GetPlaybackRate
1480 //
1481 // Pretty simple way of obtaining the playback rate from
1482 // the IMediaSeeking interface
1483 //---------------------------------------------------------------------------
1484 double wxAMMediaBackend::GetPlaybackRate()
1485 {
1486 double dRate;
1487 wxAMVERIFY( m_pMS->get_Rate(&dRate) );
1488 return dRate;
1489 }
1490
1491 //---------------------------------------------------------------------------
1492 // wxAMMediaBackend::SetPlaybackRate
1493 //
1494 // Sets the playback rate of the media - DirectShow is pretty good
1495 // about this, actually
1496 //---------------------------------------------------------------------------
1497 bool wxAMMediaBackend::SetPlaybackRate(double dRate)
1498 {
1499 return SUCCEEDED( m_pMS->put_Rate(dRate) );
1500 }
1501
1502 //---------------------------------------------------------------------------
1503 // wxAMMediaBackend::NotifyWndProc
1504 //
1505 // Here we check to see if DirectShow tells us we've reached the stop
1506 // position in our stream - if it has, it may not actually stop
1507 // the stream - which we need to do...
1508 //---------------------------------------------------------------------------
1509 LRESULT CALLBACK wxAMMediaBackend::NotifyWndProc(HWND hWnd, UINT nMsg,
1510 WPARAM wParam,
1511 LPARAM lParam)
1512 {
1513 wxAMMediaBackend* backend = (wxAMMediaBackend*)
1514 ::GetWindowLong(hWnd, GWL_USERDATA);
1515
1516 return backend->OnNotifyWndProc(hWnd, nMsg, wParam, lParam);
1517 }
1518
1519 LRESULT CALLBACK wxAMMediaBackend::OnNotifyWndProc(HWND hWnd, UINT nMsg,
1520 WPARAM wParam,
1521 LPARAM lParam)
1522 {
1523 if (nMsg == WM_GRAPHNOTIFY)
1524 {
1525 LONG evCode,
1526 evParam1,
1527 evParam2;
1528
1529 //
1530 // DirectShow keeps a list of queued events, and we need
1531 // to go through them one by one, stopping at (Hopefully only one)
1532 // EC_COMPLETE message
1533 //
1534 while(SUCCEEDED(m_pME->GetEvent(&evCode, (LONG_PTR *) &evParam1,
1535 (LONG_PTR *) &evParam2, 0)
1536 )
1537 )
1538 {
1539 // Cleanup memory that GetEvent allocated
1540 wxAMVERIFY( m_pME->FreeEventParams(evCode, evParam1, evParam2) );
1541
1542 // If this is the end of the clip, notify handler
1543 if(1 == evCode) //EC_COMPLETE
1544 {
1545 //send the event to our child
1546 wxMediaEvent theEvent(wxEVT_MEDIA_STOP, m_ctrl->GetId());
1547 m_ctrl->ProcessEvent(theEvent);
1548
1549 //if the user didn't veto it, stop the stream
1550 if (theEvent.IsAllowed())
1551 {
1552 //Interestingly enough, DirectShow does not actually stop
1553 //the filters - even when it reaches the end!
1554 wxVERIFY( Stop() );
1555
1556 //send the event to our child
1557 wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED,
1558 m_ctrl->GetId());
1559 m_ctrl->ProcessEvent(theEvent);
1560 }
1561 }
1562 }
1563 }
1564 return DefWindowProc(hWnd, nMsg, wParam, lParam);
1565 }
1566
1567 //---------------------------------------------------------------------------
1568 // wxAMMediaBackend::Cleanup
1569 //
1570 // 1) Hide/disowns the video window (MS says bad things will happen if
1571 // you don't)
1572 // 2) Releases all the directshow interfaces we use
1573 // TODO: Maybe there's a way to redirect the IMediaControl each time
1574 // we load, rather then creating and destroying the interfaces
1575 // each time?
1576 //---------------------------------------------------------------------------
1577 void wxAMMediaBackend::Cleanup()
1578 {
1579 // Hide then disown the window
1580 if(m_pVW)
1581 {
1582 m_pVW->put_Visible(0); //OSFALSE == 0
1583 m_pVW->put_Owner(NULL);
1584 }
1585
1586 // Release and zero DirectShow interfaces
1587 SAFE_RELEASE(m_pME);
1588 SAFE_RELEASE(m_pMS);
1589 SAFE_RELEASE(m_pBA);
1590 SAFE_RELEASE(m_pBV);
1591 SAFE_RELEASE(m_pVW);
1592 SAFE_RELEASE(m_pMC);
1593
1594 // Get rid of our hidden Window
1595 DestroyWindow(m_hNotifyWnd);
1596 m_hNotifyWnd = NULL;
1597 }
1598
1599
1600 //---------------------------------------------------------------------------
1601 // wxAMMediaBackend::GetVideoSize
1602 //
1603 // Obtains the cached original video size
1604 //---------------------------------------------------------------------------
1605 wxSize wxAMMediaBackend::GetVideoSize() const
1606 {
1607 return m_bestSize;
1608 }
1609
1610 //---------------------------------------------------------------------------
1611 // wxAMMediaBackend::Move
1612 //
1613 // Resizes the IVideoWindow to the size of the control window
1614 //---------------------------------------------------------------------------
1615 void wxAMMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y), int w, int h)
1616 {
1617 if(m_hNotifyWnd && m_bVideo)
1618 {
1619 wxAMVERIFY( m_pVW->SetWindowPosition(0, 0, w, h) );
1620 }
1621 }
1622
1623 //---------------------------------------------------------------------------
1624 // End of wxAMMediaBackend
1625 //---------------------------------------------------------------------------
1626 #endif //wxUSE_DIRECTSHOW
1627
1628 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1629 //
1630 // wxMCIMediaBackend
1631 //
1632 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1633
1634
1635 IMPLEMENT_DYNAMIC_CLASS(wxMCIMediaBackend, wxMediaBackend);
1636
1637 //---------------------------------------------------------------------------
1638 // Usual debugging macros for MCI returns
1639 //---------------------------------------------------------------------------
1640
1641 #ifdef __WXDEBUG__
1642 #define wxMCIVERIFY(arg) \
1643 { \
1644 DWORD nRet; \
1645 if ( (nRet = (arg)) != 0) \
1646 { \
1647 TCHAR sz[5000]; \
1648 mciGetErrorString(nRet, sz, 5000); \
1649 wxFAIL_MSG(wxString::Format(_T("MCI Error:%s"), sz)); \
1650 } \
1651 }
1652 #else
1653 #define wxMCIVERIFY(arg) (arg);
1654 #endif
1655
1656 //---------------------------------------------------------------------------
1657 // Simulation for <digitalv.h>
1658 //
1659 // Mingw and possibly other compilers don't have the digitalv.h header
1660 // that is needed to have some essential features of mci work with
1661 // windows - so we provide the declarations for the types we use here
1662 //---------------------------------------------------------------------------
1663
1664 typedef struct {
1665 DWORD_PTR dwCallback;
1666 #ifdef MCI_USE_OFFEXT
1667 POINT ptOffset;
1668 POINT ptExtent;
1669 #else
1670 RECT rc;
1671 #endif
1672 } MCI_DGV_RECT_PARMS;
1673
1674 typedef struct {
1675 DWORD_PTR dwCallback;
1676 HWND hWnd;
1677 #ifndef _WIN32
1678 WORD wReserved1;
1679 #endif
1680 UINT nCmdShow;
1681 #ifndef _WIN32
1682 WORD wReserved2;
1683 #endif
1684 wxChar* lpstrText;
1685 } MCI_DGV_WINDOW_PARMS;
1686
1687 typedef struct {
1688 DWORD_PTR dwCallback;
1689 DWORD dwTimeFormat;
1690 DWORD dwAudio;
1691 DWORD dwFileFormat;
1692 DWORD dwSpeed;
1693 } MCI_DGV_SET_PARMS;
1694
1695 typedef struct {
1696 DWORD_PTR dwCallback;
1697 DWORD dwItem;
1698 DWORD dwValue;
1699 DWORD dwOver;
1700 wxChar* lpstrAlgorithm;
1701 wxChar* lpstrQuality;
1702 } MCI_DGV_SETAUDIO_PARMS;
1703
1704 //---------------------------------------------------------------------------
1705 // wxMCIMediaBackend Constructor
1706 //
1707 // Here we don't need to do much except say we don't have any video :)
1708 //---------------------------------------------------------------------------
1709 wxMCIMediaBackend::wxMCIMediaBackend() : m_hNotifyWnd(NULL), m_bVideo(false)
1710 {
1711 }
1712
1713 //---------------------------------------------------------------------------
1714 // wxMCIMediaBackend Destructor
1715 //
1716 // We close the mci device - note that there may not be an mci device here,
1717 // or it may fail - but we don't really care, since we're destructing
1718 //---------------------------------------------------------------------------
1719 wxMCIMediaBackend::~wxMCIMediaBackend()
1720 {
1721 if(m_hNotifyWnd)
1722 {
1723 mciSendCommand(m_hDev, MCI_CLOSE, 0, 0);
1724 DestroyWindow(m_hNotifyWnd);
1725 m_hNotifyWnd = NULL;
1726 }
1727 }
1728
1729 //---------------------------------------------------------------------------
1730 // wxMCIMediaBackend::Create
1731 //
1732 // Here we just tell wxMediaCtrl that mci does exist (which it does, on all
1733 // msw systems, at least in some form dating back to win16 days)
1734 //---------------------------------------------------------------------------
1735 bool wxMCIMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
1736 wxWindowID id,
1737 const wxPoint& pos,
1738 const wxSize& size,
1739 long style,
1740 const wxValidator& validator,
1741 const wxString& name)
1742 {
1743 //
1744 // Create window
1745 // By default wxWindow(s) is created with a border -
1746 // so we need to get rid of those, and create with
1747 // wxCLIP_CHILDREN, so that if the driver/backend
1748 // is a child window, it refereshes properly
1749 //
1750 if ( !ctrl->wxControl::Create(parent, id, pos, size,
1751 (style & ~wxBORDER_MASK) | wxBORDER_NONE | wxCLIP_CHILDREN,
1752 validator, name) )
1753 return false;
1754
1755 m_ctrl = ctrl;
1756 return true;
1757 }
1758
1759 //---------------------------------------------------------------------------
1760 // wxMCIMediaBackend::Load (file version)
1761 //
1762 // Here we have MCI load a file and device, set the time format to our
1763 // default (milliseconds), and set the video (if any) to play in the control
1764 //---------------------------------------------------------------------------
1765 bool wxMCIMediaBackend::Load(const wxString& fileName)
1766 {
1767 //
1768 //if the user already called load close the previous MCI device
1769 //
1770 if(m_hNotifyWnd)
1771 {
1772 mciSendCommand(m_hDev, MCI_CLOSE, 0, 0);
1773 DestroyWindow(m_hNotifyWnd);
1774 m_hNotifyWnd = NULL;
1775 }
1776
1777 //
1778 //Opens a file and has MCI select a device. Normally you'd put
1779 //MCI_OPEN_TYPE in addition to MCI_OPEN_ELEMENT - however if you
1780 //omit this it tells MCI to select the device instead. This is
1781 //good because we have no reliable way of "enumerating" the devices
1782 //in MCI
1783 //
1784 MCI_OPEN_PARMS openParms;
1785 openParms.lpstrElementName = (wxChar*) fileName.c_str();
1786
1787 if ( mciSendCommand(0, MCI_OPEN, MCI_OPEN_ELEMENT,
1788 (DWORD)(LPVOID)&openParms) != 0)
1789 return false;
1790
1791 m_hDev = openParms.wDeviceID;
1792
1793 //
1794 //Now set the time format for the device to milliseconds
1795 //
1796 MCI_SET_PARMS setParms;
1797 setParms.dwCallback = 0;
1798 setParms.dwTimeFormat = MCI_FORMAT_MILLISECONDS;
1799
1800 if (mciSendCommand(m_hDev, MCI_SET, MCI_SET_TIME_FORMAT,
1801 (DWORD)(LPVOID)&setParms) != 0)
1802 return false;
1803
1804 //
1805 //Now tell the MCI device to display the video in our wxMediaCtrl
1806 //
1807 MCI_DGV_WINDOW_PARMS windowParms;
1808 windowParms.hWnd = (HWND)m_ctrl->GetHandle();
1809
1810 m_bVideo = (mciSendCommand(m_hDev, MCI_WINDOW,
1811 0x00010000L, //MCI_DGV_WINDOW_HWND
1812 (DWORD)(LPVOID)&windowParms) == 0);
1813
1814 //
1815 // Create a hidden window and register to handle
1816 // MCI events
1817 // Note that wxCanvasClassName is already registered
1818 // and used by all wxWindows and normal wxControls
1819 //
1820 m_hNotifyWnd = ::CreateWindow
1821 (
1822 wxCanvasClassName,
1823 NULL,
1824 0, 0, 0, 0,
1825 0,
1826 (HWND) NULL,
1827 (HMENU)NULL,
1828 wxGetInstance(),
1829 (LPVOID) NULL
1830 );
1831
1832 if(!m_hNotifyWnd)
1833 {
1834 wxLogSysError( wxT("Could not create hidden needed for ")
1835 wxT("registering for DirectShow events!") );
1836
1837 return false;
1838 }
1839
1840 #if defined(_WIN32)
1841 ::SetWindowLong(m_hNotifyWnd, GWL_WNDPROC,
1842 (LONG)wxMCIMediaBackend::NotifyWndProc);
1843 #else
1844 ::SetWindowLongPtr(m_hNotifyWnd, GWLP_WNDPROC,
1845 (LONG_PTR)wxMCIMediaBackend::NotifyWndProc);
1846 #endif
1847
1848 ::SetWindowLong(m_hNotifyWnd, GWL_USERDATA,
1849 (LONG) this);
1850
1851 //
1852 //Here, if the parent of the control has a sizer - we
1853 //tell it to recalculate the size of this control since
1854 //the user opened a seperate media file
1855 //
1856 m_ctrl->InvalidateBestSize();
1857 m_ctrl->GetParent()->Layout();
1858 m_ctrl->GetParent()->Refresh();
1859 m_ctrl->GetParent()->Update();
1860 m_ctrl->SetSize(m_ctrl->GetSize());
1861
1862 return true;
1863 }
1864
1865 //---------------------------------------------------------------------------
1866 // wxMCIMediaBackend::Load (URL version)
1867 //
1868 // MCI doesn't support URLs directly (?)
1869 //
1870 // TODO: Use wxURL/wxFileSystem and mmioInstallProc
1871 //---------------------------------------------------------------------------
1872 bool wxMCIMediaBackend::Load(const wxURI& WXUNUSED(location))
1873 {
1874 return false;
1875 }
1876
1877 //---------------------------------------------------------------------------
1878 // wxMCIMediaBackend::Play
1879 //
1880 // Plays/Resumes the MCI device... a couple notes:
1881 // 1) Certain drivers will crash and burn if we don't pass them an
1882 // MCI_PLAY_PARMS, despite the documentation that says otherwise...
1883 // 2) There is a MCI_RESUME command, but MCI_PLAY does the same thing
1884 // and will resume from a stopped state also, so there's no need to
1885 // call both, for example
1886 //---------------------------------------------------------------------------
1887 bool wxMCIMediaBackend::Play()
1888 {
1889 MCI_PLAY_PARMS playParms;
1890 playParms.dwCallback = (DWORD)m_hNotifyWnd;
1891
1892 bool bOK = ( mciSendCommand(m_hDev, MCI_PLAY, MCI_NOTIFY,
1893 (DWORD)(LPVOID)&playParms) == 0 );
1894
1895 if(bOK)
1896 m_ctrl->Show(m_bVideo);
1897
1898 return bOK;
1899 }
1900
1901 //---------------------------------------------------------------------------
1902 // wxMCIMediaBackend::Pause
1903 //
1904 // Pauses the MCI device - nothing special
1905 //---------------------------------------------------------------------------
1906 bool wxMCIMediaBackend::Pause()
1907 {
1908 return (mciSendCommand(m_hDev, MCI_PAUSE, MCI_WAIT, 0) == 0);
1909 }
1910
1911 //---------------------------------------------------------------------------
1912 // wxMCIMediaBackend::Stop
1913 //
1914 // Stops the MCI device & seeks to the beginning as wxMediaCtrl docs outline
1915 //---------------------------------------------------------------------------
1916 bool wxMCIMediaBackend::Stop()
1917 {
1918 return (mciSendCommand(m_hDev, MCI_STOP, MCI_WAIT, 0) == 0) &&
1919 (mciSendCommand(m_hDev, MCI_SEEK, MCI_SEEK_TO_START, 0) == 0);
1920 }
1921
1922 //---------------------------------------------------------------------------
1923 // wxMCIMediaBackend::GetState
1924 //
1925 // Here we get the state and convert it to a wxMediaState -
1926 // since we use direct comparisons with MCI_MODE_PLAY and
1927 // MCI_MODE_PAUSE, we don't care if the MCI_STATUS call
1928 // fails or not
1929 //---------------------------------------------------------------------------
1930 wxMediaState wxMCIMediaBackend::GetState()
1931 {
1932 MCI_STATUS_PARMS statusParms;
1933 statusParms.dwItem = MCI_STATUS_MODE;
1934
1935 mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
1936 (DWORD)(LPVOID)&statusParms);
1937
1938 if(statusParms.dwReturn == MCI_MODE_PAUSE)
1939 return wxMEDIASTATE_PAUSED;
1940 else if(statusParms.dwReturn == MCI_MODE_PLAY)
1941 return wxMEDIASTATE_PLAYING;
1942 else
1943 return wxMEDIASTATE_STOPPED;
1944 }
1945
1946 //---------------------------------------------------------------------------
1947 // wxMCIMediaBackend::SetPosition
1948 //
1949 // Here we set the position of the device in the stream.
1950 // Note that MCI actually stops the device after you seek it if the
1951 // device is playing/paused, so we need to play the file after
1952 // MCI seeks like normal APIs would
1953 //---------------------------------------------------------------------------
1954 bool wxMCIMediaBackend::SetPosition(wxLongLong where)
1955 {
1956 MCI_SEEK_PARMS seekParms;
1957 seekParms.dwCallback = 0;
1958 #if wxUSE_LONGLONG_NATIVE && !wxUSE_LONGLONG_WX
1959 seekParms.dwTo = (DWORD)where.GetValue();
1960 #else /* wxUSE_LONGLONG_WX */
1961 /* no way to return it in one piece */
1962 wxASSERT( where.GetHi()==0 );
1963 seekParms.dwTo = (DWORD)where.GetLo();
1964 #endif /* wxUSE_LONGLONG_* */
1965
1966 //device was playing?
1967 bool bReplay = GetState() == wxMEDIASTATE_PLAYING;
1968
1969 if( mciSendCommand(m_hDev, MCI_SEEK, MCI_TO,
1970 (DWORD)(LPVOID)&seekParms) != 0)
1971 return false;
1972
1973 //If the device was playing, resume it
1974 if (bReplay)
1975 return Play();
1976 else
1977 return true;
1978 }
1979
1980 //---------------------------------------------------------------------------
1981 // wxMCIMediaBackend::GetPosition
1982 //
1983 // Gets the position of the device in the stream using the current
1984 // time format... nothing special here...
1985 //---------------------------------------------------------------------------
1986 wxLongLong wxMCIMediaBackend::GetPosition()
1987 {
1988 MCI_STATUS_PARMS statusParms;
1989 statusParms.dwItem = MCI_STATUS_POSITION;
1990
1991 if (mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
1992 (DWORD)(LPSTR)&statusParms) != 0)
1993 return 0;
1994
1995 return statusParms.dwReturn;
1996 }
1997
1998 //---------------------------------------------------------------------------
1999 // wxMCIMediaBackend::GetVolume
2000 //
2001 // Gets the volume of the current media via the MCI_DGV_STATUS_VOLUME
2002 // message. Value ranges from 0 (minimum) to 1000 (maximum volume).
2003 //---------------------------------------------------------------------------
2004 double wxMCIMediaBackend::GetVolume()
2005 {
2006 MCI_STATUS_PARMS statusParms;
2007 statusParms.dwCallback = NULL;
2008 statusParms.dwItem = 0x4019; //MCI_DGV_STATUS_VOLUME
2009
2010 if (mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
2011 (DWORD)(LPSTR)&statusParms) != 0)
2012 return 0;
2013
2014 return ((double)statusParms.dwReturn) / 1000.0;
2015 }
2016
2017 //---------------------------------------------------------------------------
2018 // wxMCIMediaBackend::SetVolume
2019 //
2020 // Sets the volume of the current media via the MCI_DGV_SETAUDIO_VOLUME
2021 // message. Value ranges from 0 (minimum) to 1000 (maximum volume).
2022 //---------------------------------------------------------------------------
2023 bool wxMCIMediaBackend::SetVolume(double dVolume)
2024 {
2025 MCI_DGV_SETAUDIO_PARMS audioParms;
2026 audioParms.dwCallback = NULL;
2027 audioParms.dwItem = 0x4002; //MCI_DGV_SETAUDIO_VOLUME
2028 audioParms.dwValue = (DWORD) (dVolume * 1000.0);
2029 audioParms.dwOver = 0;
2030 audioParms.lpstrAlgorithm = NULL;
2031 audioParms.lpstrQuality = NULL;
2032
2033 if (mciSendCommand(m_hDev, 0x0873, //MCI_SETAUDIO
2034 0x00800000L | 0x01000000L, //MCI_DGV_SETAUDIO+(_ITEM | _VALUE)
2035 (DWORD)(LPSTR)&audioParms) != 0)
2036 return false;
2037 return true;
2038 }
2039
2040 //---------------------------------------------------------------------------
2041 // wxMCIMediaBackend::GetDuration
2042 //
2043 // Gets the duration of the stream... nothing special
2044 //---------------------------------------------------------------------------
2045 wxLongLong wxMCIMediaBackend::GetDuration()
2046 {
2047 MCI_STATUS_PARMS statusParms;
2048 statusParms.dwItem = MCI_STATUS_LENGTH;
2049
2050 if (mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
2051 (DWORD)(LPSTR)&statusParms) != 0)
2052 return 0;
2053
2054 return statusParms.dwReturn;
2055 }
2056
2057 //---------------------------------------------------------------------------
2058 // wxMCIMediaBackend::Move
2059 //
2060 // Moves the window to a location
2061 //---------------------------------------------------------------------------
2062 void wxMCIMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y),
2063 int w, int h)
2064 {
2065 if (m_hNotifyWnd && m_bVideo)
2066 {
2067 MCI_DGV_RECT_PARMS putParms; //ifdefed MCI_DGV_PUT_PARMS
2068 memset(&putParms, 0, sizeof(MCI_DGV_RECT_PARMS));
2069 putParms.rc.bottom = h;
2070 putParms.rc.right = w;
2071
2072 //wxStackWalker will crash and burn here on assert
2073 //and mci doesn't like 0 and 0 for some reason (out of range )
2074 //so just don't it in that case
2075 if(w || h)
2076 {
2077 wxMCIVERIFY( mciSendCommand(m_hDev, MCI_PUT,
2078 0x00040000L, //MCI_DGV_PUT_DESTINATION
2079 (DWORD)(LPSTR)&putParms) );
2080 }
2081 }
2082 }
2083
2084 //---------------------------------------------------------------------------
2085 // wxMCIMediaBackend::GetVideoSize
2086 //
2087 // Gets the original size of the movie for sizers
2088 //---------------------------------------------------------------------------
2089 wxSize wxMCIMediaBackend::GetVideoSize() const
2090 {
2091 if(m_bVideo)
2092 {
2093 MCI_DGV_RECT_PARMS whereParms; //ifdefed MCI_DGV_WHERE_PARMS
2094
2095 wxMCIVERIFY( mciSendCommand(m_hDev, MCI_WHERE,
2096 0x00020000L, //MCI_DGV_WHERE_SOURCE
2097 (DWORD)(LPSTR)&whereParms) );
2098
2099 return wxSize(whereParms.rc.right, whereParms.rc.bottom);
2100 }
2101 return wxSize(0,0);
2102 }
2103
2104 //---------------------------------------------------------------------------
2105 // wxMCIMediaBackend::GetPlaybackRate
2106 //
2107 // TODO
2108 //---------------------------------------------------------------------------
2109 double wxMCIMediaBackend::GetPlaybackRate()
2110 {
2111 return 1.0;
2112 }
2113
2114 //---------------------------------------------------------------------------
2115 // wxMCIMediaBackend::SetPlaybackRate
2116 //
2117 // TODO
2118 //---------------------------------------------------------------------------
2119 bool wxMCIMediaBackend::SetPlaybackRate(double WXUNUSED(dRate))
2120 {
2121 /*
2122 MCI_WAVE_SET_SAMPLESPERSEC
2123 MCI_DGV_SET_PARMS setParms;
2124 setParms.dwSpeed = (DWORD) (dRate * 1000.0);
2125
2126 return (mciSendCommand(m_hDev, MCI_SET,
2127 0x00020000L, //MCI_DGV_SET_SPEED
2128 (DWORD)(LPSTR)&setParms) == 0);
2129 */
2130 return false;
2131 }
2132
2133 //---------------------------------------------------------------------------
2134 // [static] wxMCIMediaBackend::MSWWindowProc
2135 //
2136 // Here we process a message when MCI reaches the stopping point
2137 // in the stream
2138 //---------------------------------------------------------------------------
2139 LRESULT CALLBACK wxMCIMediaBackend::NotifyWndProc(HWND hWnd, UINT nMsg,
2140 WPARAM wParam,
2141 LPARAM lParam)
2142 {
2143 wxMCIMediaBackend* backend = (wxMCIMediaBackend*)
2144 ::GetWindowLong(hWnd, GWL_USERDATA);
2145 wxASSERT(backend);
2146
2147 return backend->OnNotifyWndProc(hWnd, nMsg, wParam, lParam);
2148 }
2149
2150 LRESULT CALLBACK wxMCIMediaBackend::OnNotifyWndProc(HWND hWnd, UINT nMsg,
2151 WPARAM wParam,
2152 LPARAM lParam)
2153 {
2154 if(nMsg == MM_MCINOTIFY)
2155 {
2156 wxASSERT(lParam == (LPARAM) m_hDev);
2157 if(wParam == MCI_NOTIFY_SUCCESSFUL && lParam == (LPARAM)m_hDev)
2158 {
2159 wxMediaEvent theEvent(wxEVT_MEDIA_STOP, m_ctrl->GetId());
2160 m_ctrl->ProcessEvent(theEvent);
2161
2162 if(theEvent.IsAllowed())
2163 {
2164 wxMCIVERIFY( mciSendCommand(m_hDev, MCI_SEEK,
2165 MCI_SEEK_TO_START, 0) );
2166
2167 //send the event to our child
2168 wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED,
2169 m_ctrl->GetId());
2170 m_ctrl->ProcessEvent(theEvent);
2171 }
2172 }
2173 }
2174 return DefWindowProc(hWnd, nMsg, wParam, lParam);
2175 }
2176 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2177 //
2178 // wxQTMediaBackend
2179 //
2180 // TODO: Use a less cludgy way to pause/get state/set state
2181 // TODO: Dynamically load from qtml.dll
2182 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2183
2184 #if wxUSE_QUICKTIME
2185
2186 IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend);
2187
2188 //Time between timer calls
2189 #define MOVIE_DELAY 100
2190
2191 #include "wx/timer.h"
2192
2193 // --------------------------------------------------------------------------
2194 // wxQTTimer - Handle Asyncronous Playing
2195 // --------------------------------------------------------------------------
2196 class _wxQTTimer : public wxTimer
2197 {
2198 public:
2199 _wxQTTimer(Movie movie, wxQTMediaBackend* parent, wxQuickTimeLibrary* pLib) :
2200 m_movie(movie), m_bPaused(false), m_parent(parent), m_pLib(pLib)
2201 {
2202 }
2203
2204 ~_wxQTTimer()
2205 {
2206 }
2207
2208 bool GetPaused() {return m_bPaused;}
2209 void SetPaused(bool bPaused) {m_bPaused = bPaused;}
2210
2211 //-----------------------------------------------------------------------
2212 // _wxQTTimer::Notify
2213 //
2214 // 1) Checks to see if the movie is done, and if not continues
2215 // streaming the movie
2216 // 2) Sends the wxEVT_MEDIA_STOP event if we have reached the end of
2217 // the movie.
2218 //-----------------------------------------------------------------------
2219 void Notify()
2220 {
2221 if (!m_bPaused)
2222 {
2223 if(!m_pLib->IsMovieDone(m_movie))
2224 m_pLib->MoviesTask(m_movie, MOVIE_DELAY);
2225 else
2226 {
2227 wxMediaEvent theEvent(wxEVT_MEDIA_STOP,
2228 m_parent->m_ctrl->GetId());
2229 m_parent->m_ctrl->ProcessEvent(theEvent);
2230
2231 if(theEvent.IsAllowed())
2232 {
2233 Stop();
2234 m_parent->Stop();
2235 wxASSERT(m_pLib->GetMoviesError() == noErr);
2236
2237 //send the event to our child
2238 wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED,
2239 m_parent->m_ctrl->GetId());
2240 m_parent->m_ctrl->ProcessEvent(theEvent);
2241 }
2242 }
2243 }
2244 }
2245
2246 protected:
2247 Movie m_movie; //Our movie instance
2248 bool m_bPaused; //Whether we are paused or not
2249 wxQTMediaBackend* m_parent; //Backend pointer
2250 wxQuickTimeLibrary* m_pLib; //Interfaces
2251 };
2252
2253 //---------------------------------------------------------------------------
2254 // wxQTMediaBackend Destructor
2255 //
2256 // Sets m_timer to NULL signifying we havn't loaded anything yet
2257 //---------------------------------------------------------------------------
2258 wxQTMediaBackend::wxQTMediaBackend() : m_timer(NULL)
2259 {
2260 }
2261
2262 //---------------------------------------------------------------------------
2263 // wxQTMediaBackend Destructor
2264 //
2265 // 1) Cleans up the QuickTime movie instance
2266 // 2) Decrements the QuickTime reference counter - if this reaches
2267 // 0, QuickTime shuts down
2268 // 3) Decrements the QuickTime Windows Media Layer reference counter -
2269 // if this reaches 0, QuickTime shuts down the Windows Media Layer
2270 //---------------------------------------------------------------------------
2271 wxQTMediaBackend::~wxQTMediaBackend()
2272 {
2273 if(m_timer)
2274 Cleanup();
2275
2276 if(m_lib.IsOk())
2277 {
2278 //Note that ExitMovies() is not neccessary, but
2279 //the docs are fuzzy on whether or not TerminateQTML is
2280 m_lib.ExitMovies();
2281 m_lib.TerminateQTML();
2282 }
2283 }
2284
2285 //---------------------------------------------------------------------------
2286 // wxQTMediaBackend::CreateControl
2287 //
2288 // 1) Intializes QuickTime
2289 // 2) Creates the control window
2290 //---------------------------------------------------------------------------
2291 bool wxQTMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
2292 wxWindowID id,
2293 const wxPoint& pos,
2294 const wxSize& size,
2295 long style,
2296 const wxValidator& validator,
2297 const wxString& name)
2298 {
2299 if(!m_lib.Initialize())
2300 return false;
2301
2302 int nError;
2303 if ((nError = m_lib.InitializeQTML(0)) != noErr) //-2093 no dll
2304 {
2305 wxFAIL_MSG(wxString::Format(wxT("Couldn't Initialize Quicktime-%i"), nError));
2306 return false;
2307 }
2308 m_lib.EnterMovies();
2309
2310 //
2311 // Create window
2312 // By default wxWindow(s) is created with a border -
2313 // so we need to get rid of those
2314 //
2315 // Since we don't have a child window like most other
2316 // backends, we don't need wxCLIP_CHILDREN
2317 //
2318 if ( !ctrl->wxControl::Create(parent, id, pos, size,
2319 (style & ~wxBORDER_MASK) | wxBORDER_NONE,
2320 validator, name) )
2321 return false;
2322
2323 m_ctrl = ctrl;
2324 return true;
2325 }
2326
2327 //---------------------------------------------------------------------------
2328 // wxQTMediaBackend::Load (file version)
2329 //
2330 // 1) Get an FSSpec from the Windows path name
2331 // 2) Open the movie
2332 // 3) Obtain the movie instance from the movie resource
2333 // 4)
2334 //---------------------------------------------------------------------------
2335 bool wxQTMediaBackend::Load(const wxString& fileName)
2336 {
2337 if(m_timer)
2338 Cleanup();
2339
2340 OSErr err = noErr;
2341 short movieResFile;
2342 FSSpec sfFile;
2343
2344 if (m_lib.NativePathNameToFSSpec ((char*) (const char*) fileName.mb_str(),
2345 &sfFile, 0) != noErr)
2346 return false;
2347
2348 if (m_lib.OpenMovieFile (&sfFile, &movieResFile, fsRdPerm) != noErr)
2349 return false;
2350
2351 short movieResID = 0;
2352 Str255 movieName;
2353
2354 err = m_lib.NewMovieFromFile (
2355 &m_movie,
2356 movieResFile,
2357 &movieResID,
2358 movieName,
2359 newMovieActive,
2360 NULL); //wasChanged
2361
2362 m_lib.CloseMovieFile (movieResFile);
2363
2364 if (err != noErr)
2365 return false;
2366
2367 FinishLoad();
2368
2369 return m_lib.GetMoviesError() == noErr;
2370 }
2371
2372 //---------------------------------------------------------------------------
2373 // wxQTMediaBackend::Move
2374 //
2375 // TODO
2376 //---------------------------------------------------------------------------
2377 bool wxQTMediaBackend::Load(const wxURI& location)
2378 {
2379 if(m_timer)
2380 Cleanup();
2381
2382 wxString theURI = location.BuildURI();
2383
2384 OSErr err = noErr;
2385
2386 Handle theHandle = m_lib.NewHandleClear(theURI.length() + 1);
2387 wxASSERT(theHandle);
2388
2389 m_lib.BlockMove(theURI.mb_str(), *theHandle, theURI.length() + 1);
2390
2391 //create the movie from the handle that refers to the URI
2392 err = m_lib.NewMovieFromDataRef(&m_movie, newMovieActive,
2393 NULL, theHandle,
2394 'url'); //URLDataHandlerSubType
2395
2396 m_lib.DisposeHandle(theHandle);
2397
2398 if (err != noErr)
2399 return false;
2400
2401 //preroll movie for streaming
2402 //TODO:Async this?
2403 /*
2404 TimeValue timeNow;
2405 Fixed playRate;
2406 timeNow = GetMovieTime(m_movie, NULL);
2407 playRate = GetMoviePreferredRate(m_movie);
2408 PrePrerollMovie(m_movie, timeNow, playRate, NULL, NULL);
2409 PrerollMovie(m_movie, timeNow, playRate);
2410 m_lib.SetMovieRate(m_movie, playRate);
2411 */
2412
2413 FinishLoad();
2414
2415 return m_lib.GetMoviesError() == noErr;
2416 }
2417
2418 //---------------------------------------------------------------------------
2419 // wxQTMediaBackend::Move
2420 //
2421 // TODO
2422 //---------------------------------------------------------------------------
2423 void wxQTMediaBackend::FinishLoad()
2424 {
2425 m_timer = new _wxQTTimer(m_movie, (wxQTMediaBackend*) this, &m_lib);
2426 wxASSERT(m_timer);
2427
2428 //get the real size of the movie
2429 Rect outRect;
2430 m_lib.GetMovieNaturalBoundsRect (m_movie, &outRect);
2431 wxASSERT(m_lib.GetMoviesError() == noErr);
2432
2433 m_bestSize.x = outRect.right - outRect.left;
2434 m_bestSize.y = outRect.bottom - outRect.top;
2435
2436 //reparent movie/*AudioMediaCharacteristic*/
2437 if(m_lib.GetMovieIndTrackType(m_movie, 1,
2438 'eyes', //VisualMediaCharacteristic,
2439 (1 << 1) //movieTrackCharacteristic
2440 | (1 << 2) //movieTrackEnabledOnly
2441 ) != NULL)
2442 {
2443 m_lib.CreatePortAssociation(m_ctrl->GetHWND(), NULL, 0L);
2444
2445 m_lib.SetMovieGWorld(m_movie,
2446 (CGrafPtr) m_lib.GetNativeWindowPort(m_ctrl->GetHWND()),
2447 NULL);
2448 }
2449
2450 //we want millisecond precision
2451 m_lib.SetMovieTimeScale(m_movie, 1000);
2452 wxASSERT(m_lib.GetMoviesError() == noErr);
2453
2454 //
2455 //Here, if the parent of the control has a sizer - we
2456 //tell it to recalculate the size of this control since
2457 //the user opened a seperate media file
2458 //
2459 m_ctrl->InvalidateBestSize();
2460 m_ctrl->GetParent()->Layout();
2461 m_ctrl->GetParent()->Refresh();
2462 m_ctrl->GetParent()->Update();
2463 }
2464
2465 //---------------------------------------------------------------------------
2466 // wxQTMediaBackend::Move
2467 //
2468 // TODO
2469 //---------------------------------------------------------------------------
2470 bool wxQTMediaBackend::Play()
2471 {
2472 m_lib.StartMovie(m_movie);
2473 m_timer->SetPaused(false);
2474 m_timer->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS);
2475 return m_lib.GetMoviesError() == noErr;
2476 }
2477
2478 //---------------------------------------------------------------------------
2479 // wxQTMediaBackend::Move
2480 //
2481 // TODO
2482 //---------------------------------------------------------------------------
2483 bool wxQTMediaBackend::Pause()
2484 {
2485 m_lib.StopMovie(m_movie);
2486 m_timer->SetPaused(true);
2487 m_timer->Stop();
2488 return m_lib.GetMoviesError() == noErr;
2489 }
2490
2491 //---------------------------------------------------------------------------
2492 // wxQTMediaBackend::Move
2493 //
2494 // TODO
2495 //---------------------------------------------------------------------------
2496 bool wxQTMediaBackend::Stop()
2497 {
2498 m_timer->SetPaused(false);
2499 m_timer->Stop();
2500
2501 m_lib.StopMovie(m_movie);
2502 if(m_lib.GetMoviesError() != noErr)
2503 return false;
2504
2505 m_lib.GoToBeginningOfMovie(m_movie);
2506 return m_lib.GetMoviesError() == noErr;
2507 }
2508
2509 //---------------------------------------------------------------------------
2510 // wxQTMediaBackend::Move
2511 //
2512 // TODO
2513 //---------------------------------------------------------------------------
2514 double wxQTMediaBackend::GetPlaybackRate()
2515 {
2516 return ( ((double)m_lib.GetMovieRate(m_movie)) / 0x10000);
2517 }
2518
2519 //---------------------------------------------------------------------------
2520 // wxQTMediaBackend::Move
2521 //
2522 // TODO
2523 //---------------------------------------------------------------------------
2524 bool wxQTMediaBackend::SetPlaybackRate(double dRate)
2525 {
2526 m_lib.SetMovieRate(m_movie, (Fixed) (dRate * 0x10000));
2527 return m_lib.GetMoviesError() == noErr;
2528 }
2529
2530 //---------------------------------------------------------------------------
2531 // wxQTMediaBackend::Move
2532 //
2533 // TODO
2534 //---------------------------------------------------------------------------
2535 bool wxQTMediaBackend::SetPosition(wxLongLong where)
2536 {
2537 TimeRecord theTimeRecord;
2538 memset(&theTimeRecord, 0, sizeof(TimeRecord));
2539 theTimeRecord.value.lo = where.GetValue();
2540 theTimeRecord.scale = m_lib.GetMovieTimeScale(m_movie);
2541 theTimeRecord.base = m_lib.GetMovieTimeBase(m_movie);
2542 m_lib.SetMovieTime(m_movie, &theTimeRecord);
2543
2544 if (m_lib.GetMoviesError() != noErr)
2545 return false;
2546
2547 return true;
2548 }
2549
2550 //---------------------------------------------------------------------------
2551 // wxQTMediaBackend::GetPosition
2552 //
2553 // 1) Calls GetMovieTime to get the position we are in in the movie
2554 // in milliseconds (we called
2555 //---------------------------------------------------------------------------
2556 wxLongLong wxQTMediaBackend::GetPosition()
2557 {
2558 return m_lib.GetMovieTime(m_movie, NULL);
2559 }
2560
2561 //---------------------------------------------------------------------------
2562 // wxQTMediaBackend::GetVolume
2563 //
2564 // Gets the volume through GetMovieVolume - which returns a 16 bit short -
2565 //
2566 // +--------+--------+
2567 // + (1) + (2) +
2568 // +--------+--------+
2569 //
2570 // (1) first 8 bits are value before decimal
2571 // (2) second 8 bits are value after decimal
2572 //
2573 // Volume ranges from -1.0 (gain but no sound), 0 (no sound and no gain) to
2574 // 1 (full gain and sound)
2575 //---------------------------------------------------------------------------
2576 double wxQTMediaBackend::GetVolume()
2577 {
2578 short sVolume = m_lib.GetMovieVolume(m_movie);
2579
2580 if(sVolume & (128 << 8)) //negative - no sound
2581 return 0.0;
2582
2583 return (sVolume & (127 << 8)) ? 1.0 : ((double)(sVolume & 255)) / 255.0;
2584 }
2585
2586 //---------------------------------------------------------------------------
2587 // wxQTMediaBackend::SetVolume
2588 //
2589 // Sets the volume through SetMovieVolume - which takes a 16 bit short -
2590 //
2591 // +--------+--------+
2592 // + (1) + (2) +
2593 // +--------+--------+
2594 //
2595 // (1) first 8 bits are value before decimal
2596 // (2) second 8 bits are value after decimal
2597 //
2598 // Volume ranges from -1.0 (gain but no sound), 0 (no sound and no gain) to
2599 // 1 (full gain and sound)
2600 //---------------------------------------------------------------------------
2601 bool wxQTMediaBackend::SetVolume(double dVolume)
2602 {
2603 short sVolume = (dVolume >= .9999 ? 1 << 8 :
2604 (short) (dVolume * 255));
2605 m_lib.SetMovieVolume(m_movie, sVolume);
2606 return true;
2607 }
2608
2609 //---------------------------------------------------------------------------
2610 // wxQTMediaBackend::Move
2611 //
2612 // TODO
2613 //---------------------------------------------------------------------------
2614 wxLongLong wxQTMediaBackend::GetDuration()
2615 {
2616 return m_lib.GetMovieDuration(m_movie);
2617 }
2618
2619 //---------------------------------------------------------------------------
2620 // wxQTMediaBackend::Move
2621 //
2622 // TODO
2623 //---------------------------------------------------------------------------
2624 wxMediaState wxQTMediaBackend::GetState()
2625 {
2626 if ( !m_timer || (m_timer->IsRunning() == false &&
2627 m_timer->GetPaused() == false) )
2628 return wxMEDIASTATE_STOPPED;
2629
2630 if( m_timer->IsRunning() == true )
2631 return wxMEDIASTATE_PLAYING;
2632 else
2633 return wxMEDIASTATE_PAUSED;
2634 }
2635
2636 //---------------------------------------------------------------------------
2637 // wxQTMediaBackend::Move
2638 //
2639 // TODO
2640 //---------------------------------------------------------------------------
2641 void wxQTMediaBackend::Cleanup()
2642 {
2643 delete m_timer;
2644 m_timer = NULL;
2645
2646 m_lib.StopMovie(m_movie);
2647 m_lib.DisposeMovie(m_movie);
2648 }
2649
2650 //---------------------------------------------------------------------------
2651 // wxQTMediaBackend::Move
2652 //
2653 // TODO
2654 //---------------------------------------------------------------------------
2655 wxSize wxQTMediaBackend::GetVideoSize() const
2656 {
2657 return m_bestSize;
2658 }
2659
2660 //---------------------------------------------------------------------------
2661 // wxQTMediaBackend::Move
2662 //
2663 // TODO
2664 //---------------------------------------------------------------------------
2665 void wxQTMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y), int w, int h)
2666 {
2667 if(m_timer)
2668 {
2669 Rect theRect = {0, 0, h, w};
2670
2671 m_lib.SetMovieBox(m_movie, &theRect);
2672 wxASSERT(m_lib.GetMoviesError() == noErr);
2673 }
2674 }
2675
2676 //---------------------------------------------------------------------------
2677 // End QT Compilation Guard
2678 //---------------------------------------------------------------------------
2679 #endif //wxUSE_QUICKTIME
2680
2681 //in source file that contains stuff you don't directly use
2682 #include <wx/html/forcelnk.h>
2683 FORCE_LINK_ME(basewxmediabackends);
2684
2685 //---------------------------------------------------------------------------
2686 // End wxMediaCtrl Compilation Guard and this file
2687 //---------------------------------------------------------------------------
2688 #endif //wxUSE_MEDIACTRL
2689
2690