1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/msw/mediactrl_wmp10.cpp
3 // Purpose:     Windows Media Player 9/10 Media Backend for Windows
4 // Author:      Ryan Norton <wxprojects@comcast.net>
5 // Modified by:
6 // Created:     11/07/04
7 // Copyright:   (c) Ryan Norton
8 // Licence:     wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10 
11 //-----------------Introduction----------------------------------------------
12 // This backend is for Desktops with either WMP 9 or 10 and Windows
13 // mobile (5.0, some 2003 SmartPhones etc.) WMP 10 only (9 has no automation
14 // interface but you can hack it with message hacks to play through
15 // a currently running instance of media player).
16 //
17 // There are quite a few WMP 10 interfaces and unlike other media
18 // backends we actually set it to automatically play files as it has
19 // as huge caveat that you cannot (technically) obtain media information
20 // from IWMPMedia including duration and video size until a media file
21 // has literally started to play. There is a hack (and indeed we have
22 // it within this file) to enable duration getting from a non-playing
23 // file, but there is no hack I (RN) know of to get the video size from
24 // a file that isn't playing.
25 //
26 // The workaround for this is to send the wxEVT_MEDIA_LOADED when the file
27 // is about to be played - and if the user didn't change the state of the
28 // media (m_bWasStateChanged), when set it back to the stop state.
29 //
30 // The ActiveX control itself is particularly stubborn, calling
31 // IOleInPlaceSite::OnPosRectChange every file change trying to set itself
32 // to something different from what we told it to before.
33 //
34 // The docs are at
35 // http://msdn.microsoft.com/library/en-us/wmplay10/mmp_sdk/windowsmediaplayer10sdk.asp
36 
37 //===========================================================================
38 //  DECLARATIONS
39 //===========================================================================
40 
41 //---------------------------------------------------------------------------
42 // Pre-compiled header stuff
43 //---------------------------------------------------------------------------
44 
45 // For compilers that support precompilation, includes "wx.h".
46 #include "wx/wxprec.h"
47 
48 #if wxUSE_MEDIACTRL && wxUSE_ACTIVEX
49 
50 #include "wx/mediactrl.h"
51 
52 #ifndef WX_PRECOMP
53     #include "wx/log.h"
54 #endif
55 
56 #include "wx/msw/private.h" // user info and wndproc setting/getting
57 #include "wx/msw/ole/activex.h" // wxActiveXContainer - COM-specific stuff
58 
59 //---------------------------------------------------------------------------
60 // ATL Includes - define WXTEST_ATL if you
61 // want to use CAxWindow instead of wxActiveXContainer (note that
62 // this is mainly for testing as the activex events arn't implemented here)
63 //---------------------------------------------------------------------------
64 #if 0
65     #define WXTEST_ATL
66 #endif
67 
68 #ifdef WXTEST_ATL
69     #include <atlbase.h>
70     CComModule _Module;
71     #define min(x,y) (x < y ? x : y)
72     #include <atlcom.h>
73     #include <atlhost.h>
74     #include <atlctl.h>
75 #endif
76 
77 //---------------------------------------------------------------------------
78 // Other defines
79 //---------------------------------------------------------------------------
80 
81 // error logger for HRESULTS (nothing really now)
82 #define wxWMP10LOG(x)
83 
84 //---------------------------------------------------------------------------
85 // Various definitions dumped from wmp.IDL
86 //---------------------------------------------------------------------------
87 
88 wxCLANG_WARNING_SUPPRESS(unused-const-variable)
89 // CLSID_WMP10ALT is on CE and in some MS docs - on others it is the plain ver
90 const CLSID CLSID_WMP10              = {0x6BF52A50,0x394A,0x11D3,{0xB1,0x53,0x00,0xC0,0x4F,0x79,0xFA,0xA6}};
91 const CLSID CLSID_WMP10ALT           = {0x6BF52A52,0x394A,0x11D3,{0xB1,0x53,0x00,0xC0,0x4F,0x79,0xFA,0xA6}};
92 
93 const IID IID_IWMPSettings = {0x9104D1AB,0x80C9,0x4FED,{0xAB,0xF0,0x2E,0x64,0x17,0xA6,0xDF,0x14}};
94 const IID IID_IWMPCore = {0xD84CCA99,0xCCE2,0x11D2,{0x9E,0xCC,0x00,0x00,0xF8,0x08,0x59,0x81}};
95 #ifndef WXTEST_ATL
96     const IID IID_IWMPPlayer = {0x6BF52A4F,0x394A,0x11D3,{0xB1,0x53,0x00,0xC0,0x4F,0x79,0xFA,0xA6}};
97 #endif
98 
99 const IID IID_IWMPMedia = {0x94D55E95,0x3FAC,0x11D3,{0xB1,0x55,0x00,0xC0,0x4F,0x79,0xFA,0xA6}};
100 const IID IID_IWMPControls = {0x74C09E02,0xF828,0x11D2,{0xA7,0x4B,0x00,0xA0,0xC9,0x05,0xF3,0x6E}};
101 const IID IID_IWMPPlayer2 = {0x0E6B01D1,0xD407,0x4C85,{0xBF,0x5F,0x1C,0x01,0xF6,0x15,0x02,0x80}};
102 const IID IID_IWMPCore2 = {0xBC17E5B7,0x7561,0x4C18,{0xBB,0x90,0x17,0xD4,0x85,0x77,0x56,0x59}};
103 const IID IID_IWMPCore3 = {0x7587C667,0x628F,0x499F,{0x88,0xE7,0x6A,0x6F,0x4E,0x88,0x84,0x64}};
104 const IID IID_IWMPNetwork = {0xEC21B779,0xEDEF,0x462D,{0xBB,0xA4,0xAD,0x9D,0xDE,0x2B,0x29,0xA7}};
105 const IID IID_IWMPControls2 = {0x6F030D25,0x0890,0x480F,{0x97, 0x75, 0x1F,0x7E,0x40,0xAB,0x5B,0x8E}};
106 wxCLANG_WARNING_RESTORE(unused-const-variable)
107 
108 enum WMPOpenState
109 {
110     wmposUndefined  = 0,
111     wmposPlaylistChanging   = 1,
112     wmposPlaylistLocating   = 2,
113     wmposPlaylistConnecting = 3,
114     wmposPlaylistLoading    = 4,
115     wmposPlaylistOpening    = 5,
116     wmposPlaylistOpenNoMedia    = 6,
117     wmposPlaylistChanged    = 7,
118     wmposMediaChanging  = 8,
119     wmposMediaLocating  = 9,
120     wmposMediaConnecting    = 10,
121     wmposMediaLoading   = 11,
122     wmposMediaOpening   = 12,
123     wmposMediaOpen  = 13,
124     wmposBeginCodecAcquisition  = 14,
125     wmposEndCodecAcquisition    = 15,
126     wmposBeginLicenseAcquisition    = 16,
127     wmposEndLicenseAcquisition  = 17,
128     wmposBeginIndividualization = 18,
129     wmposEndIndividualization   = 19,
130     wmposMediaWaiting   = 20,
131     wmposOpeningUnknownURL  = 21
132 };
133 
134 enum WMPPlayState
135 {
136     wmppsUndefined  = 0,
137     wmppsStopped    = 1,
138     wmppsPaused = 2,
139     wmppsPlaying    = 3,
140     wmppsScanForward    = 4,
141     wmppsScanReverse    = 5,
142     wmppsBuffering  = 6,
143     wmppsWaiting    = 7,
144     wmppsMediaEnded = 8,
145     wmppsTransitioning  = 9,
146     wmppsReady  = 10,
147     wmppsReconnecting   = 11,
148     wmppsLast   = 12
149 };
150 
151 
152 struct IWMPMedia : public IDispatch
153 {
154 public:
155     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_isIdentical(
156         /* [in] */ IWMPMedia __RPC_FAR *pIWMPMedia,
157         /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pvbool) = 0;
158 
159     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_sourceURL(
160         /* [retval][out] */ BSTR __RPC_FAR *pbstrSourceURL) = 0;
161 
162     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_name(
163         /* [retval][out] */ BSTR __RPC_FAR *pbstrName) = 0;
164 
165     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_name(
166         /* [in] */ BSTR pbstrName) = 0;
167 
168     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_imageSourceWidth(
169         /* [retval][out] */ long __RPC_FAR *pWidth) = 0;
170 
171     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_imageSourceHeight(
172         /* [retval][out] */ long __RPC_FAR *pHeight) = 0;
173 
174     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_markerCount(
175         /* [retval][out] */ long __RPC_FAR *pMarkerCount) = 0;
176 
177     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE getMarkerTime(
178         /* [in] */ long MarkerNum,
179         /* [retval][out] */ double __RPC_FAR *pMarkerTime) = 0;
180 
181     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE getMarkerName(
182         /* [in] */ long MarkerNum,
183         /* [retval][out] */ BSTR __RPC_FAR *pbstrMarkerName) = 0;
184 
185     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_duration(
186         /* [retval][out] */ double __RPC_FAR *pDuration) = 0;
187 
188     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_durationString(
189         /* [retval][out] */ BSTR __RPC_FAR *pbstrDuration) = 0;
190 
191     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_attributeCount(
192         /* [retval][out] */ long __RPC_FAR *plCount) = 0;
193 
194     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE getAttributeName(
195         /* [in] */ long lIndex,
196         /* [retval][out] */ BSTR __RPC_FAR *pbstrItemName) = 0;
197 
198     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE getItemInfo(
199         /* [in] */ BSTR bstrItemName,
200         /* [retval][out] */ BSTR __RPC_FAR *pbstrVal) = 0;
201 
202     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE setItemInfo(
203         /* [in] */ BSTR bstrItemName,
204         /* [in] */ BSTR bstrVal) = 0;
205 
206     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE getItemInfoByAtom(
207         /* [in] */ long lAtom,
208         /* [retval][out] */ BSTR __RPC_FAR *pbstrVal) = 0;
209 
210     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE isMemberOf(
211         /* [in] */ IUnknown __RPC_FAR *pPlaylist,
212         /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pvarfIsMemberOf) = 0;
213 
214     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE isReadOnlyItem(
215         /* [in] */ BSTR bstrItemName,
216         /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pvarfIsReadOnly) = 0;
217 
218 };
219 
220 struct IWMPControls : public IDispatch
221 {
222 public:
223     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_isAvailable(
224         /* [in] */ BSTR bstrItem,
225         /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pIsAvailable) = 0;
226 
227     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE play( void) = 0;
228 
229     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE stop( void) = 0;
230 
231     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE pause( void) = 0;
232 
233     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE fastForward( void) = 0;
234 
235     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE fastReverse( void) = 0;
236 
237     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_currentPosition(
238         /* [retval][out] */ double __RPC_FAR *pdCurrentPosition) = 0;
239 
240     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_currentPosition(
241         /* [in] */ double pdCurrentPosition) = 0;
242 
243     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_currentPositionString(
244         /* [retval][out] */ BSTR __RPC_FAR *pbstrCurrentPosition) = 0;
245 
246     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE next( void) = 0;
247 
248     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE previous( void) = 0;
249 
250     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_currentItem(
251         /* [retval][out] */ IWMPMedia __RPC_FAR *__RPC_FAR *ppIWMPMedia) = 0;
252 
253     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_currentItem(
254         /* [in] */ IWMPMedia __RPC_FAR *ppIWMPMedia) = 0;
255 
256     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_currentMarker(
257         /* [retval][out] */ long __RPC_FAR *plMarker) = 0;
258 
259     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_currentMarker(
260         /* [in] */ long plMarker) = 0;
261 
262     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE playItem(
263         /* [in] */ IWMPMedia __RPC_FAR *pIWMPMedia) = 0;
264 
265 };
266 
267 struct IWMPControls2 : public IWMPControls
268 {
269 public:
270     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE step(
271         /* [in] */ long lStep ) = 0;
272 };
273 
274 struct IWMPSettings : public IDispatch
275 {
276 public:
277     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_isAvailable(
278         /* [in] */ BSTR bstrItem,
279         /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pIsAvailable) = 0;
280 
281     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_autoStart(
282         /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pfAutoStart) = 0;
283 
284     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_autoStart(
285         /* [in] */ VARIANT_BOOL pfAutoStart) = 0;
286 
287     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_baseURL(
288         /* [retval][out] */ BSTR __RPC_FAR *pbstrBaseURL) = 0;
289 
290     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_baseURL(
291         /* [in] */ BSTR pbstrBaseURL) = 0;
292 
293     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_defaultFrame(
294         /* [retval][out] */ BSTR __RPC_FAR *pbstrDefaultFrame) = 0;
295 
296     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_defaultFrame(
297         /* [in] */ BSTR pbstrDefaultFrame) = 0;
298 
299     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_invokeURLs(
300         /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pfInvokeURLs) = 0;
301 
302     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_invokeURLs(
303         /* [in] */ VARIANT_BOOL pfInvokeURLs) = 0;
304 
305     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_mute(
306         /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pfMute) = 0;
307 
308     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_mute(
309         /* [in] */ VARIANT_BOOL pfMute) = 0;
310 
311     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_playCount(
312         /* [retval][out] */ long __RPC_FAR *plCount) = 0;
313 
314     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_playCount(
315         /* [in] */ long plCount) = 0;
316 
317     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_rate(
318         /* [retval][out] */ double __RPC_FAR *pdRate) = 0;
319 
320     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_rate(
321         /* [in] */ double pdRate) = 0;
322 
323     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_balance(
324         /* [retval][out] */ long __RPC_FAR *plBalance) = 0;
325 
326     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_balance(
327         /* [in] */ long plBalance) = 0;
328 
329     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_volume(
330         /* [retval][out] */ long __RPC_FAR *plVolume) = 0;
331 
332     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_volume(
333         /* [in] */ long plVolume) = 0;
334 
335     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE getMode(
336         /* [in] */ BSTR bstrMode,
337         /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pvarfMode) = 0;
338 
339     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE setMode(
340         /* [in] */ BSTR bstrMode,
341         /* [in] */ VARIANT_BOOL varfMode) = 0;
342 
343     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_enableErrorDialogs(
344         /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pfEnableErrorDialogs) = 0;
345 
346     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_enableErrorDialogs(
347         /* [in] */ VARIANT_BOOL pfEnableErrorDialogs) = 0;
348 
349 };
350 
351 struct IWMPNetwork : public IDispatch
352 {
353 public:
354     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_bandWidth(
355         /* [retval][out] */ long __RPC_FAR *plBandwidth) = 0;
356 
357     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_recoveredPackets(
358         /* [retval][out] */ long __RPC_FAR *plRecoveredPackets) = 0;
359 
360     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_sourceProtocol(
361         /* [retval][out] */ BSTR __RPC_FAR *pbstrSourceProtocol) = 0;
362 
363     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_receivedPackets(
364         /* [retval][out] */ long __RPC_FAR *plReceivedPackets) = 0;
365 
366     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_lostPackets(
367         /* [retval][out] */ long __RPC_FAR *plLostPackets) = 0;
368 
369     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_receptionQuality(
370         /* [retval][out] */ long __RPC_FAR *plReceptionQuality) = 0;
371 
372     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_bufferingCount(
373         /* [retval][out] */ long __RPC_FAR *plBufferingCount) = 0;
374 
375     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_bufferingProgress(
376         /* [retval][out] */ long __RPC_FAR *plBufferingProgress) = 0;
377 
378     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_bufferingTime(
379         /* [retval][out] */ long __RPC_FAR *plBufferingTime) = 0;
380 
381     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_bufferingTime(
382         /* [in] */ long plBufferingTime) = 0;
383 
384     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_frameRate(
385         /* [retval][out] */ long __RPC_FAR *plFrameRate) = 0;
386 
387     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_maxBitRate(
388         /* [retval][out] */ long __RPC_FAR *plBitRate) = 0;
389 
390     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_bitRate(
391         /* [retval][out] */ long __RPC_FAR *plBitRate) = 0;
392 
393     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE getProxySettings(
394         /* [in] */ BSTR bstrProtocol,
395         /* [retval][out] */ long __RPC_FAR *plProxySetting) = 0;
396 
397     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE setProxySettings(
398         /* [in] */ BSTR bstrProtocol,
399         /* [in] */ long lProxySetting) = 0;
400 
401     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE getProxyName(
402         /* [in] */ BSTR bstrProtocol,
403         /* [retval][out] */ BSTR __RPC_FAR *pbstrProxyName) = 0;
404 
405     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE setProxyName(
406         /* [in] */ BSTR bstrProtocol,
407         /* [in] */ BSTR bstrProxyName) = 0;
408 
409     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE getProxyPort(
410         /* [in] */ BSTR bstrProtocol,
411         /* [retval][out] */ long __RPC_FAR *lProxyPort) = 0;
412 
413     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE setProxyPort(
414         /* [in] */ BSTR bstrProtocol,
415         /* [in] */ long lProxyPort) = 0;
416 
417     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE getProxyExceptionList(
418         /* [in] */ BSTR bstrProtocol,
419         /* [retval][out] */ BSTR __RPC_FAR *pbstrExceptionList) = 0;
420 
421     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE setProxyExceptionList(
422         /* [in] */ BSTR bstrProtocol,
423         /* [in] */ BSTR pbstrExceptionList) = 0;
424 
425     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE getProxyBypassForLocal(
426         /* [in] */ BSTR bstrProtocol,
427         /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pfBypassForLocal) = 0;
428 
429     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE setProxyBypassForLocal(
430         /* [in] */ BSTR bstrProtocol,
431         /* [in] */ VARIANT_BOOL fBypassForLocal) = 0;
432 
433     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_maxBandwidth(
434         /* [retval][out] */ long __RPC_FAR *lMaxBandwidth) = 0;
435 
436     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_maxBandwidth(
437         /* [in] */ long lMaxBandwidth) = 0;
438 
439     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_downloadProgress(
440         /* [retval][out] */ long __RPC_FAR *plDownloadProgress) = 0;
441 
442     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_encodedFrameRate(
443         /* [retval][out] */ long __RPC_FAR *plFrameRate) = 0;
444 
445     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_framesSkipped(
446         /* [retval][out] */ long __RPC_FAR *plFrames) = 0;
447 
448 };
449 
450 struct IWMPCore : public IDispatch
451 {
452 public:
453     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE close( void) = 0;
454 
455     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_URL(
456         /* [retval][out] */ BSTR __RPC_FAR *pbstrURL) = 0;
457 
458     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_URL(
459         /* [in] */ BSTR pbstrURL) = 0;
460 
461     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_openState(
462         /* [retval][out] */ WMPOpenState __RPC_FAR *pwmpos) = 0;
463 
464     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_playState(
465         /* [retval][out] */ WMPPlayState __RPC_FAR *pwmpps) = 0;
466 
467     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_controls(
468         /* [retval][out] */ IWMPControls __RPC_FAR *__RPC_FAR *ppControl) = 0;
469 
470     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_settings(
471         /* [retval][out] */ IWMPSettings __RPC_FAR *__RPC_FAR *ppSettings) = 0;
472 
473     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_currentMedia(
474         /* [retval][out] */ IWMPMedia __RPC_FAR *__RPC_FAR *ppMedia) = 0;
475 
476     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_currentMedia(
477         /* [in] */ IUnknown __RPC_FAR *ppMedia) = 0;
478 
479     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_mediaCollection(
480         /* [retval][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppMediaCollection) = 0;
481 
482     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_playlistCollection(
483         /* [retval][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppPlaylistCollection) = 0;
484 
485     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_versionInfo(
486         /* [retval][out] */ BSTR __RPC_FAR *pbstrVersionInfo) = 0;
487 
488     virtual /* [id] */ HRESULT STDMETHODCALLTYPE launchURL(
489         /* [in] */ BSTR bstrURL) = 0;
490 
491     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_network(
492         /* [retval][out] */ IWMPNetwork __RPC_FAR *__RPC_FAR *ppQNI) = 0;
493 
494     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_currentPlaylist(
495         /* [retval][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppPL) = 0;
496 
497     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_currentPlaylist(
498         /* [in] */ IUnknown __RPC_FAR *ppPL) = 0;
499 
500     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_cdromCollection(
501         /* [retval][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppCdromCollection) = 0;
502 
503     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_closedCaption(
504         /* [retval][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppClosedCaption) = 0;
505 
506     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_isOnline(
507         /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pfOnline) = 0;
508 
509     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_Error(
510         /* [retval][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppError) = 0;
511 
512     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_status(
513         /* [retval][out] */ BSTR __RPC_FAR *pbstrStatus) = 0;
514 
515 };
516 
517 struct IWMPCore2 : public IWMPCore
518 {
519 public:
520     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_dvd(
521         /* [retval][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppDVD) = 0;
522 
523 };
524 
525 struct IWMPCore3 : public IWMPCore2
526 {
527 public:
528     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE newPlaylist(
529         /* [in] */ BSTR bstrName,
530         /* [in] */ BSTR bstrURL,
531         /* [retval][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppPlaylist) = 0;
532 
533     virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE newMedia(
534         /* [in] */ BSTR bstrURL,
535         /* [retval][out] */ IWMPMedia __RPC_FAR *__RPC_FAR *ppMedia) = 0;
536 
537 };
538 
539 #ifdef WXTEST_ATL
540     MIDL_INTERFACE("6BF52A4F-394A-11D3-B153-00C04F79FAA6")
541 #else
542     struct
543 #endif
544 IWMPPlayer : public IWMPCore
545 {
546 public:
547     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_enabled(
548         /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pbEnabled) = 0;
549 
550     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_enabled(
551         /* [in] */ VARIANT_BOOL pbEnabled) = 0;
552 
553     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_fullScreen(
554         /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pbFullScreen) = 0;
555 
556     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_fullScreen(
557         VARIANT_BOOL pbFullScreen) = 0;
558 
559     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_enableContextMenu(
560         /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pbEnableContextMenu) = 0;
561 
562     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_enableContextMenu(
563         VARIANT_BOOL pbEnableContextMenu) = 0;
564 
565     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_uiMode(
566         /* [in] */ BSTR pbstrMode) = 0;
567 
568     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_uiMode(
569         /* [retval][out] */ BSTR __RPC_FAR *pbstrMode) = 0;
570 };
571 
572 struct IWMPPlayer2 : public IWMPCore
573 {
574 public:
575     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_enabled(
576         /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pbEnabled) = 0;
577 
578     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_enabled(
579         /* [in] */ VARIANT_BOOL pbEnabled) = 0;
580 
581     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_fullScreen(
582         /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pbFullScreen) = 0;
583 
584     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_fullScreen(
585         VARIANT_BOOL pbFullScreen) = 0;
586 
587     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_enableContextMenu(
588         /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pbEnableContextMenu) = 0;
589 
590     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_enableContextMenu(
591         VARIANT_BOOL pbEnableContextMenu) = 0;
592 
593     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_uiMode(
594         /* [in] */ BSTR pbstrMode) = 0;
595 
596     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_uiMode(
597         /* [retval][out] */ BSTR __RPC_FAR *pbstrMode) = 0;
598 
599     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_stretchToFit(
600         /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pbEnabled) = 0;
601 
602     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_stretchToFit(
603         /* [in] */ VARIANT_BOOL pbEnabled) = 0;
604 
605     virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_windowlessVideo(
606         /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pbEnabled) = 0;
607 
608     virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_windowlessVideo(
609         /* [in] */ VARIANT_BOOL pbEnabled) = 0;
610 
611 };
612 
613 //---------------------------------------------------------------------------
614 //
615 //  wxWMP10MediaBackend
616 //
617 //---------------------------------------------------------------------------
618 
619 class WXDLLIMPEXP_MEDIA wxWMP10MediaBackend : public wxMediaBackendCommonBase
620 {
621 public:
622     wxWMP10MediaBackend();
623     virtual ~wxWMP10MediaBackend();
624 
625     virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
626                                      wxWindowID id,
627                                      const wxPoint& pos,
628                                      const wxSize& size,
629                                      long style,
630                                      const wxValidator& validator,
631                                      const wxString& name) wxOVERRIDE;
632 
633     virtual bool Play() wxOVERRIDE;
634     virtual bool Pause() wxOVERRIDE;
635     virtual bool Stop() wxOVERRIDE;
636 
637     virtual bool Load(const wxString& fileName) wxOVERRIDE;
638     virtual bool Load(const wxURI& location) wxOVERRIDE;
639     virtual bool Load(const wxURI& location, const wxURI& proxy) wxOVERRIDE;
640 
641     bool DoLoad(const wxString& location);
642     void FinishLoad();
643 
644     virtual wxMediaState GetState() wxOVERRIDE;
645 
646     virtual bool SetPosition(wxLongLong where) wxOVERRIDE;
647     virtual wxLongLong GetPosition() wxOVERRIDE;
648     virtual wxLongLong GetDuration() wxOVERRIDE;
649 
650     virtual void Move(int x, int y, int w, int h) wxOVERRIDE;
651     wxSize GetVideoSize() const wxOVERRIDE;
652 
653     virtual double GetPlaybackRate() wxOVERRIDE;
654     virtual bool SetPlaybackRate(double) wxOVERRIDE;
655 
656     virtual double GetVolume() wxOVERRIDE;
657     virtual bool SetVolume(double) wxOVERRIDE;
658 
659     virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags) wxOVERRIDE;
660 
661     virtual wxLongLong GetDownloadProgress() wxOVERRIDE;
662     virtual wxLongLong GetDownloadTotal() wxOVERRIDE;
663 
664 
665 #ifdef WXTEST_ATL
666         CAxWindow  m_wndView;
667 #else
668         wxActiveXContainer* m_pAX;
669 #endif
670     IWMPPlayer* m_pWMPPlayer;       // Main activex interface
671     IWMPSettings* m_pWMPSettings;   // Settings such as volume
672     IWMPControls* m_pWMPControls;   // Control interface (play etc.)
673     IWMPControls2* m_pWMPControls2; // Control interface (play etc.)
674 
675     wxSize m_bestSize;              // Actual movie size
676 
677     bool m_bWasStateChanged;        // See the "introduction"
678     wxEvtHandler* m_evthandler;
679 
680     friend class wxWMP10MediaEvtHandler;
681     wxDECLARE_DYNAMIC_CLASS(wxWMP10MediaBackend);
682 };
683 
684 #ifndef WXTEST_ATL
685 class WXDLLIMPEXP_MEDIA wxWMP10MediaEvtHandler : public wxEvtHandler
686 {
687 public:
wxWMP10MediaEvtHandler(wxWMP10MediaBackend * amb)688     wxWMP10MediaEvtHandler(wxWMP10MediaBackend *amb) :
689        m_amb(amb)
690     {
691         m_amb->m_pAX->Bind(wxEVT_ACTIVEX,
692             &wxWMP10MediaEvtHandler::OnActiveX, this,
693             m_amb->m_pAX->GetId());
694     }
695 
696     void OnActiveX(wxActiveXEvent& event);
697 
698 private:
699     wxWMP10MediaBackend *m_amb;
700 
701     wxDECLARE_NO_COPY_CLASS(wxWMP10MediaEvtHandler);
702 };
703 #endif
704 
705 //===========================================================================
706 //  IMPLEMENTATION
707 //===========================================================================
708 
709 //---------------------------------------------------------------------------
710 //
711 // wxWMP10MediaBackend
712 //
713 //---------------------------------------------------------------------------
714 
715 wxIMPLEMENT_DYNAMIC_CLASS(wxWMP10MediaBackend, wxMediaBackend);
716 
717 //---------------------------------------------------------------------------
718 // wxWMP10MediaBackend Constructor
719 //---------------------------------------------------------------------------
wxWMP10MediaBackend()720 wxWMP10MediaBackend::wxWMP10MediaBackend()
721                  :
722 #ifndef WXTEST_ATL
723                 m_pAX(NULL),
724 #endif
725                 m_pWMPPlayer(NULL),
726                 m_pWMPSettings(NULL),
727                 m_pWMPControls(NULL),
728                 m_pWMPControls2(NULL)
729 
730 {
731     m_evthandler = NULL;
732 }
733 
734 //---------------------------------------------------------------------------
735 // wxWMP10MediaBackend Destructor
736 //---------------------------------------------------------------------------
~wxWMP10MediaBackend()737 wxWMP10MediaBackend::~wxWMP10MediaBackend()
738 {
739     if(m_pWMPPlayer)
740     {
741 #ifndef WXTEST_ATL
742         m_pAX->DissociateHandle();
743         delete m_pAX;
744 
745         if (m_evthandler)
746         {
747             m_ctrl->RemoveEventHandler(m_evthandler);
748             delete m_evthandler;
749         }
750 #else
751         AtlAxWinTerm();
752         _Module.Term();
753 #endif
754 
755         m_pWMPPlayer->Release();
756         if (m_pWMPSettings)
757             m_pWMPSettings->Release();
758         if (m_pWMPControls)
759             m_pWMPControls->Release();
760         if (m_pWMPControls2)
761             m_pWMPControls2->Release();
762     }
763 }
764 
765 //---------------------------------------------------------------------------
766 // wxWMP10MediaBackend::CreateControl
767 //---------------------------------------------------------------------------
CreateControl(wxControl * ctrl,wxWindow * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,long style,const wxValidator & validator,const wxString & name)768 bool wxWMP10MediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
769                                      wxWindowID id,
770                                      const wxPoint& pos,
771                                      const wxSize& size,
772                                      long style,
773                                      const wxValidator& validator,
774                                      const wxString& name)
775 {
776 #ifndef WXTEST_ATL
777     if( ::CoCreateInstance(CLSID_WMP10, NULL,
778                                   CLSCTX_INPROC_SERVER,
779                                   IID_IWMPPlayer, (void**)&m_pWMPPlayer) != 0 )
780     {
781         if( ::CoCreateInstance(CLSID_WMP10ALT, NULL,
782                                   CLSCTX_INPROC_SERVER,
783                                   IID_IWMPPlayer, (void**)&m_pWMPPlayer) != 0 )
784             return false;
785 
786         if( m_pWMPPlayer->get_settings(&m_pWMPSettings) != 0)
787         {
788             m_pWMPPlayer->Release();
789             wxLogSysError(wxT("Could not obtain settings from WMP10!"));
790             return false;
791         }
792 
793         if( m_pWMPPlayer->get_controls(&m_pWMPControls) != 0)
794         {
795             m_pWMPSettings->Release();
796             m_pWMPPlayer->Release();
797             wxLogSysError(wxT("Could not obtain controls from WMP10!"));
798             return false;
799         }
800         if (m_pWMPControls )
801             m_pWMPControls->QueryInterface(IID_IWMPControls2, (void**)&m_pWMPControls2);
802     }
803 #endif
804 
805     //
806     // Create window
807     // By default wxWindow(s) is created with a border -
808     // so we need to get rid of those
809     //
810     // Since we don't have a child window like most other
811     // backends, we don't need wxCLIP_CHILDREN
812     //
813     if ( !ctrl->wxControl::Create(parent, id, pos, size,
814                             (style & ~wxBORDER_MASK) | wxBORDER_NONE,
815                             validator, name) )
816         return false;
817 
818     //
819     // Now create the ActiveX container along with the media player
820     // interface and query them
821     //
822     m_ctrl = wxStaticCast(ctrl, wxMediaCtrl);
823 
824 #ifndef WXTEST_ATL
825     m_pAX = new wxActiveXContainer(ctrl, IID_IWMPPlayer, m_pWMPPlayer);
826 
827     // Connect for events
828     m_evthandler = new wxWMP10MediaEvtHandler(this);
829     m_ctrl->PushEventHandler(m_evthandler);
830 #else
831     _Module.Init(NULL, ::GetModuleHandle(NULL));
832     AtlAxWinInit();
833     CComPtr<IAxWinHostWindow>  spHost;
834 
835     HRESULT hr;
836     RECT rcClient;
837     ::GetClientRect((HWND)ctrl->GetHandle(), &rcClient);
838     m_wndView.Create((HWND)ctrl->GetHandle(), rcClient, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);
839     hr = m_wndView.QueryHost(&spHost);
840     hr = spHost->CreateControl(CComBSTR(wxT("{6BF52A52-394A-11d3-B153-00C04F79FAA6}")), m_wndView, 0);
841     hr = m_wndView.QueryControl(&m_pWMPPlayer);
842 
843     if( m_pWMPPlayer->get_settings(&m_pWMPSettings) != 0)
844     {
845         m_pWMPPlayer->Release();
846         wxLogSysError(wxT("Could not obtain settings from WMP10!"));
847         return false;
848     }
849 
850     if( m_pWMPPlayer->get_controls(&m_pWMPControls) != 0)
851     {
852         m_pWMPSettings->Release();
853         m_pWMPPlayer->Release();
854         wxLogSysError(wxT("Could not obtain controls from WMP10!"));
855         return false;
856     }
857 #endif
858 
859     //
860     //  Here we set up wx-specific stuff for the default
861     //  settings wxMediaCtrl says it will stay to
862     //
863 
864     IWMPPlayer2* pWMPPlayer2; // Only 2 has windowless video and stretchtofit
865     if(m_pWMPPlayer->QueryInterface(IID_IWMPPlayer2, (void**)&pWMPPlayer2) == 0)
866     {
867         // We don't check errors here as these arn't particularly important
868         // and may not be implemented (i.e. stretchToFit on CE)
869         pWMPPlayer2->put_windowlessVideo(VARIANT_TRUE);
870         pWMPPlayer2->put_stretchToFit(VARIANT_TRUE);
871         pWMPPlayer2->Release();
872     }
873 
874     // by default true (see the "introduction")
875     m_pWMPSettings->put_autoStart(VARIANT_TRUE);
876     // by default enabled
877     wxWMP10MediaBackend::ShowPlayerControls(wxMEDIACTRLPLAYERCONTROLS_NONE);
878     // by default with AM only 0.5
879     wxWMP10MediaBackend::SetVolume(1.0);
880 
881     // don't erase the background of our control window so that resizing is a
882     // bit smoother
883     m_ctrl->SetBackgroundStyle(wxBG_STYLE_PAINT);
884 
885     // success
886     return true;
887 }
888 
889 //---------------------------------------------------------------------------
890 // wxWMP10MediaBackend::Load (file version)
891 //---------------------------------------------------------------------------
Load(const wxString & fileName)892 bool wxWMP10MediaBackend::Load(const wxString& fileName)
893 {
894     return DoLoad(fileName);
895 }
896 
897 //---------------------------------------------------------------------------
898 // wxWMP10MediaBackend::Load (URL Version)
899 //---------------------------------------------------------------------------
Load(const wxURI & location)900 bool wxWMP10MediaBackend::Load(const wxURI& location)
901 {
902     return DoLoad(location.BuildURI());
903 }
904 
905 //---------------------------------------------------------------------------
906 // wxWMP10MediaBackend::Load (URL Version with Proxy)
907 //---------------------------------------------------------------------------
Load(const wxURI & location,const wxURI & proxy)908 bool wxWMP10MediaBackend::Load(const wxURI& location,
909                                const wxURI& proxy)
910 {
911     bool bOK = false;
912 
913     IWMPNetwork* pWMPNetwork;
914     if( m_pWMPPlayer->get_network(&pWMPNetwork) == 0 )
915     {
916         long lOldSetting;
917         if( pWMPNetwork->getProxySettings(
918                     wxBasicString(location.GetScheme()), &lOldSetting
919                                         ) == 0 &&
920 
921             pWMPNetwork->setProxySettings(
922                     wxBasicString(location.GetScheme()), // protocol
923                                 2) == 0) // 2 == manually specify
924         {
925             wxBasicString bsOldName;
926             long lOldPort = 0;
927 
928             pWMPNetwork->getProxyName(
929                         wxBasicString(location.GetScheme()),
930                         bsOldName.ByRef());
931             pWMPNetwork->getProxyPort(
932                         wxBasicString(location.GetScheme()),
933                         &lOldPort);
934 
935             long lPort;
936             wxString server;
937             if(proxy.IsReference())
938             {
939                 server = proxy.GetScheme();
940                 lPort = wxAtoi(proxy.GetPath());
941             }
942             else
943             {
944                 server = proxy.GetServer();
945                 lPort = wxAtoi(proxy.GetPort());
946             }
947 
948             if( pWMPNetwork->setProxyName(
949                         wxBasicString(location.GetScheme()), // proto
950                         wxBasicString(server) ) == 0  &&
951 
952                 pWMPNetwork->setProxyPort(
953                         wxBasicString(location.GetScheme()), // proto
954                         lPort
955                                          ) == 0
956               )
957             {
958                 bOK = DoLoad(location.BuildURI());
959 
960                 pWMPNetwork->setProxySettings(
961                     wxBasicString(location.GetScheme()), // protocol
962                                 lOldSetting);
963                 if(bsOldName)
964                     pWMPNetwork->setProxyName(
965                         wxBasicString(location.GetScheme()), // protocol
966                                     bsOldName);
967 
968                 if(lOldPort)
969                     pWMPNetwork->setProxyPort(
970                         wxBasicString(location.GetScheme()), // protocol
971                                 lOldPort);
972 
973                 pWMPNetwork->Release();
974             }
975             else
976                 pWMPNetwork->Release();
977 
978         }
979         else
980             pWMPNetwork->Release();
981 
982     }
983 
984     return bOK;
985 }
986 
987 //---------------------------------------------------------------------------
988 // wxWMP10MediaBackend::DoLoad
989 //
990 // Called by all functions - this actually renders
991 // the file and sets up the filter graph
992 //---------------------------------------------------------------------------
DoLoad(const wxString & location)993 bool wxWMP10MediaBackend::DoLoad(const wxString& location)
994 {
995     HRESULT hr;
996 
997 #if 0 // See the "introduction" - this is the duration hack
998     // ------------------ BLATENT HACK ALERT -------------------------
999     // Normally we can only get the duration of things already in an
1000     // existing playlist or playing - however this clever "workaround"
1001     // enables us to get the duration even when stopped :)
1002     // http://weblogs.asp.net/rweigelt/archive/2003/07/02/9613.aspx
1003 
1004     IWMPCore3* pWMPCore3;
1005     double outDuration;
1006     if(m_pWMPPlayer->QueryInterface(IID_IWMPCore3, (void**) &pWMPCore3) == 0)
1007     {
1008         IWMPMedia* pWMPMedia;
1009 
1010         if( (hr = pWMPCore3->newMedia(wxBasicString(location),
1011                                &pWMPMedia)) == 0)
1012         {
1013             // this (get_duration) will actually FAIL, but it will work.
1014             pWMPMedia->get_duration(&outDuration);
1015             pWMPCore3->put_currentMedia(pWMPMedia);
1016             pWMPMedia->Release();
1017         }
1018 
1019         pWMPCore3->Release();
1020     }
1021     else
1022 #endif
1023     {
1024         // just load it the "normal" way
1025         hr = m_pWMPPlayer->put_URL( wxBasicString(location) );
1026     }
1027 
1028     if(FAILED(hr))
1029     {
1030         wxWMP10LOG(hr);
1031         return false;
1032     }
1033 
1034     return true;
1035 }
1036 
1037 //---------------------------------------------------------------------------
1038 // wxWMP10MediaBackend::FinishLoad
1039 //
1040 // Called when our media is about to play (a.k.a. wmposMediaOpen)
1041 //---------------------------------------------------------------------------
FinishLoad()1042 void wxWMP10MediaBackend::FinishLoad()
1043 {
1044     // Get the original video size
1045     // THIS WILL NOT WORK UNLESS THE MEDIA IS ABOUT TO PLAY
1046     // See the "introduction" - also get_currentMedia will return
1047     // "1" which is a VALID HRESULT value
1048     // and a NULL pWMPMedia if the media isn't the "current" one
1049     // which is rather unintuitive in the sense that it uses it
1050     // (i.e. basically not currently playing)...
1051     IWMPMedia* pWMPMedia;
1052     if(m_pWMPPlayer->get_currentMedia(&pWMPMedia) == 0)
1053     {
1054         pWMPMedia->get_imageSourceWidth((long*)&m_bestSize.x);
1055         pWMPMedia->get_imageSourceHeight((long*)&m_bestSize.y);
1056         pWMPMedia->Release();
1057     }
1058     else
1059     {
1060         wxLogDebug(wxT("Could not get media"));
1061     }
1062 
1063     NotifyMovieLoaded();
1064 }
1065 
1066 //---------------------------------------------------------------------------
1067 // wxWMP10MediaBackend::ShowPlayerControls
1068 //---------------------------------------------------------------------------
ShowPlayerControls(wxMediaCtrlPlayerControls flags)1069 bool wxWMP10MediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
1070 {
1071     if(!flags)
1072     {
1073         m_pWMPPlayer->put_enabled(VARIANT_FALSE);
1074         m_pWMPPlayer->put_uiMode(wxBasicString(wxS("none")));
1075     }
1076     else
1077     {
1078         // TODO: use "custom"? (note that CE only supports none/full)
1079         m_pWMPPlayer->put_uiMode(wxBasicString(wxS("full")));
1080         m_pWMPPlayer->put_enabled(VARIANT_TRUE);
1081     }
1082 
1083     return true;
1084 }
1085 
1086 //---------------------------------------------------------------------------
1087 // wxWMP10MediaBackend::Play
1088 //
1089 // Plays the stream.  If it is non-seekable, it will restart it (implicit).
1090 //
1091 // TODO: We use SUCCEEDED due to pickiness on IMediaPlayer are doing it here
1092 // but do we need to?
1093 //---------------------------------------------------------------------------
Play()1094 bool wxWMP10MediaBackend::Play()
1095 {
1096     // Actually try to play the movie (will fail if not loaded completely)
1097     HRESULT hr = m_pWMPControls->play();
1098     if(SUCCEEDED(hr))
1099     {
1100        m_bWasStateChanged = true;
1101        return true;
1102     }
1103     wxWMP10LOG(hr);
1104     return false;
1105 }
1106 
1107 //---------------------------------------------------------------------------
1108 // wxWMP10MediaBackend::Pause
1109 //
1110 // Pauses the stream.
1111 //---------------------------------------------------------------------------
Pause()1112 bool wxWMP10MediaBackend::Pause()
1113 {
1114     HRESULT hr = m_pWMPControls->pause();
1115     if(SUCCEEDED(hr))
1116     {
1117         m_bWasStateChanged = true;
1118         return true;
1119     }
1120     wxWMP10LOG(hr);
1121     return false;
1122 }
1123 
1124 //---------------------------------------------------------------------------
1125 // wxWMP10MediaBackend::Stop
1126 //
1127 // Stops the stream.
1128 //---------------------------------------------------------------------------
Stop()1129 bool wxWMP10MediaBackend::Stop()
1130 {
1131     HRESULT hr = m_pWMPControls->stop();
1132     if(SUCCEEDED(hr))
1133     {
1134         // Seek to beginning
1135         wxWMP10MediaBackend::SetPosition(0);
1136         m_bWasStateChanged = true;
1137         return true;
1138     }
1139     wxWMP10LOG(hr);
1140     return false;
1141 }
1142 
1143 //---------------------------------------------------------------------------
1144 // wxWMP10MediaBackend::SetPosition
1145 //
1146 // WMP10 position values are a double in seconds - we just translate
1147 // to our base here
1148 //---------------------------------------------------------------------------
SetPosition(wxLongLong where)1149 bool wxWMP10MediaBackend::SetPosition(wxLongLong where)
1150 {
1151     // The display does not update if only put_currentPosition is called.
1152     // We have to find the time for the previous frame, set the control
1153     // to that position and then tell it to step forward one frame.  This
1154     // forces the control to draw the frame to the screen, otherwise we get
1155     // just a black screen.
1156 
1157     double timePerFrameInMSec = 0;
1158     if (m_pWMPControls2)
1159         timePerFrameInMSec = 1000 / GetPlaybackRate();
1160 
1161     HRESULT hr = m_pWMPControls->put_currentPosition(
1162                         ((LONGLONG)where.GetValue() - timePerFrameInMSec) / 1000.0
1163                                      );
1164     if(FAILED(hr))
1165     {
1166         wxWMP10LOG(hr);
1167         return false;
1168     }
1169 
1170     if (m_pWMPControls2)
1171         m_pWMPControls2->step(1);
1172 
1173 
1174     return true;
1175 }
1176 
1177 //---------------------------------------------------------------------------
1178 // wxWMP10MediaBackend::GetPosition
1179 //
1180 // WMP10 position values are a double in seconds - we just translate
1181 // to our base here
1182 //---------------------------------------------------------------------------
GetPosition()1183 wxLongLong wxWMP10MediaBackend::GetPosition()
1184 {
1185     double outCur;
1186     HRESULT hr = m_pWMPControls->get_currentPosition(&outCur);
1187     if(FAILED(hr))
1188     {
1189         wxWMP10LOG(hr);
1190         return 0;
1191     }
1192 
1193     // h,m,s,milli - outCur is in 1 second (double)
1194     outCur *= 1000;
1195     wxLongLong ll;
1196     ll.Assign(outCur);
1197 
1198     return ll;
1199 }
1200 
1201 //---------------------------------------------------------------------------
1202 // wxWMP10MediaBackend::GetVolume
1203 //
1204 // Volume 0-100
1205 //---------------------------------------------------------------------------
GetVolume()1206 double wxWMP10MediaBackend::GetVolume()
1207 {
1208     long lVolume;
1209     HRESULT hr = m_pWMPSettings->get_volume(&lVolume);
1210     if(FAILED(hr))
1211     {
1212         wxWMP10LOG(hr);
1213         return 0.0;
1214     }
1215 
1216     return (double)lVolume / 100.0;
1217 }
1218 
1219 //---------------------------------------------------------------------------
1220 // wxWMP10MediaBackend::SetVolume
1221 //
1222 // Volume 0-100
1223 //---------------------------------------------------------------------------
SetVolume(double dVolume)1224 bool wxWMP10MediaBackend::SetVolume(double dVolume)
1225 {
1226     HRESULT hr = m_pWMPSettings->put_volume( (long) (dVolume * 100.0) );
1227     if(FAILED(hr))
1228     {
1229         wxWMP10LOG(hr);
1230         return false;
1231     }
1232     return true;
1233 }
1234 
1235 //---------------------------------------------------------------------------
1236 // wxWMP10MediaBackend::GetDuration
1237 //
1238 // Obtains the duration of the media.
1239 //
1240 // See the "introduction"
1241 //
1242 // The good news is that this doesn't appear to have the XING header
1243 // parser problem that WMP6 SDK/IActiveMovie/IMediaPlayer/IWMP has
1244 //---------------------------------------------------------------------------
GetDuration()1245 wxLongLong wxWMP10MediaBackend::GetDuration()
1246 {
1247     double outDuration = 0.0;
1248 
1249     IWMPMedia* pWMPMedia;
1250     if(m_pWMPPlayer->get_currentMedia(&pWMPMedia) == 0)
1251     {
1252         if(pWMPMedia->get_duration(&outDuration) != 0)
1253         {
1254             wxLogDebug(wxT("get_duration failed"));
1255         }
1256         pWMPMedia->Release();
1257     }
1258 
1259 
1260     // h,m,s,milli - outDuration is in 1 second (double)
1261     outDuration *= 1000;
1262     wxLongLong ll;
1263     ll.Assign(outDuration);
1264 
1265     return ll;
1266 }
1267 
1268 //---------------------------------------------------------------------------
1269 // wxWMP10MediaBackend::GetState
1270 //
1271 // Returns the current state
1272 //---------------------------------------------------------------------------
GetState()1273 wxMediaState wxWMP10MediaBackend::GetState()
1274 {
1275     WMPPlayState nState;
1276     HRESULT hr = m_pWMPPlayer->get_playState(&nState);
1277     if(FAILED(hr))
1278     {
1279         wxWMP10LOG(hr);
1280         return wxMEDIASTATE_STOPPED;
1281     }
1282 
1283     switch(nState)
1284     {
1285     case wmppsPaused:
1286         return wxMEDIASTATE_PAUSED;
1287     case wmppsPlaying:
1288         return wxMEDIASTATE_PLAYING;
1289     default:
1290         return wxMEDIASTATE_STOPPED;
1291     }
1292 }
1293 
1294 //---------------------------------------------------------------------------
1295 // wxWMP10MediaBackend::GetPlaybackRate
1296 //
1297 // Just get the rate from WMP10
1298 //---------------------------------------------------------------------------
GetPlaybackRate()1299 double wxWMP10MediaBackend::GetPlaybackRate()
1300 {
1301     double dRate;
1302     HRESULT hr = m_pWMPSettings->get_rate(&dRate);
1303     if(FAILED(hr))
1304     {
1305         wxWMP10LOG(hr);
1306         return 0.0;
1307     }
1308     return dRate;
1309 }
1310 
1311 //---------------------------------------------------------------------------
1312 // wxWMP10MediaBackend::SetPlaybackRate
1313 //
1314 // Sets the playback rate of the media - DirectShow is pretty good
1315 // about this, actually
1316 //---------------------------------------------------------------------------
SetPlaybackRate(double dRate)1317 bool wxWMP10MediaBackend::SetPlaybackRate(double dRate)
1318 {
1319     HRESULT hr = m_pWMPSettings->put_rate(dRate);
1320     if(FAILED(hr))
1321     {
1322         wxWMP10LOG(hr);
1323         return false;
1324     }
1325 
1326     return true;
1327 }
1328 
1329 //---------------------------------------------------------------------------
1330 // wxWMP10MediaBackend::GetVideoSize
1331 //
1332 // Obtains the cached original video size
1333 //---------------------------------------------------------------------------
GetVideoSize() const1334 wxSize wxWMP10MediaBackend::GetVideoSize() const
1335 {
1336     return m_bestSize;
1337 }
1338 
1339 //---------------------------------------------------------------------------
1340 // wxWMP10MediaBackend::Move
1341 //
1342 // We take care of this in our redrawing
1343 //---------------------------------------------------------------------------
Move(int WXUNUSED (x),int WXUNUSED (y),int w,int h)1344 void wxWMP10MediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y),
1345 #ifdef WXTEST_ATL
1346                             int w, int h
1347 #else
1348                             int WXUNUSED(w), int WXUNUSED(h)
1349 #endif
1350                             )
1351 {
1352 #ifdef WXTEST_ATL
1353     m_wndView.MoveWindow(0,0,w,h);
1354 #endif
1355 }
1356 
1357 //---------------------------------------------------------------------------
1358 // wxWMP10MediaBackend::GetDownloadProgress()
1359 //---------------------------------------------------------------------------
GetDownloadProgress()1360 wxLongLong wxWMP10MediaBackend::GetDownloadProgress()
1361 {
1362     IWMPNetwork* pWMPNetwork;
1363     if( m_pWMPPlayer->get_network(&pWMPNetwork) == 0 )
1364     {
1365         long lPercentProg;
1366         if(pWMPNetwork->get_downloadProgress(&lPercentProg) == 0)
1367         {
1368             pWMPNetwork->Release();
1369             return (GetDownloadTotal() * lPercentProg) / 100;
1370         }
1371         pWMPNetwork->Release();
1372     }
1373     return 0;
1374 }
1375 
1376 //---------------------------------------------------------------------------
1377 // wxWMP10MediaBackend::GetDownloadTotal()
1378 //---------------------------------------------------------------------------
GetDownloadTotal()1379 wxLongLong wxWMP10MediaBackend::GetDownloadTotal()
1380 {
1381     IWMPMedia* pWMPMedia;
1382     if(m_pWMPPlayer->get_currentMedia(&pWMPMedia) == 0)
1383     {
1384         BSTR bsOut;
1385         pWMPMedia->getItemInfo(wxBasicString(wxS("FileSize")),
1386                                &bsOut);
1387 
1388         wxString sFileSize = wxConvertStringFromOle(bsOut);
1389         long lFS;
1390         sFileSize.ToLong(&lFS);
1391         pWMPMedia->Release();
1392         return lFS;
1393     }
1394 
1395     return 0;
1396 }
1397 
1398 
1399 //---------------------------------------------------------------------------
1400 // wxWMP10MediaBackend::OnActiveX
1401 //
1402 // Handle events sent from our activex control (_WMPOCXEvents actually).
1403 //
1404 // The weird numbers in the switch statement here are "dispatch ids"
1405 // (the numbers in the id field like ( id(xxx) ) ) from amcompat.idl
1406 // and wmp.IDL.
1407 //---------------------------------------------------------------------------
1408 #ifndef WXTEST_ATL
OnActiveX(wxActiveXEvent & event)1409 void wxWMP10MediaEvtHandler::OnActiveX(wxActiveXEvent& event)
1410 {
1411     switch(event.GetDispatchId())
1412     {
1413     case 0x000013ed: // playstatechange
1414         if(event.ParamCount() >= 1)
1415         {
1416             switch (event[0].GetInteger())
1417             {
1418             case wmppsMediaEnded: // media ended
1419                 if ( m_amb->SendStopEvent() )
1420                 {
1421                     // NB: If we do Stop() or similar here the media
1422                     // actually starts over and plays a bit before
1423                     // stopping. It stops by default, however, so
1424                     // there is no real need to do anything here...
1425 
1426                     // send the event to our child
1427                     m_amb->QueueFinishEvent();
1428                 }
1429                 break;
1430 
1431             case wmppsStopped: // stopping
1432                 m_amb->QueueStopEvent();
1433                 break;
1434             case wmppsPaused: // pause
1435                 m_amb->QueuePauseEvent();
1436                 break;
1437             case wmppsPlaying: // play
1438                 m_amb->QueuePlayEvent();
1439                 break;
1440             default:
1441                 break;
1442             }
1443         }
1444         else
1445             event.Skip();
1446         break;
1447 
1448     case 0x00001389: // openstatechange
1449         if(event.ParamCount() >= 1)
1450         {
1451             int nState = event[0].GetInteger();
1452             if(nState == wmposMediaOpen)
1453             {
1454                 // See the "introduction"
1455                 m_amb->m_bWasStateChanged = false;
1456                 m_amb->FinishLoad();
1457                 if(!m_amb->m_bWasStateChanged)
1458                     m_amb->Stop();
1459             }
1460         }
1461         else
1462             event.Skip();
1463         break;
1464 
1465     case 0x0000196e: // mousedown
1466         m_amb->m_ctrl->SetFocus();
1467         break;
1468 
1469     default:
1470         event.Skip();
1471         return;
1472     }
1473 }
1474 
1475 #endif
1476 
1477 // Allow the user code to use wxFORCE_LINK_MODULE() to ensure that this object
1478 // file is not discarded by the linker.
1479 #include "wx/link.h"
1480 wxFORCE_LINK_THIS_MODULE(wxmediabackend_wmp10)
1481 
1482 #endif // wxUSE_MEDIACTRL && wxUSE_ACTIVEX
1483