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