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