]> git.saurik.com Git - wxWidgets.git/blob - src/msw/mediactrl.cpp
many improvements/bug fixes to media control: new wxEVT_MEDIA_LOADED event, new metho...
[wxWidgets.git] / src / msw / mediactrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: msw/mediactrl.cpp
3 // Purpose: Built-in Media Backends for Windows
4 // Author: Ryan Norton <wxprojects@comcast.net>
5 // Modified by:
6 // Created: 11/07/04
7 // RCS-ID: $Id$
8 // Copyright: (c) Ryan Norton
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 //===========================================================================
13 // DECLARATIONS
14 //===========================================================================
15
16 //---------------------------------------------------------------------------
17 // Pre-compiled header stuff
18 //---------------------------------------------------------------------------
19
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "mediactrl.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 //---------------------------------------------------------------------------
32 // MediaCtrl include
33 //---------------------------------------------------------------------------
34 #include "wx/mediactrl.h"
35
36 //---------------------------------------------------------------------------
37 // Compilation guard
38 //---------------------------------------------------------------------------
39 #if wxUSE_MEDIACTRL
40
41 //---------------------------------------------------------------------------
42 // WX Includes
43 //---------------------------------------------------------------------------
44 #include "wx/log.h" //wxLogDebug
45 #include "wx/math.h" //log10 & pow
46 #include "wx/msw/private.h" //user info and wndproc setting/getting
47
48 //---------------------------------------------------------------------------
49 // Externals (somewhere in src/msw/app.cpp and src/msw/window.cpp)
50 //---------------------------------------------------------------------------
51 extern "C" WXDLLIMPEXP_BASE HINSTANCE wxGetInstance(void);
52 #ifdef __WXWINCE__
53 extern WXDLLIMPEXP_CORE wxChar *wxCanvasClassName;
54 #else
55 extern WXDLLIMPEXP_CORE const wxChar *wxCanvasClassName;
56 #endif
57
58 LRESULT WXDLLIMPEXP_CORE APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
59 WPARAM wParam, LPARAM lParam);
60
61 //===========================================================================
62 // BACKEND DECLARATIONS
63 //===========================================================================
64
65 //---------------------------------------------------------------------------
66 //
67 // wxAMMediaBackend
68 //
69 //---------------------------------------------------------------------------
70
71 //---------------------------------------------------------------------------
72 // COM includes
73 //---------------------------------------------------------------------------
74 #include "wx/msw/ole/oleutils.h" //wxBasicString, IID etc.
75 #include "wx/msw/ole/uuid.h" //IID etc..
76 #include <oleidl.h>
77 #include <olectl.h>
78 #include <exdisp.h>
79 #include <docobj.h>
80
81 //
82 // These defines are from another ole header - but its not in the
83 // latest sdk. Also the ifndef DISPID_READYSTATE is here because at
84 // least on my machine with the latest sdk olectl.h defines these 3
85 //
86 #ifndef DISPID_READYSTATE
87 #define DISPID_READYSTATE -525
88 #define DISPID_READYSTATECHANGE -609
89 #define DISPID_AMBIENT_TRANSFERPRIORITY -728
90 #endif
91
92 #define DISPID_AMBIENT_OFFLINEIFNOTCONNECTED -5501
93 #define DISPID_AMBIENT_SILENT -5502
94
95 #ifndef DISPID_AMBIENT_CODEPAGE
96 # define DISPID_AMBIENT_CODEPAGE -725
97 # define DISPID_AMBIENT_CHARSET -727
98 #endif
99
100 //---------------------------------------------------------------------------
101 // COM compatability definitions
102 //---------------------------------------------------------------------------
103 #ifndef STDMETHODCALLTYPE
104 #define STDMETHODCALLTYPE __stdcall
105 #endif
106 #ifndef STDMETHOD
107 #define STDMETHOD(funcname) virtual HRESULT STDMETHODCALLTYPE funcname
108 #endif
109 #ifndef PURE
110 #define PURE = 0
111 #endif
112 #ifndef __RPC_FAR
113 #define __RPC_FAR FAR
114 #endif
115
116 //---------------------------------------------------------------------------
117 // IIDS - used by CoCreateInstance and IUnknown::QueryInterface
118 //
119 // [idl name] [idl decription]
120 // amcompat.idl Microsoft Active Movie Control (Ver 2.0)
121 // nscompat.idl Microsoft NetShow Player (Ver 1.0)
122 // msdxm.idl Windows Media Player (Ver 1.0)
123 // quartz.idl
124 //
125 // First, when I say I "from XXX.idl", I mean I go into the COM Browser
126 // ($Microsoft Visual Studio$/Common/Tools/OLEVIEW.EXE), open
127 // "type libraries", open a specific type library (for quartz for example its
128 // "ActiveMovie control type library (V1.0)"), save it as an .idl, compile the
129 // idl using the midl compiler that comes with visual studio
130 // ($Microsoft Visual Studio$/VC98/bin/midl.exe on VC6) with the /h argument
131 // to make it generate stubs (a .h & .c file), then clean up the generated
132 // interfaces I want with the STDMETHOD wrappers and then put them into
133 // mediactrl.cpp.
134 //
135 // According to the MSDN docs, IMediaPlayer requires Windows 98 SE
136 // or greater. NetShow is available on Windows 3.1 and I'm guessing
137 // IActiveMovie is too. IMediaPlayer is essentially the Windows Media
138 // Player 6.4 SDK.
139 //
140 // Some of these are not used but are kept here for future reference anyway
141 //---------------------------------------------------------------------------
142 const IID IID_IActiveMovie = {0x05589FA2,0xC356,0x11CE,{0xBF,0x01,0x00,0xAA,0x00,0x55,0x59,0x5A}};
143 const IID IID_IActiveMovie2 = {0xB6CD6554,0xE9CB,0x11D0,{0x82,0x1F,0x00,0xA0,0xC9,0x1F,0x9C,0xA0}};
144 const IID IID_IActiveMovie3 = {0x265EC140,0xAE62,0x11D1,{0x85,0x00,0x00,0xA0,0xC9,0x1F,0x9C,0xA0}};
145
146 const IID IID_INSOPlay = {0x2179C5D1,0xEBFF,0x11CF,{0xB6,0xFD,0x00,0xAA,0x00,0xB4,0xE2,0x20}};
147 const IID IID_INSPlay = {0xE7C4BE80,0x7960,0x11D0,{0xB7,0x27,0x00,0xAA,0x00,0xB4,0xE2,0x20}};
148 const IID IID_INSPlay1 = {0x265EC141,0xAE62,0x11D1,{0x85,0x00,0x00,0xA0,0xC9,0x1F,0x9C,0xA0}};
149
150 const IID IID_IMediaPlayer = {0x22D6F311,0xB0F6,0x11D0,{0x94,0xAB,0x00,0x80,0xC7,0x4C,0x7E,0x95}};
151 const IID IID_IMediaPlayer2 = {0x20D4F5E0,0x5475,0x11D2,{0x97,0x74,0x00,0x00,0xF8,0x08,0x55,0xE6}};
152
153 const CLSID CLSID_ActiveMovie = {0x05589FA1,0xC356,0x11CE,{0xBF,0x01,0x00,0xAA,0x00,0x55,0x59,0x5A}};
154 const CLSID CLSID_MediaPlayer = {0x22D6F312,0xB0F6,0x11D0,{0x94,0xAB,0x00,0x80,0xC7,0x4C,0x7E,0x95}};
155 const CLSID CLSID_NSPlay = {0x2179C5D3,0xEBFF,0x11CF,{0xB6,0xFD,0x00,0xAA,0x00,0xB4,0xE2,0x20}};
156
157 const IID IID_IAMOpenProgress = {0x8E1C39A1, 0xDE53, 0x11CF,{0xAA, 0x63, 0x00, 0x80, 0xC7, 0x44, 0x52, 0x8D}};
158
159 // QUARTZ
160 const CLSID CLSID_FilgraphManager = {0xE436EBB3,0x524F,0x11CE,{0x9F,0x53,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
161 const IID IID_IMediaEvent = {0x56A868B6,0x0AD4,0x11CE,{0xB0,0x3A,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
162
163 //?? QUARTZ Also?
164 const CLSID CLSID_VideoMixingRenderer9 ={0x51B4ABF3, 0x748F, 0x4E3B,{0xA2, 0x76, 0xC8, 0x28, 0x33, 0x0E, 0x92, 0x6A}};
165 const IID IID_IVMRWindowlessControl9 = {0x8F537D09, 0xF85E, 0x4414,{0xB2, 0x3B, 0x50, 0x2E, 0x54, 0xC7, 0x99, 0x27}};
166 const IID IID_IFilterGraph = {0x56A8689F, 0x0AD4, 0x11CE,{0xB0, 0x3A, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70}};
167 const IID IID_IGraphBuilder = {0x56A868A9, 0x0AD4, 0x11CE,{0xB0, 0x3A, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70}};
168 const IID IID_IVMRFilterConfig9 = {0x5A804648, 0x4F66, 0x4867,{0x9C, 0x43, 0x4F, 0x5C, 0x82, 0x2C, 0xF1, 0xB8}};
169 const IID IID_IBaseFilter = {0x56A86895, 0x0AD4, 0x11CE,{0xB0, 0x3A, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70}};
170
171 //---------------------------------------------------------------------------
172 // QUARTZ COM INTERFACES (dumped from quartz.idl from MSVC COM Browser)
173 //---------------------------------------------------------------------------
174
175 struct IAMOpenProgress : public IUnknown
176 {
177 STDMETHOD(QueryProgress)(LONGLONG *pllTotal, LONGLONG *pllCurrent) PURE;
178 STDMETHOD(AbortOperation)(void) PURE;
179 };
180
181 struct IMediaEvent : public IDispatch
182 {
183 STDMETHOD(GetEventHandle)(LONG_PTR *) PURE;
184 STDMETHOD(GetEvent)(long *, LONG_PTR *, LONG_PTR *, long) PURE;
185 STDMETHOD(WaitForCompletion)(long, long *) PURE;
186 STDMETHOD(CancelDefaultHandling)(long) PURE;
187 STDMETHOD(RestoreDefaultHandling)(long) PURE;
188 STDMETHOD(FreeEventParams)(long, LONG_PTR, LONG_PTR) PURE;
189 };
190
191 //---------------------------------------------------------------------------
192 // ACTIVEMOVIE COM INTERFACES (dumped from amcompat.idl from MSVC COM Browser)
193 //---------------------------------------------------------------------------
194
195 enum ReadyStateConstants
196 {
197 amvUninitialized = 0,
198 amvLoading = 1,
199 amvInteractive = 3,
200 amvComplete = 4
201 };
202
203 enum StateConstants
204 {
205 amvNotLoaded = -1,
206 amvStopped = 0,
207 amvPaused = 1,
208 amvRunning = 2
209 };
210
211 enum DisplayModeConstants
212 {
213 amvTime = 0,
214 amvFrames = 1
215 };
216
217 enum WindowSizeConstants
218 {
219 amvOriginalSize = 0,
220 amvDoubleOriginalSize = 1,
221 amvOneSixteenthScreen = 2,
222 amvOneFourthScreen = 3,
223 amvOneHalfScreen = 4
224 };
225
226 enum AppearanceConstants
227 {
228 amvFlat = 0,
229 amv3D = 1
230 };
231
232 enum BorderStyleConstants
233 {
234 amvNone = 0,
235 amvFixedSingle = 1
236 };
237
238 struct IActiveMovie : public IDispatch
239 {
240 STDMETHOD(AboutBox)( void) PURE;
241 STDMETHOD(Run)( void) PURE;
242 STDMETHOD(Pause)( void) PURE;
243 STDMETHOD(Stop)( void) PURE;
244 STDMETHOD(get_ImageSourceWidth)(long __RPC_FAR *pWidth) PURE;
245 STDMETHOD(get_ImageSourceHeight)(long __RPC_FAR *pHeight) PURE;
246 STDMETHOD(get_Author)(BSTR __RPC_FAR *pbstrAuthor) PURE;
247 STDMETHOD(get_Title)(BSTR __RPC_FAR *pbstrTitle) PURE;
248 STDMETHOD(get_Copyright)(BSTR __RPC_FAR *pbstrCopyright) PURE;
249 STDMETHOD(get_Description)(BSTR __RPC_FAR *pbstrDescription) PURE;
250 STDMETHOD(get_Rating)(BSTR __RPC_FAR *pbstrRating) PURE;
251 STDMETHOD(get_FileName)(BSTR __RPC_FAR *pbstrFileName) PURE;
252 STDMETHOD(put_FileName)(BSTR pbstrFileName) PURE;
253 STDMETHOD(get_Duration)(double __RPC_FAR *pValue) PURE;
254 STDMETHOD(get_CurrentPosition)(double __RPC_FAR *pValue) PURE;
255 STDMETHOD(put_CurrentPosition)(double pValue) PURE;
256 STDMETHOD(get_PlayCount)(long __RPC_FAR *pPlayCount) PURE;
257 STDMETHOD(put_PlayCount)(long pPlayCount) PURE;
258 STDMETHOD(get_SelectionStart)(double __RPC_FAR *pValue) PURE;
259 STDMETHOD(put_SelectionStart)(double pValue) PURE;
260 STDMETHOD(get_SelectionEnd)(double __RPC_FAR *pValue) PURE;
261 STDMETHOD(put_SelectionEnd)(double pValue) PURE;
262 STDMETHOD(get_CurrentState)(StateConstants __RPC_FAR *pState) PURE;
263 STDMETHOD(get_Rate)(double __RPC_FAR *pValue) PURE;
264 STDMETHOD(put_Rate)(double pValue) PURE;
265 STDMETHOD(get_Volume)(long __RPC_FAR *pValue) PURE;
266 STDMETHOD(put_Volume)(long pValue) PURE;
267 STDMETHOD(get_Balance)(long __RPC_FAR *pValue) PURE;
268 STDMETHOD(put_Balance)(long pValue) PURE;
269 STDMETHOD(get_EnableContextMenu)(VARIANT_BOOL __RPC_FAR *pEnable) PURE;
270 STDMETHOD(put_EnableContextMenu)(VARIANT_BOOL pEnable) PURE;
271 STDMETHOD(get_ShowDisplay)(VARIANT_BOOL __RPC_FAR *Show) PURE;
272 STDMETHOD(put_ShowDisplay)(VARIANT_BOOL Show) PURE;
273 STDMETHOD(get_ShowControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
274 STDMETHOD(put_ShowControls)(VARIANT_BOOL Show) PURE;
275 STDMETHOD(get_ShowPositionControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
276 STDMETHOD(put_ShowPositionControls)(VARIANT_BOOL Show) PURE;
277 STDMETHOD(get_ShowSelectionControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
278 STDMETHOD(put_ShowSelectionControls)(VARIANT_BOOL Show) PURE;
279 STDMETHOD(get_ShowTracker)(VARIANT_BOOL __RPC_FAR *Show) PURE;
280 STDMETHOD(put_ShowTracker)(VARIANT_BOOL Show) PURE;
281 STDMETHOD(get_EnablePositionControls)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
282 STDMETHOD(put_EnablePositionControls)(VARIANT_BOOL Enable) PURE;
283 STDMETHOD(get_EnableSelectionControls)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
284 STDMETHOD(put_EnableSelectionControls)(VARIANT_BOOL Enable) PURE;
285 STDMETHOD(get_EnableTracker)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
286 STDMETHOD(put_EnableTracker)(VARIANT_BOOL Enable) PURE;
287 STDMETHOD(get_AllowHideDisplay)(VARIANT_BOOL __RPC_FAR *Show) PURE;
288 STDMETHOD(put_AllowHideDisplay)(VARIANT_BOOL Show) PURE;
289 STDMETHOD(get_AllowHideControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
290 STDMETHOD(put_AllowHideControls)(VARIANT_BOOL Show) PURE;
291 STDMETHOD(get_DisplayMode)(DisplayModeConstants __RPC_FAR *pValue) PURE;
292 STDMETHOD(put_DisplayMode)(DisplayModeConstants pValue) PURE;
293 STDMETHOD(get_AllowChangeDisplayMode)(VARIANT_BOOL __RPC_FAR *fAllow) PURE;
294 STDMETHOD(put_AllowChangeDisplayMode)(VARIANT_BOOL fAllow) PURE;
295 STDMETHOD(get_FilterGraph)(IUnknown __RPC_FAR *__RPC_FAR *ppFilterGraph) PURE;
296 STDMETHOD(put_FilterGraph)(IUnknown __RPC_FAR *ppFilterGraph) PURE;
297 STDMETHOD(get_FilterGraphDispatch)(IDispatch __RPC_FAR *__RPC_FAR *pDispatch) PURE;
298 STDMETHOD(get_DisplayForeColor)(unsigned long __RPC_FAR *ForeColor) PURE;
299 STDMETHOD(put_DisplayForeColor)(unsigned long ForeColor) PURE;
300 STDMETHOD(get_DisplayBackColor)(unsigned long __RPC_FAR *BackColor) PURE;
301 STDMETHOD(put_DisplayBackColor)(unsigned long BackColor) PURE;
302 STDMETHOD(get_MovieWindowSize)(WindowSizeConstants __RPC_FAR *WindowSize) PURE;
303 STDMETHOD(put_MovieWindowSize)(WindowSizeConstants WindowSize) PURE;
304 STDMETHOD(get_FullScreenMode)(VARIANT_BOOL __RPC_FAR *pEnable) PURE;
305 STDMETHOD(put_FullScreenMode)(VARIANT_BOOL pEnable) PURE;
306 STDMETHOD(get_AutoStart)(VARIANT_BOOL __RPC_FAR *pEnable) PURE;
307 STDMETHOD(put_AutoStart)(VARIANT_BOOL pEnable) PURE;
308 STDMETHOD(get_AutoRewind)(VARIANT_BOOL __RPC_FAR *pEnable) PURE;
309 STDMETHOD(put_AutoRewind)(VARIANT_BOOL pEnable) PURE;
310 STDMETHOD(get_hWnd)(long __RPC_FAR *hWnd) PURE;
311 STDMETHOD(get_Appearance)(AppearanceConstants __RPC_FAR *pAppearance) PURE;
312 STDMETHOD(put_Appearance)(AppearanceConstants pAppearance) PURE;
313 STDMETHOD(get_BorderStyle)(BorderStyleConstants __RPC_FAR *pBorderStyle) PURE;
314 STDMETHOD(put_BorderStyle)(BorderStyleConstants pBorderStyle) PURE;
315 STDMETHOD(get_Enabled)(VARIANT_BOOL __RPC_FAR *pEnabled) PURE;
316 STDMETHOD(put_Enabled)(VARIANT_BOOL pEnabled) PURE;
317 STDMETHOD(get_Info)(long __RPC_FAR *ppInfo) PURE;
318 };
319
320
321
322 struct IActiveMovie2 : public IActiveMovie
323 {
324 STDMETHOD(IsSoundCardEnabled)(VARIANT_BOOL __RPC_FAR *pbSoundCard) PURE;
325 STDMETHOD(get_ReadyState)(ReadyStateConstants __RPC_FAR *pValue) PURE;
326 };
327
328 struct IActiveMovie3 : public IActiveMovie2
329 {
330 STDMETHOD(get_MediaPlayer)(IDispatch __RPC_FAR *__RPC_FAR *ppDispatch) PURE;
331 };
332
333
334 //---------------------------------------------------------------------------
335 // MEDIAPLAYER COM INTERFACES (dumped from msdxm.idl from MSVC COM Browser)
336 //---------------------------------------------------------------------------
337
338 enum MPPlayStateConstants
339 {
340 mpStopped = 0,
341 mpPaused = 1,
342 mpPlaying = 2,
343 mpWaiting = 3,
344 mpScanForward = 4,
345 mpScanReverse = 5,
346 mpClosed = 6
347 };
348
349 enum MPDisplaySizeConstants
350 {
351 mpDefaultSize = 0,
352 mpHalfSize = 1,
353 mpDoubleSize = 2,
354 mpFullScreen = 3,
355 mpFitToSize = 4,
356 mpOneSixteenthScreen = 5,
357 mpOneFourthScreen = 6,
358 mpOneHalfScreen = 7
359 };
360
361 enum MPReadyStateConstants
362 {
363 mpReadyStateUninitialized = 0,
364 mpReadyStateLoading = 1,
365 mpReadyStateInteractive = 3,
366 mpReadyStateComplete = 4
367 };
368
369 typedef unsigned long VB_OLE_COLOR;
370
371 enum MPDisplayModeConstants
372 {
373 mpTime = 0,
374 mpFrames = 1
375 };
376
377 enum MPMoreInfoType
378 {
379 mpShowURL = 0,
380 mpClipURL = 1,
381 mpBannerURL = 2
382 };
383
384 enum MPMediaInfoType
385 {
386 mpShowFilename = 0,
387 mpShowTitle = 1,
388 mpShowAuthor = 2,
389 mpShowCopyright = 3,
390 mpShowRating = 4,
391 mpShowDescription = 5,
392 mpShowLogoIcon = 6,
393 mpClipFilename = 7,
394 mpClipTitle = 8,
395 mpClipAuthor = 9,
396 mpClipCopyright = 10,
397 mpClipRating = 11,
398 mpClipDescription = 12,
399 mpClipLogoIcon = 13,
400 mpBannerImage = 14,
401 mpBannerMoreInfo = 15,
402 mpWatermark = 16
403 };
404
405 enum DVDMenuIDConstants
406 {
407 dvdMenu_Title = 2,
408 dvdMenu_Root = 3,
409 dvdMenu_Subpicture = 4,
410 dvdMenu_Audio = 5,
411 dvdMenu_Angle = 6,
412 dvdMenu_Chapter = 7
413 };
414
415 enum MPShowDialogConstants
416 {
417 mpShowDialogHelp = 0,
418 mpShowDialogStatistics = 1,
419 mpShowDialogOptions = 2,
420 mpShowDialogContextMenu = 3
421 };
422
423
424 struct IMediaPlayer : public IDispatch
425 {
426 STDMETHOD(get_CurrentPosition)(double __RPC_FAR *pCurrentPosition) PURE;
427 STDMETHOD(put_CurrentPosition)(double pCurrentPosition) PURE;
428 STDMETHOD(get_Duration)(double __RPC_FAR *pDuration) PURE;
429 STDMETHOD(get_ImageSourceWidth)(long __RPC_FAR *pWidth) PURE;
430 STDMETHOD(get_ImageSourceHeight)(long __RPC_FAR *pHeight) PURE;
431 STDMETHOD(get_MarkerCount)(long __RPC_FAR *pMarkerCount) PURE;
432 STDMETHOD(get_CanScan)(VARIANT_BOOL __RPC_FAR *pCanScan) PURE;
433 STDMETHOD(get_CanSeek)(VARIANT_BOOL __RPC_FAR *pCanSeek) PURE;
434 STDMETHOD(get_CanSeekToMarkers)(VARIANT_BOOL __RPC_FAR *pCanSeekToMarkers) PURE;
435 STDMETHOD(get_CurrentMarker)(long __RPC_FAR *pCurrentMarker) PURE;
436 STDMETHOD(put_CurrentMarker)(long pCurrentMarker) PURE;
437 STDMETHOD(get_FileName)(BSTR __RPC_FAR *pbstrFileName) PURE;
438 STDMETHOD(put_FileName)(BSTR pbstrFileName) PURE;
439 STDMETHOD(get_SourceLink)(BSTR __RPC_FAR *pbstrSourceLink) PURE;
440 STDMETHOD(get_CreationDate)(DATE __RPC_FAR *pCreationDate) PURE;
441 STDMETHOD(get_ErrorCorrection)(BSTR __RPC_FAR *pbstrErrorCorrection) PURE;
442 STDMETHOD(get_Bandwidth)(long __RPC_FAR *pBandwidth) PURE;
443 STDMETHOD(get_SourceProtocol)(long __RPC_FAR *pSourceProtocol) PURE;
444 STDMETHOD(get_ReceivedPackets)(long __RPC_FAR *pReceivedPackets) PURE;
445 STDMETHOD(get_RecoveredPackets)(long __RPC_FAR *pRecoveredPackets) PURE;
446 STDMETHOD(get_LostPackets)(long __RPC_FAR *pLostPackets) PURE;
447 STDMETHOD(get_ReceptionQuality)(long __RPC_FAR *pReceptionQuality) PURE;
448 STDMETHOD(get_BufferingCount)(long __RPC_FAR *pBufferingCount) PURE;
449 STDMETHOD(get_IsBroadcast)(VARIANT_BOOL __RPC_FAR *pIsBroadcast) PURE;
450 STDMETHOD(get_BufferingProgress)(long __RPC_FAR *pBufferingProgress) PURE;
451 STDMETHOD(get_ChannelName)(BSTR __RPC_FAR *pbstrChannelName) PURE;
452 STDMETHOD(get_ChannelDescription)(BSTR __RPC_FAR *pbstrChannelDescription) PURE;
453 STDMETHOD(get_ChannelURL)(BSTR __RPC_FAR *pbstrChannelURL) PURE;
454 STDMETHOD(get_ContactAddress)(BSTR __RPC_FAR *pbstrContactAddress) PURE;
455 STDMETHOD(get_ContactPhone)(BSTR __RPC_FAR *pbstrContactPhone) PURE;
456 STDMETHOD(get_ContactEmail)(BSTR __RPC_FAR *pbstrContactEmail) PURE;
457 STDMETHOD(get_BufferingTime)(double __RPC_FAR *pBufferingTime) PURE;
458 STDMETHOD(put_BufferingTime)(double pBufferingTime) PURE;
459 STDMETHOD(get_AutoStart)(VARIANT_BOOL __RPC_FAR *pAutoStart) PURE;
460 STDMETHOD(put_AutoStart)(VARIANT_BOOL pAutoStart) PURE;
461 STDMETHOD(get_AutoRewind)(VARIANT_BOOL __RPC_FAR *pAutoRewind) PURE;
462 STDMETHOD(put_AutoRewind)(VARIANT_BOOL pAutoRewind) PURE;
463 STDMETHOD(get_Rate)(double __RPC_FAR *pRate) PURE;
464 STDMETHOD(put_Rate)(double pRate) PURE;
465 STDMETHOD(get_SendKeyboardEvents)(VARIANT_BOOL __RPC_FAR *pSendKeyboardEvents) PURE;
466 STDMETHOD(put_SendKeyboardEvents)(VARIANT_BOOL pSendKeyboardEvents) PURE;
467 STDMETHOD(get_SendMouseClickEvents)(VARIANT_BOOL __RPC_FAR *pSendMouseClickEvents) PURE;
468 STDMETHOD(put_SendMouseClickEvents)(VARIANT_BOOL pSendMouseClickEvents) PURE;
469 STDMETHOD(get_SendMouseMoveEvents)(VARIANT_BOOL __RPC_FAR *pSendMouseMoveEvents) PURE;
470 STDMETHOD(put_SendMouseMoveEvents)(VARIANT_BOOL pSendMouseMoveEvents) PURE;
471 STDMETHOD(get_PlayCount)(long __RPC_FAR *pPlayCount) PURE;
472 STDMETHOD(put_PlayCount)(long pPlayCount) PURE;
473 STDMETHOD(get_ClickToPlay)(VARIANT_BOOL __RPC_FAR *pClickToPlay) PURE;
474 STDMETHOD(put_ClickToPlay)(VARIANT_BOOL pClickToPlay) PURE;
475 STDMETHOD(get_AllowScan)(VARIANT_BOOL __RPC_FAR *pAllowScan) PURE;
476 STDMETHOD(put_AllowScan)(VARIANT_BOOL pAllowScan) PURE;
477 STDMETHOD(get_EnableContextMenu)(VARIANT_BOOL __RPC_FAR *pEnableContextMenu) PURE;
478 STDMETHOD(put_EnableContextMenu)(VARIANT_BOOL pEnableContextMenu) PURE;
479 STDMETHOD(get_CursorType)(long __RPC_FAR *pCursorType) PURE;
480 STDMETHOD(put_CursorType)(long pCursorType) PURE;
481 STDMETHOD(get_CodecCount)(long __RPC_FAR *pCodecCount) PURE;
482 STDMETHOD(get_AllowChangeDisplaySize)(VARIANT_BOOL __RPC_FAR *pAllowChangeDisplaySize) PURE;
483 STDMETHOD(put_AllowChangeDisplaySize)( VARIANT_BOOL pAllowChangeDisplaySize) PURE;
484 STDMETHOD(get_IsDurationValid)(VARIANT_BOOL __RPC_FAR *pIsDurationValid) PURE;
485 STDMETHOD(get_OpenState)(long __RPC_FAR *pOpenState) PURE;
486 STDMETHOD(get_SendOpenStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendOpenStateChangeEvents) PURE;
487 STDMETHOD(put_SendOpenStateChangeEvents)(VARIANT_BOOL pSendOpenStateChangeEvents) PURE;
488 STDMETHOD(get_SendWarningEvents)( VARIANT_BOOL __RPC_FAR *pSendWarningEvents) PURE;
489 STDMETHOD(put_SendWarningEvents)(VARIANT_BOOL pSendWarningEvents) PURE;
490 STDMETHOD(get_SendErrorEvents)(VARIANT_BOOL __RPC_FAR *pSendErrorEvents) PURE;
491 STDMETHOD(put_SendErrorEvents)(VARIANT_BOOL pSendErrorEvents) PURE;
492 STDMETHOD(get_PlayState)(MPPlayStateConstants __RPC_FAR *pPlayState) PURE;
493 STDMETHOD(get_SendPlayStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendPlayStateChangeEvents) PURE;
494 STDMETHOD(put_SendPlayStateChangeEvents)(VARIANT_BOOL pSendPlayStateChangeEvents) PURE;
495 STDMETHOD(get_DisplaySize)(MPDisplaySizeConstants __RPC_FAR *pDisplaySize) PURE;
496 STDMETHOD(put_DisplaySize)(MPDisplaySizeConstants pDisplaySize) PURE;
497 STDMETHOD(get_InvokeURLs)(VARIANT_BOOL __RPC_FAR *pInvokeURLs) PURE;
498 STDMETHOD(put_InvokeURLs)(VARIANT_BOOL pInvokeURLs) PURE;
499 STDMETHOD(get_BaseURL)(BSTR __RPC_FAR *pbstrBaseURL) PURE;
500 STDMETHOD(put_BaseURL)(BSTR pbstrBaseURL) PURE;
501 STDMETHOD(get_DefaultFrame)(BSTR __RPC_FAR *pbstrDefaultFrame) PURE;
502 STDMETHOD(put_DefaultFrame)(BSTR pbstrDefaultFrame) PURE;
503 STDMETHOD(get_HasError)(VARIANT_BOOL __RPC_FAR *pHasError) PURE;
504 STDMETHOD(get_ErrorDescription)(BSTR __RPC_FAR *pbstrErrorDescription) PURE;
505 STDMETHOD(get_ErrorCode)(long __RPC_FAR *pErrorCode) PURE;
506 STDMETHOD(get_AnimationAtStart)(VARIANT_BOOL __RPC_FAR *pAnimationAtStart) PURE;
507 STDMETHOD(put_AnimationAtStart)(VARIANT_BOOL pAnimationAtStart) PURE;
508 STDMETHOD(get_TransparentAtStart)( VARIANT_BOOL __RPC_FAR *pTransparentAtStart) PURE;
509 STDMETHOD(put_TransparentAtStart)(VARIANT_BOOL pTransparentAtStart) PURE;
510 STDMETHOD(get_Volume)(long __RPC_FAR *pVolume) PURE;
511 STDMETHOD(put_Volume)(long pVolume) PURE;
512 STDMETHOD(get_Balance)(long __RPC_FAR *pBalance) PURE;
513 STDMETHOD(put_Balance)(long pBalance) PURE;
514 STDMETHOD(get_ReadyState)(MPReadyStateConstants __RPC_FAR *pValue) PURE;
515 STDMETHOD(get_SelectionStart)(double __RPC_FAR *pValue) PURE;
516 STDMETHOD(put_SelectionStart)(double pValue) PURE;
517 STDMETHOD(get_SelectionEnd)(double __RPC_FAR *pValue) PURE;
518 STDMETHOD(put_SelectionEnd)(double pValue) PURE;
519 STDMETHOD(get_ShowDisplay)(VARIANT_BOOL __RPC_FAR *Show) PURE;
520 STDMETHOD(put_ShowDisplay)(VARIANT_BOOL Show) PURE;
521 STDMETHOD(get_ShowControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
522 STDMETHOD(put_ShowControls)(VARIANT_BOOL Show) PURE;
523 STDMETHOD(get_ShowPositionControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
524 STDMETHOD(put_ShowPositionControls)(VARIANT_BOOL Show) PURE;
525 STDMETHOD(get_ShowTracker)(VARIANT_BOOL __RPC_FAR *Show) PURE;
526 STDMETHOD(put_ShowTracker)(VARIANT_BOOL Show) PURE;
527 STDMETHOD(get_EnablePositionControls)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
528 STDMETHOD(put_EnablePositionControls)(VARIANT_BOOL Enable) PURE;
529 STDMETHOD(get_EnableTracker)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
530 STDMETHOD(put_EnableTracker)(VARIANT_BOOL Enable) PURE;
531 STDMETHOD(get_Enabled)(VARIANT_BOOL __RPC_FAR *pEnabled) PURE;
532 STDMETHOD(put_Enabled)(VARIANT_BOOL pEnabled) PURE;
533 STDMETHOD(get_DisplayForeColor)(VB_OLE_COLOR __RPC_FAR *ForeColor) PURE;
534 STDMETHOD(put_DisplayForeColor)(VB_OLE_COLOR ForeColor) PURE;
535 STDMETHOD(get_DisplayBackColor)(VB_OLE_COLOR __RPC_FAR *BackColor) PURE;
536 STDMETHOD(put_DisplayBackColor)(VB_OLE_COLOR BackColor) PURE;
537 STDMETHOD(get_DisplayMode)(MPDisplayModeConstants __RPC_FAR *pValue) PURE;
538 STDMETHOD(put_DisplayMode)(MPDisplayModeConstants pValue) PURE;
539 STDMETHOD(get_VideoBorder3D)(VARIANT_BOOL __RPC_FAR *pVideoBorderWidth) PURE;
540 STDMETHOD(put_VideoBorder3D)(VARIANT_BOOL pVideoBorderWidth) PURE;
541 STDMETHOD(get_VideoBorderWidth)(long __RPC_FAR *pVideoBorderWidth) PURE;
542 STDMETHOD(put_VideoBorderWidth)(long pVideoBorderWidth) PURE;
543 STDMETHOD(get_VideoBorderColor)(VB_OLE_COLOR __RPC_FAR *pVideoBorderWidth) PURE;
544 STDMETHOD(put_VideoBorderColor)(VB_OLE_COLOR pVideoBorderWidth) PURE;
545 STDMETHOD(get_ShowGotoBar)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
546 STDMETHOD(put_ShowGotoBar)(VARIANT_BOOL pbool) PURE;
547 STDMETHOD(get_ShowStatusBar)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
548 STDMETHOD(put_ShowStatusBar)(VARIANT_BOOL pbool) PURE;
549 STDMETHOD(get_ShowCaptioning)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
550 STDMETHOD(put_ShowCaptioning)(VARIANT_BOOL pbool) PURE;
551 STDMETHOD(get_ShowAudioControls)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
552 STDMETHOD(put_ShowAudioControls)(VARIANT_BOOL pbool) PURE;
553 STDMETHOD(get_CaptioningID)( BSTR __RPC_FAR *pstrText) PURE;
554 STDMETHOD(put_CaptioningID)(BSTR pstrText) PURE;
555 STDMETHOD(get_Mute)(VARIANT_BOOL __RPC_FAR *vbool) PURE;
556 STDMETHOD(put_Mute)(VARIANT_BOOL vbool) PURE;
557 STDMETHOD(get_CanPreview)(VARIANT_BOOL __RPC_FAR *pCanPreview) PURE;
558 STDMETHOD(get_PreviewMode)(VARIANT_BOOL __RPC_FAR *pPreviewMode) PURE;
559 STDMETHOD(put_PreviewMode)(VARIANT_BOOL pPreviewMode) PURE;
560 STDMETHOD(get_HasMultipleItems)(VARIANT_BOOL __RPC_FAR *pHasMuliItems) PURE;
561 STDMETHOD(get_Language)(long __RPC_FAR *pLanguage) PURE;
562 STDMETHOD(put_Language)(long pLanguage) PURE;
563 STDMETHOD(get_AudioStream)(long __RPC_FAR *pStream) PURE;
564 STDMETHOD(put_AudioStream)(long pStream) PURE;
565 STDMETHOD(get_SAMIStyle)(BSTR __RPC_FAR *pbstrStyle) PURE;
566 STDMETHOD(put_SAMIStyle)(BSTR pbstrStyle) PURE;
567 STDMETHOD(get_SAMILang)(BSTR __RPC_FAR *pbstrLang) PURE;
568 STDMETHOD(put_SAMILang)(BSTR pbstrLang) PURE;
569 STDMETHOD(get_SAMIFileName)(BSTR __RPC_FAR *pbstrFileName) PURE;
570 STDMETHOD(put_SAMIFileName)(BSTR pbstrFileName) PURE;
571 STDMETHOD(get_StreamCount)( long __RPC_FAR *pStreamCount) PURE;
572 STDMETHOD(get_ClientId)(BSTR __RPC_FAR *pbstrClientId) PURE;
573 STDMETHOD(get_ConnectionSpeed)(long __RPC_FAR *plConnectionSpeed) PURE;
574 STDMETHOD(get_AutoSize)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
575 STDMETHOD(put_AutoSize)(VARIANT_BOOL pbool) PURE;
576 STDMETHOD(get_EnableFullScreenControls)(VARIANT_BOOL __RPC_FAR *pbVal) PURE;
577 STDMETHOD(put_EnableFullScreenControls)(VARIANT_BOOL pbVal) PURE;
578 STDMETHOD(get_ActiveMovie)(IDispatch __RPC_FAR *__RPC_FAR *ppdispatch) PURE;
579 STDMETHOD(get_NSPlay)(IDispatch __RPC_FAR *__RPC_FAR *ppdispatch) PURE;
580 STDMETHOD(get_WindowlessVideo)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
581 STDMETHOD(put_WindowlessVideo)(VARIANT_BOOL pbool) PURE;
582 STDMETHOD(Play)(void) PURE;
583 STDMETHOD(Stop)(void) PURE;
584 STDMETHOD(Pause)(void) PURE;
585 STDMETHOD(GetMarkerTime)(long MarkerNum,
586 double __RPC_FAR *pMarkerTime) PURE;
587 STDMETHOD(GetMarkerName)(long MarkerNum,
588 BSTR __RPC_FAR *pbstrMarkerName) PURE;
589 STDMETHOD(AboutBox)(void) PURE;
590 STDMETHOD(GetCodecInstalled)(long CodecNum,
591 VARIANT_BOOL __RPC_FAR *pCodecInstalled) PURE;
592 STDMETHOD(GetCodecDescription)(long CodecNum,
593 BSTR __RPC_FAR *pbstrCodecDescription) PURE;
594 STDMETHOD(GetCodecURL)(long CodecNum,
595 BSTR __RPC_FAR *pbstrCodecURL) PURE;
596 STDMETHOD(GetMoreInfoURL)(MPMoreInfoType MoreInfoType,
597 BSTR __RPC_FAR *pbstrMoreInfoURL) PURE;
598 STDMETHOD(GetMediaInfoString)(MPMediaInfoType MediaInfoType,
599 BSTR __RPC_FAR *pbstrMediaInfo) PURE;
600 STDMETHOD(Cancel)(void) PURE;
601 STDMETHOD(Open)(BSTR bstrFileName) PURE;
602 STDMETHOD(IsSoundCardEnabled)(VARIANT_BOOL __RPC_FAR *pbSoundCard) PURE;
603 STDMETHOD(Next)(void) PURE;
604 STDMETHOD(Previous)(void) PURE;
605 STDMETHOD(StreamSelect)(long StreamNum) PURE;
606 STDMETHOD(FastForward)(void) PURE;
607 STDMETHOD(FastReverse)(void) PURE;
608 STDMETHOD(GetStreamName)(long StreamNum,
609 BSTR __RPC_FAR *pbstrStreamName) PURE;
610 STDMETHOD(GetStreamGroup)(long StreamNum,
611 long __RPC_FAR *pStreamGroup) PURE;
612 STDMETHOD(GetStreamSelected)(long StreamNum, VARIANT_BOOL __RPC_FAR *pStreamSelected) PURE;
613 };
614
615 struct IMediaPlayer2 : public IMediaPlayer
616 {
617 STDMETHOD(get_DVD)(struct IMediaPlayerDvd __RPC_FAR *__RPC_FAR *ppdispatch) PURE;
618 STDMETHOD(GetMediaParameter)(long EntryNum, BSTR bstrParameterName, BSTR __RPC_FAR *pbstrParameterValue) PURE;
619 STDMETHOD(GetMediaParameterName(long EntryNum, long Index, BSTR __RPC_FAR *pbstrParameterName) PURE;
620 STDMETHOD(get_EntryCount)(long __RPC_FAR *pNumberEntries) PURE;
621 STDMETHOD(GetCurrentEntry)(long __RPC_FAR *pEntryNumber) PURE;
622 STDMETHOD(SetCurrentEntry)(long EntryNumber) PURE;
623 STDMETHOD(ShowDialog)(MPShowDialogConstants mpDialogIndex) PURE;
624 };
625
626 //---------------------------------------------------------------------------
627 // NETSHOW COM INTERFACES (dumped from nscompat.idl from MSVC COM Browser)
628 //---------------------------------------------------------------------------
629
630 struct INSOPlay : public IDispatch
631 {
632 STDMETHOD(get_ImageSourceWidth)(long __RPC_FAR *pWidth) PURE;
633 STDMETHOD(get_ImageSourceHeight)(long __RPC_FAR *pHeight) PURE;
634 STDMETHOD(get_Duration)(double __RPC_FAR *pDuration) PURE;
635 STDMETHOD(get_Author)(BSTR __RPC_FAR *pbstrAuthor) PURE;
636 STDMETHOD(get_Copyright)(BSTR __RPC_FAR *pbstrCopyright) PURE;
637 STDMETHOD(get_Description)(BSTR __RPC_FAR *pbstrDescription) PURE;
638 STDMETHOD(get_Rating)(BSTR __RPC_FAR *pbstrRating) PURE;
639 STDMETHOD(get_Title)(BSTR __RPC_FAR *pbstrTitle) PURE;
640 STDMETHOD(get_SourceLink)(BSTR __RPC_FAR *pbstrSourceLink) PURE;
641 STDMETHOD(get_MarkerCount)(long __RPC_FAR *pMarkerCount) PURE;
642 STDMETHOD(get_CanScan)(VARIANT_BOOL __RPC_FAR *pCanScan) PURE;
643 STDMETHOD(get_CanSeek)(VARIANT_BOOL __RPC_FAR *pCanSeek) PURE;
644 STDMETHOD(get_CanSeekToMarkers)(VARIANT_BOOL __RPC_FAR *pCanSeekToMarkers) PURE;
645 STDMETHOD(get_CreationDate)(DATE __RPC_FAR *pCreationDate) PURE;
646 STDMETHOD(get_Bandwidth)(long __RPC_FAR *pBandwidth) PURE;
647 STDMETHOD(get_ErrorCorrection)(BSTR __RPC_FAR *pbstrErrorCorrection) PURE;
648 STDMETHOD(get_AutoStart)(VARIANT_BOOL __RPC_FAR *pAutoStart) PURE;
649 STDMETHOD(put_AutoStart)(VARIANT_BOOL pAutoStart) PURE;
650 STDMETHOD(get_AutoRewind)(VARIANT_BOOL __RPC_FAR *pAutoRewind) PURE;
651 STDMETHOD(put_AutoRewind)(VARIANT_BOOL pAutoRewind) PURE;
652 STDMETHOD(get_AllowChangeControlType)(VARIANT_BOOL __RPC_FAR *pAllowChangeControlType) PURE;
653 STDMETHOD(put_AllowChangeControlType)(VARIANT_BOOL pAllowChangeControlType) PURE;
654 STDMETHOD(get_InvokeURLs)(VARIANT_BOOL __RPC_FAR *pInvokeURLs) PURE;
655 STDMETHOD(put_InvokeURLs)(VARIANT_BOOL pInvokeURLs) PURE;
656 STDMETHOD(get_EnableContextMenu)(VARIANT_BOOL __RPC_FAR *pEnableContextMenu) PURE;
657 STDMETHOD(put_EnableContextMenu)(VARIANT_BOOL pEnableContextMenu) PURE;
658 STDMETHOD(get_TransparentAtStart)(VARIANT_BOOL __RPC_FAR *pTransparentAtStart) PURE;
659 STDMETHOD(put_TransparentAtStart)(VARIANT_BOOL pTransparentAtStart) PURE;
660 STDMETHOD(get_TransparentOnStop)(VARIANT_BOOL __RPC_FAR *pTransparentOnStop) PURE;
661 STDMETHOD(put_TransparentOnStop)(VARIANT_BOOL pTransparentOnStop) PURE;
662 STDMETHOD(get_ClickToPlay)(VARIANT_BOOL __RPC_FAR *pClickToPlay) PURE;
663 STDMETHOD(put_ClickToPlay)(VARIANT_BOOL pClickToPlay) PURE;
664 STDMETHOD(get_FileName)(BSTR __RPC_FAR *pbstrFileName) PURE;
665 STDMETHOD(put_FileName)(BSTR pbstrFileName) PURE;
666 STDMETHOD(get_CurrentPosition)(double __RPC_FAR *pCurrentPosition) PURE;
667 STDMETHOD(put_CurrentPosition)(double pCurrentPosition) PURE;
668 STDMETHOD(get_Rate)(double __RPC_FAR *pRate) PURE;
669 STDMETHOD(put_Rate)(double pRate) PURE;
670 STDMETHOD(get_CurrentMarker)(long __RPC_FAR *pCurrentMarker) PURE;
671 STDMETHOD(put_CurrentMarker)(long pCurrentMarker) PURE;
672 STDMETHOD(get_PlayCount)(long __RPC_FAR *pPlayCount) PURE;
673 STDMETHOD(put_PlayCount)(long pPlayCount) PURE;
674 STDMETHOD(get_CurrentState)(long __RPC_FAR *pCurrentState) PURE;
675 STDMETHOD(get_DisplaySize)(long __RPC_FAR *pDisplaySize) PURE;
676 STDMETHOD(put_DisplaySize)(long pDisplaySize) PURE;
677 STDMETHOD(get_MainWindow)(long __RPC_FAR *pMainWindow) PURE;
678 STDMETHOD(get_ControlType)(long __RPC_FAR *pControlType) PURE;
679 STDMETHOD(put_ControlType)(long pControlType) PURE;
680 STDMETHOD(get_AllowScan)(VARIANT_BOOL __RPC_FAR *pAllowScan) PURE;
681 STDMETHOD(put_AllowScan)(VARIANT_BOOL pAllowScan) PURE;
682 STDMETHOD(get_SendKeyboardEvents)(VARIANT_BOOL __RPC_FAR *pSendKeyboardEvents) PURE;
683 STDMETHOD(put_SendKeyboardEvents)(VARIANT_BOOL pSendKeyboardEvents) PURE;
684 STDMETHOD(get_SendMouseClickEvents)(VARIANT_BOOL __RPC_FAR *pSendMouseClickEvents) PURE;
685 STDMETHOD(put_SendMouseClickEvents)(VARIANT_BOOL pSendMouseClickEvents) PURE;
686 STDMETHOD(get_SendMouseMoveEvents)(VARIANT_BOOL __RPC_FAR *pSendMouseMoveEvents) PURE;
687 STDMETHOD(put_SendMouseMoveEvents)(VARIANT_BOOL pSendMouseMoveEvents) PURE;
688 STDMETHOD(get_SendStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendStateChangeEvents) PURE;
689 STDMETHOD(put_SendStateChangeEvents)(VARIANT_BOOL pSendStateChangeEvents) PURE;
690 STDMETHOD(get_ReceivedPackets)(long __RPC_FAR *pReceivedPackets) PURE;
691 STDMETHOD(get_RecoveredPackets)(long __RPC_FAR *pRecoveredPackets) PURE;
692 STDMETHOD(get_LostPackets)(long __RPC_FAR *pLostPackets) PURE;
693 STDMETHOD(get_ReceptionQuality)(long __RPC_FAR *pReceptionQuality) PURE;
694 STDMETHOD(get_BufferingCount)(long __RPC_FAR *pBufferingCount) PURE;
695 STDMETHOD(get_CursorType)(long __RPC_FAR *pCursorType) PURE;
696 STDMETHOD(put_CursorType)(long pCursorType) PURE;
697 STDMETHOD(get_AnimationAtStart)(VARIANT_BOOL __RPC_FAR *pAnimationAtStart) PURE;
698 STDMETHOD(put_AnimationAtStart)(VARIANT_BOOL pAnimationAtStart) PURE;
699 STDMETHOD(get_AnimationOnStop)(VARIANT_BOOL __RPC_FAR *pAnimationOnStop) PURE;
700 STDMETHOD(put_AnimationOnStop)(VARIANT_BOOL pAnimationOnStop) PURE;
701 STDMETHOD(Play)(void) PURE;
702 STDMETHOD(Pause)(void) PURE;
703 STDMETHOD(Stop)(void) PURE;
704 STDMETHOD(GetMarkerTime)(long MarkerNum, double __RPC_FAR *pMarkerTime) PURE;
705 STDMETHOD(GetMarkerName)(long MarkerNum, BSTR __RPC_FAR *pbstrMarkerName) PURE;
706 };
707
708 struct INSPlay : public INSOPlay
709 {
710 STDMETHOD(get_ChannelName)(BSTR __RPC_FAR *pbstrChannelName) PURE;
711 STDMETHOD(get_ChannelDescription)(BSTR __RPC_FAR *pbstrChannelDescription) PURE;
712 STDMETHOD(get_ChannelURL)(BSTR __RPC_FAR *pbstrChannelURL) PURE;
713 STDMETHOD(get_ContactAddress)(BSTR __RPC_FAR *pbstrContactAddress) PURE;
714 STDMETHOD(get_ContactPhone)(BSTR __RPC_FAR *pbstrContactPhone) PURE;
715 STDMETHOD(get_ContactEmail)(BSTR __RPC_FAR *pbstrContactEmail) PURE;
716 STDMETHOD(get_AllowChangeDisplaySize)(VARIANT_BOOL __RPC_FAR *pAllowChangeDisplaySize) PURE;
717 STDMETHOD(put_AllowChangeDisplaySize)(VARIANT_BOOL pAllowChangeDisplaySize) PURE;
718 STDMETHOD(get_CodecCount)(long __RPC_FAR *pCodecCount) PURE;
719 STDMETHOD(get_IsBroadcast)(VARIANT_BOOL __RPC_FAR *pIsBroadcast) PURE;
720 STDMETHOD(get_IsDurationValid)(VARIANT_BOOL __RPC_FAR *pIsDurationValid) PURE;
721 STDMETHOD(get_SourceProtocol)(long __RPC_FAR *pSourceProtocol) PURE;
722 STDMETHOD(get_OpenState)(long __RPC_FAR *pOpenState) PURE;
723 STDMETHOD(get_SendOpenStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendOpenStateChangeEvents) PURE;
724 STDMETHOD(put_SendOpenStateChangeEvents)(VARIANT_BOOL pSendOpenStateChangeEvents) PURE;
725 STDMETHOD(get_SendWarningEvents)(VARIANT_BOOL __RPC_FAR *pSendWarningEvents) PURE;
726 STDMETHOD(put_SendWarningEvents)(VARIANT_BOOL pSendWarningEvents) PURE;
727 STDMETHOD(get_SendErrorEvents)(VARIANT_BOOL __RPC_FAR *pSendErrorEvents) PURE;
728 STDMETHOD(put_SendErrorEvents)(VARIANT_BOOL pSendErrorEvents) PURE;
729 STDMETHOD(get_HasError)(VARIANT_BOOL __RPC_FAR *pHasError) PURE;
730 STDMETHOD(get_ErrorDescription)(BSTR __RPC_FAR *pbstrErrorDescription) PURE;
731 STDMETHOD(get_ErrorCode)(long __RPC_FAR *pErrorCode) PURE;
732 STDMETHOD(get_PlayState)(long __RPC_FAR *pPlayState) PURE;
733 STDMETHOD(get_SendPlayStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendPlayStateChangeEvents) PURE;
734 STDMETHOD(put_SendPlayStateChangeEvents)(VARIANT_BOOL pSendPlayStateChangeEvents) PURE;
735 STDMETHOD(get_BufferingTime)(double __RPC_FAR *pBufferingTime) PURE;
736 STDMETHOD(put_BufferingTime)(double pBufferingTime) PURE;
737 STDMETHOD(get_UseFixedUDPPort)(VARIANT_BOOL __RPC_FAR *pUseFixedUDPPort) PURE;
738 STDMETHOD(put_UseFixedUDPPort)(VARIANT_BOOL pUseFixedUDPPort) PURE;
739 STDMETHOD(get_FixedUDPPort)(long __RPC_FAR *pFixedUDPPort) PURE;
740 STDMETHOD(put_FixedUDPPort)(long pFixedUDPPort) PURE;
741 STDMETHOD(get_UseHTTPProxy)(VARIANT_BOOL __RPC_FAR *pUseHTTPProxy) PURE;
742 STDMETHOD(put_UseHTTPProxy)(VARIANT_BOOL pUseHTTPProxy) PURE;
743 STDMETHOD(get_EnableAutoProxy)(VARIANT_BOOL __RPC_FAR *pEnableAutoProxy) PURE;
744 STDMETHOD(put_EnableAutoProxy)(VARIANT_BOOL pEnableAutoProxy) PURE;
745 STDMETHOD(get_HTTPProxyHost)(BSTR __RPC_FAR *pbstrHTTPProxyHost) PURE;
746 STDMETHOD(put_HTTPProxyHost)(BSTR pbstrHTTPProxyHost) PURE;
747 STDMETHOD(get_HTTPProxyPort)(long __RPC_FAR *pHTTPProxyPort) PURE;
748 STDMETHOD(put_HTTPProxyPort)(long pHTTPProxyPort) PURE;
749 STDMETHOD(get_EnableMulticast)(VARIANT_BOOL __RPC_FAR *pEnableMulticast) PURE;
750 STDMETHOD(put_EnableMulticast)(VARIANT_BOOL pEnableMulticast) PURE;
751 STDMETHOD(get_EnableUDP)(VARIANT_BOOL __RPC_FAR *pEnableUDP) PURE;
752 STDMETHOD(put_EnableUDP)(VARIANT_BOOL pEnableUDP) PURE;
753 STDMETHOD(get_EnableTCP)(VARIANT_BOOL __RPC_FAR *pEnableTCP) PURE;
754 STDMETHOD(put_EnableTCP)(VARIANT_BOOL pEnableTCP) PURE;
755 STDMETHOD(get_EnableHTTP)(VARIANT_BOOL __RPC_FAR *pEnableHTTP) PURE;
756 STDMETHOD(put_EnableHTTP)(VARIANT_BOOL pEnableHTTP) PURE;
757 STDMETHOD(get_BufferingProgress)(long __RPC_FAR *pBufferingProgress) PURE;
758 STDMETHOD(get_BaseURL)(BSTR __RPC_FAR *pbstrBaseURL) PURE;
759 STDMETHOD(put_BaseURL)(BSTR pbstrBaseURL) PURE;
760 STDMETHOD(get_DefaultFrame)(BSTR __RPC_FAR *pbstrDefaultFrame) PURE;
761 STDMETHOD(put_DefaultFrame)(BSTR pbstrDefaultFrame) PURE;
762 STDMETHOD(AboutBox))(void) PURE;
763 STDMETHOD(Cancel)(void) PURE;
764 STDMETHOD(GetCodecInstalled)(long CodecNum, VARIANT_BOOL __RPC_FAR *pCodecInstalled) PURE;
765 STDMETHOD(GetCodecDescription)(long CodecNum, BSTR __RPC_FAR *pbstrCodecDescription) PURE;
766 STDMETHOD(GetCodecURL)(long CodecNum, BSTR __RPC_FAR *pbstrCodecURL) PURE;
767 STDMETHOD(Open)(BSTR bstrFileName) PURE;
768 };
769
770
771 struct INSPlay1 : public INSPlay
772 {
773 STDMETHOD(get_MediaPlayer)(IDispatch __RPC_FAR *__RPC_FAR *ppdispatch) PURE;
774 };
775
776 //---------------------------------------------------------------------------
777 // MISC COM INTERFACES
778 //---------------------------------------------------------------------------
779 typedef enum _FilterState
780 {
781 State_Stopped,
782 State_Paused,
783 State_Running
784 } FILTER_STATE;
785 typedef enum _PinDirection {
786 PINDIR_INPUT,
787 PINDIR_OUTPUT
788 } PIN_DIRECTION;
789
790 typedef struct _FilterInfo {
791 WCHAR achName[128];
792 struct IFilterGraph *pGraph;
793 } FILTER_INFO;
794
795 typedef struct _PinInfo {
796 struct IBaseFilter *pFilter;
797 PIN_DIRECTION dir;
798 WCHAR achName[128];
799 } PIN_INFO;
800
801 struct IBaseFilter;
802 struct IPin;
803 struct IEnumFilters;
804 typedef struct _MediaType {
805 GUID majortype;
806 GUID subtype;
807 BOOL bFixedSizeSamples;
808 BOOL bTemporalCompression;
809 ULONG lSampleSize;
810 GUID formattype;
811 IUnknown *pUnk;
812 ULONG cbFormat;
813 BYTE *pbFormat;
814 } AM_MEDIA_TYPE;
815
816 struct IFilterGraph : public IUnknown
817 {
818 STDMETHOD(AddFilter)(IBaseFilter *, LPCWSTR) PURE;
819 STDMETHOD(RemoveFilter)(IBaseFilter *) PURE;
820 STDMETHOD(EnumFilters)(IEnumFilters **) PURE;
821 STDMETHOD(FindFilterByName)(LPCWSTR, IBaseFilter **) PURE;
822 STDMETHOD(ConnectDirect)(IPin *, IPin *, const AM_MEDIA_TYPE *) PURE;
823 STDMETHOD(Reconnect)(IPin *) PURE;
824 STDMETHOD(Disconnect)(IPin *) PURE;
825 STDMETHOD(SetDefaultSyncSource)() PURE;
826 };
827
828 struct IGraphBuilder : public IFilterGraph
829 {
830 STDMETHOD(Connect)(IPin *, IPin *) PURE;
831 STDMETHOD(Render)(IPin *) PURE;
832 STDMETHOD(RenderFile)(LPCWSTR, LPCWSTR) PURE;
833 STDMETHOD(AddSourceFilter)(LPCWSTR, LPCWSTR, IBaseFilter **) PURE;
834 STDMETHOD(SetLogFile)(DWORD_PTR) PURE;
835 STDMETHOD(Abort)() PURE;
836 STDMETHOD(ShouldOperationContinue)() PURE;
837 };
838
839 struct IReferenceClock;
840 struct IEnumPins;
841 #define REFERENCE_TIME LONGLONG
842 struct IMediaFilter : public IPersist
843 {
844 STDMETHOD(Stop)( void) PURE;
845 STDMETHOD(Pause)( void) PURE;
846 STDMETHOD(Run)(REFERENCE_TIME tStart) PURE;
847 STDMETHOD(GetState)(DWORD dwMilliSecsTimeout,
848 FILTER_STATE *State) PURE;
849 STDMETHOD(SetSyncSource)(IReferenceClock *pClock) PURE;
850 STDMETHOD(GetSyncSource)(IReferenceClock **pClock) PURE;
851 };
852
853 struct IBaseFilter : public IMediaFilter
854 {
855 STDMETHOD(EnumPins)(IEnumPins **ppEnum) PURE;
856 STDMETHOD(FindPin)(LPCWSTR Id, IPin **ppPin) PURE;
857 STDMETHOD(QueryFilterInfo)(FILTER_INFO *pInfo) PURE;
858 STDMETHOD(JoinFilterGraph)(IFilterGraph *pGraph, LPCWSTR pName) PURE;
859 STDMETHOD(QueryVendorInfo)(LPWSTR *pVendorInfo) PURE;
860 };
861
862 //---------------------------------------------------------------------------
863 //
864 // wxActiveX (Ryan Norton's version :))
865 // wxActiveX is (C) 2003 Lindsay Mathieson
866 //
867 //---------------------------------------------------------------------------
868 #define WX_DECLARE_AUTOOLE(wxAutoOleInterface, I) \
869 class wxAutoOleInterface \
870 { \
871 protected: \
872 I *m_interface; \
873 \
874 public: \
875 explicit wxAutoOleInterface(I *pInterface = NULL) : m_interface(pInterface) {} \
876 wxAutoOleInterface(REFIID riid, IUnknown *pUnk) : m_interface(NULL) \
877 { QueryInterface(riid, pUnk); } \
878 wxAutoOleInterface(REFIID riid, IDispatch *pDispatch) : m_interface(NULL) \
879 { QueryInterface(riid, pDispatch); } \
880 wxAutoOleInterface(REFCLSID clsid, REFIID riid) : m_interface(NULL)\
881 { CreateInstance(clsid, riid); }\
882 wxAutoOleInterface(const wxAutoOleInterface& ti) : m_interface(NULL)\
883 { operator = (ti); }\
884 \
885 wxAutoOleInterface& operator = (const wxAutoOleInterface& ti)\
886 {\
887 if (ti.m_interface)\
888 ti.m_interface->AddRef();\
889 Free();\
890 m_interface = ti.m_interface;\
891 return *this;\
892 }\
893 \
894 wxAutoOleInterface& operator = (I *&ti)\
895 {\
896 Free();\
897 m_interface = ti;\
898 return *this;\
899 }\
900 \
901 ~wxAutoOleInterface() { Free(); }\
902 \
903 inline void Free()\
904 {\
905 if (m_interface)\
906 m_interface->Release();\
907 m_interface = NULL;\
908 }\
909 \
910 HRESULT QueryInterface(REFIID riid, IUnknown *pUnk)\
911 {\
912 Free();\
913 wxASSERT(pUnk != NULL);\
914 return pUnk->QueryInterface(riid, (void **) &m_interface);\
915 }\
916 \
917 HRESULT CreateInstance(REFCLSID clsid, REFIID riid)\
918 {\
919 Free();\
920 return CoCreateInstance(clsid, NULL, CLSCTX_ALL, riid, (void **) &m_interface);\
921 }\
922 \
923 inline operator I *() const {return m_interface;}\
924 inline I* operator ->() {return m_interface;}\
925 inline I** GetRef() {return &m_interface;}\
926 inline bool Ok() const {return m_interface != NULL;}\
927 };
928
929 WX_DECLARE_AUTOOLE(wxAutoIDispatch, IDispatch)
930 WX_DECLARE_AUTOOLE(wxAutoIOleClientSite, IOleClientSite)
931 WX_DECLARE_AUTOOLE(wxAutoIUnknown, IUnknown)
932 WX_DECLARE_AUTOOLE(wxAutoIOleObject, IOleObject)
933 WX_DECLARE_AUTOOLE(wxAutoIOleInPlaceObject, IOleInPlaceObject)
934 WX_DECLARE_AUTOOLE(wxAutoIOleInPlaceActiveObject, IOleInPlaceActiveObject)
935 WX_DECLARE_AUTOOLE(wxAutoIOleDocumentView, IOleDocumentView)
936 WX_DECLARE_AUTOOLE(wxAutoIViewObject, IViewObject)
937 WX_DECLARE_AUTOOLE(wxAutoIOleInPlaceSite, IOleInPlaceSite)
938 WX_DECLARE_AUTOOLE(wxAutoIOleDocument, IOleDocument)
939 WX_DECLARE_AUTOOLE(wxAutoIPersistStreamInit, IPersistStreamInit)
940 WX_DECLARE_AUTOOLE(wxAutoIAdviseSink, IAdviseSink)
941
942 class wxActiveX : public wxWindow
943 {
944 public:
945 wxActiveX(wxWindow * parent, REFIID iid, IUnknown* pUnk);
946 virtual ~wxActiveX();
947
948 void OnSize(wxSizeEvent&);
949 void OnPaint(wxPaintEvent&);
950 void OnSetFocus(wxFocusEvent&);
951 void OnKillFocus(wxFocusEvent&);
952
953 protected:
954 friend class FrameSite;
955
956 wxAutoIDispatch m_Dispatch;
957 wxAutoIOleClientSite m_clientSite;
958 wxAutoIUnknown m_ActiveX;
959 wxAutoIOleObject m_oleObject;
960 wxAutoIOleInPlaceObject m_oleInPlaceObject;
961 wxAutoIOleInPlaceActiveObject m_oleInPlaceActiveObject;
962 wxAutoIOleDocumentView m_docView;
963 wxAutoIViewObject m_viewObject;
964 HWND m_oleObjectHWND;
965 bool m_bAmbientUserMode;
966 DWORD m_docAdviseCookie;
967 wxWindow* m_realparent;
968
969 void CreateActiveX(REFIID, IUnknown*);
970 };
971
972 #define DECLARE_OLE_UNKNOWN(cls)\
973 private:\
974 class TAutoInitInt\
975 {\
976 public:\
977 LONG l;\
978 TAutoInitInt() : l(0) {}\
979 };\
980 TAutoInitInt refCount, lockCount;\
981 static void _GetInterface(cls *self, REFIID iid, void **_interface, const char *&desc);\
982 public:\
983 LONG GetRefCount();\
984 HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void ** ppvObject);\
985 ULONG STDMETHODCALLTYPE AddRef();\
986 ULONG STDMETHODCALLTYPE Release();\
987 ULONG STDMETHODCALLTYPE AddLock();\
988 ULONG STDMETHODCALLTYPE ReleaseLock()
989
990 #define DEFINE_OLE_TABLE(cls)\
991 LONG cls::GetRefCount() {return refCount.l;}\
992 HRESULT STDMETHODCALLTYPE cls::QueryInterface(REFIID iid, void ** ppvObject)\
993 {\
994 if (! ppvObject)\
995 {\
996 return E_FAIL;\
997 };\
998 const char *desc = NULL;\
999 cls::_GetInterface(this, iid, ppvObject, desc);\
1000 if (! *ppvObject)\
1001 {\
1002 return E_NOINTERFACE;\
1003 };\
1004 ((IUnknown * )(*ppvObject))->AddRef();\
1005 return S_OK;\
1006 };\
1007 ULONG STDMETHODCALLTYPE cls::AddRef()\
1008 {\
1009 InterlockedIncrement(&refCount.l);\
1010 return refCount.l;\
1011 };\
1012 ULONG STDMETHODCALLTYPE cls::Release()\
1013 {\
1014 if (refCount.l > 0)\
1015 {\
1016 InterlockedDecrement(&refCount.l);\
1017 if (refCount.l == 0)\
1018 {\
1019 delete this;\
1020 return 0;\
1021 };\
1022 return refCount.l;\
1023 }\
1024 else\
1025 return 0;\
1026 }\
1027 ULONG STDMETHODCALLTYPE cls::AddLock()\
1028 {\
1029 InterlockedIncrement(&lockCount.l);\
1030 return lockCount.l;\
1031 };\
1032 ULONG STDMETHODCALLTYPE cls::ReleaseLock()\
1033 {\
1034 if (lockCount.l > 0)\
1035 {\
1036 InterlockedDecrement(&lockCount.l);\
1037 return lockCount.l;\
1038 }\
1039 else\
1040 return 0;\
1041 }\
1042 DEFINE_OLE_BASE(cls)
1043
1044 #define DEFINE_OLE_BASE(cls)\
1045 void cls::_GetInterface(cls *self, REFIID iid, void **_interface, const char *&desc)\
1046 {\
1047 *_interface = NULL;\
1048 desc = NULL;
1049
1050 #define OLE_INTERFACE(_iid, _type)\
1051 if (IsEqualIID(iid, _iid))\
1052 {\
1053 *_interface = (IUnknown *) (_type *) self;\
1054 desc = # _iid;\
1055 return;\
1056 }
1057
1058 #define OLE_IINTERFACE(_face) OLE_INTERFACE(IID_##_face, _face)
1059
1060 #define OLE_INTERFACE_CUSTOM(func)\
1061 if (func(self, iid, _interface, desc))\
1062 {\
1063 return;\
1064 }
1065
1066 #define END_OLE_TABLE\
1067 }
1068
1069
1070 class FrameSite :
1071 public IOleClientSite,
1072 public IOleInPlaceSiteEx,
1073 public IOleInPlaceFrame,
1074 public IOleItemContainer,
1075 public IDispatch,
1076 public IOleCommandTarget,
1077 public IOleDocumentSite,
1078 public IAdviseSink,
1079 public IOleControlSite
1080 {
1081 private:
1082 DECLARE_OLE_UNKNOWN(FrameSite);
1083
1084 public:
1085 FrameSite(wxWindow * win, wxActiveX * win2)
1086 {
1087 m_window = win2;
1088 m_bSupportsWindowlessActivation = true;
1089 m_bInPlaceLocked = false;
1090 m_bUIActive = false;
1091 m_bInPlaceActive = false;
1092 m_bWindowless = false;
1093
1094 m_nAmbientLocale = 0;
1095 m_clrAmbientForeColor = ::GetSysColor(COLOR_WINDOWTEXT);
1096 m_clrAmbientBackColor = ::GetSysColor(COLOR_WINDOW);
1097 m_bAmbientShowHatching = true;
1098 m_bAmbientShowGrabHandles = true;
1099 m_bAmbientAppearance = true;
1100
1101 m_hDCBuffer = NULL;
1102 m_hWndParent = (HWND)win->GetHWND();
1103 }
1104 virtual ~FrameSite(){}
1105 //***************************IDispatch*****************************
1106 HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID, OLECHAR ** ,
1107 unsigned int , LCID ,
1108 DISPID * )
1109 { return E_NOTIMPL; }
1110 STDMETHOD(GetTypeInfo)(unsigned int, LCID, ITypeInfo **)
1111 { return E_NOTIMPL; }
1112 HRESULT STDMETHODCALLTYPE GetTypeInfoCount(unsigned int *)
1113 { return E_NOTIMPL; }
1114 HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID, LCID,
1115 WORD wFlags, DISPPARAMS *,
1116 VARIANT * pVarResult, EXCEPINFO *,
1117 unsigned int *)
1118 {
1119 if (!(wFlags & DISPATCH_PROPERTYGET))
1120 return S_OK;
1121
1122 if (pVarResult == NULL)
1123 return E_INVALIDARG;
1124
1125 //The most common case is boolean, use as an initial type
1126 V_VT(pVarResult) = VT_BOOL;
1127
1128 switch (dispIdMember)
1129 {
1130 case DISPID_AMBIENT_MESSAGEREFLECT:
1131 V_BOOL(pVarResult)= FALSE;
1132 return S_OK;
1133
1134 case DISPID_AMBIENT_DISPLAYASDEFAULT:
1135 V_BOOL(pVarResult)= TRUE;
1136 return S_OK;
1137
1138 case DISPID_AMBIENT_OFFLINEIFNOTCONNECTED:
1139 V_BOOL(pVarResult) = TRUE;
1140 return S_OK;
1141
1142 case DISPID_AMBIENT_SILENT:
1143 V_BOOL(pVarResult)= TRUE;
1144 return S_OK;
1145
1146 case DISPID_AMBIENT_APPEARANCE:
1147 pVarResult->vt = VT_BOOL;
1148 pVarResult->boolVal = m_bAmbientAppearance;
1149 break;
1150
1151 case DISPID_AMBIENT_FORECOLOR:
1152 pVarResult->vt = VT_I4;
1153 pVarResult->lVal = (long) m_clrAmbientForeColor;
1154 break;
1155
1156 case DISPID_AMBIENT_BACKCOLOR:
1157 pVarResult->vt = VT_I4;
1158 pVarResult->lVal = (long) m_clrAmbientBackColor;
1159 break;
1160
1161 case DISPID_AMBIENT_LOCALEID:
1162 pVarResult->vt = VT_I4;
1163 pVarResult->lVal = (long) m_nAmbientLocale;
1164 break;
1165
1166 case DISPID_AMBIENT_USERMODE:
1167 pVarResult->vt = VT_BOOL;
1168 pVarResult->boolVal = m_window->m_bAmbientUserMode;
1169 break;
1170
1171 case DISPID_AMBIENT_SHOWGRABHANDLES:
1172 pVarResult->vt = VT_BOOL;
1173 pVarResult->boolVal = m_bAmbientShowGrabHandles;
1174 break;
1175
1176 case DISPID_AMBIENT_SHOWHATCHING:
1177 pVarResult->vt = VT_BOOL;
1178 pVarResult->boolVal = m_bAmbientShowHatching;
1179 break;
1180
1181 default:
1182 return DISP_E_MEMBERNOTFOUND;
1183 }
1184
1185 return S_OK;
1186 }
1187
1188 //**************************IOleWindow***************************
1189 HRESULT STDMETHODCALLTYPE GetWindow(HWND * phwnd)
1190 {
1191 if (phwnd == NULL)
1192 return E_INVALIDARG;
1193 (*phwnd) = m_hWndParent;
1194 return S_OK;
1195 }
1196 HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL)
1197 {return S_OK;}
1198 //**************************IOleInPlaceUIWindow*****************
1199 HRESULT STDMETHODCALLTYPE GetBorder(LPRECT lprectBorder)
1200 {
1201 if (lprectBorder == NULL)
1202 return E_INVALIDARG;
1203 return INPLACE_E_NOTOOLSPACE;
1204 }
1205 HRESULT STDMETHODCALLTYPE RequestBorderSpace(LPCBORDERWIDTHS pborderwidths)
1206 {
1207 if (pborderwidths == NULL)
1208 return E_INVALIDARG;
1209 return INPLACE_E_NOTOOLSPACE;
1210 }
1211 HRESULT STDMETHODCALLTYPE SetBorderSpace(LPCBORDERWIDTHS)
1212 {return S_OK;}
1213 HRESULT STDMETHODCALLTYPE SetActiveObject(
1214 IOleInPlaceActiveObject *pActiveObject, LPCOLESTR)
1215 {
1216 if (pActiveObject)
1217 pActiveObject->AddRef();
1218
1219 m_window->m_oleInPlaceActiveObject = pActiveObject;
1220 return S_OK;
1221 }
1222
1223 //********************IOleInPlaceFrame************************
1224
1225 STDMETHOD(InsertMenus)(HMENU, LPOLEMENUGROUPWIDTHS){return S_OK;}
1226 STDMETHOD(SetMenu)(HMENU, HOLEMENU, HWND){ return S_OK;}
1227 STDMETHOD(RemoveMenus)(HMENU){return S_OK;}
1228 STDMETHOD(SetStatusText)(LPCOLESTR){ return S_OK;}
1229 HRESULT STDMETHODCALLTYPE EnableModeless(BOOL){return S_OK;}
1230 HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpmsg, WORD)
1231 {
1232 // TODO: send an event with this id
1233 if (m_window->m_oleInPlaceActiveObject.Ok())
1234 m_window->m_oleInPlaceActiveObject->TranslateAccelerator(lpmsg);
1235 return S_FALSE;
1236 }
1237
1238 //*******************IOleInPlaceSite**************************
1239 HRESULT STDMETHODCALLTYPE CanInPlaceActivate(){return S_OK;}
1240 HRESULT STDMETHODCALLTYPE OnInPlaceActivate()
1241 { m_bInPlaceActive = true; return S_OK; }
1242 HRESULT STDMETHODCALLTYPE OnUIActivate()
1243 { m_bUIActive = true; return S_OK; }
1244 HRESULT STDMETHODCALLTYPE GetWindowContext(IOleInPlaceFrame **ppFrame,
1245 IOleInPlaceUIWindow **ppDoc,
1246 LPRECT lprcPosRect,
1247 LPRECT lprcClipRect,
1248 LPOLEINPLACEFRAMEINFO lpFrameInfo)
1249 {
1250 if (ppFrame == NULL || ppDoc == NULL || lprcPosRect == NULL ||
1251 lprcClipRect == NULL || lpFrameInfo == NULL)
1252 {
1253 if (ppFrame != NULL)
1254 (*ppFrame) = NULL;
1255 if (ppDoc != NULL)
1256 (*ppDoc) = NULL;
1257 return E_INVALIDARG;
1258 }
1259
1260 HRESULT hr = QueryInterface(IID_IOleInPlaceFrame, (void **) ppFrame);
1261 if (! SUCCEEDED(hr))
1262 {
1263 return E_UNEXPECTED;
1264 };
1265
1266 hr = QueryInterface(IID_IOleInPlaceUIWindow, (void **) ppDoc);
1267 if (! SUCCEEDED(hr))
1268 {
1269 (*ppFrame)->Release();
1270 *ppFrame = NULL;
1271 return E_UNEXPECTED;
1272 };
1273
1274 RECT rect;
1275 ::GetClientRect(m_hWndParent, &rect);
1276 if (lprcPosRect)
1277 {
1278 lprcPosRect->left = lprcPosRect->top = 0;
1279 lprcPosRect->right = rect.right;
1280 lprcPosRect->bottom = rect.bottom;
1281 };
1282 if (lprcClipRect)
1283 {
1284 lprcClipRect->left = lprcClipRect->top = 0;
1285 lprcClipRect->right = rect.right;
1286 lprcClipRect->bottom = rect.bottom;
1287 };
1288
1289 memset(lpFrameInfo, 0, sizeof(OLEINPLACEFRAMEINFO));
1290 lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO);
1291 lpFrameInfo->hwndFrame = m_hWndParent;
1292
1293 return S_OK;
1294 }
1295 HRESULT STDMETHODCALLTYPE Scroll(SIZE){return S_OK;}
1296 HRESULT STDMETHODCALLTYPE OnUIDeactivate(BOOL)
1297 { m_bUIActive = false; return S_OK; }
1298 HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate()
1299 { m_bInPlaceActive = false; return S_OK; }
1300 HRESULT STDMETHODCALLTYPE DiscardUndoState(){return S_OK;}
1301 HRESULT STDMETHODCALLTYPE DeactivateAndUndo(){return S_OK; }
1302 HRESULT STDMETHODCALLTYPE OnPosRectChange(LPCRECT lprcPosRect)
1303 {
1304 if (m_window->m_oleInPlaceObject.Ok() && lprcPosRect)
1305 {
1306 m_window->m_oleInPlaceObject->SetObjectRects(
1307 lprcPosRect, lprcPosRect);
1308 }
1309 return S_OK;
1310 }
1311 //*************************IOleInPlaceSiteEx***********************
1312 HRESULT STDMETHODCALLTYPE OnInPlaceActivateEx(BOOL * pfNoRedraw, DWORD)
1313 {
1314 OleLockRunning(m_window->m_ActiveX, TRUE, FALSE);
1315 if (pfNoRedraw)
1316 (*pfNoRedraw) = FALSE;
1317 return S_OK;
1318 }
1319
1320 HRESULT STDMETHODCALLTYPE OnInPlaceDeactivateEx(BOOL)
1321 {
1322 OleLockRunning(m_window->m_ActiveX, FALSE, FALSE);
1323 return S_OK;
1324 }
1325 STDMETHOD(RequestUIActivate)(){ return S_OK;}
1326 //*************************IOleClientSite**************************
1327 HRESULT STDMETHODCALLTYPE SaveObject(){return S_OK;}
1328 const char *OleGetMonikerToStr(DWORD dwAssign)
1329 {
1330 switch (dwAssign)
1331 {
1332 case OLEGETMONIKER_ONLYIFTHERE : return "OLEGETMONIKER_ONLYIFTHERE";
1333 case OLEGETMONIKER_FORCEASSIGN : return "OLEGETMONIKER_FORCEASSIGN";
1334 case OLEGETMONIKER_UNASSIGN : return "OLEGETMONIKER_UNASSIGN";
1335 case OLEGETMONIKER_TEMPFORUSER : return "OLEGETMONIKER_TEMPFORUSER";
1336 default : return "Bad Enum";
1337 };
1338 };
1339
1340 const char *OleGetWhicMonikerStr(DWORD dwWhichMoniker)
1341 {
1342 switch(dwWhichMoniker)
1343 {
1344 case OLEWHICHMK_CONTAINER : return "OLEWHICHMK_CONTAINER";
1345 case OLEWHICHMK_OBJREL : return "OLEWHICHMK_OBJREL";
1346 case OLEWHICHMK_OBJFULL : return "OLEWHICHMK_OBJFULL";
1347 default : return "Bad Enum";
1348 };
1349 };
1350 STDMETHOD(GetMoniker)(DWORD, DWORD, IMoniker **){return E_FAIL;}
1351 HRESULT STDMETHODCALLTYPE GetContainer(LPOLECONTAINER * ppContainer)
1352 {
1353 if (ppContainer == NULL)
1354 return E_INVALIDARG;
1355 HRESULT hr = QueryInterface(
1356 IID_IOleContainer, (void**)(ppContainer));
1357 wxASSERT(SUCCEEDED(hr));
1358 return hr;
1359 }
1360 HRESULT STDMETHODCALLTYPE ShowObject()
1361 {
1362 if (m_window->m_oleObjectHWND)
1363 ::ShowWindow(m_window->m_oleObjectHWND, SW_SHOW);
1364 return S_OK;
1365 }
1366 STDMETHOD(OnShowWindow)(BOOL){return S_OK;}
1367 STDMETHOD(RequestNewObjectLayout)(){return E_NOTIMPL;}
1368 //********************IParseDisplayName***************************
1369 HRESULT STDMETHODCALLTYPE ParseDisplayName(
1370 IBindCtx *, LPOLESTR, ULONG *, IMoniker **){return E_NOTIMPL;}
1371 //********************IOleContainer*******************************
1372 STDMETHOD(EnumObjects)(DWORD, IEnumUnknown **){return E_NOTIMPL;}
1373 HRESULT STDMETHODCALLTYPE LockContainer(BOOL){return S_OK;}
1374 //********************IOleItemContainer***************************
1375 HRESULT STDMETHODCALLTYPE
1376 #ifdef _UNICODE
1377 GetObjectW
1378 #else
1379 GetObjectA
1380 #endif
1381 (LPOLESTR pszItem, DWORD, IBindCtx *, REFIID, void ** ppvObject)
1382 {
1383 if (pszItem == NULL || ppvObject == NULL)
1384 return E_INVALIDARG;
1385 *ppvObject = NULL;
1386 return MK_E_NOOBJECT;
1387 }
1388 HRESULT STDMETHODCALLTYPE GetObjectStorage(
1389 LPOLESTR pszItem, IBindCtx * , REFIID, void ** ppvStorage)
1390 {
1391 if (pszItem == NULL || ppvStorage == NULL)
1392 return E_INVALIDARG;
1393 *ppvStorage = NULL;
1394 return MK_E_NOOBJECT;
1395 }
1396 HRESULT STDMETHODCALLTYPE IsRunning(LPOLESTR pszItem)
1397 {
1398 if (pszItem == NULL)
1399 return E_INVALIDARG;
1400 return MK_E_NOOBJECT;
1401 }
1402 //***********************IOleControlSite*****************************
1403 HRESULT STDMETHODCALLTYPE OnControlInfoChanged()
1404 {return S_OK;}
1405 HRESULT STDMETHODCALLTYPE LockInPlaceActive(BOOL fLock)
1406 {
1407 m_bInPlaceLocked = (fLock) ? true : false;
1408 return S_OK;
1409 }
1410 HRESULT STDMETHODCALLTYPE GetExtendedControl(IDispatch **)
1411 {return E_NOTIMPL;}
1412 HRESULT STDMETHODCALLTYPE TransformCoords(
1413 POINTL * pPtlHimetric, POINTF * pPtfContainer, DWORD)
1414 {
1415 if (pPtlHimetric == NULL || pPtfContainer == NULL)
1416 return E_INVALIDARG;
1417 return E_NOTIMPL;
1418 }
1419 HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG, DWORD)
1420 {return E_NOTIMPL;}
1421 HRESULT STDMETHODCALLTYPE OnFocus(BOOL){return S_OK;}
1422 HRESULT STDMETHODCALLTYPE ShowPropertyFrame(){return E_NOTIMPL;}
1423 //**************************IOleCommandTarget***********************
1424 HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *, ULONG cCmds,
1425 OLECMD * prgCmds, OLECMDTEXT *)
1426 {
1427 if (prgCmds == NULL) return E_INVALIDARG;
1428 for (ULONG nCmd = 0; nCmd < cCmds; nCmd++)
1429 {
1430 // unsupported by default
1431 prgCmds[nCmd].cmdf = 0;
1432 }
1433 return OLECMDERR_E_UNKNOWNGROUP;
1434 }
1435
1436 HRESULT STDMETHODCALLTYPE Exec(const GUID *, DWORD,
1437 DWORD, VARIANTARG *, VARIANTARG *)
1438 {return OLECMDERR_E_NOTSUPPORTED;}
1439
1440 //**********************IAdviseSink************************************
1441 void STDMETHODCALLTYPE OnDataChange(FORMATETC *, STGMEDIUM *) {}
1442 void STDMETHODCALLTYPE OnViewChange(DWORD, LONG) {}
1443 void STDMETHODCALLTYPE OnRename(IMoniker *){}
1444 void STDMETHODCALLTYPE OnSave(){}
1445 void STDMETHODCALLTYPE OnClose(){}
1446
1447 //**********************IOleDocumentSite***************************
1448 HRESULT STDMETHODCALLTYPE ActivateMe(
1449 IOleDocumentView __RPC_FAR *pViewToActivate)
1450 {
1451 wxAutoIOleInPlaceSite inPlaceSite(
1452 IID_IOleInPlaceSite, (IDispatch *) this);
1453 if (!inPlaceSite.Ok())
1454 return E_FAIL;
1455
1456 if (pViewToActivate)
1457 {
1458 m_window->m_docView = pViewToActivate;
1459 m_window->m_docView->SetInPlaceSite(inPlaceSite);
1460 }
1461 else
1462 {
1463 wxAutoIOleDocument oleDoc(
1464 IID_IOleDocument, m_window->m_oleObject);
1465 if (! oleDoc.Ok())
1466 return E_FAIL;
1467
1468 HRESULT hr = oleDoc->CreateView(inPlaceSite, NULL,
1469 0, m_window->m_docView.GetRef());
1470 if (hr != S_OK)
1471 return E_FAIL;
1472
1473 m_window->m_docView->SetInPlaceSite(inPlaceSite);
1474 };
1475
1476 m_window->m_docView->UIActivate(TRUE);
1477 return S_OK;
1478 };
1479
1480
1481 protected:
1482 wxActiveX * m_window;
1483
1484 HDC m_hDCBuffer;
1485 HWND m_hWndParent;
1486
1487 bool m_bSupportsWindowlessActivation;
1488 bool m_bInPlaceLocked;
1489 bool m_bInPlaceActive;
1490 bool m_bUIActive;
1491 bool m_bWindowless;
1492
1493 LCID m_nAmbientLocale;
1494 COLORREF m_clrAmbientForeColor;
1495 COLORREF m_clrAmbientBackColor;
1496 bool m_bAmbientShowHatching;
1497 bool m_bAmbientShowGrabHandles;
1498 bool m_bAmbientAppearance;
1499 };
1500
1501 DEFINE_OLE_TABLE(FrameSite)
1502 OLE_INTERFACE(IID_IUnknown, IOleClientSite)
1503 OLE_IINTERFACE(IOleClientSite)
1504 OLE_INTERFACE(IID_IOleWindow, IOleInPlaceSite)
1505 OLE_IINTERFACE(IOleInPlaceSite)
1506 OLE_IINTERFACE(IOleInPlaceSiteEx)
1507 OLE_IINTERFACE(IOleInPlaceUIWindow)
1508 OLE_IINTERFACE(IOleInPlaceFrame)
1509 OLE_IINTERFACE(IParseDisplayName)
1510 OLE_IINTERFACE(IOleContainer)
1511 OLE_IINTERFACE(IOleItemContainer)
1512 OLE_IINTERFACE(IDispatch)
1513 OLE_IINTERFACE(IOleCommandTarget)
1514 OLE_IINTERFACE(IOleDocumentSite)
1515 OLE_IINTERFACE(IAdviseSink)
1516 OLE_IINTERFACE(IOleControlSite)
1517 END_OLE_TABLE;
1518
1519
1520 wxActiveX::wxActiveX(wxWindow * parent, REFIID iid, IUnknown* pUnk)
1521 : m_realparent(parent)
1522 {
1523 m_bAmbientUserMode = true;
1524 m_docAdviseCookie = 0;
1525 CreateActiveX(iid, pUnk);
1526 }
1527
1528 wxActiveX::~wxActiveX()
1529 {
1530 // disconnect connection points
1531 if (m_oleInPlaceObject.Ok())
1532 {
1533 m_oleInPlaceObject->InPlaceDeactivate();
1534 m_oleInPlaceObject->UIDeactivate();
1535 }
1536
1537 if (m_oleObject.Ok())
1538 {
1539 if (m_docAdviseCookie != 0)
1540 m_oleObject->Unadvise(m_docAdviseCookie);
1541
1542 m_oleObject->DoVerb(
1543 OLEIVERB_HIDE, NULL, m_clientSite, 0, (HWND) GetHWND(), NULL);
1544 m_oleObject->Close(OLECLOSE_NOSAVE);
1545 m_oleObject->SetClientSite(NULL);
1546 }
1547 }
1548
1549 void wxActiveX::CreateActiveX(REFIID iid, IUnknown* pUnk)
1550 {
1551 HRESULT hret;
1552 hret = m_ActiveX.QueryInterface(iid, pUnk);
1553 wxASSERT(SUCCEEDED(hret));
1554
1555 // FrameSite
1556 FrameSite *frame = new FrameSite(m_realparent, this);
1557 // oleClientSite
1558 hret = m_clientSite.QueryInterface(
1559 IID_IOleClientSite, (IDispatch *) frame);
1560 wxASSERT(SUCCEEDED(hret));
1561 // adviseSink
1562 wxAutoIAdviseSink adviseSink(IID_IAdviseSink, (IDispatch *) frame);
1563 wxASSERT(adviseSink.Ok());
1564
1565 // Get Dispatch interface
1566 hret = m_Dispatch.QueryInterface(IID_IDispatch, m_ActiveX);
1567
1568 // Get IOleObject interface
1569 hret = m_oleObject.QueryInterface(IID_IOleObject, m_ActiveX);
1570 wxASSERT(SUCCEEDED(hret));
1571
1572 // get IViewObject Interface
1573 hret = m_viewObject.QueryInterface(IID_IViewObject, m_ActiveX);
1574 wxASSERT(SUCCEEDED(hret));
1575
1576 // document advise
1577 m_docAdviseCookie = 0;
1578 hret = m_oleObject->Advise(adviseSink, &m_docAdviseCookie);
1579 m_oleObject->SetHostNames(L"wxActiveXContainer", NULL);
1580 OleSetContainedObject(m_oleObject, TRUE);
1581 OleRun(m_oleObject);
1582
1583
1584 // Get IOleInPlaceObject interface
1585 hret = m_oleInPlaceObject.QueryInterface(
1586 IID_IOleInPlaceObject, m_ActiveX);
1587 wxASSERT(SUCCEEDED(hret));
1588
1589 // status
1590 DWORD dwMiscStatus;
1591 m_oleObject->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus);
1592 wxASSERT(SUCCEEDED(hret));
1593
1594 // set client site first ?
1595 if (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
1596 m_oleObject->SetClientSite(m_clientSite);
1597
1598
1599 // stream init
1600 wxAutoIPersistStreamInit
1601 pPersistStreamInit(IID_IPersistStreamInit, m_oleObject);
1602
1603 if (pPersistStreamInit.Ok())
1604 {
1605 hret = pPersistStreamInit->InitNew();
1606 }
1607
1608 if (! (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))
1609 m_oleObject->SetClientSite(m_clientSite);
1610
1611
1612 RECT posRect;
1613 ::GetClientRect((HWND)m_realparent->GetHWND(), &posRect);
1614
1615 m_oleObjectHWND = 0;
1616
1617 if (m_oleInPlaceObject.Ok())
1618 {
1619 hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND);
1620 if (SUCCEEDED(hret))
1621 ::SetActiveWindow(m_oleObjectHWND);
1622 }
1623
1624
1625 if (! (dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME))
1626 {
1627 if (posRect.right > 0 && posRect.bottom > 0 &&
1628 m_oleInPlaceObject.Ok())
1629 m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
1630
1631 hret = m_oleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL,
1632 m_clientSite, 0, (HWND)m_realparent->GetHWND(), &posRect);
1633 hret = m_oleObject->DoVerb(OLEIVERB_SHOW, 0, m_clientSite, 0,
1634 (HWND)m_realparent->GetHWND(), &posRect);
1635 }
1636
1637 if (! m_oleObjectHWND && m_oleInPlaceObject.Ok())
1638 {
1639 hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND);
1640 }
1641
1642 if (m_oleObjectHWND)
1643 {
1644 ::SetActiveWindow(m_oleObjectHWND);
1645 ::ShowWindow(m_oleObjectHWND, SW_SHOW);
1646
1647 this->AssociateHandle(m_oleObjectHWND);
1648 this->Reparent(m_realparent);
1649
1650 wxWindow* pWnd = m_realparent;
1651 int id = m_realparent->GetId();
1652
1653 pWnd->Connect(id, wxEVT_SIZE,
1654 wxSizeEventHandler(wxActiveX::OnSize), 0, this);
1655 pWnd->Connect(id, wxEVT_SET_FOCUS,
1656 wxFocusEventHandler(wxActiveX::OnSetFocus), 0, this);
1657 pWnd->Connect(id, wxEVT_KILL_FOCUS,
1658 wxFocusEventHandler(wxActiveX::OnKillFocus), 0, this);
1659 }
1660 }
1661
1662 #define HIMETRIC_PER_INCH 2540
1663 #define MAP_PIX_TO_LOGHIM(x,ppli) MulDiv(HIMETRIC_PER_INCH, (x), (ppli))
1664
1665 static void PixelsToHimetric(SIZEL &sz)
1666 {
1667 static int logX = 0;
1668 static int logY = 0;
1669
1670 if (logY == 0)
1671 {
1672 // initaliase
1673 HDC dc = GetDC(NULL);
1674 logX = GetDeviceCaps(dc, LOGPIXELSX);
1675 logY = GetDeviceCaps(dc, LOGPIXELSY);
1676 ReleaseDC(NULL, dc);
1677 };
1678
1679 #define HIMETRIC_INCH 2540
1680 #define CONVERT(x, logpixels) MulDiv(HIMETRIC_INCH, (x), (logpixels))
1681
1682 sz.cx = CONVERT(sz.cx, logX);
1683 sz.cy = CONVERT(sz.cy, logY);
1684
1685 #undef CONVERT
1686 #undef HIMETRIC_INCH
1687 }
1688
1689
1690 void wxActiveX::OnSize(wxSizeEvent& event)
1691 {
1692 int w, h;
1693 GetParent()->GetClientSize(&w, &h);
1694
1695 RECT posRect;
1696 posRect.left = 0;
1697 posRect.top = 0;
1698 posRect.right = w;
1699 posRect.bottom = h;
1700
1701 if (w <= 0 && h <= 0)
1702 return;
1703
1704 // extents are in HIMETRIC units
1705 if (m_oleObject.Ok())
1706 {
1707 SIZEL sz = {w, h};
1708 PixelsToHimetric(sz);
1709
1710 SIZEL sz2;
1711
1712 m_oleObject->GetExtent(DVASPECT_CONTENT, &sz2);
1713 if (sz2.cx != sz.cx || sz.cy != sz2.cy)
1714 m_oleObject->SetExtent(DVASPECT_CONTENT, &sz);
1715 };
1716
1717 if (m_oleInPlaceObject.Ok())
1718 m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
1719
1720 event.Skip();
1721 }
1722
1723 void wxActiveX::OnPaint(wxPaintEvent& WXUNUSED(event))
1724 {
1725 wxPaintDC dc(this);
1726 // Draw only when control is windowless or deactivated
1727 if (m_viewObject)
1728 {
1729 dc.BeginDrawing();
1730 int w, h;
1731 GetParent()->GetSize(&w, &h);
1732 RECT posRect;
1733 posRect.left = 0;
1734 posRect.top = 0;
1735 posRect.right = w;
1736 posRect.bottom = h;
1737
1738 ::RedrawWindow(m_oleObjectHWND, NULL, NULL, RDW_INTERNALPAINT);
1739 RECTL *prcBounds = (RECTL *) &posRect;
1740 m_viewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL,
1741 (HDC)dc.GetHDC(), prcBounds, NULL, NULL, 0);
1742
1743 dc.EndDrawing();
1744 }
1745
1746 // We've got this one I think
1747 // event.Skip();
1748 }
1749
1750 void wxActiveX::OnSetFocus(wxFocusEvent& event)
1751 {
1752 if (m_oleInPlaceActiveObject.Ok())
1753 m_oleInPlaceActiveObject->OnFrameWindowActivate(TRUE);
1754
1755 event.Skip();
1756 }
1757
1758 void wxActiveX::OnKillFocus(wxFocusEvent& event)
1759 {
1760 if (m_oleInPlaceActiveObject.Ok())
1761 m_oleInPlaceActiveObject->OnFrameWindowActivate(FALSE);
1762
1763 event.Skip();
1764 }
1765
1766 //###########################################################################
1767 //
1768 //
1769 // wxAMMediaBackend
1770 //
1771 //
1772 //###########################################################################
1773
1774 typedef BOOL (WINAPI* LPAMGETERRORTEXT)(HRESULT, wxChar *, DWORD);
1775
1776 //cludgy workaround for wx events. slots would be nice :)
1777 class WXDLLIMPEXP_MEDIA wxAMMediaEvtHandler : public wxEvtHandler
1778 {
1779 public:
1780 void OnPaint(wxPaintEvent&);
1781 void OnEraseBackground(wxEraseEvent&);
1782 };
1783
1784 class WXDLLIMPEXP_MEDIA wxAMMediaBackend : public wxMediaBackend
1785 {
1786 public:
1787 wxAMMediaBackend();
1788 virtual ~wxAMMediaBackend();
1789 void Clear();
1790
1791 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
1792 wxWindowID id,
1793 const wxPoint& pos,
1794 const wxSize& size,
1795 long style,
1796 const wxValidator& validator,
1797 const wxString& name);
1798
1799 virtual bool Play();
1800 virtual bool Pause();
1801 virtual bool Stop();
1802
1803 virtual bool Load(const wxString& fileName);
1804 virtual bool Load(const wxURI& location);
1805 virtual bool Load(const wxURI& location, const wxURI& proxy);
1806
1807 bool DoLoad(const wxString& location);
1808 void FinishLoad();
1809
1810 virtual wxMediaState GetState();
1811
1812 virtual bool SetPosition(wxLongLong where);
1813 virtual wxLongLong GetPosition();
1814 virtual wxLongLong GetDuration();
1815
1816 virtual void Move(int x, int y, int w, int h);
1817 wxSize GetVideoSize() const;
1818
1819 virtual double GetPlaybackRate();
1820 virtual bool SetPlaybackRate(double);
1821
1822 virtual double GetVolume();
1823 virtual bool SetVolume(double);
1824
1825 virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags);
1826 void Cleanup();
1827
1828 void DoGetDownloadProgress(wxLongLong*, wxLongLong*);
1829 virtual wxLongLong GetDownloadProgress()
1830 {
1831 wxLongLong progress, total;
1832 DoGetDownloadProgress(&progress, &total);
1833 return progress;
1834 }
1835 virtual wxLongLong GetDownloadTotal()
1836 {
1837 wxLongLong progress, total;
1838 DoGetDownloadProgress(&progress, &total);
1839 return total;
1840 }
1841
1842 wxControl* m_ctrl;
1843 wxActiveX* m_pAX;
1844 IActiveMovie* m_pAM;
1845 IMediaPlayer* m_pMP;
1846 wxTimer* m_pTimer;
1847 wxSize m_bestSize;
1848 #ifdef __WXDEBUG__
1849 HMODULE m_hQuartzDll;
1850 LPAMGETERRORTEXT m_lpAMGetErrorText;
1851 wxString GetErrorString(HRESULT hrdsv);
1852 #endif
1853
1854 DECLARE_DYNAMIC_CLASS(wxAMMediaBackend)
1855 };
1856
1857 //---------------------------------------------------------------------------
1858 //
1859 // wxMCIMediaBackend
1860 //
1861 //---------------------------------------------------------------------------
1862
1863 //---------------------------------------------------------------------------
1864 // MCI Includes
1865 //---------------------------------------------------------------------------
1866 #include <mmsystem.h>
1867
1868 class WXDLLIMPEXP_MEDIA wxMCIMediaBackend : public wxMediaBackend
1869 {
1870 public:
1871
1872 wxMCIMediaBackend();
1873 ~wxMCIMediaBackend();
1874
1875 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
1876 wxWindowID id,
1877 const wxPoint& pos,
1878 const wxSize& size,
1879 long style,
1880 const wxValidator& validator,
1881 const wxString& name);
1882
1883 virtual bool Play();
1884 virtual bool Pause();
1885 virtual bool Stop();
1886
1887 virtual bool Load(const wxString& fileName);
1888 virtual bool Load(const wxURI& location);
1889
1890 virtual wxMediaState GetState();
1891
1892 virtual bool SetPosition(wxLongLong where);
1893 virtual wxLongLong GetPosition();
1894 virtual wxLongLong GetDuration();
1895
1896 virtual void Move(int x, int y, int w, int h);
1897 wxSize GetVideoSize() const;
1898
1899 virtual double GetPlaybackRate();
1900 virtual bool SetPlaybackRate(double dRate);
1901
1902 virtual double GetVolume();
1903 virtual bool SetVolume(double);
1904
1905 static LRESULT CALLBACK NotifyWndProc(HWND hWnd, UINT nMsg,
1906 WPARAM wParam, LPARAM lParam);
1907
1908 LRESULT CALLBACK OnNotifyWndProc(HWND hWnd, UINT nMsg,
1909 WPARAM wParam, LPARAM lParam);
1910
1911 MCIDEVICEID m_hDev; //Our MCI Device ID/Handler
1912 wxControl* m_ctrl; //Parent control
1913 HWND m_hNotifyWnd; //Window to use for MCI events
1914 bool m_bVideo; //Whether or not we have video
1915
1916 DECLARE_DYNAMIC_CLASS(wxMCIMediaBackend)
1917 };
1918
1919 //---------------------------------------------------------------------------
1920 //
1921 // wxQTMediaBackend
1922 //
1923 // We don't include Quicktime headers here and define all the types
1924 // ourselves because looking for the quicktime libaries etc. would
1925 // be tricky to do and making this a dependency for the MSVC projects
1926 // would be unrealistic.
1927 //
1928 // Thanks to Robert Roebling for the wxDL macro/library idea
1929 //---------------------------------------------------------------------------
1930
1931 //---------------------------------------------------------------------------
1932 // QT Includes
1933 //---------------------------------------------------------------------------
1934 //#include <qtml.h> //Windoze QT include
1935 //#include <QuickTimeComponents.h> //Standard QT stuff
1936 #include "wx/dynlib.h"
1937
1938 //---------------------------------------------------------------------------
1939 // QT Types
1940 //---------------------------------------------------------------------------
1941 typedef struct MovieRecord* Movie;
1942 typedef wxInt16 OSErr;
1943 typedef wxInt32 OSStatus;
1944 #define noErr 0
1945 #define fsRdPerm 1
1946 typedef unsigned char Str255[256];
1947 #define StringPtr unsigned char*
1948 #define newMovieActive 1
1949 #define newMovieAsyncOK (1 << 8)
1950 #define Ptr char*
1951 #define Handle Ptr*
1952 #define Fixed long
1953 #define OSType unsigned long
1954 #define CGrafPtr struct GrafPort *
1955 #define TimeScale long
1956 #define TimeBase struct TimeBaseRecord *
1957 typedef struct ComponentInstanceRecord * ComponentInstance;
1958 #define kMovieLoadStatePlayable 10000
1959 #define Boolean int
1960 #define MovieController ComponentInstance
1961
1962 #ifndef URLDataHandlerSubType
1963 #if defined(__WATCOMC__) || defined(__MINGW32__)
1964 // use magic numbers for compilers which complain about multicharacter integers
1965 const OSType URLDataHandlerSubType = 1970433056;
1966 const OSType VisualMediaCharacteristic = 1702454643;
1967 #else
1968 const OSType URLDataHandlerSubType = 'url ';
1969 const OSType VisualMediaCharacteristic = 'eyes';
1970 #endif
1971 #endif
1972
1973 struct FSSpec {
1974 short vRefNum;
1975 long parID;
1976 Str255 name; /*Str63 on mac, Str255 on msw */
1977 };
1978
1979 struct Rect {
1980 short top;
1981 short left;
1982 short bottom;
1983 short right;
1984 };
1985
1986 struct wide {
1987 wxInt32 hi;
1988 wxUint32 lo;
1989 };
1990
1991 struct TimeRecord {
1992 wide value; /* units */
1993 TimeScale scale; /* units per second */
1994 TimeBase base;
1995 };
1996
1997 struct Point {
1998 short v;
1999 short h;
2000 };
2001
2002 struct EventRecord {
2003 wxUint16 what;
2004 wxUint32 message;
2005 wxUint32 when;
2006 Point where;
2007 wxUint16 modifiers;
2008 };
2009
2010 enum {
2011 mcTopLeftMovie = 1,
2012 mcScaleMovieToFit = 2,
2013 mcWithBadge = 4,
2014 mcNotVisible = 8,
2015 mcWithFrame = 16
2016 };
2017
2018 //---------------------------------------------------------------------------
2019 // QT Library
2020 //---------------------------------------------------------------------------
2021 #define wxDL_METHOD_DEFINE( rettype, name, args, shortargs, defret ) \
2022 typedef rettype (* name ## Type) args ; \
2023 name ## Type pfn_ ## name; \
2024 rettype name args \
2025 { if (m_ok) return pfn_ ## name shortargs ; return defret; }
2026
2027 #define wxDL_VOIDMETHOD_DEFINE( name, args, shortargs ) \
2028 typedef void (* name ## Type) args ; \
2029 name ## Type pfn_ ## name; \
2030 void name args \
2031 { if (m_ok) pfn_ ## name shortargs ; }
2032
2033 #define wxDL_METHOD_LOAD( lib, name, success ) \
2034 pfn_ ## name = (name ## Type) lib.GetSymbol( wxT(#name), &success ); \
2035 if (!success) { wxLog::EnableLogging(bWasLoggingEnabled); return false; }
2036
2037
2038 class WXDLLIMPEXP_MEDIA wxQuickTimeLibrary
2039 {
2040 public:
2041 ~wxQuickTimeLibrary()
2042 {
2043 if(m_dll.IsLoaded())
2044 m_dll.Unload();
2045 }
2046
2047 bool Initialize();
2048 bool IsOk() const {return m_ok;}
2049
2050 protected:
2051 wxDynamicLibrary m_dll;
2052 bool m_ok;
2053
2054 public:
2055 wxDL_VOIDMETHOD_DEFINE( StartMovie, (Movie m), (m) );
2056 wxDL_VOIDMETHOD_DEFINE( StopMovie, (Movie m), (m) );
2057 wxDL_METHOD_DEFINE( bool, IsMovieDone, (Movie m), (m), false);
2058 wxDL_VOIDMETHOD_DEFINE( GoToBeginningOfMovie, (Movie m), (m) );
2059 wxDL_METHOD_DEFINE( OSErr, GetMoviesError, (), (), -1);
2060 wxDL_METHOD_DEFINE( OSErr, EnterMovies, (), (), -1);
2061 wxDL_VOIDMETHOD_DEFINE( ExitMovies, (), () );
2062 wxDL_METHOD_DEFINE( OSErr, InitializeQTML, (long flags), (flags), -1);
2063 wxDL_VOIDMETHOD_DEFINE( TerminateQTML, (), () );
2064
2065 wxDL_METHOD_DEFINE( OSErr, NativePathNameToFSSpec,
2066 (char* inName, FSSpec* outFile, long flags),
2067 (inName, outFile, flags), -1);
2068
2069 wxDL_METHOD_DEFINE( OSErr, OpenMovieFile,
2070 (const FSSpec * fileSpec, short * resRefNum, wxInt8 permission),
2071 (fileSpec, resRefNum, permission), -1 );
2072
2073 wxDL_METHOD_DEFINE( OSErr, CloseMovieFile,
2074 (short resRefNum), (resRefNum), -1);
2075
2076 wxDL_METHOD_DEFINE( OSErr, NewMovieFromFile,
2077 (Movie * theMovie, short resRefNum, short * resId,
2078 StringPtr resName, short newMovieFlags,
2079 bool * dataRefWasChanged),
2080 (theMovie, resRefNum, resId, resName, newMovieFlags,
2081 dataRefWasChanged), -1);
2082
2083 wxDL_VOIDMETHOD_DEFINE( SetMovieRate, (Movie m, Fixed rate), (m, rate) );
2084 wxDL_METHOD_DEFINE( Fixed, GetMovieRate, (Movie m), (m), 0);
2085 wxDL_VOIDMETHOD_DEFINE( MoviesTask, (Movie m, long maxms), (m, maxms) );
2086 wxDL_VOIDMETHOD_DEFINE( BlockMove,
2087 (const char* p1, const char* p2, long s), (p1,p2,s) );
2088 wxDL_METHOD_DEFINE( Handle, NewHandleClear, (long s), (s), NULL );
2089
2090 wxDL_METHOD_DEFINE( OSErr, NewMovieFromDataRef,
2091 (Movie * m, short flags, short * id,
2092 Handle dataRef, OSType dataRefType),
2093 (m,flags,id,dataRef,dataRefType), -1 );
2094
2095 wxDL_VOIDMETHOD_DEFINE( DisposeHandle, (Handle h), (h) );
2096 wxDL_VOIDMETHOD_DEFINE( GetMovieNaturalBoundsRect, (Movie m, Rect* r), (m,r) );
2097 wxDL_METHOD_DEFINE( void*, GetMovieIndTrackType,
2098 (Movie m, long index, OSType type, long flags),
2099 (m,index,type,flags), NULL );
2100 wxDL_VOIDMETHOD_DEFINE( CreatePortAssociation,
2101 (void* hWnd, void* junk, long morejunk), (hWnd, junk, morejunk) );
2102 wxDL_METHOD_DEFINE(void*, GetNativeWindowPort, (void* hWnd), (hWnd), NULL);
2103 wxDL_VOIDMETHOD_DEFINE(SetMovieGWorld, (Movie m, CGrafPtr port, void* whatever),
2104 (m, port, whatever) );
2105 wxDL_VOIDMETHOD_DEFINE(DisposeMovie, (Movie m), (m) );
2106 wxDL_VOIDMETHOD_DEFINE(SetMovieBox, (Movie m, Rect* r), (m,r));
2107 wxDL_VOIDMETHOD_DEFINE(SetMovieTimeScale, (Movie m, long s), (m,s));
2108 wxDL_METHOD_DEFINE(long, GetMovieDuration, (Movie m), (m), 0);
2109 wxDL_METHOD_DEFINE(TimeBase, GetMovieTimeBase, (Movie m), (m), 0);
2110 wxDL_METHOD_DEFINE(TimeScale, GetMovieTimeScale, (Movie m), (m), 0);
2111 wxDL_METHOD_DEFINE(long, GetMovieTime, (Movie m, void* cruft), (m,cruft), 0);
2112 wxDL_VOIDMETHOD_DEFINE(SetMovieTime, (Movie m, TimeRecord* tr), (m,tr) );
2113 wxDL_METHOD_DEFINE(short, GetMovieVolume, (Movie m), (m), 0);
2114 wxDL_VOIDMETHOD_DEFINE(SetMovieVolume, (Movie m, short sVolume), (m,sVolume) );
2115 wxDL_VOIDMETHOD_DEFINE(SetMovieTimeValue, (Movie m, long s), (m,s));
2116 wxDL_METHOD_DEFINE(ComponentInstance, NewMovieController, (Movie m, const Rect* mr, long fl), (m,mr,fl), 0);
2117 wxDL_VOIDMETHOD_DEFINE(DisposeMovieController, (ComponentInstance ci), (ci));
2118 wxDL_METHOD_DEFINE(int, MCSetVisible, (ComponentInstance m, int b), (m, b), 0);
2119
2120
2121 wxDL_VOIDMETHOD_DEFINE(PrePrerollMovie, (Movie m, long t, Fixed r, WXFARPROC p1, void* p2), (m,t,r,p1,p2) );
2122 wxDL_VOIDMETHOD_DEFINE(PrerollMovie, (Movie m, long t, Fixed r), (m,t,r) );
2123 wxDL_METHOD_DEFINE(Fixed, GetMoviePreferredRate, (Movie m), (m), 0);
2124 wxDL_METHOD_DEFINE(long, GetMovieLoadState, (Movie m), (m), 0);
2125 wxDL_METHOD_DEFINE(void*, NewRoutineDescriptor, (WXFARPROC f, int l, void* junk), (f, l, junk), 0);
2126 wxDL_VOIDMETHOD_DEFINE(DisposeRoutineDescriptor, (void* f), (f));
2127 wxDL_METHOD_DEFINE(void*, GetCurrentArchitecture, (), (), 0);
2128 wxDL_METHOD_DEFINE(int, MCDoAction, (ComponentInstance ci, long f, void* p), (ci,f,p), 0);
2129 wxDL_VOIDMETHOD_DEFINE(MCSetControllerBoundsRect, (ComponentInstance ci, Rect* r), (ci,r));
2130 wxDL_VOIDMETHOD_DEFINE(DestroyPortAssociation, (CGrafPtr g), (g));
2131 wxDL_VOIDMETHOD_DEFINE(NativeEventToMacEvent, (MSG* p1, EventRecord* p2), (p1,p2));
2132 wxDL_VOIDMETHOD_DEFINE(MCIsPlayerEvent, (ComponentInstance ci, EventRecord* p2), (ci, p2));
2133 wxDL_METHOD_DEFINE(int, MCSetMovie, (ComponentInstance ci, Movie m, void* p1, Point w),
2134 (ci,m,p1,w),0);
2135 wxDL_VOIDMETHOD_DEFINE(MCPositionController,
2136 (ComponentInstance ci, Rect* r, void* junk, void* morejunk), (ci,r,junk,morejunk));
2137 wxDL_VOIDMETHOD_DEFINE(MCSetActionFilterWithRefCon,
2138 (ComponentInstance ci, WXFARPROC cb, void* ref), (ci,cb,ref));
2139 wxDL_VOIDMETHOD_DEFINE(MCGetControllerInfo, (MovieController mc, long* flags), (mc,flags));
2140 wxDL_VOIDMETHOD_DEFINE(BeginUpdate, (CGrafPtr port), (port));
2141 wxDL_VOIDMETHOD_DEFINE(UpdateMovie, (Movie m), (m));
2142 wxDL_VOIDMETHOD_DEFINE(EndUpdate, (CGrafPtr port), (port));
2143 wxDL_METHOD_DEFINE( OSErr, GetMoviesStickyError, (), (), -1);
2144 };
2145
2146 bool wxQuickTimeLibrary::Initialize()
2147 {
2148 m_ok = false;
2149
2150 bool bWasLoggingEnabled = wxLog::EnableLogging(false); //Turn off the wxDynamicLibrary logging
2151
2152 if(!m_dll.Load(wxT("qtmlClient.dll")))
2153 {
2154 wxLog::EnableLogging(bWasLoggingEnabled);
2155 return false;
2156 }
2157
2158 wxDL_METHOD_LOAD( m_dll, StartMovie, m_ok );
2159 wxDL_METHOD_LOAD( m_dll, StopMovie, m_ok );
2160 wxDL_METHOD_LOAD( m_dll, IsMovieDone, m_ok );
2161 wxDL_METHOD_LOAD( m_dll, GoToBeginningOfMovie, m_ok );
2162 wxDL_METHOD_LOAD( m_dll, GetMoviesError, m_ok );
2163 wxDL_METHOD_LOAD( m_dll, EnterMovies, m_ok );
2164 wxDL_METHOD_LOAD( m_dll, ExitMovies, m_ok );
2165 wxDL_METHOD_LOAD( m_dll, InitializeQTML, m_ok );
2166 wxDL_METHOD_LOAD( m_dll, TerminateQTML, m_ok );
2167 wxDL_METHOD_LOAD( m_dll, NativePathNameToFSSpec, m_ok );
2168 wxDL_METHOD_LOAD( m_dll, OpenMovieFile, m_ok );
2169 wxDL_METHOD_LOAD( m_dll, CloseMovieFile, m_ok );
2170 wxDL_METHOD_LOAD( m_dll, NewMovieFromFile, m_ok );
2171 wxDL_METHOD_LOAD( m_dll, GetMovieRate, m_ok );
2172 wxDL_METHOD_LOAD( m_dll, SetMovieRate, m_ok );
2173 wxDL_METHOD_LOAD( m_dll, MoviesTask, m_ok );
2174 wxDL_METHOD_LOAD( m_dll, BlockMove, m_ok );
2175 wxDL_METHOD_LOAD( m_dll, NewHandleClear, m_ok );
2176 wxDL_METHOD_LOAD( m_dll, NewMovieFromDataRef, m_ok );
2177 wxDL_METHOD_LOAD( m_dll, DisposeHandle, m_ok );
2178 wxDL_METHOD_LOAD( m_dll, GetMovieNaturalBoundsRect, m_ok );
2179 wxDL_METHOD_LOAD( m_dll, GetMovieIndTrackType, m_ok );
2180 wxDL_METHOD_LOAD( m_dll, CreatePortAssociation, m_ok );
2181 wxDL_METHOD_LOAD( m_dll, DestroyPortAssociation, m_ok );
2182 wxDL_METHOD_LOAD( m_dll, GetNativeWindowPort, m_ok );
2183 wxDL_METHOD_LOAD( m_dll, SetMovieGWorld, m_ok );
2184 wxDL_METHOD_LOAD( m_dll, DisposeMovie, m_ok );
2185 wxDL_METHOD_LOAD( m_dll, SetMovieBox, m_ok );
2186 wxDL_METHOD_LOAD( m_dll, SetMovieTimeScale, m_ok );
2187 wxDL_METHOD_LOAD( m_dll, GetMovieDuration, m_ok );
2188 wxDL_METHOD_LOAD( m_dll, GetMovieTimeBase, m_ok );
2189 wxDL_METHOD_LOAD( m_dll, GetMovieTimeScale, m_ok );
2190 wxDL_METHOD_LOAD( m_dll, GetMovieTime, m_ok );
2191 wxDL_METHOD_LOAD( m_dll, SetMovieTime, m_ok );
2192 wxDL_METHOD_LOAD( m_dll, GetMovieVolume, m_ok );
2193 wxDL_METHOD_LOAD( m_dll, SetMovieVolume, m_ok );
2194 wxDL_METHOD_LOAD( m_dll, SetMovieTimeValue, m_ok );
2195 wxDL_METHOD_LOAD( m_dll, NewMovieController, m_ok );
2196 wxDL_METHOD_LOAD( m_dll, DisposeMovieController, m_ok );
2197 wxDL_METHOD_LOAD( m_dll, MCSetVisible, m_ok );
2198 wxDL_METHOD_LOAD( m_dll, PrePrerollMovie, m_ok );
2199 wxDL_METHOD_LOAD( m_dll, PrerollMovie, m_ok );
2200 wxDL_METHOD_LOAD( m_dll, GetMoviePreferredRate, m_ok );
2201 wxDL_METHOD_LOAD( m_dll, GetMovieLoadState, m_ok );
2202 wxDL_METHOD_LOAD( m_dll, MCDoAction, m_ok );
2203 wxDL_METHOD_LOAD( m_dll, MCSetControllerBoundsRect, m_ok );
2204 wxDL_METHOD_LOAD( m_dll, NativeEventToMacEvent, m_ok );
2205 wxDL_METHOD_LOAD( m_dll, MCIsPlayerEvent, m_ok );
2206 wxDL_METHOD_LOAD( m_dll, MCSetMovie, m_ok );
2207 wxDL_METHOD_LOAD( m_dll, MCSetActionFilterWithRefCon, m_ok );
2208 wxDL_METHOD_LOAD( m_dll, MCGetControllerInfo, m_ok );
2209 wxDL_METHOD_LOAD( m_dll, BeginUpdate, m_ok );
2210 wxDL_METHOD_LOAD( m_dll, UpdateMovie, m_ok );
2211 wxDL_METHOD_LOAD( m_dll, EndUpdate, m_ok );
2212 wxDL_METHOD_LOAD( m_dll, GetMoviesStickyError, m_ok );
2213
2214 wxLog::EnableLogging(bWasLoggingEnabled);
2215 m_ok = true;
2216
2217 return true;
2218 }
2219
2220 //cludgy workaround for wx events. slots would be nice :)
2221 class WXDLLIMPEXP_MEDIA wxQTMediaEvtHandler : public wxEvtHandler
2222 {
2223 public:
2224 void OnPaint(wxPaintEvent&);
2225 void OnEraseBackground(wxEraseEvent&);
2226 };
2227
2228 class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackend
2229 {
2230 public:
2231 wxQTMediaBackend();
2232 ~wxQTMediaBackend();
2233
2234 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
2235 wxWindowID id,
2236 const wxPoint& pos,
2237 const wxSize& size,
2238 long style,
2239 const wxValidator& validator,
2240 const wxString& name);
2241
2242 virtual bool Play();
2243 virtual bool Pause();
2244 virtual bool Stop();
2245
2246 virtual bool Load(const wxString& fileName);
2247 virtual bool Load(const wxURI& location);
2248
2249 virtual wxMediaState GetState();
2250
2251 virtual bool SetPosition(wxLongLong where);
2252 virtual wxLongLong GetPosition();
2253 virtual wxLongLong GetDuration();
2254
2255 virtual void Move(int x, int y, int w, int h);
2256 wxSize GetVideoSize() const;
2257
2258 virtual double GetPlaybackRate();
2259 virtual bool SetPlaybackRate(double dRate);
2260
2261 virtual double GetVolume();
2262 virtual bool SetVolume(double);
2263
2264 void Cleanup();
2265 void FinishLoad();
2266
2267 static void PPRMProc (Movie theMovie, OSErr theErr, void* theRefCon);
2268 //TODO: Last param actually long - does this work on 64bit machines?
2269 static Boolean MCFilterProc (MovieController theController,
2270 short action, void *params, LONG_PTR refCon);
2271
2272 static LRESULT CALLBACK QTWndProc(HWND, UINT, WPARAM, LPARAM);
2273
2274 virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags);
2275
2276 wxSize m_bestSize; //Original movie size
2277 Movie m_movie; //QT Movie handle/instance
2278 wxControl* m_ctrl; //Parent control
2279 bool m_bVideo; //Whether or not we have video
2280 bool m_bPlaying; //Whether or not movie is playing
2281 wxTimer* m_timer; //Load or Play timer
2282 wxQuickTimeLibrary m_lib; //DLL to load functions from
2283 ComponentInstance m_pMC; //Movie Controller
2284
2285 DECLARE_DYNAMIC_CLASS(wxQTMediaBackend)
2286 };
2287
2288
2289 //===========================================================================
2290 // IMPLEMENTATION
2291 //===========================================================================
2292
2293 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2294 //
2295 // wxAMMediaBackend
2296 //
2297 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2298
2299 IMPLEMENT_DYNAMIC_CLASS(wxAMMediaBackend, wxMediaBackend);
2300
2301 //---------------------------------------------------------------------------
2302 // Usual debugging macros
2303 //---------------------------------------------------------------------------
2304 #ifdef __WXDEBUG__
2305 #define MAX_ERROR_TEXT_LEN 160
2306
2307 //Get the error string for Active Movie
2308 wxString wxAMMediaBackend::GetErrorString(HRESULT hrdsv)
2309 {
2310 wxChar szError[MAX_ERROR_TEXT_LEN];
2311 if( m_lpAMGetErrorText != NULL &&
2312 (*m_lpAMGetErrorText)(hrdsv, szError, MAX_ERROR_TEXT_LEN) == 0)
2313 {
2314 return wxString::Format(wxT("DirectShow error \"%s\" \n")
2315 wxT("(numeric %X)\n")
2316 wxT("occured"),
2317 szError, (int)hrdsv);
2318 }
2319 else
2320 {
2321 return wxString::Format(wxT("Unknown error \n")
2322 wxT("(numeric %X)\n")
2323 wxT("occured"),
2324 (int)hrdsv);
2325 }
2326 }
2327
2328 #define wxAMFAIL(x) wxFAIL_MSG(GetErrorString(x));
2329 #define wxVERIFY(x) wxASSERT((x))
2330 #define wxAMLOG(x) wxLogDebug(GetErrorString(x))
2331 #else
2332 #define wxAMVERIFY(x) (x)
2333 #define wxVERIFY(x) (x)
2334 #define wxAMLOG(x)
2335 #define wxAMFAIL(x)
2336 #endif
2337
2338 //---------------------------------------------------------------------------
2339 // Standard macros for ease of use
2340 //---------------------------------------------------------------------------
2341 #define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
2342
2343 //---------------------------------------------------------------------------
2344 // wxAMLoadTimer
2345 //
2346 // Queries the control periodically to see if it has reached the point
2347 // in its loading cycle where we can begin playing the media - if so
2348 // then we finish up some things like getting the original size of the video
2349 // and then sending the loaded event to our handler
2350 //---------------------------------------------------------------------------
2351 class wxAMLoadTimer : public wxTimer
2352 {
2353 public:
2354 wxAMLoadTimer(wxAMMediaBackend* parent) :
2355 m_parent(parent) {}
2356
2357 void Notify()
2358 {
2359 if(m_parent->m_pMP)
2360 {
2361 MPReadyStateConstants nState;
2362 m_parent->m_pMP->get_ReadyState(&nState);
2363 if(nState != mpReadyStateLoading)
2364 {
2365 Stop();
2366 m_parent->FinishLoad();
2367 delete this;
2368 }
2369 }
2370 else
2371 {
2372 IActiveMovie2* pAM2 = NULL;
2373 ReadyStateConstants nState;
2374 if(m_parent->m_pAM->QueryInterface(IID_IActiveMovie2,
2375 (void**)&pAM2) == 0 &&
2376 pAM2->get_ReadyState(&nState) == 0)
2377 {
2378 pAM2->Release();
2379 if(nState != amvLoading)
2380 {
2381 Stop();
2382 m_parent->FinishLoad();
2383 delete this;
2384 }
2385 }
2386 else
2387 {
2388 if(pAM2)
2389 pAM2->Release();
2390
2391 Stop();
2392 m_parent->FinishLoad();
2393 delete this;
2394 }
2395 }
2396
2397 }
2398
2399 protected:
2400 wxAMMediaBackend* m_parent; //Backend pointer
2401 };
2402
2403 //---------------------------------------------------------------------------
2404 // wxAMPlayTimer
2405 //
2406 // Sets m_hNotifyWnd to NULL to signify that we haven't loaded anything yet
2407 // Queries the control periodically to see if it has stopped -
2408 // if it has it sends the stop event
2409 //---------------------------------------------------------------------------
2410 class wxAMPlayTimer : public wxTimer
2411 {
2412 public:
2413 wxAMPlayTimer(wxAMMediaBackend* parent) :
2414 m_parent(parent) {}
2415
2416 void Notify()
2417 {
2418 if(m_parent->GetState() == wxMEDIASTATE_STOPPED &&
2419 //NB: Stop events could get triggered by the interface
2420 //if ShowPlayerControls is enabled,
2421 //so we need this hack here to make an attempt
2422 //at it not getting sent - but its far from ideal -
2423 //they can still get sent in some cases
2424 m_parent->GetPosition() == m_parent->GetDuration())
2425 {
2426 wxMediaEvent theEvent(wxEVT_MEDIA_STOP,
2427 m_parent->m_ctrl->GetId());
2428 m_parent->m_ctrl->ProcessEvent(theEvent);
2429
2430 if(theEvent.IsAllowed())
2431 {
2432 //Seek to beginning of movie
2433 m_parent->wxAMMediaBackend::SetPosition(0);
2434 Stop();
2435
2436 //send the event to our child
2437 wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED,
2438 m_parent->m_ctrl->GetId());
2439 m_parent->m_ctrl->AddPendingEvent(theEvent);
2440 }
2441 }
2442 }
2443
2444 protected:
2445 wxAMMediaBackend* m_parent; //Backend pointer
2446 };
2447
2448
2449 /*
2450 // The following is an alternative way - but it doesn't seem
2451 // to work with the IActiveMovie control - it probably processes
2452 // its own events
2453 //---------------------------------------------------------------------------
2454 // wxAMPlayTimer
2455 //
2456 // Query the IMediaEvent interface from the embedded WMP's
2457 // filtergraph, then process the events from it - sending
2458 // EC_COMPLETE events as stop events to the media control.
2459 //---------------------------------------------------------------------------
2460 class wxAMPlayTimer : public wxTimer
2461 {
2462 public:
2463 wxAMPlayTimer(wxAMMediaBackend* pBE) : m_pBE(pBE), m_pME(NULL)
2464 {
2465 HRESULT hr;
2466 IUnknown* pGB;
2467 hr = m_pBE->m_pAM->get_FilterGraph(&pGB);
2468 wxASSERT(SUCCEEDED(hr));
2469 hr = pGB->QueryInterface(IID_IMediaEvent, (void**)&m_pME);
2470 wxASSERT(SUCCEEDED(hr));
2471 pGB->Release();
2472 }
2473
2474 ~wxAMPlayTimer()
2475 {
2476 SAFE_RELEASE(m_pME);
2477 }
2478
2479 void Notify()
2480 {
2481 LONG evCode;
2482 LONG_PTR evParam1,
2483 evParam2;
2484
2485 //
2486 // DirectShow keeps a list of queued events, and we need
2487 // to go through them one by one, stopping at (Hopefully only one)
2488 // EC_COMPLETE message
2489 //
2490 while( m_pME->GetEvent(&evCode, &evParam1, &evParam2, 0) == 0 )
2491 {
2492 // Cleanup memory that GetEvent allocated
2493 HRESULT hr = m_pME->FreeEventParams(evCode,
2494 evParam1, evParam2);
2495 if(hr != 0)
2496 {
2497 //Even though this makes a messagebox this
2498 //is windows where we can do gui stuff in seperate
2499 //threads :)
2500 wxFAIL_MSG(m_pBE->GetErrorString(hr));
2501 }
2502 // If this is the end of the clip, notify handler
2503 else if(1 == evCode) //EC_COMPLETE
2504 {
2505 wxMediaEvent theEvent(wxEVT_MEDIA_STOP,
2506 m_pBE->m_ctrl->GetId());
2507 m_pBE->m_ctrl->ProcessEvent(theEvent);
2508
2509 if(theEvent.IsAllowed())
2510 {
2511 Stop();
2512
2513 //send the event to our child
2514 wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED,
2515 m_pBE->m_ctrl->GetId());
2516 m_pBE->m_ctrl->AddPendingEvent(theEvent);
2517 }
2518 }
2519 }
2520 }
2521
2522 protected:
2523 wxAMMediaBackend* m_pBE; //Backend pointer
2524 IMediaEvent* m_pME; //To determine when to send stop event
2525 };
2526 */
2527
2528 //---------------------------------------------------------------------------
2529 // wxAMMediaBackend Constructor
2530 //---------------------------------------------------------------------------
2531 wxAMMediaBackend::wxAMMediaBackend()
2532 :m_pAX(NULL),
2533 m_pAM(NULL),
2534 m_pMP(NULL),
2535 m_pTimer(NULL)
2536 #ifdef __WXDEBUG__
2537 ,m_hQuartzDll(NULL)
2538 #endif
2539 {
2540 }
2541
2542 //---------------------------------------------------------------------------
2543 // wxAMMediaBackend Destructor
2544 //---------------------------------------------------------------------------
2545 wxAMMediaBackend::~wxAMMediaBackend()
2546 {
2547 Clear(); //Free memory from Load()
2548
2549 if(m_pAX)
2550 {
2551 m_pAX->DissociateHandle();
2552 delete m_pAX;
2553 m_pAM->Release();
2554
2555 if(m_pMP)
2556 m_pMP->Release();
2557 }
2558 #ifdef __WXDEBUG__
2559 if(m_hQuartzDll)
2560 ::FreeLibrary(m_hQuartzDll);
2561 #endif
2562 }
2563
2564 //---------------------------------------------------------------------------
2565 // wxAMMediaBackend::Clear
2566 //
2567 // Free up interfaces and memory allocated by LoadXXX
2568 //---------------------------------------------------------------------------
2569 void wxAMMediaBackend::Clear()
2570 {
2571 if(m_pTimer)
2572 delete m_pTimer;
2573 }
2574
2575 //---------------------------------------------------------------------------
2576 // wxAMMediaBackend::CreateControl
2577 //---------------------------------------------------------------------------
2578 bool wxAMMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
2579 wxWindowID id,
2580 const wxPoint& pos,
2581 const wxSize& size,
2582 long style,
2583 const wxValidator& validator,
2584 const wxString& name)
2585 {
2586 // First get the AMGetErrorText procedure in debug
2587 // mode for more meaningful messages
2588 #ifdef __WXDEBUG__
2589 m_hQuartzDll = ::LoadLibrary(wxT("quartz.dll"));
2590 if(m_hQuartzDll)
2591 {
2592 m_lpAMGetErrorText = (LPAMGETERRORTEXT) ::GetProcAddress(
2593 m_hQuartzDll,
2594 wxString::Format(wxT("AMGetErrorText%s"),
2595
2596 #if wxUSE_UNICODE
2597 wxT("W")
2598 #else
2599 wxT("A")
2600 #endif
2601 #ifdef __WXWINCE__
2602 )
2603 #else
2604 ).mb_str(wxConvLocal)
2605 #endif
2606 );
2607 }
2608 #endif
2609 // Now determine which (if any) media player interface is
2610 // available - IMediaPlayer or IActiveMovie
2611 if( ::CoCreateInstance(CLSID_MediaPlayer, NULL,
2612 CLSCTX_INPROC_SERVER,
2613 IID_IMediaPlayer, (void**)&m_pMP) != 0 )
2614 {
2615 if( ::CoCreateInstance(CLSID_ActiveMovie, NULL,
2616 CLSCTX_INPROC_SERVER,
2617 IID_IActiveMovie, (void**)&m_pAM) != 0 )
2618 return false;
2619 m_pAM->QueryInterface(IID_IMediaPlayer, (void**)&m_pMP);
2620 }
2621 else
2622 {
2623 m_pMP->QueryInterface(IID_IActiveMovie, (void**)&m_pAM);
2624 }
2625 //
2626 // Create window
2627 // By default wxWindow(s) is created with a border -
2628 // so we need to get rid of those
2629 //
2630 // Since we don't have a child window like most other
2631 // backends, we don't need wxCLIP_CHILDREN
2632 //
2633 if ( !ctrl->wxControl::Create(parent, id, pos, size,
2634 (style & ~wxBORDER_MASK) | wxBORDER_NONE,
2635 validator, name) )
2636 return false;
2637
2638 //
2639 // Now create the ActiveX container along with the media player
2640 // interface and query them
2641 //
2642 m_ctrl = ctrl;
2643 m_pAX = new wxActiveX(ctrl,
2644 m_pMP ? IID_IMediaPlayer : IID_IActiveMovie,
2645 m_pAM);
2646
2647
2648 //
2649 // Here we set up wx-specific stuff for the default
2650 // settings wxMediaCtrl says it will stay to
2651 //
2652 if(m_pMP)
2653 {
2654 m_pMP->put_DisplaySize(mpFitToSize);
2655 // TODO: Unsure what actual effect this has
2656 m_pMP->put_WindowlessVideo(VARIANT_TRUE);
2657 }
2658 else
2659 m_pAM->put_MovieWindowSize(amvDoubleOriginalSize);
2660
2661 //by default true
2662 m_pAM->put_AutoStart(VARIANT_FALSE);
2663 //by default enabled
2664 wxAMMediaBackend::ShowPlayerControls(wxMEDIACTRLPLAYERCONTROLS_NONE);
2665 //by default with AM only 0.5
2666 wxAMMediaBackend::SetVolume(1.0);
2667
2668 // My problem with this was only with a previous patch, probably the
2669 // third rewrite fixed it as a side-effect. In fact, the erase
2670 // background style of drawing not only works now, but is much better
2671 // than paint-based updates (the paint event handler flickers if the
2672 // wxMediaCtrl shares a sizer with another child window, or is on a
2673 // notebook)
2674 // - Greg Hazel
2675 m_ctrl->Connect(m_ctrl->GetId(), wxEVT_ERASE_BACKGROUND,
2676 wxEraseEventHandler(wxAMMediaEvtHandler::OnEraseBackground),
2677 NULL, (wxEvtHandler*) this);
2678
2679 // success
2680 return true;
2681 }
2682
2683 //---------------------------------------------------------------------------
2684 // wxAMMediaBackend::Load (file version)
2685 //---------------------------------------------------------------------------
2686 bool wxAMMediaBackend::Load(const wxString& fileName)
2687 {
2688 return DoLoad(fileName);
2689 }
2690
2691 //---------------------------------------------------------------------------
2692 // wxAMMediaBackend::Load (URL Version)
2693 //---------------------------------------------------------------------------
2694 bool wxAMMediaBackend::Load(const wxURI& location)
2695 {
2696 // Turn off loading from a proxy as user
2697 // may have set it previously
2698 INSPlay* pPlay = NULL;
2699 m_pAM->QueryInterface(IID_INSPlay, (void**) &pPlay);
2700 if(pPlay)
2701 {
2702 pPlay->put_UseHTTPProxy(VARIANT_FALSE);
2703 pPlay->Release();
2704 }
2705
2706 return DoLoad(location.BuildURI());
2707 }
2708
2709 //---------------------------------------------------------------------------
2710 // wxAMMediaBackend::Load (URL Version with Proxy)
2711 //---------------------------------------------------------------------------
2712 bool wxAMMediaBackend::Load(const wxURI& location, const wxURI& proxy)
2713 {
2714 // Set the proxy of the NETSHOW interface
2715 INSPlay* pPlay = NULL;
2716 m_pAM->QueryInterface(IID_INSPlay, (void**) &pPlay);
2717
2718 if(pPlay)
2719 {
2720 pPlay->put_UseHTTPProxy(VARIANT_TRUE);
2721 pPlay->put_HTTPProxyHost(wxBasicString(proxy.GetServer()).Get());
2722 pPlay->put_HTTPProxyPort(wxAtoi(proxy.GetPort()));
2723 pPlay->Release();
2724 }
2725
2726 return DoLoad(location.BuildURI());
2727 }
2728
2729 //---------------------------------------------------------------------------
2730 // wxAMMediaBackend::DoLoad
2731 //
2732 // Called by all functions - this actually renders
2733 // the file and sets up the filter graph
2734 //---------------------------------------------------------------------------
2735 bool wxAMMediaBackend::DoLoad(const wxString& location)
2736 {
2737 Clear(); //Clear up previously allocated memory
2738
2739 HRESULT hr;
2740
2741 // Play the movie the normal way through the embedded
2742 // WMP. Supposively Open is better in theory because
2743 // the docs say its async and put_FileName is not -
2744 // but in practice they both seem to be async anyway
2745 if(m_pMP)
2746 hr = m_pMP->Open( wxBasicString(location).Get() );
2747 else
2748 hr = m_pAM->put_FileName( wxBasicString(location).Get() );
2749
2750 if(FAILED(hr))
2751 {
2752 wxAMLOG(hr);
2753 return false;
2754 }
2755
2756 // In AM playing will FAIL if
2757 // the user plays before the media is loaded
2758 m_pTimer = new wxAMLoadTimer(this);
2759 m_pTimer->Start(20);
2760 return true;
2761 }
2762
2763 //---------------------------------------------------------------------------
2764 // wxAMMediaBackend::FinishLoad
2765 //
2766 // Called by our wxAMLoadTimer when the
2767 // embedded WMP tells its the media is ready to play.
2768 //
2769 // Here we get the original size of the video and
2770 // send the loaded event to our watcher :).
2771 //---------------------------------------------------------------------------
2772 void wxAMMediaBackend::FinishLoad()
2773 {
2774 //Get the original video size
2775 m_pAM->get_ImageSourceWidth((long*)&m_bestSize.x);
2776 m_pAM->get_ImageSourceHeight((long*)&m_bestSize.y);
2777
2778 //
2779 //Start the play timer to catch stop events
2780 //Previous load timer cleans up itself
2781 //
2782 m_pTimer = new wxAMPlayTimer(this);
2783
2784 //Here, if the parent of the control has a sizer - we
2785 //tell it to recalculate the size of this control since
2786 //the user opened a separate media file
2787 //
2788 m_ctrl->InvalidateBestSize();
2789 m_ctrl->GetParent()->Layout();
2790 m_ctrl->GetParent()->Refresh();
2791 m_ctrl->GetParent()->Update();
2792 m_ctrl->SetSize(m_ctrl->GetSize());
2793
2794 //Send event to our children
2795 wxMediaEvent theEvent(wxEVT_MEDIA_LOADED,
2796 m_ctrl->GetId());
2797 m_ctrl->AddPendingEvent(theEvent);
2798 }
2799
2800 //---------------------------------------------------------------------------
2801 // wxAMMediaBackend::ShowPlayerControls
2802 //---------------------------------------------------------------------------
2803 bool wxAMMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
2804 {
2805 // Note that IMediaPlayer doesn't have a statusbar by
2806 // default but IActiveMovie does - so lets try to keep
2807 // the interface consistant
2808 if(!flags)
2809 {
2810 m_pAM->put_Enabled(VARIANT_FALSE);
2811 m_pAM->put_ShowControls(VARIANT_FALSE);
2812 if(m_pMP)
2813 m_pMP->put_ShowStatusBar(VARIANT_FALSE);
2814 }
2815 else
2816 {
2817 m_pAM->put_Enabled(VARIANT_TRUE);
2818 m_pAM->put_ShowControls(VARIANT_TRUE);
2819
2820 m_pAM->put_ShowPositionControls(
2821 (flags & wxMEDIACTRLPLAYERCONTROLS_STEP) ?
2822 VARIANT_TRUE : VARIANT_FALSE);
2823
2824 if(m_pMP)
2825 {
2826 m_pMP->put_ShowStatusBar(VARIANT_TRUE);
2827 m_pMP->put_ShowAudioControls(
2828 (flags & wxMEDIACTRLPLAYERCONTROLS_VOLUME) ?
2829 VARIANT_TRUE : VARIANT_FALSE);
2830 }
2831 }
2832
2833 return true;
2834 }
2835
2836 //---------------------------------------------------------------------------
2837 // wxAMMediaBackend::Play
2838 //
2839 // Plays the stream. If it is non-seekable, it will restart it (implicit).
2840 //
2841 // Note that we use SUCCEEDED here because run/pause/stop tend to be overly
2842 // picky and return warnings on pretty much every call
2843 //---------------------------------------------------------------------------
2844 bool wxAMMediaBackend::Play()
2845 {
2846 // if the movie isn't done loading yet
2847 // go into an sync getmessage loop until it is :)
2848 if(m_pMP)
2849 {
2850 MPReadyStateConstants nState;
2851 m_pMP->get_ReadyState(&nState);
2852 while(nState == mpReadyStateLoading && wxYieldIfNeeded())
2853 {
2854 m_pMP->get_ReadyState(&nState);
2855 }
2856 }
2857 else
2858 {
2859 IActiveMovie2* pAM2;
2860 ReadyStateConstants nState;
2861 if(m_pAM->QueryInterface(IID_IActiveMovie2, (void**)&pAM2) == 0 &&
2862 pAM2->get_ReadyState(&nState) == 0)
2863 {
2864 while(nState == amvLoading && wxYieldIfNeeded())
2865 {
2866 pAM2->get_ReadyState(&nState);
2867 }
2868 pAM2->Release();
2869 }
2870 }
2871
2872 //Actually try to play the movie
2873 HRESULT hr = m_pAM->Run();
2874 if(SUCCEEDED(hr))
2875 {
2876 m_pTimer->Start(20);
2877 return true;
2878 }
2879 wxAMLOG(hr);
2880 return false;
2881 }
2882
2883 //---------------------------------------------------------------------------
2884 // wxAMMediaBackend::Pause
2885 //
2886 // Pauses the stream.
2887 //---------------------------------------------------------------------------
2888 bool wxAMMediaBackend::Pause()
2889 {
2890 HRESULT hr = m_pAM->Pause();
2891 if(SUCCEEDED(hr))
2892 return true;
2893 wxAMLOG(hr);
2894 return false;
2895 }
2896
2897 //---------------------------------------------------------------------------
2898 // wxAMMediaBackend::Stop
2899 //
2900 // Stops the stream.
2901 //---------------------------------------------------------------------------
2902 bool wxAMMediaBackend::Stop()
2903 {
2904 HRESULT hr = m_pAM->Stop();
2905 if(SUCCEEDED(hr))
2906 {
2907 //Seek to beginning
2908 wxAMMediaBackend::SetPosition(0);
2909 //Stop stop event timer
2910 m_pTimer->Stop();
2911 return true;
2912 }
2913 wxAMLOG(hr);
2914 return false;
2915 }
2916
2917 //---------------------------------------------------------------------------
2918 // wxAMMediaBackend::SetPosition
2919 //
2920 // 1) Translates the current position's time to directshow time,
2921 // which is in a scale of 1 second (in a double)
2922 // 2) Sets the play position of the IMediaSeeking interface -
2923 // passing NULL as the stop position means to keep the old
2924 // stop position
2925 //---------------------------------------------------------------------------
2926 bool wxAMMediaBackend::SetPosition(wxLongLong where)
2927 {
2928 HRESULT hr = m_pAM->put_CurrentPosition(
2929 ((LONGLONG)where.GetValue()) / 1000.0
2930 );
2931 if(FAILED(hr))
2932 {
2933 wxAMLOG(hr);
2934 return false;
2935 }
2936
2937 return true;
2938 }
2939
2940 //---------------------------------------------------------------------------
2941 // wxAMMediaBackend::GetPosition
2942 //
2943 // 1) Obtains the current play and stop positions from IMediaSeeking
2944 // 2) Returns the play position translated to our time base
2945 //---------------------------------------------------------------------------
2946 wxLongLong wxAMMediaBackend::GetPosition()
2947 {
2948 double outCur;
2949 HRESULT hr = m_pAM->get_CurrentPosition(&outCur);
2950 if(FAILED(hr))
2951 {
2952 wxAMLOG(hr);
2953 return 0;
2954 }
2955
2956 //h,m,s,milli - outdur is in 1 second (double)
2957 outCur *= 1000;
2958 wxLongLong ll;
2959 ll.Assign(outCur);
2960
2961 return ll;
2962 }
2963
2964 //---------------------------------------------------------------------------
2965 // wxAMMediaBackend::GetVolume
2966 //
2967 // Gets the volume through the IBasicAudio interface -
2968 // value ranges from 0 (MAX volume) to -10000 (minimum volume).
2969 // -100 per decibel.
2970 //---------------------------------------------------------------------------
2971 double wxAMMediaBackend::GetVolume()
2972 {
2973 long lVolume;
2974 HRESULT hr = m_pAM->get_Volume(&lVolume);
2975 if(FAILED(hr))
2976 {
2977 wxAMLOG(hr);
2978 return 0.0;
2979 }
2980 return pow(10.0, lVolume/2000.0);
2981 }
2982
2983 //---------------------------------------------------------------------------
2984 // wxAMMediaBackend::SetVolume
2985 //
2986 // Sets the volume through the IBasicAudio interface -
2987 // value ranges from 0 (MAX volume) to -10000 (minimum volume).
2988 // -100 per decibel.
2989 //---------------------------------------------------------------------------
2990 bool wxAMMediaBackend::SetVolume(double dVolume)
2991 {
2992 //pow(10.0, -80.0) to correct 0 == -INF
2993 long lVolume = (2000.0 * log10(pow(10.0, -80.0)+dVolume));
2994 HRESULT hr = m_pAM->put_Volume( lVolume );
2995 if(FAILED(hr))
2996 {
2997 wxAMLOG(hr);
2998 return false;
2999 }
3000 return true;
3001 }
3002
3003 //---------------------------------------------------------------------------
3004 // wxAMMediaBackend::GetDuration
3005 //
3006 // 1) Obtains the duration of the media from IAMMultiMediaStream
3007 // 2) Converts that value to our time base, and returns it
3008 //
3009 // NB: With VBR MP3 files the default DirectShow MP3 render does not
3010 // read the Xing header correctly, resulting in skewed values for duration
3011 // and seeking
3012 //---------------------------------------------------------------------------
3013 wxLongLong wxAMMediaBackend::GetDuration()
3014 {
3015 double outDuration;
3016 HRESULT hr = m_pAM->get_Duration(&outDuration);
3017 if(FAILED(hr))
3018 {
3019 wxAMLOG(hr);
3020 return 0;
3021 }
3022
3023 //h,m,s,milli - outdur is in 1 second (double)
3024 outDuration *= 1000;
3025 wxLongLong ll;
3026 ll.Assign(outDuration);
3027
3028 return ll;
3029 }
3030
3031 //---------------------------------------------------------------------------
3032 // wxAMMediaBackend::GetState
3033 //
3034 // Returns the cached state
3035 //---------------------------------------------------------------------------
3036 wxMediaState wxAMMediaBackend::GetState()
3037 {
3038 StateConstants nState;
3039 HRESULT hr = m_pAM->get_CurrentState(&nState);
3040 if(FAILED(hr))
3041 {
3042 wxAMLOG(hr);
3043 return wxMEDIASTATE_STOPPED;
3044 }
3045
3046 return (wxMediaState)nState;
3047 }
3048
3049 //---------------------------------------------------------------------------
3050 // wxAMMediaBackend::GetPlaybackRate
3051 //
3052 // Pretty simple way of obtaining the playback rate from
3053 // the IMediaSeeking interface
3054 //---------------------------------------------------------------------------
3055 double wxAMMediaBackend::GetPlaybackRate()
3056 {
3057 double dRate;
3058 HRESULT hr = m_pAM->get_Rate(&dRate);
3059 if(FAILED(hr))
3060 {
3061 wxAMLOG(hr);
3062 return 0.0;
3063 }
3064 return dRate;
3065 }
3066
3067 //---------------------------------------------------------------------------
3068 // wxAMMediaBackend::SetPlaybackRate
3069 //
3070 // Sets the playback rate of the media - DirectShow is pretty good
3071 // about this, actually
3072 //---------------------------------------------------------------------------
3073 bool wxAMMediaBackend::SetPlaybackRate(double dRate)
3074 {
3075 HRESULT hr = m_pAM->put_Rate(dRate);
3076 if(FAILED(hr))
3077 {
3078 wxAMLOG(hr);
3079 return false;
3080 }
3081
3082 return true;
3083 }
3084
3085 //---------------------------------------------------------------------------
3086 // wxAMMediaBackend::GetDownloadXXX
3087 //
3088 // Queries for and gets the total size of the file and the current
3089 // progress in downloading that file from the IAMOpenProgress
3090 // interface from the media player interface's filter graph
3091 //---------------------------------------------------------------------------
3092 void wxAMMediaBackend::DoGetDownloadProgress(wxLongLong* pLoadProgress,
3093 wxLongLong* pLoadTotal)
3094 {
3095 LONGLONG loadTotal = 0, loadProgress = 0;
3096 IUnknown* pFG;
3097 IAMOpenProgress* pOP;
3098 HRESULT hr;
3099 hr = m_pAM->get_FilterGraph(&pFG);
3100 if(SUCCEEDED(hr))
3101 {
3102 hr = pFG->QueryInterface(IID_IAMOpenProgress, (void**)&pOP);
3103 if(SUCCEEDED(hr))
3104 {
3105 hr = pOP->QueryProgress(&loadTotal, &loadProgress);
3106 pOP->Release();
3107 }
3108 pFG->Release();
3109 }
3110
3111 if(SUCCEEDED(hr))
3112 {
3113 *pLoadProgress = loadProgress;
3114 *pLoadTotal = loadTotal;
3115 }
3116 else
3117 {
3118 //When not loading from a URL QueryProgress will return
3119 //E_NOINTERFACE or whatever
3120 //wxAMFAIL(hr);
3121 *pLoadProgress = 0;
3122 *pLoadTotal = 0;
3123 }
3124 }
3125
3126 //---------------------------------------------------------------------------
3127 // wxAMMediaBackend::GetVideoSize
3128 //
3129 // Obtains the cached original video size
3130 //---------------------------------------------------------------------------
3131 wxSize wxAMMediaBackend::GetVideoSize() const
3132 {
3133 return m_bestSize;
3134 }
3135
3136 //---------------------------------------------------------------------------
3137 // wxAMMediaBackend::Move
3138 //
3139 // We take care of this in our redrawing
3140 //---------------------------------------------------------------------------
3141 void wxAMMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y),
3142 int WXUNUSED(w), int WXUNUSED(h))
3143 {
3144 }
3145
3146 //---------------------------------------------------------------------------
3147 // wxAMMediaEvtHandler::OnEraseBackground
3148 //
3149 // Tell WX not to erase the background of our control window
3150 // so that resizing is a bit smoother
3151 //---------------------------------------------------------------------------
3152 void wxAMMediaEvtHandler::OnEraseBackground(wxEraseEvent& WXUNUSED(evt))
3153 {
3154 }
3155
3156 //---------------------------------------------------------------------------
3157 // End of wxAMMediaBackend
3158 //---------------------------------------------------------------------------
3159
3160 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3161 //
3162 // wxMCIMediaBackend
3163 //
3164 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3165
3166 IMPLEMENT_DYNAMIC_CLASS(wxMCIMediaBackend, wxMediaBackend);
3167
3168 //---------------------------------------------------------------------------
3169 // Usual debugging macros for MCI returns
3170 //---------------------------------------------------------------------------
3171
3172 #ifdef __WXDEBUG__
3173 #define wxMCIVERIFY(arg) \
3174 { \
3175 DWORD nRet; \
3176 if ( (nRet = (arg)) != 0) \
3177 { \
3178 TCHAR sz[5000]; \
3179 mciGetErrorString(nRet, sz, 5000); \
3180 wxFAIL_MSG(wxString::Format(_T("MCI Error:%s"), sz)); \
3181 } \
3182 }
3183 #else
3184 #define wxMCIVERIFY(arg) (arg);
3185 #endif
3186
3187 //---------------------------------------------------------------------------
3188 // Simulation for <digitalv.h>
3189 //
3190 // Mingw and possibly other compilers don't have the digitalv.h header
3191 // that is needed to have some essential features of mci work with
3192 // windows - so we provide the declarations for the types we use here
3193 //---------------------------------------------------------------------------
3194
3195 typedef struct {
3196 DWORD_PTR dwCallback;
3197 #ifdef MCI_USE_OFFEXT
3198 POINT ptOffset;
3199 POINT ptExtent;
3200 #else
3201 RECT rc;
3202 #endif
3203 } MCI_DGV_RECT_PARMS;
3204
3205 typedef struct {
3206 DWORD_PTR dwCallback;
3207 HWND hWnd;
3208 #ifndef _WIN32
3209 WORD wReserved1;
3210 #endif
3211 UINT nCmdShow;
3212 #ifndef _WIN32
3213 WORD wReserved2;
3214 #endif
3215 wxChar* lpstrText;
3216 } MCI_DGV_WINDOW_PARMS;
3217
3218 typedef struct {
3219 DWORD_PTR dwCallback;
3220 DWORD dwTimeFormat;
3221 DWORD dwAudio;
3222 DWORD dwFileFormat;
3223 DWORD dwSpeed;
3224 } MCI_DGV_SET_PARMS;
3225
3226 typedef struct {
3227 DWORD_PTR dwCallback;
3228 DWORD dwItem;
3229 DWORD dwValue;
3230 DWORD dwOver;
3231 wxChar* lpstrAlgorithm;
3232 wxChar* lpstrQuality;
3233 } MCI_DGV_SETAUDIO_PARMS;
3234
3235 //---------------------------------------------------------------------------
3236 // wxMCIMediaBackend Constructor
3237 //
3238 // Here we don't need to do much except say we don't have any video :)
3239 //---------------------------------------------------------------------------
3240 wxMCIMediaBackend::wxMCIMediaBackend() : m_hNotifyWnd(NULL), m_bVideo(false)
3241 {
3242 }
3243
3244 //---------------------------------------------------------------------------
3245 // wxMCIMediaBackend Destructor
3246 //
3247 // We close the mci device - note that there may not be an mci device here,
3248 // or it may fail - but we don't really care, since we're destructing
3249 //---------------------------------------------------------------------------
3250 wxMCIMediaBackend::~wxMCIMediaBackend()
3251 {
3252 if(m_hNotifyWnd)
3253 {
3254 mciSendCommand(m_hDev, MCI_CLOSE, 0, 0);
3255 DestroyWindow(m_hNotifyWnd);
3256 m_hNotifyWnd = NULL;
3257 }
3258 }
3259
3260 //---------------------------------------------------------------------------
3261 // wxMCIMediaBackend::Create
3262 //
3263 // Here we just tell wxMediaCtrl that mci does exist (which it does, on all
3264 // msw systems, at least in some form dating back to win16 days)
3265 //---------------------------------------------------------------------------
3266 bool wxMCIMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
3267 wxWindowID id,
3268 const wxPoint& pos,
3269 const wxSize& size,
3270 long style,
3271 const wxValidator& validator,
3272 const wxString& name)
3273 {
3274 //
3275 // Create window
3276 // By default wxWindow(s) is created with a border -
3277 // so we need to get rid of those, and create with
3278 // wxCLIP_CHILDREN, so that if the driver/backend
3279 // is a child window, it refereshes properly
3280 //
3281 if ( !ctrl->wxControl::Create(parent, id, pos, size,
3282 (style & ~wxBORDER_MASK) | wxBORDER_NONE | wxCLIP_CHILDREN,
3283 validator, name) )
3284 return false;
3285
3286 m_ctrl = ctrl;
3287 return true;
3288 }
3289
3290 //---------------------------------------------------------------------------
3291 // wxMCIMediaBackend::Load (file version)
3292 //
3293 // Here we have MCI load a file and device, set the time format to our
3294 // default (milliseconds), and set the video (if any) to play in the control
3295 //---------------------------------------------------------------------------
3296 bool wxMCIMediaBackend::Load(const wxString& fileName)
3297 {
3298 //
3299 //if the user already called load close the previous MCI device
3300 //
3301 if(m_hNotifyWnd)
3302 {
3303 mciSendCommand(m_hDev, MCI_CLOSE, 0, 0);
3304 DestroyWindow(m_hNotifyWnd);
3305 m_hNotifyWnd = NULL;
3306 }
3307
3308 //
3309 //Opens a file and has MCI select a device. Normally you'd put
3310 //MCI_OPEN_TYPE in addition to MCI_OPEN_ELEMENT - however if you
3311 //omit this it tells MCI to select the device instead. This is
3312 //good because we have no reliable way of "enumerating" the devices
3313 //in MCI
3314 //
3315 MCI_OPEN_PARMS openParms;
3316 openParms.lpstrElementName = (wxChar*) fileName.c_str();
3317
3318 if ( mciSendCommand(0, MCI_OPEN, MCI_OPEN_ELEMENT,
3319 (DWORD)(LPVOID)&openParms) != 0)
3320 return false;
3321
3322 m_hDev = openParms.wDeviceID;
3323
3324 //
3325 //Now set the time format for the device to milliseconds
3326 //
3327 MCI_SET_PARMS setParms;
3328 setParms.dwCallback = 0;
3329 setParms.dwTimeFormat = MCI_FORMAT_MILLISECONDS;
3330
3331 if (mciSendCommand(m_hDev, MCI_SET, MCI_SET_TIME_FORMAT,
3332 (DWORD)(LPVOID)&setParms) != 0)
3333 return false;
3334
3335 //
3336 //Now tell the MCI device to display the video in our wxMediaCtrl
3337 //
3338 MCI_DGV_WINDOW_PARMS windowParms;
3339 windowParms.hWnd = (HWND)m_ctrl->GetHandle();
3340
3341 m_bVideo = (mciSendCommand(m_hDev, MCI_WINDOW,
3342 0x00010000L, //MCI_DGV_WINDOW_HWND
3343 (DWORD)(LPVOID)&windowParms) == 0);
3344
3345 //
3346 // Create a hidden window and register to handle
3347 // MCI events
3348 // Note that wxCanvasClassName is already registered
3349 // and used by all wxWindows and normal wxControls
3350 //
3351 m_hNotifyWnd = ::CreateWindow
3352 (
3353 wxCanvasClassName,
3354 NULL,
3355 0, 0, 0, 0,
3356 0,
3357 (HWND) NULL,
3358 (HMENU)NULL,
3359 wxGetInstance(),
3360 (LPVOID) NULL
3361 );
3362
3363 if(!m_hNotifyWnd)
3364 {
3365 wxLogSysError( wxT("Could not create hidden needed for ")
3366 wxT("registering for MCI events!") );
3367
3368 return false;
3369 }
3370
3371 wxSetWindowProc(m_hNotifyWnd, wxMCIMediaBackend::NotifyWndProc);
3372 wxSetWindowUserData(m_hNotifyWnd, this);
3373
3374 //
3375 //Here, if the parent of the control has a sizer - we
3376 //tell it to recalculate the size of this control since
3377 //the user opened a separate media file
3378 //
3379 m_ctrl->InvalidateBestSize();
3380 m_ctrl->GetParent()->Layout();
3381 m_ctrl->GetParent()->Refresh();
3382 m_ctrl->GetParent()->Update();
3383 m_ctrl->SetSize(m_ctrl->GetSize());
3384
3385 //send loaded event
3386 wxMediaEvent theEvent(wxEVT_MEDIA_LOADED,
3387 m_ctrl->GetId());
3388 m_ctrl->AddPendingEvent(theEvent);
3389
3390 return true;
3391 }
3392
3393 //---------------------------------------------------------------------------
3394 // wxMCIMediaBackend::Load (URL version)
3395 //
3396 // MCI doesn't support URLs directly (?)
3397 //
3398 // TODO: Use wxURL/wxFileSystem and mmioInstallProc
3399 //---------------------------------------------------------------------------
3400 bool wxMCIMediaBackend::Load(const wxURI& WXUNUSED(location))
3401 {
3402 return false;
3403 }
3404
3405 //---------------------------------------------------------------------------
3406 // wxMCIMediaBackend::Play
3407 //
3408 // Plays/Resumes the MCI device... a couple notes:
3409 // 1) Certain drivers will crash and burn if we don't pass them an
3410 // MCI_PLAY_PARMS, despite the documentation that says otherwise...
3411 // 2) There is a MCI_RESUME command, but MCI_PLAY does the same thing
3412 // and will resume from a stopped state also, so there's no need to
3413 // call both, for example
3414 //---------------------------------------------------------------------------
3415 bool wxMCIMediaBackend::Play()
3416 {
3417 MCI_PLAY_PARMS playParms;
3418 playParms.dwCallback = (DWORD)m_hNotifyWnd;
3419
3420 bool bOK = ( mciSendCommand(m_hDev, MCI_PLAY, MCI_NOTIFY,
3421 (DWORD)(LPVOID)&playParms) == 0 );
3422
3423 if(bOK)
3424 m_ctrl->Show(m_bVideo);
3425
3426 return bOK;
3427 }
3428
3429 //---------------------------------------------------------------------------
3430 // wxMCIMediaBackend::Pause
3431 //
3432 // Pauses the MCI device - nothing special
3433 //---------------------------------------------------------------------------
3434 bool wxMCIMediaBackend::Pause()
3435 {
3436 return (mciSendCommand(m_hDev, MCI_PAUSE, MCI_WAIT, 0) == 0);
3437 }
3438
3439 //---------------------------------------------------------------------------
3440 // wxMCIMediaBackend::Stop
3441 //
3442 // Stops the MCI device & seeks to the beginning as wxMediaCtrl docs outline
3443 //---------------------------------------------------------------------------
3444 bool wxMCIMediaBackend::Stop()
3445 {
3446 return (mciSendCommand(m_hDev, MCI_STOP, MCI_WAIT, 0) == 0) &&
3447 (mciSendCommand(m_hDev, MCI_SEEK, MCI_SEEK_TO_START, 0) == 0);
3448 }
3449
3450 //---------------------------------------------------------------------------
3451 // wxMCIMediaBackend::GetState
3452 //
3453 // Here we get the state and convert it to a wxMediaState -
3454 // since we use direct comparisons with MCI_MODE_PLAY and
3455 // MCI_MODE_PAUSE, we don't care if the MCI_STATUS call
3456 // fails or not
3457 //---------------------------------------------------------------------------
3458 wxMediaState wxMCIMediaBackend::GetState()
3459 {
3460 MCI_STATUS_PARMS statusParms;
3461 statusParms.dwItem = MCI_STATUS_MODE;
3462
3463 mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
3464 (DWORD)(LPVOID)&statusParms);
3465
3466 if(statusParms.dwReturn == MCI_MODE_PAUSE)
3467 return wxMEDIASTATE_PAUSED;
3468 else if(statusParms.dwReturn == MCI_MODE_PLAY)
3469 return wxMEDIASTATE_PLAYING;
3470 else
3471 return wxMEDIASTATE_STOPPED;
3472 }
3473
3474 //---------------------------------------------------------------------------
3475 // wxMCIMediaBackend::SetPosition
3476 //
3477 // Here we set the position of the device in the stream.
3478 // Note that MCI actually stops the device after you seek it if the
3479 // device is playing/paused, so we need to play the file after
3480 // MCI seeks like normal APIs would
3481 //---------------------------------------------------------------------------
3482 bool wxMCIMediaBackend::SetPosition(wxLongLong where)
3483 {
3484 MCI_SEEK_PARMS seekParms;
3485 seekParms.dwCallback = 0;
3486 #if wxUSE_LONGLONG_NATIVE && !wxUSE_LONGLONG_WX
3487 seekParms.dwTo = (DWORD)where.GetValue();
3488 #else /* wxUSE_LONGLONG_WX */
3489 /* no way to return it in one piece */
3490 wxASSERT( where.GetHi()==0 );
3491 seekParms.dwTo = (DWORD)where.GetLo();
3492 #endif /* wxUSE_LONGLONG_* */
3493
3494 //device was playing?
3495 bool bReplay = GetState() == wxMEDIASTATE_PLAYING;
3496
3497 if( mciSendCommand(m_hDev, MCI_SEEK, MCI_TO,
3498 (DWORD)(LPVOID)&seekParms) != 0)
3499 return false;
3500
3501 //If the device was playing, resume it
3502 if (bReplay)
3503 return Play();
3504 else
3505 return true;
3506 }
3507
3508 //---------------------------------------------------------------------------
3509 // wxMCIMediaBackend::GetPosition
3510 //
3511 // Gets the position of the device in the stream using the current
3512 // time format... nothing special here...
3513 //---------------------------------------------------------------------------
3514 wxLongLong wxMCIMediaBackend::GetPosition()
3515 {
3516 MCI_STATUS_PARMS statusParms;
3517 statusParms.dwItem = MCI_STATUS_POSITION;
3518
3519 if (mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
3520 (DWORD)(LPSTR)&statusParms) != 0)
3521 return 0;
3522
3523 return statusParms.dwReturn;
3524 }
3525
3526 //---------------------------------------------------------------------------
3527 // wxMCIMediaBackend::GetVolume
3528 //
3529 // Gets the volume of the current media via the MCI_DGV_STATUS_VOLUME
3530 // message. Value ranges from 0 (minimum) to 1000 (maximum volume).
3531 //---------------------------------------------------------------------------
3532 double wxMCIMediaBackend::GetVolume()
3533 {
3534 MCI_STATUS_PARMS statusParms;
3535 statusParms.dwCallback = 0;
3536 statusParms.dwItem = 0x4019; //MCI_DGV_STATUS_VOLUME
3537
3538 if (mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
3539 (DWORD)(LPSTR)&statusParms) != 0)
3540 return 0;
3541
3542 return ((double)statusParms.dwReturn) / 1000.0;
3543 }
3544
3545 //---------------------------------------------------------------------------
3546 // wxMCIMediaBackend::SetVolume
3547 //
3548 // Sets the volume of the current media via the MCI_DGV_SETAUDIO_VOLUME
3549 // message. Value ranges from 0 (minimum) to 1000 (maximum volume).
3550 //---------------------------------------------------------------------------
3551 bool wxMCIMediaBackend::SetVolume(double dVolume)
3552 {
3553 MCI_DGV_SETAUDIO_PARMS audioParms;
3554 audioParms.dwCallback = 0;
3555 audioParms.dwItem = 0x4002; //MCI_DGV_SETAUDIO_VOLUME
3556 audioParms.dwValue = (DWORD) (dVolume * 1000.0);
3557 audioParms.dwOver = 0;
3558 audioParms.lpstrAlgorithm = NULL;
3559 audioParms.lpstrQuality = NULL;
3560
3561 if (mciSendCommand(m_hDev, 0x0873, //MCI_SETAUDIO
3562 //MCI_DGV_SETAUDIO+(_ITEM | _VALUE)
3563 0x00800000L | 0x01000000L,
3564 (DWORD)(LPSTR)&audioParms) != 0)
3565 return false;
3566 return true;
3567 }
3568
3569 //---------------------------------------------------------------------------
3570 // wxMCIMediaBackend::GetDuration
3571 //
3572 // Gets the duration of the stream... nothing special
3573 //---------------------------------------------------------------------------
3574 wxLongLong wxMCIMediaBackend::GetDuration()
3575 {
3576 MCI_STATUS_PARMS statusParms;
3577 statusParms.dwItem = MCI_STATUS_LENGTH;
3578
3579 if (mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
3580 (DWORD)(LPSTR)&statusParms) != 0)
3581 return 0;
3582
3583 return statusParms.dwReturn;
3584 }
3585
3586 //---------------------------------------------------------------------------
3587 // wxMCIMediaBackend::Move
3588 //
3589 // Moves the window to a location
3590 //---------------------------------------------------------------------------
3591 void wxMCIMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y),
3592 int w, int h)
3593 {
3594 if (m_hNotifyWnd && m_bVideo)
3595 {
3596 MCI_DGV_RECT_PARMS putParms; //ifdefed MCI_DGV_PUT_PARMS
3597 memset(&putParms, 0, sizeof(MCI_DGV_RECT_PARMS));
3598 putParms.rc.bottom = h;
3599 putParms.rc.right = w;
3600
3601 //wxStackWalker will crash and burn here on assert
3602 //and mci doesn't like 0 and 0 for some reason (out of range )
3603 //so just don't it in that case
3604 if(w || h)
3605 {
3606 wxMCIVERIFY( mciSendCommand(m_hDev, MCI_PUT,
3607 0x00040000L, //MCI_DGV_PUT_DESTINATION
3608 (DWORD)(LPSTR)&putParms) );
3609 }
3610 }
3611 }
3612
3613 //---------------------------------------------------------------------------
3614 // wxMCIMediaBackend::GetVideoSize
3615 //
3616 // Gets the original size of the movie for sizers
3617 //---------------------------------------------------------------------------
3618 wxSize wxMCIMediaBackend::GetVideoSize() const
3619 {
3620 if(m_bVideo)
3621 {
3622 MCI_DGV_RECT_PARMS whereParms; //ifdefed MCI_DGV_WHERE_PARMS
3623
3624 wxMCIVERIFY( mciSendCommand(m_hDev, MCI_WHERE,
3625 0x00020000L, //MCI_DGV_WHERE_SOURCE
3626 (DWORD)(LPSTR)&whereParms) );
3627
3628 return wxSize(whereParms.rc.right, whereParms.rc.bottom);
3629 }
3630 return wxSize(0,0);
3631 }
3632
3633 //---------------------------------------------------------------------------
3634 // wxMCIMediaBackend::GetPlaybackRate
3635 //
3636 // TODO
3637 //---------------------------------------------------------------------------
3638 double wxMCIMediaBackend::GetPlaybackRate()
3639 {
3640 return 1.0;
3641 }
3642
3643 //---------------------------------------------------------------------------
3644 // wxMCIMediaBackend::SetPlaybackRate
3645 //
3646 // TODO
3647 //---------------------------------------------------------------------------
3648 bool wxMCIMediaBackend::SetPlaybackRate(double WXUNUSED(dRate))
3649 {
3650 /*
3651 MCI_WAVE_SET_SAMPLESPERSEC
3652 MCI_DGV_SET_PARMS setParms;
3653 setParms.dwSpeed = (DWORD) (dRate * 1000.0);
3654
3655 return (mciSendCommand(m_hDev, MCI_SET,
3656 0x00020000L, //MCI_DGV_SET_SPEED
3657 (DWORD)(LPSTR)&setParms) == 0);
3658 */
3659 return false;
3660 }
3661
3662 //---------------------------------------------------------------------------
3663 // [static] wxMCIMediaBackend::MSWWindowProc
3664 //
3665 // Here we process a message when MCI reaches the stopping point
3666 // in the stream
3667 //---------------------------------------------------------------------------
3668 LRESULT CALLBACK wxMCIMediaBackend::NotifyWndProc(HWND hWnd, UINT nMsg,
3669 WPARAM wParam,
3670 LPARAM lParam)
3671 {
3672 wxMCIMediaBackend* backend =
3673 (wxMCIMediaBackend*)wxGetWindowUserData(hWnd);
3674
3675 return backend->OnNotifyWndProc(hWnd, nMsg, wParam, lParam);
3676 }
3677
3678 LRESULT CALLBACK wxMCIMediaBackend::OnNotifyWndProc(HWND hWnd, UINT nMsg,
3679 WPARAM wParam,
3680 LPARAM lParam)
3681 {
3682 if(nMsg == MM_MCINOTIFY)
3683 {
3684 wxASSERT(lParam == (LPARAM) m_hDev);
3685 if(wParam == MCI_NOTIFY_SUCCESSFUL && lParam == (LPARAM)m_hDev)
3686 {
3687 wxMediaEvent theEvent(wxEVT_MEDIA_STOP, m_ctrl->GetId());
3688 m_ctrl->ProcessEvent(theEvent);
3689
3690 if(theEvent.IsAllowed())
3691 {
3692 wxMCIVERIFY( mciSendCommand(m_hDev, MCI_SEEK,
3693 MCI_SEEK_TO_START, 0) );
3694
3695 //send the event to our child
3696 wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED,
3697 m_ctrl->GetId());
3698 m_ctrl->ProcessEvent(theEvent);
3699 }
3700 }
3701 }
3702 return DefWindowProc(hWnd, nMsg, wParam, lParam);
3703 }
3704
3705 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3706 //
3707 // wxQTMediaBackend
3708 //
3709 // TODO: Use a less cludgy way to pause/get state/set state
3710 // FIXME: Greg Hazel reports that sometimes files that cannot be played
3711 // with this backend are treated as playable anyway - not verifyed though.
3712 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3713
3714 IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend);
3715
3716 //Time between timer calls - this is the Apple recommondation to the TCL
3717 //team I believe
3718 #define MOVIE_DELAY 20
3719
3720 #include "wx/timer.h"
3721
3722
3723 //---------------------------------------------------------------------------
3724 // wxQTLoadTimer
3725 //
3726 // QT, esp. QT for Windows is very picky about how you go about
3727 // async loading. If you were to go through a Windows message loop
3728 // or a MoviesTask or both and then check the movie load state
3729 // it would still return 1000 (loading)... even (pre)prerolling doesn't
3730 // help. However, making a load timer like this works
3731 //---------------------------------------------------------------------------
3732 class wxQTLoadTimer : public wxTimer
3733 {
3734 public:
3735 wxQTLoadTimer(Movie movie, wxQTMediaBackend* parent, wxQuickTimeLibrary* pLib) :
3736 m_movie(movie), m_parent(parent), m_pLib(pLib) {}
3737
3738 void Notify()
3739 {
3740 m_pLib->MoviesTask(m_movie, 0);
3741 //kMovieLoadStatePlayable
3742 if(m_pLib->GetMovieLoadState(m_movie) >= 10000)
3743 {
3744 m_parent->FinishLoad();
3745 delete this;
3746 }
3747 }
3748
3749 protected:
3750 Movie m_movie; //Our movie instance
3751 wxQTMediaBackend* m_parent; //Backend pointer
3752 wxQuickTimeLibrary* m_pLib; //Interfaces
3753 };
3754
3755
3756 // --------------------------------------------------------------------------
3757 // wxQTPlayTimer - Handle Asyncronous Playing
3758 //
3759 // 1) Checks to see if the movie is done, and if not continues
3760 // streaming the movie
3761 // 2) Sends the wxEVT_MEDIA_STOP event if we have reached the end of
3762 // the movie.
3763 // --------------------------------------------------------------------------
3764 class wxQTPlayTimer : public wxTimer
3765 {
3766 public:
3767 wxQTPlayTimer(Movie movie, wxQTMediaBackend* parent,
3768 wxQuickTimeLibrary* pLib) :
3769 m_movie(movie), m_parent(parent), m_pLib(pLib) {}
3770
3771 void Notify()
3772 {
3773 //
3774 // OK, a little explaining - basically originally
3775 // we only called MoviesTask if the movie was actually
3776 // playing (not paused or stopped)... this was before
3777 // we realized MoviesTask actually handles repainting
3778 // of the current frame - so if you were to resize
3779 // or something it would previously not redraw that
3780 // portion of the movie.
3781 //
3782 // So now we call MoviesTask always so that it repaints
3783 // correctly.
3784 //
3785 m_pLib->MoviesTask(m_movie, 0);
3786
3787 //
3788 // Handle the stop event - if the movie has reached
3789 // the end, notify our handler
3790 //
3791 // m_bPlaying == !(Stopped | Paused)
3792 //
3793 if (m_parent->m_bPlaying)
3794 {
3795 if(m_pLib->IsMovieDone(m_movie))
3796 {
3797 wxMediaEvent theEvent(wxEVT_MEDIA_STOP,
3798 m_parent->m_ctrl->GetId());
3799 m_parent->m_ctrl->ProcessEvent(theEvent);
3800
3801 if(theEvent.IsAllowed())
3802 {
3803 m_parent->Stop();
3804 wxASSERT(m_pLib->GetMoviesError() == noErr);
3805
3806 //send the event to our child
3807 wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED,
3808 m_parent->m_ctrl->GetId());
3809 m_parent->m_ctrl->AddPendingEvent(theEvent);
3810 }
3811 }
3812 }
3813 }
3814
3815 protected:
3816 Movie m_movie; //Our movie instance
3817 wxQTMediaBackend* m_parent; //Backend pointer
3818 wxQuickTimeLibrary* m_pLib; //Interfaces
3819 };
3820
3821
3822 //---------------------------------------------------------------------------
3823 // wxQTMediaBackend::QTWndProc
3824 //
3825 // Forwards events to the Movie Controller so that it can
3826 // redraw itself/process messages etc..
3827 //---------------------------------------------------------------------------
3828 LRESULT CALLBACK wxQTMediaBackend::QTWndProc(HWND hWnd, UINT nMsg,
3829 WPARAM wParam, LPARAM lParam)
3830 {
3831 wxQTMediaBackend* pThis = (wxQTMediaBackend*)wxGetWindowUserData(hWnd);
3832
3833 MSG msg;
3834 msg.hwnd = hWnd;
3835 msg.message = nMsg;
3836 msg.wParam = wParam;
3837 msg.lParam = lParam;
3838 msg.time = 0;
3839 msg.pt.x = 0;
3840 msg.pt.y = 0;
3841 EventRecord theEvent;
3842 pThis->m_lib.NativeEventToMacEvent(&msg, &theEvent);
3843 pThis->m_lib.MCIsPlayerEvent(pThis->m_pMC, &theEvent);
3844 return pThis->m_ctrl->MSWWindowProc(nMsg, wParam, lParam);
3845 }
3846
3847 //---------------------------------------------------------------------------
3848 // wxQTMediaBackend Destructor
3849 //
3850 // Sets m_timer to NULL signifying we havn't loaded anything yet
3851 //---------------------------------------------------------------------------
3852 wxQTMediaBackend::wxQTMediaBackend()
3853 : m_movie(NULL), m_bPlaying(false), m_timer(NULL), m_pMC(NULL)
3854 {
3855 }
3856
3857 //---------------------------------------------------------------------------
3858 // wxQTMediaBackend Destructor
3859 //
3860 // 1) Cleans up the QuickTime movie instance
3861 // 2) Decrements the QuickTime reference counter - if this reaches
3862 // 0, QuickTime shuts down
3863 // 3) Decrements the QuickTime Windows Media Layer reference counter -
3864 // if this reaches 0, QuickTime shuts down the Windows Media Layer
3865 //---------------------------------------------------------------------------
3866 wxQTMediaBackend::~wxQTMediaBackend()
3867 {
3868 if(m_movie)
3869 Cleanup();
3870
3871 if(m_lib.IsOk())
3872 {
3873 if(m_pMC)
3874 {
3875 m_lib.DisposeMovieController(m_pMC);
3876 // m_pMC = NULL;
3877 }
3878
3879 m_lib.DestroyPortAssociation(
3880 (CGrafPtr)m_lib.GetNativeWindowPort(m_ctrl->GetHWND()));
3881
3882 //Note that ExitMovies() is not necessary, but
3883 //the docs are fuzzy on whether or not TerminateQTML is
3884 m_lib.ExitMovies();
3885 m_lib.TerminateQTML();
3886 }
3887 }
3888
3889 //---------------------------------------------------------------------------
3890 // wxQTMediaBackend::CreateControl
3891 //
3892 // 1) Intializes QuickTime
3893 // 2) Creates the control window
3894 //---------------------------------------------------------------------------
3895 bool wxQTMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
3896 wxWindowID id,
3897 const wxPoint& pos,
3898 const wxSize& size,
3899 long style,
3900 const wxValidator& validator,
3901 const wxString& name)
3902 {
3903 if(!m_lib.Initialize())
3904 return false;
3905
3906 int nError = m_lib.InitializeQTML(0);
3907 if (nError != noErr) //-2093 no dll
3908 {
3909 wxFAIL_MSG(wxString::Format(wxT("Couldn't Initialize Quicktime-%i"),
3910 nError));
3911 return false;
3912 }
3913 m_lib.EnterMovies();
3914
3915 //
3916 // Create window
3917 // By default wxWindow(s) is created with a border -
3918 // so we need to get rid of those
3919 //
3920 // Since we don't have a child window like most other
3921 // backends, we don't need wxCLIP_CHILDREN
3922 //
3923 if ( !ctrl->wxControl::Create(parent, id, pos, size,
3924 (style & ~wxBORDER_MASK) | wxBORDER_NONE,
3925 validator, name) )
3926 return false;
3927
3928
3929 m_ctrl = ctrl; //assign the control to our member
3930
3931 // Create a port association for our window so we
3932 // can use it as a WindowRef
3933 m_lib.CreatePortAssociation(m_ctrl->GetHWND(), NULL, 0L);
3934
3935 //Part of a suggestion from Greg Hazel to repaint
3936 //movie when idle
3937 m_ctrl->Connect(m_ctrl->GetId(), wxEVT_ERASE_BACKGROUND,
3938 wxEraseEventHandler(wxQTMediaEvtHandler::OnEraseBackground),
3939 NULL, (wxEvtHandler*) this);
3940
3941 // done
3942 return true;
3943 }
3944
3945 //---------------------------------------------------------------------------
3946 // wxQTMediaBackend::Load (file version)
3947 //
3948 // 1) Get an FSSpec from the Windows path name
3949 // 2) Open the movie
3950 // 3) Obtain the movie instance from the movie resource
3951 // 4) Close the movie resource
3952 // 5) Finish loading
3953 //---------------------------------------------------------------------------
3954 bool wxQTMediaBackend::Load(const wxString& fileName)
3955 {
3956 if(m_movie)
3957 Cleanup();
3958
3959 short movieResFile = 0; //= 0 because of annoying VC6 warning
3960 FSSpec sfFile;
3961
3962 if (m_lib.NativePathNameToFSSpec ((char*) (const char*) fileName.mb_str(),
3963 &sfFile, 0) != noErr)
3964 return false;
3965
3966 if (m_lib.OpenMovieFile (&sfFile, &movieResFile, fsRdPerm) != noErr)
3967 return false;
3968
3969 short movieResID = 0;
3970 Str255 movieName;
3971
3972 OSErr err = m_lib.NewMovieFromFile (
3973 &m_movie,
3974 movieResFile,
3975 &movieResID,
3976 movieName,
3977 newMovieActive,
3978 NULL
3979 ); //wasChanged
3980
3981 //m_lib.GetMoviesStickyError() because it may not find the
3982 //proper codec and play black video and other strange effects,
3983 //not to mention mess up the dynamic backend loading scheme
3984 //of wxMediaCtrl - so it just does what the QuickTime player does
3985 if(err == noErr && m_lib.GetMoviesStickyError() == noErr)
3986 {
3987 m_lib.CloseMovieFile (movieResFile);
3988
3989 FinishLoad();
3990 return true;
3991 }
3992 else
3993 return false;
3994 }
3995
3996
3997 //---------------------------------------------------------------------------
3998 // wxQTMediaBackend::PPRMProc (static)
3999 //
4000 // Called when done PrePrerolling the movie.
4001 // Note that in 99% of the cases this does nothing...
4002 // Anyway we set up the loading timer here to tell us when the movie is done
4003 //---------------------------------------------------------------------------
4004 void wxQTMediaBackend::PPRMProc (Movie theMovie, OSErr theErr, void* theRefCon)
4005 {
4006 wxASSERT( theMovie );
4007 wxASSERT( theRefCon );
4008 wxASSERT( theErr == noErr );
4009
4010 wxQTMediaBackend* pBE = (wxQTMediaBackend*) theRefCon;
4011
4012 long lTime = pBE->m_lib.GetMovieTime(theMovie,NULL);
4013 Fixed rate = pBE->m_lib.GetMoviePreferredRate(theMovie);
4014 pBE->m_lib.PrerollMovie(theMovie,lTime,rate);
4015 pBE->m_timer = new wxQTLoadTimer(pBE->m_movie, pBE, &pBE->m_lib);
4016 pBE->m_timer->Start(MOVIE_DELAY);
4017 }
4018
4019
4020 //---------------------------------------------------------------------------
4021 // wxQTMediaBackend::Load (URL Version)
4022 //
4023 // 1) Build an escaped URI from location
4024 // 2) Create a handle to store the URI string
4025 // 3) Put the URI string inside the handle
4026 // 4) Make a QuickTime URL data ref from the handle with the URI in it
4027 // 5) Clean up the URI string handle
4028 // 6) Do some prerolling
4029 // 7) Finish Loading
4030 //---------------------------------------------------------------------------
4031 bool wxQTMediaBackend::Load(const wxURI& location)
4032 {
4033 if(m_movie)
4034 Cleanup();
4035
4036 wxString theURI = location.BuildURI();
4037
4038 Handle theHandle = m_lib.NewHandleClear(theURI.length() + 1);
4039 wxASSERT(theHandle);
4040
4041 m_lib.BlockMove(theURI.mb_str(), *theHandle, theURI.length() + 1);
4042
4043 //create the movie from the handle that refers to the URI
4044 OSErr err = m_lib.NewMovieFromDataRef(&m_movie, newMovieActive |
4045 newMovieAsyncOK
4046 /*|newMovieIdleImportOK*/,
4047 NULL, theHandle,
4048 URLDataHandlerSubType);
4049
4050 m_lib.DisposeHandle(theHandle);
4051
4052 if (err == noErr)
4053 {
4054 long timeNow;
4055 Fixed playRate;
4056
4057 timeNow = m_lib.GetMovieTime(m_movie, NULL);
4058 wxASSERT(m_lib.GetMoviesError() == noErr);
4059
4060 playRate = m_lib.GetMoviePreferredRate(m_movie);
4061 wxASSERT(m_lib.GetMoviesError() == noErr);
4062
4063 //
4064 // Note that the callback here is optional,
4065 // but without it PrePrerollMovie can be buggy
4066 // (see Apple ml). Also, some may wonder
4067 // why we need this at all - this is because
4068 // Apple docs say QuickTime streamed movies
4069 // require it if you don't use a Movie Controller,
4070 // which we don't by default.
4071 //
4072 m_lib.PrePrerollMovie(m_movie, timeNow, playRate,
4073 (WXFARPROC)wxQTMediaBackend::PPRMProc,
4074 (void*)this);
4075 return true;
4076 }
4077 else
4078 return false;
4079 }
4080
4081
4082 //---------------------------------------------------------------------------
4083 // wxQTMediaBackend::FinishLoad
4084 //
4085 // 1) Create the movie timer
4086 // 2) Get real size of movie for GetBestSize/sizers
4087 // 3) Set the movie time scale to something usable so that seeking
4088 // etc. will work correctly
4089 // 4) Set our Movie Controller to display the movie if it exists,
4090 // otherwise set the bounds of the Movie
4091 // 5) Refresh parent window
4092 //---------------------------------------------------------------------------
4093 void wxQTMediaBackend::FinishLoad()
4094 {
4095 // Create the playing/streaming timer
4096 m_timer = new wxQTPlayTimer(m_movie, (wxQTMediaBackend*) this, &m_lib);
4097 wxASSERT(m_timer);
4098 m_timer->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS);
4099
4100 //get the real size of the movie
4101 Rect outRect;
4102 memset(&outRect, 0, sizeof(Rect)); //for annoying VC6 warning
4103 m_lib.GetMovieNaturalBoundsRect (m_movie, &outRect);
4104 wxASSERT(m_lib.GetMoviesError() == noErr);
4105
4106 m_bestSize.x = outRect.right - outRect.left;
4107 m_bestSize.y = outRect.bottom - outRect.top;
4108
4109 //
4110 // Handle the movie GWorld
4111 //
4112 if(m_pMC)
4113 {
4114 Point thePoint;
4115 thePoint.h = thePoint.v = 0;
4116 m_lib.MCSetMovie(m_pMC, m_movie,
4117 m_lib.GetNativeWindowPort(m_ctrl->GetHandle()),
4118 thePoint);
4119 m_lib.MCSetVisible(m_pMC, true);
4120 m_bestSize.y += 16;
4121 }
4122 else
4123 {
4124 m_lib.SetMovieGWorld(m_movie,
4125 (CGrafPtr) m_lib.GetNativeWindowPort(m_ctrl->GetHWND()),
4126 NULL);
4127 }
4128
4129 //
4130 // Set the movie to millisecond precision
4131 //
4132 m_lib.SetMovieTimeScale(m_movie, 1000);
4133 wxASSERT(m_lib.GetMoviesError() == noErr);
4134
4135 //
4136 //Here, if the parent of the control has a sizer - we
4137 //tell it to recalculate the size of this control since
4138 //the user opened a separate media file
4139 //
4140 m_ctrl->InvalidateBestSize();
4141 m_ctrl->GetParent()->Layout();
4142 m_ctrl->GetParent()->Refresh();
4143 m_ctrl->GetParent()->Update();
4144 m_ctrl->SetSize(m_ctrl->GetSize());
4145
4146 //loaded - note that MoviesTask must and will be called before this
4147 //by the previous timer since this gets appended to the event list after
4148 //the timer's first go
4149 wxMediaEvent theEvent(wxEVT_MEDIA_LOADED,
4150 m_ctrl->GetId());
4151 m_ctrl->AddPendingEvent(theEvent);
4152 }
4153
4154 //---------------------------------------------------------------------------
4155 // wxQTMediaBackend::Play
4156 //
4157 // 1) Start the QT movie
4158 // 2) Start the movie loading timer
4159 //
4160 // NOTE: This will still return success even when
4161 // the movie is still loading, and as mentioned in wxQTLoadTimer
4162 // I don't know of a way to force this to be sync - so if its
4163 // still loading the function will return true but the movie will
4164 // still be in the stopped state
4165 //---------------------------------------------------------------------------
4166 bool wxQTMediaBackend::Play()
4167 {
4168 m_lib.StartMovie(m_movie);
4169 m_bPlaying = true;
4170 return m_lib.GetMoviesError() == noErr;
4171 }
4172
4173 //---------------------------------------------------------------------------
4174 // wxQTMediaBackend::Pause
4175 //
4176 // 1) Stop the movie
4177 // 2) Stop the movie timer
4178 //---------------------------------------------------------------------------
4179 bool wxQTMediaBackend::Pause()
4180 {
4181 m_bPlaying = false;
4182 m_lib.StopMovie(m_movie);
4183 return m_lib.GetMoviesError() == noErr;
4184 }
4185
4186 //---------------------------------------------------------------------------
4187 // wxQTMediaBackend::Stop
4188 //
4189 // 1) Stop the movie
4190 // 2) Stop the movie timer
4191 // 3) Seek to the beginning of the movie
4192 //---------------------------------------------------------------------------
4193 bool wxQTMediaBackend::Stop()
4194 {
4195 m_bPlaying = false;
4196
4197 m_lib.StopMovie(m_movie);
4198 if(m_lib.GetMoviesError() != noErr)
4199 return false;
4200
4201 m_lib.GoToBeginningOfMovie(m_movie);
4202 return m_lib.GetMoviesError() == noErr;
4203 }
4204
4205 //---------------------------------------------------------------------------
4206 // wxQTMediaBackend::GetPlaybackRate
4207 //
4208 // 1) Get the movie playback rate from ::GetMovieRate
4209 //---------------------------------------------------------------------------
4210 double wxQTMediaBackend::GetPlaybackRate()
4211 {
4212 return ( ((double)m_lib.GetMovieRate(m_movie)) / 0x10000);
4213 }
4214
4215 //---------------------------------------------------------------------------
4216 // wxQTMediaBackend::SetPlaybackRate
4217 //
4218 // 1) Convert dRate to Fixed and Set the movie rate through SetMovieRate
4219 //---------------------------------------------------------------------------
4220 bool wxQTMediaBackend::SetPlaybackRate(double dRate)
4221 {
4222 m_lib.SetMovieRate(m_movie, (Fixed) (dRate * 0x10000));
4223 return m_lib.GetMoviesError() == noErr;
4224 }
4225
4226 //---------------------------------------------------------------------------
4227 // wxQTMediaBackend::SetPosition
4228 //
4229 // 1) Create a time record struct (TimeRecord) with appropriate values
4230 // 2) Pass struct to SetMovieTime
4231 //---------------------------------------------------------------------------
4232 bool wxQTMediaBackend::SetPosition(wxLongLong where)
4233 {
4234 //NB: For some reason SetMovieTime does not work
4235 //correctly with the Quicktime Windows SDK (6)
4236 //From Muskelkatermann at the wxForum
4237 //http://www.solidsteel.nl/users/wxwidgets/viewtopic.php?t=2957
4238 //RN - note that I have not verified this but there
4239 //is no harm in calling SetMovieTimeValue instead
4240 #if 0
4241 TimeRecord theTimeRecord;
4242 memset(&theTimeRecord, 0, sizeof(TimeRecord));
4243 theTimeRecord.value.lo = where.GetLo();
4244 theTimeRecord.scale = m_lib.GetMovieTimeScale(m_movie);
4245 theTimeRecord.base = m_lib.GetMovieTimeBase(m_movie);
4246 m_lib.SetMovieTime(m_movie, &theTimeRecord);
4247 #else
4248 m_lib.SetMovieTimeValue(m_movie, where.GetLo());
4249 #endif
4250 if (m_lib.GetMoviesError() != noErr)
4251 return false;
4252
4253 return true;
4254 }
4255
4256 //---------------------------------------------------------------------------
4257 // wxQTMediaBackend::GetPosition
4258 //
4259 // 1) Calls GetMovieTime to get the position we are in in the movie
4260 // in milliseconds (we called
4261 //---------------------------------------------------------------------------
4262 wxLongLong wxQTMediaBackend::GetPosition()
4263 {
4264 return m_lib.GetMovieTime(m_movie, NULL);
4265 }
4266
4267 //---------------------------------------------------------------------------
4268 // wxQTMediaBackend::GetVolume
4269 //
4270 // Gets the volume through GetMovieVolume - which returns a 16 bit short -
4271 //
4272 // +--------+--------+
4273 // + (1) + (2) +
4274 // +--------+--------+
4275 //
4276 // (1) first 8 bits are value before decimal
4277 // (2) second 8 bits are value after decimal
4278 //
4279 // Volume ranges from -1.0 (gain but no sound), 0 (no sound and no gain) to
4280 // 1 (full gain and sound)
4281 //---------------------------------------------------------------------------
4282 double wxQTMediaBackend::GetVolume()
4283 {
4284 short sVolume = m_lib.GetMovieVolume(m_movie);
4285 wxASSERT(m_lib.GetMoviesError() == noErr);
4286
4287 if(sVolume & (128 << 8)) //negative - no sound
4288 return 0.0;
4289
4290 return sVolume/256.0;
4291 }
4292
4293 //---------------------------------------------------------------------------
4294 // wxQTMediaBackend::SetVolume
4295 //
4296 // Sets the volume through SetMovieVolume - which takes a 16 bit short -
4297 //
4298 // +--------+--------+
4299 // + (1) + (2) +
4300 // +--------+--------+
4301 //
4302 // (1) first 8 bits are value before decimal
4303 // (2) second 8 bits are value after decimal
4304 //
4305 // Volume ranges from -1.0 (gain but no sound), 0 (no sound and no gain) to
4306 // 1 (full gain and sound)
4307 //---------------------------------------------------------------------------
4308 bool wxQTMediaBackend::SetVolume(double dVolume)
4309 {
4310 m_lib.SetMovieVolume(m_movie, (short) (dVolume * 256));
4311 return m_lib.GetMoviesError() == noErr;
4312 }
4313
4314 //---------------------------------------------------------------------------
4315 // wxQTMediaBackend::GetDuration
4316 //
4317 // Calls GetMovieDuration
4318 //---------------------------------------------------------------------------
4319 wxLongLong wxQTMediaBackend::GetDuration()
4320 {
4321 return m_lib.GetMovieDuration(m_movie);
4322 }
4323
4324 //---------------------------------------------------------------------------
4325 // wxQTMediaBackend::GetState
4326 //
4327 // Determines the current state - if we are at the beginning we
4328 // are stopped
4329 //---------------------------------------------------------------------------
4330 wxMediaState wxQTMediaBackend::GetState()
4331 {
4332 if (m_bPlaying == true)
4333 return wxMEDIASTATE_PLAYING;
4334 else if ( !m_movie || wxQTMediaBackend::GetPosition() == 0)
4335 return wxMEDIASTATE_STOPPED;
4336 else
4337 return wxMEDIASTATE_PAUSED;
4338 }
4339
4340 //---------------------------------------------------------------------------
4341 // wxQTMediaBackend::Cleanup
4342 //
4343 // Diposes of the movie timer, Disassociates the Movie Controller with
4344 // movie and hides it if it exists, and stops and disposes
4345 // of the QT movie
4346 //---------------------------------------------------------------------------
4347 void wxQTMediaBackend::Cleanup()
4348 {
4349 m_bPlaying = false;
4350
4351 if(m_timer)
4352 {
4353 delete m_timer;
4354 m_timer = NULL;
4355 }
4356
4357 m_lib.StopMovie(m_movie);
4358
4359 if(m_pMC)
4360 {
4361 Point thePoint;
4362 thePoint.h = thePoint.v = 0;
4363 m_lib.MCSetVisible(m_pMC, false);
4364 m_lib.MCSetMovie(m_pMC, NULL, NULL, thePoint);
4365 }
4366
4367 m_lib.DisposeMovie(m_movie);
4368 m_movie = NULL;
4369 }
4370
4371 //---------------------------------------------------------------------------
4372 // wxQTMediaBackend::ShowPlayerControls
4373 //
4374 // Creates a movie controller for the Movie if the user wants it
4375 //---------------------------------------------------------------------------
4376 bool wxQTMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
4377 {
4378 if(m_pMC)
4379 {
4380 //restore old wndproc
4381 wxSetWindowProc((HWND)m_ctrl->GetHWND(), wxWndProc);
4382 m_lib.DisposeMovieController(m_pMC);
4383 m_pMC = NULL;
4384 m_bestSize.y -= 16; //movie controller height
4385 }
4386
4387 if(flags && m_movie)
4388 {
4389 Rect rect;
4390 wxRect wxrect = m_ctrl->GetClientRect();
4391
4392 //make room for controller
4393 if(wxrect.width < 320)
4394 wxrect.width = 320;
4395
4396 rect.top = wxrect.y;
4397 rect.left = wxrect.x;
4398 rect.right = rect.left + wxrect.width;
4399 rect.bottom = rect.top + wxrect.height;
4400
4401 if(!m_pMC)
4402 {
4403 m_pMC = m_lib.NewMovieController(m_movie, &rect, mcTopLeftMovie |
4404 // mcScaleMovieToFit |
4405 // mcWithBadge |
4406 mcWithFrame);
4407 m_lib.MCDoAction(m_pMC, 32, (void*)true); //mcActionSetKeysEnabled
4408 m_lib.MCSetActionFilterWithRefCon(m_pMC,
4409 (WXFARPROC)wxQTMediaBackend::MCFilterProc, (void*)this);
4410 m_bestSize.y += 16; //movie controller height
4411
4412 //
4413 // By default the movie controller uses its own color
4414 // pallette for the movie which can be bad on some files -
4415 // so turn it off. Also turn off its frame/border for
4416 // the movie
4417 //
4418 // Also we take care of a couple of the interface flags here
4419 //
4420 long mcFlags = 0;
4421 m_lib.MCDoAction(m_pMC, 39/*mcActionGetFlags*/, (void*)&mcFlags);
4422 mcFlags |= ( //(1<<0)/*mcFlagSuppressMovieFrame*/ |
4423 (1<<3)/*mcFlagsUseWindowPalette*/
4424 | ((flags & wxMEDIACTRLPLAYERCONTROLS_STEP)
4425 ? 0 : (1<<1)/*mcFlagSuppressStepButtons*/)
4426 | ((flags & wxMEDIACTRLPLAYERCONTROLS_VOLUME)
4427 ? 0 : (1<<2)/*mcFlagSuppressSpeakerButton*/)
4428 // | (1<<4) /*mcFlagDontInvalidate*/ //if we take care of repainting ourselves
4429 );
4430 m_lib.MCDoAction(m_pMC, 38/*mcActionSetFlags*/, (void*)mcFlags);
4431
4432 //intercept the wndproc of our control window
4433 wxSetWindowProc((HWND)m_ctrl->GetHWND(),
4434 wxQTMediaBackend::QTWndProc);
4435
4436 //set the user data of our window
4437 wxSetWindowUserData((HWND)m_ctrl->GetHWND(), this);
4438 }
4439 }
4440
4441 //
4442 //Here, if the parent of the control has a sizer - we
4443 //tell it to recalculate the size of this control since
4444 //the user opened a separate media file
4445 //
4446 m_ctrl->InvalidateBestSize();
4447 m_ctrl->GetParent()->Layout();
4448 m_ctrl->GetParent()->Refresh();
4449 m_ctrl->GetParent()->Update();
4450 m_ctrl->SetSize(m_ctrl->GetSize());
4451
4452 return m_lib.GetMoviesError() == noErr;
4453 }
4454
4455 //---------------------------------------------------------------------------
4456 // wxQTMediaBackend::MCFilterProc (static)
4457 //
4458 // Callback for when the movie controller recieves a message
4459 //---------------------------------------------------------------------------
4460 Boolean
4461 wxQTMediaBackend::MCFilterProc(MovieController WXUNUSED(theController),
4462 short action,
4463 void * WXUNUSED(params),
4464 LONG_PTR refCon)
4465 {
4466 if(action != 1) //don't process idle events
4467 {
4468 wxQTMediaBackend* pThis = (wxQTMediaBackend*)refCon;
4469
4470 switch(action)
4471 {
4472 case 8: //play button triggered - MC will set movie to opposite state
4473 //of current - playing ? paused : playing
4474 pThis->m_bPlaying = !(pThis->m_bPlaying);
4475
4476 // NB: Sometimes it doesn't redraw properly -
4477 // if you click on the button but don't move the mouse
4478 // the button will not change its state until you move
4479 // mcActionDraw and Refresh/Update combo do nothing
4480 // to help this unfortunately
4481 break;
4482 default:
4483 break;
4484 }
4485 }
4486 return 0;
4487 }
4488
4489 //---------------------------------------------------------------------------
4490 // wxQTMediaBackend::GetVideoSize
4491 //
4492 // Returns the actual size of the QT movie
4493 //---------------------------------------------------------------------------
4494 wxSize wxQTMediaBackend::GetVideoSize() const
4495 {
4496 return m_bestSize;
4497 }
4498
4499 //---------------------------------------------------------------------------
4500 // wxQTMediaBackend::Move
4501 //
4502 // Sets the bounds of either the Movie or Movie Controller
4503 //---------------------------------------------------------------------------
4504 void wxQTMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y), int w, int h)
4505 {
4506 if(m_movie)
4507 {
4508 //make room for controller
4509 if(m_pMC)
4510 {
4511 if(w < 320)
4512 w = 320;
4513
4514 Rect theRect = {0, 0, (short)h, (short)w};
4515 m_lib.MCSetControllerBoundsRect(m_pMC, &theRect);
4516 }
4517 else
4518 {
4519 Rect theRect = {0, 0, (short)h, (short)w};
4520 m_lib.SetMovieBox(m_movie, &theRect);
4521 }
4522
4523 wxASSERT(m_lib.GetMoviesError() == noErr);
4524 }
4525 }
4526
4527 //---------------------------------------------------------------------------
4528 // wxQTMediaBackend::OnEraseBackground
4529 //
4530 // Suggestion from Greg Hazel to repaint the movie when idle
4531 // (on pause also)
4532 //
4533 // TODO: We may be repainting too much here - under what exact circumstances
4534 // do we need this? I think Move also repaints correctly for the Movie
4535 // Controller, so in that instance we don't need this either
4536 //---------------------------------------------------------------------------
4537 void wxQTMediaEvtHandler::OnEraseBackground(wxEraseEvent& evt)
4538 {
4539 wxQTMediaBackend* qtb = (wxQTMediaBackend*)this;
4540 wxQuickTimeLibrary* m_pLib = &(qtb->m_lib);
4541
4542 if(qtb->m_pMC)
4543 {
4544 //repaint movie controller
4545 m_pLib->MCDoAction(qtb->m_pMC, 2 /*mcActionDraw*/,
4546 m_pLib->GetNativeWindowPort(qtb->m_ctrl->GetHWND())
4547 );
4548 }
4549 else if(qtb->m_movie)
4550 {
4551 CGrafPtr port = (CGrafPtr)m_pLib->GetNativeWindowPort
4552 (qtb->m_ctrl->GetHWND());
4553
4554 m_pLib->BeginUpdate(port);
4555 m_pLib->UpdateMovie(qtb->m_movie);
4556 wxASSERT(m_pLib->GetMoviesError() == noErr);
4557 m_pLib->EndUpdate(port);
4558 }
4559
4560 evt.Skip(); //repaint with window background (TODO: maybe !m_movie?)
4561 }
4562
4563 //---------------------------------------------------------------------------
4564 // End QT Backend
4565 //---------------------------------------------------------------------------
4566
4567 //in source file that contains stuff you don't directly use
4568 #include <wx/html/forcelnk.h>
4569 FORCE_LINK_ME(basewxmediabackends);
4570
4571 //---------------------------------------------------------------------------
4572 // End wxMediaCtrl Compilation Guard and this file
4573 //---------------------------------------------------------------------------
4574 #endif //wxUSE_MEDIACTRL
4575
4576