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