// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
-#include "wx/mediactrl.h"
-
#if wxUSE_MEDIACTRL
+#include "wx/mediactrl.h"
+
#if wxUSE_GSTREAMER
#include <gst/gst.h> // main gstreamer header
# include <gst/gconf/gconf.h> // gstreamer glib configuration
#endif
-#include "wx/log.h" // wxLogDebug/wxLogSysError/wxLogTrace
-#include "wx/app.h" // wxTheApp->argc, wxTheApp->argv
+#ifndef WX_PRECOMP
+ #include "wx/log.h" // wxLogDebug/wxLogSysError/wxLogTrace
+ #include "wx/app.h" // wxTheApp->argc, wxTheApp->argv
+ #include "wx/timer.h" // wxTimer
+#endif
+
#include "wx/thread.h" // wxMutex/wxMutexLocker
-#include "wx/timer.h" // wxTimer
#ifdef __WXGTK__
-# include "wx/gtk/win_gtk.h" // for <gdk/gdkx.h>/GDK_WINDOW_XWINDOW
+# include "wx/gtk/win_gtk.h"
+# include <gdk/gdkx.h> // for GDK_WINDOW_XWINDOW
#endif
//-----------------------------------------------------------------------------
virtual double GetVolume();
//------------implementation from now on-----------------------------------
+ bool DoLoad(const wxString& locstring);
wxMediaCtrl* GetControl() { return m_ctrl; } // for C Callbacks
void HandleStateChange(GstElementState oldstate, GstElementState newstate);
bool QueryVideoSizeFromElement(GstElement* element);
//
// Called when the media is about to stop
//-----------------------------------------------------------------------------
-void wxGStreamerMediaEventHandler::OnMediaFinish(wxMediaEvent& event)
+void wxGStreamerMediaEventHandler::OnMediaFinish(wxMediaEvent& WXUNUSED(event))
{
// (RN - I have no idea why I thought this was good behaviour....
// maybe it made sense for streaming/nonseeking data but
//
//init gstreamer
//
- gst_init(&wxTheApp->argc, &wxTheApp->argv);
+
+ //Convert arguments to unicode if enabled
+#if wxUSE_UNICODE
+ int i;
+ char **argvGST = new char*[wxTheApp->argc + 1];
+ for ( i = 0; i < wxTheApp->argc; i++ )
+ {
+ argvGST[i] = wxStrdupA(wxConvUTF8.cWX2MB(wxTheApp->argv[i]));
+ }
+
+ argvGST[wxTheApp->argc] = NULL;
+
+ int argcGST = wxTheApp->argc;
+#else
+#define argcGST wxTheApp->argc
+#define argvGST wxTheApp->argv
+#endif
+
+ //Really init gstreamer
+ gboolean bInited;
+ GError* error = NULL;
+#if GST_VERSION_MAJOR > 0 || GST_VERSION_MINOR >= 10
+ bInited = gst_init_check(&argcGST, &argvGST, &error);
+#else
+ bInited = gst_init_check(&argcGST, &argvGST);
+#endif
+
+ // Cleanup arguments for unicode case
+#if wxUSE_UNICODE
+ for ( i = 0; i < argcGST; i++ )
+ {
+ free(argvGST[i]);
+ }
+
+ delete [] argvGST;
+#endif
+
+ if(!bInited) //gst_init_check fail?
+ {
+ if(error)
+ {
+ wxLogSysError(wxT("Could not initialize GStreamer\n")
+ wxT("Error Message:%s"),
+ (const wxChar*) wxConvUTF8.cMB2WX(error->message)
+ );
+ g_error_free(error);
+ }
+ else
+ wxLogSysError(wxT("Could not initialize GStreamer"));
+
+ return false;
+ }
//
// wxControl creation
#ifdef __WXGTK__
// We handle our own GTK expose events
- m_ctrl->m_noExpose = TRUE;
+ m_ctrl->m_noExpose = true;
#endif
if( !m_ctrl->wxControl::Create(parent, id, pos, size,
// so it doesn't draw over the video and cause sporadic
// disappearances of the video
gtk_widget_set_double_buffered(m_ctrl->m_wxwindow, FALSE);
-
- // Tell GtkPizza not to clear the background
- gtk_pizza_set_clear(GTK_PIZZA(m_ctrl->m_wxwindow), FALSE);
#endif
// don't erase the background of our control window
//-----------------------------------------------------------------------------
// wxGStreamerMediaBackend::Load (File version)
//
-// Just calls the URI version
+// Just calls DoLoad() with a prepended file scheme
//-----------------------------------------------------------------------------
bool wxGStreamerMediaBackend::Load(const wxString& fileName)
{
- return Load(
- wxURI(
- wxString( wxT("file://") ) + fileName
- )
- );
+ return DoLoad(wxString( wxT("file://") ) + fileName);
}
//-----------------------------------------------------------------------------
// wxGStreamerMediaBackend::Load (URI version)
//
+// In the case of a file URI passes it unencoded -
+// also, as of 0.10.3 and earlier GstURI (the uri parser for gstreamer)
+// is sort of broken and only accepts uris with at least two slashes
+// after the scheme (i.e. file: == not ok, file:// == ok)
+//-----------------------------------------------------------------------------
+bool wxGStreamerMediaBackend::Load(const wxURI& location)
+{
+ if(location.GetScheme().CmpNoCase(wxT("file")) == 0)
+ {
+ wxString uristring = location.BuildUnescapedURI();
+
+ //Workaround GstURI leading "//" problem and make sure it leads
+ //with that
+ return DoLoad(wxString(wxT("file://")) +
+ uristring.Right(uristring.length() - 5)
+ );
+ }
+ else
+ return DoLoad(location.BuildURI());
+}
+
+//-----------------------------------------------------------------------------
+// wxGStreamerMediaBackend::DoLoad
+//
// Loads the media
// 1) Reset member variables and set playbin back to ready state
// 2) Check URI for validity and then tell the playbin to load it
// video size or duration - no amount of clever hacking is going to get
// around that, unfortunately.
//-----------------------------------------------------------------------------
-bool wxGStreamerMediaBackend::Load(const wxURI& location)
+bool wxGStreamerMediaBackend::DoLoad(const wxString& locstring)
{
wxMutexLocker lock(m_asynclock); // lock state events and async callbacks
// Make sure the passed URI is valid and tell playbin to load it
// non-file uris are encoded
- wxString locstring;
- if(location.GetScheme().CmpNoCase(wxT("file")))
- locstring = location.BuildUnescapedURI();
- else
- locstring = location.BuildURI();
-
wxASSERT(gst_uri_protocol_is_valid("file"));
wxASSERT(gst_uri_is_valid(locstring.mb_str()));
// NB: whether we have paused or not and keep track of the time after the
// NB: pause and whenever the user seeks while paused
// NB:
-//
+//
// THREAD-UNSAFE, at least if not paused. Requires media to be at least paused.
//-----------------------------------------------------------------------------
wxLongLong wxGStreamerMediaBackend::GetPosition()