]> git.saurik.com Git - wxWidgets.git/blob - src/msw/mediactrl.cpp
0aeb33a8b68304d05223b90f07dc98be2208c0e8
[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 //cludgy workaround for wx events. slots would be nice :)
1779 class WXDLLIMPEXP_MEDIA wxAMMediaEvtHandler : public wxEvtHandler
1780 {
1781 public:
1782 void OnEraseBackground(wxEraseEvent&);
1783 };
1784
1785 class WXDLLIMPEXP_MEDIA wxAMMediaBackend : public wxMediaBackend
1786 {
1787 public:
1788 wxAMMediaBackend();
1789 virtual ~wxAMMediaBackend();
1790 void Clear();
1791
1792 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
1793 wxWindowID id,
1794 const wxPoint& pos,
1795 const wxSize& size,
1796 long style,
1797 const wxValidator& validator,
1798 const wxString& name);
1799
1800 virtual bool Play();
1801 virtual bool Pause();
1802 virtual bool Stop();
1803
1804 virtual bool Load(const wxString& fileName);
1805 virtual bool Load(const wxURI& location);
1806 virtual bool Load(const wxURI& location, const wxURI& proxy);
1807
1808 bool DoLoad(const wxString& location);
1809 void FinishLoad();
1810
1811 virtual wxMediaState GetState();
1812
1813 virtual bool SetPosition(wxLongLong where);
1814 virtual wxLongLong GetPosition();
1815 virtual wxLongLong GetDuration();
1816
1817 virtual void Move(int x, int y, int w, int h);
1818 wxSize GetVideoSize() const;
1819
1820 virtual double GetPlaybackRate();
1821 virtual bool SetPlaybackRate(double);
1822
1823 virtual double GetVolume();
1824 virtual bool SetVolume(double);
1825
1826 virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags);
1827 void Cleanup();
1828
1829 void DoGetDownloadProgress(wxLongLong*, wxLongLong*);
1830 virtual wxLongLong GetDownloadProgress()
1831 {
1832 wxLongLong progress, total;
1833 DoGetDownloadProgress(&progress, &total);
1834 return progress;
1835 }
1836 virtual wxLongLong GetDownloadTotal()
1837 {
1838 wxLongLong progress, total;
1839 DoGetDownloadProgress(&progress, &total);
1840 return total;
1841 }
1842
1843 wxControl* m_ctrl;
1844 wxActiveX* m_pAX;
1845 IActiveMovie* m_pAM;
1846 IMediaPlayer* m_pMP;
1847 wxTimer* m_pTimer;
1848 wxSize m_bestSize;
1849 #ifdef __WXDEBUG__
1850 HMODULE m_hQuartzDll;
1851 LPAMGETERRORTEXT m_lpAMGetErrorText;
1852 wxString GetErrorString(HRESULT hrdsv);
1853 #endif
1854
1855 DECLARE_DYNAMIC_CLASS(wxAMMediaBackend)
1856 };
1857
1858 //---------------------------------------------------------------------------
1859 //
1860 // wxMCIMediaBackend
1861 //
1862 //---------------------------------------------------------------------------
1863
1864 //---------------------------------------------------------------------------
1865 // MCI Includes
1866 //---------------------------------------------------------------------------
1867 #include <mmsystem.h>
1868
1869 class WXDLLIMPEXP_MEDIA wxMCIMediaBackend : public wxMediaBackend
1870 {
1871 public:
1872
1873 wxMCIMediaBackend();
1874 ~wxMCIMediaBackend();
1875
1876 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
1877 wxWindowID id,
1878 const wxPoint& pos,
1879 const wxSize& size,
1880 long style,
1881 const wxValidator& validator,
1882 const wxString& name);
1883
1884 virtual bool Play();
1885 virtual bool Pause();
1886 virtual bool Stop();
1887
1888 virtual bool Load(const wxURI& location,
1889 const wxURI& proxy)
1890 { return wxMediaBackend::Load(location, proxy); }
1891
1892 virtual bool Load(const wxString& fileName);
1893 virtual bool Load(const wxURI& location);
1894
1895 virtual wxMediaState GetState();
1896
1897 virtual bool SetPosition(wxLongLong where);
1898 virtual wxLongLong GetPosition();
1899 virtual wxLongLong GetDuration();
1900
1901 virtual void Move(int x, int y, int w, int h);
1902 wxSize GetVideoSize() const;
1903
1904 virtual double GetPlaybackRate();
1905 virtual bool SetPlaybackRate(double dRate);
1906
1907 virtual double GetVolume();
1908 virtual bool SetVolume(double);
1909
1910 static LRESULT CALLBACK NotifyWndProc(HWND hWnd, UINT nMsg,
1911 WPARAM wParam, LPARAM lParam);
1912
1913 LRESULT CALLBACK OnNotifyWndProc(HWND hWnd, UINT nMsg,
1914 WPARAM wParam, LPARAM lParam);
1915
1916 MCIDEVICEID m_hDev; //Our MCI Device ID/Handler
1917 wxControl* m_ctrl; //Parent control
1918 HWND m_hNotifyWnd; //Window to use for MCI events
1919 bool m_bVideo; //Whether or not we have video
1920
1921 DECLARE_DYNAMIC_CLASS(wxMCIMediaBackend)
1922 };
1923
1924 //---------------------------------------------------------------------------
1925 //
1926 // wxQTMediaBackend
1927 //
1928 // We don't include Quicktime headers here and define all the types
1929 // ourselves because looking for the quicktime libaries etc. would
1930 // be tricky to do and making this a dependency for the MSVC projects
1931 // would be unrealistic.
1932 //
1933 // Thanks to Robert Roebling for the wxDL macro/library idea
1934 //---------------------------------------------------------------------------
1935
1936 //---------------------------------------------------------------------------
1937 // QT Includes
1938 //---------------------------------------------------------------------------
1939 //#include <qtml.h> //Windoze QT include
1940 //#include <QuickTimeComponents.h> //Standard QT stuff
1941 #include "wx/dynlib.h"
1942
1943 //---------------------------------------------------------------------------
1944 // QT Types
1945 //---------------------------------------------------------------------------
1946 typedef struct MovieRecord* Movie;
1947 typedef wxInt16 OSErr;
1948 typedef wxInt32 OSStatus;
1949 #define noErr 0
1950 #define fsRdPerm 1
1951 typedef unsigned char Str255[256];
1952 #define StringPtr unsigned char*
1953 #define newMovieActive 1
1954 #define newMovieAsyncOK (1 << 8)
1955 #define Ptr char*
1956 #define Handle Ptr*
1957 #define Fixed long
1958 #define OSType unsigned long
1959 #define CGrafPtr struct GrafPort *
1960 #define TimeScale long
1961 #define TimeBase struct TimeBaseRecord *
1962 typedef struct ComponentInstanceRecord * ComponentInstance;
1963 #define kMovieLoadStatePlayable 10000
1964 #define Boolean int
1965 #define MovieController ComponentInstance
1966
1967 #ifndef URLDataHandlerSubType
1968 #if defined(__WATCOMC__) || defined(__MINGW32__)
1969 // use magic numbers for compilers which complain about multicharacter integers
1970 const OSType URLDataHandlerSubType = 1970433056;
1971 const OSType VisualMediaCharacteristic = 1702454643;
1972 #else
1973 const OSType URLDataHandlerSubType = 'url ';
1974 const OSType VisualMediaCharacteristic = 'eyes';
1975 #endif
1976 #endif
1977
1978 struct FSSpec {
1979 short vRefNum;
1980 long parID;
1981 Str255 name; /*Str63 on mac, Str255 on msw */
1982 };
1983
1984 struct Rect {
1985 short top;
1986 short left;
1987 short bottom;
1988 short right;
1989 };
1990
1991 struct wide {
1992 wxInt32 hi;
1993 wxUint32 lo;
1994 };
1995
1996 struct TimeRecord {
1997 wide value; /* units */
1998 TimeScale scale; /* units per second */
1999 TimeBase base;
2000 };
2001
2002 struct Point {
2003 short v;
2004 short h;
2005 };
2006
2007 struct EventRecord {
2008 wxUint16 what;
2009 wxUint32 message;
2010 wxUint32 when;
2011 Point where;
2012 wxUint16 modifiers;
2013 };
2014
2015 enum {
2016 mcTopLeftMovie = 1,
2017 mcScaleMovieToFit = 2,
2018 mcWithBadge = 4,
2019 mcNotVisible = 8,
2020 mcWithFrame = 16
2021 };
2022
2023 //---------------------------------------------------------------------------
2024 // QT Library
2025 //---------------------------------------------------------------------------
2026 #define wxDL_METHOD_DEFINE( rettype, name, args, shortargs, defret ) \
2027 typedef rettype (* name ## Type) args ; \
2028 name ## Type pfn_ ## name; \
2029 rettype name args \
2030 { if (m_ok) return pfn_ ## name shortargs ; return defret; }
2031
2032 #define wxDL_VOIDMETHOD_DEFINE( name, args, shortargs ) \
2033 typedef void (* name ## Type) args ; \
2034 name ## Type pfn_ ## name; \
2035 void name args \
2036 { if (m_ok) pfn_ ## name shortargs ; }
2037
2038 #define wxDL_METHOD_LOAD( lib, name, success ) \
2039 pfn_ ## name = (name ## Type) lib.GetSymbol( wxT(#name), &success ); \
2040 if (!success) { wxLog::EnableLogging(bWasLoggingEnabled); return false; }
2041
2042
2043 class WXDLLIMPEXP_MEDIA wxQuickTimeLibrary
2044 {
2045 public:
2046 ~wxQuickTimeLibrary()
2047 {
2048 if(m_dll.IsLoaded())
2049 m_dll.Unload();
2050 }
2051
2052 bool Initialize();
2053 bool IsOk() const {return m_ok;}
2054
2055 protected:
2056 wxDynamicLibrary m_dll;
2057 bool m_ok;
2058
2059 public:
2060 wxDL_VOIDMETHOD_DEFINE( StartMovie, (Movie m), (m) );
2061 wxDL_VOIDMETHOD_DEFINE( StopMovie, (Movie m), (m) );
2062 wxDL_METHOD_DEFINE( bool, IsMovieDone, (Movie m), (m), false);
2063 wxDL_VOIDMETHOD_DEFINE( GoToBeginningOfMovie, (Movie m), (m) );
2064 wxDL_METHOD_DEFINE( OSErr, GetMoviesError, (), (), -1);
2065 wxDL_METHOD_DEFINE( OSErr, EnterMovies, (), (), -1);
2066 wxDL_VOIDMETHOD_DEFINE( ExitMovies, (), () );
2067 wxDL_METHOD_DEFINE( OSErr, InitializeQTML, (long flags), (flags), -1);
2068 wxDL_VOIDMETHOD_DEFINE( TerminateQTML, (), () );
2069
2070 wxDL_METHOD_DEFINE( OSErr, NativePathNameToFSSpec,
2071 (char* inName, FSSpec* outFile, long flags),
2072 (inName, outFile, flags), -1);
2073
2074 wxDL_METHOD_DEFINE( OSErr, OpenMovieFile,
2075 (const FSSpec * fileSpec, short * resRefNum, wxInt8 permission),
2076 (fileSpec, resRefNum, permission), -1 );
2077
2078 wxDL_METHOD_DEFINE( OSErr, CloseMovieFile,
2079 (short resRefNum), (resRefNum), -1);
2080
2081 wxDL_METHOD_DEFINE( OSErr, NewMovieFromFile,
2082 (Movie * theMovie, short resRefNum, short * resId,
2083 StringPtr resName, short newMovieFlags,
2084 bool * dataRefWasChanged),
2085 (theMovie, resRefNum, resId, resName, newMovieFlags,
2086 dataRefWasChanged), -1);
2087
2088 wxDL_VOIDMETHOD_DEFINE( SetMovieRate, (Movie m, Fixed rate), (m, rate) );
2089 wxDL_METHOD_DEFINE( Fixed, GetMovieRate, (Movie m), (m), 0);
2090 wxDL_VOIDMETHOD_DEFINE( MoviesTask, (Movie m, long maxms), (m, maxms) );
2091 wxDL_VOIDMETHOD_DEFINE( BlockMove,
2092 (const char* p1, const char* p2, long s), (p1,p2,s) );
2093 wxDL_METHOD_DEFINE( Handle, NewHandleClear, (long s), (s), NULL );
2094
2095 wxDL_METHOD_DEFINE( OSErr, NewMovieFromDataRef,
2096 (Movie * m, short flags, short * id,
2097 Handle dataRef, OSType dataRefType),
2098 (m,flags,id,dataRef,dataRefType), -1 );
2099
2100 wxDL_VOIDMETHOD_DEFINE( DisposeHandle, (Handle h), (h) );
2101 wxDL_VOIDMETHOD_DEFINE( GetMovieNaturalBoundsRect, (Movie m, Rect* r), (m,r) );
2102 wxDL_METHOD_DEFINE( void*, GetMovieIndTrackType,
2103 (Movie m, long index, OSType type, long flags),
2104 (m,index,type,flags), NULL );
2105 wxDL_VOIDMETHOD_DEFINE( CreatePortAssociation,
2106 (void* hWnd, void* junk, long morejunk), (hWnd, junk, morejunk) );
2107 wxDL_METHOD_DEFINE(void*, GetNativeWindowPort, (void* hWnd), (hWnd), NULL);
2108 wxDL_VOIDMETHOD_DEFINE(SetMovieGWorld, (Movie m, CGrafPtr port, void* whatever),
2109 (m, port, whatever) );
2110 wxDL_VOIDMETHOD_DEFINE(DisposeMovie, (Movie m), (m) );
2111 wxDL_VOIDMETHOD_DEFINE(SetMovieBox, (Movie m, Rect* r), (m,r));
2112 wxDL_VOIDMETHOD_DEFINE(SetMovieTimeScale, (Movie m, long s), (m,s));
2113 wxDL_METHOD_DEFINE(long, GetMovieDuration, (Movie m), (m), 0);
2114 wxDL_METHOD_DEFINE(TimeBase, GetMovieTimeBase, (Movie m), (m), 0);
2115 wxDL_METHOD_DEFINE(TimeScale, GetMovieTimeScale, (Movie m), (m), 0);
2116 wxDL_METHOD_DEFINE(long, GetMovieTime, (Movie m, void* cruft), (m,cruft), 0);
2117 wxDL_VOIDMETHOD_DEFINE(SetMovieTime, (Movie m, TimeRecord* tr), (m,tr) );
2118 wxDL_METHOD_DEFINE(short, GetMovieVolume, (Movie m), (m), 0);
2119 wxDL_VOIDMETHOD_DEFINE(SetMovieVolume, (Movie m, short sVolume), (m,sVolume) );
2120 wxDL_VOIDMETHOD_DEFINE(SetMovieTimeValue, (Movie m, long s), (m,s));
2121 wxDL_METHOD_DEFINE(ComponentInstance, NewMovieController, (Movie m, const Rect* mr, long fl), (m,mr,fl), 0);
2122 wxDL_VOIDMETHOD_DEFINE(DisposeMovieController, (ComponentInstance ci), (ci));
2123 wxDL_METHOD_DEFINE(int, MCSetVisible, (ComponentInstance m, int b), (m, b), 0);
2124
2125
2126 wxDL_VOIDMETHOD_DEFINE(PrePrerollMovie, (Movie m, long t, Fixed r, WXFARPROC p1, void* p2), (m,t,r,p1,p2) );
2127 wxDL_VOIDMETHOD_DEFINE(PrerollMovie, (Movie m, long t, Fixed r), (m,t,r) );
2128 wxDL_METHOD_DEFINE(Fixed, GetMoviePreferredRate, (Movie m), (m), 0);
2129 wxDL_METHOD_DEFINE(long, GetMovieLoadState, (Movie m), (m), 0);
2130 wxDL_METHOD_DEFINE(void*, NewRoutineDescriptor, (WXFARPROC f, int l, void* junk), (f, l, junk), 0);
2131 wxDL_VOIDMETHOD_DEFINE(DisposeRoutineDescriptor, (void* f), (f));
2132 wxDL_METHOD_DEFINE(void*, GetCurrentArchitecture, (), (), 0);
2133 wxDL_METHOD_DEFINE(int, MCDoAction, (ComponentInstance ci, long f, void* p), (ci,f,p), 0);
2134 wxDL_VOIDMETHOD_DEFINE(MCSetControllerBoundsRect, (ComponentInstance ci, Rect* r), (ci,r));
2135 wxDL_VOIDMETHOD_DEFINE(DestroyPortAssociation, (CGrafPtr g), (g));
2136 wxDL_VOIDMETHOD_DEFINE(NativeEventToMacEvent, (MSG* p1, EventRecord* p2), (p1,p2));
2137 wxDL_VOIDMETHOD_DEFINE(MCIsPlayerEvent, (ComponentInstance ci, EventRecord* p2), (ci, p2));
2138 wxDL_METHOD_DEFINE(int, MCSetMovie, (ComponentInstance ci, Movie m, void* p1, Point w),
2139 (ci,m,p1,w),0);
2140 wxDL_VOIDMETHOD_DEFINE(MCPositionController,
2141 (ComponentInstance ci, Rect* r, void* junk, void* morejunk), (ci,r,junk,morejunk));
2142 wxDL_VOIDMETHOD_DEFINE(MCSetActionFilterWithRefCon,
2143 (ComponentInstance ci, WXFARPROC cb, void* ref), (ci,cb,ref));
2144 wxDL_VOIDMETHOD_DEFINE(MCGetControllerInfo, (MovieController mc, long* flags), (mc,flags));
2145 wxDL_VOIDMETHOD_DEFINE(BeginUpdate, (CGrafPtr port), (port));
2146 wxDL_VOIDMETHOD_DEFINE(UpdateMovie, (Movie m), (m));
2147 wxDL_VOIDMETHOD_DEFINE(EndUpdate, (CGrafPtr port), (port));
2148 wxDL_METHOD_DEFINE( OSErr, GetMoviesStickyError, (), (), -1);
2149 };
2150
2151 bool wxQuickTimeLibrary::Initialize()
2152 {
2153 m_ok = false;
2154
2155 bool bWasLoggingEnabled = wxLog::EnableLogging(false); //Turn off the wxDynamicLibrary logging
2156
2157 if(!m_dll.Load(wxT("qtmlClient.dll")))
2158 {
2159 wxLog::EnableLogging(bWasLoggingEnabled);
2160 return false;
2161 }
2162
2163 wxDL_METHOD_LOAD( m_dll, StartMovie, m_ok );
2164 wxDL_METHOD_LOAD( m_dll, StopMovie, m_ok );
2165 wxDL_METHOD_LOAD( m_dll, IsMovieDone, m_ok );
2166 wxDL_METHOD_LOAD( m_dll, GoToBeginningOfMovie, m_ok );
2167 wxDL_METHOD_LOAD( m_dll, GetMoviesError, m_ok );
2168 wxDL_METHOD_LOAD( m_dll, EnterMovies, m_ok );
2169 wxDL_METHOD_LOAD( m_dll, ExitMovies, m_ok );
2170 wxDL_METHOD_LOAD( m_dll, InitializeQTML, m_ok );
2171 wxDL_METHOD_LOAD( m_dll, TerminateQTML, m_ok );
2172 wxDL_METHOD_LOAD( m_dll, NativePathNameToFSSpec, m_ok );
2173 wxDL_METHOD_LOAD( m_dll, OpenMovieFile, m_ok );
2174 wxDL_METHOD_LOAD( m_dll, CloseMovieFile, m_ok );
2175 wxDL_METHOD_LOAD( m_dll, NewMovieFromFile, m_ok );
2176 wxDL_METHOD_LOAD( m_dll, GetMovieRate, m_ok );
2177 wxDL_METHOD_LOAD( m_dll, SetMovieRate, m_ok );
2178 wxDL_METHOD_LOAD( m_dll, MoviesTask, m_ok );
2179 wxDL_METHOD_LOAD( m_dll, BlockMove, m_ok );
2180 wxDL_METHOD_LOAD( m_dll, NewHandleClear, m_ok );
2181 wxDL_METHOD_LOAD( m_dll, NewMovieFromDataRef, m_ok );
2182 wxDL_METHOD_LOAD( m_dll, DisposeHandle, m_ok );
2183 wxDL_METHOD_LOAD( m_dll, GetMovieNaturalBoundsRect, m_ok );
2184 wxDL_METHOD_LOAD( m_dll, GetMovieIndTrackType, m_ok );
2185 wxDL_METHOD_LOAD( m_dll, CreatePortAssociation, m_ok );
2186 wxDL_METHOD_LOAD( m_dll, DestroyPortAssociation, m_ok );
2187 wxDL_METHOD_LOAD( m_dll, GetNativeWindowPort, m_ok );
2188 wxDL_METHOD_LOAD( m_dll, SetMovieGWorld, m_ok );
2189 wxDL_METHOD_LOAD( m_dll, DisposeMovie, m_ok );
2190 wxDL_METHOD_LOAD( m_dll, SetMovieBox, m_ok );
2191 wxDL_METHOD_LOAD( m_dll, SetMovieTimeScale, m_ok );
2192 wxDL_METHOD_LOAD( m_dll, GetMovieDuration, m_ok );
2193 wxDL_METHOD_LOAD( m_dll, GetMovieTimeBase, m_ok );
2194 wxDL_METHOD_LOAD( m_dll, GetMovieTimeScale, m_ok );
2195 wxDL_METHOD_LOAD( m_dll, GetMovieTime, m_ok );
2196 wxDL_METHOD_LOAD( m_dll, SetMovieTime, m_ok );
2197 wxDL_METHOD_LOAD( m_dll, GetMovieVolume, m_ok );
2198 wxDL_METHOD_LOAD( m_dll, SetMovieVolume, m_ok );
2199 wxDL_METHOD_LOAD( m_dll, SetMovieTimeValue, m_ok );
2200 wxDL_METHOD_LOAD( m_dll, NewMovieController, m_ok );
2201 wxDL_METHOD_LOAD( m_dll, DisposeMovieController, m_ok );
2202 wxDL_METHOD_LOAD( m_dll, MCSetVisible, m_ok );
2203 wxDL_METHOD_LOAD( m_dll, PrePrerollMovie, m_ok );
2204 wxDL_METHOD_LOAD( m_dll, PrerollMovie, m_ok );
2205 wxDL_METHOD_LOAD( m_dll, GetMoviePreferredRate, m_ok );
2206 wxDL_METHOD_LOAD( m_dll, GetMovieLoadState, m_ok );
2207 wxDL_METHOD_LOAD( m_dll, MCDoAction, m_ok );
2208 wxDL_METHOD_LOAD( m_dll, MCSetControllerBoundsRect, m_ok );
2209 wxDL_METHOD_LOAD( m_dll, NativeEventToMacEvent, m_ok );
2210 wxDL_METHOD_LOAD( m_dll, MCIsPlayerEvent, m_ok );
2211 wxDL_METHOD_LOAD( m_dll, MCSetMovie, m_ok );
2212 wxDL_METHOD_LOAD( m_dll, MCSetActionFilterWithRefCon, m_ok );
2213 wxDL_METHOD_LOAD( m_dll, MCGetControllerInfo, m_ok );
2214 wxDL_METHOD_LOAD( m_dll, BeginUpdate, m_ok );
2215 wxDL_METHOD_LOAD( m_dll, UpdateMovie, m_ok );
2216 wxDL_METHOD_LOAD( m_dll, EndUpdate, m_ok );
2217 wxDL_METHOD_LOAD( m_dll, GetMoviesStickyError, m_ok );
2218
2219 wxLog::EnableLogging(bWasLoggingEnabled);
2220 m_ok = true;
2221
2222 return true;
2223 }
2224
2225 //cludgy workaround for wx events. slots would be nice :)
2226 class WXDLLIMPEXP_MEDIA wxQTMediaEvtHandler : public wxEvtHandler
2227 {
2228 public:
2229 void OnEraseBackground(wxEraseEvent&);
2230 };
2231
2232 class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackend
2233 {
2234 public:
2235 wxQTMediaBackend();
2236 ~wxQTMediaBackend();
2237
2238 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
2239 wxWindowID id,
2240 const wxPoint& pos,
2241 const wxSize& size,
2242 long style,
2243 const wxValidator& validator,
2244 const wxString& name);
2245
2246 virtual bool Play();
2247 virtual bool Pause();
2248 virtual bool Stop();
2249
2250 virtual bool Load(const wxURI& location,
2251 const wxURI& proxy)
2252 { return wxMediaBackend::Load(location, proxy); }
2253
2254 virtual bool Load(const wxString& fileName);
2255 virtual bool Load(const wxURI& location);
2256
2257 virtual wxMediaState GetState();
2258
2259 virtual bool SetPosition(wxLongLong where);
2260 virtual wxLongLong GetPosition();
2261 virtual wxLongLong GetDuration();
2262
2263 virtual void Move(int x, int y, int w, int h);
2264 wxSize GetVideoSize() const;
2265
2266 virtual double GetPlaybackRate();
2267 virtual bool SetPlaybackRate(double dRate);
2268
2269 virtual double GetVolume();
2270 virtual bool SetVolume(double);
2271
2272 void Cleanup();
2273 void FinishLoad();
2274
2275 static void PPRMProc (Movie theMovie, OSErr theErr, void* theRefCon);
2276 //TODO: Last param actually long - does this work on 64bit machines?
2277 static Boolean MCFilterProc (MovieController theController,
2278 short action, void *params, LONG_PTR refCon);
2279
2280 static LRESULT CALLBACK QTWndProc(HWND, UINT, WPARAM, LPARAM);
2281
2282 virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags);
2283
2284 wxSize m_bestSize; //Original movie size
2285 Movie m_movie; //QT Movie handle/instance
2286 wxControl* m_ctrl; //Parent control
2287 bool m_bVideo; //Whether or not we have video
2288 bool m_bPlaying; //Whether or not movie is playing
2289 wxTimer* m_timer; //Load or Play timer
2290 wxQuickTimeLibrary m_lib; //DLL to load functions from
2291 ComponentInstance m_pMC; //Movie Controller
2292
2293 DECLARE_DYNAMIC_CLASS(wxQTMediaBackend)
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 // My problem with this was only with a previous patch, probably the
2677 // third rewrite fixed it as a side-effect. In fact, the erase
2678 // background style of drawing not only works now, but is much better
2679 // than paint-based updates (the paint event handler flickers if the
2680 // wxMediaCtrl shares a sizer with another child window, or is on a
2681 // notebook)
2682 // - Greg Hazel
2683 m_ctrl->Connect(m_ctrl->GetId(), wxEVT_ERASE_BACKGROUND,
2684 wxEraseEventHandler(wxAMMediaEvtHandler::OnEraseBackground),
2685 NULL, (wxEvtHandler*) this);
2686
2687 // success
2688 return true;
2689 }
2690
2691 //---------------------------------------------------------------------------
2692 // wxAMMediaBackend::Load (file version)
2693 //---------------------------------------------------------------------------
2694 bool wxAMMediaBackend::Load(const wxString& fileName)
2695 {
2696 return DoLoad(fileName);
2697 }
2698
2699 //---------------------------------------------------------------------------
2700 // wxAMMediaBackend::Load (URL Version)
2701 //---------------------------------------------------------------------------
2702 bool wxAMMediaBackend::Load(const wxURI& location)
2703 {
2704 // Turn off loading from a proxy as user
2705 // may have set it previously
2706 INSPlay* pPlay = NULL;
2707 m_pAM->QueryInterface(IID_INSPlay, (void**) &pPlay);
2708 if(pPlay)
2709 {
2710 pPlay->put_UseHTTPProxy(VARIANT_FALSE);
2711 pPlay->Release();
2712 }
2713
2714 return DoLoad(location.BuildURI());
2715 }
2716
2717 //---------------------------------------------------------------------------
2718 // wxAMMediaBackend::Load (URL Version with Proxy)
2719 //---------------------------------------------------------------------------
2720 bool wxAMMediaBackend::Load(const wxURI& location, const wxURI& proxy)
2721 {
2722 // Set the proxy of the NETSHOW interface
2723 INSPlay* pPlay = NULL;
2724 m_pAM->QueryInterface(IID_INSPlay, (void**) &pPlay);
2725
2726 if(pPlay)
2727 {
2728 pPlay->put_UseHTTPProxy(VARIANT_TRUE);
2729 pPlay->put_HTTPProxyHost(wxBasicString(proxy.GetServer()).Get());
2730 pPlay->put_HTTPProxyPort(wxAtoi(proxy.GetPort()));
2731 pPlay->Release();
2732 }
2733
2734 return DoLoad(location.BuildURI());
2735 }
2736
2737 //---------------------------------------------------------------------------
2738 // wxAMMediaBackend::DoLoad
2739 //
2740 // Called by all functions - this actually renders
2741 // the file and sets up the filter graph
2742 //---------------------------------------------------------------------------
2743 bool wxAMMediaBackend::DoLoad(const wxString& location)
2744 {
2745 Clear(); //Clear up previously allocated memory
2746
2747 HRESULT hr;
2748
2749 // Play the movie the normal way through the embedded
2750 // WMP. Supposively Open is better in theory because
2751 // the docs say its async and put_FileName is not -
2752 // but in practice they both seem to be async anyway
2753 if(m_pMP)
2754 hr = m_pMP->Open( wxBasicString(location).Get() );
2755 else
2756 hr = m_pAM->put_FileName( wxBasicString(location).Get() );
2757
2758 if(FAILED(hr))
2759 {
2760 wxAMLOG(hr);
2761 return false;
2762 }
2763
2764 // In AM playing will FAIL if
2765 // the user plays before the media is loaded
2766 m_pTimer = new wxAMLoadTimer(this);
2767 m_pTimer->Start(20);
2768 return true;
2769 }
2770
2771 //---------------------------------------------------------------------------
2772 // wxAMMediaBackend::FinishLoad
2773 //
2774 // Called by our wxAMLoadTimer when the
2775 // embedded WMP tells its the media is ready to play.
2776 //
2777 // Here we get the original size of the video and
2778 // send the loaded event to our watcher :).
2779 //---------------------------------------------------------------------------
2780 void wxAMMediaBackend::FinishLoad()
2781 {
2782 //Get the original video size
2783 m_pAM->get_ImageSourceWidth((long*)&m_bestSize.x);
2784 m_pAM->get_ImageSourceHeight((long*)&m_bestSize.y);
2785
2786 //
2787 //Start the play timer to catch stop events
2788 //Previous load timer cleans up itself
2789 //
2790 m_pTimer = new wxAMPlayTimer(this);
2791
2792 //Here, if the parent of the control has a sizer - we
2793 //tell it to recalculate the size of this control since
2794 //the user opened a separate media file
2795 //
2796 m_ctrl->InvalidateBestSize();
2797 m_ctrl->GetParent()->Layout();
2798 m_ctrl->GetParent()->Refresh();
2799 m_ctrl->GetParent()->Update();
2800 m_ctrl->SetSize(m_ctrl->GetSize());
2801
2802 //Send event to our children
2803 wxMediaEvent theEvent(wxEVT_MEDIA_LOADED,
2804 m_ctrl->GetId());
2805 m_ctrl->AddPendingEvent(theEvent);
2806 }
2807
2808 //---------------------------------------------------------------------------
2809 // wxAMMediaBackend::ShowPlayerControls
2810 //---------------------------------------------------------------------------
2811 bool wxAMMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
2812 {
2813 // Note that IMediaPlayer doesn't have a statusbar by
2814 // default but IActiveMovie does - so lets try to keep
2815 // the interface consistant
2816 if(!flags)
2817 {
2818 m_pAM->put_Enabled(VARIANT_FALSE);
2819 m_pAM->put_ShowControls(VARIANT_FALSE);
2820 if(m_pMP)
2821 m_pMP->put_ShowStatusBar(VARIANT_FALSE);
2822 }
2823 else
2824 {
2825 m_pAM->put_Enabled(VARIANT_TRUE);
2826 m_pAM->put_ShowControls(VARIANT_TRUE);
2827
2828 m_pAM->put_ShowPositionControls(
2829 (flags & wxMEDIACTRLPLAYERCONTROLS_STEP) ?
2830 VARIANT_TRUE : VARIANT_FALSE);
2831
2832 if(m_pMP)
2833 {
2834 m_pMP->put_ShowStatusBar(VARIANT_TRUE);
2835 m_pMP->put_ShowAudioControls(
2836 (flags & wxMEDIACTRLPLAYERCONTROLS_VOLUME) ?
2837 VARIANT_TRUE : VARIANT_FALSE);
2838 }
2839 }
2840
2841 return true;
2842 }
2843
2844 //---------------------------------------------------------------------------
2845 // wxAMMediaBackend::Play
2846 //
2847 // Plays the stream. If it is non-seekable, it will restart it (implicit).
2848 //
2849 // Note that we use SUCCEEDED here because run/pause/stop tend to be overly
2850 // picky and return warnings on pretty much every call
2851 //---------------------------------------------------------------------------
2852 bool wxAMMediaBackend::Play()
2853 {
2854 // if the movie isn't done loading yet
2855 // go into an sync getmessage loop until it is :)
2856 if(m_pMP)
2857 {
2858 MPReadyStateConstants nState;
2859 m_pMP->get_ReadyState(&nState);
2860 while(nState == mpReadyStateLoading && wxYieldIfNeeded())
2861 {
2862 m_pMP->get_ReadyState(&nState);
2863 }
2864 }
2865 else
2866 {
2867 IActiveMovie2* pAM2;
2868 ReadyStateConstants nState;
2869 if(m_pAM->QueryInterface(IID_IActiveMovie2, (void**)&pAM2) == 0 &&
2870 pAM2->get_ReadyState(&nState) == 0)
2871 {
2872 while(nState == amvLoading && wxYieldIfNeeded())
2873 {
2874 pAM2->get_ReadyState(&nState);
2875 }
2876 pAM2->Release();
2877 }
2878 }
2879
2880 //Actually try to play the movie
2881 HRESULT hr = m_pAM->Run();
2882 if(SUCCEEDED(hr))
2883 {
2884 m_pTimer->Start(20);
2885 return true;
2886 }
2887 wxAMLOG(hr);
2888 return false;
2889 }
2890
2891 //---------------------------------------------------------------------------
2892 // wxAMMediaBackend::Pause
2893 //
2894 // Pauses the stream.
2895 //---------------------------------------------------------------------------
2896 bool wxAMMediaBackend::Pause()
2897 {
2898 HRESULT hr = m_pAM->Pause();
2899 if(SUCCEEDED(hr))
2900 return true;
2901 wxAMLOG(hr);
2902 return false;
2903 }
2904
2905 //---------------------------------------------------------------------------
2906 // wxAMMediaBackend::Stop
2907 //
2908 // Stops the stream.
2909 //---------------------------------------------------------------------------
2910 bool wxAMMediaBackend::Stop()
2911 {
2912 HRESULT hr = m_pAM->Stop();
2913 if(SUCCEEDED(hr))
2914 {
2915 //Seek to beginning
2916 wxAMMediaBackend::SetPosition(0);
2917 //Stop stop event timer
2918 m_pTimer->Stop();
2919 return true;
2920 }
2921 wxAMLOG(hr);
2922 return false;
2923 }
2924
2925 //---------------------------------------------------------------------------
2926 // wxAMMediaBackend::SetPosition
2927 //
2928 // 1) Translates the current position's time to directshow time,
2929 // which is in a scale of 1 second (in a double)
2930 // 2) Sets the play position of the IMediaSeeking interface -
2931 // passing NULL as the stop position means to keep the old
2932 // stop position
2933 //---------------------------------------------------------------------------
2934 bool wxAMMediaBackend::SetPosition(wxLongLong where)
2935 {
2936 HRESULT hr = m_pAM->put_CurrentPosition(
2937 ((LONGLONG)where.GetValue()) / 1000.0
2938 );
2939 if(FAILED(hr))
2940 {
2941 wxAMLOG(hr);
2942 return false;
2943 }
2944
2945 return true;
2946 }
2947
2948 //---------------------------------------------------------------------------
2949 // wxAMMediaBackend::GetPosition
2950 //
2951 // 1) Obtains the current play and stop positions from IMediaSeeking
2952 // 2) Returns the play position translated to our time base
2953 //---------------------------------------------------------------------------
2954 wxLongLong wxAMMediaBackend::GetPosition()
2955 {
2956 double outCur;
2957 HRESULT hr = m_pAM->get_CurrentPosition(&outCur);
2958 if(FAILED(hr))
2959 {
2960 wxAMLOG(hr);
2961 return 0;
2962 }
2963
2964 //h,m,s,milli - outdur is in 1 second (double)
2965 outCur *= 1000;
2966 wxLongLong ll;
2967 ll.Assign(outCur);
2968
2969 return ll;
2970 }
2971
2972 //---------------------------------------------------------------------------
2973 // wxAMMediaBackend::GetVolume
2974 //
2975 // Gets the volume through the IBasicAudio interface -
2976 // value ranges from 0 (MAX volume) to -10000 (minimum volume).
2977 // -100 per decibel.
2978 //---------------------------------------------------------------------------
2979 double wxAMMediaBackend::GetVolume()
2980 {
2981 long lVolume;
2982 HRESULT hr = m_pAM->get_Volume(&lVolume);
2983 if(FAILED(hr))
2984 {
2985 wxAMLOG(hr);
2986 return 0.0;
2987 }
2988 return pow(10.0, lVolume/2000.0);
2989 }
2990
2991 //---------------------------------------------------------------------------
2992 // wxAMMediaBackend::SetVolume
2993 //
2994 // Sets the volume through the IBasicAudio interface -
2995 // value ranges from 0 (MAX volume) to -10000 (minimum volume).
2996 // -100 per decibel.
2997 //---------------------------------------------------------------------------
2998 bool wxAMMediaBackend::SetVolume(double dVolume)
2999 {
3000 //pow(10.0, -80.0) to correct 0 == -INF
3001 long lVolume = (long)(2000.0 * log10(pow(10.0, -80.0)+dVolume));
3002 HRESULT hr = m_pAM->put_Volume( lVolume );
3003 if(FAILED(hr))
3004 {
3005 wxAMLOG(hr);
3006 return false;
3007 }
3008 return true;
3009 }
3010
3011 //---------------------------------------------------------------------------
3012 // wxAMMediaBackend::GetDuration
3013 //
3014 // 1) Obtains the duration of the media from IAMMultiMediaStream
3015 // 2) Converts that value to our time base, and returns it
3016 //
3017 // NB: With VBR MP3 files the default DirectShow MP3 render does not
3018 // read the Xing header correctly, resulting in skewed values for duration
3019 // and seeking
3020 //---------------------------------------------------------------------------
3021 wxLongLong wxAMMediaBackend::GetDuration()
3022 {
3023 double outDuration;
3024 HRESULT hr = m_pAM->get_Duration(&outDuration);
3025 if(FAILED(hr))
3026 {
3027 wxAMLOG(hr);
3028 return 0;
3029 }
3030
3031 //h,m,s,milli - outdur is in 1 second (double)
3032 outDuration *= 1000;
3033 wxLongLong ll;
3034 ll.Assign(outDuration);
3035
3036 return ll;
3037 }
3038
3039 //---------------------------------------------------------------------------
3040 // wxAMMediaBackend::GetState
3041 //
3042 // Returns the cached state
3043 //---------------------------------------------------------------------------
3044 wxMediaState wxAMMediaBackend::GetState()
3045 {
3046 StateConstants nState;
3047 HRESULT hr = m_pAM->get_CurrentState(&nState);
3048 if(FAILED(hr))
3049 {
3050 wxAMLOG(hr);
3051 return wxMEDIASTATE_STOPPED;
3052 }
3053
3054 return (wxMediaState)nState;
3055 }
3056
3057 //---------------------------------------------------------------------------
3058 // wxAMMediaBackend::GetPlaybackRate
3059 //
3060 // Pretty simple way of obtaining the playback rate from
3061 // the IMediaSeeking interface
3062 //---------------------------------------------------------------------------
3063 double wxAMMediaBackend::GetPlaybackRate()
3064 {
3065 double dRate;
3066 HRESULT hr = m_pAM->get_Rate(&dRate);
3067 if(FAILED(hr))
3068 {
3069 wxAMLOG(hr);
3070 return 0.0;
3071 }
3072 return dRate;
3073 }
3074
3075 //---------------------------------------------------------------------------
3076 // wxAMMediaBackend::SetPlaybackRate
3077 //
3078 // Sets the playback rate of the media - DirectShow is pretty good
3079 // about this, actually
3080 //---------------------------------------------------------------------------
3081 bool wxAMMediaBackend::SetPlaybackRate(double dRate)
3082 {
3083 HRESULT hr = m_pAM->put_Rate(dRate);
3084 if(FAILED(hr))
3085 {
3086 wxAMLOG(hr);
3087 return false;
3088 }
3089
3090 return true;
3091 }
3092
3093 //---------------------------------------------------------------------------
3094 // wxAMMediaBackend::GetDownloadXXX
3095 //
3096 // Queries for and gets the total size of the file and the current
3097 // progress in downloading that file from the IAMOpenProgress
3098 // interface from the media player interface's filter graph
3099 //---------------------------------------------------------------------------
3100 void wxAMMediaBackend::DoGetDownloadProgress(wxLongLong* pLoadProgress,
3101 wxLongLong* pLoadTotal)
3102 {
3103 LONGLONG loadTotal = 0, loadProgress = 0;
3104 IUnknown* pFG;
3105 IAMOpenProgress* pOP;
3106 HRESULT hr;
3107 hr = m_pAM->get_FilterGraph(&pFG);
3108 if(SUCCEEDED(hr))
3109 {
3110 hr = pFG->QueryInterface(IID_IAMOpenProgress, (void**)&pOP);
3111 if(SUCCEEDED(hr))
3112 {
3113 hr = pOP->QueryProgress(&loadTotal, &loadProgress);
3114 pOP->Release();
3115 }
3116 pFG->Release();
3117 }
3118
3119 if(SUCCEEDED(hr))
3120 {
3121 *pLoadProgress = loadProgress;
3122 *pLoadTotal = loadTotal;
3123 }
3124 else
3125 {
3126 //When not loading from a URL QueryProgress will return
3127 //E_NOINTERFACE or whatever
3128 //wxAMFAIL(hr);
3129 *pLoadProgress = 0;
3130 *pLoadTotal = 0;
3131 }
3132 }
3133
3134 //---------------------------------------------------------------------------
3135 // wxAMMediaBackend::GetVideoSize
3136 //
3137 // Obtains the cached original video size
3138 //---------------------------------------------------------------------------
3139 wxSize wxAMMediaBackend::GetVideoSize() const
3140 {
3141 return m_bestSize;
3142 }
3143
3144 //---------------------------------------------------------------------------
3145 // wxAMMediaBackend::Move
3146 //
3147 // We take care of this in our redrawing
3148 //---------------------------------------------------------------------------
3149 void wxAMMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y),
3150 int WXUNUSED(w), int WXUNUSED(h))
3151 {
3152 }
3153
3154 //---------------------------------------------------------------------------
3155 // wxAMMediaEvtHandler::OnEraseBackground
3156 //
3157 // Tell WX not to erase the background of our control window
3158 // so that resizing is a bit smoother
3159 //---------------------------------------------------------------------------
3160 void wxAMMediaEvtHandler::OnEraseBackground(wxEraseEvent& WXUNUSED(evt))
3161 {
3162 }
3163
3164 //---------------------------------------------------------------------------
3165 // End of wxAMMediaBackend
3166 //---------------------------------------------------------------------------
3167
3168 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3169 //
3170 // wxMCIMediaBackend
3171 //
3172 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3173
3174 IMPLEMENT_DYNAMIC_CLASS(wxMCIMediaBackend, wxMediaBackend);
3175
3176 //---------------------------------------------------------------------------
3177 // Usual debugging macros for MCI returns
3178 //---------------------------------------------------------------------------
3179
3180 #ifdef __WXDEBUG__
3181 #define wxMCIVERIFY(arg) \
3182 { \
3183 DWORD nRet; \
3184 if ( (nRet = (arg)) != 0) \
3185 { \
3186 TCHAR sz[5000]; \
3187 mciGetErrorString(nRet, sz, 5000); \
3188 wxFAIL_MSG(wxString::Format(_T("MCI Error:%s"), sz)); \
3189 } \
3190 }
3191 #else
3192 #define wxMCIVERIFY(arg) (arg);
3193 #endif
3194
3195 //---------------------------------------------------------------------------
3196 // Simulation for <digitalv.h>
3197 //
3198 // Mingw and possibly other compilers don't have the digitalv.h header
3199 // that is needed to have some essential features of mci work with
3200 // windows - so we provide the declarations for the types we use here
3201 //---------------------------------------------------------------------------
3202
3203 typedef struct {
3204 DWORD_PTR dwCallback;
3205 #ifdef MCI_USE_OFFEXT
3206 POINT ptOffset;
3207 POINT ptExtent;
3208 #else
3209 RECT rc;
3210 #endif
3211 } MCI_DGV_RECT_PARMS;
3212
3213 typedef struct {
3214 DWORD_PTR dwCallback;
3215 HWND hWnd;
3216 #ifndef _WIN32
3217 WORD wReserved1;
3218 #endif
3219 UINT nCmdShow;
3220 #ifndef _WIN32
3221 WORD wReserved2;
3222 #endif
3223 wxChar* lpstrText;
3224 } MCI_DGV_WINDOW_PARMS;
3225
3226 typedef struct {
3227 DWORD_PTR dwCallback;
3228 DWORD dwTimeFormat;
3229 DWORD dwAudio;
3230 DWORD dwFileFormat;
3231 DWORD dwSpeed;
3232 } MCI_DGV_SET_PARMS;
3233
3234 typedef struct {
3235 DWORD_PTR dwCallback;
3236 DWORD dwItem;
3237 DWORD dwValue;
3238 DWORD dwOver;
3239 wxChar* lpstrAlgorithm;
3240 wxChar* lpstrQuality;
3241 } MCI_DGV_SETAUDIO_PARMS;
3242
3243 //---------------------------------------------------------------------------
3244 // wxMCIMediaBackend Constructor
3245 //
3246 // Here we don't need to do much except say we don't have any video :)
3247 //---------------------------------------------------------------------------
3248 wxMCIMediaBackend::wxMCIMediaBackend() : m_hNotifyWnd(NULL), m_bVideo(false)
3249 {
3250 }
3251
3252 //---------------------------------------------------------------------------
3253 // wxMCIMediaBackend Destructor
3254 //
3255 // We close the mci device - note that there may not be an mci device here,
3256 // or it may fail - but we don't really care, since we're destructing
3257 //---------------------------------------------------------------------------
3258 wxMCIMediaBackend::~wxMCIMediaBackend()
3259 {
3260 if(m_hNotifyWnd)
3261 {
3262 mciSendCommand(m_hDev, MCI_CLOSE, 0, 0);
3263 DestroyWindow(m_hNotifyWnd);
3264 m_hNotifyWnd = NULL;
3265 }
3266 }
3267
3268 //---------------------------------------------------------------------------
3269 // wxMCIMediaBackend::Create
3270 //
3271 // Here we just tell wxMediaCtrl that mci does exist (which it does, on all
3272 // msw systems, at least in some form dating back to win16 days)
3273 //---------------------------------------------------------------------------
3274 bool wxMCIMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
3275 wxWindowID id,
3276 const wxPoint& pos,
3277 const wxSize& size,
3278 long style,
3279 const wxValidator& validator,
3280 const wxString& name)
3281 {
3282 //
3283 // Create window
3284 // By default wxWindow(s) is created with a border -
3285 // so we need to get rid of those, and create with
3286 // wxCLIP_CHILDREN, so that if the driver/backend
3287 // is a child window, it refereshes properly
3288 //
3289 if ( !ctrl->wxControl::Create(parent, id, pos, size,
3290 (style & ~wxBORDER_MASK) | wxBORDER_NONE | wxCLIP_CHILDREN,
3291 validator, name) )
3292 return false;
3293
3294 m_ctrl = ctrl;
3295 return true;
3296 }
3297
3298 //---------------------------------------------------------------------------
3299 // wxMCIMediaBackend::Load (file version)
3300 //
3301 // Here we have MCI load a file and device, set the time format to our
3302 // default (milliseconds), and set the video (if any) to play in the control
3303 //---------------------------------------------------------------------------
3304 bool wxMCIMediaBackend::Load(const wxString& fileName)
3305 {
3306 //
3307 //if the user already called load close the previous MCI device
3308 //
3309 if(m_hNotifyWnd)
3310 {
3311 mciSendCommand(m_hDev, MCI_CLOSE, 0, 0);
3312 DestroyWindow(m_hNotifyWnd);
3313 m_hNotifyWnd = NULL;
3314 }
3315
3316 //
3317 //Opens a file and has MCI select a device. Normally you'd put
3318 //MCI_OPEN_TYPE in addition to MCI_OPEN_ELEMENT - however if you
3319 //omit this it tells MCI to select the device instead. This is
3320 //good because we have no reliable way of "enumerating" the devices
3321 //in MCI
3322 //
3323 MCI_OPEN_PARMS openParms;
3324 openParms.lpstrElementName = (wxChar*) fileName.c_str();
3325
3326 if ( mciSendCommand(0, MCI_OPEN, MCI_OPEN_ELEMENT,
3327 (DWORD)(LPVOID)&openParms) != 0)
3328 return false;
3329
3330 m_hDev = openParms.wDeviceID;
3331
3332 //
3333 //Now set the time format for the device to milliseconds
3334 //
3335 MCI_SET_PARMS setParms;
3336 setParms.dwCallback = 0;
3337 setParms.dwTimeFormat = MCI_FORMAT_MILLISECONDS;
3338
3339 if (mciSendCommand(m_hDev, MCI_SET, MCI_SET_TIME_FORMAT,
3340 (DWORD)(LPVOID)&setParms) != 0)
3341 return false;
3342
3343 //
3344 //Now tell the MCI device to display the video in our wxMediaCtrl
3345 //
3346 MCI_DGV_WINDOW_PARMS windowParms;
3347 windowParms.hWnd = (HWND)m_ctrl->GetHandle();
3348
3349 m_bVideo = (mciSendCommand(m_hDev, MCI_WINDOW,
3350 0x00010000L, //MCI_DGV_WINDOW_HWND
3351 (DWORD)(LPVOID)&windowParms) == 0);
3352
3353 //
3354 // Create a hidden window and register to handle
3355 // MCI events
3356 // Note that wxCanvasClassName is already registered
3357 // and used by all wxWindows and normal wxControls
3358 //
3359 m_hNotifyWnd = ::CreateWindow
3360 (
3361 wxCanvasClassName,
3362 NULL,
3363 0, 0, 0, 0,
3364 0,
3365 (HWND) NULL,
3366 (HMENU)NULL,
3367 wxGetInstance(),
3368 (LPVOID) NULL
3369 );
3370
3371 if(!m_hNotifyWnd)
3372 {
3373 wxLogSysError( wxT("Could not create hidden needed for ")
3374 wxT("registering for MCI events!") );
3375
3376 return false;
3377 }
3378
3379 wxSetWindowProc(m_hNotifyWnd, wxMCIMediaBackend::NotifyWndProc);
3380 wxSetWindowUserData(m_hNotifyWnd, this);
3381
3382 //
3383 //Here, if the parent of the control has a sizer - we
3384 //tell it to recalculate the size of this control since
3385 //the user opened a separate media file
3386 //
3387 m_ctrl->InvalidateBestSize();
3388 m_ctrl->GetParent()->Layout();
3389 m_ctrl->GetParent()->Refresh();
3390 m_ctrl->GetParent()->Update();
3391 m_ctrl->SetSize(m_ctrl->GetSize());
3392
3393 //send loaded event
3394 wxMediaEvent theEvent(wxEVT_MEDIA_LOADED,
3395 m_ctrl->GetId());
3396 m_ctrl->AddPendingEvent(theEvent);
3397
3398 return true;
3399 }
3400
3401 //---------------------------------------------------------------------------
3402 // wxMCIMediaBackend::Load (URL version)
3403 //
3404 // MCI doesn't support URLs directly (?)
3405 //
3406 // TODO: Use wxURL/wxFileSystem and mmioInstallProc
3407 //---------------------------------------------------------------------------
3408 bool wxMCIMediaBackend::Load(const wxURI& WXUNUSED(location))
3409 {
3410 return false;
3411 }
3412
3413 //---------------------------------------------------------------------------
3414 // wxMCIMediaBackend::Play
3415 //
3416 // Plays/Resumes the MCI device... a couple notes:
3417 // 1) Certain drivers will crash and burn if we don't pass them an
3418 // MCI_PLAY_PARMS, despite the documentation that says otherwise...
3419 // 2) There is a MCI_RESUME command, but MCI_PLAY does the same thing
3420 // and will resume from a stopped state also, so there's no need to
3421 // call both, for example
3422 //---------------------------------------------------------------------------
3423 bool wxMCIMediaBackend::Play()
3424 {
3425 MCI_PLAY_PARMS playParms;
3426 playParms.dwCallback = (DWORD)m_hNotifyWnd;
3427
3428 bool bOK = ( mciSendCommand(m_hDev, MCI_PLAY, MCI_NOTIFY,
3429 (DWORD)(LPVOID)&playParms) == 0 );
3430
3431 if(bOK)
3432 m_ctrl->Show(m_bVideo);
3433
3434 return bOK;
3435 }
3436
3437 //---------------------------------------------------------------------------
3438 // wxMCIMediaBackend::Pause
3439 //
3440 // Pauses the MCI device - nothing special
3441 //---------------------------------------------------------------------------
3442 bool wxMCIMediaBackend::Pause()
3443 {
3444 return (mciSendCommand(m_hDev, MCI_PAUSE, MCI_WAIT, 0) == 0);
3445 }
3446
3447 //---------------------------------------------------------------------------
3448 // wxMCIMediaBackend::Stop
3449 //
3450 // Stops the MCI device & seeks to the beginning as wxMediaCtrl docs outline
3451 //---------------------------------------------------------------------------
3452 bool wxMCIMediaBackend::Stop()
3453 {
3454 return (mciSendCommand(m_hDev, MCI_STOP, MCI_WAIT, 0) == 0) &&
3455 (mciSendCommand(m_hDev, MCI_SEEK, MCI_SEEK_TO_START, 0) == 0);
3456 }
3457
3458 //---------------------------------------------------------------------------
3459 // wxMCIMediaBackend::GetState
3460 //
3461 // Here we get the state and convert it to a wxMediaState -
3462 // since we use direct comparisons with MCI_MODE_PLAY and
3463 // MCI_MODE_PAUSE, we don't care if the MCI_STATUS call
3464 // fails or not
3465 //---------------------------------------------------------------------------
3466 wxMediaState wxMCIMediaBackend::GetState()
3467 {
3468 MCI_STATUS_PARMS statusParms;
3469 statusParms.dwItem = MCI_STATUS_MODE;
3470
3471 mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
3472 (DWORD)(LPVOID)&statusParms);
3473
3474 if(statusParms.dwReturn == MCI_MODE_PAUSE)
3475 return wxMEDIASTATE_PAUSED;
3476 else if(statusParms.dwReturn == MCI_MODE_PLAY)
3477 return wxMEDIASTATE_PLAYING;
3478 else
3479 return wxMEDIASTATE_STOPPED;
3480 }
3481
3482 //---------------------------------------------------------------------------
3483 // wxMCIMediaBackend::SetPosition
3484 //
3485 // Here we set the position of the device in the stream.
3486 // Note that MCI actually stops the device after you seek it if the
3487 // device is playing/paused, so we need to play the file after
3488 // MCI seeks like normal APIs would
3489 //---------------------------------------------------------------------------
3490 bool wxMCIMediaBackend::SetPosition(wxLongLong where)
3491 {
3492 MCI_SEEK_PARMS seekParms;
3493 seekParms.dwCallback = 0;
3494 #if wxUSE_LONGLONG_NATIVE && !wxUSE_LONGLONG_WX
3495 seekParms.dwTo = (DWORD)where.GetValue();
3496 #else /* wxUSE_LONGLONG_WX */
3497 /* no way to return it in one piece */
3498 wxASSERT( where.GetHi()==0 );
3499 seekParms.dwTo = (DWORD)where.GetLo();
3500 #endif /* wxUSE_LONGLONG_* */
3501
3502 //device was playing?
3503 bool bReplay = GetState() == wxMEDIASTATE_PLAYING;
3504
3505 if( mciSendCommand(m_hDev, MCI_SEEK, MCI_TO,
3506 (DWORD)(LPVOID)&seekParms) != 0)
3507 return false;
3508
3509 //If the device was playing, resume it
3510 if (bReplay)
3511 return Play();
3512 else
3513 return true;
3514 }
3515
3516 //---------------------------------------------------------------------------
3517 // wxMCIMediaBackend::GetPosition
3518 //
3519 // Gets the position of the device in the stream using the current
3520 // time format... nothing special here...
3521 //---------------------------------------------------------------------------
3522 wxLongLong wxMCIMediaBackend::GetPosition()
3523 {
3524 MCI_STATUS_PARMS statusParms;
3525 statusParms.dwItem = MCI_STATUS_POSITION;
3526
3527 if (mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
3528 (DWORD)(LPSTR)&statusParms) != 0)
3529 return 0;
3530
3531 return statusParms.dwReturn;
3532 }
3533
3534 //---------------------------------------------------------------------------
3535 // wxMCIMediaBackend::GetVolume
3536 //
3537 // Gets the volume of the current media via the MCI_DGV_STATUS_VOLUME
3538 // message. Value ranges from 0 (minimum) to 1000 (maximum volume).
3539 //---------------------------------------------------------------------------
3540 double wxMCIMediaBackend::GetVolume()
3541 {
3542 MCI_STATUS_PARMS statusParms;
3543 statusParms.dwCallback = 0;
3544 statusParms.dwItem = 0x4019; //MCI_DGV_STATUS_VOLUME
3545
3546 if (mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
3547 (DWORD)(LPSTR)&statusParms) != 0)
3548 return 0;
3549
3550 return ((double)statusParms.dwReturn) / 1000.0;
3551 }
3552
3553 //---------------------------------------------------------------------------
3554 // wxMCIMediaBackend::SetVolume
3555 //
3556 // Sets the volume of the current media via the MCI_DGV_SETAUDIO_VOLUME
3557 // message. Value ranges from 0 (minimum) to 1000 (maximum volume).
3558 //---------------------------------------------------------------------------
3559 bool wxMCIMediaBackend::SetVolume(double dVolume)
3560 {
3561 MCI_DGV_SETAUDIO_PARMS audioParms;
3562 audioParms.dwCallback = 0;
3563 audioParms.dwItem = 0x4002; //MCI_DGV_SETAUDIO_VOLUME
3564 audioParms.dwValue = (DWORD) (dVolume * 1000.0);
3565 audioParms.dwOver = 0;
3566 audioParms.lpstrAlgorithm = NULL;
3567 audioParms.lpstrQuality = NULL;
3568
3569 if (mciSendCommand(m_hDev, 0x0873, //MCI_SETAUDIO
3570 //MCI_DGV_SETAUDIO+(_ITEM | _VALUE)
3571 0x00800000L | 0x01000000L,
3572 (DWORD)(LPSTR)&audioParms) != 0)
3573 return false;
3574 return true;
3575 }
3576
3577 //---------------------------------------------------------------------------
3578 // wxMCIMediaBackend::GetDuration
3579 //
3580 // Gets the duration of the stream... nothing special
3581 //---------------------------------------------------------------------------
3582 wxLongLong wxMCIMediaBackend::GetDuration()
3583 {
3584 MCI_STATUS_PARMS statusParms;
3585 statusParms.dwItem = MCI_STATUS_LENGTH;
3586
3587 if (mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
3588 (DWORD)(LPSTR)&statusParms) != 0)
3589 return 0;
3590
3591 return statusParms.dwReturn;
3592 }
3593
3594 //---------------------------------------------------------------------------
3595 // wxMCIMediaBackend::Move
3596 //
3597 // Moves the window to a location
3598 //---------------------------------------------------------------------------
3599 void wxMCIMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y),
3600 int w, int h)
3601 {
3602 if (m_hNotifyWnd && m_bVideo)
3603 {
3604 MCI_DGV_RECT_PARMS putParms; //ifdefed MCI_DGV_PUT_PARMS
3605 memset(&putParms, 0, sizeof(MCI_DGV_RECT_PARMS));
3606 putParms.rc.bottom = h;
3607 putParms.rc.right = w;
3608
3609 //wxStackWalker will crash and burn here on assert
3610 //and mci doesn't like 0 and 0 for some reason (out of range )
3611 //so just don't it in that case
3612 if(w || h)
3613 {
3614 wxMCIVERIFY( mciSendCommand(m_hDev, MCI_PUT,
3615 0x00040000L, //MCI_DGV_PUT_DESTINATION
3616 (DWORD)(LPSTR)&putParms) );
3617 }
3618 }
3619 }
3620
3621 //---------------------------------------------------------------------------
3622 // wxMCIMediaBackend::GetVideoSize
3623 //
3624 // Gets the original size of the movie for sizers
3625 //---------------------------------------------------------------------------
3626 wxSize wxMCIMediaBackend::GetVideoSize() const
3627 {
3628 if(m_bVideo)
3629 {
3630 MCI_DGV_RECT_PARMS whereParms; //ifdefed MCI_DGV_WHERE_PARMS
3631
3632 wxMCIVERIFY( mciSendCommand(m_hDev, MCI_WHERE,
3633 0x00020000L, //MCI_DGV_WHERE_SOURCE
3634 (DWORD)(LPSTR)&whereParms) );
3635
3636 return wxSize(whereParms.rc.right, whereParms.rc.bottom);
3637 }
3638 return wxSize(0,0);
3639 }
3640
3641 //---------------------------------------------------------------------------
3642 // wxMCIMediaBackend::GetPlaybackRate
3643 //
3644 // TODO
3645 //---------------------------------------------------------------------------
3646 double wxMCIMediaBackend::GetPlaybackRate()
3647 {
3648 return 1.0;
3649 }
3650
3651 //---------------------------------------------------------------------------
3652 // wxMCIMediaBackend::SetPlaybackRate
3653 //
3654 // TODO
3655 //---------------------------------------------------------------------------
3656 bool wxMCIMediaBackend::SetPlaybackRate(double WXUNUSED(dRate))
3657 {
3658 /*
3659 MCI_WAVE_SET_SAMPLESPERSEC
3660 MCI_DGV_SET_PARMS setParms;
3661 setParms.dwSpeed = (DWORD) (dRate * 1000.0);
3662
3663 return (mciSendCommand(m_hDev, MCI_SET,
3664 0x00020000L, //MCI_DGV_SET_SPEED
3665 (DWORD)(LPSTR)&setParms) == 0);
3666 */
3667 return false;
3668 }
3669
3670 //---------------------------------------------------------------------------
3671 // [static] wxMCIMediaBackend::MSWWindowProc
3672 //
3673 // Here we process a message when MCI reaches the stopping point
3674 // in the stream
3675 //---------------------------------------------------------------------------
3676 LRESULT CALLBACK wxMCIMediaBackend::NotifyWndProc(HWND hWnd, UINT nMsg,
3677 WPARAM wParam,
3678 LPARAM lParam)
3679 {
3680 wxMCIMediaBackend* backend =
3681 (wxMCIMediaBackend*)wxGetWindowUserData(hWnd);
3682
3683 return backend->OnNotifyWndProc(hWnd, nMsg, wParam, lParam);
3684 }
3685
3686 LRESULT CALLBACK wxMCIMediaBackend::OnNotifyWndProc(HWND hWnd, UINT nMsg,
3687 WPARAM wParam,
3688 LPARAM lParam)
3689 {
3690 if(nMsg == MM_MCINOTIFY)
3691 {
3692 wxASSERT(lParam == (LPARAM) m_hDev);
3693 if(wParam == MCI_NOTIFY_SUCCESSFUL && lParam == (LPARAM)m_hDev)
3694 {
3695 wxMediaEvent theEvent(wxEVT_MEDIA_STOP, m_ctrl->GetId());
3696 m_ctrl->ProcessEvent(theEvent);
3697
3698 if(theEvent.IsAllowed())
3699 {
3700 wxMCIVERIFY( mciSendCommand(m_hDev, MCI_SEEK,
3701 MCI_SEEK_TO_START, 0) );
3702
3703 //send the event to our child
3704 wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED,
3705 m_ctrl->GetId());
3706 m_ctrl->ProcessEvent(theEvent);
3707 }
3708 }
3709 }
3710 return DefWindowProc(hWnd, nMsg, wParam, lParam);
3711 }
3712
3713 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3714 //
3715 // wxQTMediaBackend
3716 //
3717 // TODO: Use a less cludgy way to pause/get state/set state
3718 // FIXME: Greg Hazel reports that sometimes files that cannot be played
3719 // with this backend are treated as playable anyway - not verifyed though.
3720 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3721
3722 IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend);
3723
3724 //Time between timer calls - this is the Apple recommondation to the TCL
3725 //team I believe
3726 #define MOVIE_DELAY 20
3727
3728 #include "wx/timer.h"
3729
3730
3731 //---------------------------------------------------------------------------
3732 // wxQTLoadTimer
3733 //
3734 // QT, esp. QT for Windows is very picky about how you go about
3735 // async loading. If you were to go through a Windows message loop
3736 // or a MoviesTask or both and then check the movie load state
3737 // it would still return 1000 (loading)... even (pre)prerolling doesn't
3738 // help. However, making a load timer like this works
3739 //---------------------------------------------------------------------------
3740 class wxQTLoadTimer : public wxTimer
3741 {
3742 public:
3743 wxQTLoadTimer(Movie movie, wxQTMediaBackend* parent, wxQuickTimeLibrary* pLib) :
3744 m_movie(movie), m_parent(parent), m_pLib(pLib) {}
3745
3746 void Notify()
3747 {
3748 m_pLib->MoviesTask(m_movie, 0);
3749 //kMovieLoadStatePlayable
3750 if(m_pLib->GetMovieLoadState(m_movie) >= 10000)
3751 {
3752 m_parent->FinishLoad();
3753 delete this;
3754 }
3755 }
3756
3757 protected:
3758 Movie m_movie; //Our movie instance
3759 wxQTMediaBackend* m_parent; //Backend pointer
3760 wxQuickTimeLibrary* m_pLib; //Interfaces
3761 };
3762
3763
3764 // --------------------------------------------------------------------------
3765 // wxQTPlayTimer - Handle Asyncronous Playing
3766 //
3767 // 1) Checks to see if the movie is done, and if not continues
3768 // streaming the movie
3769 // 2) Sends the wxEVT_MEDIA_STOP event if we have reached the end of
3770 // the movie.
3771 // --------------------------------------------------------------------------
3772 class wxQTPlayTimer : public wxTimer
3773 {
3774 public:
3775 wxQTPlayTimer(Movie movie, wxQTMediaBackend* parent,
3776 wxQuickTimeLibrary* pLib) :
3777 m_movie(movie), m_parent(parent), m_pLib(pLib) {}
3778
3779 void Notify()
3780 {
3781 //
3782 // OK, a little explaining - basically originally
3783 // we only called MoviesTask if the movie was actually
3784 // playing (not paused or stopped)... this was before
3785 // we realized MoviesTask actually handles repainting
3786 // of the current frame - so if you were to resize
3787 // or something it would previously not redraw that
3788 // portion of the movie.
3789 //
3790 // So now we call MoviesTask always so that it repaints
3791 // correctly.
3792 //
3793 m_pLib->MoviesTask(m_movie, 0);
3794
3795 //
3796 // Handle the stop event - if the movie has reached
3797 // the end, notify our handler
3798 //
3799 // m_bPlaying == !(Stopped | Paused)
3800 //
3801 if (m_parent->m_bPlaying)
3802 {
3803 if(m_pLib->IsMovieDone(m_movie))
3804 {
3805 wxMediaEvent theEvent(wxEVT_MEDIA_STOP,
3806 m_parent->m_ctrl->GetId());
3807 m_parent->m_ctrl->ProcessEvent(theEvent);
3808
3809 if(theEvent.IsAllowed())
3810 {
3811 m_parent->Stop();
3812 wxASSERT(m_pLib->GetMoviesError() == noErr);
3813
3814 //send the event to our child
3815 wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED,
3816 m_parent->m_ctrl->GetId());
3817 m_parent->m_ctrl->AddPendingEvent(theEvent);
3818 }
3819 }
3820 }
3821 }
3822
3823 protected:
3824 Movie m_movie; //Our movie instance
3825 wxQTMediaBackend* m_parent; //Backend pointer
3826 wxQuickTimeLibrary* m_pLib; //Interfaces
3827 };
3828
3829
3830 //---------------------------------------------------------------------------
3831 // wxQTMediaBackend::QTWndProc
3832 //
3833 // Forwards events to the Movie Controller so that it can
3834 // redraw itself/process messages etc..
3835 //---------------------------------------------------------------------------
3836 LRESULT CALLBACK wxQTMediaBackend::QTWndProc(HWND hWnd, UINT nMsg,
3837 WPARAM wParam, LPARAM lParam)
3838 {
3839 wxQTMediaBackend* pThis = (wxQTMediaBackend*)wxGetWindowUserData(hWnd);
3840
3841 MSG msg;
3842 msg.hwnd = hWnd;
3843 msg.message = nMsg;
3844 msg.wParam = wParam;
3845 msg.lParam = lParam;
3846 msg.time = 0;
3847 msg.pt.x = 0;
3848 msg.pt.y = 0;
3849 EventRecord theEvent;
3850 pThis->m_lib.NativeEventToMacEvent(&msg, &theEvent);
3851 pThis->m_lib.MCIsPlayerEvent(pThis->m_pMC, &theEvent);
3852 return pThis->m_ctrl->MSWWindowProc(nMsg, wParam, lParam);
3853 }
3854
3855 //---------------------------------------------------------------------------
3856 // wxQTMediaBackend Destructor
3857 //
3858 // Sets m_timer to NULL signifying we havn't loaded anything yet
3859 //---------------------------------------------------------------------------
3860 wxQTMediaBackend::wxQTMediaBackend()
3861 : m_movie(NULL), m_bPlaying(false), m_timer(NULL), m_pMC(NULL)
3862 {
3863 }
3864
3865 //---------------------------------------------------------------------------
3866 // wxQTMediaBackend Destructor
3867 //
3868 // 1) Cleans up the QuickTime movie instance
3869 // 2) Decrements the QuickTime reference counter - if this reaches
3870 // 0, QuickTime shuts down
3871 // 3) Decrements the QuickTime Windows Media Layer reference counter -
3872 // if this reaches 0, QuickTime shuts down the Windows Media Layer
3873 //---------------------------------------------------------------------------
3874 wxQTMediaBackend::~wxQTMediaBackend()
3875 {
3876 if(m_movie)
3877 Cleanup();
3878
3879 if(m_lib.IsOk())
3880 {
3881 if(m_pMC)
3882 {
3883 m_lib.DisposeMovieController(m_pMC);
3884 // m_pMC = NULL;
3885 }
3886
3887 m_lib.DestroyPortAssociation(
3888 (CGrafPtr)m_lib.GetNativeWindowPort(m_ctrl->GetHWND()));
3889
3890 //Note that ExitMovies() is not necessary, but
3891 //the docs are fuzzy on whether or not TerminateQTML is
3892 m_lib.ExitMovies();
3893 m_lib.TerminateQTML();
3894 }
3895 }
3896
3897 //---------------------------------------------------------------------------
3898 // wxQTMediaBackend::CreateControl
3899 //
3900 // 1) Intializes QuickTime
3901 // 2) Creates the control window
3902 //---------------------------------------------------------------------------
3903 bool wxQTMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
3904 wxWindowID id,
3905 const wxPoint& pos,
3906 const wxSize& size,
3907 long style,
3908 const wxValidator& validator,
3909 const wxString& name)
3910 {
3911 if(!m_lib.Initialize())
3912 return false;
3913
3914 int nError = m_lib.InitializeQTML(0);
3915 if (nError != noErr) //-2093 no dll
3916 {
3917 wxFAIL_MSG(wxString::Format(wxT("Couldn't Initialize Quicktime-%i"),
3918 nError));
3919 return false;
3920 }
3921 m_lib.EnterMovies();
3922
3923 //
3924 // Create window
3925 // By default wxWindow(s) is created with a border -
3926 // so we need to get rid of those
3927 //
3928 // Since we don't have a child window like most other
3929 // backends, we don't need wxCLIP_CHILDREN
3930 //
3931 if ( !ctrl->wxControl::Create(parent, id, pos, size,
3932 (style & ~wxBORDER_MASK) | wxBORDER_NONE,
3933 validator, name) )
3934 return false;
3935
3936
3937 m_ctrl = ctrl; //assign the control to our member
3938
3939 // Create a port association for our window so we
3940 // can use it as a WindowRef
3941 m_lib.CreatePortAssociation(m_ctrl->GetHWND(), NULL, 0L);
3942
3943 //Part of a suggestion from Greg Hazel to repaint
3944 //movie when idle
3945 m_ctrl->Connect(m_ctrl->GetId(), wxEVT_ERASE_BACKGROUND,
3946 wxEraseEventHandler(wxQTMediaEvtHandler::OnEraseBackground),
3947 NULL, (wxEvtHandler*) this);
3948
3949 // done
3950 return true;
3951 }
3952
3953 //---------------------------------------------------------------------------
3954 // wxQTMediaBackend::Load (file version)
3955 //
3956 // 1) Get an FSSpec from the Windows path name
3957 // 2) Open the movie
3958 // 3) Obtain the movie instance from the movie resource
3959 // 4) Close the movie resource
3960 // 5) Finish loading
3961 //---------------------------------------------------------------------------
3962 bool wxQTMediaBackend::Load(const wxString& fileName)
3963 {
3964 if(m_movie)
3965 Cleanup();
3966
3967 short movieResFile = 0; //= 0 because of annoying VC6 warning
3968 FSSpec sfFile;
3969
3970 if (m_lib.NativePathNameToFSSpec ((char*) (const char*) fileName.mb_str(),
3971 &sfFile, 0) != noErr)
3972 return false;
3973
3974 if (m_lib.OpenMovieFile (&sfFile, &movieResFile, fsRdPerm) != noErr)
3975 return false;
3976
3977 short movieResID = 0;
3978 Str255 movieName;
3979
3980 OSErr err = m_lib.NewMovieFromFile (
3981 &m_movie,
3982 movieResFile,
3983 &movieResID,
3984 movieName,
3985 newMovieActive,
3986 NULL
3987 ); //wasChanged
3988
3989 //m_lib.GetMoviesStickyError() because it may not find the
3990 //proper codec and play black video and other strange effects,
3991 //not to mention mess up the dynamic backend loading scheme
3992 //of wxMediaCtrl - so it just does what the QuickTime player does
3993 if(err == noErr && m_lib.GetMoviesStickyError() == noErr)
3994 {
3995 m_lib.CloseMovieFile (movieResFile);
3996
3997 FinishLoad();
3998 return true;
3999 }
4000 else
4001 return false;
4002 }
4003
4004
4005 //---------------------------------------------------------------------------
4006 // wxQTMediaBackend::PPRMProc (static)
4007 //
4008 // Called when done PrePrerolling the movie.
4009 // Note that in 99% of the cases this does nothing...
4010 // Anyway we set up the loading timer here to tell us when the movie is done
4011 //---------------------------------------------------------------------------
4012 void wxQTMediaBackend::PPRMProc (Movie theMovie,
4013 OSErr WXUNUSED_UNLESS_DEBUG(theErr),
4014 void* theRefCon)
4015 {
4016 wxASSERT( theMovie );
4017 wxASSERT( theRefCon );
4018 wxASSERT( theErr == noErr );
4019
4020 wxQTMediaBackend* pBE = (wxQTMediaBackend*) theRefCon;
4021
4022 long lTime = pBE->m_lib.GetMovieTime(theMovie,NULL);
4023 Fixed rate = pBE->m_lib.GetMoviePreferredRate(theMovie);
4024 pBE->m_lib.PrerollMovie(theMovie,lTime,rate);
4025 pBE->m_timer = new wxQTLoadTimer(pBE->m_movie, pBE, &pBE->m_lib);
4026 pBE->m_timer->Start(MOVIE_DELAY);
4027 }
4028
4029
4030 //---------------------------------------------------------------------------
4031 // wxQTMediaBackend::Load (URL Version)
4032 //
4033 // 1) Build an escaped URI from location
4034 // 2) Create a handle to store the URI string
4035 // 3) Put the URI string inside the handle
4036 // 4) Make a QuickTime URL data ref from the handle with the URI in it
4037 // 5) Clean up the URI string handle
4038 // 6) Do some prerolling
4039 // 7) Finish Loading
4040 //---------------------------------------------------------------------------
4041 bool wxQTMediaBackend::Load(const wxURI& location)
4042 {
4043 if(m_movie)
4044 Cleanup();
4045
4046 wxString theURI = location.BuildURI();
4047
4048 Handle theHandle = m_lib.NewHandleClear(theURI.length() + 1);
4049 wxASSERT(theHandle);
4050
4051 m_lib.BlockMove(theURI.mb_str(), *theHandle, theURI.length() + 1);
4052
4053 //create the movie from the handle that refers to the URI
4054 OSErr err = m_lib.NewMovieFromDataRef(&m_movie, newMovieActive |
4055 newMovieAsyncOK
4056 /*|newMovieIdleImportOK*/,
4057 NULL, theHandle,
4058 URLDataHandlerSubType);
4059
4060 m_lib.DisposeHandle(theHandle);
4061
4062 if (err == noErr)
4063 {
4064 long timeNow;
4065 Fixed playRate;
4066
4067 timeNow = m_lib.GetMovieTime(m_movie, NULL);
4068 wxASSERT(m_lib.GetMoviesError() == noErr);
4069
4070 playRate = m_lib.GetMoviePreferredRate(m_movie);
4071 wxASSERT(m_lib.GetMoviesError() == noErr);
4072
4073 //
4074 // Note that the callback here is optional,
4075 // but without it PrePrerollMovie can be buggy
4076 // (see Apple ml). Also, some may wonder
4077 // why we need this at all - this is because
4078 // Apple docs say QuickTime streamed movies
4079 // require it if you don't use a Movie Controller,
4080 // which we don't by default.
4081 //
4082 m_lib.PrePrerollMovie(m_movie, timeNow, playRate,
4083 (WXFARPROC)wxQTMediaBackend::PPRMProc,
4084 (void*)this);
4085 return true;
4086 }
4087 else
4088 return false;
4089 }
4090
4091
4092 //---------------------------------------------------------------------------
4093 // wxQTMediaBackend::FinishLoad
4094 //
4095 // 1) Create the movie timer
4096 // 2) Get real size of movie for GetBestSize/sizers
4097 // 3) Set the movie time scale to something usable so that seeking
4098 // etc. will work correctly
4099 // 4) Set our Movie Controller to display the movie if it exists,
4100 // otherwise set the bounds of the Movie
4101 // 5) Refresh parent window
4102 //---------------------------------------------------------------------------
4103 void wxQTMediaBackend::FinishLoad()
4104 {
4105 // Create the playing/streaming timer
4106 m_timer = new wxQTPlayTimer(m_movie, (wxQTMediaBackend*) this, &m_lib);
4107 wxASSERT(m_timer);
4108 m_timer->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS);
4109
4110 //get the real size of the movie
4111 Rect outRect;
4112 memset(&outRect, 0, sizeof(Rect)); //for annoying VC6 warning
4113 m_lib.GetMovieNaturalBoundsRect (m_movie, &outRect);
4114 wxASSERT(m_lib.GetMoviesError() == noErr);
4115
4116 m_bestSize.x = outRect.right - outRect.left;
4117 m_bestSize.y = outRect.bottom - outRect.top;
4118
4119 //
4120 // Handle the movie GWorld
4121 //
4122 if(m_pMC)
4123 {
4124 Point thePoint;
4125 thePoint.h = thePoint.v = 0;
4126 m_lib.MCSetMovie(m_pMC, m_movie,
4127 m_lib.GetNativeWindowPort(m_ctrl->GetHandle()),
4128 thePoint);
4129 m_lib.MCSetVisible(m_pMC, true);
4130 m_bestSize.y += 16;
4131 }
4132 else
4133 {
4134 m_lib.SetMovieGWorld(m_movie,
4135 (CGrafPtr) m_lib.GetNativeWindowPort(m_ctrl->GetHWND()),
4136 NULL);
4137 }
4138
4139 //
4140 // Set the movie to millisecond precision
4141 //
4142 m_lib.SetMovieTimeScale(m_movie, 1000);
4143 wxASSERT(m_lib.GetMoviesError() == noErr);
4144
4145 //
4146 //Here, if the parent of the control has a sizer - we
4147 //tell it to recalculate the size of this control since
4148 //the user opened a separate media file
4149 //
4150 m_ctrl->InvalidateBestSize();
4151 m_ctrl->GetParent()->Layout();
4152 m_ctrl->GetParent()->Refresh();
4153 m_ctrl->GetParent()->Update();
4154 m_ctrl->SetSize(m_ctrl->GetSize());
4155
4156 //loaded - note that MoviesTask must and will be called before this
4157 //by the previous timer since this gets appended to the event list after
4158 //the timer's first go
4159 wxMediaEvent theEvent(wxEVT_MEDIA_LOADED,
4160 m_ctrl->GetId());
4161 m_ctrl->AddPendingEvent(theEvent);
4162 }
4163
4164 //---------------------------------------------------------------------------
4165 // wxQTMediaBackend::Play
4166 //
4167 // 1) Start the QT movie
4168 // 2) Start the movie loading timer
4169 //
4170 // NOTE: This will still return success even when
4171 // the movie is still loading, and as mentioned in wxQTLoadTimer
4172 // I don't know of a way to force this to be sync - so if its
4173 // still loading the function will return true but the movie will
4174 // still be in the stopped state
4175 //---------------------------------------------------------------------------
4176 bool wxQTMediaBackend::Play()
4177 {
4178 m_lib.StartMovie(m_movie);
4179 m_bPlaying = true;
4180 return m_lib.GetMoviesError() == noErr;
4181 }
4182
4183 //---------------------------------------------------------------------------
4184 // wxQTMediaBackend::Pause
4185 //
4186 // 1) Stop the movie
4187 // 2) Stop the movie timer
4188 //---------------------------------------------------------------------------
4189 bool wxQTMediaBackend::Pause()
4190 {
4191 m_bPlaying = false;
4192 m_lib.StopMovie(m_movie);
4193 return m_lib.GetMoviesError() == noErr;
4194 }
4195
4196 //---------------------------------------------------------------------------
4197 // wxQTMediaBackend::Stop
4198 //
4199 // 1) Stop the movie
4200 // 2) Stop the movie timer
4201 // 3) Seek to the beginning of the movie
4202 //---------------------------------------------------------------------------
4203 bool wxQTMediaBackend::Stop()
4204 {
4205 m_bPlaying = false;
4206
4207 m_lib.StopMovie(m_movie);
4208 if(m_lib.GetMoviesError() != noErr)
4209 return false;
4210
4211 m_lib.GoToBeginningOfMovie(m_movie);
4212 return m_lib.GetMoviesError() == noErr;
4213 }
4214
4215 //---------------------------------------------------------------------------
4216 // wxQTMediaBackend::GetPlaybackRate
4217 //
4218 // 1) Get the movie playback rate from ::GetMovieRate
4219 //---------------------------------------------------------------------------
4220 double wxQTMediaBackend::GetPlaybackRate()
4221 {
4222 return ( ((double)m_lib.GetMovieRate(m_movie)) / 0x10000);
4223 }
4224
4225 //---------------------------------------------------------------------------
4226 // wxQTMediaBackend::SetPlaybackRate
4227 //
4228 // 1) Convert dRate to Fixed and Set the movie rate through SetMovieRate
4229 //---------------------------------------------------------------------------
4230 bool wxQTMediaBackend::SetPlaybackRate(double dRate)
4231 {
4232 m_lib.SetMovieRate(m_movie, (Fixed) (dRate * 0x10000));
4233 return m_lib.GetMoviesError() == noErr;
4234 }
4235
4236 //---------------------------------------------------------------------------
4237 // wxQTMediaBackend::SetPosition
4238 //
4239 // 1) Create a time record struct (TimeRecord) with appropriate values
4240 // 2) Pass struct to SetMovieTime
4241 //---------------------------------------------------------------------------
4242 bool wxQTMediaBackend::SetPosition(wxLongLong where)
4243 {
4244 //NB: For some reason SetMovieTime does not work
4245 //correctly with the Quicktime Windows SDK (6)
4246 //From Muskelkatermann at the wxForum
4247 //http://www.solidsteel.nl/users/wxwidgets/viewtopic.php?t=2957
4248 //RN - note that I have not verified this but there
4249 //is no harm in calling SetMovieTimeValue instead
4250 #if 0
4251 TimeRecord theTimeRecord;
4252 memset(&theTimeRecord, 0, sizeof(TimeRecord));
4253 theTimeRecord.value.lo = where.GetLo();
4254 theTimeRecord.scale = m_lib.GetMovieTimeScale(m_movie);
4255 theTimeRecord.base = m_lib.GetMovieTimeBase(m_movie);
4256 m_lib.SetMovieTime(m_movie, &theTimeRecord);
4257 #else
4258 m_lib.SetMovieTimeValue(m_movie, where.GetLo());
4259 #endif
4260 if (m_lib.GetMoviesError() != noErr)
4261 return false;
4262
4263 return true;
4264 }
4265
4266 //---------------------------------------------------------------------------
4267 // wxQTMediaBackend::GetPosition
4268 //
4269 // 1) Calls GetMovieTime to get the position we are in in the movie
4270 // in milliseconds (we called
4271 //---------------------------------------------------------------------------
4272 wxLongLong wxQTMediaBackend::GetPosition()
4273 {
4274 return m_lib.GetMovieTime(m_movie, NULL);
4275 }
4276
4277 //---------------------------------------------------------------------------
4278 // wxQTMediaBackend::GetVolume
4279 //
4280 // Gets the volume through GetMovieVolume - which returns a 16 bit short -
4281 //
4282 // +--------+--------+
4283 // + (1) + (2) +
4284 // +--------+--------+
4285 //
4286 // (1) first 8 bits are value before decimal
4287 // (2) second 8 bits are value after decimal
4288 //
4289 // Volume ranges from -1.0 (gain but no sound), 0 (no sound and no gain) to
4290 // 1 (full gain and sound)
4291 //---------------------------------------------------------------------------
4292 double wxQTMediaBackend::GetVolume()
4293 {
4294 short sVolume = m_lib.GetMovieVolume(m_movie);
4295 wxASSERT(m_lib.GetMoviesError() == noErr);
4296
4297 if(sVolume & (128 << 8)) //negative - no sound
4298 return 0.0;
4299
4300 return sVolume/256.0;
4301 }
4302
4303 //---------------------------------------------------------------------------
4304 // wxQTMediaBackend::SetVolume
4305 //
4306 // Sets the volume through SetMovieVolume - which takes a 16 bit short -
4307 //
4308 // +--------+--------+
4309 // + (1) + (2) +
4310 // +--------+--------+
4311 //
4312 // (1) first 8 bits are value before decimal
4313 // (2) second 8 bits are value after decimal
4314 //
4315 // Volume ranges from -1.0 (gain but no sound), 0 (no sound and no gain) to
4316 // 1 (full gain and sound)
4317 //---------------------------------------------------------------------------
4318 bool wxQTMediaBackend::SetVolume(double dVolume)
4319 {
4320 m_lib.SetMovieVolume(m_movie, (short) (dVolume * 256));
4321 return m_lib.GetMoviesError() == noErr;
4322 }
4323
4324 //---------------------------------------------------------------------------
4325 // wxQTMediaBackend::GetDuration
4326 //
4327 // Calls GetMovieDuration
4328 //---------------------------------------------------------------------------
4329 wxLongLong wxQTMediaBackend::GetDuration()
4330 {
4331 return m_lib.GetMovieDuration(m_movie);
4332 }
4333
4334 //---------------------------------------------------------------------------
4335 // wxQTMediaBackend::GetState
4336 //
4337 // Determines the current state - if we are at the beginning we
4338 // are stopped
4339 //---------------------------------------------------------------------------
4340 wxMediaState wxQTMediaBackend::GetState()
4341 {
4342 if (m_bPlaying == true)
4343 return wxMEDIASTATE_PLAYING;
4344 else if ( !m_movie || wxQTMediaBackend::GetPosition() == 0)
4345 return wxMEDIASTATE_STOPPED;
4346 else
4347 return wxMEDIASTATE_PAUSED;
4348 }
4349
4350 //---------------------------------------------------------------------------
4351 // wxQTMediaBackend::Cleanup
4352 //
4353 // Diposes of the movie timer, Disassociates the Movie Controller with
4354 // movie and hides it if it exists, and stops and disposes
4355 // of the QT movie
4356 //---------------------------------------------------------------------------
4357 void wxQTMediaBackend::Cleanup()
4358 {
4359 m_bPlaying = false;
4360
4361 if(m_timer)
4362 {
4363 delete m_timer;
4364 m_timer = NULL;
4365 }
4366
4367 m_lib.StopMovie(m_movie);
4368
4369 if(m_pMC)
4370 {
4371 Point thePoint;
4372 thePoint.h = thePoint.v = 0;
4373 m_lib.MCSetVisible(m_pMC, false);
4374 m_lib.MCSetMovie(m_pMC, NULL, NULL, thePoint);
4375 }
4376
4377 m_lib.DisposeMovie(m_movie);
4378 m_movie = NULL;
4379 }
4380
4381 //---------------------------------------------------------------------------
4382 // wxQTMediaBackend::ShowPlayerControls
4383 //
4384 // Creates a movie controller for the Movie if the user wants it
4385 //---------------------------------------------------------------------------
4386 bool wxQTMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
4387 {
4388 if(m_pMC)
4389 {
4390 //restore old wndproc
4391 wxSetWindowProc((HWND)m_ctrl->GetHWND(), wxWndProc);
4392 m_lib.DisposeMovieController(m_pMC);
4393 m_pMC = NULL;
4394 m_bestSize.y -= 16; //movie controller height
4395 }
4396
4397 if(flags && m_movie)
4398 {
4399 Rect rect;
4400 wxRect wxrect = m_ctrl->GetClientRect();
4401
4402 //make room for controller
4403 if(wxrect.width < 320)
4404 wxrect.width = 320;
4405
4406 rect.top = (short)wxrect.y;
4407 rect.left = (short)wxrect.x;
4408 rect.right = (short)(rect.left + wxrect.width);
4409 rect.bottom = (short)(rect.top + wxrect.height);
4410
4411 if(!m_pMC)
4412 {
4413 m_pMC = m_lib.NewMovieController(m_movie, &rect, mcTopLeftMovie |
4414 // mcScaleMovieToFit |
4415 // mcWithBadge |
4416 mcWithFrame);
4417 m_lib.MCDoAction(m_pMC, 32, (void*)true); //mcActionSetKeysEnabled
4418 m_lib.MCSetActionFilterWithRefCon(m_pMC,
4419 (WXFARPROC)wxQTMediaBackend::MCFilterProc, (void*)this);
4420 m_bestSize.y += 16; //movie controller height
4421
4422 //
4423 // By default the movie controller uses its own color
4424 // pallette for the movie which can be bad on some files -
4425 // so turn it off. Also turn off its frame/border for
4426 // the movie
4427 //
4428 // Also we take care of a couple of the interface flags here
4429 //
4430 long mcFlags = 0;
4431 m_lib.MCDoAction(m_pMC, 39/*mcActionGetFlags*/, (void*)&mcFlags);
4432 mcFlags |= ( //(1<<0)/*mcFlagSuppressMovieFrame*/ |
4433 (1<<3)/*mcFlagsUseWindowPalette*/
4434 | ((flags & wxMEDIACTRLPLAYERCONTROLS_STEP)
4435 ? 0 : (1<<1)/*mcFlagSuppressStepButtons*/)
4436 | ((flags & wxMEDIACTRLPLAYERCONTROLS_VOLUME)
4437 ? 0 : (1<<2)/*mcFlagSuppressSpeakerButton*/)
4438 // | (1<<4) /*mcFlagDontInvalidate*/ //if we take care of repainting ourselves
4439 );
4440 m_lib.MCDoAction(m_pMC, 38/*mcActionSetFlags*/, (void*)mcFlags);
4441
4442 //intercept the wndproc of our control window
4443 wxSetWindowProc((HWND)m_ctrl->GetHWND(),
4444 wxQTMediaBackend::QTWndProc);
4445
4446 //set the user data of our window
4447 wxSetWindowUserData((HWND)m_ctrl->GetHWND(), this);
4448 }
4449 }
4450
4451 //
4452 //Here, if the parent of the control has a sizer - we
4453 //tell it to recalculate the size of this control since
4454 //the user opened a separate media file
4455 //
4456 m_ctrl->InvalidateBestSize();
4457 m_ctrl->GetParent()->Layout();
4458 m_ctrl->GetParent()->Refresh();
4459 m_ctrl->GetParent()->Update();
4460 m_ctrl->SetSize(m_ctrl->GetSize());
4461
4462 return m_lib.GetMoviesError() == noErr;
4463 }
4464
4465 //---------------------------------------------------------------------------
4466 // wxQTMediaBackend::MCFilterProc (static)
4467 //
4468 // Callback for when the movie controller recieves a message
4469 //---------------------------------------------------------------------------
4470 Boolean
4471 wxQTMediaBackend::MCFilterProc(MovieController WXUNUSED(theController),
4472 short action,
4473 void * WXUNUSED(params),
4474 LONG_PTR refCon)
4475 {
4476 if(action != 1) //don't process idle events
4477 {
4478 wxQTMediaBackend* pThis = (wxQTMediaBackend*)refCon;
4479
4480 switch(action)
4481 {
4482 case 8: //play button triggered - MC will set movie to opposite state
4483 //of current - playing ? paused : playing
4484 pThis->m_bPlaying = !(pThis->m_bPlaying);
4485
4486 // NB: Sometimes it doesn't redraw properly -
4487 // if you click on the button but don't move the mouse
4488 // the button will not change its state until you move
4489 // mcActionDraw and Refresh/Update combo do nothing
4490 // to help this unfortunately
4491 break;
4492 default:
4493 break;
4494 }
4495 }
4496 return 0;
4497 }
4498
4499 //---------------------------------------------------------------------------
4500 // wxQTMediaBackend::GetVideoSize
4501 //
4502 // Returns the actual size of the QT movie
4503 //---------------------------------------------------------------------------
4504 wxSize wxQTMediaBackend::GetVideoSize() const
4505 {
4506 return m_bestSize;
4507 }
4508
4509 //---------------------------------------------------------------------------
4510 // wxQTMediaBackend::Move
4511 //
4512 // Sets the bounds of either the Movie or Movie Controller
4513 //---------------------------------------------------------------------------
4514 void wxQTMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y), int w, int h)
4515 {
4516 if(m_movie)
4517 {
4518 //make room for controller
4519 if(m_pMC)
4520 {
4521 if(w < 320)
4522 w = 320;
4523
4524 Rect theRect = {0, 0, (short)h, (short)w};
4525 m_lib.MCSetControllerBoundsRect(m_pMC, &theRect);
4526 }
4527 else
4528 {
4529 Rect theRect = {0, 0, (short)h, (short)w};
4530 m_lib.SetMovieBox(m_movie, &theRect);
4531 }
4532
4533 wxASSERT(m_lib.GetMoviesError() == noErr);
4534 }
4535 }
4536
4537 //---------------------------------------------------------------------------
4538 // wxQTMediaBackend::OnEraseBackground
4539 //
4540 // Suggestion from Greg Hazel to repaint the movie when idle
4541 // (on pause also)
4542 //
4543 // TODO: We may be repainting too much here - under what exact circumstances
4544 // do we need this? I think Move also repaints correctly for the Movie
4545 // Controller, so in that instance we don't need this either
4546 //---------------------------------------------------------------------------
4547 void wxQTMediaEvtHandler::OnEraseBackground(wxEraseEvent& evt)
4548 {
4549 wxQTMediaBackend* qtb = (wxQTMediaBackend*)this;
4550 wxQuickTimeLibrary* m_pLib = &(qtb->m_lib);
4551
4552 if(qtb->m_pMC)
4553 {
4554 //repaint movie controller
4555 m_pLib->MCDoAction(qtb->m_pMC, 2 /*mcActionDraw*/,
4556 m_pLib->GetNativeWindowPort(qtb->m_ctrl->GetHWND())
4557 );
4558 }
4559 else if(qtb->m_movie)
4560 {
4561 CGrafPtr port = (CGrafPtr)m_pLib->GetNativeWindowPort
4562 (qtb->m_ctrl->GetHWND());
4563
4564 m_pLib->BeginUpdate(port);
4565 m_pLib->UpdateMovie(qtb->m_movie);
4566 wxASSERT(m_pLib->GetMoviesError() == noErr);
4567 m_pLib->EndUpdate(port);
4568 }
4569
4570 evt.Skip(); //repaint with window background (TODO: maybe !m_movie?)
4571 }
4572
4573 //---------------------------------------------------------------------------
4574 // End QT Backend
4575 //---------------------------------------------------------------------------
4576
4577 //in source file that contains stuff you don't directly use
4578 #include <wx/html/forcelnk.h>
4579 FORCE_LINK_ME(basewxmediabackends);
4580
4581 //---------------------------------------------------------------------------
4582 // End wxMediaCtrl Compilation Guard and this file
4583 //---------------------------------------------------------------------------
4584 #endif //wxUSE_MEDIACTRL
4585
4586