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