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