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