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