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