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