many improvements/bug fixes to media control: new wxEVT_MEDIA_LOADED event, new methods taking URIs, new DirectShow implementation, significant sample improvements (patch 1233613)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@34974 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2005-07-28 23:56:57 +00:00
parent dca92ddfbf
commit c5191fbd2b
10 changed files with 4061 additions and 1222 deletions

View File

@@ -9,6 +9,8 @@ All:
- Fixed wxScopeGuard to work with VC++, documented it.
- Fixed proxy handling in wxURL.
- Added wxEVT_MEDIA_LOADED event for wxMediaCtrl
- Added new methods to wxMediaCtrl (wxURI version of Load, ShowPlayerControls)
- Added wxZipFSHandler::Cleanup() (Stas Sergeev)
- Added wxImage::RotateHue() and RGB <-> HSV conversions (John Anderson)

View File

@@ -39,8 +39,9 @@ realm of licensing restrictions).
For general operation, all you need to do is call
\helpref{wxMediaCtrl::Load}{wxmediactrlload} to load the file
you want to render, then call \helpref{wxMediaCtrl::Play}{wxmediactrlplay}
to show the video/audio of the media.
you want to render, catch the EVT\_MEDIA\_LOADED event,
and then call \helpref{wxMediaCtrl::Play}{wxmediactrlplay}
to show the video/audio of the media in that event.
More complex operations are generally more heavily dependant on the
capabilities of the backend. For example, QuickTime cannot set
@@ -102,7 +103,7 @@ Use ActiveMovie/DirectShow. Requires wxUSE\_DIRECTSHOW to be
enabled, requires linkage with the static library strmiids.lib,
and is available on Windows Only.}
\twocolitem{{\bf wxMEDIABACKEND\_QUICKTIME}}{
Use QuickTime. Windows and Mac Only. WARNING: On Mac Systems lower than OSX 10.2 this defaults to emulating window positioning and suffers from several bugs, including not working correctly embedded in a wxNotebook. }
Use QuickTime. Windows and Mac Only. NOTE: On Mac Systems lower than OSX 10.2 this defaults to emulating window positioning and suffers from several bugs, including not working correctly embedded in a wxNotebook. }
\twocolitem{{\bf wxMEDIABACKEND\_MCI}}{
Use Media Command Interface. Windows Only. }
\twocolitem{{\bf wxMEDIABACKEND\_GSTREAMER}}{
@@ -206,6 +207,13 @@ Obtains the state the playback of the movie is in -
Loads the file that \tt{fileName} refers to. Returns false if loading fails.
\membersection{wxMediaCtrl::Load}\label{wxmediactrlloaduri}
\func{bool}{Load}{\param{const wxURI\& }{location}}
Loads the url that \tt{location} refers to. Returns false if loading fails.
\membersection{wxMediaCtrl::Pause}\label{wxmediactrlpause}
\func{bool}{Pause}{\void}
@@ -222,7 +230,7 @@ Resumes playback of the movie.
\membersection{wxMediaCtrl::Seek}\label{wxmediactrlsetposition}
\func{wxFileOffset}{SetPosition}{\param{wxFileOffset }{where}, \param{wxSeekMode }{mode}}
\func{wxFileOffset}{Seek}{\param{wxFileOffset }{where}, \param{wxSeekMode }{mode}}
Seeks to a position within the movie.
@@ -235,3 +243,45 @@ Stops the media.
See \helpref{Operation}{operationwxmediactrl} for an overview of how stopping works.
\membersection{wxMediaCtrl::SetVolume}\label{wxmediactrlsetvolume}
\func{bool}{SetVolume}{\param{double }{dVolume}}
Sets the volume of the media from a 0.0 to 1.0 range.
\membersection{wxMediaCtrl::GetVolume}\label{wxmediactrlgetvolume}
\func{double}{GetVolume}{\void}
Gets the volume of the media from a 0.0 to 1.0 range.
\membersection{wxMediaCtrl::GetPlaybackRate}\label{wxmediactrlgetplaybackrate}
\func{double}{GetPlaybackrate}{\void}
Gets the playback rate of the media; for example 2.0 is double speed.
Not implemented on MCI or GStreamer.
\membersection{wxMediaCtrl::SetPlaybackRate}\label{wxmediactrlsetplaybackrate}
\func{bool}{SetPlaybackrate}{\param{double }{dVolume}}
Sets the rate that the media plays; for example 0.5 is half speed.
\membersection{wxMediaCtrl::ShowPlayerControls}\label{wxmediactrlshowplayercontrols}
\func{bool}{ShowPlayerControls}{\param{wxMediaCtrlPlayerControls }{flags}}
Normally, when you use wxMediaCtrl it is just a window for the video to
play in. However, platforms generally have their own media player interface,
like quicktime has a bar below the video with a slider etc.. If you want that native
interface instead of making your own use this function. There are several options
for the flags parameter, however you can look at the mediactrl header for these.
The two general flags are wxMEDIACTRLPLAYERCONTROLS\_NONE which turns off the
native interface, and wxMEDIACTRLPLAYERCONTROLS\_DEFAULT which lets wxMediaCtrl
decide what native controls on the interface.

View File

@@ -25,6 +25,7 @@ Event \helpref{wxMediaCtrl}{wxmediactrl} uses.
\twocolwidtha{7cm}
\begin{twocollist}\itemsep=0pt
\twocolitem{{\bf EVT\_MEDIA\_LOADED(func)}}{Sent when a media has loaded enough data that it can start playing.}
\twocolitem{{\bf EVT\_MEDIA\_STOP(func)}}{
Triggerred right before the media stops. You can Veto this event to prevent it from stopping, causing it to continue playing - even if it has reached that end of the media. }
\twocolitem{{\bf EVT\_MEDIA\_FINISHED(func)}}{Sent when a media has finished playing in a \helpref{wxMediaCtrl}{wxmediactrl}. Note that if you connect to this event and don't skip it, it will override the looping behaviour of the media control.}

View File

@@ -58,11 +58,24 @@ enum wxMediaState
wxMEDIASTATE_PLAYING
};
enum wxMediaCtrlPlayerControls
{
wxMEDIACTRLPLAYERCONTROLS_NONE = 0,
//Step controls like fastfoward, step one frame etc.
wxMEDIACTRLPLAYERCONTROLS_STEP = 1 << 0,
//Volume controls like the speaker icon, volume slider, etc.
wxMEDIACTRLPLAYERCONTROLS_VOLUME = 1 << 1,
wxMEDIACTRLPLAYERCONTROLS_DEFAULT =
wxMEDIACTRLPLAYERCONTROLS_STEP |
wxMEDIACTRLPLAYERCONTROLS_VOLUME
};
#define wxMEDIABACKEND_DIRECTSHOW wxT("wxAMMediaBackend")
#define wxMEDIABACKEND_MCI wxT("wxMCIMediaBackend")
#define wxMEDIABACKEND_QUICKTIME wxT("wxQTMediaBackend")
#define wxMEDIABACKEND_GSTREAMER wxT("wxGStreamerMediaBackend")
// ----------------------------------------------------------------------------
//
// wxMediaEvent
@@ -158,7 +171,7 @@ public:
long style = 0,
const wxString& szBackend = wxEmptyString,
const wxValidator& validator = wxDefaultValidator,
const wxString& name = wxT("mediaCtrl")); //DirectShow only
const wxString& name = wxT("mediaCtrl"));
bool DoCreate(wxClassInfo* instance,
wxWindow* parent, wxWindowID winid,
@@ -174,25 +187,36 @@ public:
bool Load(const wxString& fileName);
wxMediaState GetState();
wxFileOffset Seek(wxFileOffset where, wxSeekMode mode = wxFromStart);
wxFileOffset Tell(); //FIXME: This should be const
wxFileOffset Length(); //FIXME: This should be const
//
// Unofficial parts of API
//
//DirectShow/GStreamer only. Quicktime too, but somewhat buggy...
bool Load(const wxURI& location);
#if wxABI_VERSION >= 20601 /* 2.6.1+ only */
double GetPlaybackRate(); //All but MCI & GStreamer
bool SetPlaybackRate(double dRate); //All but MCI & GStreamer
#endif
double GetVolume(); //DirectShow only
bool SetVolume(double dVolume); //DirectShow only
#if wxABI_VERSION >= 20602 /* 2.6.2+ only */
bool Load(const wxURI& location);
bool Load(const wxURI& location, const wxURI& proxy);
wxFileOffset GetDownloadProgress();
wxFileOffset GetDownloadTotal();
double GetVolume();
bool SetVolume(double dVolume);
bool ShowPlayerControls(
wxMediaCtrlPlayerControls flags = wxMEDIACTRLPLAYERCONTROLS_DEFAULT);
//helpers for the wxPython people
bool LoadURI(const wxString& fileName)
{ return Load(wxURI(fileName)); }
bool LoadURIWithProxy(const wxString& fileName, const wxString& proxy)
{ return Load(wxURI(fileName), wxURI(proxy)); }
#endif
protected:
static wxClassInfo* NextBackend();
@@ -202,10 +226,7 @@ protected:
//FIXME: This is nasty... find a better way to work around
//inheritance issues
#ifdef __WXMAC__
friend class wxQTMediaBackend;
#endif
#ifdef __WXCOCOA__
#if defined(__WXMAC__) || defined(__WXCOCOA__)
friend class wxQTMediaBackend;
#endif
class wxMediaBackend* m_imp;
@@ -218,7 +239,13 @@ protected:
//
// wxMediaBackend
//
// Currently an internal class - API stability not guaranteed.
// Derive from this and use standard wxWidgets RTTI
// (DECLARE_DYNAMIC_CLASS and IMPLEMENT_CLASS) to make a backend
// for wxMediaCtrl. Backends are searched alphabetically -
// the one with the earliest letter is tried first.
//
// Note that this is currently not API or ABI compatable -
// so statically link or make the client compile on-site.
//
// ----------------------------------------------------------------------------
@@ -278,11 +305,21 @@ public:
virtual bool SetVolume(double WXUNUSED(dVolume))
{ return false; }
virtual void RESERVED3() {}
virtual void RESERVED4() {}
virtual void RESERVED5() {}
virtual void RESERVED6() {}
virtual void RESERVED7() {}
virtual bool Load(const wxURI& WXUNUSED(location),
const wxURI& WXUNUSED(proxy))
{ return false; }
virtual bool ShowPlayerControls(
wxMediaCtrlPlayerControls WXUNUSED(flags))
{ return false; }
virtual bool IsInterfaceShown()
{ return false; }
virtual wxLongLong GetDownloadProgress()
{ return 0; }
virtual wxLongLong GetDownloadTotal()
{ return 0; }
virtual void RESERVED8() {}
virtual void RESERVED9() {}
@@ -307,6 +344,12 @@ typedef void (wxEvtHandler::*wxMediaEventFunction)(wxMediaEvent&);
#define EVT_MEDIA_FINISHED(winid, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MEDIA_FINISHED, winid, wxID_ANY, wxMediaEventHandler(fn), (wxObject *) NULL ),
#define EVT_MEDIA_STOP(winid, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MEDIA_STOP, winid, wxID_ANY, wxMediaEventHandler(fn), (wxObject *) NULL ),
#if wxABI_VERSION >= 20602 /* 2.6.2+ only */
# define wxMEDIA_LOADED_ID 13002
DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_MEDIA, wxEVT_MEDIA_LOADED, wxMEDIA_LOADED_ID)
# define EVT_MEDIA_LOADED(winid, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MEDIA_LOADED, winid, wxID_ANY, wxMediaEventHandler(fn), (wxObject *) NULL ),
#endif
// ----------------------------------------------------------------------------
// End compilation gaurd
// ----------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@@ -52,6 +52,7 @@ IMPLEMENT_CLASS(wxMediaCtrl, wxControl);
IMPLEMENT_CLASS(wxMediaBackend, wxObject);
IMPLEMENT_DYNAMIC_CLASS(wxMediaEvent, wxEvent);
DEFINE_EVENT_TYPE(wxEVT_MEDIA_FINISHED);
DEFINE_EVENT_TYPE(wxEVT_MEDIA_LOADED);
DEFINE_EVENT_TYPE(wxEVT_MEDIA_STOP);
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -281,6 +282,8 @@ wxMediaCtrl::~wxMediaCtrl()
//---------------------------------------------------------------------------
// wxMediaCtrl::Load (file version)
// wxMediaCtrl::Load (URL version)
// wxMediaCtrl::Load (URL & Proxy version)
// wxMediaCtrl::Load (wxInputStream version)
//
// Here we call load of the backend - keeping
// track of whether it was successful or not - which
@@ -300,6 +303,13 @@ bool wxMediaCtrl::Load(const wxURI& location)
return false;
}
bool wxMediaCtrl::Load(const wxURI& location, const wxURI& proxy)
{
if(m_imp)
return (m_bLoaded = m_imp->Load(location, proxy));
return false;
}
//---------------------------------------------------------------------------
// wxMediaCtrl::Play
// wxMediaCtrl::Pause
@@ -313,6 +323,9 @@ bool wxMediaCtrl::Load(const wxURI& location)
// wxMediaCtrl::DoGetBestSize
// wxMediaCtrl::SetVolume
// wxMediaCtrl::GetVolume
// wxMediaCtrl::ShowInterface
// wxMediaCtrl::GetDownloadProgress
// wxMediaCtrl::GetDownloadTotal
//
// 1) Check to see whether the backend exists and is loading
// 2) Call the backend's version of the method, returning success
@@ -418,6 +431,27 @@ bool wxMediaCtrl::SetVolume(double dVolume)
return false;
}
bool wxMediaCtrl::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
{
if(m_imp)
return m_imp->ShowPlayerControls(flags);
return false;
}
wxFileOffset wxMediaCtrl::GetDownloadProgress()
{
if(m_imp && m_bLoaded)
return (wxFileOffset) m_imp->GetDownloadProgress().ToLong();
return wxInvalidOffset;
}
wxFileOffset wxMediaCtrl::GetDownloadTotal()
{
if(m_imp && m_bLoaded)
return (wxFileOffset) m_imp->GetDownloadTotal().ToLong();
return wxInvalidOffset;
}
//---------------------------------------------------------------------------
// wxMediaCtrl::DoMoveWindow
//

View File

@@ -118,6 +118,9 @@ public:
virtual double GetPlaybackRate();
virtual bool SetPlaybackRate(double dRate);
virtual double GetVolume();
virtual bool SetVolume(double);
void Cleanup();
void FinishLoad();
@@ -477,6 +480,11 @@ void wxQTMediaBackend::FinishLoad()
m_ctrl->GetParent()->Layout();
m_ctrl->GetParent()->Refresh();
m_ctrl->GetParent()->Update();
//send loaded event
wxMediaEvent theEvent(wxEVT_MEDIA_LOADED,
m_ctrl->GetId());
m_ctrl->AddPendingEvent(theEvent);
}
//---------------------------------------------------------------------------
@@ -579,6 +587,53 @@ wxLongLong wxQTMediaBackend::GetPosition()
return ::GetMovieTime(m_movie, NULL);
}
//---------------------------------------------------------------------------
// wxQTMediaBackend::GetVolume
//
// Gets the volume through GetMovieVolume - which returns a 16 bit short -
//
// +--------+--------+
// + (1) + (2) +
// +--------+--------+
//
// (1) first 8 bits are value before decimal
// (2) second 8 bits are value after decimal
//
// Volume ranges from -1.0 (gain but no sound), 0 (no sound and no gain) to
// 1 (full gain and sound)
//---------------------------------------------------------------------------
double wxQTMediaBackend::GetVolume()
{
short sVolume = GetMovieVolume(m_movie);
if(sVolume & (128 << 8)) //negative - no sound
return 0.0;
return (sVolume & (127 << 8)) ? 1.0 : ((double)(sVolume & 255)) / 255.0;
}
//---------------------------------------------------------------------------
// wxQTMediaBackend::SetVolume
//
// Sets the volume through SetMovieVolume - which takes a 16 bit short -
//
// +--------+--------+
// + (1) + (2) +
// +--------+--------+
//
// (1) first 8 bits are value before decimal
// (2) second 8 bits are value after decimal
//
// Volume ranges from -1.0 (gain but no sound), 0 (no sound and no gain) to
// 1 (full gain and sound)
//---------------------------------------------------------------------------
bool wxQTMediaBackend::SetVolume(double dVolume)
{
short sVolume = (short) (dVolume >= .9999 ? 1 << 8 : (dVolume * 255) );
SetMovieVolume(m_movie, sVolume);
return true;
}
//---------------------------------------------------------------------------
// wxQTMediaBackend::GetDuration
//

File diff suppressed because it is too large Load Diff

View File

@@ -274,6 +274,8 @@ bool wxGStreamerMediaBackend::TransCapsToVideoSize(wxGStreamerMediaBackend* be,
gst_structure_get_int (s, "width", &be->m_videoSize.x);
gst_structure_get_int (s, "height", &be->m_videoSize.y);
wxLogDebug(wxT("Native video size: [%i,%i]"), be->m_videoSize.x, be->m_videoSize.y);
const GValue *par;
par = gst_structure_get_value (s, "pixel-aspect-ratio");
@@ -289,6 +291,8 @@ bool wxGStreamerMediaBackend::TransCapsToVideoSize(wxGStreamerMediaBackend* be,
be->m_videoSize.y = (int) ((float) den * be->m_videoSize.y / num);
}
wxLogDebug(wxT("Adjusted video size: [%i,%i]"), be->m_videoSize.x, be->m_videoSize.y);
be->PostRecalcSize();
return true;
}//end if caps
@@ -308,6 +312,7 @@ void wxGStreamerMediaBackend::PostRecalcSize()
m_ctrl->GetParent()->Layout();
m_ctrl->GetParent()->Refresh();
m_ctrl->GetParent()->Update();
m_ctrl->SetSize(m_ctrl->GetSize());
}
//---------------------------------------------------------------------------
@@ -446,6 +451,7 @@ bool wxGStreamerMediaBackend::Load(const wxURI& location)
if ( ! GST_IS_X_OVERLAY(overlay) )
{
#endif
wxLogDebug(wxT("Could not load Gnome preferences, reverting to xvimagesink for video for gstreamer"));
videosink = gst_element_factory_make ("xvimagesink", "videosink");
if ( !GST_IS_OBJECT(videosink) )
videosink = gst_element_factory_make ("ximagesink", "videosink");
@@ -502,13 +508,18 @@ bool wxGStreamerMediaBackend::Load(const wxURI& location)
#endif
//8
wxASSERT(gst_element_set_state (m_player,
GST_STATE_PAUSED) == GST_STATE_SUCCESS);
int nResult = gst_element_set_state (m_player, GST_STATE_PAUSED);
if(nResult != GST_STATE_SUCCESS)
{
wxLogDebug(wxT("Could not set initial state to paused!"));
return false;
}
const GList *list = NULL;
g_object_get (G_OBJECT (m_player), "stream-info", &list, NULL);
bool bVideoFound = false;
for ( ; list != NULL; list = list->next)
{
GObject *info = (GObject *) list->data;
@@ -546,6 +557,9 @@ bool wxGStreamerMediaBackend::Load(const wxURI& location)
G_CALLBACK(wxGStreamerMediaBackend::OnVideoCapsReady),
this);
}
bVideoFound = true;
break;
}//end if video
else
{
@@ -554,7 +568,17 @@ bool wxGStreamerMediaBackend::Load(const wxURI& location)
}
}//end searching through info list
if(!bVideoFound)
{
wxLogDebug(wxT("No video found for gstreamer stream"));
}
m_nPausedPos = 0;
//send loaded event
wxMediaEvent theEvent(wxEVT_MEDIA_LOADED,
m_ctrl->GetId());
m_ctrl->AddPendingEvent(theEvent);
return true;
}

View File

@@ -11,12 +11,15 @@
@WX_VERSION_TAG@.2 {
global:
*wxDialog*GetEscapeId*;
*wxLogBuffer*;
*wxEVT_MEDIA_LOADED*;
*wxGenericListCtrl*SetItemFont*wxFont*;
*wxGenericListCtrl*GetItemFont*;
*wxImage*HSVValue*;
*wxImage*RGBValue*;
*wxImage*RotateHue*;
*wxLogBuffer*;
*wxMediaCtrl*Load*wxURI*wxURI*;
*wxMediaCtrl*ShowPlayerControls*wxMediaPlayerControls*;
*wxMessageOutputBest*;
*wxShadowObject*;
*wxWizard*FinishLayout*;