]> git.saurik.com Git - wxWidgets.git/blame - src/msw/mediactrl.cpp
Do not allow events to fire after socket is closed (fixes crash on GTK with GDK_Input...
[wxWidgets.git] / src / msw / mediactrl.cpp
CommitLineData
1a680109
RN
1/////////////////////////////////////////////////////////////////////////////
2// Name: msw/mediactrl.cpp
ff4aedc5 3// Purpose: Built-in Media Backends for Windows
1a680109 4// Author: Ryan Norton <wxprojects@comcast.net>
72259e00 5// Modified by:
1a680109
RN
6// Created: 11/07/04
7// RCS-ID: $Id$
8// Copyright: (c) Ryan Norton
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
aa200e97
VZ
12/*
13 FIXME FIXME FIXME:
14 - extract different backends in different files (better yet, make backends
15 dynamically loadable...), they have nothing to do with each other and
16 this file is huge and also separate the standard contents from our code
17 itself
aa200e97
VZ
18 */
19
ff4aedc5
RN
20//===========================================================================
21// DECLARATIONS
22//===========================================================================
23
1a680109 24//---------------------------------------------------------------------------
ff4aedc5 25// Pre-compiled header stuff
1a680109
RN
26//---------------------------------------------------------------------------
27
1a680109
RN
28// For compilers that support precompilation, includes "wx.h".
29#include "wx/wxprec.h"
30
31#ifdef __BORLANDC__
32#pragma hdrstop
33#endif
34
ff4aedc5 35//---------------------------------------------------------------------------
c5191fbd 36// MediaCtrl include
ff4aedc5 37//---------------------------------------------------------------------------
1a680109
RN
38#include "wx/mediactrl.h"
39
ff4aedc5
RN
40//---------------------------------------------------------------------------
41// Compilation guard
42//---------------------------------------------------------------------------
1a680109
RN
43#if wxUSE_MEDIACTRL
44
c5191fbd
VZ
45//---------------------------------------------------------------------------
46// WX Includes
47//---------------------------------------------------------------------------
48#include "wx/log.h" //wxLogDebug
49#include "wx/math.h" //log10 & pow
50#include "wx/msw/private.h" //user info and wndproc setting/getting
3832f946
WS
51#include "wx/dcclient.h"
52#include "wx/timer.h"
40d4efa8 53#include "wx/dynlib.h"
b195b4fa 54
1a680109 55//---------------------------------------------------------------------------
c5191fbd 56// Externals (somewhere in src/msw/app.cpp and src/msw/window.cpp)
1a680109 57//---------------------------------------------------------------------------
ff4aedc5
RN
58extern "C" WXDLLIMPEXP_BASE HINSTANCE wxGetInstance(void);
59#ifdef __WXWINCE__
7a4d2469 60extern WXDLLIMPEXP_CORE wxChar *wxCanvasClassName;
ff4aedc5 61#else
316d19ac 62extern WXDLLIMPEXP_CORE const wxChar *wxCanvasClassName;
ff4aedc5 63#endif
1a680109 64
c5191fbd
VZ
65LRESULT WXDLLIMPEXP_CORE APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
66 WPARAM wParam, LPARAM lParam);
67
ff4aedc5
RN
68//===========================================================================
69// BACKEND DECLARATIONS
70//===========================================================================
1a680109
RN
71
72//---------------------------------------------------------------------------
ff4aedc5
RN
73//
74// wxAMMediaBackend
75//
1a680109
RN
76//---------------------------------------------------------------------------
77
ff4aedc5 78//---------------------------------------------------------------------------
bf354396 79// wxActiveXContainer - includes all the COM-specific stuff we need
920a7c15 80//---------------------------------------------------------------------------
bf354396 81#include "wx/msw/ole/activex.h"
c5191fbd 82
a2a444e3
RN
83//---------------------------------------------------------------------------
84// IIDS - used by CoCreateInstance and IUnknown::QueryInterface
c5191fbd
VZ
85//
86// [idl name] [idl decription]
87// amcompat.idl Microsoft Active Movie Control (Ver 2.0)
88// nscompat.idl Microsoft NetShow Player (Ver 1.0)
89// msdxm.idl Windows Media Player (Ver 1.0)
90// quartz.idl
91//
92// First, when I say I "from XXX.idl", I mean I go into the COM Browser
93// ($Microsoft Visual Studio$/Common/Tools/OLEVIEW.EXE), open
94// "type libraries", open a specific type library (for quartz for example its
95// "ActiveMovie control type library (V1.0)"), save it as an .idl, compile the
96// idl using the midl compiler that comes with visual studio
97// ($Microsoft Visual Studio$/VC98/bin/midl.exe on VC6) with the /h argument
98// to make it generate stubs (a .h & .c file), then clean up the generated
99// interfaces I want with the STDMETHOD wrappers and then put them into
100// mediactrl.cpp.
101//
102// According to the MSDN docs, IMediaPlayer requires Windows 98 SE
103// or greater. NetShow is available on Windows 3.1 and I'm guessing
104// IActiveMovie is too. IMediaPlayer is essentially the Windows Media
105// Player 6.4 SDK.
920a7c15
JS
106//
107// Some of these are not used but are kept here for future reference anyway
a2a444e3 108//---------------------------------------------------------------------------
c5191fbd
VZ
109const IID IID_IActiveMovie = {0x05589FA2,0xC356,0x11CE,{0xBF,0x01,0x00,0xAA,0x00,0x55,0x59,0x5A}};
110const IID IID_IActiveMovie2 = {0xB6CD6554,0xE9CB,0x11D0,{0x82,0x1F,0x00,0xA0,0xC9,0x1F,0x9C,0xA0}};
111const IID IID_IActiveMovie3 = {0x265EC140,0xAE62,0x11D1,{0x85,0x00,0x00,0xA0,0xC9,0x1F,0x9C,0xA0}};
920a7c15 112
c5191fbd
VZ
113const IID IID_INSOPlay = {0x2179C5D1,0xEBFF,0x11CF,{0xB6,0xFD,0x00,0xAA,0x00,0xB4,0xE2,0x20}};
114const IID IID_INSPlay = {0xE7C4BE80,0x7960,0x11D0,{0xB7,0x27,0x00,0xAA,0x00,0xB4,0xE2,0x20}};
115const IID IID_INSPlay1 = {0x265EC141,0xAE62,0x11D1,{0x85,0x00,0x00,0xA0,0xC9,0x1F,0x9C,0xA0}};
116
117const IID IID_IMediaPlayer = {0x22D6F311,0xB0F6,0x11D0,{0x94,0xAB,0x00,0x80,0xC7,0x4C,0x7E,0x95}};
118const IID IID_IMediaPlayer2 = {0x20D4F5E0,0x5475,0x11D2,{0x97,0x74,0x00,0x00,0xF8,0x08,0x55,0xE6}};
a2a444e3 119
c5191fbd
VZ
120const CLSID CLSID_ActiveMovie = {0x05589FA1,0xC356,0x11CE,{0xBF,0x01,0x00,0xAA,0x00,0x55,0x59,0x5A}};
121const CLSID CLSID_MediaPlayer = {0x22D6F312,0xB0F6,0x11D0,{0x94,0xAB,0x00,0x80,0xC7,0x4C,0x7E,0x95}};
122const CLSID CLSID_NSPlay = {0x2179C5D3,0xEBFF,0x11CF,{0xB6,0xFD,0x00,0xAA,0x00,0xB4,0xE2,0x20}};
920a7c15 123
c5191fbd
VZ
124const IID IID_IAMOpenProgress = {0x8E1C39A1, 0xDE53, 0x11CF,{0xAA, 0x63, 0x00, 0x80, 0xC7, 0x44, 0x52, 0x8D}};
125
126// QUARTZ
127const CLSID CLSID_FilgraphManager = {0xE436EBB3,0x524F,0x11CE,{0x9F,0x53,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
128const IID IID_IMediaEvent = {0x56A868B6,0x0AD4,0x11CE,{0xB0,0x3A,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
920a7c15
JS
129
130//?? QUARTZ Also?
c5191fbd
VZ
131const CLSID CLSID_VideoMixingRenderer9 ={0x51B4ABF3, 0x748F, 0x4E3B,{0xA2, 0x76, 0xC8, 0x28, 0x33, 0x0E, 0x92, 0x6A}};
132const IID IID_IVMRWindowlessControl9 = {0x8F537D09, 0xF85E, 0x4414,{0xB2, 0x3B, 0x50, 0x2E, 0x54, 0xC7, 0x99, 0x27}};
920a7c15
JS
133const IID IID_IFilterGraph = {0x56A8689F, 0x0AD4, 0x11CE,{0xB0, 0x3A, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70}};
134const IID IID_IGraphBuilder = {0x56A868A9, 0x0AD4, 0x11CE,{0xB0, 0x3A, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70}};
c5191fbd 135const IID IID_IVMRFilterConfig9 = {0x5A804648, 0x4F66, 0x4867,{0x9C, 0x43, 0x4F, 0x5C, 0x82, 0x2C, 0xF1, 0xB8}};
920a7c15
JS
136const IID IID_IBaseFilter = {0x56A86895, 0x0AD4, 0x11CE,{0xB0, 0x3A, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70}};
137
138//---------------------------------------------------------------------------
c5191fbd 139// QUARTZ COM INTERFACES (dumped from quartz.idl from MSVC COM Browser)
920a7c15 140//---------------------------------------------------------------------------
920a7c15 141
c5191fbd
VZ
142struct IAMOpenProgress : public IUnknown
143{
144 STDMETHOD(QueryProgress)(LONGLONG *pllTotal, LONGLONG *pllCurrent) PURE;
145 STDMETHOD(AbortOperation)(void) PURE;
146};
920a7c15 147
c5191fbd 148struct IMediaEvent : public IDispatch
920a7c15 149{
c5191fbd
VZ
150 STDMETHOD(GetEventHandle)(LONG_PTR *) PURE;
151 STDMETHOD(GetEvent)(long *, LONG_PTR *, LONG_PTR *, long) PURE;
152 STDMETHOD(WaitForCompletion)(long, long *) PURE;
153 STDMETHOD(CancelDefaultHandling)(long) PURE;
154 STDMETHOD(RestoreDefaultHandling)(long) PURE;
155 STDMETHOD(FreeEventParams)(long, LONG_PTR, LONG_PTR) PURE;
a2a444e3
RN
156};
157
c5191fbd
VZ
158//---------------------------------------------------------------------------
159// ACTIVEMOVIE COM INTERFACES (dumped from amcompat.idl from MSVC COM Browser)
160//---------------------------------------------------------------------------
161
162enum ReadyStateConstants
a2a444e3 163{
c5191fbd
VZ
164 amvUninitialized = 0,
165 amvLoading = 1,
166 amvInteractive = 3,
167 amvComplete = 4
a2a444e3
RN
168};
169
c5191fbd
VZ
170enum StateConstants
171{
172 amvNotLoaded = -1,
173 amvStopped = 0,
174 amvPaused = 1,
175 amvRunning = 2
a2a444e3
RN
176};
177
c5191fbd
VZ
178enum DisplayModeConstants
179{
180 amvTime = 0,
181 amvFrames = 1
920a7c15 182};
32f65e50 183
c5191fbd 184enum WindowSizeConstants
a2a444e3 185{
c5191fbd
VZ
186 amvOriginalSize = 0,
187 amvDoubleOriginalSize = 1,
188 amvOneSixteenthScreen = 2,
189 amvOneFourthScreen = 3,
190 amvOneHalfScreen = 4
a2a444e3 191};
b11eba7e 192
c5191fbd 193enum AppearanceConstants
a2a444e3 194{
c5191fbd
VZ
195 amvFlat = 0,
196 amv3D = 1
a2a444e3
RN
197};
198
c5191fbd 199enum BorderStyleConstants
a2a444e3 200{
c5191fbd
VZ
201 amvNone = 0,
202 amvFixedSingle = 1
a2a444e3 203};
b11eba7e 204
c5191fbd 205struct IActiveMovie : public IDispatch
a2a444e3 206{
c5191fbd
VZ
207 STDMETHOD(AboutBox)( void) PURE;
208 STDMETHOD(Run)( void) PURE;
209 STDMETHOD(Pause)( void) PURE;
210 STDMETHOD(Stop)( void) PURE;
211 STDMETHOD(get_ImageSourceWidth)(long __RPC_FAR *pWidth) PURE;
212 STDMETHOD(get_ImageSourceHeight)(long __RPC_FAR *pHeight) PURE;
213 STDMETHOD(get_Author)(BSTR __RPC_FAR *pbstrAuthor) PURE;
214 STDMETHOD(get_Title)(BSTR __RPC_FAR *pbstrTitle) PURE;
215 STDMETHOD(get_Copyright)(BSTR __RPC_FAR *pbstrCopyright) PURE;
216 STDMETHOD(get_Description)(BSTR __RPC_FAR *pbstrDescription) PURE;
217 STDMETHOD(get_Rating)(BSTR __RPC_FAR *pbstrRating) PURE;
218 STDMETHOD(get_FileName)(BSTR __RPC_FAR *pbstrFileName) PURE;
219 STDMETHOD(put_FileName)(BSTR pbstrFileName) PURE;
220 STDMETHOD(get_Duration)(double __RPC_FAR *pValue) PURE;
221 STDMETHOD(get_CurrentPosition)(double __RPC_FAR *pValue) PURE;
222 STDMETHOD(put_CurrentPosition)(double pValue) PURE;
223 STDMETHOD(get_PlayCount)(long __RPC_FAR *pPlayCount) PURE;
224 STDMETHOD(put_PlayCount)(long pPlayCount) PURE;
225 STDMETHOD(get_SelectionStart)(double __RPC_FAR *pValue) PURE;
226 STDMETHOD(put_SelectionStart)(double pValue) PURE;
227 STDMETHOD(get_SelectionEnd)(double __RPC_FAR *pValue) PURE;
228 STDMETHOD(put_SelectionEnd)(double pValue) PURE;
229 STDMETHOD(get_CurrentState)(StateConstants __RPC_FAR *pState) PURE;
230 STDMETHOD(get_Rate)(double __RPC_FAR *pValue) PURE;
231 STDMETHOD(put_Rate)(double pValue) PURE;
232 STDMETHOD(get_Volume)(long __RPC_FAR *pValue) PURE;
233 STDMETHOD(put_Volume)(long pValue) PURE;
234 STDMETHOD(get_Balance)(long __RPC_FAR *pValue) PURE;
235 STDMETHOD(put_Balance)(long pValue) PURE;
236 STDMETHOD(get_EnableContextMenu)(VARIANT_BOOL __RPC_FAR *pEnable) PURE;
237 STDMETHOD(put_EnableContextMenu)(VARIANT_BOOL pEnable) PURE;
238 STDMETHOD(get_ShowDisplay)(VARIANT_BOOL __RPC_FAR *Show) PURE;
239 STDMETHOD(put_ShowDisplay)(VARIANT_BOOL Show) PURE;
240 STDMETHOD(get_ShowControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
241 STDMETHOD(put_ShowControls)(VARIANT_BOOL Show) PURE;
242 STDMETHOD(get_ShowPositionControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
243 STDMETHOD(put_ShowPositionControls)(VARIANT_BOOL Show) PURE;
244 STDMETHOD(get_ShowSelectionControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
245 STDMETHOD(put_ShowSelectionControls)(VARIANT_BOOL Show) PURE;
246 STDMETHOD(get_ShowTracker)(VARIANT_BOOL __RPC_FAR *Show) PURE;
247 STDMETHOD(put_ShowTracker)(VARIANT_BOOL Show) PURE;
248 STDMETHOD(get_EnablePositionControls)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
249 STDMETHOD(put_EnablePositionControls)(VARIANT_BOOL Enable) PURE;
250 STDMETHOD(get_EnableSelectionControls)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
251 STDMETHOD(put_EnableSelectionControls)(VARIANT_BOOL Enable) PURE;
252 STDMETHOD(get_EnableTracker)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
253 STDMETHOD(put_EnableTracker)(VARIANT_BOOL Enable) PURE;
254 STDMETHOD(get_AllowHideDisplay)(VARIANT_BOOL __RPC_FAR *Show) PURE;
255 STDMETHOD(put_AllowHideDisplay)(VARIANT_BOOL Show) PURE;
256 STDMETHOD(get_AllowHideControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
257 STDMETHOD(put_AllowHideControls)(VARIANT_BOOL Show) PURE;
258 STDMETHOD(get_DisplayMode)(DisplayModeConstants __RPC_FAR *pValue) PURE;
259 STDMETHOD(put_DisplayMode)(DisplayModeConstants pValue) PURE;
260 STDMETHOD(get_AllowChangeDisplayMode)(VARIANT_BOOL __RPC_FAR *fAllow) PURE;
261 STDMETHOD(put_AllowChangeDisplayMode)(VARIANT_BOOL fAllow) PURE;
262 STDMETHOD(get_FilterGraph)(IUnknown __RPC_FAR *__RPC_FAR *ppFilterGraph) PURE;
263 STDMETHOD(put_FilterGraph)(IUnknown __RPC_FAR *ppFilterGraph) PURE;
264 STDMETHOD(get_FilterGraphDispatch)(IDispatch __RPC_FAR *__RPC_FAR *pDispatch) PURE;
265 STDMETHOD(get_DisplayForeColor)(unsigned long __RPC_FAR *ForeColor) PURE;
266 STDMETHOD(put_DisplayForeColor)(unsigned long ForeColor) PURE;
267 STDMETHOD(get_DisplayBackColor)(unsigned long __RPC_FAR *BackColor) PURE;
268 STDMETHOD(put_DisplayBackColor)(unsigned long BackColor) PURE;
269 STDMETHOD(get_MovieWindowSize)(WindowSizeConstants __RPC_FAR *WindowSize) PURE;
270 STDMETHOD(put_MovieWindowSize)(WindowSizeConstants WindowSize) PURE;
271 STDMETHOD(get_FullScreenMode)(VARIANT_BOOL __RPC_FAR *pEnable) PURE;
272 STDMETHOD(put_FullScreenMode)(VARIANT_BOOL pEnable) PURE;
273 STDMETHOD(get_AutoStart)(VARIANT_BOOL __RPC_FAR *pEnable) PURE;
274 STDMETHOD(put_AutoStart)(VARIANT_BOOL pEnable) PURE;
275 STDMETHOD(get_AutoRewind)(VARIANT_BOOL __RPC_FAR *pEnable) PURE;
276 STDMETHOD(put_AutoRewind)(VARIANT_BOOL pEnable) PURE;
277 STDMETHOD(get_hWnd)(long __RPC_FAR *hWnd) PURE;
278 STDMETHOD(get_Appearance)(AppearanceConstants __RPC_FAR *pAppearance) PURE;
279 STDMETHOD(put_Appearance)(AppearanceConstants pAppearance) PURE;
280 STDMETHOD(get_BorderStyle)(BorderStyleConstants __RPC_FAR *pBorderStyle) PURE;
281 STDMETHOD(put_BorderStyle)(BorderStyleConstants pBorderStyle) PURE;
282 STDMETHOD(get_Enabled)(VARIANT_BOOL __RPC_FAR *pEnabled) PURE;
283 STDMETHOD(put_Enabled)(VARIANT_BOOL pEnabled) PURE;
284 STDMETHOD(get_Info)(long __RPC_FAR *ppInfo) PURE;
920a7c15 285};
b11eba7e 286
c5191fbd
VZ
287
288
289struct IActiveMovie2 : public IActiveMovie
290{
291 STDMETHOD(IsSoundCardEnabled)(VARIANT_BOOL __RPC_FAR *pbSoundCard) PURE;
292 STDMETHOD(get_ReadyState)(ReadyStateConstants __RPC_FAR *pValue) PURE;
a2a444e3 293};
1a680109 294
c5191fbd 295struct IActiveMovie3 : public IActiveMovie2
a2a444e3 296{
c5191fbd 297 STDMETHOD(get_MediaPlayer)(IDispatch __RPC_FAR *__RPC_FAR *ppDispatch) PURE;
a2a444e3 298};
b11eba7e 299
c5191fbd 300
920a7c15 301//---------------------------------------------------------------------------
c5191fbd 302// MEDIAPLAYER COM INTERFACES (dumped from msdxm.idl from MSVC COM Browser)
920a7c15 303//---------------------------------------------------------------------------
c5191fbd
VZ
304
305enum MPPlayStateConstants
a2a444e3 306{
c5191fbd
VZ
307 mpStopped = 0,
308 mpPaused = 1,
309 mpPlaying = 2,
310 mpWaiting = 3,
311 mpScanForward = 4,
312 mpScanReverse = 5,
313 mpClosed = 6
920a7c15 314};
b11eba7e 315
c5191fbd
VZ
316enum MPDisplaySizeConstants
317{
318 mpDefaultSize = 0,
319 mpHalfSize = 1,
320 mpDoubleSize = 2,
321 mpFullScreen = 3,
322 mpFitToSize = 4,
323 mpOneSixteenthScreen = 5,
324 mpOneFourthScreen = 6,
325 mpOneHalfScreen = 7
a2a444e3 326};
b11eba7e 327
c5191fbd 328enum MPReadyStateConstants
a2a444e3 329{
c5191fbd
VZ
330 mpReadyStateUninitialized = 0,
331 mpReadyStateLoading = 1,
332 mpReadyStateInteractive = 3,
333 mpReadyStateComplete = 4
a2a444e3
RN
334};
335
c5191fbd
VZ
336typedef unsigned long VB_OLE_COLOR;
337
338enum MPDisplayModeConstants
a2a444e3 339{
c5191fbd
VZ
340 mpTime = 0,
341 mpFrames = 1
920a7c15 342};
b11eba7e 343
c5191fbd
VZ
344enum MPMoreInfoType
345{
346 mpShowURL = 0,
347 mpClipURL = 1,
348 mpBannerURL = 2
a2a444e3 349};
b11eba7e 350
c5191fbd 351enum MPMediaInfoType
a2a444e3 352{
c5191fbd
VZ
353 mpShowFilename = 0,
354 mpShowTitle = 1,
355 mpShowAuthor = 2,
356 mpShowCopyright = 3,
357 mpShowRating = 4,
358 mpShowDescription = 5,
359 mpShowLogoIcon = 6,
360 mpClipFilename = 7,
361 mpClipTitle = 8,
362 mpClipAuthor = 9,
363 mpClipCopyright = 10,
364 mpClipRating = 11,
365 mpClipDescription = 12,
366 mpClipLogoIcon = 13,
367 mpBannerImage = 14,
368 mpBannerMoreInfo = 15,
369 mpWatermark = 16
370};
371
372enum DVDMenuIDConstants
373{
374 dvdMenu_Title = 2,
375 dvdMenu_Root = 3,
376 dvdMenu_Subpicture = 4,
377 dvdMenu_Audio = 5,
378 dvdMenu_Angle = 6,
379 dvdMenu_Chapter = 7
380};
381
382enum MPShowDialogConstants
383{
384 mpShowDialogHelp = 0,
385 mpShowDialogStatistics = 1,
386 mpShowDialogOptions = 2,
387 mpShowDialogContextMenu = 3
388};
389
390
391struct IMediaPlayer : public IDispatch
392{
393 STDMETHOD(get_CurrentPosition)(double __RPC_FAR *pCurrentPosition) PURE;
394 STDMETHOD(put_CurrentPosition)(double pCurrentPosition) PURE;
395 STDMETHOD(get_Duration)(double __RPC_FAR *pDuration) PURE;
396 STDMETHOD(get_ImageSourceWidth)(long __RPC_FAR *pWidth) PURE;
397 STDMETHOD(get_ImageSourceHeight)(long __RPC_FAR *pHeight) PURE;
398 STDMETHOD(get_MarkerCount)(long __RPC_FAR *pMarkerCount) PURE;
399 STDMETHOD(get_CanScan)(VARIANT_BOOL __RPC_FAR *pCanScan) PURE;
400 STDMETHOD(get_CanSeek)(VARIANT_BOOL __RPC_FAR *pCanSeek) PURE;
401 STDMETHOD(get_CanSeekToMarkers)(VARIANT_BOOL __RPC_FAR *pCanSeekToMarkers) PURE;
402 STDMETHOD(get_CurrentMarker)(long __RPC_FAR *pCurrentMarker) PURE;
403 STDMETHOD(put_CurrentMarker)(long pCurrentMarker) PURE;
404 STDMETHOD(get_FileName)(BSTR __RPC_FAR *pbstrFileName) PURE;
405 STDMETHOD(put_FileName)(BSTR pbstrFileName) PURE;
406 STDMETHOD(get_SourceLink)(BSTR __RPC_FAR *pbstrSourceLink) PURE;
407 STDMETHOD(get_CreationDate)(DATE __RPC_FAR *pCreationDate) PURE;
408 STDMETHOD(get_ErrorCorrection)(BSTR __RPC_FAR *pbstrErrorCorrection) PURE;
409 STDMETHOD(get_Bandwidth)(long __RPC_FAR *pBandwidth) PURE;
410 STDMETHOD(get_SourceProtocol)(long __RPC_FAR *pSourceProtocol) PURE;
411 STDMETHOD(get_ReceivedPackets)(long __RPC_FAR *pReceivedPackets) PURE;
412 STDMETHOD(get_RecoveredPackets)(long __RPC_FAR *pRecoveredPackets) PURE;
413 STDMETHOD(get_LostPackets)(long __RPC_FAR *pLostPackets) PURE;
414 STDMETHOD(get_ReceptionQuality)(long __RPC_FAR *pReceptionQuality) PURE;
415 STDMETHOD(get_BufferingCount)(long __RPC_FAR *pBufferingCount) PURE;
416 STDMETHOD(get_IsBroadcast)(VARIANT_BOOL __RPC_FAR *pIsBroadcast) PURE;
417 STDMETHOD(get_BufferingProgress)(long __RPC_FAR *pBufferingProgress) PURE;
418 STDMETHOD(get_ChannelName)(BSTR __RPC_FAR *pbstrChannelName) PURE;
419 STDMETHOD(get_ChannelDescription)(BSTR __RPC_FAR *pbstrChannelDescription) PURE;
420 STDMETHOD(get_ChannelURL)(BSTR __RPC_FAR *pbstrChannelURL) PURE;
421 STDMETHOD(get_ContactAddress)(BSTR __RPC_FAR *pbstrContactAddress) PURE;
422 STDMETHOD(get_ContactPhone)(BSTR __RPC_FAR *pbstrContactPhone) PURE;
423 STDMETHOD(get_ContactEmail)(BSTR __RPC_FAR *pbstrContactEmail) PURE;
424 STDMETHOD(get_BufferingTime)(double __RPC_FAR *pBufferingTime) PURE;
425 STDMETHOD(put_BufferingTime)(double pBufferingTime) PURE;
426 STDMETHOD(get_AutoStart)(VARIANT_BOOL __RPC_FAR *pAutoStart) PURE;
427 STDMETHOD(put_AutoStart)(VARIANT_BOOL pAutoStart) PURE;
428 STDMETHOD(get_AutoRewind)(VARIANT_BOOL __RPC_FAR *pAutoRewind) PURE;
429 STDMETHOD(put_AutoRewind)(VARIANT_BOOL pAutoRewind) PURE;
430 STDMETHOD(get_Rate)(double __RPC_FAR *pRate) PURE;
431 STDMETHOD(put_Rate)(double pRate) PURE;
432 STDMETHOD(get_SendKeyboardEvents)(VARIANT_BOOL __RPC_FAR *pSendKeyboardEvents) PURE;
433 STDMETHOD(put_SendKeyboardEvents)(VARIANT_BOOL pSendKeyboardEvents) PURE;
434 STDMETHOD(get_SendMouseClickEvents)(VARIANT_BOOL __RPC_FAR *pSendMouseClickEvents) PURE;
435 STDMETHOD(put_SendMouseClickEvents)(VARIANT_BOOL pSendMouseClickEvents) PURE;
436 STDMETHOD(get_SendMouseMoveEvents)(VARIANT_BOOL __RPC_FAR *pSendMouseMoveEvents) PURE;
437 STDMETHOD(put_SendMouseMoveEvents)(VARIANT_BOOL pSendMouseMoveEvents) PURE;
438 STDMETHOD(get_PlayCount)(long __RPC_FAR *pPlayCount) PURE;
439 STDMETHOD(put_PlayCount)(long pPlayCount) PURE;
440 STDMETHOD(get_ClickToPlay)(VARIANT_BOOL __RPC_FAR *pClickToPlay) PURE;
441 STDMETHOD(put_ClickToPlay)(VARIANT_BOOL pClickToPlay) PURE;
442 STDMETHOD(get_AllowScan)(VARIANT_BOOL __RPC_FAR *pAllowScan) PURE;
443 STDMETHOD(put_AllowScan)(VARIANT_BOOL pAllowScan) PURE;
444 STDMETHOD(get_EnableContextMenu)(VARIANT_BOOL __RPC_FAR *pEnableContextMenu) PURE;
445 STDMETHOD(put_EnableContextMenu)(VARIANT_BOOL pEnableContextMenu) PURE;
446 STDMETHOD(get_CursorType)(long __RPC_FAR *pCursorType) PURE;
447 STDMETHOD(put_CursorType)(long pCursorType) PURE;
448 STDMETHOD(get_CodecCount)(long __RPC_FAR *pCodecCount) PURE;
449 STDMETHOD(get_AllowChangeDisplaySize)(VARIANT_BOOL __RPC_FAR *pAllowChangeDisplaySize) PURE;
450 STDMETHOD(put_AllowChangeDisplaySize)( VARIANT_BOOL pAllowChangeDisplaySize) PURE;
451 STDMETHOD(get_IsDurationValid)(VARIANT_BOOL __RPC_FAR *pIsDurationValid) PURE;
452 STDMETHOD(get_OpenState)(long __RPC_FAR *pOpenState) PURE;
453 STDMETHOD(get_SendOpenStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendOpenStateChangeEvents) PURE;
454 STDMETHOD(put_SendOpenStateChangeEvents)(VARIANT_BOOL pSendOpenStateChangeEvents) PURE;
455 STDMETHOD(get_SendWarningEvents)( VARIANT_BOOL __RPC_FAR *pSendWarningEvents) PURE;
456 STDMETHOD(put_SendWarningEvents)(VARIANT_BOOL pSendWarningEvents) PURE;
457 STDMETHOD(get_SendErrorEvents)(VARIANT_BOOL __RPC_FAR *pSendErrorEvents) PURE;
458 STDMETHOD(put_SendErrorEvents)(VARIANT_BOOL pSendErrorEvents) PURE;
459 STDMETHOD(get_PlayState)(MPPlayStateConstants __RPC_FAR *pPlayState) PURE;
460 STDMETHOD(get_SendPlayStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendPlayStateChangeEvents) PURE;
461 STDMETHOD(put_SendPlayStateChangeEvents)(VARIANT_BOOL pSendPlayStateChangeEvents) PURE;
462 STDMETHOD(get_DisplaySize)(MPDisplaySizeConstants __RPC_FAR *pDisplaySize) PURE;
463 STDMETHOD(put_DisplaySize)(MPDisplaySizeConstants pDisplaySize) PURE;
464 STDMETHOD(get_InvokeURLs)(VARIANT_BOOL __RPC_FAR *pInvokeURLs) PURE;
465 STDMETHOD(put_InvokeURLs)(VARIANT_BOOL pInvokeURLs) PURE;
466 STDMETHOD(get_BaseURL)(BSTR __RPC_FAR *pbstrBaseURL) PURE;
467 STDMETHOD(put_BaseURL)(BSTR pbstrBaseURL) PURE;
468 STDMETHOD(get_DefaultFrame)(BSTR __RPC_FAR *pbstrDefaultFrame) PURE;
469 STDMETHOD(put_DefaultFrame)(BSTR pbstrDefaultFrame) PURE;
470 STDMETHOD(get_HasError)(VARIANT_BOOL __RPC_FAR *pHasError) PURE;
471 STDMETHOD(get_ErrorDescription)(BSTR __RPC_FAR *pbstrErrorDescription) PURE;
472 STDMETHOD(get_ErrorCode)(long __RPC_FAR *pErrorCode) PURE;
473 STDMETHOD(get_AnimationAtStart)(VARIANT_BOOL __RPC_FAR *pAnimationAtStart) PURE;
474 STDMETHOD(put_AnimationAtStart)(VARIANT_BOOL pAnimationAtStart) PURE;
475 STDMETHOD(get_TransparentAtStart)( VARIANT_BOOL __RPC_FAR *pTransparentAtStart) PURE;
476 STDMETHOD(put_TransparentAtStart)(VARIANT_BOOL pTransparentAtStart) PURE;
477 STDMETHOD(get_Volume)(long __RPC_FAR *pVolume) PURE;
478 STDMETHOD(put_Volume)(long pVolume) PURE;
479 STDMETHOD(get_Balance)(long __RPC_FAR *pBalance) PURE;
480 STDMETHOD(put_Balance)(long pBalance) PURE;
481 STDMETHOD(get_ReadyState)(MPReadyStateConstants __RPC_FAR *pValue) PURE;
482 STDMETHOD(get_SelectionStart)(double __RPC_FAR *pValue) PURE;
483 STDMETHOD(put_SelectionStart)(double pValue) PURE;
484 STDMETHOD(get_SelectionEnd)(double __RPC_FAR *pValue) PURE;
485 STDMETHOD(put_SelectionEnd)(double pValue) PURE;
486 STDMETHOD(get_ShowDisplay)(VARIANT_BOOL __RPC_FAR *Show) PURE;
487 STDMETHOD(put_ShowDisplay)(VARIANT_BOOL Show) PURE;
488 STDMETHOD(get_ShowControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
489 STDMETHOD(put_ShowControls)(VARIANT_BOOL Show) PURE;
490 STDMETHOD(get_ShowPositionControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
491 STDMETHOD(put_ShowPositionControls)(VARIANT_BOOL Show) PURE;
492 STDMETHOD(get_ShowTracker)(VARIANT_BOOL __RPC_FAR *Show) PURE;
493 STDMETHOD(put_ShowTracker)(VARIANT_BOOL Show) PURE;
494 STDMETHOD(get_EnablePositionControls)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
495 STDMETHOD(put_EnablePositionControls)(VARIANT_BOOL Enable) PURE;
496 STDMETHOD(get_EnableTracker)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
497 STDMETHOD(put_EnableTracker)(VARIANT_BOOL Enable) PURE;
498 STDMETHOD(get_Enabled)(VARIANT_BOOL __RPC_FAR *pEnabled) PURE;
499 STDMETHOD(put_Enabled)(VARIANT_BOOL pEnabled) PURE;
500 STDMETHOD(get_DisplayForeColor)(VB_OLE_COLOR __RPC_FAR *ForeColor) PURE;
501 STDMETHOD(put_DisplayForeColor)(VB_OLE_COLOR ForeColor) PURE;
502 STDMETHOD(get_DisplayBackColor)(VB_OLE_COLOR __RPC_FAR *BackColor) PURE;
503 STDMETHOD(put_DisplayBackColor)(VB_OLE_COLOR BackColor) PURE;
504 STDMETHOD(get_DisplayMode)(MPDisplayModeConstants __RPC_FAR *pValue) PURE;
505 STDMETHOD(put_DisplayMode)(MPDisplayModeConstants pValue) PURE;
506 STDMETHOD(get_VideoBorder3D)(VARIANT_BOOL __RPC_FAR *pVideoBorderWidth) PURE;
507 STDMETHOD(put_VideoBorder3D)(VARIANT_BOOL pVideoBorderWidth) PURE;
508 STDMETHOD(get_VideoBorderWidth)(long __RPC_FAR *pVideoBorderWidth) PURE;
509 STDMETHOD(put_VideoBorderWidth)(long pVideoBorderWidth) PURE;
510 STDMETHOD(get_VideoBorderColor)(VB_OLE_COLOR __RPC_FAR *pVideoBorderWidth) PURE;
511 STDMETHOD(put_VideoBorderColor)(VB_OLE_COLOR pVideoBorderWidth) PURE;
512 STDMETHOD(get_ShowGotoBar)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
513 STDMETHOD(put_ShowGotoBar)(VARIANT_BOOL pbool) PURE;
514 STDMETHOD(get_ShowStatusBar)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
515 STDMETHOD(put_ShowStatusBar)(VARIANT_BOOL pbool) PURE;
516 STDMETHOD(get_ShowCaptioning)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
517 STDMETHOD(put_ShowCaptioning)(VARIANT_BOOL pbool) PURE;
518 STDMETHOD(get_ShowAudioControls)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
519 STDMETHOD(put_ShowAudioControls)(VARIANT_BOOL pbool) PURE;
520 STDMETHOD(get_CaptioningID)( BSTR __RPC_FAR *pstrText) PURE;
521 STDMETHOD(put_CaptioningID)(BSTR pstrText) PURE;
522 STDMETHOD(get_Mute)(VARIANT_BOOL __RPC_FAR *vbool) PURE;
523 STDMETHOD(put_Mute)(VARIANT_BOOL vbool) PURE;
524 STDMETHOD(get_CanPreview)(VARIANT_BOOL __RPC_FAR *pCanPreview) PURE;
525 STDMETHOD(get_PreviewMode)(VARIANT_BOOL __RPC_FAR *pPreviewMode) PURE;
526 STDMETHOD(put_PreviewMode)(VARIANT_BOOL pPreviewMode) PURE;
527 STDMETHOD(get_HasMultipleItems)(VARIANT_BOOL __RPC_FAR *pHasMuliItems) PURE;
528 STDMETHOD(get_Language)(long __RPC_FAR *pLanguage) PURE;
529 STDMETHOD(put_Language)(long pLanguage) PURE;
530 STDMETHOD(get_AudioStream)(long __RPC_FAR *pStream) PURE;
531 STDMETHOD(put_AudioStream)(long pStream) PURE;
532 STDMETHOD(get_SAMIStyle)(BSTR __RPC_FAR *pbstrStyle) PURE;
533 STDMETHOD(put_SAMIStyle)(BSTR pbstrStyle) PURE;
534 STDMETHOD(get_SAMILang)(BSTR __RPC_FAR *pbstrLang) PURE;
535 STDMETHOD(put_SAMILang)(BSTR pbstrLang) PURE;
536 STDMETHOD(get_SAMIFileName)(BSTR __RPC_FAR *pbstrFileName) PURE;
537 STDMETHOD(put_SAMIFileName)(BSTR pbstrFileName) PURE;
538 STDMETHOD(get_StreamCount)( long __RPC_FAR *pStreamCount) PURE;
539 STDMETHOD(get_ClientId)(BSTR __RPC_FAR *pbstrClientId) PURE;
540 STDMETHOD(get_ConnectionSpeed)(long __RPC_FAR *plConnectionSpeed) PURE;
541 STDMETHOD(get_AutoSize)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
542 STDMETHOD(put_AutoSize)(VARIANT_BOOL pbool) PURE;
543 STDMETHOD(get_EnableFullScreenControls)(VARIANT_BOOL __RPC_FAR *pbVal) PURE;
544 STDMETHOD(put_EnableFullScreenControls)(VARIANT_BOOL pbVal) PURE;
545 STDMETHOD(get_ActiveMovie)(IDispatch __RPC_FAR *__RPC_FAR *ppdispatch) PURE;
546 STDMETHOD(get_NSPlay)(IDispatch __RPC_FAR *__RPC_FAR *ppdispatch) PURE;
547 STDMETHOD(get_WindowlessVideo)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
548 STDMETHOD(put_WindowlessVideo)(VARIANT_BOOL pbool) PURE;
549 STDMETHOD(Play)(void) PURE;
550 STDMETHOD(Stop)(void) PURE;
551 STDMETHOD(Pause)(void) PURE;
552 STDMETHOD(GetMarkerTime)(long MarkerNum,
553 double __RPC_FAR *pMarkerTime) PURE;
554 STDMETHOD(GetMarkerName)(long MarkerNum,
555 BSTR __RPC_FAR *pbstrMarkerName) PURE;
556 STDMETHOD(AboutBox)(void) PURE;
557 STDMETHOD(GetCodecInstalled)(long CodecNum,
558 VARIANT_BOOL __RPC_FAR *pCodecInstalled) PURE;
559 STDMETHOD(GetCodecDescription)(long CodecNum,
560 BSTR __RPC_FAR *pbstrCodecDescription) PURE;
561 STDMETHOD(GetCodecURL)(long CodecNum,
562 BSTR __RPC_FAR *pbstrCodecURL) PURE;
563 STDMETHOD(GetMoreInfoURL)(MPMoreInfoType MoreInfoType,
564 BSTR __RPC_FAR *pbstrMoreInfoURL) PURE;
565 STDMETHOD(GetMediaInfoString)(MPMediaInfoType MediaInfoType,
566 BSTR __RPC_FAR *pbstrMediaInfo) PURE;
567 STDMETHOD(Cancel)(void) PURE;
568 STDMETHOD(Open)(BSTR bstrFileName) PURE;
569 STDMETHOD(IsSoundCardEnabled)(VARIANT_BOOL __RPC_FAR *pbSoundCard) PURE;
570 STDMETHOD(Next)(void) PURE;
571 STDMETHOD(Previous)(void) PURE;
572 STDMETHOD(StreamSelect)(long StreamNum) PURE;
573 STDMETHOD(FastForward)(void) PURE;
574 STDMETHOD(FastReverse)(void) PURE;
575 STDMETHOD(GetStreamName)(long StreamNum,
576 BSTR __RPC_FAR *pbstrStreamName) PURE;
577 STDMETHOD(GetStreamGroup)(long StreamNum,
578 long __RPC_FAR *pStreamGroup) PURE;
579 STDMETHOD(GetStreamSelected)(long StreamNum, VARIANT_BOOL __RPC_FAR *pStreamSelected) PURE;
580};
581
582struct IMediaPlayer2 : public IMediaPlayer
583{
584 STDMETHOD(get_DVD)(struct IMediaPlayerDvd __RPC_FAR *__RPC_FAR *ppdispatch) PURE;
585 STDMETHOD(GetMediaParameter)(long EntryNum, BSTR bstrParameterName, BSTR __RPC_FAR *pbstrParameterValue) PURE;
586 STDMETHOD(GetMediaParameterName(long EntryNum, long Index, BSTR __RPC_FAR *pbstrParameterName) PURE;
587 STDMETHOD(get_EntryCount)(long __RPC_FAR *pNumberEntries) PURE;
588 STDMETHOD(GetCurrentEntry)(long __RPC_FAR *pEntryNumber) PURE;
589 STDMETHOD(SetCurrentEntry)(long EntryNumber) PURE;
590 STDMETHOD(ShowDialog)(MPShowDialogConstants mpDialogIndex) PURE;
a2a444e3 591};
b11eba7e 592
920a7c15 593//---------------------------------------------------------------------------
c5191fbd 594// NETSHOW COM INTERFACES (dumped from nscompat.idl from MSVC COM Browser)
920a7c15 595//---------------------------------------------------------------------------
c5191fbd
VZ
596
597struct INSOPlay : public IDispatch
598{
599 STDMETHOD(get_ImageSourceWidth)(long __RPC_FAR *pWidth) PURE;
600 STDMETHOD(get_ImageSourceHeight)(long __RPC_FAR *pHeight) PURE;
601 STDMETHOD(get_Duration)(double __RPC_FAR *pDuration) PURE;
602 STDMETHOD(get_Author)(BSTR __RPC_FAR *pbstrAuthor) PURE;
603 STDMETHOD(get_Copyright)(BSTR __RPC_FAR *pbstrCopyright) PURE;
604 STDMETHOD(get_Description)(BSTR __RPC_FAR *pbstrDescription) PURE;
605 STDMETHOD(get_Rating)(BSTR __RPC_FAR *pbstrRating) PURE;
606 STDMETHOD(get_Title)(BSTR __RPC_FAR *pbstrTitle) PURE;
607 STDMETHOD(get_SourceLink)(BSTR __RPC_FAR *pbstrSourceLink) PURE;
608 STDMETHOD(get_MarkerCount)(long __RPC_FAR *pMarkerCount) PURE;
609 STDMETHOD(get_CanScan)(VARIANT_BOOL __RPC_FAR *pCanScan) PURE;
610 STDMETHOD(get_CanSeek)(VARIANT_BOOL __RPC_FAR *pCanSeek) PURE;
611 STDMETHOD(get_CanSeekToMarkers)(VARIANT_BOOL __RPC_FAR *pCanSeekToMarkers) PURE;
612 STDMETHOD(get_CreationDate)(DATE __RPC_FAR *pCreationDate) PURE;
613 STDMETHOD(get_Bandwidth)(long __RPC_FAR *pBandwidth) PURE;
614 STDMETHOD(get_ErrorCorrection)(BSTR __RPC_FAR *pbstrErrorCorrection) PURE;
615 STDMETHOD(get_AutoStart)(VARIANT_BOOL __RPC_FAR *pAutoStart) PURE;
616 STDMETHOD(put_AutoStart)(VARIANT_BOOL pAutoStart) PURE;
617 STDMETHOD(get_AutoRewind)(VARIANT_BOOL __RPC_FAR *pAutoRewind) PURE;
618 STDMETHOD(put_AutoRewind)(VARIANT_BOOL pAutoRewind) PURE;
619 STDMETHOD(get_AllowChangeControlType)(VARIANT_BOOL __RPC_FAR *pAllowChangeControlType) PURE;
620 STDMETHOD(put_AllowChangeControlType)(VARIANT_BOOL pAllowChangeControlType) PURE;
621 STDMETHOD(get_InvokeURLs)(VARIANT_BOOL __RPC_FAR *pInvokeURLs) PURE;
622 STDMETHOD(put_InvokeURLs)(VARIANT_BOOL pInvokeURLs) PURE;
623 STDMETHOD(get_EnableContextMenu)(VARIANT_BOOL __RPC_FAR *pEnableContextMenu) PURE;
624 STDMETHOD(put_EnableContextMenu)(VARIANT_BOOL pEnableContextMenu) PURE;
625 STDMETHOD(get_TransparentAtStart)(VARIANT_BOOL __RPC_FAR *pTransparentAtStart) PURE;
626 STDMETHOD(put_TransparentAtStart)(VARIANT_BOOL pTransparentAtStart) PURE;
627 STDMETHOD(get_TransparentOnStop)(VARIANT_BOOL __RPC_FAR *pTransparentOnStop) PURE;
628 STDMETHOD(put_TransparentOnStop)(VARIANT_BOOL pTransparentOnStop) PURE;
629 STDMETHOD(get_ClickToPlay)(VARIANT_BOOL __RPC_FAR *pClickToPlay) PURE;
630 STDMETHOD(put_ClickToPlay)(VARIANT_BOOL pClickToPlay) PURE;
631 STDMETHOD(get_FileName)(BSTR __RPC_FAR *pbstrFileName) PURE;
632 STDMETHOD(put_FileName)(BSTR pbstrFileName) PURE;
633 STDMETHOD(get_CurrentPosition)(double __RPC_FAR *pCurrentPosition) PURE;
634 STDMETHOD(put_CurrentPosition)(double pCurrentPosition) PURE;
635 STDMETHOD(get_Rate)(double __RPC_FAR *pRate) PURE;
636 STDMETHOD(put_Rate)(double pRate) PURE;
637 STDMETHOD(get_CurrentMarker)(long __RPC_FAR *pCurrentMarker) PURE;
638 STDMETHOD(put_CurrentMarker)(long pCurrentMarker) PURE;
639 STDMETHOD(get_PlayCount)(long __RPC_FAR *pPlayCount) PURE;
640 STDMETHOD(put_PlayCount)(long pPlayCount) PURE;
641 STDMETHOD(get_CurrentState)(long __RPC_FAR *pCurrentState) PURE;
642 STDMETHOD(get_DisplaySize)(long __RPC_FAR *pDisplaySize) PURE;
643 STDMETHOD(put_DisplaySize)(long pDisplaySize) PURE;
644 STDMETHOD(get_MainWindow)(long __RPC_FAR *pMainWindow) PURE;
645 STDMETHOD(get_ControlType)(long __RPC_FAR *pControlType) PURE;
646 STDMETHOD(put_ControlType)(long pControlType) PURE;
647 STDMETHOD(get_AllowScan)(VARIANT_BOOL __RPC_FAR *pAllowScan) PURE;
648 STDMETHOD(put_AllowScan)(VARIANT_BOOL pAllowScan) PURE;
649 STDMETHOD(get_SendKeyboardEvents)(VARIANT_BOOL __RPC_FAR *pSendKeyboardEvents) PURE;
650 STDMETHOD(put_SendKeyboardEvents)(VARIANT_BOOL pSendKeyboardEvents) PURE;
651 STDMETHOD(get_SendMouseClickEvents)(VARIANT_BOOL __RPC_FAR *pSendMouseClickEvents) PURE;
652 STDMETHOD(put_SendMouseClickEvents)(VARIANT_BOOL pSendMouseClickEvents) PURE;
653 STDMETHOD(get_SendMouseMoveEvents)(VARIANT_BOOL __RPC_FAR *pSendMouseMoveEvents) PURE;
654 STDMETHOD(put_SendMouseMoveEvents)(VARIANT_BOOL pSendMouseMoveEvents) PURE;
655 STDMETHOD(get_SendStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendStateChangeEvents) PURE;
656 STDMETHOD(put_SendStateChangeEvents)(VARIANT_BOOL pSendStateChangeEvents) PURE;
657 STDMETHOD(get_ReceivedPackets)(long __RPC_FAR *pReceivedPackets) PURE;
658 STDMETHOD(get_RecoveredPackets)(long __RPC_FAR *pRecoveredPackets) PURE;
659 STDMETHOD(get_LostPackets)(long __RPC_FAR *pLostPackets) PURE;
660 STDMETHOD(get_ReceptionQuality)(long __RPC_FAR *pReceptionQuality) PURE;
661 STDMETHOD(get_BufferingCount)(long __RPC_FAR *pBufferingCount) PURE;
662 STDMETHOD(get_CursorType)(long __RPC_FAR *pCursorType) PURE;
663 STDMETHOD(put_CursorType)(long pCursorType) PURE;
664 STDMETHOD(get_AnimationAtStart)(VARIANT_BOOL __RPC_FAR *pAnimationAtStart) PURE;
665 STDMETHOD(put_AnimationAtStart)(VARIANT_BOOL pAnimationAtStart) PURE;
666 STDMETHOD(get_AnimationOnStop)(VARIANT_BOOL __RPC_FAR *pAnimationOnStop) PURE;
667 STDMETHOD(put_AnimationOnStop)(VARIANT_BOOL pAnimationOnStop) PURE;
668 STDMETHOD(Play)(void) PURE;
669 STDMETHOD(Pause)(void) PURE;
670 STDMETHOD(Stop)(void) PURE;
671 STDMETHOD(GetMarkerTime)(long MarkerNum, double __RPC_FAR *pMarkerTime) PURE;
672 STDMETHOD(GetMarkerName)(long MarkerNum, BSTR __RPC_FAR *pbstrMarkerName) PURE;
920a7c15 673};
b11eba7e 674
c5191fbd
VZ
675struct INSPlay : public INSOPlay
676{
677 STDMETHOD(get_ChannelName)(BSTR __RPC_FAR *pbstrChannelName) PURE;
678 STDMETHOD(get_ChannelDescription)(BSTR __RPC_FAR *pbstrChannelDescription) PURE;
679 STDMETHOD(get_ChannelURL)(BSTR __RPC_FAR *pbstrChannelURL) PURE;
680 STDMETHOD(get_ContactAddress)(BSTR __RPC_FAR *pbstrContactAddress) PURE;
681 STDMETHOD(get_ContactPhone)(BSTR __RPC_FAR *pbstrContactPhone) PURE;
682 STDMETHOD(get_ContactEmail)(BSTR __RPC_FAR *pbstrContactEmail) PURE;
683 STDMETHOD(get_AllowChangeDisplaySize)(VARIANT_BOOL __RPC_FAR *pAllowChangeDisplaySize) PURE;
684 STDMETHOD(put_AllowChangeDisplaySize)(VARIANT_BOOL pAllowChangeDisplaySize) PURE;
685 STDMETHOD(get_CodecCount)(long __RPC_FAR *pCodecCount) PURE;
686 STDMETHOD(get_IsBroadcast)(VARIANT_BOOL __RPC_FAR *pIsBroadcast) PURE;
687 STDMETHOD(get_IsDurationValid)(VARIANT_BOOL __RPC_FAR *pIsDurationValid) PURE;
688 STDMETHOD(get_SourceProtocol)(long __RPC_FAR *pSourceProtocol) PURE;
689 STDMETHOD(get_OpenState)(long __RPC_FAR *pOpenState) PURE;
690 STDMETHOD(get_SendOpenStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendOpenStateChangeEvents) PURE;
691 STDMETHOD(put_SendOpenStateChangeEvents)(VARIANT_BOOL pSendOpenStateChangeEvents) PURE;
692 STDMETHOD(get_SendWarningEvents)(VARIANT_BOOL __RPC_FAR *pSendWarningEvents) PURE;
693 STDMETHOD(put_SendWarningEvents)(VARIANT_BOOL pSendWarningEvents) PURE;
694 STDMETHOD(get_SendErrorEvents)(VARIANT_BOOL __RPC_FAR *pSendErrorEvents) PURE;
695 STDMETHOD(put_SendErrorEvents)(VARIANT_BOOL pSendErrorEvents) PURE;
696 STDMETHOD(get_HasError)(VARIANT_BOOL __RPC_FAR *pHasError) PURE;
697 STDMETHOD(get_ErrorDescription)(BSTR __RPC_FAR *pbstrErrorDescription) PURE;
698 STDMETHOD(get_ErrorCode)(long __RPC_FAR *pErrorCode) PURE;
699 STDMETHOD(get_PlayState)(long __RPC_FAR *pPlayState) PURE;
700 STDMETHOD(get_SendPlayStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendPlayStateChangeEvents) PURE;
701 STDMETHOD(put_SendPlayStateChangeEvents)(VARIANT_BOOL pSendPlayStateChangeEvents) PURE;
702 STDMETHOD(get_BufferingTime)(double __RPC_FAR *pBufferingTime) PURE;
703 STDMETHOD(put_BufferingTime)(double pBufferingTime) PURE;
704 STDMETHOD(get_UseFixedUDPPort)(VARIANT_BOOL __RPC_FAR *pUseFixedUDPPort) PURE;
705 STDMETHOD(put_UseFixedUDPPort)(VARIANT_BOOL pUseFixedUDPPort) PURE;
706 STDMETHOD(get_FixedUDPPort)(long __RPC_FAR *pFixedUDPPort) PURE;
707 STDMETHOD(put_FixedUDPPort)(long pFixedUDPPort) PURE;
708 STDMETHOD(get_UseHTTPProxy)(VARIANT_BOOL __RPC_FAR *pUseHTTPProxy) PURE;
709 STDMETHOD(put_UseHTTPProxy)(VARIANT_BOOL pUseHTTPProxy) PURE;
710 STDMETHOD(get_EnableAutoProxy)(VARIANT_BOOL __RPC_FAR *pEnableAutoProxy) PURE;
711 STDMETHOD(put_EnableAutoProxy)(VARIANT_BOOL pEnableAutoProxy) PURE;
712 STDMETHOD(get_HTTPProxyHost)(BSTR __RPC_FAR *pbstrHTTPProxyHost) PURE;
713 STDMETHOD(put_HTTPProxyHost)(BSTR pbstrHTTPProxyHost) PURE;
714 STDMETHOD(get_HTTPProxyPort)(long __RPC_FAR *pHTTPProxyPort) PURE;
715 STDMETHOD(put_HTTPProxyPort)(long pHTTPProxyPort) PURE;
716 STDMETHOD(get_EnableMulticast)(VARIANT_BOOL __RPC_FAR *pEnableMulticast) PURE;
717 STDMETHOD(put_EnableMulticast)(VARIANT_BOOL pEnableMulticast) PURE;
718 STDMETHOD(get_EnableUDP)(VARIANT_BOOL __RPC_FAR *pEnableUDP) PURE;
719 STDMETHOD(put_EnableUDP)(VARIANT_BOOL pEnableUDP) PURE;
720 STDMETHOD(get_EnableTCP)(VARIANT_BOOL __RPC_FAR *pEnableTCP) PURE;
721 STDMETHOD(put_EnableTCP)(VARIANT_BOOL pEnableTCP) PURE;
722 STDMETHOD(get_EnableHTTP)(VARIANT_BOOL __RPC_FAR *pEnableHTTP) PURE;
723 STDMETHOD(put_EnableHTTP)(VARIANT_BOOL pEnableHTTP) PURE;
724 STDMETHOD(get_BufferingProgress)(long __RPC_FAR *pBufferingProgress) PURE;
725 STDMETHOD(get_BaseURL)(BSTR __RPC_FAR *pbstrBaseURL) PURE;
726 STDMETHOD(put_BaseURL)(BSTR pbstrBaseURL) PURE;
727 STDMETHOD(get_DefaultFrame)(BSTR __RPC_FAR *pbstrDefaultFrame) PURE;
728 STDMETHOD(put_DefaultFrame)(BSTR pbstrDefaultFrame) PURE;
729 STDMETHOD(AboutBox))(void) PURE;
730 STDMETHOD(Cancel)(void) PURE;
731 STDMETHOD(GetCodecInstalled)(long CodecNum, VARIANT_BOOL __RPC_FAR *pCodecInstalled) PURE;
732 STDMETHOD(GetCodecDescription)(long CodecNum, BSTR __RPC_FAR *pbstrCodecDescription) PURE;
733 STDMETHOD(GetCodecURL)(long CodecNum, BSTR __RPC_FAR *pbstrCodecURL) PURE;
734 STDMETHOD(Open)(BSTR bstrFileName) PURE;
735};
b11eba7e 736
c5191fbd
VZ
737
738struct INSPlay1 : public INSPlay
920a7c15 739{
c5191fbd 740 STDMETHOD(get_MediaPlayer)(IDispatch __RPC_FAR *__RPC_FAR *ppdispatch) PURE;
920a7c15 741};
32f65e50 742
c5191fbd
VZ
743//---------------------------------------------------------------------------
744// MISC COM INTERFACES
745//---------------------------------------------------------------------------
746typedef enum _FilterState
747{
748 State_Stopped,
749 State_Paused,
750 State_Running
751} FILTER_STATE;
752typedef enum _PinDirection {
753 PINDIR_INPUT,
754 PINDIR_OUTPUT
755} PIN_DIRECTION;
756
757typedef struct _FilterInfo {
758 WCHAR achName[128];
759 struct IFilterGraph *pGraph;
760} FILTER_INFO;
761
762typedef struct _PinInfo {
763 struct IBaseFilter *pFilter;
764 PIN_DIRECTION dir;
765 WCHAR achName[128];
766} PIN_INFO;
767
768struct IBaseFilter;
769struct IPin;
770struct IEnumFilters;
771typedef struct _MediaType {
772 GUID majortype;
773 GUID subtype;
774 BOOL bFixedSizeSamples;
775 BOOL bTemporalCompression;
776 ULONG lSampleSize;
777 GUID formattype;
778 IUnknown *pUnk;
779 ULONG cbFormat;
780 BYTE *pbFormat;
781} AM_MEDIA_TYPE;
920a7c15
JS
782
783struct IFilterGraph : public IUnknown
784{
785 STDMETHOD(AddFilter)(IBaseFilter *, LPCWSTR) PURE;
786 STDMETHOD(RemoveFilter)(IBaseFilter *) PURE;
787 STDMETHOD(EnumFilters)(IEnumFilters **) PURE;
788 STDMETHOD(FindFilterByName)(LPCWSTR, IBaseFilter **) PURE;
789 STDMETHOD(ConnectDirect)(IPin *, IPin *, const AM_MEDIA_TYPE *) PURE;
790 STDMETHOD(Reconnect)(IPin *) PURE;
791 STDMETHOD(Disconnect)(IPin *) PURE;
792 STDMETHOD(SetDefaultSyncSource)() PURE;
a2a444e3 793};
b11eba7e 794
920a7c15 795struct IGraphBuilder : public IFilterGraph
a2a444e3 796{
920a7c15
JS
797 STDMETHOD(Connect)(IPin *, IPin *) PURE;
798 STDMETHOD(Render)(IPin *) PURE;
799 STDMETHOD(RenderFile)(LPCWSTR, LPCWSTR) PURE;
800 STDMETHOD(AddSourceFilter)(LPCWSTR, LPCWSTR, IBaseFilter **) PURE;
801 STDMETHOD(SetLogFile)(DWORD_PTR) PURE;
802 STDMETHOD(Abort)() PURE;
803 STDMETHOD(ShouldOperationContinue)() PURE;
a2a444e3 804};
b11eba7e 805
c5191fbd
VZ
806struct IReferenceClock;
807struct IEnumPins;
808#define REFERENCE_TIME LONGLONG
809struct IMediaFilter : public IPersist
810{
811 STDMETHOD(Stop)( void) PURE;
812 STDMETHOD(Pause)( void) PURE;
813 STDMETHOD(Run)(REFERENCE_TIME tStart) PURE;
814 STDMETHOD(GetState)(DWORD dwMilliSecsTimeout,
815 FILTER_STATE *State) PURE;
816 STDMETHOD(SetSyncSource)(IReferenceClock *pClock) PURE;
817 STDMETHOD(GetSyncSource)(IReferenceClock **pClock) PURE;
818};
819
820struct IBaseFilter : public IMediaFilter
a2a444e3 821{
c5191fbd
VZ
822 STDMETHOD(EnumPins)(IEnumPins **ppEnum) PURE;
823 STDMETHOD(FindPin)(LPCWSTR Id, IPin **ppPin) PURE;
824 STDMETHOD(QueryFilterInfo)(FILTER_INFO *pInfo) PURE;
825 STDMETHOD(JoinFilterGraph)(IFilterGraph *pGraph, LPCWSTR pName) PURE;
826 STDMETHOD(QueryVendorInfo)(LPWSTR *pVendorInfo) PURE;
827};
828
c5191fbd
VZ
829
830//###########################################################################
831//
832//
833// wxAMMediaBackend
834//
835//
836//###########################################################################
837
838typedef BOOL (WINAPI* LPAMGETERRORTEXT)(HRESULT, wxChar *, DWORD);
839
7e41b689 840class WXDLLIMPEXP_MEDIA wxAMMediaBackend : public wxMediaBackendCommonBase
1a680109
RN
841{
842public:
ff4aedc5 843 wxAMMediaBackend();
ff4aedc5 844 virtual ~wxAMMediaBackend();
c5191fbd 845 void Clear();
1a680109 846
226ec5a7 847 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
ff4aedc5 848 wxWindowID id,
226ec5a7 849 const wxPoint& pos,
ff4aedc5 850 const wxSize& size,
226ec5a7 851 long style,
ff4aedc5
RN
852 const wxValidator& validator,
853 const wxString& name);
1a680109
RN
854
855 virtual bool Play();
856 virtual bool Pause();
857 virtual bool Stop();
858
859 virtual bool Load(const wxString& fileName);
860 virtual bool Load(const wxURI& location);
c5191fbd
VZ
861 virtual bool Load(const wxURI& location, const wxURI& proxy);
862
863 bool DoLoad(const wxString& location);
864 void FinishLoad();
1a680109
RN
865
866 virtual wxMediaState GetState();
867
ff4aedc5
RN
868 virtual bool SetPosition(wxLongLong where);
869 virtual wxLongLong GetPosition();
870 virtual wxLongLong GetDuration();
1a680109 871
ff4aedc5
RN
872 virtual void Move(int x, int y, int w, int h);
873 wxSize GetVideoSize() const;
1a680109
RN
874
875 virtual double GetPlaybackRate();
876 virtual bool SetPlaybackRate(double);
877
6f8c67e7
JS
878 virtual double GetVolume();
879 virtual bool SetVolume(double);
880
c5191fbd 881 virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags);
1a680109 882 void Cleanup();
920a7c15 883
c5191fbd
VZ
884 void DoGetDownloadProgress(wxLongLong*, wxLongLong*);
885 virtual wxLongLong GetDownloadProgress()
886 {
887 wxLongLong progress, total;
888 DoGetDownloadProgress(&progress, &total);
889 return progress;
890 }
891 virtual wxLongLong GetDownloadTotal()
892 {
893 wxLongLong progress, total;
894 DoGetDownloadProgress(&progress, &total);
895 return total;
896 }
1a680109 897
bf354396 898 wxActiveXContainer* m_pAX;
c5191fbd
VZ
899 IActiveMovie* m_pAM;
900 IMediaPlayer* m_pMP;
901 wxTimer* m_pTimer;
1a680109 902 wxSize m_bestSize;
aa200e97 903
920a7c15 904#ifdef __WXDEBUG__
aa200e97 905 wxDynamicLibrary m_dllQuartz;
920a7c15 906 LPAMGETERRORTEXT m_lpAMGetErrorText;
a3c1ce50 907 wxString GetErrorString(HRESULT hrdsv);
aa200e97 908#endif // __WXDEBUG__
920a7c15 909
19b6f122 910 DECLARE_DYNAMIC_CLASS(wxAMMediaBackend)
1a680109
RN
911};
912
1a680109 913//---------------------------------------------------------------------------
ff4aedc5
RN
914//
915// wxMCIMediaBackend
916//
1a680109
RN
917//---------------------------------------------------------------------------
918
ff4aedc5
RN
919//---------------------------------------------------------------------------
920// MCI Includes
921//---------------------------------------------------------------------------
1a680109 922#include <mmsystem.h>
1a680109 923
7e41b689 924class WXDLLIMPEXP_MEDIA wxMCIMediaBackend : public wxMediaBackendCommonBase
1a680109
RN
925{
926public:
3f9a3bf9 927
ff4aedc5
RN
928 wxMCIMediaBackend();
929 ~wxMCIMediaBackend();
1a680109 930
226ec5a7 931 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
ff4aedc5 932 wxWindowID id,
226ec5a7 933 const wxPoint& pos,
ff4aedc5 934 const wxSize& size,
226ec5a7 935 long style,
ff4aedc5
RN
936 const wxValidator& validator,
937 const wxString& name);
1a680109
RN
938
939 virtual bool Play();
940 virtual bool Pause();
941 virtual bool Stop();
942
3832f946
WS
943 virtual bool Load(const wxURI& location,
944 const wxURI& proxy)
945 { return wxMediaBackend::Load(location, proxy); }
946
1a680109
RN
947 virtual bool Load(const wxString& fileName);
948 virtual bool Load(const wxURI& location);
949
950 virtual wxMediaState GetState();
951
ff4aedc5
RN
952 virtual bool SetPosition(wxLongLong where);
953 virtual wxLongLong GetPosition();
954 virtual wxLongLong GetDuration();
1a680109 955
ff4aedc5
RN
956 virtual void Move(int x, int y, int w, int h);
957 wxSize GetVideoSize() const;
1a680109
RN
958
959 virtual double GetPlaybackRate();
ff4aedc5 960 virtual bool SetPlaybackRate(double dRate);
3f9a3bf9 961
6f8c67e7
JS
962 virtual double GetVolume();
963 virtual bool SetVolume(double);
964
226ec5a7 965 static LRESULT CALLBACK NotifyWndProc(HWND hWnd, UINT nMsg,
ff4aedc5 966 WPARAM wParam, LPARAM lParam);
5987f174 967
226ec5a7 968 LRESULT CALLBACK OnNotifyWndProc(HWND hWnd, UINT nMsg,
ff4aedc5 969 WPARAM wParam, LPARAM lParam);
1a680109 970
ff4aedc5 971 MCIDEVICEID m_hDev; //Our MCI Device ID/Handler
ff4aedc5
RN
972 HWND m_hNotifyWnd; //Window to use for MCI events
973 bool m_bVideo; //Whether or not we have video
974
3839f37e 975 DECLARE_DYNAMIC_CLASS(wxMCIMediaBackend)
ff4aedc5 976};
1a680109
RN
977
978//---------------------------------------------------------------------------
979//
ff4aedc5 980// wxQTMediaBackend
1a680109 981//
c5191fbd
VZ
982// We don't include Quicktime headers here and define all the types
983// ourselves because looking for the quicktime libaries etc. would
984// be tricky to do and making this a dependency for the MSVC projects
985// would be unrealistic.
986//
987// Thanks to Robert Roebling for the wxDL macro/library idea
1a680109
RN
988//---------------------------------------------------------------------------
989
ff4aedc5
RN
990//---------------------------------------------------------------------------
991// QT Includes
992//---------------------------------------------------------------------------
d7a9c895
RN
993//#include <qtml.h> //Windoze QT include
994//#include <QuickTimeComponents.h> //Standard QT stuff
995#include "wx/dynlib.h"
996
997//---------------------------------------------------------------------------
998// QT Types
999//---------------------------------------------------------------------------
1000typedef struct MovieRecord* Movie;
1001typedef wxInt16 OSErr;
1002typedef wxInt32 OSStatus;
1003#define noErr 0
1004#define fsRdPerm 1
1005typedef unsigned char Str255[256];
1006#define StringPtr unsigned char*
1007#define newMovieActive 1
c5191fbd 1008#define newMovieAsyncOK (1 << 8)
b11eba7e 1009#define Ptr char*
d7a9c895
RN
1010#define Handle Ptr*
1011#define Fixed long
1012#define OSType unsigned long
b11eba7e 1013#define CGrafPtr struct GrafPort *
d7a9c895 1014#define TimeScale long
b11eba7e 1015#define TimeBase struct TimeBaseRecord *
c5191fbd
VZ
1016typedef struct ComponentInstanceRecord * ComponentInstance;
1017#define kMovieLoadStatePlayable 10000
1018#define Boolean int
1019#define MovieController ComponentInstance
d7a9c895 1020
19b6f122
WS
1021#ifndef URLDataHandlerSubType
1022#if defined(__WATCOMC__) || defined(__MINGW32__)
1023// use magic numbers for compilers which complain about multicharacter integers
1024const OSType URLDataHandlerSubType = 1970433056;
1025const OSType VisualMediaCharacteristic = 1702454643;
1026#else
1027const OSType URLDataHandlerSubType = 'url ';
1028const OSType VisualMediaCharacteristic = 'eyes';
1029#endif
1030#endif
1031
d7a9c895 1032struct FSSpec {
600ffb32
WS
1033 short vRefNum;
1034 long parID;
1035 Str255 name; /*Str63 on mac, Str255 on msw */
d7a9c895
RN
1036};
1037
1038struct Rect {
600ffb32
WS
1039 short top;
1040 short left;
1041 short bottom;
1042 short right;
d7a9c895
RN
1043};
1044
1045struct wide {
600ffb32
WS
1046 wxInt32 hi;
1047 wxUint32 lo;
d7a9c895
RN
1048};
1049
1050struct TimeRecord {
600ffb32
WS
1051 wide value; /* units */
1052 TimeScale scale; /* units per second */
1053 TimeBase base;
d7a9c895
RN
1054};
1055
c5191fbd
VZ
1056struct Point {
1057 short v;
1058 short h;
1059};
1060
1061struct EventRecord {
1062 wxUint16 what;
1063 wxUint32 message;
1064 wxUint32 when;
1065 Point where;
1066 wxUint16 modifiers;
1067};
1068
1069enum {
1070 mcTopLeftMovie = 1,
1071 mcScaleMovieToFit = 2,
1072 mcWithBadge = 4,
1073 mcNotVisible = 8,
1074 mcWithFrame = 16
1075};
1076
d7a9c895
RN
1077//---------------------------------------------------------------------------
1078// QT Library
1079//---------------------------------------------------------------------------
1080#define wxDL_METHOD_DEFINE( rettype, name, args, shortargs, defret ) \
1081 typedef rettype (* name ## Type) args ; \
1082 name ## Type pfn_ ## name; \
1083 rettype name args \
1084 { if (m_ok) return pfn_ ## name shortargs ; return defret; }
b11eba7e 1085
d7a9c895
RN
1086#define wxDL_VOIDMETHOD_DEFINE( name, args, shortargs ) \
1087 typedef void (* name ## Type) args ; \
1088 name ## Type pfn_ ## name; \
1089 void name args \
1090 { if (m_ok) pfn_ ## name shortargs ; }
1091
1092#define wxDL_METHOD_LOAD( lib, name, success ) \
1093 pfn_ ## name = (name ## Type) lib.GetSymbol( wxT(#name), &success ); \
3131207f 1094 if (!success) { wxLog::EnableLogging(bWasLoggingEnabled); return false; }
32f65e50 1095
d7a9c895 1096
b11eba7e 1097class WXDLLIMPEXP_MEDIA wxQuickTimeLibrary
d7a9c895
RN
1098{
1099public:
1100 ~wxQuickTimeLibrary()
b11eba7e 1101 {
d7a9c895
RN
1102 if(m_dll.IsLoaded())
1103 m_dll.Unload();
1104 }
1105
1106 bool Initialize();
1107 bool IsOk() const {return m_ok;}
1108
1109protected:
1110 wxDynamicLibrary m_dll;
1111 bool m_ok;
1112
1113public:
1114 wxDL_VOIDMETHOD_DEFINE( StartMovie, (Movie m), (m) );
1115 wxDL_VOIDMETHOD_DEFINE( StopMovie, (Movie m), (m) );
1116 wxDL_METHOD_DEFINE( bool, IsMovieDone, (Movie m), (m), false);
1117 wxDL_VOIDMETHOD_DEFINE( GoToBeginningOfMovie, (Movie m), (m) );
1118 wxDL_METHOD_DEFINE( OSErr, GetMoviesError, (), (), -1);
1119 wxDL_METHOD_DEFINE( OSErr, EnterMovies, (), (), -1);
1120 wxDL_VOIDMETHOD_DEFINE( ExitMovies, (), () );
1121 wxDL_METHOD_DEFINE( OSErr, InitializeQTML, (long flags), (flags), -1);
1122 wxDL_VOIDMETHOD_DEFINE( TerminateQTML, (), () );
1123
b11eba7e
WS
1124 wxDL_METHOD_DEFINE( OSErr, NativePathNameToFSSpec,
1125 (char* inName, FSSpec* outFile, long flags),
d7a9c895
RN
1126 (inName, outFile, flags), -1);
1127
b11eba7e 1128 wxDL_METHOD_DEFINE( OSErr, OpenMovieFile,
d7a9c895
RN
1129 (const FSSpec * fileSpec, short * resRefNum, wxInt8 permission),
1130 (fileSpec, resRefNum, permission), -1 );
1131
1132 wxDL_METHOD_DEFINE( OSErr, CloseMovieFile,
1133 (short resRefNum), (resRefNum), -1);
1134
1135 wxDL_METHOD_DEFINE( OSErr, NewMovieFromFile,
1136 (Movie * theMovie, short resRefNum, short * resId,
1137 StringPtr resName, short newMovieFlags,
b11eba7e 1138 bool * dataRefWasChanged),
d7a9c895
RN
1139 (theMovie, resRefNum, resId, resName, newMovieFlags,
1140 dataRefWasChanged), -1);
1141
1142 wxDL_VOIDMETHOD_DEFINE( SetMovieRate, (Movie m, Fixed rate), (m, rate) );
1143 wxDL_METHOD_DEFINE( Fixed, GetMovieRate, (Movie m), (m), 0);
1144 wxDL_VOIDMETHOD_DEFINE( MoviesTask, (Movie m, long maxms), (m, maxms) );
b11eba7e 1145 wxDL_VOIDMETHOD_DEFINE( BlockMove,
d7a9c895
RN
1146 (const char* p1, const char* p2, long s), (p1,p2,s) );
1147 wxDL_METHOD_DEFINE( Handle, NewHandleClear, (long s), (s), NULL );
1148
b11eba7e 1149 wxDL_METHOD_DEFINE( OSErr, NewMovieFromDataRef,
d7a9c895
RN
1150 (Movie * m, short flags, short * id,
1151 Handle dataRef, OSType dataRefType),
1152 (m,flags,id,dataRef,dataRefType), -1 );
1153
1154 wxDL_VOIDMETHOD_DEFINE( DisposeHandle, (Handle h), (h) );
1155 wxDL_VOIDMETHOD_DEFINE( GetMovieNaturalBoundsRect, (Movie m, Rect* r), (m,r) );
b11eba7e
WS
1156 wxDL_METHOD_DEFINE( void*, GetMovieIndTrackType,
1157 (Movie m, long index, OSType type, long flags),
d7a9c895 1158 (m,index,type,flags), NULL );
b11eba7e 1159 wxDL_VOIDMETHOD_DEFINE( CreatePortAssociation,
d7a9c895
RN
1160 (void* hWnd, void* junk, long morejunk), (hWnd, junk, morejunk) );
1161 wxDL_METHOD_DEFINE(void*, GetNativeWindowPort, (void* hWnd), (hWnd), NULL);
1162 wxDL_VOIDMETHOD_DEFINE(SetMovieGWorld, (Movie m, CGrafPtr port, void* whatever),
1163 (m, port, whatever) );
1164 wxDL_VOIDMETHOD_DEFINE(DisposeMovie, (Movie m), (m) );
1165 wxDL_VOIDMETHOD_DEFINE(SetMovieBox, (Movie m, Rect* r), (m,r));
1166 wxDL_VOIDMETHOD_DEFINE(SetMovieTimeScale, (Movie m, long s), (m,s));
1167 wxDL_METHOD_DEFINE(long, GetMovieDuration, (Movie m), (m), 0);
1168 wxDL_METHOD_DEFINE(TimeBase, GetMovieTimeBase, (Movie m), (m), 0);
1169 wxDL_METHOD_DEFINE(TimeScale, GetMovieTimeScale, (Movie m), (m), 0);
1170 wxDL_METHOD_DEFINE(long, GetMovieTime, (Movie m, void* cruft), (m,cruft), 0);
1171 wxDL_VOIDMETHOD_DEFINE(SetMovieTime, (Movie m, TimeRecord* tr), (m,tr) );
6f8c67e7
JS
1172 wxDL_METHOD_DEFINE(short, GetMovieVolume, (Movie m), (m), 0);
1173 wxDL_VOIDMETHOD_DEFINE(SetMovieVolume, (Movie m, short sVolume), (m,sVolume) );
c5191fbd
VZ
1174 wxDL_VOIDMETHOD_DEFINE(SetMovieTimeValue, (Movie m, long s), (m,s));
1175 wxDL_METHOD_DEFINE(ComponentInstance, NewMovieController, (Movie m, const Rect* mr, long fl), (m,mr,fl), 0);
1176 wxDL_VOIDMETHOD_DEFINE(DisposeMovieController, (ComponentInstance ci), (ci));
1177 wxDL_METHOD_DEFINE(int, MCSetVisible, (ComponentInstance m, int b), (m, b), 0);
1178
1179
1180 wxDL_VOIDMETHOD_DEFINE(PrePrerollMovie, (Movie m, long t, Fixed r, WXFARPROC p1, void* p2), (m,t,r,p1,p2) );
1181 wxDL_VOIDMETHOD_DEFINE(PrerollMovie, (Movie m, long t, Fixed r), (m,t,r) );
1182 wxDL_METHOD_DEFINE(Fixed, GetMoviePreferredRate, (Movie m), (m), 0);
1183 wxDL_METHOD_DEFINE(long, GetMovieLoadState, (Movie m), (m), 0);
1184 wxDL_METHOD_DEFINE(void*, NewRoutineDescriptor, (WXFARPROC f, int l, void* junk), (f, l, junk), 0);
1185 wxDL_VOIDMETHOD_DEFINE(DisposeRoutineDescriptor, (void* f), (f));
1186 wxDL_METHOD_DEFINE(void*, GetCurrentArchitecture, (), (), 0);
1187 wxDL_METHOD_DEFINE(int, MCDoAction, (ComponentInstance ci, long f, void* p), (ci,f,p), 0);
1188 wxDL_VOIDMETHOD_DEFINE(MCSetControllerBoundsRect, (ComponentInstance ci, Rect* r), (ci,r));
1189 wxDL_VOIDMETHOD_DEFINE(DestroyPortAssociation, (CGrafPtr g), (g));
1190 wxDL_VOIDMETHOD_DEFINE(NativeEventToMacEvent, (MSG* p1, EventRecord* p2), (p1,p2));
1191 wxDL_VOIDMETHOD_DEFINE(MCIsPlayerEvent, (ComponentInstance ci, EventRecord* p2), (ci, p2));
fbfb8bcc 1192 wxDL_METHOD_DEFINE(int, MCSetMovie, (ComponentInstance ci, Movie m, void* p1, const Point& w),
c5191fbd
VZ
1193 (ci,m,p1,w),0);
1194 wxDL_VOIDMETHOD_DEFINE(MCPositionController,
1195 (ComponentInstance ci, Rect* r, void* junk, void* morejunk), (ci,r,junk,morejunk));
1196 wxDL_VOIDMETHOD_DEFINE(MCSetActionFilterWithRefCon,
1197 (ComponentInstance ci, WXFARPROC cb, void* ref), (ci,cb,ref));
1198 wxDL_VOIDMETHOD_DEFINE(MCGetControllerInfo, (MovieController mc, long* flags), (mc,flags));
1199 wxDL_VOIDMETHOD_DEFINE(BeginUpdate, (CGrafPtr port), (port));
1200 wxDL_VOIDMETHOD_DEFINE(UpdateMovie, (Movie m), (m));
1201 wxDL_VOIDMETHOD_DEFINE(EndUpdate, (CGrafPtr port), (port));
1202 wxDL_METHOD_DEFINE( OSErr, GetMoviesStickyError, (), (), -1);
d7a9c895
RN
1203};
1204
1205bool wxQuickTimeLibrary::Initialize()
1206{
1207 m_ok = false;
1208
3131207f 1209 bool bWasLoggingEnabled = wxLog::EnableLogging(false); //Turn off the wxDynamicLibrary logging
32f65e50 1210
d7a9c895 1211 if(!m_dll.Load(wxT("qtmlClient.dll")))
32f65e50 1212 {
3131207f 1213 wxLog::EnableLogging(bWasLoggingEnabled);
d7a9c895 1214 return false;
32f65e50 1215 }
d7a9c895 1216
c5191fbd
VZ
1217 wxDL_METHOD_LOAD( m_dll, StartMovie, m_ok );
1218 wxDL_METHOD_LOAD( m_dll, StopMovie, m_ok );
1219 wxDL_METHOD_LOAD( m_dll, IsMovieDone, m_ok );
1220 wxDL_METHOD_LOAD( m_dll, GoToBeginningOfMovie, m_ok );
1221 wxDL_METHOD_LOAD( m_dll, GetMoviesError, m_ok );
1222 wxDL_METHOD_LOAD( m_dll, EnterMovies, m_ok );
1223 wxDL_METHOD_LOAD( m_dll, ExitMovies, m_ok );
1224 wxDL_METHOD_LOAD( m_dll, InitializeQTML, m_ok );
1225 wxDL_METHOD_LOAD( m_dll, TerminateQTML, m_ok );
1226 wxDL_METHOD_LOAD( m_dll, NativePathNameToFSSpec, m_ok );
1227 wxDL_METHOD_LOAD( m_dll, OpenMovieFile, m_ok );
1228 wxDL_METHOD_LOAD( m_dll, CloseMovieFile, m_ok );
1229 wxDL_METHOD_LOAD( m_dll, NewMovieFromFile, m_ok );
1230 wxDL_METHOD_LOAD( m_dll, GetMovieRate, m_ok );
1231 wxDL_METHOD_LOAD( m_dll, SetMovieRate, m_ok );
1232 wxDL_METHOD_LOAD( m_dll, MoviesTask, m_ok );
1233 wxDL_METHOD_LOAD( m_dll, BlockMove, m_ok );
1234 wxDL_METHOD_LOAD( m_dll, NewHandleClear, m_ok );
1235 wxDL_METHOD_LOAD( m_dll, NewMovieFromDataRef, m_ok );
1236 wxDL_METHOD_LOAD( m_dll, DisposeHandle, m_ok );
1237 wxDL_METHOD_LOAD( m_dll, GetMovieNaturalBoundsRect, m_ok );
1238 wxDL_METHOD_LOAD( m_dll, GetMovieIndTrackType, m_ok );
1239 wxDL_METHOD_LOAD( m_dll, CreatePortAssociation, m_ok );
1240 wxDL_METHOD_LOAD( m_dll, DestroyPortAssociation, m_ok );
1241 wxDL_METHOD_LOAD( m_dll, GetNativeWindowPort, m_ok );
1242 wxDL_METHOD_LOAD( m_dll, SetMovieGWorld, m_ok );
1243 wxDL_METHOD_LOAD( m_dll, DisposeMovie, m_ok );
1244 wxDL_METHOD_LOAD( m_dll, SetMovieBox, m_ok );
1245 wxDL_METHOD_LOAD( m_dll, SetMovieTimeScale, m_ok );
1246 wxDL_METHOD_LOAD( m_dll, GetMovieDuration, m_ok );
1247 wxDL_METHOD_LOAD( m_dll, GetMovieTimeBase, m_ok );
1248 wxDL_METHOD_LOAD( m_dll, GetMovieTimeScale, m_ok );
1249 wxDL_METHOD_LOAD( m_dll, GetMovieTime, m_ok );
1250 wxDL_METHOD_LOAD( m_dll, SetMovieTime, m_ok );
1251 wxDL_METHOD_LOAD( m_dll, GetMovieVolume, m_ok );
1252 wxDL_METHOD_LOAD( m_dll, SetMovieVolume, m_ok );
1253 wxDL_METHOD_LOAD( m_dll, SetMovieTimeValue, m_ok );
1254 wxDL_METHOD_LOAD( m_dll, NewMovieController, m_ok );
1255 wxDL_METHOD_LOAD( m_dll, DisposeMovieController, m_ok );
1256 wxDL_METHOD_LOAD( m_dll, MCSetVisible, m_ok );
1257 wxDL_METHOD_LOAD( m_dll, PrePrerollMovie, m_ok );
1258 wxDL_METHOD_LOAD( m_dll, PrerollMovie, m_ok );
1259 wxDL_METHOD_LOAD( m_dll, GetMoviePreferredRate, m_ok );
1260 wxDL_METHOD_LOAD( m_dll, GetMovieLoadState, m_ok );
1261 wxDL_METHOD_LOAD( m_dll, MCDoAction, m_ok );
1262 wxDL_METHOD_LOAD( m_dll, MCSetControllerBoundsRect, m_ok );
1263 wxDL_METHOD_LOAD( m_dll, NativeEventToMacEvent, m_ok );
1264 wxDL_METHOD_LOAD( m_dll, MCIsPlayerEvent, m_ok );
1265 wxDL_METHOD_LOAD( m_dll, MCSetMovie, m_ok );
1266 wxDL_METHOD_LOAD( m_dll, MCSetActionFilterWithRefCon, m_ok );
1267 wxDL_METHOD_LOAD( m_dll, MCGetControllerInfo, m_ok );
1268 wxDL_METHOD_LOAD( m_dll, BeginUpdate, m_ok );
1269 wxDL_METHOD_LOAD( m_dll, UpdateMovie, m_ok );
1270 wxDL_METHOD_LOAD( m_dll, EndUpdate, m_ok );
1271 wxDL_METHOD_LOAD( m_dll, GetMoviesStickyError, m_ok );
b11eba7e 1272
3131207f 1273 wxLog::EnableLogging(bWasLoggingEnabled);
d7a9c895
RN
1274 m_ok = true;
1275
1276 return true;
1277}
1a680109 1278
7e41b689 1279class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackendCommonBase
ff4aedc5
RN
1280{
1281public:
ff4aedc5
RN
1282 wxQTMediaBackend();
1283 ~wxQTMediaBackend();
1a680109 1284
226ec5a7 1285 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
ff4aedc5 1286 wxWindowID id,
226ec5a7 1287 const wxPoint& pos,
ff4aedc5 1288 const wxSize& size,
226ec5a7 1289 long style,
ff4aedc5
RN
1290 const wxValidator& validator,
1291 const wxString& name);
1a680109 1292
ff4aedc5
RN
1293 virtual bool Play();
1294 virtual bool Pause();
1295 virtual bool Stop();
1a680109 1296
3832f946
WS
1297 virtual bool Load(const wxURI& location,
1298 const wxURI& proxy)
1299 { return wxMediaBackend::Load(location, proxy); }
1300
ff4aedc5
RN
1301 virtual bool Load(const wxString& fileName);
1302 virtual bool Load(const wxURI& location);
1a680109 1303
ff4aedc5 1304 virtual wxMediaState GetState();
1a680109 1305
ff4aedc5
RN
1306 virtual bool SetPosition(wxLongLong where);
1307 virtual wxLongLong GetPosition();
1308 virtual wxLongLong GetDuration();
1a680109 1309
ff4aedc5
RN
1310 virtual void Move(int x, int y, int w, int h);
1311 wxSize GetVideoSize() const;
1a680109 1312
ff4aedc5
RN
1313 virtual double GetPlaybackRate();
1314 virtual bool SetPlaybackRate(double dRate);
1a680109 1315
6f8c67e7
JS
1316 virtual double GetVolume();
1317 virtual bool SetVolume(double);
1318
ff4aedc5
RN
1319 void Cleanup();
1320 void FinishLoad();
1a680109 1321
c5191fbd
VZ
1322 static void PPRMProc (Movie theMovie, OSErr theErr, void* theRefCon);
1323 //TODO: Last param actually long - does this work on 64bit machines?
1324 static Boolean MCFilterProc (MovieController theController,
1325 short action, void *params, LONG_PTR refCon);
1326
1327 static LRESULT CALLBACK QTWndProc(HWND, UINT, WPARAM, LPARAM);
1328
1329 virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags);
1330
ff4aedc5 1331 wxSize m_bestSize; //Original movie size
d7a9c895 1332 Movie m_movie; //QT Movie handle/instance
ff4aedc5 1333 bool m_bVideo; //Whether or not we have video
c5191fbd
VZ
1334 bool m_bPlaying; //Whether or not movie is playing
1335 wxTimer* m_timer; //Load or Play timer
1336 wxQuickTimeLibrary m_lib; //DLL to load functions from
1337 ComponentInstance m_pMC; //Movie Controller
d7a9c895 1338
bf354396 1339 friend class wxQTMediaEvtHandler;
19b6f122 1340 DECLARE_DYNAMIC_CLASS(wxQTMediaBackend)
ff4aedc5 1341};
1a680109 1342
6ab9bf57
VZ
1343// helper to hijack background erasing for the QT window
1344class WXDLLIMPEXP_MEDIA wxQTMediaEvtHandler : public wxEvtHandler
1345{
1346public:
7e41b689
VZ
1347 wxQTMediaEvtHandler(wxQTMediaBackend *qtb, WXHWND hwnd)
1348 {
1349 m_qtb = qtb;
1350 m_hwnd = hwnd;
bf354396
VZ
1351
1352 m_qtb->m_ctrl->Connect(m_qtb->m_ctrl->GetId(),
1353 wxEVT_ERASE_BACKGROUND,
1354 wxEraseEventHandler(wxQTMediaEvtHandler::OnEraseBackground),
1355 NULL, this
1356 );
7e41b689 1357 }
6ab9bf57
VZ
1358
1359 void OnEraseBackground(wxEraseEvent& event);
1360
1361private:
1362 wxQTMediaBackend *m_qtb;
7e41b689 1363 WXHWND m_hwnd;
6ab9bf57
VZ
1364
1365 DECLARE_NO_COPY_CLASS(wxQTMediaEvtHandler)
1366};
1367
1a680109 1368
ff4aedc5
RN
1369//===========================================================================
1370// IMPLEMENTATION
1371//===========================================================================
1a680109 1372
ff4aedc5
RN
1373//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1374//
1375// wxAMMediaBackend
1376//
1377//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1a680109 1378
ff4aedc5 1379IMPLEMENT_DYNAMIC_CLASS(wxAMMediaBackend, wxMediaBackend);
1a680109 1380
ff4aedc5
RN
1381//---------------------------------------------------------------------------
1382// Usual debugging macros
1383//---------------------------------------------------------------------------
1384#ifdef __WXDEBUG__
920a7c15 1385#define MAX_ERROR_TEXT_LEN 160
a3c1ce50
JS
1386
1387//Get the error string for Active Movie
1388wxString wxAMMediaBackend::GetErrorString(HRESULT hrdsv)
1389{
32f65e50
WS
1390 wxChar szError[MAX_ERROR_TEXT_LEN];
1391 if( m_lpAMGetErrorText != NULL &&
1392 (*m_lpAMGetErrorText)(hrdsv, szError, MAX_ERROR_TEXT_LEN) == 0)
1393 {
a3c1ce50 1394 return wxString::Format(wxT("DirectShow error \"%s\" \n")
c5191fbd
VZ
1395 wxT("(numeric %X)\n")
1396 wxT("occured"),
1397 szError, (int)hrdsv);
32f65e50
WS
1398 }
1399 else
1400 {
c5191fbd
VZ
1401 return wxString::Format(wxT("Unknown error \n")
1402 wxT("(numeric %X)\n")
1403 wxT("occured"),
1404 (int)hrdsv);
32f65e50 1405 }
1a680109 1406}
a3c1ce50 1407
c5191fbd
VZ
1408#define wxAMFAIL(x) wxFAIL_MSG(GetErrorString(x));
1409#define wxVERIFY(x) wxASSERT((x))
1410#define wxAMLOG(x) wxLogDebug(GetErrorString(x))
1411#else
1412#define wxAMVERIFY(x) (x)
1413#define wxVERIFY(x) (x)
1414#define wxAMLOG(x)
1415#define wxAMFAIL(x)
1416#endif
1417
1418//---------------------------------------------------------------------------
1419// Standard macros for ease of use
1420//---------------------------------------------------------------------------
1421#define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
1422
1423//---------------------------------------------------------------------------
1424// wxAMLoadTimer
1425//
1426// Queries the control periodically to see if it has reached the point
1427// in its loading cycle where we can begin playing the media - if so
1428// then we finish up some things like getting the original size of the video
1429// and then sending the loaded event to our handler
1430//---------------------------------------------------------------------------
1431class wxAMLoadTimer : public wxTimer
1432{
1433public:
1434 wxAMLoadTimer(wxAMMediaBackend* parent) :
1435 m_parent(parent) {}
1436
1437 void Notify()
1438 {
1439 if(m_parent->m_pMP)
1440 {
1441 MPReadyStateConstants nState;
1442 m_parent->m_pMP->get_ReadyState(&nState);
1443 if(nState != mpReadyStateLoading)
1444 {
1445 Stop();
1446 m_parent->FinishLoad();
1447 delete this;
1448 }
1449 }
1450 else
1451 {
1452 IActiveMovie2* pAM2 = NULL;
1453 ReadyStateConstants nState;
1454 if(m_parent->m_pAM->QueryInterface(IID_IActiveMovie2,
1455 (void**)&pAM2) == 0 &&
1456 pAM2->get_ReadyState(&nState) == 0)
1457 {
1458 pAM2->Release();
1459 if(nState != amvLoading)
1460 {
1461 Stop();
1462 m_parent->FinishLoad();
1463 delete this;
1464 }
1465 }
1466 else
1467 {
1468 if(pAM2)
1469 pAM2->Release();
1470
1471 Stop();
1472 m_parent->FinishLoad();
1473 delete this;
1474 }
1475 }
1476
1477 }
1478
1479protected:
1480 wxAMMediaBackend* m_parent; //Backend pointer
1481};
1482
1483//---------------------------------------------------------------------------
1484// wxAMPlayTimer
1485//
1486// Sets m_hNotifyWnd to NULL to signify that we haven't loaded anything yet
1487// Queries the control periodically to see if it has stopped -
1488// if it has it sends the stop event
1489//---------------------------------------------------------------------------
1490class wxAMPlayTimer : public wxTimer
1491{
1492public:
1493 wxAMPlayTimer(wxAMMediaBackend* parent) :
1494 m_parent(parent) {}
1495
1496 void Notify()
1497 {
1498 if(m_parent->GetState() == wxMEDIASTATE_STOPPED &&
1499 //NB: Stop events could get triggered by the interface
1500 //if ShowPlayerControls is enabled,
1501 //so we need this hack here to make an attempt
1502 //at it not getting sent - but its far from ideal -
1503 //they can still get sent in some cases
1504 m_parent->GetPosition() == m_parent->GetDuration())
1505 {
7e41b689 1506 if ( m_parent->SendStopEvent() )
c5191fbd
VZ
1507 {
1508 //Seek to beginning of movie
1509 m_parent->wxAMMediaBackend::SetPosition(0);
1510 Stop();
1511
1512 //send the event to our child
7e41b689 1513 m_parent->QueueFinishEvent();
c5191fbd
VZ
1514 }
1515 }
1516 }
1517
1518protected:
1519 wxAMMediaBackend* m_parent; //Backend pointer
1520};
1521
1522
1523/*
1524// The following is an alternative way - but it doesn't seem
1525// to work with the IActiveMovie control - it probably processes
1526// its own events
1527//---------------------------------------------------------------------------
1528// wxAMPlayTimer
1529//
1530// Query the IMediaEvent interface from the embedded WMP's
1531// filtergraph, then process the events from it - sending
1532// EC_COMPLETE events as stop events to the media control.
1533//---------------------------------------------------------------------------
1534class wxAMPlayTimer : public wxTimer
1535{
1536public:
1537 wxAMPlayTimer(wxAMMediaBackend* pBE) : m_pBE(pBE), m_pME(NULL)
1538 {
1539 HRESULT hr;
1540 IUnknown* pGB;
1541 hr = m_pBE->m_pAM->get_FilterGraph(&pGB);
1542 wxASSERT(SUCCEEDED(hr));
1543 hr = pGB->QueryInterface(IID_IMediaEvent, (void**)&m_pME);
1544 wxASSERT(SUCCEEDED(hr));
1545 pGB->Release();
1546 }
1547
1548 ~wxAMPlayTimer()
1549 {
1550 SAFE_RELEASE(m_pME);
1551 }
1552
1553 void Notify()
1554 {
1555 LONG evCode;
1556 LONG_PTR evParam1,
1557 evParam2;
1558
1559 //
1560 // DirectShow keeps a list of queued events, and we need
1561 // to go through them one by one, stopping at (Hopefully only one)
1562 // EC_COMPLETE message
1563 //
1564 while( m_pME->GetEvent(&evCode, &evParam1, &evParam2, 0) == 0 )
1565 {
1566 // Cleanup memory that GetEvent allocated
1567 HRESULT hr = m_pME->FreeEventParams(evCode,
1568 evParam1, evParam2);
1569 if(hr != 0)
1570 {
1571 //Even though this makes a messagebox this
1572 //is windows where we can do gui stuff in seperate
1573 //threads :)
1574 wxFAIL_MSG(m_pBE->GetErrorString(hr));
1575 }
1576 // If this is the end of the clip, notify handler
1577 else if(1 == evCode) //EC_COMPLETE
1578 {
7e41b689 1579 if ( m_pBE->SendStopEvent() )
c5191fbd
VZ
1580 {
1581 Stop();
1582
7e41b689 1583 m_pBE->QueueFinishEvent();
c5191fbd
VZ
1584 }
1585 }
1586 }
1587 }
1a680109 1588
c5191fbd
VZ
1589protected:
1590 wxAMMediaBackend* m_pBE; //Backend pointer
1591 IMediaEvent* m_pME; //To determine when to send stop event
1592};
1593*/
1a680109 1594
ff4aedc5
RN
1595//---------------------------------------------------------------------------
1596// wxAMMediaBackend Constructor
226ec5a7 1597//---------------------------------------------------------------------------
32f65e50 1598wxAMMediaBackend::wxAMMediaBackend()
c5191fbd
VZ
1599 :m_pAX(NULL),
1600 m_pAM(NULL),
1601 m_pMP(NULL),
1602 m_pTimer(NULL)
1a680109 1603{
1a680109
RN
1604}
1605
ff4aedc5
RN
1606//---------------------------------------------------------------------------
1607// wxAMMediaBackend Destructor
226ec5a7 1608//---------------------------------------------------------------------------
ff4aedc5 1609wxAMMediaBackend::~wxAMMediaBackend()
1a680109 1610{
c5191fbd
VZ
1611 Clear(); //Free memory from Load()
1612
1613 if(m_pAX)
1614 {
1615 m_pAX->DissociateHandle();
1616 delete m_pAX;
1617 m_pAM->Release();
1618
1619 if(m_pMP)
1620 m_pMP->Release();
1621 }
1a680109
RN
1622}
1623
1a680109 1624//---------------------------------------------------------------------------
c5191fbd 1625// wxAMMediaBackend::Clear
1a680109 1626//
c5191fbd
VZ
1627// Free up interfaces and memory allocated by LoadXXX
1628//---------------------------------------------------------------------------
1629void wxAMMediaBackend::Clear()
1630{
1631 if(m_pTimer)
1632 delete m_pTimer;
1633}
1634
1635//---------------------------------------------------------------------------
1636// wxAMMediaBackend::CreateControl
226ec5a7
WS
1637//---------------------------------------------------------------------------
1638bool wxAMMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
ff4aedc5 1639 wxWindowID id,
226ec5a7 1640 const wxPoint& pos,
ff4aedc5 1641 const wxSize& size,
226ec5a7 1642 long style,
ff4aedc5
RN
1643 const wxValidator& validator,
1644 const wxString& name)
226ec5a7 1645{
c5191fbd
VZ
1646 // First get the AMGetErrorText procedure in debug
1647 // mode for more meaningful messages
920a7c15 1648#ifdef __WXDEBUG__
aa200e97 1649 if ( m_dllQuartz.Load(_T("quartz.dll"), wxDL_VERBATIM) )
920a7c15 1650 {
aa200e97
VZ
1651 m_lpAMGetErrorText = (LPAMGETERRORTEXT)
1652 m_dllQuartz.GetSymbolAorW(wxT("AMGetErrorText"));
920a7c15 1653 }
aa200e97
VZ
1654#endif // __WXDEBUG__
1655
c5191fbd
VZ
1656 // Now determine which (if any) media player interface is
1657 // available - IMediaPlayer or IActiveMovie
1658 if( ::CoCreateInstance(CLSID_MediaPlayer, NULL,
920a7c15 1659 CLSCTX_INPROC_SERVER,
c5191fbd
VZ
1660 IID_IMediaPlayer, (void**)&m_pMP) != 0 )
1661 {
1662 if( ::CoCreateInstance(CLSID_ActiveMovie, NULL,
1663 CLSCTX_INPROC_SERVER,
1664 IID_IActiveMovie, (void**)&m_pAM) != 0 )
aa200e97 1665 return false;
c5191fbd
VZ
1666 m_pAM->QueryInterface(IID_IMediaPlayer, (void**)&m_pMP);
1667 }
1668 else
1669 {
1670 m_pMP->QueryInterface(IID_IActiveMovie, (void**)&m_pAM);
1671 }
ff4aedc5
RN
1672 //
1673 // Create window
1674 // By default wxWindow(s) is created with a border -
c5191fbd
VZ
1675 // so we need to get rid of those
1676 //
1677 // Since we don't have a child window like most other
1678 // backends, we don't need wxCLIP_CHILDREN
ff4aedc5
RN
1679 //
1680 if ( !ctrl->wxControl::Create(parent, id, pos, size,
c5191fbd 1681 (style & ~wxBORDER_MASK) | wxBORDER_NONE,
ff4aedc5
RN
1682 validator, name) )
1683 return false;
1a680109 1684
920a7c15 1685 //
c5191fbd
VZ
1686 // Now create the ActiveX container along with the media player
1687 // interface and query them
920a7c15 1688 //
bf354396
VZ
1689 m_ctrl = wxStaticCast(ctrl, wxMediaCtrl);
1690 m_pAX = new wxActiveXContainer(ctrl,
c5191fbd
VZ
1691 m_pMP ? IID_IMediaPlayer : IID_IActiveMovie,
1692 m_pAM);
ff4aedc5 1693
ff4aedc5
RN
1694
1695 //
c5191fbd
VZ
1696 // Here we set up wx-specific stuff for the default
1697 // settings wxMediaCtrl says it will stay to
ff4aedc5 1698 //
c5191fbd 1699 if(m_pMP)
1a680109 1700 {
c5191fbd
VZ
1701 m_pMP->put_DisplaySize(mpFitToSize);
1702 // TODO: Unsure what actual effect this has
1703 m_pMP->put_WindowlessVideo(VARIANT_TRUE);
1a680109 1704 }
920a7c15 1705 else
c5191fbd
VZ
1706 m_pAM->put_MovieWindowSize(amvDoubleOriginalSize);
1707
1708 //by default true
1709 m_pAM->put_AutoStart(VARIANT_FALSE);
1710 //by default enabled
1711 wxAMMediaBackend::ShowPlayerControls(wxMEDIACTRLPLAYERCONTROLS_NONE);
1712 //by default with AM only 0.5
1713 wxAMMediaBackend::SetVolume(1.0);
1714
6ab9bf57
VZ
1715 // don't erase the background of our control window so that resizing is a
1716 // bit smoother
1717 m_ctrl->SetBackgroundStyle(wxBG_STYLE_CUSTOM);
ff4aedc5 1718
c5191fbd 1719 // success
32f65e50 1720 return true;
920a7c15 1721}
1a680109 1722
920a7c15
JS
1723//---------------------------------------------------------------------------
1724// wxAMMediaBackend::Load (file version)
920a7c15
JS
1725//---------------------------------------------------------------------------
1726bool wxAMMediaBackend::Load(const wxString& fileName)
1727{
c5191fbd
VZ
1728 return DoLoad(fileName);
1729}
920a7c15 1730
c5191fbd
VZ
1731//---------------------------------------------------------------------------
1732// wxAMMediaBackend::Load (URL Version)
1733//---------------------------------------------------------------------------
1734bool wxAMMediaBackend::Load(const wxURI& location)
1735{
1736 // Turn off loading from a proxy as user
1737 // may have set it previously
1738 INSPlay* pPlay = NULL;
1739 m_pAM->QueryInterface(IID_INSPlay, (void**) &pPlay);
1740 if(pPlay)
1741 {
1742 pPlay->put_UseHTTPProxy(VARIANT_FALSE);
1743 pPlay->Release();
1744 }
920a7c15 1745
c5191fbd
VZ
1746 return DoLoad(location.BuildURI());
1747}
920a7c15 1748
c5191fbd
VZ
1749//---------------------------------------------------------------------------
1750// wxAMMediaBackend::Load (URL Version with Proxy)
1751//---------------------------------------------------------------------------
1752bool wxAMMediaBackend::Load(const wxURI& location, const wxURI& proxy)
1753{
1754 // Set the proxy of the NETSHOW interface
1755 INSPlay* pPlay = NULL;
1756 m_pAM->QueryInterface(IID_INSPlay, (void**) &pPlay);
a3c1ce50 1757
c5191fbd 1758 if(pPlay)
920a7c15 1759 {
c5191fbd
VZ
1760 pPlay->put_UseHTTPProxy(VARIANT_TRUE);
1761 pPlay->put_HTTPProxyHost(wxBasicString(proxy.GetServer()).Get());
1762 pPlay->put_HTTPProxyPort(wxAtoi(proxy.GetPort()));
1763 pPlay->Release();
ff4aedc5 1764 }
226ec5a7 1765
c5191fbd
VZ
1766 return DoLoad(location.BuildURI());
1767}
1a680109 1768
c5191fbd
VZ
1769//---------------------------------------------------------------------------
1770// wxAMMediaBackend::DoLoad
1771//
1772// Called by all functions - this actually renders
1773// the file and sets up the filter graph
1774//---------------------------------------------------------------------------
1775bool wxAMMediaBackend::DoLoad(const wxString& location)
1776{
1777 Clear(); //Clear up previously allocated memory
a3c1ce50 1778
c5191fbd
VZ
1779 HRESULT hr;
1780
1781 // Play the movie the normal way through the embedded
1782 // WMP. Supposively Open is better in theory because
1783 // the docs say its async and put_FileName is not -
1784 // but in practice they both seem to be async anyway
1785 if(m_pMP)
1786 hr = m_pMP->Open( wxBasicString(location).Get() );
1787 else
1788 hr = m_pAM->put_FileName( wxBasicString(location).Get() );
a3c1ce50 1789
a3c1ce50
JS
1790 if(FAILED(hr))
1791 {
1792 wxAMLOG(hr);
1793 return false;
1794 }
1795
c5191fbd
VZ
1796 // In AM playing will FAIL if
1797 // the user plays before the media is loaded
1798 m_pTimer = new wxAMLoadTimer(this);
1799 m_pTimer->Start(20);
1800 return true;
1801}
1802
1803//---------------------------------------------------------------------------
1804// wxAMMediaBackend::FinishLoad
1805//
1806// Called by our wxAMLoadTimer when the
1807// embedded WMP tells its the media is ready to play.
1808//
1809// Here we get the original size of the video and
1810// send the loaded event to our watcher :).
1811//---------------------------------------------------------------------------
1812void wxAMMediaBackend::FinishLoad()
1813{
1814 //Get the original video size
1815 m_pAM->get_ImageSourceWidth((long*)&m_bestSize.x);
1816 m_pAM->get_ImageSourceHeight((long*)&m_bestSize.y);
1a680109 1817
a3c1ce50 1818 //
c5191fbd
VZ
1819 //Start the play timer to catch stop events
1820 //Previous load timer cleans up itself
a3c1ce50 1821 //
c5191fbd 1822 m_pTimer = new wxAMPlayTimer(this);
96339a78 1823
7e41b689 1824 NotifyMovieLoaded();
1a680109
RN
1825}
1826
a3c1ce50 1827//---------------------------------------------------------------------------
c5191fbd 1828// wxAMMediaBackend::ShowPlayerControls
a3c1ce50 1829//---------------------------------------------------------------------------
c5191fbd 1830bool wxAMMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
a3c1ce50 1831{
c5191fbd
VZ
1832 // Note that IMediaPlayer doesn't have a statusbar by
1833 // default but IActiveMovie does - so lets try to keep
1834 // the interface consistant
1835 if(!flags)
1836 {
1837 m_pAM->put_Enabled(VARIANT_FALSE);
1838 m_pAM->put_ShowControls(VARIANT_FALSE);
1839 if(m_pMP)
1840 m_pMP->put_ShowStatusBar(VARIANT_FALSE);
1841 }
1842 else
a3c1ce50 1843 {
c5191fbd
VZ
1844 m_pAM->put_Enabled(VARIANT_TRUE);
1845 m_pAM->put_ShowControls(VARIANT_TRUE);
1846
1847 m_pAM->put_ShowPositionControls(
1848 (flags & wxMEDIACTRLPLAYERCONTROLS_STEP) ?
1849 VARIANT_TRUE : VARIANT_FALSE);
1850
1851 if(m_pMP)
1852 {
1853 m_pMP->put_ShowStatusBar(VARIANT_TRUE);
1854 m_pMP->put_ShowAudioControls(
1855 (flags & wxMEDIACTRLPLAYERCONTROLS_VOLUME) ?
1856 VARIANT_TRUE : VARIANT_FALSE);
1857 }
a3c1ce50
JS
1858 }
1859
c5191fbd 1860 return true;
a3c1ce50
JS
1861}
1862
ff4aedc5
RN
1863//---------------------------------------------------------------------------
1864// wxAMMediaBackend::Play
1865//
920a7c15
JS
1866// Plays the stream. If it is non-seekable, it will restart it (implicit).
1867//
1868// Note that we use SUCCEEDED here because run/pause/stop tend to be overly
1869// picky and return warnings on pretty much every call
226ec5a7 1870//---------------------------------------------------------------------------
ff4aedc5 1871bool wxAMMediaBackend::Play()
1a680109 1872{
c5191fbd
VZ
1873 // if the movie isn't done loading yet
1874 // go into an sync getmessage loop until it is :)
1875 if(m_pMP)
1876 {
1877 MPReadyStateConstants nState;
1878 m_pMP->get_ReadyState(&nState);
1879 while(nState == mpReadyStateLoading && wxYieldIfNeeded())
1880 {
1881 m_pMP->get_ReadyState(&nState);
1882 }
1883 }
1884 else
1885 {
1886 IActiveMovie2* pAM2;
1887 ReadyStateConstants nState;
1888 if(m_pAM->QueryInterface(IID_IActiveMovie2, (void**)&pAM2) == 0 &&
1889 pAM2->get_ReadyState(&nState) == 0)
1890 {
1891 while(nState == amvLoading && wxYieldIfNeeded())
1892 {
1893 pAM2->get_ReadyState(&nState);
1894 }
1895 pAM2->Release();
1896 }
1897 }
920a7c15 1898
c5191fbd
VZ
1899 //Actually try to play the movie
1900 HRESULT hr = m_pAM->Run();
1901 if(SUCCEEDED(hr))
920a7c15 1902 {
c5191fbd 1903 m_pTimer->Start(20);
920a7c15
JS
1904 return true;
1905 }
c5191fbd 1906 wxAMLOG(hr);
920a7c15 1907 return false;
1a680109
RN
1908}
1909
ff4aedc5
RN
1910//---------------------------------------------------------------------------
1911// wxAMMediaBackend::Pause
1912//
1913// Pauses the stream.
226ec5a7 1914//---------------------------------------------------------------------------
ff4aedc5 1915bool wxAMMediaBackend::Pause()
1a680109 1916{
c5191fbd
VZ
1917 HRESULT hr = m_pAM->Pause();
1918 if(SUCCEEDED(hr))
920a7c15 1919 return true;
c5191fbd 1920 wxAMLOG(hr);
920a7c15 1921 return false;
1a680109
RN
1922}
1923
ff4aedc5
RN
1924//---------------------------------------------------------------------------
1925// wxAMMediaBackend::Stop
1926//
1927// Stops the stream.
226ec5a7 1928//---------------------------------------------------------------------------
ff4aedc5 1929bool wxAMMediaBackend::Stop()
1a680109 1930{
c5191fbd
VZ
1931 HRESULT hr = m_pAM->Stop();
1932 if(SUCCEEDED(hr))
920a7c15 1933 {
c5191fbd 1934 //Seek to beginning
920a7c15 1935 wxAMMediaBackend::SetPosition(0);
c5191fbd
VZ
1936 //Stop stop event timer
1937 m_pTimer->Stop();
920a7c15
JS
1938 return true;
1939 }
c5191fbd 1940 wxAMLOG(hr);
920a7c15 1941 return false;
1a680109
RN
1942}
1943
ff4aedc5
RN
1944//---------------------------------------------------------------------------
1945// wxAMMediaBackend::SetPosition
1946//
226ec5a7 1947// 1) Translates the current position's time to directshow time,
a2a444e3 1948// which is in a scale of 1 second (in a double)
ff4aedc5
RN
1949// 2) Sets the play position of the IMediaSeeking interface -
1950// passing NULL as the stop position means to keep the old
1951// stop position
226ec5a7 1952//---------------------------------------------------------------------------
ff4aedc5 1953bool wxAMMediaBackend::SetPosition(wxLongLong where)
1a680109 1954{
c5191fbd 1955 HRESULT hr = m_pAM->put_CurrentPosition(
920a7c15 1956 ((LONGLONG)where.GetValue()) / 1000.0
a3c1ce50
JS
1957 );
1958 if(FAILED(hr))
1959 {
1960 wxAMLOG(hr);
1961 return false;
1962 }
1963
1964 return true;
1a680109
RN
1965}
1966
ff4aedc5
RN
1967//---------------------------------------------------------------------------
1968// wxAMMediaBackend::GetPosition
1969//
1970// 1) Obtains the current play and stop positions from IMediaSeeking
1971// 2) Returns the play position translated to our time base
226ec5a7 1972//---------------------------------------------------------------------------
ff4aedc5 1973wxLongLong wxAMMediaBackend::GetPosition()
1a680109 1974{
a2a444e3 1975 double outCur;
c5191fbd 1976 HRESULT hr = m_pAM->get_CurrentPosition(&outCur);
a3c1ce50
JS
1977 if(FAILED(hr))
1978 {
1979 wxAMLOG(hr);
1980 return 0;
1981 }
1a680109 1982
a2a444e3 1983 //h,m,s,milli - outdur is in 1 second (double)
600ffb32
WS
1984 outCur *= 1000;
1985 wxLongLong ll;
1986 ll.Assign(outCur);
1987
1988 return ll;
1a680109
RN
1989}
1990
6f8c67e7 1991//---------------------------------------------------------------------------
a3c1ce50 1992// wxAMMediaBackend::GetVolume
6f8c67e7 1993//
a3c1ce50 1994// Gets the volume through the IBasicAudio interface -
6f8c67e7
JS
1995// value ranges from 0 (MAX volume) to -10000 (minimum volume).
1996// -100 per decibel.
1997//---------------------------------------------------------------------------
a3c1ce50 1998double wxAMMediaBackend::GetVolume()
b11eba7e 1999{
a3c1ce50 2000 long lVolume;
c5191fbd 2001 HRESULT hr = m_pAM->get_Volume(&lVolume);
a3c1ce50
JS
2002 if(FAILED(hr))
2003 {
2004 wxAMLOG(hr);
2005 return 0.0;
a3c1ce50 2006 }
c5191fbd 2007 return pow(10.0, lVolume/2000.0);
b11eba7e 2008}
6f8c67e7
JS
2009
2010//---------------------------------------------------------------------------
a3c1ce50 2011// wxAMMediaBackend::SetVolume
6f8c67e7 2012//
a3c1ce50 2013// Sets the volume through the IBasicAudio interface -
6f8c67e7
JS
2014// value ranges from 0 (MAX volume) to -10000 (minimum volume).
2015// -100 per decibel.
2016//---------------------------------------------------------------------------
a3c1ce50 2017bool wxAMMediaBackend::SetVolume(double dVolume)
6f8c67e7 2018{
c5191fbd 2019 //pow(10.0, -80.0) to correct 0 == -INF
3832f946 2020 long lVolume = (long)(2000.0 * log10(pow(10.0, -80.0)+dVolume));
c5191fbd 2021 HRESULT hr = m_pAM->put_Volume( lVolume );
a3c1ce50
JS
2022 if(FAILED(hr))
2023 {
2024 wxAMLOG(hr);
2025 return false;
2026 }
2027 return true;
6f8c67e7 2028}
b11eba7e 2029
ff4aedc5
RN
2030//---------------------------------------------------------------------------
2031// wxAMMediaBackend::GetDuration
2032//
920a7c15 2033// 1) Obtains the duration of the media from IAMMultiMediaStream
ff4aedc5 2034// 2) Converts that value to our time base, and returns it
920a7c15 2035//
32f65e50 2036// NB: With VBR MP3 files the default DirectShow MP3 render does not
920a7c15
JS
2037// read the Xing header correctly, resulting in skewed values for duration
2038// and seeking
226ec5a7 2039//---------------------------------------------------------------------------
ff4aedc5 2040wxLongLong wxAMMediaBackend::GetDuration()
1a680109 2041{
a2a444e3 2042 double outDuration;
c5191fbd 2043 HRESULT hr = m_pAM->get_Duration(&outDuration);
a3c1ce50
JS
2044 if(FAILED(hr))
2045 {
2046 wxAMLOG(hr);
2047 return 0;
2048 }
1a680109 2049
a2a444e3 2050 //h,m,s,milli - outdur is in 1 second (double)
600ffb32
WS
2051 outDuration *= 1000;
2052 wxLongLong ll;
2053 ll.Assign(outDuration);
2054
2055 return ll;
1a680109
RN
2056}
2057
ff4aedc5
RN
2058//---------------------------------------------------------------------------
2059// wxAMMediaBackend::GetState
2060//
920a7c15 2061// Returns the cached state
226ec5a7 2062//---------------------------------------------------------------------------
ff4aedc5 2063wxMediaState wxAMMediaBackend::GetState()
1a680109 2064{
c5191fbd
VZ
2065 StateConstants nState;
2066 HRESULT hr = m_pAM->get_CurrentState(&nState);
2067 if(FAILED(hr))
2068 {
2069 wxAMLOG(hr);
2070 return wxMEDIASTATE_STOPPED;
2071 }
2072
2073 return (wxMediaState)nState;
1a680109
RN
2074}
2075
ff4aedc5
RN
2076//---------------------------------------------------------------------------
2077// wxAMMediaBackend::GetPlaybackRate
2078//
2079// Pretty simple way of obtaining the playback rate from
2080// the IMediaSeeking interface
226ec5a7 2081//---------------------------------------------------------------------------
ff4aedc5 2082double wxAMMediaBackend::GetPlaybackRate()
1a680109
RN
2083{
2084 double dRate;
c5191fbd 2085 HRESULT hr = m_pAM->get_Rate(&dRate);
a3c1ce50
JS
2086 if(FAILED(hr))
2087 {
2088 wxAMLOG(hr);
2089 return 0.0;
2090 }
1a680109
RN
2091 return dRate;
2092}
2093
ff4aedc5
RN
2094//---------------------------------------------------------------------------
2095// wxAMMediaBackend::SetPlaybackRate
2096//
2097// Sets the playback rate of the media - DirectShow is pretty good
2098// about this, actually
226ec5a7 2099//---------------------------------------------------------------------------
ff4aedc5 2100bool wxAMMediaBackend::SetPlaybackRate(double dRate)
c5191fbd
VZ
2101{
2102 HRESULT hr = m_pAM->put_Rate(dRate);
2103 if(FAILED(hr))
2104 {
2105 wxAMLOG(hr);
2106 return false;
920a7c15 2107 }
c5191fbd
VZ
2108
2109 return true;
920a7c15
JS
2110}
2111
920a7c15 2112//---------------------------------------------------------------------------
c5191fbd 2113// wxAMMediaBackend::GetDownloadXXX
920a7c15 2114//
c5191fbd
VZ
2115// Queries for and gets the total size of the file and the current
2116// progress in downloading that file from the IAMOpenProgress
2117// interface from the media player interface's filter graph
920a7c15 2118//---------------------------------------------------------------------------
c5191fbd
VZ
2119void wxAMMediaBackend::DoGetDownloadProgress(wxLongLong* pLoadProgress,
2120 wxLongLong* pLoadTotal)
1a680109 2121{
c5191fbd
VZ
2122 LONGLONG loadTotal = 0, loadProgress = 0;
2123 IUnknown* pFG;
2124 IAMOpenProgress* pOP;
2125 HRESULT hr;
2126 hr = m_pAM->get_FilterGraph(&pFG);
2127 if(SUCCEEDED(hr))
1a680109 2128 {
c5191fbd
VZ
2129 hr = pFG->QueryInterface(IID_IAMOpenProgress, (void**)&pOP);
2130 if(SUCCEEDED(hr))
2131 {
2132 hr = pOP->QueryProgress(&loadTotal, &loadProgress);
2133 pOP->Release();
2134 }
2135 pFG->Release();
2136 }
2137
2138 if(SUCCEEDED(hr))
920a7c15 2139 {
c5191fbd
VZ
2140 *pLoadProgress = loadProgress;
2141 *pLoadTotal = loadTotal;
920a7c15 2142 }
c5191fbd 2143 else
1a680109 2144 {
c5191fbd
VZ
2145 //When not loading from a URL QueryProgress will return
2146 //E_NOINTERFACE or whatever
2147 //wxAMFAIL(hr);
2148 *pLoadProgress = 0;
2149 *pLoadTotal = 0;
920a7c15 2150 }
920a7c15
JS
2151}
2152
920a7c15 2153//---------------------------------------------------------------------------
c5191fbd 2154// wxAMMediaBackend::GetVideoSize
920a7c15 2155//
c5191fbd 2156// Obtains the cached original video size
920a7c15 2157//---------------------------------------------------------------------------
c5191fbd 2158wxSize wxAMMediaBackend::GetVideoSize() const
920a7c15 2159{
c5191fbd
VZ
2160 return m_bestSize;
2161}
b81383bb 2162
c5191fbd
VZ
2163//---------------------------------------------------------------------------
2164// wxAMMediaBackend::Move
2165//
2166// We take care of this in our redrawing
2167//---------------------------------------------------------------------------
2168void wxAMMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y),
2169 int WXUNUSED(w), int WXUNUSED(h))
2170{
1a680109
RN
2171}
2172
ff4aedc5
RN
2173//---------------------------------------------------------------------------
2174// End of wxAMMediaBackend
2175//---------------------------------------------------------------------------
1a680109 2176
ff4aedc5 2177//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1a680109 2178//
ff4aedc5 2179// wxMCIMediaBackend
226ec5a7 2180//
ff4aedc5
RN
2181//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2182
ff4aedc5
RN
2183IMPLEMENT_DYNAMIC_CLASS(wxMCIMediaBackend, wxMediaBackend);
2184
2185//---------------------------------------------------------------------------
2186// Usual debugging macros for MCI returns
1a680109
RN
2187//---------------------------------------------------------------------------
2188
ff4aedc5
RN
2189#ifdef __WXDEBUG__
2190#define wxMCIVERIFY(arg) \
2191{ \
2192 DWORD nRet; \
2193 if ( (nRet = (arg)) != 0) \
2194 { \
2195 TCHAR sz[5000]; \
2196 mciGetErrorString(nRet, sz, 5000); \
2197 wxFAIL_MSG(wxString::Format(_T("MCI Error:%s"), sz)); \
2198 } \
2199}
2200#else
2201#define wxMCIVERIFY(arg) (arg);
2202#endif
2203
2204//---------------------------------------------------------------------------
2205// Simulation for <digitalv.h>
33d8e2fc 2206//
ff4aedc5 2207// Mingw and possibly other compilers don't have the digitalv.h header
226ec5a7 2208// that is needed to have some essential features of mci work with
ff4aedc5
RN
2209// windows - so we provide the declarations for the types we use here
2210//---------------------------------------------------------------------------
33d8e2fc
RN
2211
2212typedef struct {
2213 DWORD_PTR dwCallback;
2214#ifdef MCI_USE_OFFEXT
2215 POINT ptOffset;
2216 POINT ptExtent;
226ec5a7 2217#else
33d8e2fc
RN
2218 RECT rc;
2219#endif
2220} MCI_DGV_RECT_PARMS;
2221
2222typedef struct {
2223 DWORD_PTR dwCallback;
2224 HWND hWnd;
2225#ifndef _WIN32
2226 WORD wReserved1;
2227#endif
2228 UINT nCmdShow;
2229#ifndef _WIN32
2230 WORD wReserved2;
2231#endif
ff4aedc5
RN
2232 wxChar* lpstrText;
2233} MCI_DGV_WINDOW_PARMS;
33d8e2fc
RN
2234
2235typedef struct {
226ec5a7
WS
2236 DWORD_PTR dwCallback;
2237 DWORD dwTimeFormat;
2238 DWORD dwAudio;
2239 DWORD dwFileFormat;
2240 DWORD dwSpeed;
2241} MCI_DGV_SET_PARMS;
33d8e2fc 2242
6f8c67e7
JS
2243typedef struct {
2244 DWORD_PTR dwCallback;
2245 DWORD dwItem;
2246 DWORD dwValue;
2247 DWORD dwOver;
2248 wxChar* lpstrAlgorithm;
2249 wxChar* lpstrQuality;
2250} MCI_DGV_SETAUDIO_PARMS;
2251
ff4aedc5
RN
2252//---------------------------------------------------------------------------
2253// wxMCIMediaBackend Constructor
2254//
2255// Here we don't need to do much except say we don't have any video :)
2256//---------------------------------------------------------------------------
2257wxMCIMediaBackend::wxMCIMediaBackend() : m_hNotifyWnd(NULL), m_bVideo(false)
2258{
3f9a3bf9
RN
2259}
2260
ff4aedc5
RN
2261//---------------------------------------------------------------------------
2262// wxMCIMediaBackend Destructor
2263//
2264// We close the mci device - note that there may not be an mci device here,
2265// or it may fail - but we don't really care, since we're destructing
2266//---------------------------------------------------------------------------
2267wxMCIMediaBackend::~wxMCIMediaBackend()
3f9a3bf9 2268{
ff4aedc5
RN
2269 if(m_hNotifyWnd)
2270 {
2271 mciSendCommand(m_hDev, MCI_CLOSE, 0, 0);
2272 DestroyWindow(m_hNotifyWnd);
2273 m_hNotifyWnd = NULL;
2274 }
3f9a3bf9
RN
2275}
2276
ff4aedc5
RN
2277//---------------------------------------------------------------------------
2278// wxMCIMediaBackend::Create
2279//
2280// Here we just tell wxMediaCtrl that mci does exist (which it does, on all
2281// msw systems, at least in some form dating back to win16 days)
2282//---------------------------------------------------------------------------
226ec5a7 2283bool wxMCIMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
ff4aedc5 2284 wxWindowID id,
226ec5a7 2285 const wxPoint& pos,
ff4aedc5 2286 const wxSize& size,
226ec5a7 2287 long style,
ff4aedc5
RN
2288 const wxValidator& validator,
2289 const wxString& name)
72259e00 2290{
ff4aedc5
RN
2291 //
2292 // Create window
2293 // By default wxWindow(s) is created with a border -
2294 // so we need to get rid of those, and create with
2295 // wxCLIP_CHILDREN, so that if the driver/backend
2296 // is a child window, it refereshes properly
2297 //
2298 if ( !ctrl->wxControl::Create(parent, id, pos, size,
11085e4b 2299 (style & ~wxBORDER_MASK) | wxBORDER_NONE | wxCLIP_CHILDREN,
ff4aedc5
RN
2300 validator, name) )
2301 return false;
2302
bf354396 2303 m_ctrl = wxStaticCast(ctrl, wxMediaCtrl);
3f9a3bf9
RN
2304 return true;
2305}
2306
ff4aedc5
RN
2307//---------------------------------------------------------------------------
2308// wxMCIMediaBackend::Load (file version)
2309//
2310// Here we have MCI load a file and device, set the time format to our
2311// default (milliseconds), and set the video (if any) to play in the control
2312//---------------------------------------------------------------------------
2313bool wxMCIMediaBackend::Load(const wxString& fileName)
3f9a3bf9 2314{
ff4aedc5
RN
2315 //
2316 //if the user already called load close the previous MCI device
2317 //
2318 if(m_hNotifyWnd)
2319 {
3f9a3bf9 2320 mciSendCommand(m_hDev, MCI_CLOSE, 0, 0);
ff4aedc5
RN
2321 DestroyWindow(m_hNotifyWnd);
2322 m_hNotifyWnd = NULL;
2323 }
3f9a3bf9 2324
ff4aedc5
RN
2325 //
2326 //Opens a file and has MCI select a device. Normally you'd put
2327 //MCI_OPEN_TYPE in addition to MCI_OPEN_ELEMENT - however if you
226ec5a7 2328 //omit this it tells MCI to select the device instead. This is
ff4aedc5
RN
2329 //good because we have no reliable way of "enumerating" the devices
2330 //in MCI
2331 //
3f9a3bf9 2332 MCI_OPEN_PARMS openParms;
3f9a3bf9
RN
2333 openParms.lpstrElementName = (wxChar*) fileName.c_str();
2334
226ec5a7 2335 if ( mciSendCommand(0, MCI_OPEN, MCI_OPEN_ELEMENT,
ff4aedc5
RN
2336 (DWORD)(LPVOID)&openParms) != 0)
2337 return false;
3f9a3bf9
RN
2338
2339 m_hDev = openParms.wDeviceID;
2340
ff4aedc5
RN
2341 //
2342 //Now set the time format for the device to milliseconds
2343 //
2344 MCI_SET_PARMS setParms;
3f9a3bf9
RN
2345 setParms.dwCallback = 0;
2346 setParms.dwTimeFormat = MCI_FORMAT_MILLISECONDS;
2347
2348 if (mciSendCommand(m_hDev, MCI_SET, MCI_SET_TIME_FORMAT,
2349 (DWORD)(LPVOID)&setParms) != 0)
2350 return false;
2351
ff4aedc5
RN
2352 //
2353 //Now tell the MCI device to display the video in our wxMediaCtrl
2354 //
3f9a3bf9 2355 MCI_DGV_WINDOW_PARMS windowParms;
5987f174 2356 windowParms.hWnd = (HWND)m_ctrl->GetHandle();
3f9a3bf9 2357
226ec5a7 2358 m_bVideo = (mciSendCommand(m_hDev, MCI_WINDOW,
ff4aedc5
RN
2359 0x00010000L, //MCI_DGV_WINDOW_HWND
2360 (DWORD)(LPVOID)&windowParms) == 0);
2361
2362 //
2363 // Create a hidden window and register to handle
2364 // MCI events
226ec5a7 2365 // Note that wxCanvasClassName is already registered
ff4aedc5 2366 // and used by all wxWindows and normal wxControls
226ec5a7 2367 //
ff4aedc5
RN
2368 m_hNotifyWnd = ::CreateWindow
2369 (
2370 wxCanvasClassName,
2371 NULL,
2372 0, 0, 0, 0,
2373 0,
2374 (HWND) NULL,
2375 (HMENU)NULL,
2376 wxGetInstance(),
2377 (LPVOID) NULL
2378 );
2379
2380 if(!m_hNotifyWnd)
2381 {
2382 wxLogSysError( wxT("Could not create hidden needed for ")
c5191fbd 2383 wxT("registering for MCI events!") );
ff4aedc5
RN
2384
2385 return false;
2386 }
226ec5a7 2387
1146983c 2388 wxSetWindowProc(m_hNotifyWnd, wxMCIMediaBackend::NotifyWndProc);
c5191fbd 2389 wxSetWindowUserData(m_hNotifyWnd, this);
ff4aedc5 2390
7e41b689 2391 NotifyMovieLoaded();
c5191fbd 2392
3f9a3bf9
RN
2393 return true;
2394}
2395
ff4aedc5
RN
2396//---------------------------------------------------------------------------
2397// wxMCIMediaBackend::Load (URL version)
2398//
2399// MCI doesn't support URLs directly (?)
2400//
2401// TODO: Use wxURL/wxFileSystem and mmioInstallProc
2402//---------------------------------------------------------------------------
2403bool wxMCIMediaBackend::Load(const wxURI& WXUNUSED(location))
3f9a3bf9
RN
2404{
2405 return false;
2406}
2407
ff4aedc5
RN
2408//---------------------------------------------------------------------------
2409// wxMCIMediaBackend::Play
2410//
2411// Plays/Resumes the MCI device... a couple notes:
2412// 1) Certain drivers will crash and burn if we don't pass them an
2413// MCI_PLAY_PARMS, despite the documentation that says otherwise...
2414// 2) There is a MCI_RESUME command, but MCI_PLAY does the same thing
226ec5a7 2415// and will resume from a stopped state also, so there's no need to
ff4aedc5
RN
2416// call both, for example
2417//---------------------------------------------------------------------------
2418bool wxMCIMediaBackend::Play()
5987f174 2419{
5987f174 2420 MCI_PLAY_PARMS playParms;
ff4aedc5
RN
2421 playParms.dwCallback = (DWORD)m_hNotifyWnd;
2422
11219c9e 2423 bool bOK = ( mciSendCommand(m_hDev, MCI_PLAY, MCI_NOTIFY,
ff4aedc5 2424 (DWORD)(LPVOID)&playParms) == 0 );
11219c9e
RN
2425
2426 if(bOK)
2427 m_ctrl->Show(m_bVideo);
2428
2429 return bOK;
5987f174
RN
2430}
2431
ff4aedc5
RN
2432//---------------------------------------------------------------------------
2433// wxMCIMediaBackend::Pause
2434//
2435// Pauses the MCI device - nothing special
226ec5a7 2436//---------------------------------------------------------------------------
ff4aedc5 2437bool wxMCIMediaBackend::Pause()
5987f174
RN
2438{
2439 return (mciSendCommand(m_hDev, MCI_PAUSE, MCI_WAIT, 0) == 0);
2440}
2441
ff4aedc5
RN
2442//---------------------------------------------------------------------------
2443// wxMCIMediaBackend::Stop
2444//
2445// Stops the MCI device & seeks to the beginning as wxMediaCtrl docs outline
226ec5a7 2446//---------------------------------------------------------------------------
ff4aedc5 2447bool wxMCIMediaBackend::Stop()
5987f174
RN
2448{
2449 return (mciSendCommand(m_hDev, MCI_STOP, MCI_WAIT, 0) == 0) &&
2450 (mciSendCommand(m_hDev, MCI_SEEK, MCI_SEEK_TO_START, 0) == 0);
2451}
2452
ff4aedc5
RN
2453//---------------------------------------------------------------------------
2454// wxMCIMediaBackend::GetState
2455//
2456// Here we get the state and convert it to a wxMediaState -
2457// since we use direct comparisons with MCI_MODE_PLAY and
2458// MCI_MODE_PAUSE, we don't care if the MCI_STATUS call
2459// fails or not
226ec5a7 2460//---------------------------------------------------------------------------
ff4aedc5 2461wxMediaState wxMCIMediaBackend::GetState()
3f9a3bf9
RN
2462{
2463 MCI_STATUS_PARMS statusParms;
2464 statusParms.dwItem = MCI_STATUS_MODE;
ff4aedc5 2465
3f9a3bf9
RN
2466 mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
2467 (DWORD)(LPVOID)&statusParms);
2468
2469 if(statusParms.dwReturn == MCI_MODE_PAUSE)
2470 return wxMEDIASTATE_PAUSED;
2471 else if(statusParms.dwReturn == MCI_MODE_PLAY)
2472 return wxMEDIASTATE_PLAYING;
2473 else
2474 return wxMEDIASTATE_STOPPED;
2475}
2476
ff4aedc5
RN
2477//---------------------------------------------------------------------------
2478// wxMCIMediaBackend::SetPosition
2479//
2480// Here we set the position of the device in the stream.
226ec5a7 2481// Note that MCI actually stops the device after you seek it if the
ff4aedc5 2482// device is playing/paused, so we need to play the file after
226ec5a7
WS
2483// MCI seeks like normal APIs would
2484//---------------------------------------------------------------------------
ff4aedc5 2485bool wxMCIMediaBackend::SetPosition(wxLongLong where)
3f9a3bf9
RN
2486{
2487 MCI_SEEK_PARMS seekParms;
2488 seekParms.dwCallback = 0;
e70fda0e 2489#if wxUSE_LONGLONG_NATIVE && !wxUSE_LONGLONG_WX
226ec5a7 2490 seekParms.dwTo = (DWORD)where.GetValue();
e70fda0e
WS
2491#else /* wxUSE_LONGLONG_WX */
2492 /* no way to return it in one piece */
2493 wxASSERT( where.GetHi()==0 );
2494 seekParms.dwTo = (DWORD)where.GetLo();
2495#endif /* wxUSE_LONGLONG_* */
3f9a3bf9 2496
ff4aedc5 2497 //device was playing?
3f9a3bf9
RN
2498 bool bReplay = GetState() == wxMEDIASTATE_PLAYING;
2499
226ec5a7 2500 if( mciSendCommand(m_hDev, MCI_SEEK, MCI_TO,
ff4aedc5 2501 (DWORD)(LPVOID)&seekParms) != 0)
3f9a3bf9 2502 return false;
3f9a3bf9 2503
ff4aedc5 2504 //If the device was playing, resume it
3f9a3bf9
RN
2505 if (bReplay)
2506 return Play();
2507 else
2508 return true;
2509}
2510
ff4aedc5
RN
2511//---------------------------------------------------------------------------
2512// wxMCIMediaBackend::GetPosition
2513//
2514// Gets the position of the device in the stream using the current
2515// time format... nothing special here...
226ec5a7 2516//---------------------------------------------------------------------------
ff4aedc5 2517wxLongLong wxMCIMediaBackend::GetPosition()
3f9a3bf9
RN
2518{
2519 MCI_STATUS_PARMS statusParms;
72259e00 2520 statusParms.dwItem = MCI_STATUS_POSITION;
ff4aedc5 2521
72259e00 2522 if (mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
ff4aedc5 2523 (DWORD)(LPSTR)&statusParms) != 0)
3f9a3bf9
RN
2524 return 0;
2525
2526 return statusParms.dwReturn;
2527}
2528
6f8c67e7
JS
2529//---------------------------------------------------------------------------
2530// wxMCIMediaBackend::GetVolume
2531//
2532// Gets the volume of the current media via the MCI_DGV_STATUS_VOLUME
2533// message. Value ranges from 0 (minimum) to 1000 (maximum volume).
2534//---------------------------------------------------------------------------
2535double wxMCIMediaBackend::GetVolume()
2536{
2537 MCI_STATUS_PARMS statusParms;
600ffb32 2538 statusParms.dwCallback = 0;
6f8c67e7
JS
2539 statusParms.dwItem = 0x4019; //MCI_DGV_STATUS_VOLUME
2540
2541 if (mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
2542 (DWORD)(LPSTR)&statusParms) != 0)
2543 return 0;
2544
2545 return ((double)statusParms.dwReturn) / 1000.0;
2546}
2547
2548//---------------------------------------------------------------------------
2549// wxMCIMediaBackend::SetVolume
2550//
2551// Sets the volume of the current media via the MCI_DGV_SETAUDIO_VOLUME
2552// message. Value ranges from 0 (minimum) to 1000 (maximum volume).
2553//---------------------------------------------------------------------------
2554bool wxMCIMediaBackend::SetVolume(double dVolume)
2555{
2556 MCI_DGV_SETAUDIO_PARMS audioParms;
600ffb32 2557 audioParms.dwCallback = 0;
6f8c67e7
JS
2558 audioParms.dwItem = 0x4002; //MCI_DGV_SETAUDIO_VOLUME
2559 audioParms.dwValue = (DWORD) (dVolume * 1000.0);
2560 audioParms.dwOver = 0;
2561 audioParms.lpstrAlgorithm = NULL;
2562 audioParms.lpstrQuality = NULL;
2563
b11eba7e 2564 if (mciSendCommand(m_hDev, 0x0873, //MCI_SETAUDIO
c5191fbd
VZ
2565 //MCI_DGV_SETAUDIO+(_ITEM | _VALUE)
2566 0x00800000L | 0x01000000L,
6f8c67e7
JS
2567 (DWORD)(LPSTR)&audioParms) != 0)
2568 return false;
2569 return true;
2570}
2571
ff4aedc5
RN
2572//---------------------------------------------------------------------------
2573// wxMCIMediaBackend::GetDuration
2574//
2575// Gets the duration of the stream... nothing special
226ec5a7 2576//---------------------------------------------------------------------------
ff4aedc5 2577wxLongLong wxMCIMediaBackend::GetDuration()
3f9a3bf9
RN
2578{
2579 MCI_STATUS_PARMS statusParms;
72259e00 2580 statusParms.dwItem = MCI_STATUS_LENGTH;
ff4aedc5 2581
72259e00 2582 if (mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
ff4aedc5 2583 (DWORD)(LPSTR)&statusParms) != 0)
3f9a3bf9
RN
2584 return 0;
2585
2586 return statusParms.dwReturn;
2587}
2588
ff4aedc5
RN
2589//---------------------------------------------------------------------------
2590// wxMCIMediaBackend::Move
2591//
2592// Moves the window to a location
226ec5a7
WS
2593//---------------------------------------------------------------------------
2594void wxMCIMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y),
ff4aedc5 2595 int w, int h)
3f9a3bf9 2596{
ff4aedc5
RN
2597 if (m_hNotifyWnd && m_bVideo)
2598 {
2599 MCI_DGV_RECT_PARMS putParms; //ifdefed MCI_DGV_PUT_PARMS
b11eba7e 2600 memset(&putParms, 0, sizeof(MCI_DGV_RECT_PARMS));
ff4aedc5 2601 putParms.rc.bottom = h;
b11eba7e 2602 putParms.rc.right = w;
7c4a4505 2603
b11eba7e
WS
2604 //wxStackWalker will crash and burn here on assert
2605 //and mci doesn't like 0 and 0 for some reason (out of range )
2606 //so just don't it in that case
2607 if(w || h)
2608 {
7c4a4505 2609 wxMCIVERIFY( mciSendCommand(m_hDev, MCI_PUT,
ff4aedc5
RN
2610 0x00040000L, //MCI_DGV_PUT_DESTINATION
2611 (DWORD)(LPSTR)&putParms) );
7c4a4505 2612 }
ff4aedc5 2613 }
3f9a3bf9
RN
2614}
2615
ff4aedc5
RN
2616//---------------------------------------------------------------------------
2617// wxMCIMediaBackend::GetVideoSize
2618//
2619// Gets the original size of the movie for sizers
226ec5a7 2620//---------------------------------------------------------------------------
ff4aedc5 2621wxSize wxMCIMediaBackend::GetVideoSize() const
3f9a3bf9
RN
2622{
2623 if(m_bVideo)
2624 {
ff4aedc5 2625 MCI_DGV_RECT_PARMS whereParms; //ifdefed MCI_DGV_WHERE_PARMS
3f9a3bf9 2626
226ec5a7 2627 wxMCIVERIFY( mciSendCommand(m_hDev, MCI_WHERE,
ff4aedc5
RN
2628 0x00020000L, //MCI_DGV_WHERE_SOURCE
2629 (DWORD)(LPSTR)&whereParms) );
226ec5a7 2630
ff4aedc5 2631 return wxSize(whereParms.rc.right, whereParms.rc.bottom);
3f9a3bf9 2632 }
c47addef 2633 return wxSize(0,0);
3f9a3bf9
RN
2634}
2635
ff4aedc5
RN
2636//---------------------------------------------------------------------------
2637// wxMCIMediaBackend::GetPlaybackRate
2638//
2639// TODO
226ec5a7 2640//---------------------------------------------------------------------------
ff4aedc5 2641double wxMCIMediaBackend::GetPlaybackRate()
3f9a3bf9
RN
2642{
2643 return 1.0;
2644}
2645
ff4aedc5
RN
2646//---------------------------------------------------------------------------
2647// wxMCIMediaBackend::SetPlaybackRate
2648//
2649// TODO
226ec5a7 2650//---------------------------------------------------------------------------
ff4aedc5 2651bool wxMCIMediaBackend::SetPlaybackRate(double WXUNUSED(dRate))
3f9a3bf9 2652{
ff4aedc5
RN
2653/*
2654 MCI_WAVE_SET_SAMPLESPERSEC
2655 MCI_DGV_SET_PARMS setParms;
2656 setParms.dwSpeed = (DWORD) (dRate * 1000.0);
2657
226ec5a7 2658 return (mciSendCommand(m_hDev, MCI_SET,
ff4aedc5
RN
2659 0x00020000L, //MCI_DGV_SET_SPEED
2660 (DWORD)(LPSTR)&setParms) == 0);
2661*/
3f9a3bf9
RN
2662 return false;
2663}
2664
ff4aedc5
RN
2665//---------------------------------------------------------------------------
2666// [static] wxMCIMediaBackend::MSWWindowProc
2667//
226ec5a7 2668// Here we process a message when MCI reaches the stopping point
ff4aedc5 2669// in the stream
226ec5a7
WS
2670//---------------------------------------------------------------------------
2671LRESULT CALLBACK wxMCIMediaBackend::NotifyWndProc(HWND hWnd, UINT nMsg,
2672 WPARAM wParam,
ff4aedc5
RN
2673 LPARAM lParam)
2674{
c5191fbd
VZ
2675 wxMCIMediaBackend* backend =
2676 (wxMCIMediaBackend*)wxGetWindowUserData(hWnd);
ff4aedc5
RN
2677
2678 return backend->OnNotifyWndProc(hWnd, nMsg, wParam, lParam);
2679}
2680
226ec5a7
WS
2681LRESULT CALLBACK wxMCIMediaBackend::OnNotifyWndProc(HWND hWnd, UINT nMsg,
2682 WPARAM wParam,
ff4aedc5 2683 LPARAM lParam)
3f9a3bf9 2684{
5987f174
RN
2685 if(nMsg == MM_MCINOTIFY)
2686 {
ff4aedc5
RN
2687 wxASSERT(lParam == (LPARAM) m_hDev);
2688 if(wParam == MCI_NOTIFY_SUCCESSFUL && lParam == (LPARAM)m_hDev)
5987f174 2689 {
7e41b689 2690 if ( SendStopEvent() )
ff4aedc5 2691 {
226ec5a7 2692 wxMCIVERIFY( mciSendCommand(m_hDev, MCI_SEEK,
ff4aedc5 2693 MCI_SEEK_TO_START, 0) );
3f9a3bf9 2694
7e41b689 2695 QueueFinishEvent();
ff4aedc5 2696 }
5987f174 2697 }
5987f174 2698 }
ff4aedc5 2699 return DefWindowProc(hWnd, nMsg, wParam, lParam);
3f9a3bf9 2700}
c5191fbd 2701
ff4aedc5
RN
2702//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2703//
2704// wxQTMediaBackend
226ec5a7 2705//
ff4aedc5 2706// TODO: Use a less cludgy way to pause/get state/set state
c5191fbd
VZ
2707// FIXME: Greg Hazel reports that sometimes files that cannot be played
2708// with this backend are treated as playable anyway - not verifyed though.
ff4aedc5
RN
2709//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2710
ff4aedc5
RN
2711IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend);
2712
c5191fbd
VZ
2713//Time between timer calls - this is the Apple recommondation to the TCL
2714//team I believe
2715#define MOVIE_DELAY 20
ff4aedc5
RN
2716
2717#include "wx/timer.h"
2718
c5191fbd
VZ
2719
2720//---------------------------------------------------------------------------
2721// wxQTLoadTimer
2722//
2723// QT, esp. QT for Windows is very picky about how you go about
2724// async loading. If you were to go through a Windows message loop
2725// or a MoviesTask or both and then check the movie load state
2726// it would still return 1000 (loading)... even (pre)prerolling doesn't
2727// help. However, making a load timer like this works
2728//---------------------------------------------------------------------------
2729class wxQTLoadTimer : public wxTimer
ff4aedc5
RN
2730{
2731public:
c5191fbd
VZ
2732 wxQTLoadTimer(Movie movie, wxQTMediaBackend* parent, wxQuickTimeLibrary* pLib) :
2733 m_movie(movie), m_parent(parent), m_pLib(pLib) {}
ff4aedc5 2734
c5191fbd 2735 void Notify()
ff4aedc5 2736 {
c5191fbd
VZ
2737 m_pLib->MoviesTask(m_movie, 0);
2738 //kMovieLoadStatePlayable
2739 if(m_pLib->GetMovieLoadState(m_movie) >= 10000)
2740 {
2741 m_parent->FinishLoad();
2742 delete this;
2743 }
ff4aedc5
RN
2744 }
2745
c5191fbd
VZ
2746protected:
2747 Movie m_movie; //Our movie instance
2748 wxQTMediaBackend* m_parent; //Backend pointer
2749 wxQuickTimeLibrary* m_pLib; //Interfaces
2750};
2751
2752
2753// --------------------------------------------------------------------------
2754// wxQTPlayTimer - Handle Asyncronous Playing
2755//
2756// 1) Checks to see if the movie is done, and if not continues
2757// streaming the movie
2758// 2) Sends the wxEVT_MEDIA_STOP event if we have reached the end of
2759// the movie.
2760// --------------------------------------------------------------------------
2761class wxQTPlayTimer : public wxTimer
2762{
2763public:
2764 wxQTPlayTimer(Movie movie, wxQTMediaBackend* parent,
2765 wxQuickTimeLibrary* pLib) :
2766 m_movie(movie), m_parent(parent), m_pLib(pLib) {}
ff4aedc5 2767
ff4aedc5
RN
2768 void Notify()
2769 {
c5191fbd
VZ
2770 //
2771 // OK, a little explaining - basically originally
2772 // we only called MoviesTask if the movie was actually
2773 // playing (not paused or stopped)... this was before
2774 // we realized MoviesTask actually handles repainting
2775 // of the current frame - so if you were to resize
2776 // or something it would previously not redraw that
2777 // portion of the movie.
2778 //
2779 // So now we call MoviesTask always so that it repaints
2780 // correctly.
2781 //
2782 m_pLib->MoviesTask(m_movie, 0);
2783
2784 //
2785 // Handle the stop event - if the movie has reached
2786 // the end, notify our handler
2787 //
2788 // m_bPlaying == !(Stopped | Paused)
2789 //
2790 if (m_parent->m_bPlaying)
ff4aedc5 2791 {
c5191fbd 2792 if(m_pLib->IsMovieDone(m_movie))
ff4aedc5 2793 {
7e41b689 2794 if ( m_parent->SendStopEvent() )
ff4aedc5 2795 {
ff4aedc5 2796 m_parent->Stop();
d7a9c895 2797 wxASSERT(m_pLib->GetMoviesError() == noErr);
ff4aedc5 2798
7e41b689 2799 m_parent->QueueFinishEvent();
ff4aedc5
RN
2800 }
2801 }
2802 }
2803 }
2804
2805protected:
2806 Movie m_movie; //Our movie instance
ff4aedc5 2807 wxQTMediaBackend* m_parent; //Backend pointer
d7a9c895 2808 wxQuickTimeLibrary* m_pLib; //Interfaces
ff4aedc5
RN
2809};
2810
c5191fbd
VZ
2811
2812//---------------------------------------------------------------------------
2813// wxQTMediaBackend::QTWndProc
2814//
2815// Forwards events to the Movie Controller so that it can
2816// redraw itself/process messages etc..
2817//---------------------------------------------------------------------------
2818LRESULT CALLBACK wxQTMediaBackend::QTWndProc(HWND hWnd, UINT nMsg,
2819 WPARAM wParam, LPARAM lParam)
2820{
2821 wxQTMediaBackend* pThis = (wxQTMediaBackend*)wxGetWindowUserData(hWnd);
2822
2823 MSG msg;
2824 msg.hwnd = hWnd;
2825 msg.message = nMsg;
2826 msg.wParam = wParam;
2827 msg.lParam = lParam;
2828 msg.time = 0;
2829 msg.pt.x = 0;
2830 msg.pt.y = 0;
2831 EventRecord theEvent;
2832 pThis->m_lib.NativeEventToMacEvent(&msg, &theEvent);
2833 pThis->m_lib.MCIsPlayerEvent(pThis->m_pMC, &theEvent);
2834 return pThis->m_ctrl->MSWWindowProc(nMsg, wParam, lParam);
2835}
2836
ff4aedc5
RN
2837//---------------------------------------------------------------------------
2838// wxQTMediaBackend Destructor
2839//
2840// Sets m_timer to NULL signifying we havn't loaded anything yet
2841//---------------------------------------------------------------------------
c5191fbd
VZ
2842wxQTMediaBackend::wxQTMediaBackend()
2843: m_movie(NULL), m_bPlaying(false), m_timer(NULL), m_pMC(NULL)
ff4aedc5
RN
2844{
2845}
2846
2847//---------------------------------------------------------------------------
2848// wxQTMediaBackend Destructor
2849//
2850// 1) Cleans up the QuickTime movie instance
2851// 2) Decrements the QuickTime reference counter - if this reaches
2852// 0, QuickTime shuts down
2853// 3) Decrements the QuickTime Windows Media Layer reference counter -
2854// if this reaches 0, QuickTime shuts down the Windows Media Layer
2855//---------------------------------------------------------------------------
2856wxQTMediaBackend::~wxQTMediaBackend()
2857{
c5191fbd 2858 if(m_movie)
ff4aedc5
RN
2859 Cleanup();
2860
d7a9c895
RN
2861 if(m_lib.IsOk())
2862 {
c5191fbd
VZ
2863 if(m_pMC)
2864 {
2865 m_lib.DisposeMovieController(m_pMC);
2866 // m_pMC = NULL;
2867 }
2868
6ab9bf57
VZ
2869 // destroy wxQTMediaEvtHandler we pushed on it
2870 m_ctrl->PopEventHandler(true);
2871
c5191fbd
VZ
2872 m_lib.DestroyPortAssociation(
2873 (CGrafPtr)m_lib.GetNativeWindowPort(m_ctrl->GetHWND()));
2874
3103e8a9 2875 //Note that ExitMovies() is not necessary, but
d7a9c895
RN
2876 //the docs are fuzzy on whether or not TerminateQTML is
2877 m_lib.ExitMovies();
2878 m_lib.TerminateQTML();
2879 }
ff4aedc5
RN
2880}
2881
2882//---------------------------------------------------------------------------
2883// wxQTMediaBackend::CreateControl
2884//
2885// 1) Intializes QuickTime
2886// 2) Creates the control window
2887//---------------------------------------------------------------------------
226ec5a7 2888bool wxQTMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
ff4aedc5 2889 wxWindowID id,
226ec5a7 2890 const wxPoint& pos,
ff4aedc5 2891 const wxSize& size,
226ec5a7 2892 long style,
ff4aedc5
RN
2893 const wxValidator& validator,
2894 const wxString& name)
2895{
d7a9c895
RN
2896 if(!m_lib.Initialize())
2897 return false;
b11eba7e 2898
600ffb32
WS
2899 int nError = m_lib.InitializeQTML(0);
2900 if (nError != noErr) //-2093 no dll
ff4aedc5 2901 {
c5191fbd
VZ
2902 wxFAIL_MSG(wxString::Format(wxT("Couldn't Initialize Quicktime-%i"),
2903 nError));
ff4aedc5
RN
2904 return false;
2905 }
d7a9c895 2906 m_lib.EnterMovies();
ff4aedc5
RN
2907
2908 //
2909 // Create window
2910 // By default wxWindow(s) is created with a border -
2911 // so we need to get rid of those
2912 //
2913 // Since we don't have a child window like most other
2914 // backends, we don't need wxCLIP_CHILDREN
2915 //
2916 if ( !ctrl->wxControl::Create(parent, id, pos, size,
11085e4b 2917 (style & ~wxBORDER_MASK) | wxBORDER_NONE,
ff4aedc5
RN
2918 validator, name) )
2919 return false;
2920
c5191fbd 2921
bf354396 2922 m_ctrl = wxStaticCast(ctrl, wxMediaCtrl);
c5191fbd
VZ
2923
2924 // Create a port association for our window so we
2925 // can use it as a WindowRef
2926 m_lib.CreatePortAssociation(m_ctrl->GetHWND(), NULL, 0L);
2927
2928 //Part of a suggestion from Greg Hazel to repaint
2929 //movie when idle
7e41b689 2930 m_ctrl->PushEventHandler(new wxQTMediaEvtHandler(this, m_ctrl->GetHWND()));
c5191fbd
VZ
2931
2932 // done
ff4aedc5
RN
2933 return true;
2934}
2935
2936//---------------------------------------------------------------------------
2937// wxQTMediaBackend::Load (file version)
2938//
2939// 1) Get an FSSpec from the Windows path name
2940// 2) Open the movie
2941// 3) Obtain the movie instance from the movie resource
c5191fbd
VZ
2942// 4) Close the movie resource
2943// 5) Finish loading
ff4aedc5
RN
2944//---------------------------------------------------------------------------
2945bool wxQTMediaBackend::Load(const wxString& fileName)
2946{
c5191fbd 2947 if(m_movie)
ff4aedc5 2948 Cleanup();
3f9a3bf9 2949
920a7c15 2950 short movieResFile = 0; //= 0 because of annoying VC6 warning
ff4aedc5
RN
2951 FSSpec sfFile;
2952
d7a9c895 2953 if (m_lib.NativePathNameToFSSpec ((char*) (const char*) fileName.mb_str(),
78450975 2954 &sfFile, 0) != noErr)
ff4aedc5 2955 return false;
226ec5a7 2956
d7a9c895 2957 if (m_lib.OpenMovieFile (&sfFile, &movieResFile, fsRdPerm) != noErr)
ff4aedc5
RN
2958 return false;
2959
2960 short movieResID = 0;
2961 Str255 movieName;
2962
600ffb32
WS
2963 OSErr err = m_lib.NewMovieFromFile (
2964 &m_movie,
2965 movieResFile,
2966 &movieResID,
2967 movieName,
2968 newMovieActive,
2969 NULL
2970 ); //wasChanged
ff4aedc5 2971
c5191fbd
VZ
2972 //m_lib.GetMoviesStickyError() because it may not find the
2973 //proper codec and play black video and other strange effects,
2974 //not to mention mess up the dynamic backend loading scheme
2975 //of wxMediaCtrl - so it just does what the QuickTime player does
2976 if(err == noErr && m_lib.GetMoviesStickyError() == noErr)
2977 {
d7a9c895 2978 m_lib.CloseMovieFile (movieResFile);
ff4aedc5 2979
c5191fbd
VZ
2980 FinishLoad();
2981 return true;
2982 }
2983 else
ff4aedc5 2984 return false;
c5191fbd 2985}
ff4aedc5 2986
ff4aedc5 2987
c5191fbd
VZ
2988//---------------------------------------------------------------------------
2989// wxQTMediaBackend::PPRMProc (static)
2990//
2991// Called when done PrePrerolling the movie.
2992// Note that in 99% of the cases this does nothing...
2993// Anyway we set up the loading timer here to tell us when the movie is done
2994//---------------------------------------------------------------------------
3832f946
WS
2995void wxQTMediaBackend::PPRMProc (Movie theMovie,
2996 OSErr WXUNUSED_UNLESS_DEBUG(theErr),
2997 void* theRefCon)
c5191fbd
VZ
2998{
2999 wxASSERT( theMovie );
3000 wxASSERT( theRefCon );
3001 wxASSERT( theErr == noErr );
3002
3003 wxQTMediaBackend* pBE = (wxQTMediaBackend*) theRefCon;
3004
3005 long lTime = pBE->m_lib.GetMovieTime(theMovie,NULL);
3006 Fixed rate = pBE->m_lib.GetMoviePreferredRate(theMovie);
3007 pBE->m_lib.PrerollMovie(theMovie,lTime,rate);
3008 pBE->m_timer = new wxQTLoadTimer(pBE->m_movie, pBE, &pBE->m_lib);
3009 pBE->m_timer->Start(MOVIE_DELAY);
ff4aedc5
RN
3010}
3011
c5191fbd 3012
ff4aedc5 3013//---------------------------------------------------------------------------
c5191fbd 3014// wxQTMediaBackend::Load (URL Version)
ff4aedc5 3015//
c5191fbd
VZ
3016// 1) Build an escaped URI from location
3017// 2) Create a handle to store the URI string
3018// 3) Put the URI string inside the handle
3019// 4) Make a QuickTime URL data ref from the handle with the URI in it
3020// 5) Clean up the URI string handle
3021// 6) Do some prerolling
3022// 7) Finish Loading
ff4aedc5
RN
3023//---------------------------------------------------------------------------
3024bool wxQTMediaBackend::Load(const wxURI& location)
3025{
c5191fbd 3026 if(m_movie)
ff4aedc5
RN
3027 Cleanup();
3028
3029 wxString theURI = location.BuildURI();
3030
d7a9c895 3031 Handle theHandle = m_lib.NewHandleClear(theURI.length() + 1);
ff4aedc5
RN
3032 wxASSERT(theHandle);
3033
d7a9c895 3034 m_lib.BlockMove(theURI.mb_str(), *theHandle, theURI.length() + 1);
ff4aedc5
RN
3035
3036 //create the movie from the handle that refers to the URI
c5191fbd
VZ
3037 OSErr err = m_lib.NewMovieFromDataRef(&m_movie, newMovieActive |
3038 newMovieAsyncOK
3039 /*|newMovieIdleImportOK*/,
226ec5a7 3040 NULL, theHandle,
19b6f122 3041 URLDataHandlerSubType);
ff4aedc5 3042
d7a9c895 3043 m_lib.DisposeHandle(theHandle);
ff4aedc5 3044
c5191fbd
VZ
3045 if (err == noErr)
3046 {
3047 long timeNow;
ff4aedc5 3048 Fixed playRate;
ff4aedc5 3049
c5191fbd
VZ
3050 timeNow = m_lib.GetMovieTime(m_movie, NULL);
3051 wxASSERT(m_lib.GetMoviesError() == noErr);
ff4aedc5 3052
c5191fbd
VZ
3053 playRate = m_lib.GetMoviePreferredRate(m_movie);
3054 wxASSERT(m_lib.GetMoviesError() == noErr);
3055
3056 //
3057 // Note that the callback here is optional,
3058 // but without it PrePrerollMovie can be buggy
3059 // (see Apple ml). Also, some may wonder
3060 // why we need this at all - this is because
3061 // Apple docs say QuickTime streamed movies
3062 // require it if you don't use a Movie Controller,
3063 // which we don't by default.
3064 //
3065 m_lib.PrePrerollMovie(m_movie, timeNow, playRate,
3066 (WXFARPROC)wxQTMediaBackend::PPRMProc,
3067 (void*)this);
3068 return true;
3069 }
3070 else
3071 return false;
ff4aedc5
RN
3072}
3073
c5191fbd 3074
ff4aedc5 3075//---------------------------------------------------------------------------
c5191fbd 3076// wxQTMediaBackend::FinishLoad
ff4aedc5 3077//
c5191fbd
VZ
3078// 1) Create the movie timer
3079// 2) Get real size of movie for GetBestSize/sizers
3080// 3) Set the movie time scale to something usable so that seeking
3081// etc. will work correctly
3082// 4) Set our Movie Controller to display the movie if it exists,
3083// otherwise set the bounds of the Movie
3084// 5) Refresh parent window
ff4aedc5
RN
3085//---------------------------------------------------------------------------
3086void wxQTMediaBackend::FinishLoad()
3087{
c5191fbd
VZ
3088 // Create the playing/streaming timer
3089 m_timer = new wxQTPlayTimer(m_movie, (wxQTMediaBackend*) this, &m_lib);
ff4aedc5 3090 wxASSERT(m_timer);
c5191fbd 3091 m_timer->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS);
ff4aedc5
RN
3092
3093 //get the real size of the movie
3094 Rect outRect;
920a7c15 3095 memset(&outRect, 0, sizeof(Rect)); //for annoying VC6 warning
d7a9c895
RN
3096 m_lib.GetMovieNaturalBoundsRect (m_movie, &outRect);
3097 wxASSERT(m_lib.GetMoviesError() == noErr);
ff4aedc5
RN
3098
3099 m_bestSize.x = outRect.right - outRect.left;
3100 m_bestSize.y = outRect.bottom - outRect.top;
226ec5a7 3101
c5191fbd
VZ
3102 //
3103 // Handle the movie GWorld
3104 //
3105 if(m_pMC)
3106 {
3107 Point thePoint;
3108 thePoint.h = thePoint.v = 0;
3109 m_lib.MCSetMovie(m_pMC, m_movie,
3110 m_lib.GetNativeWindowPort(m_ctrl->GetHandle()),
3111 thePoint);
3112 m_lib.MCSetVisible(m_pMC, true);
3113 m_bestSize.y += 16;
3114 }
3115 else
ff4aedc5 3116 {
d7a9c895
RN
3117 m_lib.SetMovieGWorld(m_movie,
3118 (CGrafPtr) m_lib.GetNativeWindowPort(m_ctrl->GetHWND()),
3119 NULL);
ff4aedc5
RN
3120 }
3121
c5191fbd
VZ
3122 //
3123 // Set the movie to millisecond precision
3124 //
d7a9c895
RN
3125 m_lib.SetMovieTimeScale(m_movie, 1000);
3126 wxASSERT(m_lib.GetMoviesError() == noErr);
ff4aedc5 3127
7e41b689 3128 NotifyMovieLoaded();
ff4aedc5
RN
3129}
3130
3131//---------------------------------------------------------------------------
c5191fbd 3132// wxQTMediaBackend::Play
ff4aedc5 3133//
c5191fbd
VZ
3134// 1) Start the QT movie
3135// 2) Start the movie loading timer
3136//
3137// NOTE: This will still return success even when
3138// the movie is still loading, and as mentioned in wxQTLoadTimer
3139// I don't know of a way to force this to be sync - so if its
3140// still loading the function will return true but the movie will
3141// still be in the stopped state
ff4aedc5
RN
3142//---------------------------------------------------------------------------
3143bool wxQTMediaBackend::Play()
3144{
d7a9c895 3145 m_lib.StartMovie(m_movie);
c5191fbd 3146 m_bPlaying = true;
d7a9c895 3147 return m_lib.GetMoviesError() == noErr;
ff4aedc5
RN
3148}
3149
3150//---------------------------------------------------------------------------
c5191fbd 3151// wxQTMediaBackend::Pause
ff4aedc5 3152//
c5191fbd
VZ
3153// 1) Stop the movie
3154// 2) Stop the movie timer
ff4aedc5
RN
3155//---------------------------------------------------------------------------
3156bool wxQTMediaBackend::Pause()
3157{
c5191fbd 3158 m_bPlaying = false;
d7a9c895 3159 m_lib.StopMovie(m_movie);
d7a9c895 3160 return m_lib.GetMoviesError() == noErr;
ff4aedc5
RN
3161}
3162
3163//---------------------------------------------------------------------------
c5191fbd 3164// wxQTMediaBackend::Stop
ff4aedc5 3165//
c5191fbd
VZ
3166// 1) Stop the movie
3167// 2) Stop the movie timer
3168// 3) Seek to the beginning of the movie
ff4aedc5
RN
3169//---------------------------------------------------------------------------
3170bool wxQTMediaBackend::Stop()
3171{
c5191fbd 3172 m_bPlaying = false;
ff4aedc5 3173
d7a9c895
RN
3174 m_lib.StopMovie(m_movie);
3175 if(m_lib.GetMoviesError() != noErr)
ff4aedc5 3176 return false;
226ec5a7 3177
d7a9c895
RN
3178 m_lib.GoToBeginningOfMovie(m_movie);
3179 return m_lib.GetMoviesError() == noErr;
ff4aedc5
RN
3180}
3181
3182//---------------------------------------------------------------------------
c5191fbd 3183// wxQTMediaBackend::GetPlaybackRate
ff4aedc5 3184//
c5191fbd 3185// 1) Get the movie playback rate from ::GetMovieRate
ff4aedc5
RN
3186//---------------------------------------------------------------------------
3187double wxQTMediaBackend::GetPlaybackRate()
3188{
d7a9c895 3189 return ( ((double)m_lib.GetMovieRate(m_movie)) / 0x10000);
ff4aedc5
RN
3190}
3191
3192//---------------------------------------------------------------------------
c5191fbd 3193// wxQTMediaBackend::SetPlaybackRate
ff4aedc5 3194//
c5191fbd 3195// 1) Convert dRate to Fixed and Set the movie rate through SetMovieRate
ff4aedc5
RN
3196//---------------------------------------------------------------------------
3197bool wxQTMediaBackend::SetPlaybackRate(double dRate)
3198{
d7a9c895
RN
3199 m_lib.SetMovieRate(m_movie, (Fixed) (dRate * 0x10000));
3200 return m_lib.GetMoviesError() == noErr;
ff4aedc5
RN
3201}
3202
3203//---------------------------------------------------------------------------
c5191fbd 3204// wxQTMediaBackend::SetPosition
ff4aedc5 3205//
c5191fbd
VZ
3206// 1) Create a time record struct (TimeRecord) with appropriate values
3207// 2) Pass struct to SetMovieTime
ff4aedc5
RN
3208//---------------------------------------------------------------------------
3209bool wxQTMediaBackend::SetPosition(wxLongLong where)
3210{
c5191fbd
VZ
3211 //NB: For some reason SetMovieTime does not work
3212 //correctly with the Quicktime Windows SDK (6)
3213 //From Muskelkatermann at the wxForum
3214 //http://www.solidsteel.nl/users/wxwidgets/viewtopic.php?t=2957
3215 //RN - note that I have not verified this but there
3216 //is no harm in calling SetMovieTimeValue instead
3217#if 0
ff4aedc5
RN
3218 TimeRecord theTimeRecord;
3219 memset(&theTimeRecord, 0, sizeof(TimeRecord));
600ffb32 3220 theTimeRecord.value.lo = where.GetLo();
d7a9c895
RN
3221 theTimeRecord.scale = m_lib.GetMovieTimeScale(m_movie);
3222 theTimeRecord.base = m_lib.GetMovieTimeBase(m_movie);
3223 m_lib.SetMovieTime(m_movie, &theTimeRecord);
c5191fbd
VZ
3224#else
3225 m_lib.SetMovieTimeValue(m_movie, where.GetLo());
3226#endif
d7a9c895 3227 if (m_lib.GetMoviesError() != noErr)
ff4aedc5
RN
3228 return false;
3229
3230 return true;
3231}
3232
3233//---------------------------------------------------------------------------
e163773d 3234// wxQTMediaBackend::GetPosition
ff4aedc5 3235//
e163773d 3236// 1) Calls GetMovieTime to get the position we are in in the movie
8b5d5223 3237// in milliseconds (we called
ff4aedc5
RN
3238//---------------------------------------------------------------------------
3239wxLongLong wxQTMediaBackend::GetPosition()
3240{
d7a9c895 3241 return m_lib.GetMovieTime(m_movie, NULL);
ff4aedc5
RN
3242}
3243
6f8c67e7
JS
3244//---------------------------------------------------------------------------
3245// wxQTMediaBackend::GetVolume
3246//
3247// Gets the volume through GetMovieVolume - which returns a 16 bit short -
3248//
3249// +--------+--------+
3250// + (1) + (2) +
3251// +--------+--------+
3252//
3253// (1) first 8 bits are value before decimal
3254// (2) second 8 bits are value after decimal
3255//
3256// Volume ranges from -1.0 (gain but no sound), 0 (no sound and no gain) to
3257// 1 (full gain and sound)
3258//---------------------------------------------------------------------------
3259double wxQTMediaBackend::GetVolume()
3260{
3261 short sVolume = m_lib.GetMovieVolume(m_movie);
c5191fbd 3262 wxASSERT(m_lib.GetMoviesError() == noErr);
b11eba7e 3263
6f8c67e7
JS
3264 if(sVolume & (128 << 8)) //negative - no sound
3265 return 0.0;
3266
c5191fbd 3267 return sVolume/256.0;
6f8c67e7
JS
3268}
3269
3270//---------------------------------------------------------------------------
3271// wxQTMediaBackend::SetVolume
3272//
3273// Sets the volume through SetMovieVolume - which takes a 16 bit short -
3274//
3275// +--------+--------+
3276// + (1) + (2) +
3277// +--------+--------+
3278//
3279// (1) first 8 bits are value before decimal
3280// (2) second 8 bits are value after decimal
3281//
3282// Volume ranges from -1.0 (gain but no sound), 0 (no sound and no gain) to
3283// 1 (full gain and sound)
3284//---------------------------------------------------------------------------
3285bool wxQTMediaBackend::SetVolume(double dVolume)
3286{
c5191fbd
VZ
3287 m_lib.SetMovieVolume(m_movie, (short) (dVolume * 256));
3288 return m_lib.GetMoviesError() == noErr;
6f8c67e7
JS
3289}
3290
ff4aedc5 3291//---------------------------------------------------------------------------
c5191fbd 3292// wxQTMediaBackend::GetDuration
ff4aedc5 3293//
c5191fbd 3294// Calls GetMovieDuration
ff4aedc5
RN
3295//---------------------------------------------------------------------------
3296wxLongLong wxQTMediaBackend::GetDuration()
3297{
d7a9c895 3298 return m_lib.GetMovieDuration(m_movie);
ff4aedc5
RN
3299}
3300
3301//---------------------------------------------------------------------------
c5191fbd 3302// wxQTMediaBackend::GetState
ff4aedc5 3303//
c5191fbd
VZ
3304// Determines the current state - if we are at the beginning we
3305// are stopped
ff4aedc5
RN
3306//---------------------------------------------------------------------------
3307wxMediaState wxQTMediaBackend::GetState()
3308{
c5191fbd 3309 if (m_bPlaying == true)
ff4aedc5 3310 return wxMEDIASTATE_PLAYING;
c5191fbd
VZ
3311 else if ( !m_movie || wxQTMediaBackend::GetPosition() == 0)
3312 return wxMEDIASTATE_STOPPED;
ff4aedc5
RN
3313 else
3314 return wxMEDIASTATE_PAUSED;
3315}
3316
3317//---------------------------------------------------------------------------
c5191fbd 3318// wxQTMediaBackend::Cleanup
ff4aedc5 3319//
c5191fbd
VZ
3320// Diposes of the movie timer, Disassociates the Movie Controller with
3321// movie and hides it if it exists, and stops and disposes
3322// of the QT movie
ff4aedc5
RN
3323//---------------------------------------------------------------------------
3324void wxQTMediaBackend::Cleanup()
3325{
c5191fbd
VZ
3326 m_bPlaying = false;
3327
3328 if(m_timer)
3329 {
ff4aedc5
RN
3330 delete m_timer;
3331 m_timer = NULL;
c5191fbd 3332 }
ff4aedc5 3333
d7a9c895 3334 m_lib.StopMovie(m_movie);
c5191fbd
VZ
3335
3336 if(m_pMC)
3337 {
3338 Point thePoint;
3339 thePoint.h = thePoint.v = 0;
3340 m_lib.MCSetVisible(m_pMC, false);
3341 m_lib.MCSetMovie(m_pMC, NULL, NULL, thePoint);
3342 }
3343
d7a9c895 3344 m_lib.DisposeMovie(m_movie);
c5191fbd 3345 m_movie = NULL;
ff4aedc5
RN
3346}
3347
3348//---------------------------------------------------------------------------
c5191fbd 3349// wxQTMediaBackend::ShowPlayerControls
ff4aedc5 3350//
c5191fbd
VZ
3351// Creates a movie controller for the Movie if the user wants it
3352//---------------------------------------------------------------------------
3353bool wxQTMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
3354{
3355 if(m_pMC)
3356 {
3357 //restore old wndproc
3358 wxSetWindowProc((HWND)m_ctrl->GetHWND(), wxWndProc);
3359 m_lib.DisposeMovieController(m_pMC);
3360 m_pMC = NULL;
3361 m_bestSize.y -= 16; //movie controller height
3362 }
3363
3364 if(flags && m_movie)
3365 {
3366 Rect rect;
3367 wxRect wxrect = m_ctrl->GetClientRect();
3368
3369 //make room for controller
3370 if(wxrect.width < 320)
3371 wxrect.width = 320;
3372
3832f946
WS
3373 rect.top = (short)wxrect.y;
3374 rect.left = (short)wxrect.x;
3375 rect.right = (short)(rect.left + wxrect.width);
3376 rect.bottom = (short)(rect.top + wxrect.height);
c5191fbd
VZ
3377
3378 if(!m_pMC)
3379 {
3380 m_pMC = m_lib.NewMovieController(m_movie, &rect, mcTopLeftMovie |
3381 // mcScaleMovieToFit |
3382 // mcWithBadge |
3383 mcWithFrame);
3384 m_lib.MCDoAction(m_pMC, 32, (void*)true); //mcActionSetKeysEnabled
3385 m_lib.MCSetActionFilterWithRefCon(m_pMC,
3386 (WXFARPROC)wxQTMediaBackend::MCFilterProc, (void*)this);
3387 m_bestSize.y += 16; //movie controller height
3388
3389 //
3390 // By default the movie controller uses its own color
3391 // pallette for the movie which can be bad on some files -
3392 // so turn it off. Also turn off its frame/border for
3393 // the movie
3394 //
3395 // Also we take care of a couple of the interface flags here
3396 //
3397 long mcFlags = 0;
3398 m_lib.MCDoAction(m_pMC, 39/*mcActionGetFlags*/, (void*)&mcFlags);
3399 mcFlags |= ( //(1<<0)/*mcFlagSuppressMovieFrame*/ |
3400 (1<<3)/*mcFlagsUseWindowPalette*/
3401 | ((flags & wxMEDIACTRLPLAYERCONTROLS_STEP)
3402 ? 0 : (1<<1)/*mcFlagSuppressStepButtons*/)
3403 | ((flags & wxMEDIACTRLPLAYERCONTROLS_VOLUME)
3404 ? 0 : (1<<2)/*mcFlagSuppressSpeakerButton*/)
3405 // | (1<<4) /*mcFlagDontInvalidate*/ //if we take care of repainting ourselves
3406 );
3407 m_lib.MCDoAction(m_pMC, 38/*mcActionSetFlags*/, (void*)mcFlags);
3408
3409 //intercept the wndproc of our control window
3410 wxSetWindowProc((HWND)m_ctrl->GetHWND(),
3411 wxQTMediaBackend::QTWndProc);
3412
3413 //set the user data of our window
3414 wxSetWindowUserData((HWND)m_ctrl->GetHWND(), this);
3415 }
3416 }
3417
7e41b689 3418 NotifyMovieSizeChanged();
c5191fbd
VZ
3419
3420 return m_lib.GetMoviesError() == noErr;
3421}
3422
3423//---------------------------------------------------------------------------
3424// wxQTMediaBackend::MCFilterProc (static)
3425//
3426// Callback for when the movie controller recieves a message
3427//---------------------------------------------------------------------------
3428Boolean
3429wxQTMediaBackend::MCFilterProc(MovieController WXUNUSED(theController),
3430 short action,
3431 void * WXUNUSED(params),
3432 LONG_PTR refCon)
3433{
3434 if(action != 1) //don't process idle events
3435 {
3436 wxQTMediaBackend* pThis = (wxQTMediaBackend*)refCon;
3437
3438 switch(action)
3439 {
3440 case 8: //play button triggered - MC will set movie to opposite state
3441 //of current - playing ? paused : playing
3442 pThis->m_bPlaying = !(pThis->m_bPlaying);
3443
3444 // NB: Sometimes it doesn't redraw properly -
3445 // if you click on the button but don't move the mouse
3446 // the button will not change its state until you move
3447 // mcActionDraw and Refresh/Update combo do nothing
3448 // to help this unfortunately
3449 break;
3450 default:
3451 break;
3452 }
3453 }
3454 return 0;
3455}
3456
3457//---------------------------------------------------------------------------
3458// wxQTMediaBackend::GetVideoSize
3459//
3460// Returns the actual size of the QT movie
ff4aedc5
RN
3461//---------------------------------------------------------------------------
3462wxSize wxQTMediaBackend::GetVideoSize() const
3463{
3464 return m_bestSize;
3465}
3466
3467//---------------------------------------------------------------------------
3468// wxQTMediaBackend::Move
3469//
c5191fbd 3470// Sets the bounds of either the Movie or Movie Controller
ff4aedc5 3471//---------------------------------------------------------------------------
d7a9c895 3472void wxQTMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y), int w, int h)
ff4aedc5 3473{
c5191fbd 3474 if(m_movie)
ff4aedc5 3475 {
c5191fbd
VZ
3476 //make room for controller
3477 if(m_pMC)
3478 {
3479 if(w < 320)
3480 w = 320;
ff4aedc5 3481
c5191fbd
VZ
3482 Rect theRect = {0, 0, (short)h, (short)w};
3483 m_lib.MCSetControllerBoundsRect(m_pMC, &theRect);
3484 }
3485 else
3486 {
3487 Rect theRect = {0, 0, (short)h, (short)w};
d7a9c895 3488 m_lib.SetMovieBox(m_movie, &theRect);
c5191fbd
VZ
3489 }
3490
d7a9c895 3491 wxASSERT(m_lib.GetMoviesError() == noErr);
ff4aedc5
RN
3492 }
3493}
3494
c5191fbd
VZ
3495//---------------------------------------------------------------------------
3496// wxQTMediaBackend::OnEraseBackground
3497//
3498// Suggestion from Greg Hazel to repaint the movie when idle
3499// (on pause also)
3500//
3501// TODO: We may be repainting too much here - under what exact circumstances
3502// do we need this? I think Move also repaints correctly for the Movie
3503// Controller, so in that instance we don't need this either
3504//---------------------------------------------------------------------------
3505void wxQTMediaEvtHandler::OnEraseBackground(wxEraseEvent& evt)
3506{
6ab9bf57 3507 wxQuickTimeLibrary& m_pLib = m_qtb->m_lib;
c5191fbd 3508
6ab9bf57 3509 if ( m_qtb->m_pMC )
c5191fbd 3510 {
f10747d8 3511 // repaint movie controller
6ab9bf57 3512 m_pLib.MCDoAction(m_qtb->m_pMC, 2 /*mcActionDraw*/,
7e41b689 3513 m_pLib.GetNativeWindowPort(m_hwnd));
c5191fbd 3514 }
f10747d8 3515 else // no movie controller
c5191fbd 3516 {
f10747d8
VZ
3517 if ( m_qtb->m_movie )
3518 {
3519 CGrafPtr port = (CGrafPtr)m_pLib.GetNativeWindowPort(m_hwnd);
c5191fbd 3520
f10747d8
VZ
3521 m_pLib.BeginUpdate(port);
3522 m_pLib.UpdateMovie(m_qtb->m_movie);
3523 wxASSERT(m_pLib.GetMoviesError() == noErr);
3524 m_pLib.EndUpdate(port);
3525 }
3526 else // no movie
3527 {
3528 // let the system repaint the window
3529 evt.Skip();
3530 }
c5191fbd 3531 }
c5191fbd
VZ
3532}
3533
ff4aedc5 3534//---------------------------------------------------------------------------
1146983c 3535// End QT Backend
ff4aedc5 3536//---------------------------------------------------------------------------
ff4aedc5
RN
3537
3538//in source file that contains stuff you don't directly use
3539#include <wx/html/forcelnk.h>
3540FORCE_LINK_ME(basewxmediabackends);
3541
3542//---------------------------------------------------------------------------
3543// End wxMediaCtrl Compilation Guard and this file
3544//---------------------------------------------------------------------------
72259e00
RL
3545#endif //wxUSE_MEDIACTRL
3546
ff4aedc5 3547