1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/msw/mediactrl_am.cpp
3 // Purpose:     ActiveMovie/WMP6/PocketPC 2000 Media Backend for Windows
4 // Author:      Ryan Norton <wxprojects@comcast.net>
5 // Modified by:
6 // Created:     01/29/05
7 // Copyright:   (c) Ryan Norton
8 // Licence:     wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10 
11 // TODO: Actually test HTTP proxies...
12 
13 //-----------------Introduction----------------------------------------------
14 // This is the media backend for Windows Media Player 6 and ActiveMovie.
15 //
16 // We use a combination of the WMP 6 IMediaPlayer interface as well as the
17 // ActiveMovie interface IActiveMovie.
18 //
19 // For supporting HTTP proxies and such we query the media player
20 // interface (IActiveMovie) for the INSPlay (NetShow) interface.
21 //
22 // The IMediaPlayer/IActiveMovie are rather clean and straightforward
23 // interfaces that are fairly simplistic.
24 //
25 // Docs for IMediaPlayer are at
26 // http://msdn.microsoft.com/library/en-us/wmp6sdk/htm/microsoftwindowsmediaplayercontrolversion64sdk.asp
27 
28 //===========================================================================
29 //  DECLARATIONS
30 //===========================================================================
31 
32 //---------------------------------------------------------------------------
33 // Pre-compiled header stuff
34 //---------------------------------------------------------------------------
35 
36 // For compilers that support precompilation, includes "wx.h".
37 #include "wx/wxprec.h"
38 
39 
40 #if wxUSE_MEDIACTRL && wxUSE_ACTIVEX
41 
42 #include "wx/mediactrl.h"
43 
44 #ifndef WX_PRECOMP
45     #include "wx/log.h"
46     #include "wx/dcclient.h"
47     #include "wx/timer.h"
48     #include "wx/math.h"        // log10 & pow
49     #include "wx/stopwatch.h"
50 #endif
51 
52 #include "wx/msw/private.h" // user info and wndproc setting/getting
53 #include "wx/dynlib.h"
54 
55 //---------------------------------------------------------------------------
56 //  wxActiveXContainer - includes all the COM-specific stuff we need
57 //---------------------------------------------------------------------------
58 #include "wx/msw/ole/activex.h"
59 
60 //---------------------------------------------------------------------------
61 //  IIDS - used by CoCreateInstance and IUnknown::QueryInterface
62 //
63 //  [idl name]          [idl decription]
64 //  amcompat.idl        Microsoft Active Movie Control (Ver 2.0)
65 //  nscompat.idl        Microsoft NetShow Player (Ver 1.0)
66 //  msdxm.idl           Windows Media Player (Ver 1.0)
67 //  quartz.idl
68 //
69 //  First, when I say I "from XXX.idl", I mean I go into the COM Browser
70 //  ($Microsoft Visual Studio$/Common/Tools/OLEVIEW.EXE), open
71 //  "type libraries", open a specific type library (for quartz for example its
72 //  "ActiveMovie control type library (V1.0)"), save it as an .idl, compile the
73 //  idl using the midl compiler that comes with visual studio with the /h
74 //  argument to make it generate stubs (a .h & .c file), then clean up the
75 //  generated interfaces I want with the STDMETHOD wrappers and then put them
76 //  into mediactrl.cpp.
77 //
78 //  Some of these are not used but are kept here for future reference anyway
79 //---------------------------------------------------------------------------
80 wxCLANG_WARNING_SUPPRESS(unused-const-variable)
81 const IID IID_IActiveMovie          = {0x05589FA2,0xC356,0x11CE,{0xBF,0x01,0x00,0xAA,0x00,0x55,0x59,0x5A}};
82 const IID IID_IActiveMovie2         = {0xB6CD6554,0xE9CB,0x11D0,{0x82,0x1F,0x00,0xA0,0xC9,0x1F,0x9C,0xA0}};
83 const IID IID_IActiveMovie3         = {0x265EC140,0xAE62,0x11D1,{0x85,0x00,0x00,0xA0,0xC9,0x1F,0x9C,0xA0}};
84 
85 const IID IID_INSOPlay              = {0x2179C5D1,0xEBFF,0x11CF,{0xB6,0xFD,0x00,0xAA,0x00,0xB4,0xE2,0x20}};
86 const IID IID_INSPlay               = {0xE7C4BE80,0x7960,0x11D0,{0xB7,0x27,0x00,0xAA,0x00,0xB4,0xE2,0x20}};
87 const IID IID_INSPlay1              = {0x265EC141,0xAE62,0x11D1,{0x85,0x00,0x00,0xA0,0xC9,0x1F,0x9C,0xA0}};
88 
89 const IID IID_IMediaPlayer          = {0x22D6F311,0xB0F6,0x11D0,{0x94,0xAB,0x00,0x80,0xC7,0x4C,0x7E,0x95}};
90 const IID IID_IMediaPlayer2         = {0x20D4F5E0,0x5475,0x11D2,{0x97,0x74,0x00,0x00,0xF8,0x08,0x55,0xE6}};
91 
92 
93 const CLSID CLSID_ActiveMovie       = {0x05589FA1,0xC356,0x11CE,{0xBF,0x01,0x00,0xAA,0x00,0x55,0x59,0x5A}};
94 const CLSID CLSID_MediaPlayer       = {0x22D6F312,0xB0F6,0x11D0,{0x94,0xAB,0x00,0x80,0xC7,0x4C,0x7E,0x95}};
95 const CLSID CLSID_NSPlay            = {0x2179C5D3,0xEBFF,0x11CF,{0xB6,0xFD,0x00,0xAA,0x00,0xB4,0xE2,0x20}};
96 
97 const IID IID_IAMOpenProgress = {0x8E1C39A1, 0xDE53, 0x11CF,{0xAA, 0x63, 0x00, 0x80, 0xC7, 0x44, 0x52, 0x8D}};
98 
99 // QUARTZ
100 const CLSID CLSID_FilgraphManager = {0xE436EBB3,0x524F,0x11CE,{0x9F,0x53,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
101 const IID IID_IMediaEvent = {0x56A868B6,0x0AD4,0x11CE,{0xB0,0x3A,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
102 
103 //??  QUARTZ Also?
104 const CLSID CLSID_VideoMixingRenderer9 ={0x51B4ABF3, 0x748F, 0x4E3B,{0xA2, 0x76, 0xC8, 0x28, 0x33, 0x0E, 0x92, 0x6A}};
105 const IID IID_IVMRWindowlessControl9 =  {0x8F537D09, 0xF85E, 0x4414,{0xB2, 0x3B, 0x50, 0x2E, 0x54, 0xC7, 0x99, 0x27}};
106 const IID IID_IFilterGraph =            {0x56A8689F, 0x0AD4, 0x11CE,{0xB0, 0x3A, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70}};
107 const IID IID_IGraphBuilder =           {0x56A868A9, 0x0AD4, 0x11CE,{0xB0, 0x3A, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70}};
108 const IID IID_IVMRFilterConfig9 =       {0x5A804648, 0x4F66, 0x4867,{0x9C, 0x43, 0x4F, 0x5C, 0x82, 0x2C, 0xF1, 0xB8}};
109 const IID IID_IBaseFilter =             {0x56A86895, 0x0AD4, 0x11CE,{0xB0, 0x3A, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70}};
110 wxCLANG_WARNING_RESTORE(unused-const-variable)
111 
112 //---------------------------------------------------------------------------
113 //  QUARTZ COM INTERFACES (dumped from quartz.idl from MSVC COM Browser)
114 //---------------------------------------------------------------------------
115 
116 struct IAMOpenProgress : public IUnknown
117 {
118     STDMETHOD(QueryProgress)(LONGLONG *pllTotal, LONGLONG *pllCurrent) PURE;
119     STDMETHOD(AbortOperation)(void) PURE;
120 };
121 
122 struct IMediaEvent : public IDispatch
123 {
124     STDMETHOD(GetEventHandle)(LONG_PTR *) PURE;
125     STDMETHOD(GetEvent)(long *, LONG_PTR *, LONG_PTR *, long) PURE;
126     STDMETHOD(WaitForCompletion)(long, long *) PURE;
127     STDMETHOD(CancelDefaultHandling)(long) PURE;
128     STDMETHOD(RestoreDefaultHandling)(long) PURE;
129     STDMETHOD(FreeEventParams)(long, LONG_PTR, LONG_PTR) PURE;
130 };
131 
132 //---------------------------------------------------------------------------
133 //  ACTIVEMOVIE COM INTERFACES (dumped from amcompat.idl from MSVC COM Browser)
134 //---------------------------------------------------------------------------
135 
136 enum ReadyStateConstants
137 {
138     amvUninitialized  = 0,
139     amvLoading        = 1,
140     amvInteractive    = 3,
141     amvComplete       = 4
142 };
143 
144 enum StateConstants
145 {
146     amvNotLoaded    = -1,
147     amvStopped      = 0,
148     amvPaused       = 1,
149     amvRunning      = 2
150 };
151 
152 enum DisplayModeConstants
153 {
154     amvTime      = 0,
155     amvFrames    = 1
156 };
157 
158 enum WindowSizeConstants
159 {
160     amvOriginalSize    = 0,
161     amvDoubleOriginalSize    = 1,
162     amvOneSixteenthScreen    = 2,
163     amvOneFourthScreen    = 3,
164     amvOneHalfScreen    = 4
165 };
166 
167 enum AppearanceConstants
168 {
169     amvFlat    = 0,
170     amv3D    = 1
171 };
172 
173 enum BorderStyleConstants
174 {
175     amvNone    = 0,
176     amvFixedSingle    = 1
177 };
178 
179 struct IActiveMovie : public IDispatch
180 {
181     STDMETHOD(AboutBox)( void) PURE;
182     STDMETHOD(Run)( void) PURE;
183     STDMETHOD(Pause)( void) PURE;
184     STDMETHOD(Stop)( void) PURE;
185     STDMETHOD(get_ImageSourceWidth)(long __RPC_FAR *pWidth) PURE;
186     STDMETHOD(get_ImageSourceHeight)(long __RPC_FAR *pHeight) PURE;
187     STDMETHOD(get_Author)(BSTR __RPC_FAR *pbstrAuthor) PURE;
188     STDMETHOD(get_Title)(BSTR __RPC_FAR *pbstrTitle) PURE;
189     STDMETHOD(get_Copyright)(BSTR __RPC_FAR *pbstrCopyright) PURE;
190     STDMETHOD(get_Description)(BSTR __RPC_FAR *pbstrDescription) PURE;
191     STDMETHOD(get_Rating)(BSTR __RPC_FAR *pbstrRating) PURE;
192     STDMETHOD(get_FileName)(BSTR __RPC_FAR *pbstrFileName) PURE;
193     STDMETHOD(put_FileName)(BSTR pbstrFileName) PURE;
194     STDMETHOD(get_Duration)(double __RPC_FAR *pValue) PURE;
195     STDMETHOD(get_CurrentPosition)(double __RPC_FAR *pValue) PURE;
196     STDMETHOD(put_CurrentPosition)(double pValue) PURE;
197     STDMETHOD(get_PlayCount)(long __RPC_FAR *pPlayCount) PURE;
198     STDMETHOD(put_PlayCount)(long pPlayCount) PURE;
199     STDMETHOD(get_SelectionStart)(double __RPC_FAR *pValue) PURE;
200     STDMETHOD(put_SelectionStart)(double pValue) PURE;
201     STDMETHOD(get_SelectionEnd)(double __RPC_FAR *pValue) PURE;
202     STDMETHOD(put_SelectionEnd)(double pValue) PURE;
203     STDMETHOD(get_CurrentState)(StateConstants __RPC_FAR *pState) PURE;
204     STDMETHOD(get_Rate)(double __RPC_FAR *pValue) PURE;
205     STDMETHOD(put_Rate)(double pValue) PURE;
206     STDMETHOD(get_Volume)(long __RPC_FAR *pValue) PURE;
207     STDMETHOD(put_Volume)(long pValue) PURE;
208     STDMETHOD(get_Balance)(long __RPC_FAR *pValue) PURE;
209     STDMETHOD(put_Balance)(long pValue) PURE;
210     STDMETHOD(get_EnableContextMenu)(VARIANT_BOOL __RPC_FAR *pEnable) PURE;
211     STDMETHOD(put_EnableContextMenu)(VARIANT_BOOL pEnable) PURE;
212     STDMETHOD(get_ShowDisplay)(VARIANT_BOOL __RPC_FAR *Show) PURE;
213     STDMETHOD(put_ShowDisplay)(VARIANT_BOOL Show) PURE;
214     STDMETHOD(get_ShowControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
215     STDMETHOD(put_ShowControls)(VARIANT_BOOL Show) PURE;
216     STDMETHOD(get_ShowPositionControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
217     STDMETHOD(put_ShowPositionControls)(VARIANT_BOOL Show) PURE;
218     STDMETHOD(get_ShowSelectionControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
219     STDMETHOD(put_ShowSelectionControls)(VARIANT_BOOL Show) PURE;
220     STDMETHOD(get_ShowTracker)(VARIANT_BOOL __RPC_FAR *Show) PURE;
221     STDMETHOD(put_ShowTracker)(VARIANT_BOOL Show) PURE;
222     STDMETHOD(get_EnablePositionControls)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
223     STDMETHOD(put_EnablePositionControls)(VARIANT_BOOL Enable) PURE;
224     STDMETHOD(get_EnableSelectionControls)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
225     STDMETHOD(put_EnableSelectionControls)(VARIANT_BOOL Enable) PURE;
226     STDMETHOD(get_EnableTracker)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
227     STDMETHOD(put_EnableTracker)(VARIANT_BOOL Enable) PURE;
228     STDMETHOD(get_AllowHideDisplay)(VARIANT_BOOL __RPC_FAR *Show) PURE;
229     STDMETHOD(put_AllowHideDisplay)(VARIANT_BOOL Show) PURE;
230     STDMETHOD(get_AllowHideControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
231     STDMETHOD(put_AllowHideControls)(VARIANT_BOOL Show) PURE;
232     STDMETHOD(get_DisplayMode)(DisplayModeConstants __RPC_FAR *pValue) PURE;
233     STDMETHOD(put_DisplayMode)(DisplayModeConstants pValue) PURE;
234     STDMETHOD(get_AllowChangeDisplayMode)(VARIANT_BOOL __RPC_FAR *fAllow) PURE;
235     STDMETHOD(put_AllowChangeDisplayMode)(VARIANT_BOOL fAllow) PURE;
236     STDMETHOD(get_FilterGraph)(IUnknown __RPC_FAR *__RPC_FAR *ppFilterGraph) PURE;
237     STDMETHOD(put_FilterGraph)(IUnknown __RPC_FAR *ppFilterGraph) PURE;
238     STDMETHOD(get_FilterGraphDispatch)(IDispatch __RPC_FAR *__RPC_FAR *pDispatch) PURE;
239     STDMETHOD(get_DisplayForeColor)(unsigned long __RPC_FAR *ForeColor) PURE;
240     STDMETHOD(put_DisplayForeColor)(unsigned long ForeColor) PURE;
241     STDMETHOD(get_DisplayBackColor)(unsigned long __RPC_FAR *BackColor) PURE;
242     STDMETHOD(put_DisplayBackColor)(unsigned long BackColor) PURE;
243     STDMETHOD(get_MovieWindowSize)(WindowSizeConstants __RPC_FAR *WindowSize) PURE;
244     STDMETHOD(put_MovieWindowSize)(WindowSizeConstants WindowSize) PURE;
245     STDMETHOD(get_FullScreenMode)(VARIANT_BOOL __RPC_FAR *pEnable) PURE;
246     STDMETHOD(put_FullScreenMode)(VARIANT_BOOL pEnable) PURE;
247     STDMETHOD(get_AutoStart)(VARIANT_BOOL __RPC_FAR *pEnable) PURE;
248     STDMETHOD(put_AutoStart)(VARIANT_BOOL pEnable) PURE;
249     STDMETHOD(get_AutoRewind)(VARIANT_BOOL __RPC_FAR *pEnable) PURE;
250     STDMETHOD(put_AutoRewind)(VARIANT_BOOL pEnable) PURE;
251     STDMETHOD(get_hWnd)(long __RPC_FAR *hWnd) PURE;
252     STDMETHOD(get_Appearance)(AppearanceConstants __RPC_FAR *pAppearance) PURE;
253     STDMETHOD(put_Appearance)(AppearanceConstants pAppearance) PURE;
254     STDMETHOD(get_BorderStyle)(BorderStyleConstants __RPC_FAR *pBorderStyle) PURE;
255     STDMETHOD(put_BorderStyle)(BorderStyleConstants pBorderStyle) PURE;
256     STDMETHOD(get_Enabled)(VARIANT_BOOL __RPC_FAR *pEnabled) PURE;
257     STDMETHOD(put_Enabled)(VARIANT_BOOL pEnabled) PURE;
258     STDMETHOD(get_Info)(long __RPC_FAR *ppInfo) PURE;
259 };
260 
261 
262 
263 struct IActiveMovie2 : public IActiveMovie
264 {
265     STDMETHOD(IsSoundCardEnabled)(VARIANT_BOOL __RPC_FAR *pbSoundCard) PURE;
266     STDMETHOD(get_ReadyState)(ReadyStateConstants __RPC_FAR *pValue) PURE;
267 };
268 
269 struct IActiveMovie3 : public IActiveMovie2
270 {
271     STDMETHOD(get_MediaPlayer)(IDispatch __RPC_FAR *__RPC_FAR *ppDispatch) PURE;
272 };
273 
274 
275 //---------------------------------------------------------------------------
276 //  MEDIAPLAYER COM INTERFACES (dumped from msdxm.idl from MSVC COM Browser)
277 //---------------------------------------------------------------------------
278 
279 enum MPPlayStateConstants
280 {
281     mpStopped = 0,
282     mpPaused    = 1,
283     mpPlaying    = 2,
284     mpWaiting    = 3,
285     mpScanForward    = 4,
286     mpScanReverse    = 5,
287     mpClosed    = 6
288 };
289 
290 enum MPDisplaySizeConstants
291 {
292     mpDefaultSize = 0,
293     mpHalfSize    = 1,
294     mpDoubleSize    = 2,
295     mpFullScreen    = 3,
296     mpFitToSize    = 4,
297     mpOneSixteenthScreen    = 5,
298     mpOneFourthScreen    = 6,
299     mpOneHalfScreen    = 7
300 };
301 
302 enum MPReadyStateConstants
303 {
304     mpReadyStateUninitialized = 0,
305     mpReadyStateLoading    = 1,
306     mpReadyStateInteractive    = 3,
307     mpReadyStateComplete    = 4
308 };
309 
310 typedef unsigned long VB_OLE_COLOR;
311 
312 enum MPDisplayModeConstants
313 {
314     mpTime = 0,
315     mpFrames    = 1
316 };
317 
318 enum MPMoreInfoType
319 {
320     mpShowURL = 0,
321     mpClipURL    = 1,
322     mpBannerURL    = 2
323 };
324 
325 enum MPMediaInfoType
326 {
327     mpShowFilename = 0,
328     mpShowTitle    = 1,
329     mpShowAuthor    = 2,
330     mpShowCopyright    = 3,
331     mpShowRating    = 4,
332     mpShowDescription    = 5,
333     mpShowLogoIcon    = 6,
334     mpClipFilename    = 7,
335     mpClipTitle    = 8,
336     mpClipAuthor    = 9,
337     mpClipCopyright    = 10,
338     mpClipRating    = 11,
339     mpClipDescription    = 12,
340     mpClipLogoIcon    = 13,
341     mpBannerImage    = 14,
342     mpBannerMoreInfo    = 15,
343     mpWatermark    = 16
344 };
345 
346 enum DVDMenuIDConstants
347 {
348     dvdMenu_Title    = 2,
349     dvdMenu_Root    = 3,
350     dvdMenu_Subpicture    = 4,
351     dvdMenu_Audio    = 5,
352     dvdMenu_Angle    = 6,
353     dvdMenu_Chapter    = 7
354 };
355 
356 enum MPShowDialogConstants
357 {
358     mpShowDialogHelp = 0,
359     mpShowDialogStatistics    = 1,
360     mpShowDialogOptions    = 2,
361     mpShowDialogContextMenu    = 3
362 };
363 
364 
365 struct IMediaPlayer : public IDispatch
366 {
367     STDMETHOD(get_CurrentPosition)(double __RPC_FAR *pCurrentPosition) PURE;
368     STDMETHOD(put_CurrentPosition)(double pCurrentPosition) PURE;
369     STDMETHOD(get_Duration)(double __RPC_FAR *pDuration) PURE;
370     STDMETHOD(get_ImageSourceWidth)(long __RPC_FAR *pWidth) PURE;
371     STDMETHOD(get_ImageSourceHeight)(long __RPC_FAR *pHeight) PURE;
372     STDMETHOD(get_MarkerCount)(long __RPC_FAR *pMarkerCount) PURE;
373     STDMETHOD(get_CanScan)(VARIANT_BOOL __RPC_FAR *pCanScan) PURE;
374     STDMETHOD(get_CanSeek)(VARIANT_BOOL __RPC_FAR *pCanSeek) PURE;
375     STDMETHOD(get_CanSeekToMarkers)(VARIANT_BOOL __RPC_FAR *pCanSeekToMarkers) PURE;
376     STDMETHOD(get_CurrentMarker)(long __RPC_FAR *pCurrentMarker) PURE;
377     STDMETHOD(put_CurrentMarker)(long pCurrentMarker) PURE;
378     STDMETHOD(get_FileName)(BSTR __RPC_FAR *pbstrFileName) PURE;
379     STDMETHOD(put_FileName)(BSTR pbstrFileName) PURE;
380     STDMETHOD(get_SourceLink)(BSTR __RPC_FAR *pbstrSourceLink) PURE;
381     STDMETHOD(get_CreationDate)(DATE __RPC_FAR *pCreationDate) PURE;
382     STDMETHOD(get_ErrorCorrection)(BSTR __RPC_FAR *pbstrErrorCorrection) PURE;
383     STDMETHOD(get_Bandwidth)(long __RPC_FAR *pBandwidth) PURE;
384     STDMETHOD(get_SourceProtocol)(long __RPC_FAR *pSourceProtocol) PURE;
385     STDMETHOD(get_ReceivedPackets)(long __RPC_FAR *pReceivedPackets) PURE;
386     STDMETHOD(get_RecoveredPackets)(long __RPC_FAR *pRecoveredPackets) PURE;
387     STDMETHOD(get_LostPackets)(long __RPC_FAR *pLostPackets) PURE;
388     STDMETHOD(get_ReceptionQuality)(long __RPC_FAR *pReceptionQuality) PURE;
389     STDMETHOD(get_BufferingCount)(long __RPC_FAR *pBufferingCount) PURE;
390     STDMETHOD(get_IsBroadcast)(VARIANT_BOOL __RPC_FAR *pIsBroadcast) PURE;
391     STDMETHOD(get_BufferingProgress)(long __RPC_FAR *pBufferingProgress) PURE;
392     STDMETHOD(get_ChannelName)(BSTR __RPC_FAR *pbstrChannelName) PURE;
393     STDMETHOD(get_ChannelDescription)(BSTR __RPC_FAR *pbstrChannelDescription) PURE;
394     STDMETHOD(get_ChannelURL)(BSTR __RPC_FAR *pbstrChannelURL) PURE;
395     STDMETHOD(get_ContactAddress)(BSTR __RPC_FAR *pbstrContactAddress) PURE;
396     STDMETHOD(get_ContactPhone)(BSTR __RPC_FAR *pbstrContactPhone) PURE;
397     STDMETHOD(get_ContactEmail)(BSTR __RPC_FAR *pbstrContactEmail) PURE;
398     STDMETHOD(get_BufferingTime)(double __RPC_FAR *pBufferingTime) PURE;
399     STDMETHOD(put_BufferingTime)(double pBufferingTime) PURE;
400     STDMETHOD(get_AutoStart)(VARIANT_BOOL __RPC_FAR *pAutoStart) PURE;
401     STDMETHOD(put_AutoStart)(VARIANT_BOOL pAutoStart) PURE;
402     STDMETHOD(get_AutoRewind)(VARIANT_BOOL __RPC_FAR *pAutoRewind) PURE;
403     STDMETHOD(put_AutoRewind)(VARIANT_BOOL pAutoRewind) PURE;
404     STDMETHOD(get_Rate)(double __RPC_FAR *pRate) PURE;
405     STDMETHOD(put_Rate)(double pRate) PURE;
406     STDMETHOD(get_SendKeyboardEvents)(VARIANT_BOOL __RPC_FAR *pSendKeyboardEvents) PURE;
407     STDMETHOD(put_SendKeyboardEvents)(VARIANT_BOOL pSendKeyboardEvents) PURE;
408     STDMETHOD(get_SendMouseClickEvents)(VARIANT_BOOL __RPC_FAR *pSendMouseClickEvents) PURE;
409     STDMETHOD(put_SendMouseClickEvents)(VARIANT_BOOL pSendMouseClickEvents) PURE;
410     STDMETHOD(get_SendMouseMoveEvents)(VARIANT_BOOL __RPC_FAR *pSendMouseMoveEvents) PURE;
411     STDMETHOD(put_SendMouseMoveEvents)(VARIANT_BOOL pSendMouseMoveEvents) PURE;
412     STDMETHOD(get_PlayCount)(long __RPC_FAR *pPlayCount) PURE;
413     STDMETHOD(put_PlayCount)(long pPlayCount) PURE;
414     STDMETHOD(get_ClickToPlay)(VARIANT_BOOL __RPC_FAR *pClickToPlay) PURE;
415     STDMETHOD(put_ClickToPlay)(VARIANT_BOOL pClickToPlay) PURE;
416     STDMETHOD(get_AllowScan)(VARIANT_BOOL __RPC_FAR *pAllowScan) PURE;
417     STDMETHOD(put_AllowScan)(VARIANT_BOOL pAllowScan) PURE;
418     STDMETHOD(get_EnableContextMenu)(VARIANT_BOOL __RPC_FAR *pEnableContextMenu) PURE;
419     STDMETHOD(put_EnableContextMenu)(VARIANT_BOOL pEnableContextMenu) PURE;
420     STDMETHOD(get_CursorType)(long __RPC_FAR *pCursorType) PURE;
421     STDMETHOD(put_CursorType)(long pCursorType) PURE;
422     STDMETHOD(get_CodecCount)(long __RPC_FAR *pCodecCount) PURE;
423     STDMETHOD(get_AllowChangeDisplaySize)(VARIANT_BOOL __RPC_FAR *pAllowChangeDisplaySize) PURE;
424     STDMETHOD(put_AllowChangeDisplaySize)( VARIANT_BOOL pAllowChangeDisplaySize) PURE;
425     STDMETHOD(get_IsDurationValid)(VARIANT_BOOL __RPC_FAR *pIsDurationValid) PURE;
426     STDMETHOD(get_OpenState)(long __RPC_FAR *pOpenState) PURE;
427     STDMETHOD(get_SendOpenStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendOpenStateChangeEvents) PURE;
428     STDMETHOD(put_SendOpenStateChangeEvents)(VARIANT_BOOL pSendOpenStateChangeEvents) PURE;
429     STDMETHOD(get_SendWarningEvents)( VARIANT_BOOL __RPC_FAR *pSendWarningEvents) PURE;
430     STDMETHOD(put_SendWarningEvents)(VARIANT_BOOL pSendWarningEvents) PURE;
431     STDMETHOD(get_SendErrorEvents)(VARIANT_BOOL __RPC_FAR *pSendErrorEvents) PURE;
432     STDMETHOD(put_SendErrorEvents)(VARIANT_BOOL pSendErrorEvents) PURE;
433     STDMETHOD(get_PlayState)(MPPlayStateConstants __RPC_FAR *pPlayState) PURE;
434     STDMETHOD(get_SendPlayStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendPlayStateChangeEvents) PURE;
435     STDMETHOD(put_SendPlayStateChangeEvents)(VARIANT_BOOL pSendPlayStateChangeEvents) PURE;
436     STDMETHOD(get_DisplaySize)(MPDisplaySizeConstants __RPC_FAR *pDisplaySize) PURE;
437     STDMETHOD(put_DisplaySize)(MPDisplaySizeConstants pDisplaySize) PURE;
438     STDMETHOD(get_InvokeURLs)(VARIANT_BOOL __RPC_FAR *pInvokeURLs) PURE;
439     STDMETHOD(put_InvokeURLs)(VARIANT_BOOL pInvokeURLs) PURE;
440     STDMETHOD(get_BaseURL)(BSTR __RPC_FAR *pbstrBaseURL) PURE;
441     STDMETHOD(put_BaseURL)(BSTR pbstrBaseURL) PURE;
442     STDMETHOD(get_DefaultFrame)(BSTR __RPC_FAR *pbstrDefaultFrame) PURE;
443     STDMETHOD(put_DefaultFrame)(BSTR pbstrDefaultFrame) PURE;
444     STDMETHOD(get_HasError)(VARIANT_BOOL __RPC_FAR *pHasError) PURE;
445     STDMETHOD(get_ErrorDescription)(BSTR __RPC_FAR *pbstrErrorDescription) PURE;
446     STDMETHOD(get_ErrorCode)(long __RPC_FAR *pErrorCode) PURE;
447     STDMETHOD(get_AnimationAtStart)(VARIANT_BOOL __RPC_FAR *pAnimationAtStart) PURE;
448     STDMETHOD(put_AnimationAtStart)(VARIANT_BOOL pAnimationAtStart) PURE;
449     STDMETHOD(get_TransparentAtStart)( VARIANT_BOOL __RPC_FAR *pTransparentAtStart) PURE;
450     STDMETHOD(put_TransparentAtStart)(VARIANT_BOOL pTransparentAtStart) PURE;
451     STDMETHOD(get_Volume)(long __RPC_FAR *pVolume) PURE;
452     STDMETHOD(put_Volume)(long pVolume) PURE;
453     STDMETHOD(get_Balance)(long __RPC_FAR *pBalance) PURE;
454     STDMETHOD(put_Balance)(long pBalance) PURE;
455     STDMETHOD(get_ReadyState)(MPReadyStateConstants __RPC_FAR *pValue) PURE;
456     STDMETHOD(get_SelectionStart)(double __RPC_FAR *pValue) PURE;
457     STDMETHOD(put_SelectionStart)(double pValue) PURE;
458     STDMETHOD(get_SelectionEnd)(double __RPC_FAR *pValue) PURE;
459     STDMETHOD(put_SelectionEnd)(double pValue) PURE;
460     STDMETHOD(get_ShowDisplay)(VARIANT_BOOL __RPC_FAR *Show) PURE;
461     STDMETHOD(put_ShowDisplay)(VARIANT_BOOL Show) PURE;
462     STDMETHOD(get_ShowControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
463     STDMETHOD(put_ShowControls)(VARIANT_BOOL Show) PURE;
464     STDMETHOD(get_ShowPositionControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
465     STDMETHOD(put_ShowPositionControls)(VARIANT_BOOL Show) PURE;
466     STDMETHOD(get_ShowTracker)(VARIANT_BOOL __RPC_FAR *Show) PURE;
467     STDMETHOD(put_ShowTracker)(VARIANT_BOOL Show) PURE;
468     STDMETHOD(get_EnablePositionControls)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
469     STDMETHOD(put_EnablePositionControls)(VARIANT_BOOL Enable) PURE;
470     STDMETHOD(get_EnableTracker)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
471     STDMETHOD(put_EnableTracker)(VARIANT_BOOL Enable) PURE;
472     STDMETHOD(get_Enabled)(VARIANT_BOOL __RPC_FAR *pEnabled) PURE;
473     STDMETHOD(put_Enabled)(VARIANT_BOOL pEnabled) PURE;
474     STDMETHOD(get_DisplayForeColor)(VB_OLE_COLOR __RPC_FAR *ForeColor) PURE;
475     STDMETHOD(put_DisplayForeColor)(VB_OLE_COLOR ForeColor) PURE;
476     STDMETHOD(get_DisplayBackColor)(VB_OLE_COLOR __RPC_FAR *BackColor) PURE;
477     STDMETHOD(put_DisplayBackColor)(VB_OLE_COLOR BackColor) PURE;
478     STDMETHOD(get_DisplayMode)(MPDisplayModeConstants __RPC_FAR *pValue) PURE;
479     STDMETHOD(put_DisplayMode)(MPDisplayModeConstants pValue) PURE;
480     STDMETHOD(get_VideoBorder3D)(VARIANT_BOOL __RPC_FAR *pVideoBorderWidth) PURE;
481     STDMETHOD(put_VideoBorder3D)(VARIANT_BOOL pVideoBorderWidth) PURE;
482     STDMETHOD(get_VideoBorderWidth)(long __RPC_FAR *pVideoBorderWidth) PURE;
483     STDMETHOD(put_VideoBorderWidth)(long pVideoBorderWidth) PURE;
484     STDMETHOD(get_VideoBorderColor)(VB_OLE_COLOR __RPC_FAR *pVideoBorderWidth) PURE;
485     STDMETHOD(put_VideoBorderColor)(VB_OLE_COLOR pVideoBorderWidth) PURE;
486     STDMETHOD(get_ShowGotoBar)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
487     STDMETHOD(put_ShowGotoBar)(VARIANT_BOOL pbool) PURE;
488     STDMETHOD(get_ShowStatusBar)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
489     STDMETHOD(put_ShowStatusBar)(VARIANT_BOOL pbool) PURE;
490     STDMETHOD(get_ShowCaptioning)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
491     STDMETHOD(put_ShowCaptioning)(VARIANT_BOOL pbool) PURE;
492     STDMETHOD(get_ShowAudioControls)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
493     STDMETHOD(put_ShowAudioControls)(VARIANT_BOOL pbool) PURE;
494     STDMETHOD(get_CaptioningID)( BSTR __RPC_FAR *pstrText) PURE;
495     STDMETHOD(put_CaptioningID)(BSTR pstrText) PURE;
496     STDMETHOD(get_Mute)(VARIANT_BOOL __RPC_FAR *vbool) PURE;
497     STDMETHOD(put_Mute)(VARIANT_BOOL vbool) PURE;
498     STDMETHOD(get_CanPreview)(VARIANT_BOOL __RPC_FAR *pCanPreview) PURE;
499     STDMETHOD(get_PreviewMode)(VARIANT_BOOL __RPC_FAR *pPreviewMode) PURE;
500     STDMETHOD(put_PreviewMode)(VARIANT_BOOL pPreviewMode) PURE;
501     STDMETHOD(get_HasMultipleItems)(VARIANT_BOOL __RPC_FAR *pHasMuliItems) PURE;
502     STDMETHOD(get_Language)(long __RPC_FAR *pLanguage) PURE;
503     STDMETHOD(put_Language)(long pLanguage) PURE;
504     STDMETHOD(get_AudioStream)(long __RPC_FAR *pStream) PURE;
505     STDMETHOD(put_AudioStream)(long pStream) PURE;
506     STDMETHOD(get_SAMIStyle)(BSTR __RPC_FAR *pbstrStyle) PURE;
507     STDMETHOD(put_SAMIStyle)(BSTR pbstrStyle) PURE;
508     STDMETHOD(get_SAMILang)(BSTR __RPC_FAR *pbstrLang) PURE;
509     STDMETHOD(put_SAMILang)(BSTR pbstrLang) PURE;
510     STDMETHOD(get_SAMIFileName)(BSTR __RPC_FAR *pbstrFileName) PURE;
511     STDMETHOD(put_SAMIFileName)(BSTR pbstrFileName) PURE;
512     STDMETHOD(get_StreamCount)( long __RPC_FAR *pStreamCount) PURE;
513     STDMETHOD(get_ClientId)(BSTR __RPC_FAR *pbstrClientId) PURE;
514     STDMETHOD(get_ConnectionSpeed)(long __RPC_FAR *plConnectionSpeed) PURE;
515     STDMETHOD(get_AutoSize)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
516     STDMETHOD(put_AutoSize)(VARIANT_BOOL pbool) PURE;
517     STDMETHOD(get_EnableFullScreenControls)(VARIANT_BOOL __RPC_FAR *pbVal) PURE;
518     STDMETHOD(put_EnableFullScreenControls)(VARIANT_BOOL pbVal) PURE;
519     STDMETHOD(get_ActiveMovie)(IDispatch __RPC_FAR *__RPC_FAR *ppdispatch) PURE;
520     STDMETHOD(get_NSPlay)(IDispatch __RPC_FAR *__RPC_FAR *ppdispatch) PURE;
521     STDMETHOD(get_WindowlessVideo)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
522     STDMETHOD(put_WindowlessVideo)(VARIANT_BOOL pbool) PURE;
523     STDMETHOD(Play)(void) PURE;
524     STDMETHOD(Stop)(void) PURE;
525     STDMETHOD(Pause)(void) PURE;
526     STDMETHOD(GetMarkerTime)(long MarkerNum,
527                              double __RPC_FAR *pMarkerTime) PURE;
528     STDMETHOD(GetMarkerName)(long MarkerNum,
529                              BSTR __RPC_FAR *pbstrMarkerName) PURE;
530     STDMETHOD(AboutBox)(void) PURE;
531     STDMETHOD(GetCodecInstalled)(long CodecNum,
532                               VARIANT_BOOL __RPC_FAR *pCodecInstalled) PURE;
533     STDMETHOD(GetCodecDescription)(long CodecNum,
534                                  BSTR __RPC_FAR *pbstrCodecDescription) PURE;
535     STDMETHOD(GetCodecURL)(long CodecNum,
536                            BSTR __RPC_FAR *pbstrCodecURL) PURE;
537     STDMETHOD(GetMoreInfoURL)(MPMoreInfoType MoreInfoType,
538                               BSTR __RPC_FAR *pbstrMoreInfoURL) PURE;
539     STDMETHOD(GetMediaInfoString)(MPMediaInfoType MediaInfoType,
540                                   BSTR __RPC_FAR *pbstrMediaInfo) PURE;
541     STDMETHOD(Cancel)(void) PURE;
542     STDMETHOD(Open)(BSTR bstrFileName) PURE;
543     STDMETHOD(IsSoundCardEnabled)(VARIANT_BOOL __RPC_FAR *pbSoundCard) PURE;
544     STDMETHOD(Next)(void) PURE;
545     STDMETHOD(Previous)(void) PURE;
546     STDMETHOD(StreamSelect)(long StreamNum) PURE;
547     STDMETHOD(FastForward)(void) PURE;
548     STDMETHOD(FastReverse)(void) PURE;
549     STDMETHOD(GetStreamName)(long StreamNum,
550                              BSTR __RPC_FAR *pbstrStreamName) PURE;
551     STDMETHOD(GetStreamGroup)(long StreamNum,
552                               long __RPC_FAR *pStreamGroup) PURE;
553     STDMETHOD(GetStreamSelected)(long StreamNum, VARIANT_BOOL __RPC_FAR *pStreamSelected) PURE;
554 };
555 
556 struct IMediaPlayer2 : public IMediaPlayer
557 {
558     STDMETHOD(get_DVD)(struct IMediaPlayerDvd __RPC_FAR *__RPC_FAR *ppdispatch) PURE;
559     STDMETHOD(GetMediaParameter)(long EntryNum, BSTR bstrParameterName, BSTR __RPC_FAR *pbstrParameterValue) PURE;
560     STDMETHOD(GetMediaParameterName)(long EntryNum, long Index, BSTR __RPC_FAR *pbstrParameterName) PURE;
561     STDMETHOD(get_EntryCount)(long __RPC_FAR *pNumberEntries) PURE;
562     STDMETHOD(GetCurrentEntry)(long __RPC_FAR *pEntryNumber) PURE;
563     STDMETHOD(SetCurrentEntry)(long EntryNumber) PURE;
564     STDMETHOD(ShowDialog)(MPShowDialogConstants mpDialogIndex) PURE;
565 };
566 
567 //---------------------------------------------------------------------------
568 //  NETSHOW COM INTERFACES (dumped from nscompat.idl from MSVC COM Browser)
569 //---------------------------------------------------------------------------
570 
571 struct INSOPlay : public IDispatch
572 {
573     STDMETHOD(get_ImageSourceWidth)(long __RPC_FAR *pWidth) PURE;
574     STDMETHOD(get_ImageSourceHeight)(long __RPC_FAR *pHeight) PURE;
575     STDMETHOD(get_Duration)(double __RPC_FAR *pDuration) PURE;
576     STDMETHOD(get_Author)(BSTR __RPC_FAR *pbstrAuthor) PURE;
577     STDMETHOD(get_Copyright)(BSTR __RPC_FAR *pbstrCopyright) PURE;
578     STDMETHOD(get_Description)(BSTR __RPC_FAR *pbstrDescription) PURE;
579     STDMETHOD(get_Rating)(BSTR __RPC_FAR *pbstrRating) PURE;
580     STDMETHOD(get_Title)(BSTR __RPC_FAR *pbstrTitle) PURE;
581     STDMETHOD(get_SourceLink)(BSTR __RPC_FAR *pbstrSourceLink) PURE;
582     STDMETHOD(get_MarkerCount)(long __RPC_FAR *pMarkerCount) PURE;
583     STDMETHOD(get_CanScan)(VARIANT_BOOL __RPC_FAR *pCanScan) PURE;
584     STDMETHOD(get_CanSeek)(VARIANT_BOOL __RPC_FAR *pCanSeek) PURE;
585     STDMETHOD(get_CanSeekToMarkers)(VARIANT_BOOL __RPC_FAR *pCanSeekToMarkers) PURE;
586     STDMETHOD(get_CreationDate)(DATE __RPC_FAR *pCreationDate) PURE;
587     STDMETHOD(get_Bandwidth)(long __RPC_FAR *pBandwidth) PURE;
588     STDMETHOD(get_ErrorCorrection)(BSTR __RPC_FAR *pbstrErrorCorrection) PURE;
589     STDMETHOD(get_AutoStart)(VARIANT_BOOL __RPC_FAR *pAutoStart) PURE;
590     STDMETHOD(put_AutoStart)(VARIANT_BOOL pAutoStart) PURE;
591     STDMETHOD(get_AutoRewind)(VARIANT_BOOL __RPC_FAR *pAutoRewind) PURE;
592     STDMETHOD(put_AutoRewind)(VARIANT_BOOL pAutoRewind) PURE;
593     STDMETHOD(get_AllowChangeControlType)(VARIANT_BOOL __RPC_FAR *pAllowChangeControlType) PURE;
594     STDMETHOD(put_AllowChangeControlType)(VARIANT_BOOL pAllowChangeControlType) PURE;
595     STDMETHOD(get_InvokeURLs)(VARIANT_BOOL __RPC_FAR *pInvokeURLs) PURE;
596     STDMETHOD(put_InvokeURLs)(VARIANT_BOOL pInvokeURLs) PURE;
597     STDMETHOD(get_EnableContextMenu)(VARIANT_BOOL __RPC_FAR *pEnableContextMenu) PURE;
598     STDMETHOD(put_EnableContextMenu)(VARIANT_BOOL pEnableContextMenu) PURE;
599     STDMETHOD(get_TransparentAtStart)(VARIANT_BOOL __RPC_FAR *pTransparentAtStart) PURE;
600     STDMETHOD(put_TransparentAtStart)(VARIANT_BOOL pTransparentAtStart) PURE;
601     STDMETHOD(get_TransparentOnStop)(VARIANT_BOOL __RPC_FAR *pTransparentOnStop) PURE;
602     STDMETHOD(put_TransparentOnStop)(VARIANT_BOOL pTransparentOnStop) PURE;
603     STDMETHOD(get_ClickToPlay)(VARIANT_BOOL __RPC_FAR *pClickToPlay) PURE;
604     STDMETHOD(put_ClickToPlay)(VARIANT_BOOL pClickToPlay) PURE;
605     STDMETHOD(get_FileName)(BSTR __RPC_FAR *pbstrFileName) PURE;
606     STDMETHOD(put_FileName)(BSTR pbstrFileName) PURE;
607     STDMETHOD(get_CurrentPosition)(double __RPC_FAR *pCurrentPosition) PURE;
608     STDMETHOD(put_CurrentPosition)(double pCurrentPosition) PURE;
609     STDMETHOD(get_Rate)(double __RPC_FAR *pRate) PURE;
610     STDMETHOD(put_Rate)(double pRate) PURE;
611     STDMETHOD(get_CurrentMarker)(long __RPC_FAR *pCurrentMarker) PURE;
612     STDMETHOD(put_CurrentMarker)(long pCurrentMarker) PURE;
613     STDMETHOD(get_PlayCount)(long __RPC_FAR *pPlayCount) PURE;
614     STDMETHOD(put_PlayCount)(long pPlayCount) PURE;
615     STDMETHOD(get_CurrentState)(long __RPC_FAR *pCurrentState) PURE;
616     STDMETHOD(get_DisplaySize)(long __RPC_FAR *pDisplaySize) PURE;
617     STDMETHOD(put_DisplaySize)(long pDisplaySize) PURE;
618     STDMETHOD(get_MainWindow)(long __RPC_FAR *pMainWindow) PURE;
619     STDMETHOD(get_ControlType)(long __RPC_FAR *pControlType) PURE;
620     STDMETHOD(put_ControlType)(long pControlType) PURE;
621     STDMETHOD(get_AllowScan)(VARIANT_BOOL __RPC_FAR *pAllowScan) PURE;
622     STDMETHOD(put_AllowScan)(VARIANT_BOOL pAllowScan) PURE;
623     STDMETHOD(get_SendKeyboardEvents)(VARIANT_BOOL __RPC_FAR *pSendKeyboardEvents) PURE;
624     STDMETHOD(put_SendKeyboardEvents)(VARIANT_BOOL pSendKeyboardEvents) PURE;
625     STDMETHOD(get_SendMouseClickEvents)(VARIANT_BOOL __RPC_FAR *pSendMouseClickEvents) PURE;
626     STDMETHOD(put_SendMouseClickEvents)(VARIANT_BOOL pSendMouseClickEvents) PURE;
627     STDMETHOD(get_SendMouseMoveEvents)(VARIANT_BOOL __RPC_FAR *pSendMouseMoveEvents) PURE;
628     STDMETHOD(put_SendMouseMoveEvents)(VARIANT_BOOL pSendMouseMoveEvents) PURE;
629     STDMETHOD(get_SendStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendStateChangeEvents) PURE;
630     STDMETHOD(put_SendStateChangeEvents)(VARIANT_BOOL pSendStateChangeEvents) PURE;
631     STDMETHOD(get_ReceivedPackets)(long __RPC_FAR *pReceivedPackets) PURE;
632     STDMETHOD(get_RecoveredPackets)(long __RPC_FAR *pRecoveredPackets) PURE;
633     STDMETHOD(get_LostPackets)(long __RPC_FAR *pLostPackets) PURE;
634     STDMETHOD(get_ReceptionQuality)(long __RPC_FAR *pReceptionQuality) PURE;
635     STDMETHOD(get_BufferingCount)(long __RPC_FAR *pBufferingCount) PURE;
636     STDMETHOD(get_CursorType)(long __RPC_FAR *pCursorType) PURE;
637     STDMETHOD(put_CursorType)(long pCursorType) PURE;
638     STDMETHOD(get_AnimationAtStart)(VARIANT_BOOL __RPC_FAR *pAnimationAtStart) PURE;
639     STDMETHOD(put_AnimationAtStart)(VARIANT_BOOL pAnimationAtStart) PURE;
640     STDMETHOD(get_AnimationOnStop)(VARIANT_BOOL __RPC_FAR *pAnimationOnStop) PURE;
641     STDMETHOD(put_AnimationOnStop)(VARIANT_BOOL pAnimationOnStop) PURE;
642     STDMETHOD(Play)(void) PURE;
643     STDMETHOD(Pause)(void) PURE;
644     STDMETHOD(Stop)(void) PURE;
645     STDMETHOD(GetMarkerTime)(long MarkerNum, double __RPC_FAR *pMarkerTime) PURE;
646     STDMETHOD(GetMarkerName)(long MarkerNum, BSTR __RPC_FAR *pbstrMarkerName) PURE;
647 };
648 
649 struct INSPlay : public INSOPlay
650 {
651     STDMETHOD(get_ChannelName)(BSTR __RPC_FAR *pbstrChannelName) PURE;
652     STDMETHOD(get_ChannelDescription)(BSTR __RPC_FAR *pbstrChannelDescription) PURE;
653     STDMETHOD(get_ChannelURL)(BSTR __RPC_FAR *pbstrChannelURL) PURE;
654     STDMETHOD(get_ContactAddress)(BSTR __RPC_FAR *pbstrContactAddress) PURE;
655     STDMETHOD(get_ContactPhone)(BSTR __RPC_FAR *pbstrContactPhone) PURE;
656     STDMETHOD(get_ContactEmail)(BSTR __RPC_FAR *pbstrContactEmail) PURE;
657     STDMETHOD(get_AllowChangeDisplaySize)(VARIANT_BOOL __RPC_FAR *pAllowChangeDisplaySize) PURE;
658     STDMETHOD(put_AllowChangeDisplaySize)(VARIANT_BOOL pAllowChangeDisplaySize) PURE;
659     STDMETHOD(get_CodecCount)(long __RPC_FAR *pCodecCount) PURE;
660     STDMETHOD(get_IsBroadcast)(VARIANT_BOOL __RPC_FAR *pIsBroadcast) PURE;
661     STDMETHOD(get_IsDurationValid)(VARIANT_BOOL __RPC_FAR *pIsDurationValid) PURE;
662     STDMETHOD(get_SourceProtocol)(long __RPC_FAR *pSourceProtocol) PURE;
663     STDMETHOD(get_OpenState)(long __RPC_FAR *pOpenState) PURE;
664     STDMETHOD(get_SendOpenStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendOpenStateChangeEvents) PURE;
665     STDMETHOD(put_SendOpenStateChangeEvents)(VARIANT_BOOL pSendOpenStateChangeEvents) PURE;
666     STDMETHOD(get_SendWarningEvents)(VARIANT_BOOL __RPC_FAR *pSendWarningEvents) PURE;
667     STDMETHOD(put_SendWarningEvents)(VARIANT_BOOL pSendWarningEvents) PURE;
668     STDMETHOD(get_SendErrorEvents)(VARIANT_BOOL __RPC_FAR *pSendErrorEvents) PURE;
669     STDMETHOD(put_SendErrorEvents)(VARIANT_BOOL pSendErrorEvents) PURE;
670     STDMETHOD(get_HasError)(VARIANT_BOOL __RPC_FAR *pHasError) PURE;
671     STDMETHOD(get_ErrorDescription)(BSTR __RPC_FAR *pbstrErrorDescription) PURE;
672     STDMETHOD(get_ErrorCode)(long __RPC_FAR *pErrorCode) PURE;
673     STDMETHOD(get_PlayState)(long __RPC_FAR *pPlayState) PURE;
674     STDMETHOD(get_SendPlayStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendPlayStateChangeEvents) PURE;
675     STDMETHOD(put_SendPlayStateChangeEvents)(VARIANT_BOOL pSendPlayStateChangeEvents) PURE;
676     STDMETHOD(get_BufferingTime)(double __RPC_FAR *pBufferingTime) PURE;
677     STDMETHOD(put_BufferingTime)(double pBufferingTime) PURE;
678     STDMETHOD(get_UseFixedUDPPort)(VARIANT_BOOL __RPC_FAR *pUseFixedUDPPort) PURE;
679     STDMETHOD(put_UseFixedUDPPort)(VARIANT_BOOL pUseFixedUDPPort) PURE;
680     STDMETHOD(get_FixedUDPPort)(long __RPC_FAR *pFixedUDPPort) PURE;
681     STDMETHOD(put_FixedUDPPort)(long pFixedUDPPort) PURE;
682     STDMETHOD(get_UseHTTPProxy)(VARIANT_BOOL __RPC_FAR *pUseHTTPProxy) PURE;
683     STDMETHOD(put_UseHTTPProxy)(VARIANT_BOOL pUseHTTPProxy) PURE;
684     STDMETHOD(get_EnableAutoProxy)(VARIANT_BOOL __RPC_FAR *pEnableAutoProxy) PURE;
685     STDMETHOD(put_EnableAutoProxy)(VARIANT_BOOL pEnableAutoProxy) PURE;
686     STDMETHOD(get_HTTPProxyHost)(BSTR __RPC_FAR *pbstrHTTPProxyHost) PURE;
687     STDMETHOD(put_HTTPProxyHost)(BSTR pbstrHTTPProxyHost) PURE;
688     STDMETHOD(get_HTTPProxyPort)(long __RPC_FAR *pHTTPProxyPort) PURE;
689     STDMETHOD(put_HTTPProxyPort)(long pHTTPProxyPort) PURE;
690     STDMETHOD(get_EnableMulticast)(VARIANT_BOOL __RPC_FAR *pEnableMulticast) PURE;
691     STDMETHOD(put_EnableMulticast)(VARIANT_BOOL pEnableMulticast) PURE;
692     STDMETHOD(get_EnableUDP)(VARIANT_BOOL __RPC_FAR *pEnableUDP) PURE;
693     STDMETHOD(put_EnableUDP)(VARIANT_BOOL pEnableUDP) PURE;
694     STDMETHOD(get_EnableTCP)(VARIANT_BOOL __RPC_FAR *pEnableTCP) PURE;
695     STDMETHOD(put_EnableTCP)(VARIANT_BOOL pEnableTCP) PURE;
696     STDMETHOD(get_EnableHTTP)(VARIANT_BOOL __RPC_FAR *pEnableHTTP) PURE;
697     STDMETHOD(put_EnableHTTP)(VARIANT_BOOL pEnableHTTP) PURE;
698     STDMETHOD(get_BufferingProgress)(long __RPC_FAR *pBufferingProgress) PURE;
699     STDMETHOD(get_BaseURL)(BSTR __RPC_FAR *pbstrBaseURL) PURE;
700     STDMETHOD(put_BaseURL)(BSTR pbstrBaseURL) PURE;
701     STDMETHOD(get_DefaultFrame)(BSTR __RPC_FAR *pbstrDefaultFrame) PURE;
702     STDMETHOD(put_DefaultFrame)(BSTR pbstrDefaultFrame) PURE;
703     STDMETHOD(AboutBox)(void) PURE;
704     STDMETHOD(Cancel)(void) PURE;
705     STDMETHOD(GetCodecInstalled)(long CodecNum, VARIANT_BOOL __RPC_FAR *pCodecInstalled) PURE;
706     STDMETHOD(GetCodecDescription)(long CodecNum, BSTR __RPC_FAR *pbstrCodecDescription) PURE;
707     STDMETHOD(GetCodecURL)(long CodecNum, BSTR __RPC_FAR *pbstrCodecURL) PURE;
708     STDMETHOD(Open)(BSTR bstrFileName) PURE;
709 };
710 
711 
712 struct INSPlay1 : public INSPlay
713 {
714     STDMETHOD(get_MediaPlayer)(IDispatch __RPC_FAR *__RPC_FAR *ppdispatch) PURE;
715 };
716 
717 //---------------------------------------------------------------------------
718 // MISC COM INTERFACES
719 //---------------------------------------------------------------------------
720 typedef enum _FilterState
721 {
722     State_Stopped,
723     State_Paused,
724     State_Running
725 } FILTER_STATE;
726 typedef enum _PinDirection {
727     PINDIR_INPUT,
728     PINDIR_OUTPUT
729 } PIN_DIRECTION;
730 
731 typedef struct _FilterInfo {
732     WCHAR        achName[128];
733     struct IFilterGraph *pGraph;
734 } FILTER_INFO;
735 
736 typedef struct _PinInfo {
737     struct IBaseFilter *pFilter;
738     PIN_DIRECTION dir;
739     WCHAR achName[128];
740 } PIN_INFO;
741 
742 struct IBaseFilter;
743 struct IPin;
744 struct IEnumFilters;
745 typedef struct  _MediaType {
746     GUID      majortype;
747     GUID      subtype;
748     BOOL      bFixedSizeSamples;
749     BOOL      bTemporalCompression;
750     ULONG     lSampleSize;
751     GUID      formattype;
752     IUnknown  *pUnk;
753     ULONG     cbFormat;
754     BYTE *pbFormat;
755 } AM_MEDIA_TYPE;
756 
757 struct IFilterGraph : public IUnknown
758 {
759     STDMETHOD(AddFilter)(IBaseFilter *, LPCWSTR) PURE;
760     STDMETHOD(RemoveFilter)(IBaseFilter *) PURE;
761     STDMETHOD(EnumFilters)(IEnumFilters **) PURE;
762     STDMETHOD(FindFilterByName)(LPCWSTR, IBaseFilter **) PURE;
763     STDMETHOD(ConnectDirect)(IPin *, IPin *, const AM_MEDIA_TYPE *) PURE;
764     STDMETHOD(Reconnect)(IPin *) PURE;
765     STDMETHOD(Disconnect)(IPin *) PURE;
766     STDMETHOD(SetDefaultSyncSource)() PURE;
767 };
768 
769 struct IGraphBuilder : public IFilterGraph
770 {
771     STDMETHOD(Connect)(IPin *, IPin *) PURE;
772     STDMETHOD(Render)(IPin *) PURE;
773     STDMETHOD(RenderFile)(LPCWSTR, LPCWSTR) PURE;
774     STDMETHOD(AddSourceFilter)(LPCWSTR, LPCWSTR, IBaseFilter **) PURE;
775     STDMETHOD(SetLogFile)(DWORD_PTR) PURE;
776     STDMETHOD(Abort)() PURE;
777     STDMETHOD(ShouldOperationContinue)() PURE;
778 };
779 
780 struct IReferenceClock;
781 struct IEnumPins;
782 #define REFERENCE_TIME LONGLONG
783 struct IMediaFilter : public IPersist
784 {
785     STDMETHOD(Stop)( void) PURE;
786     STDMETHOD(Pause)( void) PURE;
787     STDMETHOD(Run)(REFERENCE_TIME tStart) PURE;
788     STDMETHOD(GetState)(DWORD dwMilliSecsTimeout,
789                        FILTER_STATE *State) PURE;
790     STDMETHOD(SetSyncSource)(IReferenceClock *pClock) PURE;
791     STDMETHOD(GetSyncSource)(IReferenceClock **pClock) PURE;
792 };
793 
794 struct IBaseFilter : public IMediaFilter
795 {
796     STDMETHOD(EnumPins)(IEnumPins **ppEnum) PURE;
797     STDMETHOD(FindPin)(LPCWSTR Id, IPin **ppPin) PURE;
798     STDMETHOD(QueryFilterInfo)(FILTER_INFO *pInfo) PURE;
799     STDMETHOD(JoinFilterGraph)(IFilterGraph *pGraph, LPCWSTR pName) PURE;
800     STDMETHOD(QueryVendorInfo)(LPWSTR *pVendorInfo) PURE;
801 };
802 
803 
804 //---------------------------------------------------------------------------
805 //
806 //  wxAMMediaBackend
807 //
808 //---------------------------------------------------------------------------
809 
810 typedef BOOL (WINAPI* LPAMGETERRORTEXT)(HRESULT, wxChar *, DWORD);
811 
812 class WXDLLIMPEXP_MEDIA wxAMMediaBackend : public wxMediaBackendCommonBase
813 {
814 public:
815     wxAMMediaBackend();
816     virtual ~wxAMMediaBackend();
817 
818     virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
819                                      wxWindowID id,
820                                      const wxPoint& pos,
821                                      const wxSize& size,
822                                      long style,
823                                      const wxValidator& validator,
824                                      const wxString& name) wxOVERRIDE;
825 
826     virtual bool Play() wxOVERRIDE;
827     virtual bool Pause() wxOVERRIDE;
828     virtual bool Stop() wxOVERRIDE;
829 
830     virtual bool Load(const wxString& fileName) wxOVERRIDE;
831     virtual bool Load(const wxURI& location) wxOVERRIDE;
832     virtual bool Load(const wxURI& location, const wxURI& proxy) wxOVERRIDE;
833 
834     bool DoLoad(const wxString& location);
835     void FinishLoad();
836 
837     virtual wxMediaState GetState() wxOVERRIDE;
838 
839     virtual bool SetPosition(wxLongLong where) wxOVERRIDE;
840     virtual wxLongLong GetPosition() wxOVERRIDE;
841     virtual wxLongLong GetDuration() wxOVERRIDE;
842 
843     virtual void Move(int x, int y, int w, int h) wxOVERRIDE;
844     wxSize GetVideoSize() const wxOVERRIDE;
845 
846     virtual double GetPlaybackRate() wxOVERRIDE;
847     virtual bool SetPlaybackRate(double) wxOVERRIDE;
848 
849     virtual double GetVolume() wxOVERRIDE;
850     virtual bool SetVolume(double) wxOVERRIDE;
851 
852     virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags) wxOVERRIDE;
853 
854     void DoGetDownloadProgress(wxLongLong*, wxLongLong*);
GetDownloadProgress()855     virtual wxLongLong GetDownloadProgress() wxOVERRIDE
856     {
857         wxLongLong progress, total;
858         DoGetDownloadProgress(&progress, &total);
859         return progress;
860     }
GetDownloadTotal()861     virtual wxLongLong GetDownloadTotal() wxOVERRIDE
862     {
863         wxLongLong progress, total;
864         DoGetDownloadProgress(&progress, &total);
865         return total;
866     }
867 
868     wxActiveXContainer* m_pAX;   // ActiveX host
869     IActiveMovie* m_pAM;
870     IMediaPlayer* m_pMP;
871 
GetMP()872     IMediaPlayer* GetMP() {return m_pMP;}
GetAM()873     IActiveMovie* GetAM() {return m_pAM;}
874     wxSize m_bestSize;  // Cached size
875 
876     // Stuff for getting useful debugging strings
877 #if wxDEBUG_LEVEL
878     wxDynamicLibrary m_dllQuartz;
879     LPAMGETERRORTEXT m_lpAMGetErrorText;
880     wxString GetErrorString(HRESULT hrdsv);
881 #endif // wxDEBUG_LEVEL
882     wxEvtHandler* m_evthandler;
883 
884     friend class wxAMMediaEvtHandler;
885     wxDECLARE_DYNAMIC_CLASS(wxAMMediaBackend);
886 };
887 
888 class WXDLLIMPEXP_MEDIA wxAMMediaEvtHandler : public wxEvtHandler
889 {
890 public:
wxAMMediaEvtHandler(wxAMMediaBackend * amb)891     wxAMMediaEvtHandler(wxAMMediaBackend *amb) :
892        m_amb(amb), m_bLoadEventSent(false)
893     {
894         m_amb->m_pAX->Bind(
895             wxEVT_ACTIVEX,
896             &wxAMMediaEvtHandler::OnActiveX, this,
897             m_amb->m_pAX->GetId()
898                               );
899     }
900 
901     void OnActiveX(wxActiveXEvent& event);
902 
903 private:
904     wxAMMediaBackend *m_amb;
905     bool m_bLoadEventSent; // Whether or not FinishLoaded was already called
906                            // prevents it being called multiple times
907 
908     wxDECLARE_NO_COPY_CLASS(wxAMMediaEvtHandler);
909 };
910 
911 //===========================================================================
912 //  IMPLEMENTATION
913 //===========================================================================
914 
915 //---------------------------------------------------------------------------
916 //
917 // wxAMMediaBackend
918 //
919 //---------------------------------------------------------------------------
920 
921 wxIMPLEMENT_DYNAMIC_CLASS(wxAMMediaBackend, wxMediaBackend);
922 
923 //---------------------------------------------------------------------------
924 // Usual debugging macros
925 //---------------------------------------------------------------------------
926 #if wxDEBUG_LEVEL
927 #define MAX_ERROR_TEXT_LEN 160
928 
929 // Get the error string for Active Movie
GetErrorString(HRESULT hrdsv)930 wxString wxAMMediaBackend::GetErrorString(HRESULT hrdsv)
931 {
932     wxChar szError[MAX_ERROR_TEXT_LEN];
933     if( m_lpAMGetErrorText != NULL &&
934        (*m_lpAMGetErrorText)(hrdsv, szError, MAX_ERROR_TEXT_LEN) == 0)
935     {
936         return wxString::Format(wxT("DirectShow error \"%s\" \n")
937                                      wxT("(numeric %X)\n")
938                                      wxT("occurred"),
939                                      szError, (int)hrdsv);
940     }
941     else
942     {
943         return wxString::Format(wxT("Unknown error \n")
944                                      wxT("(numeric %X)\n")
945                                      wxT("occurred"),
946                                      (int)hrdsv);
947     }
948 }
949 
950 #define wxAMFAIL(x) wxFAIL_MSG(GetErrorString(x));
951 #define wxVERIFY(x) wxASSERT((x))
952 #define wxAMLOG(x) wxLogDebug(GetErrorString(x))
953 #else
954 #define wxAMVERIFY(x) (x)
955 #define wxVERIFY(x) (x)
956 #define wxAMLOG(x)
957 #define wxAMFAIL(x)
958 #endif
959 
960 //---------------------------------------------------------------------------
961 // wxAMMediaBackend Constructor
962 //---------------------------------------------------------------------------
wxAMMediaBackend()963 wxAMMediaBackend::wxAMMediaBackend()
964                  :m_pAX(NULL),
965                   m_pAM(NULL),
966                   m_pMP(NULL),
967                   m_bestSize(wxDefaultSize)
968 {
969    m_evthandler = NULL;
970 }
971 
972 //---------------------------------------------------------------------------
973 // wxAMMediaBackend Destructor
974 //---------------------------------------------------------------------------
~wxAMMediaBackend()975 wxAMMediaBackend::~wxAMMediaBackend()
976 {
977     if(m_pAX)
978     {
979         m_pAX->DissociateHandle();
980         delete m_pAX;
981         m_pAM->Release();
982 
983         if (GetMP())
984             GetMP()->Release();
985 
986         if (m_evthandler)
987         {
988             m_ctrl->RemoveEventHandler(m_evthandler);
989             delete m_evthandler;
990         }
991     }
992 }
993 
994 //---------------------------------------------------------------------------
995 // wxAMMediaBackend::CreateControl
996 //---------------------------------------------------------------------------
CreateControl(wxControl * ctrl,wxWindow * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,long style,const wxValidator & validator,const wxString & name)997 bool wxAMMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
998                                      wxWindowID id,
999                                      const wxPoint& pos,
1000                                      const wxSize& size,
1001                                      long style,
1002                                      const wxValidator& validator,
1003                                      const wxString& name)
1004 {
1005     // First get the AMGetErrorText procedure in debug
1006     // mode for more meaningful messages
1007 #if wxDEBUG_LEVEL
1008     if ( m_dllQuartz.Load(wxT("quartz.dll"), wxDL_VERBATIM) )
1009     {
1010         m_lpAMGetErrorText = (LPAMGETERRORTEXT)
1011                                 m_dllQuartz.GetSymbolAorW(wxT("AMGetErrorText"));
1012     }
1013 #endif // wxDEBUG_LEVEL
1014 
1015 
1016 
1017     // Now determine which (if any) media player interface is
1018     // available - IMediaPlayer or IActiveMovie
1019     if( ::CoCreateInstance(CLSID_MediaPlayer, NULL,
1020                                   CLSCTX_INPROC_SERVER,
1021                                   IID_IMediaPlayer, (void**)&m_pMP) != 0 )
1022     {
1023         if( ::CoCreateInstance(CLSID_ActiveMovie, NULL,
1024                                   CLSCTX_INPROC_SERVER,
1025                                   IID_IActiveMovie, (void**)&m_pAM) != 0 )
1026             return false;
1027         m_pAM->QueryInterface(IID_IMediaPlayer, (void**)&m_pMP);
1028     }
1029     else
1030     {
1031         m_pMP->QueryInterface(IID_IActiveMovie, (void**)&m_pAM);
1032     }
1033 
1034     //
1035     // Create window
1036     // By default wxWindow(s) is created with a border -
1037     // so we need to get rid of those
1038     //
1039     // Since we don't have a child window like most other
1040     // backends, we don't need wxCLIP_CHILDREN
1041     //
1042     if ( !ctrl->wxControl::Create(parent, id, pos, size,
1043                             (style & ~wxBORDER_MASK) | wxBORDER_NONE,
1044                             validator, name) )
1045         return false;
1046 
1047     //
1048     // Now create the ActiveX container along with the media player
1049     // interface and query them
1050     //
1051     m_ctrl = wxStaticCast(ctrl, wxMediaCtrl);
1052     m_pAX = new wxActiveXContainer(ctrl,
1053                 m_pMP ? IID_IMediaPlayer : IID_IActiveMovie, m_pAM
1054                                   );
1055     // Connect for events
1056     m_evthandler = new wxAMMediaEvtHandler(this);
1057     m_ctrl->PushEventHandler(m_evthandler);
1058 
1059     //
1060     //  Here we set up wx-specific stuff for the default
1061     //  settings wxMediaCtrl says it will stay to
1062     //
1063     if(GetMP())
1064     {
1065         GetMP()->put_DisplaySize(mpFitToSize);
1066         // TODO: Unsure what actual effect this has
1067         // In DirectShow Windowless video results in less delay when
1068         // dragging, for example - but this doesn't appear to really do anything
1069         // in practice (it may be something different...)...
1070         GetMP()->put_WindowlessVideo(VARIANT_TRUE);
1071 
1072     }
1073     else
1074         GetAM()->put_MovieWindowSize(amvDoubleOriginalSize);
1075 
1076     // by default true
1077     GetAM()->put_AutoStart(VARIANT_FALSE);
1078     // by default enabled
1079     wxAMMediaBackend::ShowPlayerControls(wxMEDIACTRLPLAYERCONTROLS_NONE);
1080     // by default with AM only 0.5
1081     wxAMMediaBackend::SetVolume(1.0);
1082 
1083     // don't erase the background of our control window so that resizing is a
1084     // bit smoother
1085     m_ctrl->SetBackgroundStyle(wxBG_STYLE_PAINT);
1086 
1087     // success
1088     return true;
1089 }
1090 
1091 //---------------------------------------------------------------------------
1092 // wxAMMediaBackend::Load (file version)
1093 //---------------------------------------------------------------------------
Load(const wxString & fileName)1094 bool wxAMMediaBackend::Load(const wxString& fileName)
1095 {
1096     return DoLoad(fileName);
1097 }
1098 
1099 //---------------------------------------------------------------------------
1100 // wxAMMediaBackend::Load (URL Version)
1101 //---------------------------------------------------------------------------
Load(const wxURI & location)1102 bool wxAMMediaBackend::Load(const wxURI& location)
1103 {
1104     //  Turn off loading from a proxy as user
1105     //  may have set it previously
1106     INSPlay* pPlay = NULL;
1107     GetAM()->QueryInterface(IID_INSPlay, (void**) &pPlay);
1108     if(pPlay)
1109     {
1110         pPlay->put_UseHTTPProxy(VARIANT_FALSE);
1111         pPlay->Release();
1112     }
1113 
1114     return DoLoad(location.BuildURI());
1115 }
1116 
1117 //---------------------------------------------------------------------------
1118 // wxAMMediaBackend::Load (URL Version with Proxy)
1119 //---------------------------------------------------------------------------
Load(const wxURI & location,const wxURI & proxy)1120 bool wxAMMediaBackend::Load(const wxURI& location, const wxURI& proxy)
1121 {
1122     // Set the proxy of the NETSHOW interface
1123     INSPlay* pPlay = NULL;
1124     GetAM()->QueryInterface(IID_INSPlay, (void**) &pPlay);
1125 
1126     if(pPlay)
1127     {
1128         pPlay->put_UseHTTPProxy(VARIANT_TRUE);
1129         pPlay->put_HTTPProxyHost(wxBasicString(proxy.GetServer()));
1130         pPlay->put_HTTPProxyPort(wxAtoi(proxy.GetPort()));
1131         pPlay->Release();
1132     }
1133 
1134     return DoLoad(location.BuildURI());
1135 }
1136 
1137 //---------------------------------------------------------------------------
1138 // wxAMMediaBackend::DoLoad
1139 //
1140 // Called by all functions - this actually renders
1141 // the file and sets up the filter graph
1142 //---------------------------------------------------------------------------
DoLoad(const wxString & location)1143 bool wxAMMediaBackend::DoLoad(const wxString& location)
1144 {
1145     HRESULT hr;
1146 
1147     // Play the movie the normal way through the embedded
1148     // WMP.  Supposively Open is better in theory because
1149     // the docs say its async and put_FileName is not -
1150     // but in practice they both seem to be async anyway
1151     if(GetMP())
1152         hr = GetMP()->Open( wxBasicString(location) );
1153     else
1154         hr = GetAM()->put_FileName( wxBasicString(location) );
1155 
1156     if(FAILED(hr))
1157     {
1158         wxAMLOG(hr);
1159         return false;
1160     }
1161 
1162     m_bestSize = wxDefaultSize;
1163     return true;
1164 }
1165 
1166 //---------------------------------------------------------------------------
1167 // wxAMMediaBackend::FinishLoad
1168 //
1169 // Called when the media has finished loaded and is ready to play
1170 //
1171 // Here we get the original size of the video and
1172 // send the loaded event to our watcher :).
1173 //---------------------------------------------------------------------------
FinishLoad()1174 void wxAMMediaBackend::FinishLoad()
1175 {
1176     NotifyMovieLoaded();
1177 }
1178 
1179 //---------------------------------------------------------------------------
1180 // wxAMMediaBackend::ShowPlayerControls
1181 //---------------------------------------------------------------------------
ShowPlayerControls(wxMediaCtrlPlayerControls flags)1182 bool wxAMMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
1183 {
1184     // Note that IMediaPlayer doesn't have a statusbar by
1185     // default but IActiveMovie does - so let's try to keep
1186     // the interface consistent.
1187     if(!flags)
1188     {
1189         GetAM()->put_Enabled(VARIANT_FALSE);
1190         GetAM()->put_ShowControls(VARIANT_FALSE);
1191         if(GetMP())
1192             GetMP()->put_ShowStatusBar(VARIANT_FALSE);
1193     }
1194     else
1195     {
1196         GetAM()->put_Enabled(VARIANT_TRUE);
1197         GetAM()->put_ShowControls(VARIANT_TRUE);
1198 
1199         GetAM()->put_ShowPositionControls(
1200                 (flags & wxMEDIACTRLPLAYERCONTROLS_STEP) ?
1201                 VARIANT_TRUE : VARIANT_FALSE);
1202 
1203         if(GetMP())
1204         {
1205             GetMP()->put_ShowStatusBar(VARIANT_TRUE);
1206             GetMP()->put_ShowAudioControls(
1207                 (flags & wxMEDIACTRLPLAYERCONTROLS_VOLUME) ?
1208                 VARIANT_TRUE : VARIANT_FALSE);
1209         }
1210     }
1211 
1212     return true;
1213 }
1214 
1215 //---------------------------------------------------------------------------
1216 // wxAMMediaBackend::Play
1217 //
1218 // Plays the stream.  If it is non-seekable, it will restart it (implicit).
1219 //
1220 // Note that we use SUCCEEDED here because run/pause/stop tend to be overly
1221 // picky and return warnings on pretty much every call
1222 //---------------------------------------------------------------------------
Play()1223 bool wxAMMediaBackend::Play()
1224 {
1225     // Actually try to play the movie (will fail if not loaded completely)
1226     HRESULT hr = GetAM()->Run();
1227     if(SUCCEEDED(hr))
1228     {
1229        return true;
1230     }
1231     wxAMLOG(hr);
1232     return false;
1233 }
1234 
1235 //---------------------------------------------------------------------------
1236 // wxAMMediaBackend::Pause
1237 //
1238 // Pauses the stream.
1239 //---------------------------------------------------------------------------
Pause()1240 bool wxAMMediaBackend::Pause()
1241 {
1242     HRESULT hr = GetAM()->Pause();
1243     if(SUCCEEDED(hr))
1244         return true;
1245     wxAMLOG(hr);
1246     return false;
1247 }
1248 
1249 //---------------------------------------------------------------------------
1250 // wxAMMediaBackend::Stop
1251 //
1252 // Stops the stream.
1253 //---------------------------------------------------------------------------
Stop()1254 bool wxAMMediaBackend::Stop()
1255 {
1256     HRESULT hr = GetAM()->Stop();
1257     if(SUCCEEDED(hr))
1258     {
1259         // Seek to beginning
1260         wxAMMediaBackend::SetPosition(0);
1261         return true;
1262     }
1263     wxAMLOG(hr);
1264     return false;
1265 }
1266 
1267 //---------------------------------------------------------------------------
1268 // wxAMMediaBackend::SetPosition
1269 //
1270 // 1) Translates the current position's time to directshow time,
1271 //    which is in a scale of 1 second (in a double)
1272 // 2) Sets the play position of the IActiveMovie interface -
1273 //    passing NULL as the stop position means to keep the old
1274 //    stop position
1275 //---------------------------------------------------------------------------
SetPosition(wxLongLong where)1276 bool wxAMMediaBackend::SetPosition(wxLongLong where)
1277 {
1278     HRESULT hr = GetAM()->put_CurrentPosition(
1279                         ((LONGLONG)where.GetValue()) / 1000.0
1280                                      );
1281     if(FAILED(hr))
1282     {
1283         wxAMLOG(hr);
1284         return false;
1285     }
1286 
1287     return true;
1288 }
1289 
1290 //---------------------------------------------------------------------------
1291 // wxAMMediaBackend::GetPosition
1292 //
1293 // 1) Obtains the current play and stop positions from IMediaSeeking
1294 // 2) Returns the play position translated to our time base
1295 //---------------------------------------------------------------------------
GetPosition()1296 wxLongLong wxAMMediaBackend::GetPosition()
1297 {
1298     double outCur;
1299     HRESULT hr = GetAM()->get_CurrentPosition(&outCur);
1300     if(FAILED(hr))
1301     {
1302         wxAMLOG(hr);
1303         return 0;
1304     }
1305 
1306     // h,m,s,milli - outCur is in 1 second (double)
1307     outCur *= 1000;
1308     wxLongLong ll;
1309     ll.Assign(outCur);
1310 
1311     return ll;
1312 }
1313 
1314 //---------------------------------------------------------------------------
1315 // wxAMMediaBackend::GetVolume and SetVolume()
1316 //
1317 // Notice that for the IActiveMovie interface value ranges from 0 (MAX volume)
1318 // to -10000 (minimum volume) and the scale is logarithmic in 0.01db per step.
1319 //---------------------------------------------------------------------------
1320 
GetVolume()1321 double wxAMMediaBackend::GetVolume()
1322 {
1323     long lVolume;
1324     HRESULT hr = GetAM()->get_Volume(&lVolume);
1325     if(FAILED(hr))
1326     {
1327         wxAMLOG(hr);
1328         return 0.0;
1329     }
1330 
1331     double dVolume = lVolume / 2000.; // volume is now in [-5..0] range
1332     dVolume = pow(10.0, dVolume);     //                 [10^-5, 1]
1333     dVolume -= 0.00001;               //                [0, 1-10^-5]
1334     dVolume /= 1 - 0.00001;           //                   [0, 1]
1335 
1336     return dVolume;
1337 }
1338 
SetVolume(double dVolume)1339 bool wxAMMediaBackend::SetVolume(double dVolume)
1340 {
1341     // inverse the transformation above
1342     long lVolume = static_cast<long>(2000*log10(dVolume + (1 - dVolume)*0.00001));
1343 
1344     HRESULT hr = GetAM()->put_Volume(lVolume);
1345     if(FAILED(hr))
1346     {
1347         wxAMLOG(hr);
1348         return false;
1349     }
1350     return true;
1351 }
1352 
1353 //---------------------------------------------------------------------------
1354 // wxAMMediaBackend::GetDuration
1355 //
1356 // 1) Obtains the duration of the media from IActiveMovie
1357 // 2) Converts that value to our time base, and returns it
1358 //
1359 // NB: With VBR MP3 files the default DirectShow MP3 render does not
1360 // read the Xing header correctly, resulting in skewed values for duration
1361 // and seeking
1362 //---------------------------------------------------------------------------
GetDuration()1363 wxLongLong wxAMMediaBackend::GetDuration()
1364 {
1365     double outDuration;
1366     HRESULT hr = GetAM()->get_Duration(&outDuration);
1367     switch ( hr )
1368     {
1369         default:
1370             wxAMLOG(hr);
1371             wxFALLTHROUGH;
1372 
1373         case S_FALSE:
1374             return 0;
1375 
1376         case S_OK:
1377             // outDuration is in seconds, we need milliseconds
1378 #ifdef wxLongLong_t
1379             return static_cast<wxLongLong_t>(outDuration * 1000);
1380 #else
1381             // In principle it's possible to have video of duration greater
1382             // than ~1193 hours which corresponds LONG_MAX in milliseconds so
1383             // cast to wxLongLong first and multiply by 1000 only then to avoid
1384             // the overflow (resulting in maximal duration of ~136 years).
1385             return wxLongLong(static_cast<long>(outDuration)) * 1000;
1386 #endif
1387     }
1388 }
1389 
1390 //---------------------------------------------------------------------------
1391 // wxAMMediaBackend::GetState
1392 //
1393 // Returns the cached state
1394 //---------------------------------------------------------------------------
GetState()1395 wxMediaState wxAMMediaBackend::GetState()
1396 {
1397     StateConstants nState;
1398     HRESULT hr = GetAM()->get_CurrentState(&nState);
1399     if(FAILED(hr))
1400     {
1401         wxAMLOG(hr);
1402         return wxMEDIASTATE_STOPPED;
1403     }
1404 
1405     return (wxMediaState)nState;
1406 }
1407 
1408 //---------------------------------------------------------------------------
1409 // wxAMMediaBackend::GetPlaybackRate
1410 //
1411 // Pretty simple way of obtaining the playback rate from
1412 // the IActiveMovie interface
1413 //---------------------------------------------------------------------------
GetPlaybackRate()1414 double wxAMMediaBackend::GetPlaybackRate()
1415 {
1416     double dRate;
1417     HRESULT hr = GetAM()->get_Rate(&dRate);
1418     if(FAILED(hr))
1419     {
1420         wxAMLOG(hr);
1421         return 0.0;
1422     }
1423     return dRate;
1424 }
1425 
1426 //---------------------------------------------------------------------------
1427 // wxAMMediaBackend::SetPlaybackRate
1428 //
1429 // Sets the playback rate of the media - DirectShow is pretty good
1430 // about this, actually
1431 //---------------------------------------------------------------------------
SetPlaybackRate(double dRate)1432 bool wxAMMediaBackend::SetPlaybackRate(double dRate)
1433 {
1434     HRESULT hr = GetAM()->put_Rate(dRate);
1435     if(FAILED(hr))
1436     {
1437         wxAMLOG(hr);
1438         return false;
1439     }
1440 
1441     return true;
1442 }
1443 
1444 //---------------------------------------------------------------------------
1445 // wxAMMediaBackend::GetDownloadXXX
1446 //
1447 // Queries for and gets the total size of the file and the current
1448 // progress in downloading that file from the IAMOpenProgress
1449 // interface from the media player interface's filter graph
1450 //---------------------------------------------------------------------------
DoGetDownloadProgress(wxLongLong * pLoadProgress,wxLongLong * pLoadTotal)1451 void wxAMMediaBackend::DoGetDownloadProgress(wxLongLong* pLoadProgress,
1452                                              wxLongLong* pLoadTotal)
1453 {
1454     IUnknown* pFG = NULL;
1455 
1456     HRESULT hr = m_pAM->get_FilterGraph(&pFG);
1457 
1458     // notice that the call above may return S_FALSE and leave pFG NULL
1459     if(SUCCEEDED(hr) && pFG)
1460     {
1461         IAMOpenProgress* pOP = NULL;
1462         hr = pFG->QueryInterface(IID_IAMOpenProgress, (void**)&pOP);
1463         if(SUCCEEDED(hr) && pOP)
1464         {
1465             LONGLONG
1466                 loadTotal = 0,
1467                 loadProgress = 0;
1468             hr = pOP->QueryProgress(&loadTotal, &loadProgress);
1469             pOP->Release();
1470 
1471             if(SUCCEEDED(hr))
1472             {
1473                 *pLoadProgress = loadProgress;
1474                 *pLoadTotal = loadTotal;
1475                 pFG->Release();
1476                 return;
1477             }
1478         }
1479         pFG->Release();
1480     }
1481 
1482     *pLoadProgress = 0;
1483     *pLoadTotal = 0;
1484 }
1485 
1486 //---------------------------------------------------------------------------
1487 // wxAMMediaBackend::GetVideoSize
1488 //
1489 // Obtains the cached original video size
1490 //---------------------------------------------------------------------------
GetVideoSize() const1491 wxSize wxAMMediaBackend::GetVideoSize() const
1492 {
1493     if (m_bestSize == wxDefaultSize)
1494     {
1495         wxAMMediaBackend* self = wxConstCast(this, wxAMMediaBackend);
1496         long w = 0;
1497         long h = 0;
1498 
1499         self->GetAM()->get_ImageSourceWidth(&w);
1500         self->GetAM()->get_ImageSourceHeight(&h);
1501 
1502         if (w != 0 && h != 0)
1503             self->m_bestSize.Set(w, h);
1504         else
1505             return wxSize(0,0);
1506     }
1507 
1508    return m_bestSize;
1509 }
1510 
1511 //---------------------------------------------------------------------------
1512 // wxAMMediaBackend::Move
1513 //
1514 // We take care of this in our redrawing
1515 //---------------------------------------------------------------------------
Move(int WXUNUSED (x),int WXUNUSED (y),int WXUNUSED (w),int WXUNUSED (h))1516 void wxAMMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y),
1517                             int WXUNUSED(w), int WXUNUSED(h))
1518 {
1519 }
1520 
1521 //---------------------------------------------------------------------------
1522 // wxAMMediaBackend::OnActiveX
1523 //
1524 // Handle events sent from our activex control (IActiveMovie/IMediaPlayer).
1525 //
1526 // The weird numbers in the switch statement here are "dispatch ids"
1527 // (the numbers in the id field like ( id(xxx) ) ) from amcompat.idl
1528 // and msdxm.idl.
1529 //---------------------------------------------------------------------------
OnActiveX(wxActiveXEvent & event)1530 void wxAMMediaEvtHandler::OnActiveX(wxActiveXEvent& event)
1531 {
1532     // cast to unsigned long to fix narrowing error with case 0xfffffd9f
1533     // when using clang
1534     switch (static_cast<unsigned long>(event.GetDispatchId()))
1535     {
1536     case 0x00000001: // statechange in IActiveMovie
1537     case 0x00000bc4: // playstatechange in IMediaPlayer
1538         if(event.ParamCount() >= 2)
1539         {
1540             switch (event[1].GetInteger())
1541             {
1542             case 0: // stopping
1543                 if( m_amb->wxAMMediaBackend::GetPosition() ==
1544                     m_amb->wxAMMediaBackend::GetDuration() )
1545                 {
1546                     if ( m_amb->SendStopEvent() )
1547                     {
1548                         // Seek to beginning of movie
1549                         m_amb->wxAMMediaBackend::SetPosition(0);
1550 
1551                         // send the event to our child
1552                         m_amb->QueueFinishEvent();
1553                     }
1554                 }
1555                 else
1556                 {
1557                     m_amb->QueueStopEvent();
1558                 }
1559                 break;
1560             case 1: // pause
1561                 m_amb->QueuePauseEvent();
1562                 break;
1563             case 2: // play
1564                 m_amb->QueuePlayEvent();
1565                 break;
1566             default:
1567                 break;
1568             }
1569         }
1570         else
1571             event.Skip();
1572         break;
1573 
1574     case 0x00000032: // opencomplete in IActiveMovie
1575         if(!m_bLoadEventSent)
1576         {
1577             m_amb->FinishLoad();
1578         }
1579         break;
1580 
1581     case 0xfffffd9f: // readystatechange in IActiveMovie2 and IMediaPlayer
1582         if(event.ParamCount() >= 1)
1583         {
1584             if(event[0].GetInteger() == 0)
1585             {
1586                 m_bLoadEventSent = false;
1587             }
1588             // Originally this was >= 3 here but on 3 we can't get the
1589             // size of the video (will error) - however on 4
1590             // it won't play on downloaded things until it is
1591             // completely downloaded so we use the lesser of two evils...
1592             else if(event[0].GetInteger() == 3 &&
1593                 !m_bLoadEventSent)
1594             {
1595                 m_bLoadEventSent = true;
1596                 m_amb->FinishLoad();
1597             }
1598         }
1599         else
1600             event.Skip();
1601         break;
1602 
1603     default:
1604         event.Skip();
1605         return;
1606     }
1607 }
1608 
1609 //---------------------------------------------------------------------------
1610 // End of wxAMMediaBackend
1611 //---------------------------------------------------------------------------
1612 
1613 // Allow the user code to use wxFORCE_LINK_MODULE() to ensure that this object
1614 // file is not discarded by the linker.
1615 #include "wx/link.h"
1616 wxFORCE_LINK_THIS_MODULE(wxmediabackend_am)
1617 
1618 #endif // wxUSE_MEDIACTRL && wxUSE_ACTIVEX
1619