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