]> git.saurik.com Git - wxWidgets.git/blob - src/msw/mediactrl.cpp
Applied patch [ 1374215 ] Bug fix to wxSpinCtrl for Windows
[wxWidgets.git] / src / msw / mediactrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/mediactrl.cpp
3 // Purpose: Built-in Media Backends for Windows
4 // Author: Ryan Norton <wxprojects@comcast.net>
5 // Modified by:
6 // Created: 11/07/04
7 // RCS-ID: $Id$
8 // Copyright: (c) Ryan Norton
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 /*
13 FIXME FIXME FIXME:
14 - extract different backends in different files (better yet, make backends
15 dynamically loadable...), they have nothing to do with each other and
16 this file is huge and also separate the standard contents from our code
17 itself
18 */
19
20 //===========================================================================
21 // DECLARATIONS
22 //===========================================================================
23
24 //---------------------------------------------------------------------------
25 // Pre-compiled header stuff
26 //---------------------------------------------------------------------------
27
28 // For compilers that support precompilation, includes "wx.h".
29 #include "wx/wxprec.h"
30
31 #ifdef __BORLANDC__
32 #pragma hdrstop
33 #endif
34
35 //---------------------------------------------------------------------------
36 // MediaCtrl include
37 //---------------------------------------------------------------------------
38 #include "wx/mediactrl.h"
39
40 //---------------------------------------------------------------------------
41 // Compilation guard
42 //---------------------------------------------------------------------------
43 #if wxUSE_MEDIACTRL
44
45 //---------------------------------------------------------------------------
46 // WX Includes
47 //---------------------------------------------------------------------------
48 #include "wx/log.h" //wxLogDebug
49 #include "wx/math.h" //log10 & pow
50 #include "wx/msw/private.h" //user info and wndproc setting/getting
51 #include "wx/dcclient.h"
52 #include "wx/timer.h"
53 #include "wx/dynlib.h"
54
55 //---------------------------------------------------------------------------
56 // Externals (somewhere in src/msw/app.cpp and src/msw/window.cpp)
57 //---------------------------------------------------------------------------
58 extern "C" WXDLLIMPEXP_BASE HINSTANCE wxGetInstance(void);
59 #ifdef __WXWINCE__
60 extern WXDLLIMPEXP_CORE wxChar *wxCanvasClassName;
61 #else
62 extern WXDLLIMPEXP_CORE const wxChar *wxCanvasClassName;
63 #endif
64
65 LRESULT WXDLLIMPEXP_CORE APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
66 WPARAM wParam, LPARAM lParam);
67
68 //===========================================================================
69 // BACKEND DECLARATIONS
70 //===========================================================================
71
72 //---------------------------------------------------------------------------
73 //
74 // wxAMMediaBackend
75 //
76 //---------------------------------------------------------------------------
77
78 //---------------------------------------------------------------------------
79 // wxActiveXContainer - includes all the COM-specific stuff we need
80 //---------------------------------------------------------------------------
81 #include "wx/msw/ole/activex.h"
82
83 //---------------------------------------------------------------------------
84 // IIDS - used by CoCreateInstance and IUnknown::QueryInterface
85 //
86 // [idl name] [idl decription]
87 // amcompat.idl Microsoft Active Movie Control (Ver 2.0)
88 // nscompat.idl Microsoft NetShow Player (Ver 1.0)
89 // msdxm.idl Windows Media Player (Ver 1.0)
90 // quartz.idl
91 //
92 // First, when I say I "from XXX.idl", I mean I go into the COM Browser
93 // ($Microsoft Visual Studio$/Common/Tools/OLEVIEW.EXE), open
94 // "type libraries", open a specific type library (for quartz for example its
95 // "ActiveMovie control type library (V1.0)"), save it as an .idl, compile the
96 // idl using the midl compiler that comes with visual studio
97 // ($Microsoft Visual Studio$/VC98/bin/midl.exe on VC6) with the /h argument
98 // to make it generate stubs (a .h & .c file), then clean up the generated
99 // interfaces I want with the STDMETHOD wrappers and then put them into
100 // mediactrl.cpp.
101 //
102 // According to the MSDN docs, IMediaPlayer requires Windows 98 SE
103 // or greater. NetShow is available on Windows 3.1 and I'm guessing
104 // IActiveMovie is too. IMediaPlayer is essentially the Windows Media
105 // Player 6.4 SDK.
106 //
107 // Some of these are not used but are kept here for future reference anyway
108 //---------------------------------------------------------------------------
109 const IID IID_IActiveMovie = {0x05589FA2,0xC356,0x11CE,{0xBF,0x01,0x00,0xAA,0x00,0x55,0x59,0x5A}};
110 const IID IID_IActiveMovie2 = {0xB6CD6554,0xE9CB,0x11D0,{0x82,0x1F,0x00,0xA0,0xC9,0x1F,0x9C,0xA0}};
111 const IID IID_IActiveMovie3 = {0x265EC140,0xAE62,0x11D1,{0x85,0x00,0x00,0xA0,0xC9,0x1F,0x9C,0xA0}};
112
113 const IID IID_INSOPlay = {0x2179C5D1,0xEBFF,0x11CF,{0xB6,0xFD,0x00,0xAA,0x00,0xB4,0xE2,0x20}};
114 const IID IID_INSPlay = {0xE7C4BE80,0x7960,0x11D0,{0xB7,0x27,0x00,0xAA,0x00,0xB4,0xE2,0x20}};
115 const IID IID_INSPlay1 = {0x265EC141,0xAE62,0x11D1,{0x85,0x00,0x00,0xA0,0xC9,0x1F,0x9C,0xA0}};
116
117 const IID IID_IMediaPlayer = {0x22D6F311,0xB0F6,0x11D0,{0x94,0xAB,0x00,0x80,0xC7,0x4C,0x7E,0x95}};
118 const IID IID_IMediaPlayer2 = {0x20D4F5E0,0x5475,0x11D2,{0x97,0x74,0x00,0x00,0xF8,0x08,0x55,0xE6}};
119
120 const CLSID CLSID_ActiveMovie = {0x05589FA1,0xC356,0x11CE,{0xBF,0x01,0x00,0xAA,0x00,0x55,0x59,0x5A}};
121 const CLSID CLSID_MediaPlayer = {0x22D6F312,0xB0F6,0x11D0,{0x94,0xAB,0x00,0x80,0xC7,0x4C,0x7E,0x95}};
122 const CLSID CLSID_NSPlay = {0x2179C5D3,0xEBFF,0x11CF,{0xB6,0xFD,0x00,0xAA,0x00,0xB4,0xE2,0x20}};
123
124 const IID IID_IAMOpenProgress = {0x8E1C39A1, 0xDE53, 0x11CF,{0xAA, 0x63, 0x00, 0x80, 0xC7, 0x44, 0x52, 0x8D}};
125
126 // QUARTZ
127 const CLSID CLSID_FilgraphManager = {0xE436EBB3,0x524F,0x11CE,{0x9F,0x53,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
128 const IID IID_IMediaEvent = {0x56A868B6,0x0AD4,0x11CE,{0xB0,0x3A,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
129
130 //?? QUARTZ Also?
131 const CLSID CLSID_VideoMixingRenderer9 ={0x51B4ABF3, 0x748F, 0x4E3B,{0xA2, 0x76, 0xC8, 0x28, 0x33, 0x0E, 0x92, 0x6A}};
132 const IID IID_IVMRWindowlessControl9 = {0x8F537D09, 0xF85E, 0x4414,{0xB2, 0x3B, 0x50, 0x2E, 0x54, 0xC7, 0x99, 0x27}};
133 const IID IID_IFilterGraph = {0x56A8689F, 0x0AD4, 0x11CE,{0xB0, 0x3A, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70}};
134 const IID IID_IGraphBuilder = {0x56A868A9, 0x0AD4, 0x11CE,{0xB0, 0x3A, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70}};
135 const IID IID_IVMRFilterConfig9 = {0x5A804648, 0x4F66, 0x4867,{0x9C, 0x43, 0x4F, 0x5C, 0x82, 0x2C, 0xF1, 0xB8}};
136 const IID IID_IBaseFilter = {0x56A86895, 0x0AD4, 0x11CE,{0xB0, 0x3A, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70}};
137
138 //---------------------------------------------------------------------------
139 // QUARTZ COM INTERFACES (dumped from quartz.idl from MSVC COM Browser)
140 //---------------------------------------------------------------------------
141
142 struct IAMOpenProgress : public IUnknown
143 {
144 STDMETHOD(QueryProgress)(LONGLONG *pllTotal, LONGLONG *pllCurrent) PURE;
145 STDMETHOD(AbortOperation)(void) PURE;
146 };
147
148 struct IMediaEvent : public IDispatch
149 {
150 STDMETHOD(GetEventHandle)(LONG_PTR *) PURE;
151 STDMETHOD(GetEvent)(long *, LONG_PTR *, LONG_PTR *, long) PURE;
152 STDMETHOD(WaitForCompletion)(long, long *) PURE;
153 STDMETHOD(CancelDefaultHandling)(long) PURE;
154 STDMETHOD(RestoreDefaultHandling)(long) PURE;
155 STDMETHOD(FreeEventParams)(long, LONG_PTR, LONG_PTR) PURE;
156 };
157
158 //---------------------------------------------------------------------------
159 // ACTIVEMOVIE COM INTERFACES (dumped from amcompat.idl from MSVC COM Browser)
160 //---------------------------------------------------------------------------
161
162 enum ReadyStateConstants
163 {
164 amvUninitialized = 0,
165 amvLoading = 1,
166 amvInteractive = 3,
167 amvComplete = 4
168 };
169
170 enum StateConstants
171 {
172 amvNotLoaded = -1,
173 amvStopped = 0,
174 amvPaused = 1,
175 amvRunning = 2
176 };
177
178 enum DisplayModeConstants
179 {
180 amvTime = 0,
181 amvFrames = 1
182 };
183
184 enum WindowSizeConstants
185 {
186 amvOriginalSize = 0,
187 amvDoubleOriginalSize = 1,
188 amvOneSixteenthScreen = 2,
189 amvOneFourthScreen = 3,
190 amvOneHalfScreen = 4
191 };
192
193 enum AppearanceConstants
194 {
195 amvFlat = 0,
196 amv3D = 1
197 };
198
199 enum BorderStyleConstants
200 {
201 amvNone = 0,
202 amvFixedSingle = 1
203 };
204
205 struct IActiveMovie : public IDispatch
206 {
207 STDMETHOD(AboutBox)( void) PURE;
208 STDMETHOD(Run)( void) PURE;
209 STDMETHOD(Pause)( void) PURE;
210 STDMETHOD(Stop)( void) PURE;
211 STDMETHOD(get_ImageSourceWidth)(long __RPC_FAR *pWidth) PURE;
212 STDMETHOD(get_ImageSourceHeight)(long __RPC_FAR *pHeight) PURE;
213 STDMETHOD(get_Author)(BSTR __RPC_FAR *pbstrAuthor) PURE;
214 STDMETHOD(get_Title)(BSTR __RPC_FAR *pbstrTitle) PURE;
215 STDMETHOD(get_Copyright)(BSTR __RPC_FAR *pbstrCopyright) PURE;
216 STDMETHOD(get_Description)(BSTR __RPC_FAR *pbstrDescription) PURE;
217 STDMETHOD(get_Rating)(BSTR __RPC_FAR *pbstrRating) PURE;
218 STDMETHOD(get_FileName)(BSTR __RPC_FAR *pbstrFileName) PURE;
219 STDMETHOD(put_FileName)(BSTR pbstrFileName) PURE;
220 STDMETHOD(get_Duration)(double __RPC_FAR *pValue) PURE;
221 STDMETHOD(get_CurrentPosition)(double __RPC_FAR *pValue) PURE;
222 STDMETHOD(put_CurrentPosition)(double pValue) PURE;
223 STDMETHOD(get_PlayCount)(long __RPC_FAR *pPlayCount) PURE;
224 STDMETHOD(put_PlayCount)(long pPlayCount) PURE;
225 STDMETHOD(get_SelectionStart)(double __RPC_FAR *pValue) PURE;
226 STDMETHOD(put_SelectionStart)(double pValue) PURE;
227 STDMETHOD(get_SelectionEnd)(double __RPC_FAR *pValue) PURE;
228 STDMETHOD(put_SelectionEnd)(double pValue) PURE;
229 STDMETHOD(get_CurrentState)(StateConstants __RPC_FAR *pState) PURE;
230 STDMETHOD(get_Rate)(double __RPC_FAR *pValue) PURE;
231 STDMETHOD(put_Rate)(double pValue) PURE;
232 STDMETHOD(get_Volume)(long __RPC_FAR *pValue) PURE;
233 STDMETHOD(put_Volume)(long pValue) PURE;
234 STDMETHOD(get_Balance)(long __RPC_FAR *pValue) PURE;
235 STDMETHOD(put_Balance)(long pValue) PURE;
236 STDMETHOD(get_EnableContextMenu)(VARIANT_BOOL __RPC_FAR *pEnable) PURE;
237 STDMETHOD(put_EnableContextMenu)(VARIANT_BOOL pEnable) PURE;
238 STDMETHOD(get_ShowDisplay)(VARIANT_BOOL __RPC_FAR *Show) PURE;
239 STDMETHOD(put_ShowDisplay)(VARIANT_BOOL Show) PURE;
240 STDMETHOD(get_ShowControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
241 STDMETHOD(put_ShowControls)(VARIANT_BOOL Show) PURE;
242 STDMETHOD(get_ShowPositionControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
243 STDMETHOD(put_ShowPositionControls)(VARIANT_BOOL Show) PURE;
244 STDMETHOD(get_ShowSelectionControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
245 STDMETHOD(put_ShowSelectionControls)(VARIANT_BOOL Show) PURE;
246 STDMETHOD(get_ShowTracker)(VARIANT_BOOL __RPC_FAR *Show) PURE;
247 STDMETHOD(put_ShowTracker)(VARIANT_BOOL Show) PURE;
248 STDMETHOD(get_EnablePositionControls)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
249 STDMETHOD(put_EnablePositionControls)(VARIANT_BOOL Enable) PURE;
250 STDMETHOD(get_EnableSelectionControls)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
251 STDMETHOD(put_EnableSelectionControls)(VARIANT_BOOL Enable) PURE;
252 STDMETHOD(get_EnableTracker)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
253 STDMETHOD(put_EnableTracker)(VARIANT_BOOL Enable) PURE;
254 STDMETHOD(get_AllowHideDisplay)(VARIANT_BOOL __RPC_FAR *Show) PURE;
255 STDMETHOD(put_AllowHideDisplay)(VARIANT_BOOL Show) PURE;
256 STDMETHOD(get_AllowHideControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
257 STDMETHOD(put_AllowHideControls)(VARIANT_BOOL Show) PURE;
258 STDMETHOD(get_DisplayMode)(DisplayModeConstants __RPC_FAR *pValue) PURE;
259 STDMETHOD(put_DisplayMode)(DisplayModeConstants pValue) PURE;
260 STDMETHOD(get_AllowChangeDisplayMode)(VARIANT_BOOL __RPC_FAR *fAllow) PURE;
261 STDMETHOD(put_AllowChangeDisplayMode)(VARIANT_BOOL fAllow) PURE;
262 STDMETHOD(get_FilterGraph)(IUnknown __RPC_FAR *__RPC_FAR *ppFilterGraph) PURE;
263 STDMETHOD(put_FilterGraph)(IUnknown __RPC_FAR *ppFilterGraph) PURE;
264 STDMETHOD(get_FilterGraphDispatch)(IDispatch __RPC_FAR *__RPC_FAR *pDispatch) PURE;
265 STDMETHOD(get_DisplayForeColor)(unsigned long __RPC_FAR *ForeColor) PURE;
266 STDMETHOD(put_DisplayForeColor)(unsigned long ForeColor) PURE;
267 STDMETHOD(get_DisplayBackColor)(unsigned long __RPC_FAR *BackColor) PURE;
268 STDMETHOD(put_DisplayBackColor)(unsigned long BackColor) PURE;
269 STDMETHOD(get_MovieWindowSize)(WindowSizeConstants __RPC_FAR *WindowSize) PURE;
270 STDMETHOD(put_MovieWindowSize)(WindowSizeConstants WindowSize) PURE;
271 STDMETHOD(get_FullScreenMode)(VARIANT_BOOL __RPC_FAR *pEnable) PURE;
272 STDMETHOD(put_FullScreenMode)(VARIANT_BOOL pEnable) PURE;
273 STDMETHOD(get_AutoStart)(VARIANT_BOOL __RPC_FAR *pEnable) PURE;
274 STDMETHOD(put_AutoStart)(VARIANT_BOOL pEnable) PURE;
275 STDMETHOD(get_AutoRewind)(VARIANT_BOOL __RPC_FAR *pEnable) PURE;
276 STDMETHOD(put_AutoRewind)(VARIANT_BOOL pEnable) PURE;
277 STDMETHOD(get_hWnd)(long __RPC_FAR *hWnd) PURE;
278 STDMETHOD(get_Appearance)(AppearanceConstants __RPC_FAR *pAppearance) PURE;
279 STDMETHOD(put_Appearance)(AppearanceConstants pAppearance) PURE;
280 STDMETHOD(get_BorderStyle)(BorderStyleConstants __RPC_FAR *pBorderStyle) PURE;
281 STDMETHOD(put_BorderStyle)(BorderStyleConstants pBorderStyle) PURE;
282 STDMETHOD(get_Enabled)(VARIANT_BOOL __RPC_FAR *pEnabled) PURE;
283 STDMETHOD(put_Enabled)(VARIANT_BOOL pEnabled) PURE;
284 STDMETHOD(get_Info)(long __RPC_FAR *ppInfo) PURE;
285 };
286
287
288
289 struct IActiveMovie2 : public IActiveMovie
290 {
291 STDMETHOD(IsSoundCardEnabled)(VARIANT_BOOL __RPC_FAR *pbSoundCard) PURE;
292 STDMETHOD(get_ReadyState)(ReadyStateConstants __RPC_FAR *pValue) PURE;
293 };
294
295 struct IActiveMovie3 : public IActiveMovie2
296 {
297 STDMETHOD(get_MediaPlayer)(IDispatch __RPC_FAR *__RPC_FAR *ppDispatch) PURE;
298 };
299
300
301 //---------------------------------------------------------------------------
302 // MEDIAPLAYER COM INTERFACES (dumped from msdxm.idl from MSVC COM Browser)
303 //---------------------------------------------------------------------------
304
305 enum MPPlayStateConstants
306 {
307 mpStopped = 0,
308 mpPaused = 1,
309 mpPlaying = 2,
310 mpWaiting = 3,
311 mpScanForward = 4,
312 mpScanReverse = 5,
313 mpClosed = 6
314 };
315
316 enum MPDisplaySizeConstants
317 {
318 mpDefaultSize = 0,
319 mpHalfSize = 1,
320 mpDoubleSize = 2,
321 mpFullScreen = 3,
322 mpFitToSize = 4,
323 mpOneSixteenthScreen = 5,
324 mpOneFourthScreen = 6,
325 mpOneHalfScreen = 7
326 };
327
328 enum MPReadyStateConstants
329 {
330 mpReadyStateUninitialized = 0,
331 mpReadyStateLoading = 1,
332 mpReadyStateInteractive = 3,
333 mpReadyStateComplete = 4
334 };
335
336 typedef unsigned long VB_OLE_COLOR;
337
338 enum MPDisplayModeConstants
339 {
340 mpTime = 0,
341 mpFrames = 1
342 };
343
344 enum MPMoreInfoType
345 {
346 mpShowURL = 0,
347 mpClipURL = 1,
348 mpBannerURL = 2
349 };
350
351 enum MPMediaInfoType
352 {
353 mpShowFilename = 0,
354 mpShowTitle = 1,
355 mpShowAuthor = 2,
356 mpShowCopyright = 3,
357 mpShowRating = 4,
358 mpShowDescription = 5,
359 mpShowLogoIcon = 6,
360 mpClipFilename = 7,
361 mpClipTitle = 8,
362 mpClipAuthor = 9,
363 mpClipCopyright = 10,
364 mpClipRating = 11,
365 mpClipDescription = 12,
366 mpClipLogoIcon = 13,
367 mpBannerImage = 14,
368 mpBannerMoreInfo = 15,
369 mpWatermark = 16
370 };
371
372 enum DVDMenuIDConstants
373 {
374 dvdMenu_Title = 2,
375 dvdMenu_Root = 3,
376 dvdMenu_Subpicture = 4,
377 dvdMenu_Audio = 5,
378 dvdMenu_Angle = 6,
379 dvdMenu_Chapter = 7
380 };
381
382 enum MPShowDialogConstants
383 {
384 mpShowDialogHelp = 0,
385 mpShowDialogStatistics = 1,
386 mpShowDialogOptions = 2,
387 mpShowDialogContextMenu = 3
388 };
389
390
391 struct IMediaPlayer : public IDispatch
392 {
393 STDMETHOD(get_CurrentPosition)(double __RPC_FAR *pCurrentPosition) PURE;
394 STDMETHOD(put_CurrentPosition)(double pCurrentPosition) PURE;
395 STDMETHOD(get_Duration)(double __RPC_FAR *pDuration) PURE;
396 STDMETHOD(get_ImageSourceWidth)(long __RPC_FAR *pWidth) PURE;
397 STDMETHOD(get_ImageSourceHeight)(long __RPC_FAR *pHeight) PURE;
398 STDMETHOD(get_MarkerCount)(long __RPC_FAR *pMarkerCount) PURE;
399 STDMETHOD(get_CanScan)(VARIANT_BOOL __RPC_FAR *pCanScan) PURE;
400 STDMETHOD(get_CanSeek)(VARIANT_BOOL __RPC_FAR *pCanSeek) PURE;
401 STDMETHOD(get_CanSeekToMarkers)(VARIANT_BOOL __RPC_FAR *pCanSeekToMarkers) PURE;
402 STDMETHOD(get_CurrentMarker)(long __RPC_FAR *pCurrentMarker) PURE;
403 STDMETHOD(put_CurrentMarker)(long pCurrentMarker) PURE;
404 STDMETHOD(get_FileName)(BSTR __RPC_FAR *pbstrFileName) PURE;
405 STDMETHOD(put_FileName)(BSTR pbstrFileName) PURE;
406 STDMETHOD(get_SourceLink)(BSTR __RPC_FAR *pbstrSourceLink) PURE;
407 STDMETHOD(get_CreationDate)(DATE __RPC_FAR *pCreationDate) PURE;
408 STDMETHOD(get_ErrorCorrection)(BSTR __RPC_FAR *pbstrErrorCorrection) PURE;
409 STDMETHOD(get_Bandwidth)(long __RPC_FAR *pBandwidth) PURE;
410 STDMETHOD(get_SourceProtocol)(long __RPC_FAR *pSourceProtocol) PURE;
411 STDMETHOD(get_ReceivedPackets)(long __RPC_FAR *pReceivedPackets) PURE;
412 STDMETHOD(get_RecoveredPackets)(long __RPC_FAR *pRecoveredPackets) PURE;
413 STDMETHOD(get_LostPackets)(long __RPC_FAR *pLostPackets) PURE;
414 STDMETHOD(get_ReceptionQuality)(long __RPC_FAR *pReceptionQuality) PURE;
415 STDMETHOD(get_BufferingCount)(long __RPC_FAR *pBufferingCount) PURE;
416 STDMETHOD(get_IsBroadcast)(VARIANT_BOOL __RPC_FAR *pIsBroadcast) PURE;
417 STDMETHOD(get_BufferingProgress)(long __RPC_FAR *pBufferingProgress) PURE;
418 STDMETHOD(get_ChannelName)(BSTR __RPC_FAR *pbstrChannelName) PURE;
419 STDMETHOD(get_ChannelDescription)(BSTR __RPC_FAR *pbstrChannelDescription) PURE;
420 STDMETHOD(get_ChannelURL)(BSTR __RPC_FAR *pbstrChannelURL) PURE;
421 STDMETHOD(get_ContactAddress)(BSTR __RPC_FAR *pbstrContactAddress) PURE;
422 STDMETHOD(get_ContactPhone)(BSTR __RPC_FAR *pbstrContactPhone) PURE;
423 STDMETHOD(get_ContactEmail)(BSTR __RPC_FAR *pbstrContactEmail) PURE;
424 STDMETHOD(get_BufferingTime)(double __RPC_FAR *pBufferingTime) PURE;
425 STDMETHOD(put_BufferingTime)(double pBufferingTime) PURE;
426 STDMETHOD(get_AutoStart)(VARIANT_BOOL __RPC_FAR *pAutoStart) PURE;
427 STDMETHOD(put_AutoStart)(VARIANT_BOOL pAutoStart) PURE;
428 STDMETHOD(get_AutoRewind)(VARIANT_BOOL __RPC_FAR *pAutoRewind) PURE;
429 STDMETHOD(put_AutoRewind)(VARIANT_BOOL pAutoRewind) PURE;
430 STDMETHOD(get_Rate)(double __RPC_FAR *pRate) PURE;
431 STDMETHOD(put_Rate)(double pRate) PURE;
432 STDMETHOD(get_SendKeyboardEvents)(VARIANT_BOOL __RPC_FAR *pSendKeyboardEvents) PURE;
433 STDMETHOD(put_SendKeyboardEvents)(VARIANT_BOOL pSendKeyboardEvents) PURE;
434 STDMETHOD(get_SendMouseClickEvents)(VARIANT_BOOL __RPC_FAR *pSendMouseClickEvents) PURE;
435 STDMETHOD(put_SendMouseClickEvents)(VARIANT_BOOL pSendMouseClickEvents) PURE;
436 STDMETHOD(get_SendMouseMoveEvents)(VARIANT_BOOL __RPC_FAR *pSendMouseMoveEvents) PURE;
437 STDMETHOD(put_SendMouseMoveEvents)(VARIANT_BOOL pSendMouseMoveEvents) PURE;
438 STDMETHOD(get_PlayCount)(long __RPC_FAR *pPlayCount) PURE;
439 STDMETHOD(put_PlayCount)(long pPlayCount) PURE;
440 STDMETHOD(get_ClickToPlay)(VARIANT_BOOL __RPC_FAR *pClickToPlay) PURE;
441 STDMETHOD(put_ClickToPlay)(VARIANT_BOOL pClickToPlay) PURE;
442 STDMETHOD(get_AllowScan)(VARIANT_BOOL __RPC_FAR *pAllowScan) PURE;
443 STDMETHOD(put_AllowScan)(VARIANT_BOOL pAllowScan) PURE;
444 STDMETHOD(get_EnableContextMenu)(VARIANT_BOOL __RPC_FAR *pEnableContextMenu) PURE;
445 STDMETHOD(put_EnableContextMenu)(VARIANT_BOOL pEnableContextMenu) PURE;
446 STDMETHOD(get_CursorType)(long __RPC_FAR *pCursorType) PURE;
447 STDMETHOD(put_CursorType)(long pCursorType) PURE;
448 STDMETHOD(get_CodecCount)(long __RPC_FAR *pCodecCount) PURE;
449 STDMETHOD(get_AllowChangeDisplaySize)(VARIANT_BOOL __RPC_FAR *pAllowChangeDisplaySize) PURE;
450 STDMETHOD(put_AllowChangeDisplaySize)( VARIANT_BOOL pAllowChangeDisplaySize) PURE;
451 STDMETHOD(get_IsDurationValid)(VARIANT_BOOL __RPC_FAR *pIsDurationValid) PURE;
452 STDMETHOD(get_OpenState)(long __RPC_FAR *pOpenState) PURE;
453 STDMETHOD(get_SendOpenStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendOpenStateChangeEvents) PURE;
454 STDMETHOD(put_SendOpenStateChangeEvents)(VARIANT_BOOL pSendOpenStateChangeEvents) PURE;
455 STDMETHOD(get_SendWarningEvents)( VARIANT_BOOL __RPC_FAR *pSendWarningEvents) PURE;
456 STDMETHOD(put_SendWarningEvents)(VARIANT_BOOL pSendWarningEvents) PURE;
457 STDMETHOD(get_SendErrorEvents)(VARIANT_BOOL __RPC_FAR *pSendErrorEvents) PURE;
458 STDMETHOD(put_SendErrorEvents)(VARIANT_BOOL pSendErrorEvents) PURE;
459 STDMETHOD(get_PlayState)(MPPlayStateConstants __RPC_FAR *pPlayState) PURE;
460 STDMETHOD(get_SendPlayStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendPlayStateChangeEvents) PURE;
461 STDMETHOD(put_SendPlayStateChangeEvents)(VARIANT_BOOL pSendPlayStateChangeEvents) PURE;
462 STDMETHOD(get_DisplaySize)(MPDisplaySizeConstants __RPC_FAR *pDisplaySize) PURE;
463 STDMETHOD(put_DisplaySize)(MPDisplaySizeConstants pDisplaySize) PURE;
464 STDMETHOD(get_InvokeURLs)(VARIANT_BOOL __RPC_FAR *pInvokeURLs) PURE;
465 STDMETHOD(put_InvokeURLs)(VARIANT_BOOL pInvokeURLs) PURE;
466 STDMETHOD(get_BaseURL)(BSTR __RPC_FAR *pbstrBaseURL) PURE;
467 STDMETHOD(put_BaseURL)(BSTR pbstrBaseURL) PURE;
468 STDMETHOD(get_DefaultFrame)(BSTR __RPC_FAR *pbstrDefaultFrame) PURE;
469 STDMETHOD(put_DefaultFrame)(BSTR pbstrDefaultFrame) PURE;
470 STDMETHOD(get_HasError)(VARIANT_BOOL __RPC_FAR *pHasError) PURE;
471 STDMETHOD(get_ErrorDescription)(BSTR __RPC_FAR *pbstrErrorDescription) PURE;
472 STDMETHOD(get_ErrorCode)(long __RPC_FAR *pErrorCode) PURE;
473 STDMETHOD(get_AnimationAtStart)(VARIANT_BOOL __RPC_FAR *pAnimationAtStart) PURE;
474 STDMETHOD(put_AnimationAtStart)(VARIANT_BOOL pAnimationAtStart) PURE;
475 STDMETHOD(get_TransparentAtStart)( VARIANT_BOOL __RPC_FAR *pTransparentAtStart) PURE;
476 STDMETHOD(put_TransparentAtStart)(VARIANT_BOOL pTransparentAtStart) PURE;
477 STDMETHOD(get_Volume)(long __RPC_FAR *pVolume) PURE;
478 STDMETHOD(put_Volume)(long pVolume) PURE;
479 STDMETHOD(get_Balance)(long __RPC_FAR *pBalance) PURE;
480 STDMETHOD(put_Balance)(long pBalance) PURE;
481 STDMETHOD(get_ReadyState)(MPReadyStateConstants __RPC_FAR *pValue) PURE;
482 STDMETHOD(get_SelectionStart)(double __RPC_FAR *pValue) PURE;
483 STDMETHOD(put_SelectionStart)(double pValue) PURE;
484 STDMETHOD(get_SelectionEnd)(double __RPC_FAR *pValue) PURE;
485 STDMETHOD(put_SelectionEnd)(double pValue) PURE;
486 STDMETHOD(get_ShowDisplay)(VARIANT_BOOL __RPC_FAR *Show) PURE;
487 STDMETHOD(put_ShowDisplay)(VARIANT_BOOL Show) PURE;
488 STDMETHOD(get_ShowControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
489 STDMETHOD(put_ShowControls)(VARIANT_BOOL Show) PURE;
490 STDMETHOD(get_ShowPositionControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
491 STDMETHOD(put_ShowPositionControls)(VARIANT_BOOL Show) PURE;
492 STDMETHOD(get_ShowTracker)(VARIANT_BOOL __RPC_FAR *Show) PURE;
493 STDMETHOD(put_ShowTracker)(VARIANT_BOOL Show) PURE;
494 STDMETHOD(get_EnablePositionControls)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
495 STDMETHOD(put_EnablePositionControls)(VARIANT_BOOL Enable) PURE;
496 STDMETHOD(get_EnableTracker)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
497 STDMETHOD(put_EnableTracker)(VARIANT_BOOL Enable) PURE;
498 STDMETHOD(get_Enabled)(VARIANT_BOOL __RPC_FAR *pEnabled) PURE;
499 STDMETHOD(put_Enabled)(VARIANT_BOOL pEnabled) PURE;
500 STDMETHOD(get_DisplayForeColor)(VB_OLE_COLOR __RPC_FAR *ForeColor) PURE;
501 STDMETHOD(put_DisplayForeColor)(VB_OLE_COLOR ForeColor) PURE;
502 STDMETHOD(get_DisplayBackColor)(VB_OLE_COLOR __RPC_FAR *BackColor) PURE;
503 STDMETHOD(put_DisplayBackColor)(VB_OLE_COLOR BackColor) PURE;
504 STDMETHOD(get_DisplayMode)(MPDisplayModeConstants __RPC_FAR *pValue) PURE;
505 STDMETHOD(put_DisplayMode)(MPDisplayModeConstants pValue) PURE;
506 STDMETHOD(get_VideoBorder3D)(VARIANT_BOOL __RPC_FAR *pVideoBorderWidth) PURE;
507 STDMETHOD(put_VideoBorder3D)(VARIANT_BOOL pVideoBorderWidth) PURE;
508 STDMETHOD(get_VideoBorderWidth)(long __RPC_FAR *pVideoBorderWidth) PURE;
509 STDMETHOD(put_VideoBorderWidth)(long pVideoBorderWidth) PURE;
510 STDMETHOD(get_VideoBorderColor)(VB_OLE_COLOR __RPC_FAR *pVideoBorderWidth) PURE;
511 STDMETHOD(put_VideoBorderColor)(VB_OLE_COLOR pVideoBorderWidth) PURE;
512 STDMETHOD(get_ShowGotoBar)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
513 STDMETHOD(put_ShowGotoBar)(VARIANT_BOOL pbool) PURE;
514 STDMETHOD(get_ShowStatusBar)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
515 STDMETHOD(put_ShowStatusBar)(VARIANT_BOOL pbool) PURE;
516 STDMETHOD(get_ShowCaptioning)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
517 STDMETHOD(put_ShowCaptioning)(VARIANT_BOOL pbool) PURE;
518 STDMETHOD(get_ShowAudioControls)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
519 STDMETHOD(put_ShowAudioControls)(VARIANT_BOOL pbool) PURE;
520 STDMETHOD(get_CaptioningID)( BSTR __RPC_FAR *pstrText) PURE;
521 STDMETHOD(put_CaptioningID)(BSTR pstrText) PURE;
522 STDMETHOD(get_Mute)(VARIANT_BOOL __RPC_FAR *vbool) PURE;
523 STDMETHOD(put_Mute)(VARIANT_BOOL vbool) PURE;
524 STDMETHOD(get_CanPreview)(VARIANT_BOOL __RPC_FAR *pCanPreview) PURE;
525 STDMETHOD(get_PreviewMode)(VARIANT_BOOL __RPC_FAR *pPreviewMode) PURE;
526 STDMETHOD(put_PreviewMode)(VARIANT_BOOL pPreviewMode) PURE;
527 STDMETHOD(get_HasMultipleItems)(VARIANT_BOOL __RPC_FAR *pHasMuliItems) PURE;
528 STDMETHOD(get_Language)(long __RPC_FAR *pLanguage) PURE;
529 STDMETHOD(put_Language)(long pLanguage) PURE;
530 STDMETHOD(get_AudioStream)(long __RPC_FAR *pStream) PURE;
531 STDMETHOD(put_AudioStream)(long pStream) PURE;
532 STDMETHOD(get_SAMIStyle)(BSTR __RPC_FAR *pbstrStyle) PURE;
533 STDMETHOD(put_SAMIStyle)(BSTR pbstrStyle) PURE;
534 STDMETHOD(get_SAMILang)(BSTR __RPC_FAR *pbstrLang) PURE;
535 STDMETHOD(put_SAMILang)(BSTR pbstrLang) PURE;
536 STDMETHOD(get_SAMIFileName)(BSTR __RPC_FAR *pbstrFileName) PURE;
537 STDMETHOD(put_SAMIFileName)(BSTR pbstrFileName) PURE;
538 STDMETHOD(get_StreamCount)( long __RPC_FAR *pStreamCount) PURE;
539 STDMETHOD(get_ClientId)(BSTR __RPC_FAR *pbstrClientId) PURE;
540 STDMETHOD(get_ConnectionSpeed)(long __RPC_FAR *plConnectionSpeed) PURE;
541 STDMETHOD(get_AutoSize)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
542 STDMETHOD(put_AutoSize)(VARIANT_BOOL pbool) PURE;
543 STDMETHOD(get_EnableFullScreenControls)(VARIANT_BOOL __RPC_FAR *pbVal) PURE;
544 STDMETHOD(put_EnableFullScreenControls)(VARIANT_BOOL pbVal) PURE;
545 STDMETHOD(get_ActiveMovie)(IDispatch __RPC_FAR *__RPC_FAR *ppdispatch) PURE;
546 STDMETHOD(get_NSPlay)(IDispatch __RPC_FAR *__RPC_FAR *ppdispatch) PURE;
547 STDMETHOD(get_WindowlessVideo)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
548 STDMETHOD(put_WindowlessVideo)(VARIANT_BOOL pbool) PURE;
549 STDMETHOD(Play)(void) PURE;
550 STDMETHOD(Stop)(void) PURE;
551 STDMETHOD(Pause)(void) PURE;
552 STDMETHOD(GetMarkerTime)(long MarkerNum,
553 double __RPC_FAR *pMarkerTime) PURE;
554 STDMETHOD(GetMarkerName)(long MarkerNum,
555 BSTR __RPC_FAR *pbstrMarkerName) PURE;
556 STDMETHOD(AboutBox)(void) PURE;
557 STDMETHOD(GetCodecInstalled)(long CodecNum,
558 VARIANT_BOOL __RPC_FAR *pCodecInstalled) PURE;
559 STDMETHOD(GetCodecDescription)(long CodecNum,
560 BSTR __RPC_FAR *pbstrCodecDescription) PURE;
561 STDMETHOD(GetCodecURL)(long CodecNum,
562 BSTR __RPC_FAR *pbstrCodecURL) PURE;
563 STDMETHOD(GetMoreInfoURL)(MPMoreInfoType MoreInfoType,
564 BSTR __RPC_FAR *pbstrMoreInfoURL) PURE;
565 STDMETHOD(GetMediaInfoString)(MPMediaInfoType MediaInfoType,
566 BSTR __RPC_FAR *pbstrMediaInfo) PURE;
567 STDMETHOD(Cancel)(void) PURE;
568 STDMETHOD(Open)(BSTR bstrFileName) PURE;
569 STDMETHOD(IsSoundCardEnabled)(VARIANT_BOOL __RPC_FAR *pbSoundCard) PURE;
570 STDMETHOD(Next)(void) PURE;
571 STDMETHOD(Previous)(void) PURE;
572 STDMETHOD(StreamSelect)(long StreamNum) PURE;
573 STDMETHOD(FastForward)(void) PURE;
574 STDMETHOD(FastReverse)(void) PURE;
575 STDMETHOD(GetStreamName)(long StreamNum,
576 BSTR __RPC_FAR *pbstrStreamName) PURE;
577 STDMETHOD(GetStreamGroup)(long StreamNum,
578 long __RPC_FAR *pStreamGroup) PURE;
579 STDMETHOD(GetStreamSelected)(long StreamNum, VARIANT_BOOL __RPC_FAR *pStreamSelected) PURE;
580 };
581
582 struct IMediaPlayer2 : public IMediaPlayer
583 {
584 STDMETHOD(get_DVD)(struct IMediaPlayerDvd __RPC_FAR *__RPC_FAR *ppdispatch) PURE;
585 STDMETHOD(GetMediaParameter)(long EntryNum, BSTR bstrParameterName, BSTR __RPC_FAR *pbstrParameterValue) PURE;
586 STDMETHOD(GetMediaParameterName(long EntryNum, long Index, BSTR __RPC_FAR *pbstrParameterName) PURE;
587 STDMETHOD(get_EntryCount)(long __RPC_FAR *pNumberEntries) PURE;
588 STDMETHOD(GetCurrentEntry)(long __RPC_FAR *pEntryNumber) PURE;
589 STDMETHOD(SetCurrentEntry)(long EntryNumber) PURE;
590 STDMETHOD(ShowDialog)(MPShowDialogConstants mpDialogIndex) PURE;
591 };
592
593 //---------------------------------------------------------------------------
594 // NETSHOW COM INTERFACES (dumped from nscompat.idl from MSVC COM Browser)
595 //---------------------------------------------------------------------------
596
597 struct INSOPlay : public IDispatch
598 {
599 STDMETHOD(get_ImageSourceWidth)(long __RPC_FAR *pWidth) PURE;
600 STDMETHOD(get_ImageSourceHeight)(long __RPC_FAR *pHeight) PURE;
601 STDMETHOD(get_Duration)(double __RPC_FAR *pDuration) PURE;
602 STDMETHOD(get_Author)(BSTR __RPC_FAR *pbstrAuthor) PURE;
603 STDMETHOD(get_Copyright)(BSTR __RPC_FAR *pbstrCopyright) PURE;
604 STDMETHOD(get_Description)(BSTR __RPC_FAR *pbstrDescription) PURE;
605 STDMETHOD(get_Rating)(BSTR __RPC_FAR *pbstrRating) PURE;
606 STDMETHOD(get_Title)(BSTR __RPC_FAR *pbstrTitle) PURE;
607 STDMETHOD(get_SourceLink)(BSTR __RPC_FAR *pbstrSourceLink) PURE;
608 STDMETHOD(get_MarkerCount)(long __RPC_FAR *pMarkerCount) PURE;
609 STDMETHOD(get_CanScan)(VARIANT_BOOL __RPC_FAR *pCanScan) PURE;
610 STDMETHOD(get_CanSeek)(VARIANT_BOOL __RPC_FAR *pCanSeek) PURE;
611 STDMETHOD(get_CanSeekToMarkers)(VARIANT_BOOL __RPC_FAR *pCanSeekToMarkers) PURE;
612 STDMETHOD(get_CreationDate)(DATE __RPC_FAR *pCreationDate) PURE;
613 STDMETHOD(get_Bandwidth)(long __RPC_FAR *pBandwidth) PURE;
614 STDMETHOD(get_ErrorCorrection)(BSTR __RPC_FAR *pbstrErrorCorrection) PURE;
615 STDMETHOD(get_AutoStart)(VARIANT_BOOL __RPC_FAR *pAutoStart) PURE;
616 STDMETHOD(put_AutoStart)(VARIANT_BOOL pAutoStart) PURE;
617 STDMETHOD(get_AutoRewind)(VARIANT_BOOL __RPC_FAR *pAutoRewind) PURE;
618 STDMETHOD(put_AutoRewind)(VARIANT_BOOL pAutoRewind) PURE;
619 STDMETHOD(get_AllowChangeControlType)(VARIANT_BOOL __RPC_FAR *pAllowChangeControlType) PURE;
620 STDMETHOD(put_AllowChangeControlType)(VARIANT_BOOL pAllowChangeControlType) PURE;
621 STDMETHOD(get_InvokeURLs)(VARIANT_BOOL __RPC_FAR *pInvokeURLs) PURE;
622 STDMETHOD(put_InvokeURLs)(VARIANT_BOOL pInvokeURLs) PURE;
623 STDMETHOD(get_EnableContextMenu)(VARIANT_BOOL __RPC_FAR *pEnableContextMenu) PURE;
624 STDMETHOD(put_EnableContextMenu)(VARIANT_BOOL pEnableContextMenu) PURE;
625 STDMETHOD(get_TransparentAtStart)(VARIANT_BOOL __RPC_FAR *pTransparentAtStart) PURE;
626 STDMETHOD(put_TransparentAtStart)(VARIANT_BOOL pTransparentAtStart) PURE;
627 STDMETHOD(get_TransparentOnStop)(VARIANT_BOOL __RPC_FAR *pTransparentOnStop) PURE;
628 STDMETHOD(put_TransparentOnStop)(VARIANT_BOOL pTransparentOnStop) PURE;
629 STDMETHOD(get_ClickToPlay)(VARIANT_BOOL __RPC_FAR *pClickToPlay) PURE;
630 STDMETHOD(put_ClickToPlay)(VARIANT_BOOL pClickToPlay) PURE;
631 STDMETHOD(get_FileName)(BSTR __RPC_FAR *pbstrFileName) PURE;
632 STDMETHOD(put_FileName)(BSTR pbstrFileName) PURE;
633 STDMETHOD(get_CurrentPosition)(double __RPC_FAR *pCurrentPosition) PURE;
634 STDMETHOD(put_CurrentPosition)(double pCurrentPosition) PURE;
635 STDMETHOD(get_Rate)(double __RPC_FAR *pRate) PURE;
636 STDMETHOD(put_Rate)(double pRate) PURE;
637 STDMETHOD(get_CurrentMarker)(long __RPC_FAR *pCurrentMarker) PURE;
638 STDMETHOD(put_CurrentMarker)(long pCurrentMarker) PURE;
639 STDMETHOD(get_PlayCount)(long __RPC_FAR *pPlayCount) PURE;
640 STDMETHOD(put_PlayCount)(long pPlayCount) PURE;
641 STDMETHOD(get_CurrentState)(long __RPC_FAR *pCurrentState) PURE;
642 STDMETHOD(get_DisplaySize)(long __RPC_FAR *pDisplaySize) PURE;
643 STDMETHOD(put_DisplaySize)(long pDisplaySize) PURE;
644 STDMETHOD(get_MainWindow)(long __RPC_FAR *pMainWindow) PURE;
645 STDMETHOD(get_ControlType)(long __RPC_FAR *pControlType) PURE;
646 STDMETHOD(put_ControlType)(long pControlType) PURE;
647 STDMETHOD(get_AllowScan)(VARIANT_BOOL __RPC_FAR *pAllowScan) PURE;
648 STDMETHOD(put_AllowScan)(VARIANT_BOOL pAllowScan) PURE;
649 STDMETHOD(get_SendKeyboardEvents)(VARIANT_BOOL __RPC_FAR *pSendKeyboardEvents) PURE;
650 STDMETHOD(put_SendKeyboardEvents)(VARIANT_BOOL pSendKeyboardEvents) PURE;
651 STDMETHOD(get_SendMouseClickEvents)(VARIANT_BOOL __RPC_FAR *pSendMouseClickEvents) PURE;
652 STDMETHOD(put_SendMouseClickEvents)(VARIANT_BOOL pSendMouseClickEvents) PURE;
653 STDMETHOD(get_SendMouseMoveEvents)(VARIANT_BOOL __RPC_FAR *pSendMouseMoveEvents) PURE;
654 STDMETHOD(put_SendMouseMoveEvents)(VARIANT_BOOL pSendMouseMoveEvents) PURE;
655 STDMETHOD(get_SendStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendStateChangeEvents) PURE;
656 STDMETHOD(put_SendStateChangeEvents)(VARIANT_BOOL pSendStateChangeEvents) PURE;
657 STDMETHOD(get_ReceivedPackets)(long __RPC_FAR *pReceivedPackets) PURE;
658 STDMETHOD(get_RecoveredPackets)(long __RPC_FAR *pRecoveredPackets) PURE;
659 STDMETHOD(get_LostPackets)(long __RPC_FAR *pLostPackets) PURE;
660 STDMETHOD(get_ReceptionQuality)(long __RPC_FAR *pReceptionQuality) PURE;
661 STDMETHOD(get_BufferingCount)(long __RPC_FAR *pBufferingCount) PURE;
662 STDMETHOD(get_CursorType)(long __RPC_FAR *pCursorType) PURE;
663 STDMETHOD(put_CursorType)(long pCursorType) PURE;
664 STDMETHOD(get_AnimationAtStart)(VARIANT_BOOL __RPC_FAR *pAnimationAtStart) PURE;
665 STDMETHOD(put_AnimationAtStart)(VARIANT_BOOL pAnimationAtStart) PURE;
666 STDMETHOD(get_AnimationOnStop)(VARIANT_BOOL __RPC_FAR *pAnimationOnStop) PURE;
667 STDMETHOD(put_AnimationOnStop)(VARIANT_BOOL pAnimationOnStop) PURE;
668 STDMETHOD(Play)(void) PURE;
669 STDMETHOD(Pause)(void) PURE;
670 STDMETHOD(Stop)(void) PURE;
671 STDMETHOD(GetMarkerTime)(long MarkerNum, double __RPC_FAR *pMarkerTime) PURE;
672 STDMETHOD(GetMarkerName)(long MarkerNum, BSTR __RPC_FAR *pbstrMarkerName) PURE;
673 };
674
675 struct INSPlay : public INSOPlay
676 {
677 STDMETHOD(get_ChannelName)(BSTR __RPC_FAR *pbstrChannelName) PURE;
678 STDMETHOD(get_ChannelDescription)(BSTR __RPC_FAR *pbstrChannelDescription) PURE;
679 STDMETHOD(get_ChannelURL)(BSTR __RPC_FAR *pbstrChannelURL) PURE;
680 STDMETHOD(get_ContactAddress)(BSTR __RPC_FAR *pbstrContactAddress) PURE;
681 STDMETHOD(get_ContactPhone)(BSTR __RPC_FAR *pbstrContactPhone) PURE;
682 STDMETHOD(get_ContactEmail)(BSTR __RPC_FAR *pbstrContactEmail) PURE;
683 STDMETHOD(get_AllowChangeDisplaySize)(VARIANT_BOOL __RPC_FAR *pAllowChangeDisplaySize) PURE;
684 STDMETHOD(put_AllowChangeDisplaySize)(VARIANT_BOOL pAllowChangeDisplaySize) PURE;
685 STDMETHOD(get_CodecCount)(long __RPC_FAR *pCodecCount) PURE;
686 STDMETHOD(get_IsBroadcast)(VARIANT_BOOL __RPC_FAR *pIsBroadcast) PURE;
687 STDMETHOD(get_IsDurationValid)(VARIANT_BOOL __RPC_FAR *pIsDurationValid) PURE;
688 STDMETHOD(get_SourceProtocol)(long __RPC_FAR *pSourceProtocol) PURE;
689 STDMETHOD(get_OpenState)(long __RPC_FAR *pOpenState) PURE;
690 STDMETHOD(get_SendOpenStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendOpenStateChangeEvents) PURE;
691 STDMETHOD(put_SendOpenStateChangeEvents)(VARIANT_BOOL pSendOpenStateChangeEvents) PURE;
692 STDMETHOD(get_SendWarningEvents)(VARIANT_BOOL __RPC_FAR *pSendWarningEvents) PURE;
693 STDMETHOD(put_SendWarningEvents)(VARIANT_BOOL pSendWarningEvents) PURE;
694 STDMETHOD(get_SendErrorEvents)(VARIANT_BOOL __RPC_FAR *pSendErrorEvents) PURE;
695 STDMETHOD(put_SendErrorEvents)(VARIANT_BOOL pSendErrorEvents) PURE;
696 STDMETHOD(get_HasError)(VARIANT_BOOL __RPC_FAR *pHasError) PURE;
697 STDMETHOD(get_ErrorDescription)(BSTR __RPC_FAR *pbstrErrorDescription) PURE;
698 STDMETHOD(get_ErrorCode)(long __RPC_FAR *pErrorCode) PURE;
699 STDMETHOD(get_PlayState)(long __RPC_FAR *pPlayState) PURE;
700 STDMETHOD(get_SendPlayStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendPlayStateChangeEvents) PURE;
701 STDMETHOD(put_SendPlayStateChangeEvents)(VARIANT_BOOL pSendPlayStateChangeEvents) PURE;
702 STDMETHOD(get_BufferingTime)(double __RPC_FAR *pBufferingTime) PURE;
703 STDMETHOD(put_BufferingTime)(double pBufferingTime) PURE;
704 STDMETHOD(get_UseFixedUDPPort)(VARIANT_BOOL __RPC_FAR *pUseFixedUDPPort) PURE;
705 STDMETHOD(put_UseFixedUDPPort)(VARIANT_BOOL pUseFixedUDPPort) PURE;
706 STDMETHOD(get_FixedUDPPort)(long __RPC_FAR *pFixedUDPPort) PURE;
707 STDMETHOD(put_FixedUDPPort)(long pFixedUDPPort) PURE;
708 STDMETHOD(get_UseHTTPProxy)(VARIANT_BOOL __RPC_FAR *pUseHTTPProxy) PURE;
709 STDMETHOD(put_UseHTTPProxy)(VARIANT_BOOL pUseHTTPProxy) PURE;
710 STDMETHOD(get_EnableAutoProxy)(VARIANT_BOOL __RPC_FAR *pEnableAutoProxy) PURE;
711 STDMETHOD(put_EnableAutoProxy)(VARIANT_BOOL pEnableAutoProxy) PURE;
712 STDMETHOD(get_HTTPProxyHost)(BSTR __RPC_FAR *pbstrHTTPProxyHost) PURE;
713 STDMETHOD(put_HTTPProxyHost)(BSTR pbstrHTTPProxyHost) PURE;
714 STDMETHOD(get_HTTPProxyPort)(long __RPC_FAR *pHTTPProxyPort) PURE;
715 STDMETHOD(put_HTTPProxyPort)(long pHTTPProxyPort) PURE;
716 STDMETHOD(get_EnableMulticast)(VARIANT_BOOL __RPC_FAR *pEnableMulticast) PURE;
717 STDMETHOD(put_EnableMulticast)(VARIANT_BOOL pEnableMulticast) PURE;
718 STDMETHOD(get_EnableUDP)(VARIANT_BOOL __RPC_FAR *pEnableUDP) PURE;
719 STDMETHOD(put_EnableUDP)(VARIANT_BOOL pEnableUDP) PURE;
720 STDMETHOD(get_EnableTCP)(VARIANT_BOOL __RPC_FAR *pEnableTCP) PURE;
721 STDMETHOD(put_EnableTCP)(VARIANT_BOOL pEnableTCP) PURE;
722 STDMETHOD(get_EnableHTTP)(VARIANT_BOOL __RPC_FAR *pEnableHTTP) PURE;
723 STDMETHOD(put_EnableHTTP)(VARIANT_BOOL pEnableHTTP) PURE;
724 STDMETHOD(get_BufferingProgress)(long __RPC_FAR *pBufferingProgress) PURE;
725 STDMETHOD(get_BaseURL)(BSTR __RPC_FAR *pbstrBaseURL) PURE;
726 STDMETHOD(put_BaseURL)(BSTR pbstrBaseURL) PURE;
727 STDMETHOD(get_DefaultFrame)(BSTR __RPC_FAR *pbstrDefaultFrame) PURE;
728 STDMETHOD(put_DefaultFrame)(BSTR pbstrDefaultFrame) PURE;
729 STDMETHOD(AboutBox))(void) PURE;
730 STDMETHOD(Cancel)(void) PURE;
731 STDMETHOD(GetCodecInstalled)(long CodecNum, VARIANT_BOOL __RPC_FAR *pCodecInstalled) PURE;
732 STDMETHOD(GetCodecDescription)(long CodecNum, BSTR __RPC_FAR *pbstrCodecDescription) PURE;
733 STDMETHOD(GetCodecURL)(long CodecNum, BSTR __RPC_FAR *pbstrCodecURL) PURE;
734 STDMETHOD(Open)(BSTR bstrFileName) PURE;
735 };
736
737
738 struct INSPlay1 : public INSPlay
739 {
740 STDMETHOD(get_MediaPlayer)(IDispatch __RPC_FAR *__RPC_FAR *ppdispatch) PURE;
741 };
742
743 //---------------------------------------------------------------------------
744 // MISC COM INTERFACES
745 //---------------------------------------------------------------------------
746 typedef enum _FilterState
747 {
748 State_Stopped,
749 State_Paused,
750 State_Running
751 } FILTER_STATE;
752 typedef enum _PinDirection {
753 PINDIR_INPUT,
754 PINDIR_OUTPUT
755 } PIN_DIRECTION;
756
757 typedef struct _FilterInfo {
758 WCHAR achName[128];
759 struct IFilterGraph *pGraph;
760 } FILTER_INFO;
761
762 typedef struct _PinInfo {
763 struct IBaseFilter *pFilter;
764 PIN_DIRECTION dir;
765 WCHAR achName[128];
766 } PIN_INFO;
767
768 struct IBaseFilter;
769 struct IPin;
770 struct IEnumFilters;
771 typedef struct _MediaType {
772 GUID majortype;
773 GUID subtype;
774 BOOL bFixedSizeSamples;
775 BOOL bTemporalCompression;
776 ULONG lSampleSize;
777 GUID formattype;
778 IUnknown *pUnk;
779 ULONG cbFormat;
780 BYTE *pbFormat;
781 } AM_MEDIA_TYPE;
782
783 struct IFilterGraph : public IUnknown
784 {
785 STDMETHOD(AddFilter)(IBaseFilter *, LPCWSTR) PURE;
786 STDMETHOD(RemoveFilter)(IBaseFilter *) PURE;
787 STDMETHOD(EnumFilters)(IEnumFilters **) PURE;
788 STDMETHOD(FindFilterByName)(LPCWSTR, IBaseFilter **) PURE;
789 STDMETHOD(ConnectDirect)(IPin *, IPin *, const AM_MEDIA_TYPE *) PURE;
790 STDMETHOD(Reconnect)(IPin *) PURE;
791 STDMETHOD(Disconnect)(IPin *) PURE;
792 STDMETHOD(SetDefaultSyncSource)() PURE;
793 };
794
795 struct IGraphBuilder : public IFilterGraph
796 {
797 STDMETHOD(Connect)(IPin *, IPin *) PURE;
798 STDMETHOD(Render)(IPin *) PURE;
799 STDMETHOD(RenderFile)(LPCWSTR, LPCWSTR) PURE;
800 STDMETHOD(AddSourceFilter)(LPCWSTR, LPCWSTR, IBaseFilter **) PURE;
801 STDMETHOD(SetLogFile)(DWORD_PTR) PURE;
802 STDMETHOD(Abort)() PURE;
803 STDMETHOD(ShouldOperationContinue)() PURE;
804 };
805
806 struct IReferenceClock;
807 struct IEnumPins;
808 #define REFERENCE_TIME LONGLONG
809 struct IMediaFilter : public IPersist
810 {
811 STDMETHOD(Stop)( void) PURE;
812 STDMETHOD(Pause)( void) PURE;
813 STDMETHOD(Run)(REFERENCE_TIME tStart) PURE;
814 STDMETHOD(GetState)(DWORD dwMilliSecsTimeout,
815 FILTER_STATE *State) PURE;
816 STDMETHOD(SetSyncSource)(IReferenceClock *pClock) PURE;
817 STDMETHOD(GetSyncSource)(IReferenceClock **pClock) PURE;
818 };
819
820 struct IBaseFilter : public IMediaFilter
821 {
822 STDMETHOD(EnumPins)(IEnumPins **ppEnum) PURE;
823 STDMETHOD(FindPin)(LPCWSTR Id, IPin **ppPin) PURE;
824 STDMETHOD(QueryFilterInfo)(FILTER_INFO *pInfo) PURE;
825 STDMETHOD(JoinFilterGraph)(IFilterGraph *pGraph, LPCWSTR pName) PURE;
826 STDMETHOD(QueryVendorInfo)(LPWSTR *pVendorInfo) PURE;
827 };
828
829
830 //###########################################################################
831 //
832 //
833 // wxAMMediaBackend
834 //
835 //
836 //###########################################################################
837
838 typedef BOOL (WINAPI* LPAMGETERRORTEXT)(HRESULT, wxChar *, DWORD);
839
840 class WXDLLIMPEXP_MEDIA wxAMMediaBackend : public wxMediaBackendCommonBase
841 {
842 public:
843 wxAMMediaBackend();
844 virtual ~wxAMMediaBackend();
845 void Clear();
846
847 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
848 wxWindowID id,
849 const wxPoint& pos,
850 const wxSize& size,
851 long style,
852 const wxValidator& validator,
853 const wxString& name);
854
855 virtual bool Play();
856 virtual bool Pause();
857 virtual bool Stop();
858
859 virtual bool Load(const wxString& fileName);
860 virtual bool Load(const wxURI& location);
861 virtual bool Load(const wxURI& location, const wxURI& proxy);
862
863 bool DoLoad(const wxString& location);
864 void FinishLoad();
865
866 virtual wxMediaState GetState();
867
868 virtual bool SetPosition(wxLongLong where);
869 virtual wxLongLong GetPosition();
870 virtual wxLongLong GetDuration();
871
872 virtual void Move(int x, int y, int w, int h);
873 wxSize GetVideoSize() const;
874
875 virtual double GetPlaybackRate();
876 virtual bool SetPlaybackRate(double);
877
878 virtual double GetVolume();
879 virtual bool SetVolume(double);
880
881 virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags);
882 void Cleanup();
883
884 void DoGetDownloadProgress(wxLongLong*, wxLongLong*);
885 virtual wxLongLong GetDownloadProgress()
886 {
887 wxLongLong progress, total;
888 DoGetDownloadProgress(&progress, &total);
889 return progress;
890 }
891 virtual wxLongLong GetDownloadTotal()
892 {
893 wxLongLong progress, total;
894 DoGetDownloadProgress(&progress, &total);
895 return total;
896 }
897
898 wxActiveXContainer* m_pAX;
899 IActiveMovie* m_pAM;
900 IMediaPlayer* m_pMP;
901 wxTimer* m_pTimer;
902 wxSize m_bestSize;
903
904 #ifdef __WXDEBUG__
905 wxDynamicLibrary m_dllQuartz;
906 LPAMGETERRORTEXT m_lpAMGetErrorText;
907 wxString GetErrorString(HRESULT hrdsv);
908 #endif // __WXDEBUG__
909
910 DECLARE_DYNAMIC_CLASS(wxAMMediaBackend)
911 };
912
913 //---------------------------------------------------------------------------
914 //
915 // wxMCIMediaBackend
916 //
917 //---------------------------------------------------------------------------
918
919 //---------------------------------------------------------------------------
920 // MCI Includes
921 //---------------------------------------------------------------------------
922 #include <mmsystem.h>
923
924 class WXDLLIMPEXP_MEDIA wxMCIMediaBackend : public wxMediaBackendCommonBase
925 {
926 public:
927
928 wxMCIMediaBackend();
929 ~wxMCIMediaBackend();
930
931 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
932 wxWindowID id,
933 const wxPoint& pos,
934 const wxSize& size,
935 long style,
936 const wxValidator& validator,
937 const wxString& name);
938
939 virtual bool Play();
940 virtual bool Pause();
941 virtual bool Stop();
942
943 virtual bool Load(const wxURI& location,
944 const wxURI& proxy)
945 { return wxMediaBackend::Load(location, proxy); }
946
947 virtual bool Load(const wxString& fileName);
948 virtual bool Load(const wxURI& location);
949
950 virtual wxMediaState GetState();
951
952 virtual bool SetPosition(wxLongLong where);
953 virtual wxLongLong GetPosition();
954 virtual wxLongLong GetDuration();
955
956 virtual void Move(int x, int y, int w, int h);
957 wxSize GetVideoSize() const;
958
959 virtual double GetPlaybackRate();
960 virtual bool SetPlaybackRate(double dRate);
961
962 virtual double GetVolume();
963 virtual bool SetVolume(double);
964
965 static LRESULT CALLBACK NotifyWndProc(HWND hWnd, UINT nMsg,
966 WPARAM wParam, LPARAM lParam);
967
968 LRESULT CALLBACK OnNotifyWndProc(HWND hWnd, UINT nMsg,
969 WPARAM wParam, LPARAM lParam);
970
971 MCIDEVICEID m_hDev; //Our MCI Device ID/Handler
972 HWND m_hNotifyWnd; //Window to use for MCI events
973 bool m_bVideo; //Whether or not we have video
974
975 DECLARE_DYNAMIC_CLASS(wxMCIMediaBackend)
976 };
977
978 //---------------------------------------------------------------------------
979 //
980 // wxQTMediaBackend
981 //
982 // We don't include Quicktime headers here and define all the types
983 // ourselves because looking for the quicktime libaries etc. would
984 // be tricky to do and making this a dependency for the MSVC projects
985 // would be unrealistic.
986 //
987 // Thanks to Robert Roebling for the wxDL macro/library idea
988 //---------------------------------------------------------------------------
989
990 //---------------------------------------------------------------------------
991 // QT Includes
992 //---------------------------------------------------------------------------
993 //#include <qtml.h> //Windoze QT include
994 //#include <QuickTimeComponents.h> //Standard QT stuff
995 #include "wx/dynlib.h"
996
997 //---------------------------------------------------------------------------
998 // QT Types
999 //---------------------------------------------------------------------------
1000 typedef struct MovieRecord* Movie;
1001 typedef wxInt16 OSErr;
1002 typedef wxInt32 OSStatus;
1003 #define noErr 0
1004 #define fsRdPerm 1
1005 typedef unsigned char Str255[256];
1006 #define StringPtr unsigned char*
1007 #define newMovieActive 1
1008 #define newMovieAsyncOK (1 << 8)
1009 #define Ptr char*
1010 #define Handle Ptr*
1011 #define Fixed long
1012 #define OSType unsigned long
1013 #define CGrafPtr struct GrafPort *
1014 #define TimeScale long
1015 #define TimeBase struct TimeBaseRecord *
1016 typedef struct ComponentInstanceRecord * ComponentInstance;
1017 #define kMovieLoadStatePlayable 10000
1018 #define Boolean int
1019 #define MovieController ComponentInstance
1020
1021 #ifndef URLDataHandlerSubType
1022 #if defined(__WATCOMC__) || defined(__MINGW32__)
1023 // use magic numbers for compilers which complain about multicharacter integers
1024 const OSType URLDataHandlerSubType = 1970433056;
1025 const OSType VisualMediaCharacteristic = 1702454643;
1026 #else
1027 const OSType URLDataHandlerSubType = 'url ';
1028 const OSType VisualMediaCharacteristic = 'eyes';
1029 #endif
1030 #endif
1031
1032 struct FSSpec {
1033 short vRefNum;
1034 long parID;
1035 Str255 name; /*Str63 on mac, Str255 on msw */
1036 };
1037
1038 struct Rect {
1039 short top;
1040 short left;
1041 short bottom;
1042 short right;
1043 };
1044
1045 struct wide {
1046 wxInt32 hi;
1047 wxUint32 lo;
1048 };
1049
1050 struct TimeRecord {
1051 wide value; /* units */
1052 TimeScale scale; /* units per second */
1053 TimeBase base;
1054 };
1055
1056 struct Point {
1057 short v;
1058 short h;
1059 };
1060
1061 struct EventRecord {
1062 wxUint16 what;
1063 wxUint32 message;
1064 wxUint32 when;
1065 Point where;
1066 wxUint16 modifiers;
1067 };
1068
1069 enum {
1070 mcTopLeftMovie = 1,
1071 mcScaleMovieToFit = 2,
1072 mcWithBadge = 4,
1073 mcNotVisible = 8,
1074 mcWithFrame = 16
1075 };
1076
1077 //---------------------------------------------------------------------------
1078 // QT Library
1079 //---------------------------------------------------------------------------
1080 #define wxDL_METHOD_DEFINE( rettype, name, args, shortargs, defret ) \
1081 typedef rettype (* name ## Type) args ; \
1082 name ## Type pfn_ ## name; \
1083 rettype name args \
1084 { if (m_ok) return pfn_ ## name shortargs ; return defret; }
1085
1086 #define wxDL_VOIDMETHOD_DEFINE( name, args, shortargs ) \
1087 typedef void (* name ## Type) args ; \
1088 name ## Type pfn_ ## name; \
1089 void name args \
1090 { if (m_ok) pfn_ ## name shortargs ; }
1091
1092 #define wxDL_METHOD_LOAD( lib, name, success ) \
1093 pfn_ ## name = (name ## Type) lib.GetSymbol( wxT(#name), &success ); \
1094 if (!success) { wxLog::EnableLogging(bWasLoggingEnabled); return false; }
1095
1096
1097 class WXDLLIMPEXP_MEDIA wxQuickTimeLibrary
1098 {
1099 public:
1100 ~wxQuickTimeLibrary()
1101 {
1102 if(m_dll.IsLoaded())
1103 m_dll.Unload();
1104 }
1105
1106 bool Initialize();
1107 bool IsOk() const {return m_ok;}
1108
1109 protected:
1110 wxDynamicLibrary m_dll;
1111 bool m_ok;
1112
1113 public:
1114 wxDL_VOIDMETHOD_DEFINE( StartMovie, (Movie m), (m) );
1115 wxDL_VOIDMETHOD_DEFINE( StopMovie, (Movie m), (m) );
1116 wxDL_METHOD_DEFINE( bool, IsMovieDone, (Movie m), (m), false);
1117 wxDL_VOIDMETHOD_DEFINE( GoToBeginningOfMovie, (Movie m), (m) );
1118 wxDL_METHOD_DEFINE( OSErr, GetMoviesError, (), (), -1);
1119 wxDL_METHOD_DEFINE( OSErr, EnterMovies, (), (), -1);
1120 wxDL_VOIDMETHOD_DEFINE( ExitMovies, (), () );
1121 wxDL_METHOD_DEFINE( OSErr, InitializeQTML, (long flags), (flags), -1);
1122 wxDL_VOIDMETHOD_DEFINE( TerminateQTML, (), () );
1123
1124 wxDL_METHOD_DEFINE( OSErr, NativePathNameToFSSpec,
1125 (char* inName, FSSpec* outFile, long flags),
1126 (inName, outFile, flags), -1);
1127
1128 wxDL_METHOD_DEFINE( OSErr, OpenMovieFile,
1129 (const FSSpec * fileSpec, short * resRefNum, wxInt8 permission),
1130 (fileSpec, resRefNum, permission), -1 );
1131
1132 wxDL_METHOD_DEFINE( OSErr, CloseMovieFile,
1133 (short resRefNum), (resRefNum), -1);
1134
1135 wxDL_METHOD_DEFINE( OSErr, NewMovieFromFile,
1136 (Movie * theMovie, short resRefNum, short * resId,
1137 StringPtr resName, short newMovieFlags,
1138 bool * dataRefWasChanged),
1139 (theMovie, resRefNum, resId, resName, newMovieFlags,
1140 dataRefWasChanged), -1);
1141
1142 wxDL_VOIDMETHOD_DEFINE( SetMovieRate, (Movie m, Fixed rate), (m, rate) );
1143 wxDL_METHOD_DEFINE( Fixed, GetMovieRate, (Movie m), (m), 0);
1144 wxDL_VOIDMETHOD_DEFINE( MoviesTask, (Movie m, long maxms), (m, maxms) );
1145 wxDL_VOIDMETHOD_DEFINE( BlockMove,
1146 (const char* p1, const char* p2, long s), (p1,p2,s) );
1147 wxDL_METHOD_DEFINE( Handle, NewHandleClear, (long s), (s), NULL );
1148
1149 wxDL_METHOD_DEFINE( OSErr, NewMovieFromDataRef,
1150 (Movie * m, short flags, short * id,
1151 Handle dataRef, OSType dataRefType),
1152 (m,flags,id,dataRef,dataRefType), -1 );
1153
1154 wxDL_VOIDMETHOD_DEFINE( DisposeHandle, (Handle h), (h) );
1155 wxDL_VOIDMETHOD_DEFINE( GetMovieNaturalBoundsRect, (Movie m, Rect* r), (m,r) );
1156 wxDL_METHOD_DEFINE( void*, GetMovieIndTrackType,
1157 (Movie m, long index, OSType type, long flags),
1158 (m,index,type,flags), NULL );
1159 wxDL_VOIDMETHOD_DEFINE( CreatePortAssociation,
1160 (void* hWnd, void* junk, long morejunk), (hWnd, junk, morejunk) );
1161 wxDL_METHOD_DEFINE(void*, GetNativeWindowPort, (void* hWnd), (hWnd), NULL);
1162 wxDL_VOIDMETHOD_DEFINE(SetMovieGWorld, (Movie m, CGrafPtr port, void* whatever),
1163 (m, port, whatever) );
1164 wxDL_VOIDMETHOD_DEFINE(DisposeMovie, (Movie m), (m) );
1165 wxDL_VOIDMETHOD_DEFINE(SetMovieBox, (Movie m, Rect* r), (m,r));
1166 wxDL_VOIDMETHOD_DEFINE(SetMovieTimeScale, (Movie m, long s), (m,s));
1167 wxDL_METHOD_DEFINE(long, GetMovieDuration, (Movie m), (m), 0);
1168 wxDL_METHOD_DEFINE(TimeBase, GetMovieTimeBase, (Movie m), (m), 0);
1169 wxDL_METHOD_DEFINE(TimeScale, GetMovieTimeScale, (Movie m), (m), 0);
1170 wxDL_METHOD_DEFINE(long, GetMovieTime, (Movie m, void* cruft), (m,cruft), 0);
1171 wxDL_VOIDMETHOD_DEFINE(SetMovieTime, (Movie m, TimeRecord* tr), (m,tr) );
1172 wxDL_METHOD_DEFINE(short, GetMovieVolume, (Movie m), (m), 0);
1173 wxDL_VOIDMETHOD_DEFINE(SetMovieVolume, (Movie m, short sVolume), (m,sVolume) );
1174 wxDL_VOIDMETHOD_DEFINE(SetMovieTimeValue, (Movie m, long s), (m,s));
1175 wxDL_METHOD_DEFINE(ComponentInstance, NewMovieController, (Movie m, const Rect* mr, long fl), (m,mr,fl), 0);
1176 wxDL_VOIDMETHOD_DEFINE(DisposeMovieController, (ComponentInstance ci), (ci));
1177 wxDL_METHOD_DEFINE(int, MCSetVisible, (ComponentInstance m, int b), (m, b), 0);
1178
1179
1180 wxDL_VOIDMETHOD_DEFINE(PrePrerollMovie, (Movie m, long t, Fixed r, WXFARPROC p1, void* p2), (m,t,r,p1,p2) );
1181 wxDL_VOIDMETHOD_DEFINE(PrerollMovie, (Movie m, long t, Fixed r), (m,t,r) );
1182 wxDL_METHOD_DEFINE(Fixed, GetMoviePreferredRate, (Movie m), (m), 0);
1183 wxDL_METHOD_DEFINE(long, GetMovieLoadState, (Movie m), (m), 0);
1184 wxDL_METHOD_DEFINE(void*, NewRoutineDescriptor, (WXFARPROC f, int l, void* junk), (f, l, junk), 0);
1185 wxDL_VOIDMETHOD_DEFINE(DisposeRoutineDescriptor, (void* f), (f));
1186 wxDL_METHOD_DEFINE(void*, GetCurrentArchitecture, (), (), 0);
1187 wxDL_METHOD_DEFINE(int, MCDoAction, (ComponentInstance ci, long f, void* p), (ci,f,p), 0);
1188 wxDL_VOIDMETHOD_DEFINE(MCSetControllerBoundsRect, (ComponentInstance ci, Rect* r), (ci,r));
1189 wxDL_VOIDMETHOD_DEFINE(DestroyPortAssociation, (CGrafPtr g), (g));
1190 wxDL_VOIDMETHOD_DEFINE(NativeEventToMacEvent, (MSG* p1, EventRecord* p2), (p1,p2));
1191 wxDL_VOIDMETHOD_DEFINE(MCIsPlayerEvent, (ComponentInstance ci, EventRecord* p2), (ci, p2));
1192 wxDL_METHOD_DEFINE(int, MCSetMovie, (ComponentInstance ci, Movie m, void* p1, Point w),
1193 (ci,m,p1,w),0);
1194 wxDL_VOIDMETHOD_DEFINE(MCPositionController,
1195 (ComponentInstance ci, Rect* r, void* junk, void* morejunk), (ci,r,junk,morejunk));
1196 wxDL_VOIDMETHOD_DEFINE(MCSetActionFilterWithRefCon,
1197 (ComponentInstance ci, WXFARPROC cb, void* ref), (ci,cb,ref));
1198 wxDL_VOIDMETHOD_DEFINE(MCGetControllerInfo, (MovieController mc, long* flags), (mc,flags));
1199 wxDL_VOIDMETHOD_DEFINE(BeginUpdate, (CGrafPtr port), (port));
1200 wxDL_VOIDMETHOD_DEFINE(UpdateMovie, (Movie m), (m));
1201 wxDL_VOIDMETHOD_DEFINE(EndUpdate, (CGrafPtr port), (port));
1202 wxDL_METHOD_DEFINE( OSErr, GetMoviesStickyError, (), (), -1);
1203 };
1204
1205 bool wxQuickTimeLibrary::Initialize()
1206 {
1207 m_ok = false;
1208
1209 bool bWasLoggingEnabled = wxLog::EnableLogging(false); //Turn off the wxDynamicLibrary logging
1210
1211 if(!m_dll.Load(wxT("qtmlClient.dll")))
1212 {
1213 wxLog::EnableLogging(bWasLoggingEnabled);
1214 return false;
1215 }
1216
1217 wxDL_METHOD_LOAD( m_dll, StartMovie, m_ok );
1218 wxDL_METHOD_LOAD( m_dll, StopMovie, m_ok );
1219 wxDL_METHOD_LOAD( m_dll, IsMovieDone, m_ok );
1220 wxDL_METHOD_LOAD( m_dll, GoToBeginningOfMovie, m_ok );
1221 wxDL_METHOD_LOAD( m_dll, GetMoviesError, m_ok );
1222 wxDL_METHOD_LOAD( m_dll, EnterMovies, m_ok );
1223 wxDL_METHOD_LOAD( m_dll, ExitMovies, m_ok );
1224 wxDL_METHOD_LOAD( m_dll, InitializeQTML, m_ok );
1225 wxDL_METHOD_LOAD( m_dll, TerminateQTML, m_ok );
1226 wxDL_METHOD_LOAD( m_dll, NativePathNameToFSSpec, m_ok );
1227 wxDL_METHOD_LOAD( m_dll, OpenMovieFile, m_ok );
1228 wxDL_METHOD_LOAD( m_dll, CloseMovieFile, m_ok );
1229 wxDL_METHOD_LOAD( m_dll, NewMovieFromFile, m_ok );
1230 wxDL_METHOD_LOAD( m_dll, GetMovieRate, m_ok );
1231 wxDL_METHOD_LOAD( m_dll, SetMovieRate, m_ok );
1232 wxDL_METHOD_LOAD( m_dll, MoviesTask, m_ok );
1233 wxDL_METHOD_LOAD( m_dll, BlockMove, m_ok );
1234 wxDL_METHOD_LOAD( m_dll, NewHandleClear, m_ok );
1235 wxDL_METHOD_LOAD( m_dll, NewMovieFromDataRef, m_ok );
1236 wxDL_METHOD_LOAD( m_dll, DisposeHandle, m_ok );
1237 wxDL_METHOD_LOAD( m_dll, GetMovieNaturalBoundsRect, m_ok );
1238 wxDL_METHOD_LOAD( m_dll, GetMovieIndTrackType, m_ok );
1239 wxDL_METHOD_LOAD( m_dll, CreatePortAssociation, m_ok );
1240 wxDL_METHOD_LOAD( m_dll, DestroyPortAssociation, m_ok );
1241 wxDL_METHOD_LOAD( m_dll, GetNativeWindowPort, m_ok );
1242 wxDL_METHOD_LOAD( m_dll, SetMovieGWorld, m_ok );
1243 wxDL_METHOD_LOAD( m_dll, DisposeMovie, m_ok );
1244 wxDL_METHOD_LOAD( m_dll, SetMovieBox, m_ok );
1245 wxDL_METHOD_LOAD( m_dll, SetMovieTimeScale, m_ok );
1246 wxDL_METHOD_LOAD( m_dll, GetMovieDuration, m_ok );
1247 wxDL_METHOD_LOAD( m_dll, GetMovieTimeBase, m_ok );
1248 wxDL_METHOD_LOAD( m_dll, GetMovieTimeScale, m_ok );
1249 wxDL_METHOD_LOAD( m_dll, GetMovieTime, m_ok );
1250 wxDL_METHOD_LOAD( m_dll, SetMovieTime, m_ok );
1251 wxDL_METHOD_LOAD( m_dll, GetMovieVolume, m_ok );
1252 wxDL_METHOD_LOAD( m_dll, SetMovieVolume, m_ok );
1253 wxDL_METHOD_LOAD( m_dll, SetMovieTimeValue, m_ok );
1254 wxDL_METHOD_LOAD( m_dll, NewMovieController, m_ok );
1255 wxDL_METHOD_LOAD( m_dll, DisposeMovieController, m_ok );
1256 wxDL_METHOD_LOAD( m_dll, MCSetVisible, m_ok );
1257 wxDL_METHOD_LOAD( m_dll, PrePrerollMovie, m_ok );
1258 wxDL_METHOD_LOAD( m_dll, PrerollMovie, m_ok );
1259 wxDL_METHOD_LOAD( m_dll, GetMoviePreferredRate, m_ok );
1260 wxDL_METHOD_LOAD( m_dll, GetMovieLoadState, m_ok );
1261 wxDL_METHOD_LOAD( m_dll, MCDoAction, m_ok );
1262 wxDL_METHOD_LOAD( m_dll, MCSetControllerBoundsRect, m_ok );
1263 wxDL_METHOD_LOAD( m_dll, NativeEventToMacEvent, m_ok );
1264 wxDL_METHOD_LOAD( m_dll, MCIsPlayerEvent, m_ok );
1265 wxDL_METHOD_LOAD( m_dll, MCSetMovie, m_ok );
1266 wxDL_METHOD_LOAD( m_dll, MCSetActionFilterWithRefCon, m_ok );
1267 wxDL_METHOD_LOAD( m_dll, MCGetControllerInfo, m_ok );
1268 wxDL_METHOD_LOAD( m_dll, BeginUpdate, m_ok );
1269 wxDL_METHOD_LOAD( m_dll, UpdateMovie, m_ok );
1270 wxDL_METHOD_LOAD( m_dll, EndUpdate, m_ok );
1271 wxDL_METHOD_LOAD( m_dll, GetMoviesStickyError, m_ok );
1272
1273 wxLog::EnableLogging(bWasLoggingEnabled);
1274 m_ok = true;
1275
1276 return true;
1277 }
1278
1279 class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackendCommonBase
1280 {
1281 public:
1282 wxQTMediaBackend();
1283 ~wxQTMediaBackend();
1284
1285 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
1286 wxWindowID id,
1287 const wxPoint& pos,
1288 const wxSize& size,
1289 long style,
1290 const wxValidator& validator,
1291 const wxString& name);
1292
1293 virtual bool Play();
1294 virtual bool Pause();
1295 virtual bool Stop();
1296
1297 virtual bool Load(const wxURI& location,
1298 const wxURI& proxy)
1299 { return wxMediaBackend::Load(location, proxy); }
1300
1301 virtual bool Load(const wxString& fileName);
1302 virtual bool Load(const wxURI& location);
1303
1304 virtual wxMediaState GetState();
1305
1306 virtual bool SetPosition(wxLongLong where);
1307 virtual wxLongLong GetPosition();
1308 virtual wxLongLong GetDuration();
1309
1310 virtual void Move(int x, int y, int w, int h);
1311 wxSize GetVideoSize() const;
1312
1313 virtual double GetPlaybackRate();
1314 virtual bool SetPlaybackRate(double dRate);
1315
1316 virtual double GetVolume();
1317 virtual bool SetVolume(double);
1318
1319 void Cleanup();
1320 void FinishLoad();
1321
1322 static void PPRMProc (Movie theMovie, OSErr theErr, void* theRefCon);
1323 //TODO: Last param actually long - does this work on 64bit machines?
1324 static Boolean MCFilterProc (MovieController theController,
1325 short action, void *params, LONG_PTR refCon);
1326
1327 static LRESULT CALLBACK QTWndProc(HWND, UINT, WPARAM, LPARAM);
1328
1329 virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags);
1330
1331 wxSize m_bestSize; //Original movie size
1332 Movie m_movie; //QT Movie handle/instance
1333 bool m_bVideo; //Whether or not we have video
1334 bool m_bPlaying; //Whether or not movie is playing
1335 wxTimer* m_timer; //Load or Play timer
1336 wxQuickTimeLibrary m_lib; //DLL to load functions from
1337 ComponentInstance m_pMC; //Movie Controller
1338
1339 friend class wxQTMediaEvtHandler;
1340 DECLARE_DYNAMIC_CLASS(wxQTMediaBackend)
1341 };
1342
1343 // helper to hijack background erasing for the QT window
1344 class WXDLLIMPEXP_MEDIA wxQTMediaEvtHandler : public wxEvtHandler
1345 {
1346 public:
1347 wxQTMediaEvtHandler(wxQTMediaBackend *qtb, WXHWND hwnd)
1348 {
1349 m_qtb = qtb;
1350 m_hwnd = hwnd;
1351
1352 m_qtb->m_ctrl->Connect(m_qtb->m_ctrl->GetId(),
1353 wxEVT_ERASE_BACKGROUND,
1354 wxEraseEventHandler(wxQTMediaEvtHandler::OnEraseBackground),
1355 NULL, this
1356 );
1357 }
1358
1359 void OnEraseBackground(wxEraseEvent& event);
1360
1361 private:
1362 wxQTMediaBackend *m_qtb;
1363 WXHWND m_hwnd;
1364
1365 DECLARE_NO_COPY_CLASS(wxQTMediaEvtHandler)
1366 };
1367
1368
1369 //===========================================================================
1370 // IMPLEMENTATION
1371 //===========================================================================
1372
1373 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1374 //
1375 // wxAMMediaBackend
1376 //
1377 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1378
1379 IMPLEMENT_DYNAMIC_CLASS(wxAMMediaBackend, wxMediaBackend)
1380
1381 //---------------------------------------------------------------------------
1382 // Usual debugging macros
1383 //---------------------------------------------------------------------------
1384 #ifdef __WXDEBUG__
1385 #define MAX_ERROR_TEXT_LEN 160
1386
1387 //Get the error string for Active Movie
1388 wxString wxAMMediaBackend::GetErrorString(HRESULT hrdsv)
1389 {
1390 wxChar szError[MAX_ERROR_TEXT_LEN];
1391 if( m_lpAMGetErrorText != NULL &&
1392 (*m_lpAMGetErrorText)(hrdsv, szError, MAX_ERROR_TEXT_LEN) == 0)
1393 {
1394 return wxString::Format(wxT("DirectShow error \"%s\" \n")
1395 wxT("(numeric %X)\n")
1396 wxT("occured"),
1397 szError, (int)hrdsv);
1398 }
1399 else
1400 {
1401 return wxString::Format(wxT("Unknown error \n")
1402 wxT("(numeric %X)\n")
1403 wxT("occured"),
1404 (int)hrdsv);
1405 }
1406 }
1407
1408 #define wxAMFAIL(x) wxFAIL_MSG(GetErrorString(x));
1409 #define wxVERIFY(x) wxASSERT((x))
1410 #define wxAMLOG(x) wxLogDebug(GetErrorString(x))
1411 #else
1412 #define wxAMVERIFY(x) (x)
1413 #define wxVERIFY(x) (x)
1414 #define wxAMLOG(x)
1415 #define wxAMFAIL(x)
1416 #endif
1417
1418 //---------------------------------------------------------------------------
1419 // Standard macros for ease of use
1420 //---------------------------------------------------------------------------
1421 #define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
1422
1423 //---------------------------------------------------------------------------
1424 // wxAMLoadTimer
1425 //
1426 // Queries the control periodically to see if it has reached the point
1427 // in its loading cycle where we can begin playing the media - if so
1428 // then we finish up some things like getting the original size of the video
1429 // and then sending the loaded event to our handler
1430 //---------------------------------------------------------------------------
1431 class wxAMLoadTimer : public wxTimer
1432 {
1433 public:
1434 wxAMLoadTimer(wxAMMediaBackend* parent) :
1435 m_parent(parent) {}
1436
1437 void Notify()
1438 {
1439 if(m_parent->m_pMP)
1440 {
1441 MPReadyStateConstants nState;
1442 m_parent->m_pMP->get_ReadyState(&nState);
1443 if(nState != mpReadyStateLoading)
1444 {
1445 Stop();
1446 m_parent->FinishLoad();
1447 delete this;
1448 }
1449 }
1450 else
1451 {
1452 IActiveMovie2* pAM2 = NULL;
1453 ReadyStateConstants nState;
1454 if(m_parent->m_pAM->QueryInterface(IID_IActiveMovie2,
1455 (void**)&pAM2) == 0 &&
1456 pAM2->get_ReadyState(&nState) == 0)
1457 {
1458 pAM2->Release();
1459 if(nState != amvLoading)
1460 {
1461 Stop();
1462 m_parent->FinishLoad();
1463 delete this;
1464 }
1465 }
1466 else
1467 {
1468 if(pAM2)
1469 pAM2->Release();
1470
1471 Stop();
1472 m_parent->FinishLoad();
1473 delete this;
1474 }
1475 }
1476
1477 }
1478
1479 protected:
1480 wxAMMediaBackend* m_parent; //Backend pointer
1481 };
1482
1483 //---------------------------------------------------------------------------
1484 // wxAMPlayTimer
1485 //
1486 // Sets m_hNotifyWnd to NULL to signify that we haven't loaded anything yet
1487 // Queries the control periodically to see if it has stopped -
1488 // if it has it sends the stop event
1489 //---------------------------------------------------------------------------
1490 class wxAMPlayTimer : public wxTimer
1491 {
1492 public:
1493 wxAMPlayTimer(wxAMMediaBackend* parent) :
1494 m_parent(parent) {}
1495
1496 void Notify()
1497 {
1498 if(m_parent->GetState() == wxMEDIASTATE_STOPPED &&
1499 //NB: Stop events could get triggered by the interface
1500 //if ShowPlayerControls is enabled,
1501 //so we need this hack here to make an attempt
1502 //at it not getting sent - but its far from ideal -
1503 //they can still get sent in some cases
1504 m_parent->GetPosition() == m_parent->GetDuration())
1505 {
1506 if ( m_parent->SendStopEvent() )
1507 {
1508 //Seek to beginning of movie
1509 m_parent->wxAMMediaBackend::SetPosition(0);
1510 Stop();
1511
1512 //send the event to our child
1513 m_parent->QueueFinishEvent();
1514 }
1515 }
1516 }
1517
1518 protected:
1519 wxAMMediaBackend* m_parent; //Backend pointer
1520 };
1521
1522
1523 /*
1524 // The following is an alternative way - but it doesn't seem
1525 // to work with the IActiveMovie control - it probably processes
1526 // its own events
1527 //---------------------------------------------------------------------------
1528 // wxAMPlayTimer
1529 //
1530 // Query the IMediaEvent interface from the embedded WMP's
1531 // filtergraph, then process the events from it - sending
1532 // EC_COMPLETE events as stop events to the media control.
1533 //---------------------------------------------------------------------------
1534 class wxAMPlayTimer : public wxTimer
1535 {
1536 public:
1537 wxAMPlayTimer(wxAMMediaBackend* pBE) : m_pBE(pBE), m_pME(NULL)
1538 {
1539 HRESULT hr;
1540 IUnknown* pGB;
1541 hr = m_pBE->m_pAM->get_FilterGraph(&pGB);
1542 wxASSERT(SUCCEEDED(hr));
1543 hr = pGB->QueryInterface(IID_IMediaEvent, (void**)&m_pME);
1544 wxASSERT(SUCCEEDED(hr));
1545 pGB->Release();
1546 }
1547
1548 ~wxAMPlayTimer()
1549 {
1550 SAFE_RELEASE(m_pME);
1551 }
1552
1553 void Notify()
1554 {
1555 LONG evCode;
1556 LONG_PTR evParam1,
1557 evParam2;
1558
1559 //
1560 // DirectShow keeps a list of queued events, and we need
1561 // to go through them one by one, stopping at (Hopefully only one)
1562 // EC_COMPLETE message
1563 //
1564 while( m_pME->GetEvent(&evCode, &evParam1, &evParam2, 0) == 0 )
1565 {
1566 // Cleanup memory that GetEvent allocated
1567 HRESULT hr = m_pME->FreeEventParams(evCode,
1568 evParam1, evParam2);
1569 if(hr != 0)
1570 {
1571 //Even though this makes a messagebox this
1572 //is windows where we can do gui stuff in seperate
1573 //threads :)
1574 wxFAIL_MSG(m_pBE->GetErrorString(hr));
1575 }
1576 // If this is the end of the clip, notify handler
1577 else if(1 == evCode) //EC_COMPLETE
1578 {
1579 if ( m_pBE->SendStopEvent() )
1580 {
1581 Stop();
1582
1583 m_pBE->QueueFinishEvent();
1584 }
1585 }
1586 }
1587 }
1588
1589 protected:
1590 wxAMMediaBackend* m_pBE; //Backend pointer
1591 IMediaEvent* m_pME; //To determine when to send stop event
1592 };
1593 */
1594
1595 //---------------------------------------------------------------------------
1596 // wxAMMediaBackend Constructor
1597 //---------------------------------------------------------------------------
1598 wxAMMediaBackend::wxAMMediaBackend()
1599 :m_pAX(NULL),
1600 m_pAM(NULL),
1601 m_pMP(NULL),
1602 m_pTimer(NULL)
1603 {
1604 }
1605
1606 //---------------------------------------------------------------------------
1607 // wxAMMediaBackend Destructor
1608 //---------------------------------------------------------------------------
1609 wxAMMediaBackend::~wxAMMediaBackend()
1610 {
1611 Clear(); //Free memory from Load()
1612
1613 if(m_pAX)
1614 {
1615 {
1616 wxLogNull noLog;
1617 m_pAX->DissociateHandle();
1618 }
1619 delete m_pAX;
1620 m_pAM->Release();
1621
1622 if(m_pMP)
1623 m_pMP->Release();
1624 }
1625 }
1626
1627 //---------------------------------------------------------------------------
1628 // wxAMMediaBackend::Clear
1629 //
1630 // Free up interfaces and memory allocated by LoadXXX
1631 //---------------------------------------------------------------------------
1632 void wxAMMediaBackend::Clear()
1633 {
1634 if(m_pTimer)
1635 {
1636 delete m_pTimer;
1637 m_pTimer = NULL;
1638 }
1639 }
1640
1641 //---------------------------------------------------------------------------
1642 // wxAMMediaBackend::CreateControl
1643 //---------------------------------------------------------------------------
1644 bool wxAMMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
1645 wxWindowID id,
1646 const wxPoint& pos,
1647 const wxSize& size,
1648 long style,
1649 const wxValidator& validator,
1650 const wxString& name)
1651 {
1652 // First get the AMGetErrorText procedure in debug
1653 // mode for more meaningful messages
1654 #ifdef __WXDEBUG__
1655 if ( m_dllQuartz.Load(_T("quartz.dll"), wxDL_VERBATIM) )
1656 {
1657 m_lpAMGetErrorText = (LPAMGETERRORTEXT)
1658 m_dllQuartz.GetSymbolAorW(wxT("AMGetErrorText"));
1659 }
1660 #endif // __WXDEBUG__
1661
1662 // Now determine which (if any) media player interface is
1663 // available - IMediaPlayer or IActiveMovie
1664 if( ::CoCreateInstance(CLSID_MediaPlayer, NULL,
1665 CLSCTX_INPROC_SERVER,
1666 IID_IMediaPlayer, (void**)&m_pMP) != 0 )
1667 {
1668 if( ::CoCreateInstance(CLSID_ActiveMovie, NULL,
1669 CLSCTX_INPROC_SERVER,
1670 IID_IActiveMovie, (void**)&m_pAM) != 0 )
1671 return false;
1672 m_pAM->QueryInterface(IID_IMediaPlayer, (void**)&m_pMP);
1673 }
1674 else
1675 {
1676 m_pMP->QueryInterface(IID_IActiveMovie, (void**)&m_pAM);
1677 }
1678 //
1679 // Create window
1680 // By default wxWindow(s) is created with a border -
1681 // so we need to get rid of those
1682 //
1683 // Since we don't have a child window like most other
1684 // backends, we don't need wxCLIP_CHILDREN
1685 //
1686 if ( !ctrl->wxControl::Create(parent, id, pos, size,
1687 (style & ~wxBORDER_MASK) | wxBORDER_NONE,
1688 validator, name) )
1689 return false;
1690
1691 //
1692 // Now create the ActiveX container along with the media player
1693 // interface and query them
1694 //
1695 m_ctrl = wxStaticCast(ctrl, wxMediaCtrl);
1696 m_pAX = new wxActiveXContainer(ctrl,
1697 m_pMP ? IID_IMediaPlayer : IID_IActiveMovie,
1698 m_pAM);
1699
1700
1701 //
1702 // Here we set up wx-specific stuff for the default
1703 // settings wxMediaCtrl says it will stay to
1704 //
1705 if(m_pMP)
1706 {
1707 m_pMP->put_DisplaySize(mpFitToSize);
1708 // TODO: Unsure what actual effect this has
1709 m_pMP->put_WindowlessVideo(VARIANT_TRUE);
1710 }
1711 else
1712 m_pAM->put_MovieWindowSize(amvDoubleOriginalSize);
1713
1714 //by default true
1715 m_pAM->put_AutoStart(VARIANT_FALSE);
1716 //by default enabled
1717 wxAMMediaBackend::ShowPlayerControls(wxMEDIACTRLPLAYERCONTROLS_NONE);
1718 //by default with AM only 0.5
1719 wxAMMediaBackend::SetVolume(1.0);
1720
1721 // don't erase the background of our control window so that resizing is a
1722 // bit smoother
1723 m_ctrl->SetBackgroundStyle(wxBG_STYLE_CUSTOM);
1724
1725 // success
1726 return true;
1727 }
1728
1729 //---------------------------------------------------------------------------
1730 // wxAMMediaBackend::Load (file version)
1731 //---------------------------------------------------------------------------
1732 bool wxAMMediaBackend::Load(const wxString& fileName)
1733 {
1734 return DoLoad(fileName);
1735 }
1736
1737 //---------------------------------------------------------------------------
1738 // wxAMMediaBackend::Load (URL Version)
1739 //---------------------------------------------------------------------------
1740 bool wxAMMediaBackend::Load(const wxURI& location)
1741 {
1742 // Turn off loading from a proxy as user
1743 // may have set it previously
1744 INSPlay* pPlay = NULL;
1745 m_pAM->QueryInterface(IID_INSPlay, (void**) &pPlay);
1746 if(pPlay)
1747 {
1748 pPlay->put_UseHTTPProxy(VARIANT_FALSE);
1749 pPlay->Release();
1750 }
1751
1752 return DoLoad(location.BuildURI());
1753 }
1754
1755 //---------------------------------------------------------------------------
1756 // wxAMMediaBackend::Load (URL Version with Proxy)
1757 //---------------------------------------------------------------------------
1758 bool wxAMMediaBackend::Load(const wxURI& location, const wxURI& proxy)
1759 {
1760 // Set the proxy of the NETSHOW interface
1761 INSPlay* pPlay = NULL;
1762 m_pAM->QueryInterface(IID_INSPlay, (void**) &pPlay);
1763
1764 if(pPlay)
1765 {
1766 pPlay->put_UseHTTPProxy(VARIANT_TRUE);
1767 pPlay->put_HTTPProxyHost(wxBasicString(proxy.GetServer()).Get());
1768 pPlay->put_HTTPProxyPort(wxAtoi(proxy.GetPort()));
1769 pPlay->Release();
1770 }
1771
1772 return DoLoad(location.BuildURI());
1773 }
1774
1775 //---------------------------------------------------------------------------
1776 // wxAMMediaBackend::DoLoad
1777 //
1778 // Called by all functions - this actually renders
1779 // the file and sets up the filter graph
1780 //---------------------------------------------------------------------------
1781 bool wxAMMediaBackend::DoLoad(const wxString& location)
1782 {
1783 Clear(); //Clear up previously allocated memory
1784
1785 HRESULT hr;
1786
1787 // Play the movie the normal way through the embedded
1788 // WMP. Supposively Open is better in theory because
1789 // the docs say its async and put_FileName is not -
1790 // but in practice they both seem to be async anyway
1791 if(m_pMP)
1792 hr = m_pMP->Open( wxBasicString(location).Get() );
1793 else
1794 hr = m_pAM->put_FileName( wxBasicString(location).Get() );
1795
1796 if(FAILED(hr))
1797 {
1798 wxAMLOG(hr);
1799 return false;
1800 }
1801
1802 // In AM playing will FAIL if
1803 // the user plays before the media is loaded
1804 m_pTimer = new wxAMLoadTimer(this);
1805 m_pTimer->Start(20);
1806 return true;
1807 }
1808
1809 //---------------------------------------------------------------------------
1810 // wxAMMediaBackend::FinishLoad
1811 //
1812 // Called by our wxAMLoadTimer when the
1813 // embedded WMP tells its the media is ready to play.
1814 //
1815 // Here we get the original size of the video and
1816 // send the loaded event to our watcher :).
1817 //---------------------------------------------------------------------------
1818 void wxAMMediaBackend::FinishLoad()
1819 {
1820 //Get the original video size
1821 m_pAM->get_ImageSourceWidth((long*)&m_bestSize.x);
1822 m_pAM->get_ImageSourceHeight((long*)&m_bestSize.y);
1823
1824 //
1825 //Start the play timer to catch stop events
1826 //Previous load timer cleans up itself
1827 //
1828 m_pTimer = new wxAMPlayTimer(this);
1829
1830 NotifyMovieLoaded();
1831 }
1832
1833 //---------------------------------------------------------------------------
1834 // wxAMMediaBackend::ShowPlayerControls
1835 //---------------------------------------------------------------------------
1836 bool wxAMMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
1837 {
1838 // Note that IMediaPlayer doesn't have a statusbar by
1839 // default but IActiveMovie does - so lets try to keep
1840 // the interface consistant
1841 if(!flags)
1842 {
1843 m_pAM->put_Enabled(VARIANT_FALSE);
1844 m_pAM->put_ShowControls(VARIANT_FALSE);
1845 if(m_pMP)
1846 m_pMP->put_ShowStatusBar(VARIANT_FALSE);
1847 }
1848 else
1849 {
1850 m_pAM->put_Enabled(VARIANT_TRUE);
1851 m_pAM->put_ShowControls(VARIANT_TRUE);
1852
1853 m_pAM->put_ShowPositionControls(
1854 (flags & wxMEDIACTRLPLAYERCONTROLS_STEP) ?
1855 VARIANT_TRUE : VARIANT_FALSE);
1856
1857 if(m_pMP)
1858 {
1859 m_pMP->put_ShowStatusBar(VARIANT_TRUE);
1860 m_pMP->put_ShowAudioControls(
1861 (flags & wxMEDIACTRLPLAYERCONTROLS_VOLUME) ?
1862 VARIANT_TRUE : VARIANT_FALSE);
1863 }
1864 }
1865
1866 return true;
1867 }
1868
1869 //---------------------------------------------------------------------------
1870 // wxAMMediaBackend::Play
1871 //
1872 // Plays the stream. If it is non-seekable, it will restart it (implicit).
1873 //
1874 // Note that we use SUCCEEDED here because run/pause/stop tend to be overly
1875 // picky and return warnings on pretty much every call
1876 //---------------------------------------------------------------------------
1877 bool wxAMMediaBackend::Play()
1878 {
1879 // Actually try to play the movie, even though it may not be loaded yet.
1880 HRESULT hr = m_pAM->Run();
1881 if(SUCCEEDED(hr))
1882 {
1883 m_pTimer->Start(20);
1884 return true;
1885 }
1886 wxAMLOG(hr);
1887 return false;
1888 }
1889
1890 //---------------------------------------------------------------------------
1891 // wxAMMediaBackend::Pause
1892 //
1893 // Pauses the stream.
1894 //---------------------------------------------------------------------------
1895 bool wxAMMediaBackend::Pause()
1896 {
1897 HRESULT hr = m_pAM->Pause();
1898 if(SUCCEEDED(hr))
1899 return true;
1900 wxAMLOG(hr);
1901 return false;
1902 }
1903
1904 //---------------------------------------------------------------------------
1905 // wxAMMediaBackend::Stop
1906 //
1907 // Stops the stream.
1908 //---------------------------------------------------------------------------
1909 bool wxAMMediaBackend::Stop()
1910 {
1911 HRESULT hr = m_pAM->Stop();
1912 if(SUCCEEDED(hr))
1913 {
1914 //Seek to beginning
1915 wxAMMediaBackend::SetPosition(0);
1916 //Stop stop event timer
1917 m_pTimer->Stop();
1918 return true;
1919 }
1920 wxAMLOG(hr);
1921 return false;
1922 }
1923
1924 //---------------------------------------------------------------------------
1925 // wxAMMediaBackend::SetPosition
1926 //
1927 // 1) Translates the current position's time to directshow time,
1928 // which is in a scale of 1 second (in a double)
1929 // 2) Sets the play position of the IMediaSeeking interface -
1930 // passing NULL as the stop position means to keep the old
1931 // stop position
1932 //---------------------------------------------------------------------------
1933 bool wxAMMediaBackend::SetPosition(wxLongLong where)
1934 {
1935 HRESULT hr = m_pAM->put_CurrentPosition(
1936 ((LONGLONG)where.GetValue()) / 1000.0
1937 );
1938 if(FAILED(hr))
1939 {
1940 wxAMLOG(hr);
1941 return false;
1942 }
1943
1944 return true;
1945 }
1946
1947 //---------------------------------------------------------------------------
1948 // wxAMMediaBackend::GetPosition
1949 //
1950 // 1) Obtains the current play and stop positions from IMediaSeeking
1951 // 2) Returns the play position translated to our time base
1952 //---------------------------------------------------------------------------
1953 wxLongLong wxAMMediaBackend::GetPosition()
1954 {
1955 double outCur;
1956 HRESULT hr = m_pAM->get_CurrentPosition(&outCur);
1957 if(FAILED(hr))
1958 {
1959 wxAMLOG(hr);
1960 return 0;
1961 }
1962
1963 //h,m,s,milli - outdur is in 1 second (double)
1964 outCur *= 1000;
1965 wxLongLong ll;
1966 ll.Assign(outCur);
1967
1968 return ll;
1969 }
1970
1971 //---------------------------------------------------------------------------
1972 // wxAMMediaBackend::GetVolume
1973 //
1974 // Gets the volume through the IBasicAudio interface -
1975 // value ranges from 0 (MAX volume) to -10000 (minimum volume).
1976 // -100 per decibel.
1977 //---------------------------------------------------------------------------
1978 double wxAMMediaBackend::GetVolume()
1979 {
1980 long lVolume;
1981 HRESULT hr = m_pAM->get_Volume(&lVolume);
1982 if(FAILED(hr))
1983 {
1984 wxAMLOG(hr);
1985 return 0.0;
1986 }
1987 return pow(10.0, lVolume/2000.0);
1988 }
1989
1990 //---------------------------------------------------------------------------
1991 // wxAMMediaBackend::SetVolume
1992 //
1993 // Sets the volume through the IBasicAudio interface -
1994 // value ranges from 0 (MAX volume) to -10000 (minimum volume).
1995 // -100 per decibel.
1996 //---------------------------------------------------------------------------
1997 bool wxAMMediaBackend::SetVolume(double dVolume)
1998 {
1999 //pow(10.0, -80.0) to correct 0 == -INF
2000 long lVolume = (long)(2000.0 * log10(pow(10.0, -80.0)+dVolume));
2001 HRESULT hr = m_pAM->put_Volume( lVolume );
2002 if(FAILED(hr))
2003 {
2004 wxAMLOG(hr);
2005 return false;
2006 }
2007 return true;
2008 }
2009
2010 //---------------------------------------------------------------------------
2011 // wxAMMediaBackend::GetDuration
2012 //
2013 // 1) Obtains the duration of the media from IAMMultiMediaStream
2014 // 2) Converts that value to our time base, and returns it
2015 //
2016 // NB: With VBR MP3 files the default DirectShow MP3 render does not
2017 // read the Xing header correctly, resulting in skewed values for duration
2018 // and seeking
2019 //---------------------------------------------------------------------------
2020 wxLongLong wxAMMediaBackend::GetDuration()
2021 {
2022 double outDuration;
2023 HRESULT hr = m_pAM->get_Duration(&outDuration);
2024 if(FAILED(hr))
2025 {
2026 wxAMLOG(hr);
2027 return 0;
2028 }
2029
2030 //h,m,s,milli - outdur is in 1 second (double)
2031 outDuration *= 1000;
2032 wxLongLong ll;
2033 ll.Assign(outDuration);
2034
2035 return ll;
2036 }
2037
2038 //---------------------------------------------------------------------------
2039 // wxAMMediaBackend::GetState
2040 //
2041 // Returns the cached state
2042 //---------------------------------------------------------------------------
2043 wxMediaState wxAMMediaBackend::GetState()
2044 {
2045 StateConstants nState;
2046 HRESULT hr = m_pAM->get_CurrentState(&nState);
2047 if(FAILED(hr))
2048 {
2049 wxAMLOG(hr);
2050 return wxMEDIASTATE_STOPPED;
2051 }
2052
2053 return (wxMediaState)nState;
2054 }
2055
2056 //---------------------------------------------------------------------------
2057 // wxAMMediaBackend::GetPlaybackRate
2058 //
2059 // Pretty simple way of obtaining the playback rate from
2060 // the IMediaSeeking interface
2061 //---------------------------------------------------------------------------
2062 double wxAMMediaBackend::GetPlaybackRate()
2063 {
2064 double dRate;
2065 HRESULT hr = m_pAM->get_Rate(&dRate);
2066 if(FAILED(hr))
2067 {
2068 wxAMLOG(hr);
2069 return 0.0;
2070 }
2071 return dRate;
2072 }
2073
2074 //---------------------------------------------------------------------------
2075 // wxAMMediaBackend::SetPlaybackRate
2076 //
2077 // Sets the playback rate of the media - DirectShow is pretty good
2078 // about this, actually
2079 //---------------------------------------------------------------------------
2080 bool wxAMMediaBackend::SetPlaybackRate(double dRate)
2081 {
2082 HRESULT hr = m_pAM->put_Rate(dRate);
2083 if(FAILED(hr))
2084 {
2085 wxAMLOG(hr);
2086 return false;
2087 }
2088
2089 return true;
2090 }
2091
2092 //---------------------------------------------------------------------------
2093 // wxAMMediaBackend::GetDownloadXXX
2094 //
2095 // Queries for and gets the total size of the file and the current
2096 // progress in downloading that file from the IAMOpenProgress
2097 // interface from the media player interface's filter graph
2098 //---------------------------------------------------------------------------
2099 void wxAMMediaBackend::DoGetDownloadProgress(wxLongLong* pLoadProgress,
2100 wxLongLong* pLoadTotal)
2101 {
2102 LONGLONG loadTotal = 0, loadProgress = 0;
2103 IUnknown* pFG;
2104 IAMOpenProgress* pOP;
2105 HRESULT hr;
2106 hr = m_pAM->get_FilterGraph(&pFG);
2107 if(SUCCEEDED(hr))
2108 {
2109 hr = pFG->QueryInterface(IID_IAMOpenProgress, (void**)&pOP);
2110 if(SUCCEEDED(hr))
2111 {
2112 hr = pOP->QueryProgress(&loadTotal, &loadProgress);
2113 pOP->Release();
2114 }
2115 pFG->Release();
2116 }
2117
2118 if(SUCCEEDED(hr))
2119 {
2120 *pLoadProgress = loadProgress;
2121 *pLoadTotal = loadTotal;
2122 }
2123 else
2124 {
2125 //When not loading from a URL QueryProgress will return
2126 //E_NOINTERFACE or whatever
2127 //wxAMFAIL(hr);
2128 *pLoadProgress = 0;
2129 *pLoadTotal = 0;
2130 }
2131 }
2132
2133 //---------------------------------------------------------------------------
2134 // wxAMMediaBackend::GetVideoSize
2135 //
2136 // Obtains the cached original video size
2137 //---------------------------------------------------------------------------
2138 wxSize wxAMMediaBackend::GetVideoSize() const
2139 {
2140 return m_bestSize;
2141 }
2142
2143 //---------------------------------------------------------------------------
2144 // wxAMMediaBackend::Move
2145 //
2146 // We take care of this in our redrawing
2147 //---------------------------------------------------------------------------
2148 void wxAMMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y),
2149 int WXUNUSED(w), int WXUNUSED(h))
2150 {
2151 }
2152
2153 //---------------------------------------------------------------------------
2154 // End of wxAMMediaBackend
2155 //---------------------------------------------------------------------------
2156
2157 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2158 //
2159 // wxMCIMediaBackend
2160 //
2161 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2162
2163 IMPLEMENT_DYNAMIC_CLASS(wxMCIMediaBackend, wxMediaBackend)
2164
2165 //---------------------------------------------------------------------------
2166 // Usual debugging macros for MCI returns
2167 //---------------------------------------------------------------------------
2168
2169 #ifdef __WXDEBUG__
2170 #define wxMCIVERIFY(arg) \
2171 { \
2172 DWORD nRet; \
2173 if ( (nRet = (arg)) != 0) \
2174 { \
2175 TCHAR sz[5000]; \
2176 mciGetErrorString(nRet, sz, 5000); \
2177 wxFAIL_MSG(wxString::Format(_T("MCI Error:%s"), sz)); \
2178 } \
2179 }
2180 #else
2181 #define wxMCIVERIFY(arg) (arg);
2182 #endif
2183
2184 //---------------------------------------------------------------------------
2185 // Simulation for <digitalv.h>
2186 //
2187 // Mingw and possibly other compilers don't have the digitalv.h header
2188 // that is needed to have some essential features of mci work with
2189 // windows - so we provide the declarations for the types we use here
2190 //---------------------------------------------------------------------------
2191
2192 typedef struct {
2193 DWORD_PTR dwCallback;
2194 #ifdef MCI_USE_OFFEXT
2195 POINT ptOffset;
2196 POINT ptExtent;
2197 #else
2198 RECT rc;
2199 #endif
2200 } MCI_DGV_RECT_PARMS;
2201
2202 typedef struct {
2203 DWORD_PTR dwCallback;
2204 HWND hWnd;
2205 #ifndef _WIN32
2206 WORD wReserved1;
2207 #endif
2208 UINT nCmdShow;
2209 #ifndef _WIN32
2210 WORD wReserved2;
2211 #endif
2212 wxChar* lpstrText;
2213 } MCI_DGV_WINDOW_PARMS;
2214
2215 typedef struct {
2216 DWORD_PTR dwCallback;
2217 DWORD dwTimeFormat;
2218 DWORD dwAudio;
2219 DWORD dwFileFormat;
2220 DWORD dwSpeed;
2221 } MCI_DGV_SET_PARMS;
2222
2223 typedef struct {
2224 DWORD_PTR dwCallback;
2225 DWORD dwItem;
2226 DWORD dwValue;
2227 DWORD dwOver;
2228 wxChar* lpstrAlgorithm;
2229 wxChar* lpstrQuality;
2230 } MCI_DGV_SETAUDIO_PARMS;
2231
2232 //---------------------------------------------------------------------------
2233 // wxMCIMediaBackend Constructor
2234 //
2235 // Here we don't need to do much except say we don't have any video :)
2236 //---------------------------------------------------------------------------
2237 wxMCIMediaBackend::wxMCIMediaBackend() : m_hNotifyWnd(NULL), m_bVideo(false)
2238 {
2239 }
2240
2241 //---------------------------------------------------------------------------
2242 // wxMCIMediaBackend Destructor
2243 //
2244 // We close the mci device - note that there may not be an mci device here,
2245 // or it may fail - but we don't really care, since we're destructing
2246 //---------------------------------------------------------------------------
2247 wxMCIMediaBackend::~wxMCIMediaBackend()
2248 {
2249 if(m_hNotifyWnd)
2250 {
2251 mciSendCommand(m_hDev, MCI_CLOSE, 0, 0);
2252 DestroyWindow(m_hNotifyWnd);
2253 m_hNotifyWnd = NULL;
2254 }
2255 }
2256
2257 //---------------------------------------------------------------------------
2258 // wxMCIMediaBackend::Create
2259 //
2260 // Here we just tell wxMediaCtrl that mci does exist (which it does, on all
2261 // msw systems, at least in some form dating back to win16 days)
2262 //---------------------------------------------------------------------------
2263 bool wxMCIMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
2264 wxWindowID id,
2265 const wxPoint& pos,
2266 const wxSize& size,
2267 long style,
2268 const wxValidator& validator,
2269 const wxString& name)
2270 {
2271 //
2272 // Create window
2273 // By default wxWindow(s) is created with a border -
2274 // so we need to get rid of those, and create with
2275 // wxCLIP_CHILDREN, so that if the driver/backend
2276 // is a child window, it refereshes properly
2277 //
2278 if ( !ctrl->wxControl::Create(parent, id, pos, size,
2279 (style & ~wxBORDER_MASK) | wxBORDER_NONE | wxCLIP_CHILDREN,
2280 validator, name) )
2281 return false;
2282
2283 m_ctrl = wxStaticCast(ctrl, wxMediaCtrl);
2284 return true;
2285 }
2286
2287 //---------------------------------------------------------------------------
2288 // wxMCIMediaBackend::Load (file version)
2289 //
2290 // Here we have MCI load a file and device, set the time format to our
2291 // default (milliseconds), and set the video (if any) to play in the control
2292 //---------------------------------------------------------------------------
2293 bool wxMCIMediaBackend::Load(const wxString& fileName)
2294 {
2295 //
2296 //if the user already called load close the previous MCI device
2297 //
2298 if(m_hNotifyWnd)
2299 {
2300 mciSendCommand(m_hDev, MCI_CLOSE, 0, 0);
2301 DestroyWindow(m_hNotifyWnd);
2302 m_hNotifyWnd = NULL;
2303 }
2304
2305 //
2306 //Opens a file and has MCI select a device. Normally you'd put
2307 //MCI_OPEN_TYPE in addition to MCI_OPEN_ELEMENT - however if you
2308 //omit this it tells MCI to select the device instead. This is
2309 //good because we have no reliable way of "enumerating" the devices
2310 //in MCI
2311 //
2312 MCI_OPEN_PARMS openParms;
2313 openParms.lpstrElementName = (wxChar*) fileName.c_str();
2314
2315 if ( mciSendCommand(0, MCI_OPEN, MCI_OPEN_ELEMENT,
2316 (DWORD)(LPVOID)&openParms) != 0)
2317 return false;
2318
2319 m_hDev = openParms.wDeviceID;
2320
2321 //
2322 //Now set the time format for the device to milliseconds
2323 //
2324 MCI_SET_PARMS setParms;
2325 setParms.dwCallback = 0;
2326 setParms.dwTimeFormat = MCI_FORMAT_MILLISECONDS;
2327
2328 if (mciSendCommand(m_hDev, MCI_SET, MCI_SET_TIME_FORMAT,
2329 (DWORD)(LPVOID)&setParms) != 0)
2330 return false;
2331
2332 //
2333 //Now tell the MCI device to display the video in our wxMediaCtrl
2334 //
2335 MCI_DGV_WINDOW_PARMS windowParms;
2336 windowParms.hWnd = (HWND)m_ctrl->GetHandle();
2337
2338 m_bVideo = (mciSendCommand(m_hDev, MCI_WINDOW,
2339 0x00010000L, //MCI_DGV_WINDOW_HWND
2340 (DWORD)(LPVOID)&windowParms) == 0);
2341
2342 //
2343 // Create a hidden window and register to handle
2344 // MCI events
2345 // Note that wxCanvasClassName is already registered
2346 // and used by all wxWindows and normal wxControls
2347 //
2348 m_hNotifyWnd = ::CreateWindow
2349 (
2350 wxCanvasClassName,
2351 NULL,
2352 0, 0, 0, 0,
2353 0,
2354 (HWND) NULL,
2355 (HMENU)NULL,
2356 wxGetInstance(),
2357 (LPVOID) NULL
2358 );
2359
2360 if(!m_hNotifyWnd)
2361 {
2362 wxLogSysError( wxT("Could not create hidden needed for ")
2363 wxT("registering for MCI events!") );
2364
2365 return false;
2366 }
2367
2368 wxSetWindowProc(m_hNotifyWnd, wxMCIMediaBackend::NotifyWndProc);
2369 wxSetWindowUserData(m_hNotifyWnd, this);
2370
2371 NotifyMovieLoaded();
2372
2373 return true;
2374 }
2375
2376 //---------------------------------------------------------------------------
2377 // wxMCIMediaBackend::Load (URL version)
2378 //
2379 // MCI doesn't support URLs directly (?)
2380 //
2381 // TODO: Use wxURL/wxFileSystem and mmioInstallProc
2382 //---------------------------------------------------------------------------
2383 bool wxMCIMediaBackend::Load(const wxURI& WXUNUSED(location))
2384 {
2385 return false;
2386 }
2387
2388 //---------------------------------------------------------------------------
2389 // wxMCIMediaBackend::Play
2390 //
2391 // Plays/Resumes the MCI device... a couple notes:
2392 // 1) Certain drivers will crash and burn if we don't pass them an
2393 // MCI_PLAY_PARMS, despite the documentation that says otherwise...
2394 // 2) There is a MCI_RESUME command, but MCI_PLAY does the same thing
2395 // and will resume from a stopped state also, so there's no need to
2396 // call both, for example
2397 //---------------------------------------------------------------------------
2398 bool wxMCIMediaBackend::Play()
2399 {
2400 MCI_PLAY_PARMS playParms;
2401 playParms.dwCallback = (DWORD)m_hNotifyWnd;
2402
2403 bool bOK = ( mciSendCommand(m_hDev, MCI_PLAY, MCI_NOTIFY,
2404 (DWORD)(LPVOID)&playParms) == 0 );
2405
2406 if(bOK)
2407 m_ctrl->Show(m_bVideo);
2408
2409 return bOK;
2410 }
2411
2412 //---------------------------------------------------------------------------
2413 // wxMCIMediaBackend::Pause
2414 //
2415 // Pauses the MCI device - nothing special
2416 //---------------------------------------------------------------------------
2417 bool wxMCIMediaBackend::Pause()
2418 {
2419 return (mciSendCommand(m_hDev, MCI_PAUSE, MCI_WAIT, 0) == 0);
2420 }
2421
2422 //---------------------------------------------------------------------------
2423 // wxMCIMediaBackend::Stop
2424 //
2425 // Stops the MCI device & seeks to the beginning as wxMediaCtrl docs outline
2426 //---------------------------------------------------------------------------
2427 bool wxMCIMediaBackend::Stop()
2428 {
2429 return (mciSendCommand(m_hDev, MCI_STOP, MCI_WAIT, 0) == 0) &&
2430 (mciSendCommand(m_hDev, MCI_SEEK, MCI_SEEK_TO_START, 0) == 0);
2431 }
2432
2433 //---------------------------------------------------------------------------
2434 // wxMCIMediaBackend::GetState
2435 //
2436 // Here we get the state and convert it to a wxMediaState -
2437 // since we use direct comparisons with MCI_MODE_PLAY and
2438 // MCI_MODE_PAUSE, we don't care if the MCI_STATUS call
2439 // fails or not
2440 //---------------------------------------------------------------------------
2441 wxMediaState wxMCIMediaBackend::GetState()
2442 {
2443 MCI_STATUS_PARMS statusParms;
2444 statusParms.dwItem = MCI_STATUS_MODE;
2445
2446 mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
2447 (DWORD)(LPVOID)&statusParms);
2448
2449 if(statusParms.dwReturn == MCI_MODE_PAUSE)
2450 return wxMEDIASTATE_PAUSED;
2451 else if(statusParms.dwReturn == MCI_MODE_PLAY)
2452 return wxMEDIASTATE_PLAYING;
2453 else
2454 return wxMEDIASTATE_STOPPED;
2455 }
2456
2457 //---------------------------------------------------------------------------
2458 // wxMCIMediaBackend::SetPosition
2459 //
2460 // Here we set the position of the device in the stream.
2461 // Note that MCI actually stops the device after you seek it if the
2462 // device is playing/paused, so we need to play the file after
2463 // MCI seeks like normal APIs would
2464 //---------------------------------------------------------------------------
2465 bool wxMCIMediaBackend::SetPosition(wxLongLong where)
2466 {
2467 MCI_SEEK_PARMS seekParms;
2468 seekParms.dwCallback = 0;
2469 #if wxUSE_LONGLONG_NATIVE && !wxUSE_LONGLONG_WX
2470 seekParms.dwTo = (DWORD)where.GetValue();
2471 #else /* wxUSE_LONGLONG_WX */
2472 /* no way to return it in one piece */
2473 wxASSERT( where.GetHi()==0 );
2474 seekParms.dwTo = (DWORD)where.GetLo();
2475 #endif /* wxUSE_LONGLONG_* */
2476
2477 //device was playing?
2478 bool bReplay = GetState() == wxMEDIASTATE_PLAYING;
2479
2480 if( mciSendCommand(m_hDev, MCI_SEEK, MCI_TO,
2481 (DWORD)(LPVOID)&seekParms) != 0)
2482 return false;
2483
2484 //If the device was playing, resume it
2485 if (bReplay)
2486 return Play();
2487 else
2488 return true;
2489 }
2490
2491 //---------------------------------------------------------------------------
2492 // wxMCIMediaBackend::GetPosition
2493 //
2494 // Gets the position of the device in the stream using the current
2495 // time format... nothing special here...
2496 //---------------------------------------------------------------------------
2497 wxLongLong wxMCIMediaBackend::GetPosition()
2498 {
2499 MCI_STATUS_PARMS statusParms;
2500 statusParms.dwItem = MCI_STATUS_POSITION;
2501
2502 if (mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
2503 (DWORD)(LPSTR)&statusParms) != 0)
2504 return 0;
2505
2506 return statusParms.dwReturn;
2507 }
2508
2509 //---------------------------------------------------------------------------
2510 // wxMCIMediaBackend::GetVolume
2511 //
2512 // Gets the volume of the current media via the MCI_DGV_STATUS_VOLUME
2513 // message. Value ranges from 0 (minimum) to 1000 (maximum volume).
2514 //---------------------------------------------------------------------------
2515 double wxMCIMediaBackend::GetVolume()
2516 {
2517 MCI_STATUS_PARMS statusParms;
2518 statusParms.dwCallback = 0;
2519 statusParms.dwItem = 0x4019; //MCI_DGV_STATUS_VOLUME
2520
2521 if (mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
2522 (DWORD)(LPSTR)&statusParms) != 0)
2523 return 0;
2524
2525 return ((double)statusParms.dwReturn) / 1000.0;
2526 }
2527
2528 //---------------------------------------------------------------------------
2529 // wxMCIMediaBackend::SetVolume
2530 //
2531 // Sets the volume of the current media via the MCI_DGV_SETAUDIO_VOLUME
2532 // message. Value ranges from 0 (minimum) to 1000 (maximum volume).
2533 //---------------------------------------------------------------------------
2534 bool wxMCIMediaBackend::SetVolume(double dVolume)
2535 {
2536 MCI_DGV_SETAUDIO_PARMS audioParms;
2537 audioParms.dwCallback = 0;
2538 audioParms.dwItem = 0x4002; //MCI_DGV_SETAUDIO_VOLUME
2539 audioParms.dwValue = (DWORD) (dVolume * 1000.0);
2540 audioParms.dwOver = 0;
2541 audioParms.lpstrAlgorithm = NULL;
2542 audioParms.lpstrQuality = NULL;
2543
2544 if (mciSendCommand(m_hDev, 0x0873, //MCI_SETAUDIO
2545 //MCI_DGV_SETAUDIO+(_ITEM | _VALUE)
2546 0x00800000L | 0x01000000L,
2547 (DWORD)(LPSTR)&audioParms) != 0)
2548 return false;
2549 return true;
2550 }
2551
2552 //---------------------------------------------------------------------------
2553 // wxMCIMediaBackend::GetDuration
2554 //
2555 // Gets the duration of the stream... nothing special
2556 //---------------------------------------------------------------------------
2557 wxLongLong wxMCIMediaBackend::GetDuration()
2558 {
2559 MCI_STATUS_PARMS statusParms;
2560 statusParms.dwItem = MCI_STATUS_LENGTH;
2561
2562 if (mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
2563 (DWORD)(LPSTR)&statusParms) != 0)
2564 return 0;
2565
2566 return statusParms.dwReturn;
2567 }
2568
2569 //---------------------------------------------------------------------------
2570 // wxMCIMediaBackend::Move
2571 //
2572 // Moves the window to a location
2573 //---------------------------------------------------------------------------
2574 void wxMCIMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y),
2575 int w, int h)
2576 {
2577 if (m_hNotifyWnd && m_bVideo)
2578 {
2579 MCI_DGV_RECT_PARMS putParms; //ifdefed MCI_DGV_PUT_PARMS
2580 memset(&putParms, 0, sizeof(MCI_DGV_RECT_PARMS));
2581 putParms.rc.bottom = h;
2582 putParms.rc.right = w;
2583
2584 //wxStackWalker will crash and burn here on assert
2585 //and mci doesn't like 0 and 0 for some reason (out of range )
2586 //so just don't it in that case
2587 if(w || h)
2588 {
2589 wxMCIVERIFY( mciSendCommand(m_hDev, MCI_PUT,
2590 0x00040000L, //MCI_DGV_PUT_DESTINATION
2591 (DWORD)(LPSTR)&putParms) );
2592 }
2593 }
2594 }
2595
2596 //---------------------------------------------------------------------------
2597 // wxMCIMediaBackend::GetVideoSize
2598 //
2599 // Gets the original size of the movie for sizers
2600 //---------------------------------------------------------------------------
2601 wxSize wxMCIMediaBackend::GetVideoSize() const
2602 {
2603 if(m_bVideo)
2604 {
2605 MCI_DGV_RECT_PARMS whereParms; //ifdefed MCI_DGV_WHERE_PARMS
2606
2607 wxMCIVERIFY( mciSendCommand(m_hDev, MCI_WHERE,
2608 0x00020000L, //MCI_DGV_WHERE_SOURCE
2609 (DWORD)(LPSTR)&whereParms) );
2610
2611 return wxSize(whereParms.rc.right, whereParms.rc.bottom);
2612 }
2613 return wxSize(0,0);
2614 }
2615
2616 //---------------------------------------------------------------------------
2617 // wxMCIMediaBackend::GetPlaybackRate
2618 //
2619 // TODO
2620 //---------------------------------------------------------------------------
2621 double wxMCIMediaBackend::GetPlaybackRate()
2622 {
2623 return 1.0;
2624 }
2625
2626 //---------------------------------------------------------------------------
2627 // wxMCIMediaBackend::SetPlaybackRate
2628 //
2629 // TODO
2630 //---------------------------------------------------------------------------
2631 bool wxMCIMediaBackend::SetPlaybackRate(double WXUNUSED(dRate))
2632 {
2633 /*
2634 MCI_WAVE_SET_SAMPLESPERSEC
2635 MCI_DGV_SET_PARMS setParms;
2636 setParms.dwSpeed = (DWORD) (dRate * 1000.0);
2637
2638 return (mciSendCommand(m_hDev, MCI_SET,
2639 0x00020000L, //MCI_DGV_SET_SPEED
2640 (DWORD)(LPSTR)&setParms) == 0);
2641 */
2642 return false;
2643 }
2644
2645 //---------------------------------------------------------------------------
2646 // [static] wxMCIMediaBackend::MSWWindowProc
2647 //
2648 // Here we process a message when MCI reaches the stopping point
2649 // in the stream
2650 //---------------------------------------------------------------------------
2651 LRESULT CALLBACK wxMCIMediaBackend::NotifyWndProc(HWND hWnd, UINT nMsg,
2652 WPARAM wParam,
2653 LPARAM lParam)
2654 {
2655 wxMCIMediaBackend* backend =
2656 (wxMCIMediaBackend*)wxGetWindowUserData(hWnd);
2657
2658 return backend->OnNotifyWndProc(hWnd, nMsg, wParam, lParam);
2659 }
2660
2661 LRESULT CALLBACK wxMCIMediaBackend::OnNotifyWndProc(HWND hWnd, UINT nMsg,
2662 WPARAM wParam,
2663 LPARAM lParam)
2664 {
2665 if(nMsg == MM_MCINOTIFY)
2666 {
2667 wxASSERT(lParam == (LPARAM) m_hDev);
2668 if(wParam == MCI_NOTIFY_SUCCESSFUL && lParam == (LPARAM)m_hDev)
2669 {
2670 if ( SendStopEvent() )
2671 {
2672 wxMCIVERIFY( mciSendCommand(m_hDev, MCI_SEEK,
2673 MCI_SEEK_TO_START, 0) );
2674
2675 QueueFinishEvent();
2676 }
2677 }
2678 }
2679 return DefWindowProc(hWnd, nMsg, wParam, lParam);
2680 }
2681
2682 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2683 //
2684 // wxQTMediaBackend
2685 //
2686 // TODO: Use a less cludgy way to pause/get state/set state
2687 // FIXME: Greg Hazel reports that sometimes files that cannot be played
2688 // with this backend are treated as playable anyway - not verifyed though.
2689 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2690
2691 IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend)
2692
2693 //Time between timer calls - this is the Apple recommondation to the TCL
2694 //team I believe
2695 #define MOVIE_DELAY 20
2696
2697 #include "wx/timer.h"
2698
2699
2700 //---------------------------------------------------------------------------
2701 // wxQTLoadTimer
2702 //
2703 // QT, esp. QT for Windows is very picky about how you go about
2704 // async loading. If you were to go through a Windows message loop
2705 // or a MoviesTask or both and then check the movie load state
2706 // it would still return 1000 (loading)... even (pre)prerolling doesn't
2707 // help. However, making a load timer like this works
2708 //---------------------------------------------------------------------------
2709 class wxQTLoadTimer : public wxTimer
2710 {
2711 public:
2712 wxQTLoadTimer(Movie movie, wxQTMediaBackend* parent, wxQuickTimeLibrary* pLib) :
2713 m_movie(movie), m_parent(parent), m_pLib(pLib) {}
2714
2715 void Notify()
2716 {
2717 m_pLib->MoviesTask(m_movie, 0);
2718 //kMovieLoadStatePlayable
2719 if(m_pLib->GetMovieLoadState(m_movie) >= 10000)
2720 {
2721 m_parent->FinishLoad();
2722 delete this;
2723 }
2724 }
2725
2726 protected:
2727 Movie m_movie; //Our movie instance
2728 wxQTMediaBackend* m_parent; //Backend pointer
2729 wxQuickTimeLibrary* m_pLib; //Interfaces
2730 };
2731
2732
2733 // --------------------------------------------------------------------------
2734 // wxQTPlayTimer - Handle Asyncronous Playing
2735 //
2736 // 1) Checks to see if the movie is done, and if not continues
2737 // streaming the movie
2738 // 2) Sends the wxEVT_MEDIA_STOP event if we have reached the end of
2739 // the movie.
2740 // --------------------------------------------------------------------------
2741 class wxQTPlayTimer : public wxTimer
2742 {
2743 public:
2744 wxQTPlayTimer(Movie movie, wxQTMediaBackend* parent,
2745 wxQuickTimeLibrary* pLib) :
2746 m_movie(movie), m_parent(parent), m_pLib(pLib) {}
2747
2748 void Notify()
2749 {
2750 //
2751 // OK, a little explaining - basically originally
2752 // we only called MoviesTask if the movie was actually
2753 // playing (not paused or stopped)... this was before
2754 // we realized MoviesTask actually handles repainting
2755 // of the current frame - so if you were to resize
2756 // or something it would previously not redraw that
2757 // portion of the movie.
2758 //
2759 // So now we call MoviesTask always so that it repaints
2760 // correctly.
2761 //
2762 m_pLib->MoviesTask(m_movie, 0);
2763
2764 //
2765 // Handle the stop event - if the movie has reached
2766 // the end, notify our handler
2767 //
2768 // m_bPlaying == !(Stopped | Paused)
2769 //
2770 if (m_parent->m_bPlaying)
2771 {
2772 if(m_pLib->IsMovieDone(m_movie))
2773 {
2774 if ( m_parent->SendStopEvent() )
2775 {
2776 m_parent->Stop();
2777 wxASSERT(m_pLib->GetMoviesError() == noErr);
2778
2779 m_parent->QueueFinishEvent();
2780 }
2781 }
2782 }
2783 }
2784
2785 protected:
2786 Movie m_movie; //Our movie instance
2787 wxQTMediaBackend* m_parent; //Backend pointer
2788 wxQuickTimeLibrary* m_pLib; //Interfaces
2789 };
2790
2791
2792 //---------------------------------------------------------------------------
2793 // wxQTMediaBackend::QTWndProc
2794 //
2795 // Forwards events to the Movie Controller so that it can
2796 // redraw itself/process messages etc..
2797 //---------------------------------------------------------------------------
2798 LRESULT CALLBACK wxQTMediaBackend::QTWndProc(HWND hWnd, UINT nMsg,
2799 WPARAM wParam, LPARAM lParam)
2800 {
2801 wxQTMediaBackend* pThis = (wxQTMediaBackend*)wxGetWindowUserData(hWnd);
2802
2803 MSG msg;
2804 msg.hwnd = hWnd;
2805 msg.message = nMsg;
2806 msg.wParam = wParam;
2807 msg.lParam = lParam;
2808 msg.time = 0;
2809 msg.pt.x = 0;
2810 msg.pt.y = 0;
2811 EventRecord theEvent;
2812 pThis->m_lib.NativeEventToMacEvent(&msg, &theEvent);
2813 pThis->m_lib.MCIsPlayerEvent(pThis->m_pMC, &theEvent);
2814 return pThis->m_ctrl->MSWWindowProc(nMsg, wParam, lParam);
2815 }
2816
2817 //---------------------------------------------------------------------------
2818 // wxQTMediaBackend Destructor
2819 //
2820 // Sets m_timer to NULL signifying we havn't loaded anything yet
2821 //---------------------------------------------------------------------------
2822 wxQTMediaBackend::wxQTMediaBackend()
2823 : m_movie(NULL), m_bPlaying(false), m_timer(NULL), m_pMC(NULL)
2824 {
2825 }
2826
2827 //---------------------------------------------------------------------------
2828 // wxQTMediaBackend Destructor
2829 //
2830 // 1) Cleans up the QuickTime movie instance
2831 // 2) Decrements the QuickTime reference counter - if this reaches
2832 // 0, QuickTime shuts down
2833 // 3) Decrements the QuickTime Windows Media Layer reference counter -
2834 // if this reaches 0, QuickTime shuts down the Windows Media Layer
2835 //---------------------------------------------------------------------------
2836 wxQTMediaBackend::~wxQTMediaBackend()
2837 {
2838 if(m_movie)
2839 Cleanup();
2840
2841 if(m_lib.IsOk())
2842 {
2843 if(m_pMC)
2844 {
2845 m_lib.DisposeMovieController(m_pMC);
2846 // m_pMC = NULL;
2847 }
2848
2849 // destroy wxQTMediaEvtHandler we pushed on it
2850 m_ctrl->PopEventHandler(true);
2851
2852 m_lib.DestroyPortAssociation(
2853 (CGrafPtr)m_lib.GetNativeWindowPort(m_ctrl->GetHWND()));
2854
2855 //Note that ExitMovies() is not necessary, but
2856 //the docs are fuzzy on whether or not TerminateQTML is
2857 m_lib.ExitMovies();
2858 m_lib.TerminateQTML();
2859 }
2860 }
2861
2862 //---------------------------------------------------------------------------
2863 // wxQTMediaBackend::CreateControl
2864 //
2865 // 1) Intializes QuickTime
2866 // 2) Creates the control window
2867 //---------------------------------------------------------------------------
2868 bool wxQTMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
2869 wxWindowID id,
2870 const wxPoint& pos,
2871 const wxSize& size,
2872 long style,
2873 const wxValidator& validator,
2874 const wxString& name)
2875 {
2876 if(!m_lib.Initialize())
2877 return false;
2878
2879 int nError = m_lib.InitializeQTML(0);
2880 if (nError != noErr) //-2093 no dll
2881 {
2882 wxFAIL_MSG(wxString::Format(wxT("Couldn't Initialize Quicktime-%i"),
2883 nError));
2884 return false;
2885 }
2886 m_lib.EnterMovies();
2887
2888 //
2889 // Create window
2890 // By default wxWindow(s) is created with a border -
2891 // so we need to get rid of those
2892 //
2893 // Since we don't have a child window like most other
2894 // backends, we don't need wxCLIP_CHILDREN
2895 //
2896 if ( !ctrl->wxControl::Create(parent, id, pos, size,
2897 (style & ~wxBORDER_MASK) | wxBORDER_NONE,
2898 validator, name) )
2899 return false;
2900
2901
2902 m_ctrl = wxStaticCast(ctrl, wxMediaCtrl);
2903
2904 // Create a port association for our window so we
2905 // can use it as a WindowRef
2906 m_lib.CreatePortAssociation(m_ctrl->GetHWND(), NULL, 0L);
2907
2908 //Part of a suggestion from Greg Hazel to repaint
2909 //movie when idle
2910 m_ctrl->PushEventHandler(new wxQTMediaEvtHandler(this, m_ctrl->GetHWND()));
2911
2912 // done
2913 return true;
2914 }
2915
2916 //---------------------------------------------------------------------------
2917 // wxQTMediaBackend::Load (file version)
2918 //
2919 // 1) Get an FSSpec from the Windows path name
2920 // 2) Open the movie
2921 // 3) Obtain the movie instance from the movie resource
2922 // 4) Close the movie resource
2923 // 5) Finish loading
2924 //---------------------------------------------------------------------------
2925 bool wxQTMediaBackend::Load(const wxString& fileName)
2926 {
2927 if(m_movie)
2928 Cleanup();
2929
2930 short movieResFile = 0; //= 0 because of annoying VC6 warning
2931 FSSpec sfFile;
2932
2933 if (m_lib.NativePathNameToFSSpec ((char*) (const char*) fileName.mb_str(),
2934 &sfFile, 0) != noErr)
2935 return false;
2936
2937 if (m_lib.OpenMovieFile (&sfFile, &movieResFile, fsRdPerm) != noErr)
2938 return false;
2939
2940 short movieResID = 0;
2941 Str255 movieName;
2942
2943 OSErr err = m_lib.NewMovieFromFile (
2944 &m_movie,
2945 movieResFile,
2946 &movieResID,
2947 movieName,
2948 newMovieActive,
2949 NULL
2950 ); //wasChanged
2951
2952 //m_lib.GetMoviesStickyError() because it may not find the
2953 //proper codec and play black video and other strange effects,
2954 //not to mention mess up the dynamic backend loading scheme
2955 //of wxMediaCtrl - so it just does what the QuickTime player does
2956 if(err == noErr && m_lib.GetMoviesStickyError() == noErr)
2957 {
2958 m_lib.CloseMovieFile (movieResFile);
2959
2960 FinishLoad();
2961 return true;
2962 }
2963 else
2964 return false;
2965 }
2966
2967
2968 //---------------------------------------------------------------------------
2969 // wxQTMediaBackend::PPRMProc (static)
2970 //
2971 // Called when done PrePrerolling the movie.
2972 // Note that in 99% of the cases this does nothing...
2973 // Anyway we set up the loading timer here to tell us when the movie is done
2974 //---------------------------------------------------------------------------
2975 void wxQTMediaBackend::PPRMProc (Movie theMovie,
2976 OSErr WXUNUSED_UNLESS_DEBUG(theErr),
2977 void* theRefCon)
2978 {
2979 wxASSERT( theMovie );
2980 wxASSERT( theRefCon );
2981 wxASSERT( theErr == noErr );
2982
2983 wxQTMediaBackend* pBE = (wxQTMediaBackend*) theRefCon;
2984
2985 long lTime = pBE->m_lib.GetMovieTime(theMovie,NULL);
2986 Fixed rate = pBE->m_lib.GetMoviePreferredRate(theMovie);
2987 pBE->m_lib.PrerollMovie(theMovie,lTime,rate);
2988 pBE->m_timer = new wxQTLoadTimer(pBE->m_movie, pBE, &pBE->m_lib);
2989 pBE->m_timer->Start(MOVIE_DELAY);
2990 }
2991
2992
2993 //---------------------------------------------------------------------------
2994 // wxQTMediaBackend::Load (URL Version)
2995 //
2996 // 1) Build an escaped URI from location
2997 // 2) Create a handle to store the URI string
2998 // 3) Put the URI string inside the handle
2999 // 4) Make a QuickTime URL data ref from the handle with the URI in it
3000 // 5) Clean up the URI string handle
3001 // 6) Do some prerolling
3002 // 7) Finish Loading
3003 //---------------------------------------------------------------------------
3004 bool wxQTMediaBackend::Load(const wxURI& location)
3005 {
3006 if(m_movie)
3007 Cleanup();
3008
3009 wxString theURI = location.BuildURI();
3010
3011 Handle theHandle = m_lib.NewHandleClear(theURI.length() + 1);
3012 wxASSERT(theHandle);
3013
3014 m_lib.BlockMove(theURI.mb_str(), *theHandle, theURI.length() + 1);
3015
3016 //create the movie from the handle that refers to the URI
3017 OSErr err = m_lib.NewMovieFromDataRef(&m_movie, newMovieActive |
3018 newMovieAsyncOK
3019 /*|newMovieIdleImportOK*/,
3020 NULL, theHandle,
3021 URLDataHandlerSubType);
3022
3023 m_lib.DisposeHandle(theHandle);
3024
3025 if (err == noErr)
3026 {
3027 long timeNow;
3028 Fixed playRate;
3029
3030 timeNow = m_lib.GetMovieTime(m_movie, NULL);
3031 wxASSERT(m_lib.GetMoviesError() == noErr);
3032
3033 playRate = m_lib.GetMoviePreferredRate(m_movie);
3034 wxASSERT(m_lib.GetMoviesError() == noErr);
3035
3036 //
3037 // Note that the callback here is optional,
3038 // but without it PrePrerollMovie can be buggy
3039 // (see Apple ml). Also, some may wonder
3040 // why we need this at all - this is because
3041 // Apple docs say QuickTime streamed movies
3042 // require it if you don't use a Movie Controller,
3043 // which we don't by default.
3044 //
3045 m_lib.PrePrerollMovie(m_movie, timeNow, playRate,
3046 (WXFARPROC)wxQTMediaBackend::PPRMProc,
3047 (void*)this);
3048 return true;
3049 }
3050 else
3051 return false;
3052 }
3053
3054
3055 //---------------------------------------------------------------------------
3056 // wxQTMediaBackend::FinishLoad
3057 //
3058 // 1) Create the movie timer
3059 // 2) Get real size of movie for GetBestSize/sizers
3060 // 3) Set the movie time scale to something usable so that seeking
3061 // etc. will work correctly
3062 // 4) Set our Movie Controller to display the movie if it exists,
3063 // otherwise set the bounds of the Movie
3064 // 5) Refresh parent window
3065 //---------------------------------------------------------------------------
3066 void wxQTMediaBackend::FinishLoad()
3067 {
3068 // Create the playing/streaming timer
3069 m_timer = new wxQTPlayTimer(m_movie, (wxQTMediaBackend*) this, &m_lib);
3070 wxASSERT(m_timer);
3071 m_timer->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS);
3072
3073 //get the real size of the movie
3074 Rect outRect;
3075 memset(&outRect, 0, sizeof(Rect)); //for annoying VC6 warning
3076 m_lib.GetMovieNaturalBoundsRect (m_movie, &outRect);
3077 wxASSERT(m_lib.GetMoviesError() == noErr);
3078
3079 m_bestSize.x = outRect.right - outRect.left;
3080 m_bestSize.y = outRect.bottom - outRect.top;
3081
3082 //
3083 // Handle the movie GWorld
3084 //
3085 if(m_pMC)
3086 {
3087 Point thePoint;
3088 thePoint.h = thePoint.v = 0;
3089 m_lib.MCSetMovie(m_pMC, m_movie,
3090 m_lib.GetNativeWindowPort(m_ctrl->GetHandle()),
3091 thePoint);
3092 m_lib.MCSetVisible(m_pMC, true);
3093 m_bestSize.y += 16;
3094 }
3095 else
3096 {
3097 m_lib.SetMovieGWorld(m_movie,
3098 (CGrafPtr) m_lib.GetNativeWindowPort(m_ctrl->GetHWND()),
3099 NULL);
3100 }
3101
3102 //
3103 // Set the movie to millisecond precision
3104 //
3105 m_lib.SetMovieTimeScale(m_movie, 1000);
3106 wxASSERT(m_lib.GetMoviesError() == noErr);
3107
3108 NotifyMovieLoaded();
3109 }
3110
3111 //---------------------------------------------------------------------------
3112 // wxQTMediaBackend::Play
3113 //
3114 // 1) Start the QT movie
3115 // 2) Start the movie loading timer
3116 //
3117 // NOTE: This will still return success even when
3118 // the movie is still loading, and as mentioned in wxQTLoadTimer
3119 // I don't know of a way to force this to be sync - so if its
3120 // still loading the function will return true but the movie will
3121 // still be in the stopped state
3122 //---------------------------------------------------------------------------
3123 bool wxQTMediaBackend::Play()
3124 {
3125 m_lib.StartMovie(m_movie);
3126 m_bPlaying = true;
3127 return m_lib.GetMoviesError() == noErr;
3128 }
3129
3130 //---------------------------------------------------------------------------
3131 // wxQTMediaBackend::Pause
3132 //
3133 // 1) Stop the movie
3134 // 2) Stop the movie timer
3135 //---------------------------------------------------------------------------
3136 bool wxQTMediaBackend::Pause()
3137 {
3138 m_bPlaying = false;
3139 m_lib.StopMovie(m_movie);
3140 return m_lib.GetMoviesError() == noErr;
3141 }
3142
3143 //---------------------------------------------------------------------------
3144 // wxQTMediaBackend::Stop
3145 //
3146 // 1) Stop the movie
3147 // 2) Stop the movie timer
3148 // 3) Seek to the beginning of the movie
3149 //---------------------------------------------------------------------------
3150 bool wxQTMediaBackend::Stop()
3151 {
3152 m_bPlaying = false;
3153
3154 m_lib.StopMovie(m_movie);
3155 if(m_lib.GetMoviesError() != noErr)
3156 return false;
3157
3158 m_lib.GoToBeginningOfMovie(m_movie);
3159 return m_lib.GetMoviesError() == noErr;
3160 }
3161
3162 //---------------------------------------------------------------------------
3163 // wxQTMediaBackend::GetPlaybackRate
3164 //
3165 // 1) Get the movie playback rate from ::GetMovieRate
3166 //---------------------------------------------------------------------------
3167 double wxQTMediaBackend::GetPlaybackRate()
3168 {
3169 return ( ((double)m_lib.GetMovieRate(m_movie)) / 0x10000);
3170 }
3171
3172 //---------------------------------------------------------------------------
3173 // wxQTMediaBackend::SetPlaybackRate
3174 //
3175 // 1) Convert dRate to Fixed and Set the movie rate through SetMovieRate
3176 //---------------------------------------------------------------------------
3177 bool wxQTMediaBackend::SetPlaybackRate(double dRate)
3178 {
3179 m_lib.SetMovieRate(m_movie, (Fixed) (dRate * 0x10000));
3180 return m_lib.GetMoviesError() == noErr;
3181 }
3182
3183 //---------------------------------------------------------------------------
3184 // wxQTMediaBackend::SetPosition
3185 //
3186 // 1) Create a time record struct (TimeRecord) with appropriate values
3187 // 2) Pass struct to SetMovieTime
3188 //---------------------------------------------------------------------------
3189 bool wxQTMediaBackend::SetPosition(wxLongLong where)
3190 {
3191 //NB: For some reason SetMovieTime does not work
3192 //correctly with the Quicktime Windows SDK (6)
3193 //From Muskelkatermann at the wxForum
3194 //http://www.solidsteel.nl/users/wxwidgets/viewtopic.php?t=2957
3195 //RN - note that I have not verified this but there
3196 //is no harm in calling SetMovieTimeValue instead
3197 #if 0
3198 TimeRecord theTimeRecord;
3199 memset(&theTimeRecord, 0, sizeof(TimeRecord));
3200 theTimeRecord.value.lo = where.GetLo();
3201 theTimeRecord.scale = m_lib.GetMovieTimeScale(m_movie);
3202 theTimeRecord.base = m_lib.GetMovieTimeBase(m_movie);
3203 m_lib.SetMovieTime(m_movie, &theTimeRecord);
3204 #else
3205 m_lib.SetMovieTimeValue(m_movie, where.GetLo());
3206 #endif
3207 if (m_lib.GetMoviesError() != noErr)
3208 return false;
3209
3210 return true;
3211 }
3212
3213 //---------------------------------------------------------------------------
3214 // wxQTMediaBackend::GetPosition
3215 //
3216 // 1) Calls GetMovieTime to get the position we are in in the movie
3217 // in milliseconds (we called
3218 //---------------------------------------------------------------------------
3219 wxLongLong wxQTMediaBackend::GetPosition()
3220 {
3221 return m_lib.GetMovieTime(m_movie, NULL);
3222 }
3223
3224 //---------------------------------------------------------------------------
3225 // wxQTMediaBackend::GetVolume
3226 //
3227 // Gets the volume through GetMovieVolume - which returns a 16 bit short -
3228 //
3229 // +--------+--------+
3230 // + (1) + (2) +
3231 // +--------+--------+
3232 //
3233 // (1) first 8 bits are value before decimal
3234 // (2) second 8 bits are value after decimal
3235 //
3236 // Volume ranges from -1.0 (gain but no sound), 0 (no sound and no gain) to
3237 // 1 (full gain and sound)
3238 //---------------------------------------------------------------------------
3239 double wxQTMediaBackend::GetVolume()
3240 {
3241 short sVolume = m_lib.GetMovieVolume(m_movie);
3242 wxASSERT(m_lib.GetMoviesError() == noErr);
3243
3244 if(sVolume & (128 << 8)) //negative - no sound
3245 return 0.0;
3246
3247 return sVolume/256.0;
3248 }
3249
3250 //---------------------------------------------------------------------------
3251 // wxQTMediaBackend::SetVolume
3252 //
3253 // Sets the volume through SetMovieVolume - which takes a 16 bit short -
3254 //
3255 // +--------+--------+
3256 // + (1) + (2) +
3257 // +--------+--------+
3258 //
3259 // (1) first 8 bits are value before decimal
3260 // (2) second 8 bits are value after decimal
3261 //
3262 // Volume ranges from -1.0 (gain but no sound), 0 (no sound and no gain) to
3263 // 1 (full gain and sound)
3264 //---------------------------------------------------------------------------
3265 bool wxQTMediaBackend::SetVolume(double dVolume)
3266 {
3267 m_lib.SetMovieVolume(m_movie, (short) (dVolume * 256));
3268 return m_lib.GetMoviesError() == noErr;
3269 }
3270
3271 //---------------------------------------------------------------------------
3272 // wxQTMediaBackend::GetDuration
3273 //
3274 // Calls GetMovieDuration
3275 //---------------------------------------------------------------------------
3276 wxLongLong wxQTMediaBackend::GetDuration()
3277 {
3278 return m_lib.GetMovieDuration(m_movie);
3279 }
3280
3281 //---------------------------------------------------------------------------
3282 // wxQTMediaBackend::GetState
3283 //
3284 // Determines the current state - if we are at the beginning we
3285 // are stopped
3286 //---------------------------------------------------------------------------
3287 wxMediaState wxQTMediaBackend::GetState()
3288 {
3289 if (m_bPlaying == true)
3290 return wxMEDIASTATE_PLAYING;
3291 else if ( !m_movie || wxQTMediaBackend::GetPosition() == 0)
3292 return wxMEDIASTATE_STOPPED;
3293 else
3294 return wxMEDIASTATE_PAUSED;
3295 }
3296
3297 //---------------------------------------------------------------------------
3298 // wxQTMediaBackend::Cleanup
3299 //
3300 // Diposes of the movie timer, Disassociates the Movie Controller with
3301 // movie and hides it if it exists, and stops and disposes
3302 // of the QT movie
3303 //---------------------------------------------------------------------------
3304 void wxQTMediaBackend::Cleanup()
3305 {
3306 m_bPlaying = false;
3307
3308 if(m_timer)
3309 {
3310 delete m_timer;
3311 m_timer = NULL;
3312 }
3313
3314 m_lib.StopMovie(m_movie);
3315
3316 if(m_pMC)
3317 {
3318 Point thePoint;
3319 thePoint.h = thePoint.v = 0;
3320 m_lib.MCSetVisible(m_pMC, false);
3321 m_lib.MCSetMovie(m_pMC, NULL, NULL, thePoint);
3322 }
3323
3324 m_lib.DisposeMovie(m_movie);
3325 m_movie = NULL;
3326 }
3327
3328 //---------------------------------------------------------------------------
3329 // wxQTMediaBackend::ShowPlayerControls
3330 //
3331 // Creates a movie controller for the Movie if the user wants it
3332 //---------------------------------------------------------------------------
3333 bool wxQTMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
3334 {
3335 if(m_pMC)
3336 {
3337 //restore old wndproc
3338 wxSetWindowProc((HWND)m_ctrl->GetHWND(), wxWndProc);
3339 m_lib.DisposeMovieController(m_pMC);
3340 m_pMC = NULL;
3341 m_bestSize.y -= 16; //movie controller height
3342 }
3343
3344 if(flags && m_movie)
3345 {
3346 Rect rect;
3347 wxRect wxrect = m_ctrl->GetClientRect();
3348
3349 //make room for controller
3350 if(wxrect.width < 320)
3351 wxrect.width = 320;
3352
3353 rect.top = (short)wxrect.y;
3354 rect.left = (short)wxrect.x;
3355 rect.right = (short)(rect.left + wxrect.width);
3356 rect.bottom = (short)(rect.top + wxrect.height);
3357
3358 if(!m_pMC)
3359 {
3360 m_pMC = m_lib.NewMovieController(m_movie, &rect, mcTopLeftMovie |
3361 // mcScaleMovieToFit |
3362 // mcWithBadge |
3363 mcWithFrame);
3364 m_lib.MCDoAction(m_pMC, 32, (void*)true); //mcActionSetKeysEnabled
3365 m_lib.MCSetActionFilterWithRefCon(m_pMC,
3366 (WXFARPROC)wxQTMediaBackend::MCFilterProc, (void*)this);
3367 m_bestSize.y += 16; //movie controller height
3368
3369 //
3370 // By default the movie controller uses its own color
3371 // pallette for the movie which can be bad on some files -
3372 // so turn it off. Also turn off its frame/border for
3373 // the movie
3374 //
3375 // Also we take care of a couple of the interface flags here
3376 //
3377 long mcFlags = 0;
3378 m_lib.MCDoAction(m_pMC, 39/*mcActionGetFlags*/, (void*)&mcFlags);
3379 mcFlags |= ( //(1<<0)/*mcFlagSuppressMovieFrame*/ |
3380 (1<<3)/*mcFlagsUseWindowPalette*/
3381 | ((flags & wxMEDIACTRLPLAYERCONTROLS_STEP)
3382 ? 0 : (1<<1)/*mcFlagSuppressStepButtons*/)
3383 | ((flags & wxMEDIACTRLPLAYERCONTROLS_VOLUME)
3384 ? 0 : (1<<2)/*mcFlagSuppressSpeakerButton*/)
3385 // | (1<<4) /*mcFlagDontInvalidate*/ //if we take care of repainting ourselves
3386 );
3387 m_lib.MCDoAction(m_pMC, 38/*mcActionSetFlags*/, (void*)mcFlags);
3388
3389 //intercept the wndproc of our control window
3390 wxSetWindowProc((HWND)m_ctrl->GetHWND(),
3391 wxQTMediaBackend::QTWndProc);
3392
3393 //set the user data of our window
3394 wxSetWindowUserData((HWND)m_ctrl->GetHWND(), this);
3395 }
3396 }
3397
3398 NotifyMovieSizeChanged();
3399
3400 return m_lib.GetMoviesError() == noErr;
3401 }
3402
3403 //---------------------------------------------------------------------------
3404 // wxQTMediaBackend::MCFilterProc (static)
3405 //
3406 // Callback for when the movie controller recieves a message
3407 //---------------------------------------------------------------------------
3408 Boolean
3409 wxQTMediaBackend::MCFilterProc(MovieController WXUNUSED(theController),
3410 short action,
3411 void * WXUNUSED(params),
3412 LONG_PTR refCon)
3413 {
3414 if(action != 1) //don't process idle events
3415 {
3416 wxQTMediaBackend* pThis = (wxQTMediaBackend*)refCon;
3417
3418 switch(action)
3419 {
3420 case 8: //play button triggered - MC will set movie to opposite state
3421 //of current - playing ? paused : playing
3422 pThis->m_bPlaying = !(pThis->m_bPlaying);
3423
3424 // NB: Sometimes it doesn't redraw properly -
3425 // if you click on the button but don't move the mouse
3426 // the button will not change its state until you move
3427 // mcActionDraw and Refresh/Update combo do nothing
3428 // to help this unfortunately
3429 break;
3430 default:
3431 break;
3432 }
3433 }
3434 return 0;
3435 }
3436
3437 //---------------------------------------------------------------------------
3438 // wxQTMediaBackend::GetVideoSize
3439 //
3440 // Returns the actual size of the QT movie
3441 //---------------------------------------------------------------------------
3442 wxSize wxQTMediaBackend::GetVideoSize() const
3443 {
3444 return m_bestSize;
3445 }
3446
3447 //---------------------------------------------------------------------------
3448 // wxQTMediaBackend::Move
3449 //
3450 // Sets the bounds of either the Movie or Movie Controller
3451 //---------------------------------------------------------------------------
3452 void wxQTMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y), int w, int h)
3453 {
3454 if(m_movie)
3455 {
3456 //make room for controller
3457 if(m_pMC)
3458 {
3459 if(w < 320)
3460 w = 320;
3461
3462 Rect theRect = {0, 0, (short)h, (short)w};
3463 m_lib.MCSetControllerBoundsRect(m_pMC, &theRect);
3464 }
3465 else
3466 {
3467 Rect theRect = {0, 0, (short)h, (short)w};
3468 m_lib.SetMovieBox(m_movie, &theRect);
3469 }
3470
3471 wxASSERT(m_lib.GetMoviesError() == noErr);
3472 }
3473 }
3474
3475 //---------------------------------------------------------------------------
3476 // wxQTMediaBackend::OnEraseBackground
3477 //
3478 // Suggestion from Greg Hazel to repaint the movie when idle
3479 // (on pause also)
3480 //
3481 // TODO: We may be repainting too much here - under what exact circumstances
3482 // do we need this? I think Move also repaints correctly for the Movie
3483 // Controller, so in that instance we don't need this either
3484 //---------------------------------------------------------------------------
3485 void wxQTMediaEvtHandler::OnEraseBackground(wxEraseEvent& evt)
3486 {
3487 wxQuickTimeLibrary& m_pLib = m_qtb->m_lib;
3488
3489 if ( m_qtb->m_pMC )
3490 {
3491 // repaint movie controller
3492 m_pLib.MCDoAction(m_qtb->m_pMC, 2 /*mcActionDraw*/,
3493 m_pLib.GetNativeWindowPort(m_hwnd));
3494 }
3495 else // no movie controller
3496 {
3497 if ( m_qtb->m_movie )
3498 {
3499 CGrafPtr port = (CGrafPtr)m_pLib.GetNativeWindowPort(m_hwnd);
3500
3501 m_pLib.BeginUpdate(port);
3502 m_pLib.UpdateMovie(m_qtb->m_movie);
3503 wxASSERT(m_pLib.GetMoviesError() == noErr);
3504 m_pLib.EndUpdate(port);
3505 }
3506 else // no movie
3507 {
3508 // let the system repaint the window
3509 evt.Skip();
3510 }
3511 }
3512 }
3513
3514 //---------------------------------------------------------------------------
3515 // End QT Backend
3516 //---------------------------------------------------------------------------
3517
3518 //in source file that contains stuff you don't directly use
3519 #include "wx/html/forcelnk.h"
3520 FORCE_LINK_ME(basewxmediabackends)
3521
3522 //---------------------------------------------------------------------------
3523 // End wxMediaCtrl Compilation Guard and this file
3524 //---------------------------------------------------------------------------
3525 #endif //wxUSE_MEDIACTRL