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