// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
+/*
+ FIXME FIXME FIXME:
+ - extract different backends in different files (better yet, make backends
+ dynamically loadable...), they have nothing to do with each other and
+ this file is huge and also separate the standard contents from our code
+ itself
+ - extract ~1000 lines of wxActiveX code in its own file, why does it have
+ to be here??
+ */
+
//===========================================================================
// DECLARATIONS
//===========================================================================
#include "wx/msw/private.h" //user info and wndproc setting/getting
#include "wx/dcclient.h"
#include "wx/timer.h"
+#include "wx/dynlib.h"
//---------------------------------------------------------------------------
// Externals (somewhere in src/msw/app.cpp and src/msw/window.cpp)
// BACKEND DECLARATIONS
//===========================================================================
+// ----------------------------------------------------------------------------
+// common backend base class used by all other backends
+// ----------------------------------------------------------------------------
+
+class WXDLLIMPEXP_MEDIA wxMediaBackendCommonBase : public wxMediaBackend
+{
+public:
+ // add a pending wxMediaEvent of the given type
+ void QueueEvent(wxEventType evtType);
+
+ // notify that the movie playback is finished
+ void QueueFinishEvent() { QueueEvent(wxEVT_MEDIA_FINISHED); }
+
+ // send the stop event and return true if it hasn't been vetoed
+ bool SendStopEvent();
+
+protected:
+ // call this when the movie size has changed but not because it has just
+ // been loaded (in this case, call NotifyMovieLoaded() below)
+ void NotifyMovieSizeChanged();
+
+ // call this when the movie is fully loaded
+ void NotifyMovieLoaded();
+
+
+ wxControl *m_ctrl; // parent control
+};
+
//---------------------------------------------------------------------------
//
// wxAMMediaBackend
typedef BOOL (WINAPI* LPAMGETERRORTEXT)(HRESULT, wxChar *, DWORD);
-class WXDLLIMPEXP_MEDIA wxAMMediaBackend : public wxMediaBackend
+class WXDLLIMPEXP_MEDIA wxAMMediaBackend : public wxMediaBackendCommonBase
{
public:
wxAMMediaBackend();
return total;
}
- wxControl* m_ctrl;
wxActiveX* m_pAX;
IActiveMovie* m_pAM;
IMediaPlayer* m_pMP;
wxTimer* m_pTimer;
wxSize m_bestSize;
+
#ifdef __WXDEBUG__
- HMODULE m_hQuartzDll;
+ wxDynamicLibrary m_dllQuartz;
LPAMGETERRORTEXT m_lpAMGetErrorText;
wxString GetErrorString(HRESULT hrdsv);
-#endif
+#endif // __WXDEBUG__
DECLARE_DYNAMIC_CLASS(wxAMMediaBackend)
};
//---------------------------------------------------------------------------
#include <mmsystem.h>
-class WXDLLIMPEXP_MEDIA wxMCIMediaBackend : public wxMediaBackend
+class WXDLLIMPEXP_MEDIA wxMCIMediaBackend : public wxMediaBackendCommonBase
{
public:
WPARAM wParam, LPARAM lParam);
MCIDEVICEID m_hDev; //Our MCI Device ID/Handler
- wxControl* m_ctrl; //Parent control
HWND m_hNotifyWnd; //Window to use for MCI events
bool m_bVideo; //Whether or not we have video
return true;
}
-class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackend
+class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackendCommonBase
{
public:
wxQTMediaBackend();
wxSize m_bestSize; //Original movie size
Movie m_movie; //QT Movie handle/instance
- wxControl* m_ctrl; //Parent control
bool m_bVideo; //Whether or not we have video
bool m_bPlaying; //Whether or not movie is playing
wxTimer* m_timer; //Load or Play timer
class WXDLLIMPEXP_MEDIA wxQTMediaEvtHandler : public wxEvtHandler
{
public:
- wxQTMediaEvtHandler(wxQTMediaBackend *qtb) { m_qtb = qtb; }
+ wxQTMediaEvtHandler(wxQTMediaBackend *qtb, WXHWND hwnd)
+ {
+ m_qtb = qtb;
+ m_hwnd = hwnd;
+ }
void OnEraseBackground(wxEraseEvent& event);
private:
wxQTMediaBackend *m_qtb;
+ WXHWND m_hwnd;
DECLARE_NO_COPY_CLASS(wxQTMediaEvtHandler)
};
// IMPLEMENTATION
//===========================================================================
+// ----------------------------------------------------------------------------
+// wxMediaBackendCommonBase
+// ----------------------------------------------------------------------------
+
+void wxMediaBackendCommonBase::NotifyMovieSizeChanged()
+{
+ // our best size changed after opening a new file
+ m_ctrl->InvalidateBestSize();
+ m_ctrl->SetSize(m_ctrl->GetSize());
+
+ // if the parent of the control has a sizer ask it to refresh our size
+ wxWindow * const parent = m_ctrl->GetParent();
+ if ( parent->GetSizer() )
+ {
+ m_ctrl->GetParent()->Layout();
+ m_ctrl->GetParent()->Refresh();
+ m_ctrl->GetParent()->Update();
+ }
+}
+
+void wxMediaBackendCommonBase::NotifyMovieLoaded()
+{
+ NotifyMovieSizeChanged();
+
+ // notify about movie being fully loaded
+ QueueEvent(wxEVT_MEDIA_LOADED);
+}
+
+bool wxMediaBackendCommonBase::SendStopEvent()
+{
+ wxMediaEvent theEvent(wxEVT_MEDIA_STOP, m_ctrl->GetId());
+
+ return !m_ctrl->ProcessEvent(theEvent) || theEvent.IsAllowed();
+}
+
+void wxMediaBackendCommonBase::QueueEvent(wxEventType evtType)
+{
+ wxMediaEvent theEvent(evtType, m_ctrl->GetId());
+ m_ctrl->AddPendingEvent(theEvent);
+}
+
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// wxAMMediaBackend
//they can still get sent in some cases
m_parent->GetPosition() == m_parent->GetDuration())
{
- wxMediaEvent theEvent(wxEVT_MEDIA_STOP,
- m_parent->m_ctrl->GetId());
- m_parent->m_ctrl->ProcessEvent(theEvent);
-
- if(theEvent.IsAllowed())
+ if ( m_parent->SendStopEvent() )
{
//Seek to beginning of movie
m_parent->wxAMMediaBackend::SetPosition(0);
Stop();
//send the event to our child
- wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED,
- m_parent->m_ctrl->GetId());
- m_parent->m_ctrl->AddPendingEvent(theEvent);
+ m_parent->QueueFinishEvent();
}
}
}
// If this is the end of the clip, notify handler
else if(1 == evCode) //EC_COMPLETE
{
- wxMediaEvent theEvent(wxEVT_MEDIA_STOP,
- m_pBE->m_ctrl->GetId());
- m_pBE->m_ctrl->ProcessEvent(theEvent);
-
- if(theEvent.IsAllowed())
+ if ( m_pBE->SendStopEvent() )
{
Stop();
- //send the event to our child
- wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED,
- m_pBE->m_ctrl->GetId());
- m_pBE->m_ctrl->AddPendingEvent(theEvent);
+ m_pBE->QueueFinishEvent();
}
}
}
m_pAM(NULL),
m_pMP(NULL),
m_pTimer(NULL)
-#ifdef __WXDEBUG__
- ,m_hQuartzDll(NULL)
-#endif
{
}
if(m_pMP)
m_pMP->Release();
}
-#ifdef __WXDEBUG__
- if(m_hQuartzDll)
- ::FreeLibrary(m_hQuartzDll);
-#endif
}
//---------------------------------------------------------------------------
// First get the AMGetErrorText procedure in debug
// mode for more meaningful messages
#ifdef __WXDEBUG__
- m_hQuartzDll = ::LoadLibrary(wxT("quartz.dll"));
- if(m_hQuartzDll)
+ if ( m_dllQuartz.Load(_T("quartz.dll"), wxDL_VERBATIM) )
{
- m_lpAMGetErrorText = (LPAMGETERRORTEXT) ::GetProcAddress(
- m_hQuartzDll,
- wxString::Format(wxT("AMGetErrorText%s"),
-
-#if wxUSE_UNICODE
- wxT("W")
-#else
- wxT("A")
-#endif
-#ifdef __WXWINCE__
- )
-#else
- ).mb_str(wxConvLocal)
-#endif
- );
+ m_lpAMGetErrorText = (LPAMGETERRORTEXT)
+ m_dllQuartz.GetSymbolAorW(wxT("AMGetErrorText"));
}
-#endif
+#endif // __WXDEBUG__
+
// Now determine which (if any) media player interface is
// available - IMediaPlayer or IActiveMovie
if( ::CoCreateInstance(CLSID_MediaPlayer, NULL,
if( ::CoCreateInstance(CLSID_ActiveMovie, NULL,
CLSCTX_INPROC_SERVER,
IID_IActiveMovie, (void**)&m_pAM) != 0 )
- return false;
+ return false;
m_pAM->QueryInterface(IID_IMediaPlayer, (void**)&m_pMP);
}
else
//
m_pTimer = new wxAMPlayTimer(this);
- //Here, if the parent of the control has a sizer - we
- //tell it to recalculate the size of this control since
- //the user opened a separate media file
- //
- m_ctrl->InvalidateBestSize();
- m_ctrl->GetParent()->Layout();
- m_ctrl->GetParent()->Refresh();
- m_ctrl->GetParent()->Update();
- m_ctrl->SetSize(m_ctrl->GetSize());
-
- //Send event to our children
- wxMediaEvent theEvent(wxEVT_MEDIA_LOADED,
- m_ctrl->GetId());
- m_ctrl->AddPendingEvent(theEvent);
+ NotifyMovieLoaded();
}
//---------------------------------------------------------------------------
wxSetWindowProc(m_hNotifyWnd, wxMCIMediaBackend::NotifyWndProc);
wxSetWindowUserData(m_hNotifyWnd, this);
- //
- //Here, if the parent of the control has a sizer - we
- //tell it to recalculate the size of this control since
- //the user opened a separate media file
- //
- m_ctrl->InvalidateBestSize();
- m_ctrl->GetParent()->Layout();
- m_ctrl->GetParent()->Refresh();
- m_ctrl->GetParent()->Update();
- m_ctrl->SetSize(m_ctrl->GetSize());
-
- //send loaded event
- wxMediaEvent theEvent(wxEVT_MEDIA_LOADED,
- m_ctrl->GetId());
- m_ctrl->AddPendingEvent(theEvent);
+ NotifyMovieLoaded();
return true;
}
wxASSERT(lParam == (LPARAM) m_hDev);
if(wParam == MCI_NOTIFY_SUCCESSFUL && lParam == (LPARAM)m_hDev)
{
- wxMediaEvent theEvent(wxEVT_MEDIA_STOP, m_ctrl->GetId());
- m_ctrl->ProcessEvent(theEvent);
-
- if(theEvent.IsAllowed())
+ if ( SendStopEvent() )
{
wxMCIVERIFY( mciSendCommand(m_hDev, MCI_SEEK,
MCI_SEEK_TO_START, 0) );
- //send the event to our child
- wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED,
- m_ctrl->GetId());
- m_ctrl->ProcessEvent(theEvent);
+ QueueFinishEvent();
}
}
}
{
if(m_pLib->IsMovieDone(m_movie))
{
- wxMediaEvent theEvent(wxEVT_MEDIA_STOP,
- m_parent->m_ctrl->GetId());
- m_parent->m_ctrl->ProcessEvent(theEvent);
-
- if(theEvent.IsAllowed())
+ if ( m_parent->SendStopEvent() )
{
m_parent->Stop();
wxASSERT(m_pLib->GetMoviesError() == noErr);
- //send the event to our child
- wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED,
- m_parent->m_ctrl->GetId());
- m_parent->m_ctrl->AddPendingEvent(theEvent);
+ m_parent->QueueFinishEvent();
}
}
}
//Part of a suggestion from Greg Hazel to repaint
//movie when idle
- m_ctrl->PushEventHandler(new wxQTMediaEvtHandler(this));
+ m_ctrl->PushEventHandler(new wxQTMediaEvtHandler(this, m_ctrl->GetHWND()));
// done
return true;
m_lib.SetMovieTimeScale(m_movie, 1000);
wxASSERT(m_lib.GetMoviesError() == noErr);
- //
- //Here, if the parent of the control has a sizer - we
- //tell it to recalculate the size of this control since
- //the user opened a separate media file
- //
- m_ctrl->InvalidateBestSize();
- m_ctrl->GetParent()->Layout();
- m_ctrl->GetParent()->Refresh();
- m_ctrl->GetParent()->Update();
- m_ctrl->SetSize(m_ctrl->GetSize());
-
- //loaded - note that MoviesTask must and will be called before this
- //by the previous timer since this gets appended to the event list after
- //the timer's first go
- wxMediaEvent theEvent(wxEVT_MEDIA_LOADED,
- m_ctrl->GetId());
- m_ctrl->AddPendingEvent(theEvent);
+ NotifyMovieLoaded();
}
//---------------------------------------------------------------------------
}
}
- //
- //Here, if the parent of the control has a sizer - we
- //tell it to recalculate the size of this control since
- //the user opened a separate media file
- //
- m_ctrl->InvalidateBestSize();
- m_ctrl->GetParent()->Layout();
- m_ctrl->GetParent()->Refresh();
- m_ctrl->GetParent()->Update();
- m_ctrl->SetSize(m_ctrl->GetSize());
+ NotifyMovieSizeChanged();
return m_lib.GetMoviesError() == noErr;
}
if ( m_qtb->m_pMC )
{
- //repaint movie controller
+ // repaint movie controller
m_pLib.MCDoAction(m_qtb->m_pMC, 2 /*mcActionDraw*/,
- m_pLib.GetNativeWindowPort(m_qtb->m_ctrl->GetHWND())
- );
+ m_pLib.GetNativeWindowPort(m_hwnd));
}
- else if(m_qtb->m_movie)
+ else // no movie controller
{
- CGrafPtr port = (CGrafPtr)m_pLib.GetNativeWindowPort
- (m_qtb->m_ctrl->GetHWND());
+ if ( m_qtb->m_movie )
+ {
+ CGrafPtr port = (CGrafPtr)m_pLib.GetNativeWindowPort(m_hwnd);
- m_pLib.BeginUpdate(port);
- m_pLib.UpdateMovie(m_qtb->m_movie);
- wxASSERT(m_pLib.GetMoviesError() == noErr);
- m_pLib.EndUpdate(port);
+ m_pLib.BeginUpdate(port);
+ m_pLib.UpdateMovie(m_qtb->m_movie);
+ wxASSERT(m_pLib.GetMoviesError() == noErr);
+ m_pLib.EndUpdate(port);
+ }
+ else // no movie
+ {
+ // let the system repaint the window
+ evt.Skip();
+ }
}
-
- // VZ: this doesn't make sense: why should we erase the background after
- // taking the trouble to do whatever we did above? (FIXME)
- evt.Skip(); //repaint with window background (TODO: maybe !m_movie?)
}
//---------------------------------------------------------------------------