]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/mediactrl_qt.cpp
Set missing Language: headers in PO files.
[wxWidgets.git] / src / msw / mediactrl_qt.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/msw/mediactrl_qt.cpp
3// Purpose: QuickTime Media Backend for Windows
4// Author: Ryan Norton <wxprojects@comcast.net>
5// Modified by: Robin Dunn (moved QT code from mediactrl.cpp)
6//
7// Created: 11/07/04
8// Copyright: (c) Ryan Norton
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12
13//===========================================================================
14// DECLARATIONS
15//===========================================================================
16
17//---------------------------------------------------------------------------
18// Pre-compiled header stuff
19//---------------------------------------------------------------------------
20
21// For compilers that support precompilation, includes "wx.h".
22#include "wx/wxprec.h"
23
24#ifdef __BORLANDC__
25 #pragma hdrstop
26#endif
27
28#if wxUSE_MEDIACTRL
29
30#include "wx/mediactrl.h"
31
32#ifndef WX_PRECOMP
33 #include "wx/log.h"
34 #include "wx/dcclient.h"
35 #include "wx/timer.h"
36 #include "wx/math.h" // log10 & pow
37#endif
38
39#include "wx/msw/private.h" // user info and wndproc setting/getting
40#include "wx/dynlib.h"
41
42//---------------------------------------------------------------------------
43// Externals (somewhere in src/msw/app.cpp and src/msw/window.cpp)
44//---------------------------------------------------------------------------
45extern "C" WXDLLIMPEXP_BASE HINSTANCE wxGetInstance(void);
46extern WXDLLIMPEXP_CORE const wxChar *wxCanvasClassName;
47
48LRESULT WXDLLIMPEXP_CORE APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
49 WPARAM wParam, LPARAM lParam);
50
51//---------------------------------------------------------------------------
52// Killed MSVC warnings
53//---------------------------------------------------------------------------
54//disable "cast truncates constant value" for VARIANT_BOOL values
55//passed as parameters in VC5 and up
56#ifdef _MSC_VER
57#pragma warning (disable:4310)
58#endif
59
60
61//---------------------------------------------------------------------------
62// wxQTMediaBackend
63//
64// We don't include Quicktime headers here and define all the types
65// ourselves because looking for the quicktime libaries etc. would
66// be tricky to do and making this a dependency for the MSVC projects
67// would be unrealistic.
68//
69// Thanks to Robert Roebling for the wxDL macro/library idea
70//---------------------------------------------------------------------------
71
72//---------------------------------------------------------------------------
73// QT Includes
74//---------------------------------------------------------------------------
75//#include <qtml.h> // Windoze QT include
76//#include <QuickTimeComponents.h> // Standard QT stuff
77#include "wx/dynlib.h"
78
79//---------------------------------------------------------------------------
80// QT Types
81//---------------------------------------------------------------------------
82typedef struct MovieRecord* Movie;
83typedef wxInt16 OSErr;
84typedef wxInt32 OSStatus;
85#define noErr 0
86#define fsRdPerm 1
87typedef unsigned char Str255[256];
88#define StringPtr unsigned char*
89#define newMovieActive 1
90#define newMovieAsyncOK (1 << 8)
91#define Ptr char*
92#define Handle Ptr*
93#define Fixed long
94#define OSType unsigned long
95#define CGrafPtr struct GrafPort *
96#define TimeScale long
97#define TimeBase struct TimeBaseRecord *
98typedef struct ComponentInstanceRecord * ComponentInstance;
99#define kMovieLoadStatePlayable 10000
100#define Boolean int
101#define MovieController ComponentInstance
102
103#ifndef URLDataHandlerSubType
104#if defined(__WATCOMC__) || defined(__MINGW32__)
105// use magic numbers for compilers which complain about multicharacter integers
106const OSType URLDataHandlerSubType = 1970433056;
107const OSType VisualMediaCharacteristic = 1702454643;
108#else
109const OSType URLDataHandlerSubType = 'url ';
110const OSType VisualMediaCharacteristic = 'eyes';
111#endif
112#endif
113
114struct FSSpec
115{
116 short vRefNum;
117 long parID;
118 Str255 name; // Str63 on mac, Str255 on msw
119};
120
121struct Rect
122{
123 short top;
124 short left;
125 short bottom;
126 short right;
127};
128
129struct wide
130{
131 wxInt32 hi;
132 wxUint32 lo;
133};
134
135struct TimeRecord
136{
137 wide value; // units
138 TimeScale scale; // units per second
139 TimeBase base;
140};
141
142struct Point
143{
144 short v;
145 short h;
146};
147
148struct EventRecord
149{
150 wxUint16 what;
151 wxUint32 message;
152 wxUint32 when;
153 Point where;
154 wxUint16 modifiers;
155};
156
157enum
158{
159 mcTopLeftMovie = 1,
160 mcScaleMovieToFit = 2,
161 mcWithBadge = 4,
162 mcNotVisible = 8,
163 mcWithFrame = 16
164};
165
166//---------------------------------------------------------------------------
167// QT Library
168//---------------------------------------------------------------------------
169
170class WXDLLIMPEXP_MEDIA wxQuickTimeLibrary
171{
172public:
173 ~wxQuickTimeLibrary()
174 {
175 if (m_dll.IsLoaded())
176 m_dll.Unload();
177 }
178
179 bool Initialize();
180 bool IsOk() const {return m_ok;}
181
182protected:
183 wxDynamicLibrary m_dll;
184 bool m_ok;
185
186public:
187 wxDL_VOIDMETHOD_DEFINE( StartMovie, (Movie m), (m) )
188 wxDL_VOIDMETHOD_DEFINE( StopMovie, (Movie m), (m) )
189 wxDL_METHOD_DEFINE( bool, IsMovieDone, (Movie m), (m), false)
190 wxDL_VOIDMETHOD_DEFINE( GoToBeginningOfMovie, (Movie m), (m) )
191 wxDL_METHOD_DEFINE( OSErr, GetMoviesError, (), (), -1)
192 wxDL_METHOD_DEFINE( OSErr, EnterMovies, (), (), -1)
193 wxDL_VOIDMETHOD_DEFINE( ExitMovies, (), () )
194 wxDL_METHOD_DEFINE( OSErr, InitializeQTML, (long flags), (flags), -1)
195 wxDL_VOIDMETHOD_DEFINE( TerminateQTML, (), () )
196
197 wxDL_METHOD_DEFINE( OSErr, NativePathNameToFSSpec,
198 (char* inName, FSSpec* outFile, long flags),
199 (inName, outFile, flags), -1)
200
201 wxDL_METHOD_DEFINE( OSErr, OpenMovieFile,
202 (const FSSpec * fileSpec, short * resRefNum, wxInt8 permission),
203 (fileSpec, resRefNum, permission), -1 )
204
205 wxDL_METHOD_DEFINE( OSErr, CloseMovieFile,
206 (short resRefNum), (resRefNum), -1)
207
208 wxDL_METHOD_DEFINE( OSErr, NewMovieFromFile,
209 (Movie * theMovie, short resRefNum, short * resId,
210 StringPtr resName, short newMovieFlags,
211 bool * dataRefWasChanged),
212 (theMovie, resRefNum, resId, resName, newMovieFlags,
213 dataRefWasChanged), -1)
214
215 wxDL_VOIDMETHOD_DEFINE( SetMovieRate, (Movie m, Fixed rate), (m, rate) )
216 wxDL_METHOD_DEFINE( Fixed, GetMovieRate, (Movie m), (m), 0)
217 wxDL_VOIDMETHOD_DEFINE( MoviesTask, (Movie m, long maxms), (m, maxms) )
218 wxDL_VOIDMETHOD_DEFINE( BlockMove,
219 (const char* p1, const char* p2, long s), (p1,p2,s) )
220 wxDL_METHOD_DEFINE( Handle, NewHandleClear, (long s), (s), NULL )
221
222 wxDL_METHOD_DEFINE( OSErr, NewMovieFromDataRef,
223 (Movie * m, short flags, short * id,
224 Handle dataRef, OSType dataRefType),
225 (m,flags,id,dataRef,dataRefType), -1 )
226
227 wxDL_VOIDMETHOD_DEFINE( DisposeHandle, (Handle h), (h) )
228 wxDL_VOIDMETHOD_DEFINE( GetMovieNaturalBoundsRect, (Movie m, Rect* r), (m,r) )
229 wxDL_METHOD_DEFINE( void*, GetMovieIndTrackType,
230 (Movie m, long index, OSType type, long flags),
231 (m,index,type,flags), NULL )
232 wxDL_VOIDMETHOD_DEFINE( CreatePortAssociation,
233 (void* hWnd, void* junk, long morejunk), (hWnd, junk, morejunk) )
234 wxDL_METHOD_DEFINE(void*, GetNativeWindowPort, (void* hWnd), (hWnd), NULL)
235 wxDL_VOIDMETHOD_DEFINE(SetMovieGWorld, (Movie m, CGrafPtr port, void* whatever),
236 (m, port, whatever) )
237 wxDL_VOIDMETHOD_DEFINE(DisposeMovie, (Movie m), (m) )
238 wxDL_VOIDMETHOD_DEFINE(SetMovieBox, (Movie m, Rect* r), (m,r))
239 wxDL_VOIDMETHOD_DEFINE(SetMovieTimeScale, (Movie m, long s), (m,s))
240 wxDL_METHOD_DEFINE(long, GetMovieDuration, (Movie m), (m), 0)
241 wxDL_METHOD_DEFINE(TimeBase, GetMovieTimeBase, (Movie m), (m), 0)
242 wxDL_METHOD_DEFINE(TimeScale, GetMovieTimeScale, (Movie m), (m), 0)
243 wxDL_METHOD_DEFINE(long, GetMovieTime, (Movie m, void* cruft), (m,cruft), 0)
244 wxDL_VOIDMETHOD_DEFINE(SetMovieTime, (Movie m, TimeRecord* tr), (m,tr) )
245 wxDL_METHOD_DEFINE(short, GetMovieVolume, (Movie m), (m), 0)
246 wxDL_VOIDMETHOD_DEFINE(SetMovieVolume, (Movie m, short sVolume), (m,sVolume) )
247 wxDL_VOIDMETHOD_DEFINE(SetMovieTimeValue, (Movie m, long s), (m,s))
248 wxDL_METHOD_DEFINE(ComponentInstance, NewMovieController, (Movie m, const Rect* mr, long fl), (m,mr,fl), 0)
249 wxDL_VOIDMETHOD_DEFINE(DisposeMovieController, (ComponentInstance ci), (ci))
250 wxDL_METHOD_DEFINE(int, MCSetVisible, (ComponentInstance m, int b), (m, b), 0)
251
252 wxDL_VOIDMETHOD_DEFINE(PrePrerollMovie, (Movie m, long t, Fixed r, WXFARPROC p1, void* p2), (m,t,r,p1,p2) )
253 wxDL_VOIDMETHOD_DEFINE(PrerollMovie, (Movie m, long t, Fixed r), (m,t,r) )
254 wxDL_METHOD_DEFINE(Fixed, GetMoviePreferredRate, (Movie m), (m), 0)
255 wxDL_METHOD_DEFINE(long, GetMovieLoadState, (Movie m), (m), 0)
256 wxDL_METHOD_DEFINE(void*, NewRoutineDescriptor, (WXFARPROC f, int l, void* junk), (f, l, junk), 0)
257 wxDL_VOIDMETHOD_DEFINE(DisposeRoutineDescriptor, (void* f), (f))
258 wxDL_METHOD_DEFINE(void*, GetCurrentArchitecture, (), (), 0)
259 wxDL_METHOD_DEFINE(int, MCDoAction, (ComponentInstance ci, long f, void* p), (ci,f,p), 0)
260 wxDL_VOIDMETHOD_DEFINE(MCSetControllerBoundsRect, (ComponentInstance ci, Rect* r), (ci,r))
261 wxDL_VOIDMETHOD_DEFINE(DestroyPortAssociation, (CGrafPtr g), (g))
262 wxDL_VOIDMETHOD_DEFINE(NativeEventToMacEvent, (MSG* p1, EventRecord* p2), (p1,p2))
263 wxDL_VOIDMETHOD_DEFINE(MCIsPlayerEvent, (ComponentInstance ci, EventRecord* p2), (ci, p2))
264 wxDL_METHOD_DEFINE(int, MCSetMovie, (ComponentInstance ci, Movie m, void* p1, Point w),
265 (ci,m,p1,w),0)
266 wxDL_VOIDMETHOD_DEFINE(MCPositionController,
267 (ComponentInstance ci, Rect* r, void* junk, void* morejunk), (ci,r,junk,morejunk))
268 wxDL_VOIDMETHOD_DEFINE(MCSetActionFilterWithRefCon,
269 (ComponentInstance ci, WXFARPROC cb, void* ref), (ci,cb,ref))
270 wxDL_VOIDMETHOD_DEFINE(MCGetControllerInfo, (MovieController mc, long* flags), (mc,flags))
271 wxDL_VOIDMETHOD_DEFINE(BeginUpdate, (CGrafPtr port), (port))
272 wxDL_VOIDMETHOD_DEFINE(UpdateMovie, (Movie m), (m))
273 wxDL_VOIDMETHOD_DEFINE(EndUpdate, (CGrafPtr port), (port))
274 wxDL_METHOD_DEFINE( OSErr, GetMoviesStickyError, (), (), -1)
275};
276
277bool wxQuickTimeLibrary::Initialize()
278{
279 // Turn off the wxDynamicLibrary logging as we're prepared to handle the
280 // errors
281 wxLogNull nolog;
282
283 m_ok = m_dll.Load(wxT("qtmlClient.dll"));
284 if ( !m_ok )
285 return false;
286
287 wxDL_METHOD_LOAD( m_dll, StartMovie );
288 wxDL_METHOD_LOAD( m_dll, StopMovie );
289 wxDL_METHOD_LOAD( m_dll, IsMovieDone );
290 wxDL_METHOD_LOAD( m_dll, GoToBeginningOfMovie );
291 wxDL_METHOD_LOAD( m_dll, GetMoviesError );
292 wxDL_METHOD_LOAD( m_dll, EnterMovies );
293 wxDL_METHOD_LOAD( m_dll, ExitMovies );
294 wxDL_METHOD_LOAD( m_dll, InitializeQTML );
295 wxDL_METHOD_LOAD( m_dll, TerminateQTML );
296 wxDL_METHOD_LOAD( m_dll, NativePathNameToFSSpec );
297 wxDL_METHOD_LOAD( m_dll, OpenMovieFile );
298 wxDL_METHOD_LOAD( m_dll, CloseMovieFile );
299 wxDL_METHOD_LOAD( m_dll, NewMovieFromFile );
300 wxDL_METHOD_LOAD( m_dll, GetMovieRate );
301 wxDL_METHOD_LOAD( m_dll, SetMovieRate );
302 wxDL_METHOD_LOAD( m_dll, MoviesTask );
303 wxDL_METHOD_LOAD( m_dll, BlockMove );
304 wxDL_METHOD_LOAD( m_dll, NewHandleClear );
305 wxDL_METHOD_LOAD( m_dll, NewMovieFromDataRef );
306 wxDL_METHOD_LOAD( m_dll, DisposeHandle );
307 wxDL_METHOD_LOAD( m_dll, GetMovieNaturalBoundsRect );
308 wxDL_METHOD_LOAD( m_dll, GetMovieIndTrackType );
309 wxDL_METHOD_LOAD( m_dll, CreatePortAssociation );
310 wxDL_METHOD_LOAD( m_dll, DestroyPortAssociation );
311 wxDL_METHOD_LOAD( m_dll, GetNativeWindowPort );
312 wxDL_METHOD_LOAD( m_dll, SetMovieGWorld );
313 wxDL_METHOD_LOAD( m_dll, DisposeMovie );
314 wxDL_METHOD_LOAD( m_dll, SetMovieBox );
315 wxDL_METHOD_LOAD( m_dll, SetMovieTimeScale );
316 wxDL_METHOD_LOAD( m_dll, GetMovieDuration );
317 wxDL_METHOD_LOAD( m_dll, GetMovieTimeBase );
318 wxDL_METHOD_LOAD( m_dll, GetMovieTimeScale );
319 wxDL_METHOD_LOAD( m_dll, GetMovieTime );
320 wxDL_METHOD_LOAD( m_dll, SetMovieTime );
321 wxDL_METHOD_LOAD( m_dll, GetMovieVolume );
322 wxDL_METHOD_LOAD( m_dll, SetMovieVolume );
323 wxDL_METHOD_LOAD( m_dll, SetMovieTimeValue );
324 wxDL_METHOD_LOAD( m_dll, NewMovieController );
325 wxDL_METHOD_LOAD( m_dll, DisposeMovieController );
326 wxDL_METHOD_LOAD( m_dll, MCSetVisible );
327 wxDL_METHOD_LOAD( m_dll, PrePrerollMovie );
328 wxDL_METHOD_LOAD( m_dll, PrerollMovie );
329 wxDL_METHOD_LOAD( m_dll, GetMoviePreferredRate );
330 wxDL_METHOD_LOAD( m_dll, GetMovieLoadState );
331 wxDL_METHOD_LOAD( m_dll, MCDoAction );
332 wxDL_METHOD_LOAD( m_dll, MCSetControllerBoundsRect );
333 wxDL_METHOD_LOAD( m_dll, NativeEventToMacEvent );
334 wxDL_METHOD_LOAD( m_dll, MCIsPlayerEvent );
335 wxDL_METHOD_LOAD( m_dll, MCSetMovie );
336 wxDL_METHOD_LOAD( m_dll, MCSetActionFilterWithRefCon );
337 wxDL_METHOD_LOAD( m_dll, MCGetControllerInfo );
338 wxDL_METHOD_LOAD( m_dll, BeginUpdate );
339 wxDL_METHOD_LOAD( m_dll, UpdateMovie );
340 wxDL_METHOD_LOAD( m_dll, EndUpdate );
341 wxDL_METHOD_LOAD( m_dll, GetMoviesStickyError );
342
343 return m_ok;
344}
345
346class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackendCommonBase
347{
348public:
349 wxQTMediaBackend();
350 virtual ~wxQTMediaBackend();
351
352 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
353 wxWindowID id,
354 const wxPoint& pos,
355 const wxSize& size,
356 long style,
357 const wxValidator& validator,
358 const wxString& name);
359
360 virtual bool Play();
361 virtual bool Pause();
362 virtual bool Stop();
363
364 virtual bool Load(const wxURI& location,
365 const wxURI& proxy)
366 { return wxMediaBackend::Load(location, proxy); }
367
368 virtual bool Load(const wxString& fileName);
369 virtual bool Load(const wxURI& location);
370
371 virtual wxMediaState GetState();
372
373 virtual bool SetPosition(wxLongLong where);
374 virtual wxLongLong GetPosition();
375 virtual wxLongLong GetDuration();
376
377 virtual void Move(int x, int y, int w, int h);
378 wxSize GetVideoSize() const;
379
380 virtual double GetPlaybackRate();
381 virtual bool SetPlaybackRate(double dRate);
382
383 virtual double GetVolume();
384 virtual bool SetVolume(double);
385
386 void Cleanup();
387 void FinishLoad();
388
389 static void PPRMProc (Movie theMovie, OSErr theErr, void* theRefCon);
390
391 // TODO: Last param actually long - does this work on 64bit machines?
392 static Boolean MCFilterProc(MovieController theController,
393 short action, void *params, LONG_PTR refCon);
394
395 static LRESULT CALLBACK QTWndProc(HWND, UINT, WPARAM, LPARAM);
396
397 virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags);
398
399 wxSize m_bestSize; // Original movie size
400 Movie m_movie; // QT Movie handle/instance
401 bool m_bVideo; // Whether or not we have video
402 bool m_bPlaying; // Whether or not movie is playing
403 wxTimer* m_timer; // Load or Play timer
404 wxQuickTimeLibrary m_lib; // DLL to load functions from
405 ComponentInstance m_pMC; // Movie Controller
406 wxEvtHandler* m_evthandler;
407
408 friend class wxQTMediaEvtHandler;
409
410 DECLARE_DYNAMIC_CLASS(wxQTMediaBackend)
411};
412
413// helper to hijack background erasing for the QT window
414class WXDLLIMPEXP_MEDIA wxQTMediaEvtHandler : public wxEvtHandler
415{
416public:
417 wxQTMediaEvtHandler(wxQTMediaBackend *qtb, WXHWND hwnd)
418 {
419 m_qtb = qtb;
420 m_hwnd = hwnd;
421
422 m_qtb->m_ctrl->Connect(m_qtb->m_ctrl->GetId(),
423 wxEVT_ERASE_BACKGROUND,
424 wxEraseEventHandler(wxQTMediaEvtHandler::OnEraseBackground),
425 NULL, this);
426 }
427
428 void OnEraseBackground(wxEraseEvent& event);
429
430private:
431 wxQTMediaBackend *m_qtb;
432 WXHWND m_hwnd;
433
434 wxDECLARE_NO_COPY_CLASS(wxQTMediaEvtHandler);
435};
436
437
438//===========================================================================
439// IMPLEMENTATION
440//===========================================================================
441
442
443//---------------------------------------------------------------------------
444// wxQTMediaBackend
445//
446// TODO: Use a less kludgy way to pause/get state/set state
447// FIXME: Greg Hazel reports that sometimes files that cannot be played
448// with this backend are treated as playable anyway - not verified though.
449//---------------------------------------------------------------------------
450
451IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend)
452
453// Time between timer calls - this is the Apple recommendation to the TCL
454// team I believe
455#define MOVIE_DELAY 20
456
457//---------------------------------------------------------------------------
458// wxQTLoadTimer
459//
460// QT, esp. QT for Windows is very picky about how you go about
461// async loading. If you were to go through a Windows message loop
462// or a MoviesTask or both and then check the movie load state
463// it would still return 1000 (loading)... even (pre)prerolling doesn't
464// help. However, making a load timer like this works
465//---------------------------------------------------------------------------
466class wxQTLoadTimer : public wxTimer
467{
468public:
469 wxQTLoadTimer(Movie movie, wxQTMediaBackend* parent, wxQuickTimeLibrary* pLib) :
470 m_movie(movie), m_parent(parent), m_pLib(pLib) {}
471
472 void Notify()
473 {
474 m_pLib->MoviesTask(m_movie, 0);
475 // kMovieLoadStatePlayable
476 if (m_pLib->GetMovieLoadState(m_movie) >= 10000)
477 {
478 m_parent->FinishLoad();
479 delete this;
480 }
481 }
482
483protected:
484 Movie m_movie; //Our movie instance
485 wxQTMediaBackend* m_parent; //Backend pointer
486 wxQuickTimeLibrary* m_pLib; //Interfaces
487};
488
489
490// --------------------------------------------------------------------------
491// wxQTPlayTimer - Handle Asyncronous Playing
492//
493// 1) Checks to see if the movie is done, and if not continues
494// streaming the movie
495// 2) Sends the wxEVT_MEDIA_STOP event if we have reached the end of
496// the movie.
497// --------------------------------------------------------------------------
498class wxQTPlayTimer : public wxTimer
499{
500public:
501 wxQTPlayTimer(Movie movie, wxQTMediaBackend* parent,
502 wxQuickTimeLibrary* pLib) :
503 m_movie(movie), m_parent(parent), m_pLib(pLib) {}
504
505 void Notify()
506 {
507 //
508 // OK, a little explaining - basically originally
509 // we only called MoviesTask if the movie was actually
510 // playing (not paused or stopped)... this was before
511 // we realized MoviesTask actually handles repainting
512 // of the current frame - so if you were to resize
513 // or something it would previously not redraw that
514 // portion of the movie.
515 //
516 // So now we call MoviesTask always so that it repaints
517 // correctly.
518 //
519 m_pLib->MoviesTask(m_movie, 0);
520
521 //
522 // Handle the stop event - if the movie has reached
523 // the end, notify our handler
524 //
525 // m_bPlaying == !(Stopped | Paused)
526 //
527 if (m_parent->m_bPlaying)
528 {
529 if (m_pLib->IsMovieDone(m_movie))
530 {
531 if ( m_parent->SendStopEvent() )
532 {
533 m_parent->Stop();
534 wxASSERT(m_pLib->GetMoviesError() == noErr);
535
536 m_parent->QueueFinishEvent();
537 }
538 }
539 }
540 }
541
542protected:
543 Movie m_movie; // Our movie instance
544 wxQTMediaBackend* m_parent; //Backend pointer
545 wxQuickTimeLibrary* m_pLib; //Interfaces
546};
547
548
549//---------------------------------------------------------------------------
550// wxQTMediaBackend::QTWndProc
551//
552// Forwards events to the Movie Controller so that it can
553// redraw itself/process messages etc..
554//---------------------------------------------------------------------------
555LRESULT CALLBACK wxQTMediaBackend::QTWndProc(HWND hWnd, UINT nMsg,
556 WPARAM wParam, LPARAM lParam)
557{
558 wxQTMediaBackend* pThis = (wxQTMediaBackend*)wxGetWindowUserData(hWnd);
559
560 MSG msg;
561 msg.hwnd = hWnd;
562 msg.message = nMsg;
563 msg.wParam = wParam;
564 msg.lParam = lParam;
565 msg.time = 0;
566 msg.pt.x = 0;
567 msg.pt.y = 0;
568 EventRecord theEvent;
569 pThis->m_lib.NativeEventToMacEvent(&msg, &theEvent);
570 pThis->m_lib.MCIsPlayerEvent(pThis->m_pMC, &theEvent);
571
572 return pThis->m_ctrl->MSWWindowProc(nMsg, wParam, lParam);
573}
574
575//---------------------------------------------------------------------------
576// wxQTMediaBackend Destructor
577//
578// Sets m_timer to NULL signifying we havn't loaded anything yet
579//---------------------------------------------------------------------------
580wxQTMediaBackend::wxQTMediaBackend()
581: m_movie(NULL), m_bPlaying(false), m_timer(NULL), m_pMC(NULL)
582{
583 m_evthandler = NULL;
584}
585
586//---------------------------------------------------------------------------
587// wxQTMediaBackend Destructor
588//
589// 1) Cleans up the QuickTime movie instance
590// 2) Decrements the QuickTime reference counter - if this reaches
591// 0, QuickTime shuts down
592// 3) Decrements the QuickTime Windows Media Layer reference counter -
593// if this reaches 0, QuickTime shuts down the Windows Media Layer
594//---------------------------------------------------------------------------
595wxQTMediaBackend::~wxQTMediaBackend()
596{
597 if (m_movie)
598 Cleanup();
599
600 if (m_lib.IsOk())
601 {
602 if (m_pMC)
603 {
604 m_lib.DisposeMovieController(m_pMC);
605 // m_pMC = NULL;
606 }
607
608 // destroy wxQTMediaEvtHandler we pushed on it
609 if (m_evthandler)
610 {
611 m_ctrl->RemoveEventHandler(m_evthandler);
612 delete m_evthandler;
613 }
614
615 m_lib.DestroyPortAssociation(
616 (CGrafPtr)m_lib.GetNativeWindowPort(m_ctrl->GetHWND()));
617
618 //Note that ExitMovies() is not necessary, but
619 //the docs are fuzzy on whether or not TerminateQTML is
620 m_lib.ExitMovies();
621 m_lib.TerminateQTML();
622 }
623}
624
625//---------------------------------------------------------------------------
626// wxQTMediaBackend::CreateControl
627//
628// 1) Intializes QuickTime
629// 2) Creates the control window
630//---------------------------------------------------------------------------
631bool wxQTMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
632 wxWindowID id,
633 const wxPoint& pos,
634 const wxSize& size,
635 long style,
636 const wxValidator& validator,
637 const wxString& name)
638{
639 if (!m_lib.Initialize())
640 return false;
641
642 int nError = m_lib.InitializeQTML(0);
643 if (nError != noErr) //-2093 no dll
644 {
645 wxFAIL_MSG(wxString::Format(wxT("Couldn't Initialize Quicktime-%i"), nError));
646 return false;
647 }
648
649 m_lib.EnterMovies();
650
651 // Create window
652 // By default wxWindow(s) is created with a border -
653 // so we need to get rid of those
654 //
655 // Since we don't have a child window like most other
656 // backends, we don't need wxCLIP_CHILDREN
657 if ( !ctrl->wxControl::Create(parent, id, pos, size,
658 (style & ~wxBORDER_MASK) | wxBORDER_NONE,
659 validator, name) )
660 {
661 return false;
662 }
663
664 m_ctrl = wxStaticCast(ctrl, wxMediaCtrl);
665
666 // Create a port association for our window so we
667 // can use it as a WindowRef
668 m_lib.CreatePortAssociation(m_ctrl->GetHWND(), NULL, 0L);
669
670 // Part of a suggestion from Greg Hazel
671 // to repaint movie when idle
672 m_evthandler = new wxQTMediaEvtHandler(this, m_ctrl->GetHWND());
673 m_ctrl->PushEventHandler(m_evthandler);
674
675 // done
676 return true;
677}
678
679//---------------------------------------------------------------------------
680// wxQTMediaBackend::Load (file version)
681//
682// 1) Get an FSSpec from the Windows path name
683// 2) Open the movie
684// 3) Obtain the movie instance from the movie resource
685// 4) Close the movie resource
686// 5) Finish loading
687//---------------------------------------------------------------------------
688bool wxQTMediaBackend::Load(const wxString& fileName)
689{
690 if (m_movie)
691 Cleanup();
692
693 short movieResFile = 0; //= 0 because of annoying VC6 warning
694 FSSpec sfFile;
695
696 OSErr err = m_lib.NativePathNameToFSSpec(
697 (char*) (const char*) fileName.mb_str(),
698 &sfFile, 0);
699 bool result = (err == noErr);
700
701 if (result)
702 {
703 err = m_lib.OpenMovieFile(&sfFile, &movieResFile, fsRdPerm);
704 result = (err == noErr);
705 }
706
707 if (result)
708 {
709 short movieResID = 0;
710 Str255 movieName;
711
712 err = m_lib.NewMovieFromFile(
713 &m_movie,
714 movieResFile,
715 &movieResID,
716 movieName,
717 newMovieActive,
718 NULL ); // wasChanged
719 result = (err == noErr /*&& m_lib.GetMoviesStickyError() == noErr*/);
720
721 // check m_lib.GetMoviesStickyError() because it may not find the
722 // proper codec and play black video and other strange effects,
723 // not to mention mess up the dynamic backend loading scheme
724 // of wxMediaCtrl - so it just does what the QuickTime player does
725 if (result)
726 {
727 m_lib.CloseMovieFile(movieResFile);
728 FinishLoad();
729 }
730 }
731
732 return result;
733}
734
735//---------------------------------------------------------------------------
736// wxQTMediaBackend::PPRMProc (static)
737//
738// Called when done PrePrerolling the movie.
739// Note that in 99% of the cases this does nothing...
740// Anyway we set up the loading timer here to tell us when the movie is done
741//---------------------------------------------------------------------------
742void wxQTMediaBackend::PPRMProc (Movie theMovie,
743 OSErr WXUNUSED_UNLESS_DEBUG(theErr),
744 void* theRefCon)
745{
746 wxASSERT( theMovie );
747 wxASSERT( theRefCon );
748 wxASSERT( theErr == noErr );
749
750 wxQTMediaBackend* pBE = (wxQTMediaBackend*) theRefCon;
751
752 long lTime = pBE->m_lib.GetMovieTime(theMovie,NULL);
753 Fixed rate = pBE->m_lib.GetMoviePreferredRate(theMovie);
754 pBE->m_lib.PrerollMovie(theMovie, lTime, rate);
755 pBE->m_timer = new wxQTLoadTimer(pBE->m_movie, pBE, &pBE->m_lib);
756 pBE->m_timer->Start(MOVIE_DELAY);
757}
758
759//---------------------------------------------------------------------------
760// wxQTMediaBackend::Load (URL Version)
761//
762// 1) Build an escaped URI from location
763// 2) Create a handle to store the URI string
764// 3) Put the URI string inside the handle
765// 4) Make a QuickTime URL data ref from the handle with the URI in it
766// 5) Clean up the URI string handle
767// 6) Do some prerolling
768// 7) Finish Loading
769//---------------------------------------------------------------------------
770bool wxQTMediaBackend::Load(const wxURI& location)
771{
772 if (m_movie)
773 Cleanup();
774
775 wxString theURI = location.BuildURI();
776
777 Handle theHandle = m_lib.NewHandleClear(theURI.length() + 1);
778 wxASSERT(theHandle);
779
780 m_lib.BlockMove(theURI.mb_str(), *theHandle, theURI.length() + 1);
781
782 // create the movie from the handle that refers to the URI
783 OSErr err = m_lib.NewMovieFromDataRef(&m_movie, newMovieActive |
784 newMovieAsyncOK
785 /* | newMovieIdleImportOK */,
786 NULL, theHandle,
787 URLDataHandlerSubType);
788
789 m_lib.DisposeHandle(theHandle);
790
791 if (err == noErr)
792 {
793 long timeNow;
794 Fixed playRate;
795
796 timeNow = m_lib.GetMovieTime(m_movie, NULL);
797 wxASSERT(m_lib.GetMoviesError() == noErr);
798
799 playRate = m_lib.GetMoviePreferredRate(m_movie);
800 wxASSERT(m_lib.GetMoviesError() == noErr);
801
802 // Note that the callback here is optional,
803 // but without it PrePrerollMovie can be buggy
804 // (see Apple ml). Also, some may wonder
805 // why we need this at all - this is because
806 // Apple docs say QuickTime streamed movies
807 // require it if you don't use a Movie Controller,
808 // which we don't by default.
809 //
810 m_lib.PrePrerollMovie(m_movie, timeNow, playRate,
811 (WXFARPROC)wxQTMediaBackend::PPRMProc,
812 (void*)this);
813
814 return true;
815 }
816 else
817 return false;
818}
819
820//---------------------------------------------------------------------------
821// wxQTMediaBackend::FinishLoad
822//
823// 1) Create the movie timer
824// 2) Get real size of movie for GetBestSize/sizers
825// 3) Set the movie time scale to something usable so that seeking
826// etc. will work correctly
827// 4) Set our Movie Controller to display the movie if it exists,
828// otherwise set the bounds of the Movie
829// 5) Refresh parent window
830//---------------------------------------------------------------------------
831void wxQTMediaBackend::FinishLoad()
832{
833 // Create the playing/streaming timer
834 m_timer = new wxQTPlayTimer(m_movie, (wxQTMediaBackend*) this, &m_lib);
835 wxASSERT(m_timer);
836
837 m_timer->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS);
838
839 // get the real size of the movie
840 Rect outRect;
841 memset(&outRect, 0, sizeof(Rect)); // suppress annoying VC6 warning
842 m_lib.GetMovieNaturalBoundsRect (m_movie, &outRect);
843 wxASSERT(m_lib.GetMoviesError() == noErr);
844
845 m_bestSize.x = outRect.right - outRect.left;
846 m_bestSize.y = outRect.bottom - outRect.top;
847
848 // Handle the movie GWorld
849 if (m_pMC)
850 {
851 Point thePoint;
852 thePoint.h = thePoint.v = 0;
853 m_lib.MCSetMovie(m_pMC, m_movie,
854 m_lib.GetNativeWindowPort(m_ctrl->GetHandle()),
855 thePoint);
856 m_lib.MCSetVisible(m_pMC, true);
857 m_bestSize.y += 16;
858 }
859 else
860 {
861 m_lib.SetMovieGWorld(m_movie,
862 (CGrafPtr) m_lib.GetNativeWindowPort(m_ctrl->GetHWND()),
863 NULL);
864 }
865
866 // Set the movie to millisecond precision
867 m_lib.SetMovieTimeScale(m_movie, 1000);
868 wxASSERT(m_lib.GetMoviesError() == noErr);
869
870 NotifyMovieLoaded();
871}
872
873//---------------------------------------------------------------------------
874// wxQTMediaBackend::Play
875//
876// 1) Start the QT movie
877// 2) Start the movie loading timer
878//
879// NOTE: This will still return success even when
880// the movie is still loading, and as mentioned in wxQTLoadTimer
881// I don't know of a way to force this to be sync - so if its
882// still loading the function will return true but the movie will
883// still be in the stopped state
884//---------------------------------------------------------------------------
885bool wxQTMediaBackend::Play()
886{
887 m_lib.StartMovie(m_movie);
888 m_bPlaying = true;
889
890 return m_lib.GetMoviesError() == noErr;
891}
892
893//---------------------------------------------------------------------------
894// wxQTMediaBackend::Pause
895//
896// 1) Stop the movie
897// 2) Stop the movie timer
898//---------------------------------------------------------------------------
899bool wxQTMediaBackend::Pause()
900{
901 m_bPlaying = false;
902 m_lib.StopMovie(m_movie);
903
904 return m_lib.GetMoviesError() == noErr;
905}
906
907//---------------------------------------------------------------------------
908// wxQTMediaBackend::Stop
909//
910// 1) Stop the movie
911// 2) Stop the movie timer
912// 3) Seek to the beginning of the movie
913//---------------------------------------------------------------------------
914bool wxQTMediaBackend::Stop()
915{
916 m_bPlaying = false;
917
918 m_lib.StopMovie(m_movie);
919 if (m_lib.GetMoviesError() == noErr)
920 m_lib.GoToBeginningOfMovie(m_movie);
921
922 return m_lib.GetMoviesError() == noErr;
923}
924
925//---------------------------------------------------------------------------
926// wxQTMediaBackend::GetPlaybackRate
927//
928// Get the movie playback rate from ::GetMovieRate
929//---------------------------------------------------------------------------
930double wxQTMediaBackend::GetPlaybackRate()
931{
932 return ( ((double)m_lib.GetMovieRate(m_movie)) / 0x10000);
933}
934
935//---------------------------------------------------------------------------
936// wxQTMediaBackend::SetPlaybackRate
937//
938// Convert dRate to Fixed and Set the movie rate through SetMovieRate
939//---------------------------------------------------------------------------
940bool wxQTMediaBackend::SetPlaybackRate(double dRate)
941{
942 m_lib.SetMovieRate(m_movie, (Fixed) (dRate * 0x10000));
943
944 return m_lib.GetMoviesError() == noErr;
945}
946
947//---------------------------------------------------------------------------
948// wxQTMediaBackend::SetPosition
949//
950// 1) Create a time record struct (TimeRecord) with appropriate values
951// 2) Pass struct to SetMovieTime
952//---------------------------------------------------------------------------
953bool wxQTMediaBackend::SetPosition(wxLongLong where)
954{
955 // NB: For some reason SetMovieTime does not work
956 // correctly with the Quicktime Windows SDK (6)
957 // From Muskelkatermann at the wxForum
958 // http://www.solidsteel.nl/users/wxwidgets/viewtopic.php?t=2957
959 // RN - note that I have not verified this but there
960 // is no harm in calling SetMovieTimeValue instead
961#if 0
962 TimeRecord theTimeRecord;
963 memset(&theTimeRecord, 0, sizeof(TimeRecord));
964 theTimeRecord.value.lo = where.GetLo();
965 theTimeRecord.scale = m_lib.GetMovieTimeScale(m_movie);
966 theTimeRecord.base = m_lib.GetMovieTimeBase(m_movie);
967 m_lib.SetMovieTime(m_movie, &theTimeRecord);
968#else
969 m_lib.SetMovieTimeValue(m_movie, where.GetLo());
970#endif
971
972 return (m_lib.GetMoviesError() == noErr);
973}
974
975//---------------------------------------------------------------------------
976// wxQTMediaBackend::GetPosition
977//
978// 1) Calls GetMovieTime to get the position we are in in the movie
979// in milliseconds (we called
980//---------------------------------------------------------------------------
981wxLongLong wxQTMediaBackend::GetPosition()
982{
983 return m_lib.GetMovieTime(m_movie, NULL);
984}
985
986//---------------------------------------------------------------------------
987// wxQTMediaBackend::GetVolume
988//
989// Gets the volume through GetMovieVolume - which returns a 16 bit short -
990//
991// +--------+--------+
992// + (1) + (2) +
993// +--------+--------+
994//
995// (1) first 8 bits are value before decimal
996// (2) second 8 bits are value after decimal
997//
998// Volume ranges from -1.0 (gain but no sound), 0 (no sound and no gain) to
999// 1 (full gain and sound)
1000//---------------------------------------------------------------------------
1001double wxQTMediaBackend::GetVolume()
1002{
1003 short sVolume = m_lib.GetMovieVolume(m_movie);
1004 wxASSERT(m_lib.GetMoviesError() == noErr);
1005
1006 if (sVolume & (128 << 8)) //negative - no sound
1007 return 0.0;
1008
1009 return sVolume / 256.0;
1010}
1011
1012//---------------------------------------------------------------------------
1013// wxQTMediaBackend::SetVolume
1014//
1015// Sets the volume through SetMovieVolume - which takes a 16 bit short -
1016//
1017// +--------+--------+
1018// + (1) + (2) +
1019// +--------+--------+
1020//
1021// (1) first 8 bits are value before decimal
1022// (2) second 8 bits are value after decimal
1023//
1024// Volume ranges from -1.0 (gain but no sound), 0 (no sound and no gain) to
1025// 1 (full gain and sound)
1026//---------------------------------------------------------------------------
1027bool wxQTMediaBackend::SetVolume(double dVolume)
1028{
1029 m_lib.SetMovieVolume(m_movie, (short) (dVolume * 256));
1030 return m_lib.GetMoviesError() == noErr;
1031}
1032
1033//---------------------------------------------------------------------------
1034// wxQTMediaBackend::GetDuration
1035//
1036// Calls GetMovieDuration
1037//---------------------------------------------------------------------------
1038wxLongLong wxQTMediaBackend::GetDuration()
1039{
1040 return m_lib.GetMovieDuration(m_movie);
1041}
1042
1043//---------------------------------------------------------------------------
1044// wxQTMediaBackend::GetState
1045//
1046// Determines the current state:
1047// if we are at the beginning, then we are stopped
1048//---------------------------------------------------------------------------
1049wxMediaState wxQTMediaBackend::GetState()
1050{
1051 if (m_bPlaying)
1052 return wxMEDIASTATE_PLAYING;
1053 else if ( !m_movie || wxQTMediaBackend::GetPosition() == 0 )
1054 return wxMEDIASTATE_STOPPED;
1055 else
1056 return wxMEDIASTATE_PAUSED;
1057}
1058
1059//---------------------------------------------------------------------------
1060// wxQTMediaBackend::Cleanup
1061//
1062// Diposes of the movie timer, Disassociates the Movie Controller with
1063// movie and hides it if it exists, and stops and disposes
1064// of the QT movie
1065//---------------------------------------------------------------------------
1066void wxQTMediaBackend::Cleanup()
1067{
1068 m_bPlaying = false;
1069
1070 wxDELETE(m_timer);
1071
1072 m_lib.StopMovie(m_movie);
1073
1074 if (m_pMC)
1075 {
1076 Point thePoint;
1077 thePoint.h = thePoint.v = 0;
1078 m_lib.MCSetVisible(m_pMC, false);
1079 m_lib.MCSetMovie(m_pMC, NULL, NULL, thePoint);
1080 }
1081
1082 m_lib.DisposeMovie(m_movie);
1083 m_movie = NULL;
1084}
1085
1086//---------------------------------------------------------------------------
1087// wxQTMediaBackend::ShowPlayerControls
1088//
1089// Creates a movie controller for the Movie if the user wants it
1090//---------------------------------------------------------------------------
1091bool wxQTMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
1092{
1093 if (m_pMC)
1094 {
1095 // restore old wndproc
1096 wxSetWindowProc((HWND)m_ctrl->GetHWND(), wxWndProc);
1097 m_lib.DisposeMovieController(m_pMC);
1098 m_pMC = NULL;
1099
1100 // movie controller height
1101 m_bestSize.y -= 16;
1102 }
1103
1104 if (flags && m_movie)
1105 {
1106 Rect rect;
1107 wxRect wxrect = m_ctrl->GetClientRect();
1108
1109 // make room for controller
1110 if (wxrect.width < 320)
1111 wxrect.width = 320;
1112
1113 rect.top = (short)wxrect.y;
1114 rect.left = (short)wxrect.x;
1115 rect.right = (short)(rect.left + wxrect.width);
1116 rect.bottom = (short)(rect.top + wxrect.height);
1117
1118 if (!m_pMC)
1119 {
1120 m_pMC = m_lib.NewMovieController(m_movie, &rect, mcTopLeftMovie |
1121 // mcScaleMovieToFit |
1122 // mcWithBadge |
1123 mcWithFrame);
1124 m_lib.MCDoAction(m_pMC, 32, (void*)true); // mcActionSetKeysEnabled
1125 m_lib.MCSetActionFilterWithRefCon(m_pMC,
1126 (WXFARPROC)wxQTMediaBackend::MCFilterProc, (void*)this);
1127 m_bestSize.y += 16; // movie controller height
1128
1129 // By default the movie controller uses its own colour palette
1130 // for the movie which can be bad on some files, so turn it off.
1131 // Also turn off its frame / border for the movie
1132 // Also take care of a couple of the interface flags here
1133 long mcFlags = 0;
1134 m_lib.MCDoAction(m_pMC, 39/*mcActionGetFlags*/, (void*)&mcFlags);
1135
1136 mcFlags |=
1137 // (1<< 0) /*mcFlagSuppressMovieFrame*/ |
1138 (1<< 3) /*mcFlagsUseWindowPalette*/
1139 | ((flags & wxMEDIACTRLPLAYERCONTROLS_STEP)
1140 ? 0 : (1<< 1) /*mcFlagSuppressStepButtons*/)
1141 | ((flags & wxMEDIACTRLPLAYERCONTROLS_VOLUME)
1142 ? 0 : (1<< 2) /*mcFlagSuppressSpeakerButton*/)
1143// | (1<< 4) /*mcFlagDontInvalidate*/ // if we take care of repainting ourselves
1144 ;
1145
1146 m_lib.MCDoAction(m_pMC, 38/*mcActionSetFlags*/, wxUIntToPtr(mcFlags));
1147
1148 // intercept the wndproc of our control window
1149 wxSetWindowProc((HWND)m_ctrl->GetHWND(), wxQTMediaBackend::QTWndProc);
1150
1151 // set the user data of our window
1152 wxSetWindowUserData((HWND)m_ctrl->GetHWND(), this);
1153 }
1154 }
1155
1156 NotifyMovieSizeChanged();
1157
1158 return m_lib.GetMoviesError() == noErr;
1159}
1160
1161//---------------------------------------------------------------------------
1162// wxQTMediaBackend::MCFilterProc (static)
1163//
1164// Callback for when the movie controller receives a message
1165//---------------------------------------------------------------------------
1166Boolean wxQTMediaBackend::MCFilterProc(MovieController WXUNUSED(theController),
1167 short action,
1168 void * WXUNUSED(params),
1169 LONG_PTR refCon)
1170{
1171// NB: potential optimisation
1172// if (action == 1)
1173// return 0;
1174
1175 wxQTMediaBackend* pThis = (wxQTMediaBackend*)refCon;
1176
1177 switch (action)
1178 {
1179 case 1:
1180 // don't process idle events
1181 break;
1182
1183 case 8:
1184 // play button triggered - MC will set movie to opposite state
1185 // of current - playing ? paused : playing
1186 if (pThis)
1187 pThis->m_bPlaying = !(pThis->m_bPlaying);
1188
1189 // NB: Sometimes it doesn't redraw properly -
1190 // if you click on the button but don't move the mouse
1191 // the button will not change its state until you move
1192 // mcActionDraw and Refresh/Update combo do nothing
1193 // to help this unfortunately
1194 break;
1195
1196 default:
1197 break;
1198 }
1199
1200 return 0;
1201}
1202
1203//---------------------------------------------------------------------------
1204// wxQTMediaBackend::GetVideoSize
1205//
1206// Returns the actual size of the QT movie
1207//---------------------------------------------------------------------------
1208wxSize wxQTMediaBackend::GetVideoSize() const
1209{
1210 return m_bestSize;
1211}
1212
1213//---------------------------------------------------------------------------
1214// wxQTMediaBackend::Move
1215//
1216// Sets the bounds of either the Movie or Movie Controller
1217//---------------------------------------------------------------------------
1218void wxQTMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y), int w, int h)
1219{
1220 if (m_movie)
1221 {
1222 // make room for controller
1223 if (m_pMC)
1224 {
1225 if (w < 320)
1226 w = 320;
1227
1228 Rect theRect = {0, 0, (short)h, (short)w};
1229 m_lib.MCSetControllerBoundsRect(m_pMC, &theRect);
1230 }
1231 else
1232 {
1233 Rect theRect = {0, 0, (short)h, (short)w};
1234 m_lib.SetMovieBox(m_movie, &theRect);
1235 }
1236
1237 wxASSERT(m_lib.GetMoviesError() == noErr);
1238 }
1239}
1240
1241//---------------------------------------------------------------------------
1242// wxQTMediaBackend::OnEraseBackground
1243//
1244// Suggestion from Greg Hazel to repaint the movie when idle
1245// (on pause also)
1246//
1247// TODO: We may be repainting too much here - under what exact circumstances
1248// do we need this? I think Move also repaints correctly for the Movie
1249// Controller, so in that instance we don't need this either
1250//---------------------------------------------------------------------------
1251void wxQTMediaEvtHandler::OnEraseBackground(wxEraseEvent& evt)
1252{
1253 wxQuickTimeLibrary& m_pLib = m_qtb->m_lib;
1254
1255 if ( m_qtb->m_pMC )
1256 {
1257 // repaint movie controller
1258 m_pLib.MCDoAction(m_qtb->m_pMC, 2 /*mcActionDraw*/,
1259 m_pLib.GetNativeWindowPort(m_hwnd));
1260 }
1261 else if ( m_qtb->m_movie )
1262 {
1263 // no movie controller
1264 CGrafPtr port = (CGrafPtr)m_pLib.GetNativeWindowPort(m_hwnd);
1265
1266 m_pLib.BeginUpdate(port);
1267 m_pLib.UpdateMovie(m_qtb->m_movie);
1268 wxASSERT(m_pLib.GetMoviesError() == noErr);
1269 m_pLib.EndUpdate(port);
1270 }
1271 else
1272 {
1273 // no movie
1274 // let the system repaint the window
1275 evt.Skip();
1276 }
1277}
1278
1279//---------------------------------------------------------------------------
1280// End QT Backend
1281//---------------------------------------------------------------------------
1282
1283// Allow the user code to use wxFORCE_LINK_MODULE() to ensure that this object
1284// file is not discarded by the linker.
1285#include "wx/link.h"
1286wxFORCE_LINK_THIS_MODULE(wxmediabackend_qt)
1287
1288#endif // wxUSE_MEDIACTRL && wxUSE_ACTIVEX