[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: =?utf-8?q?=5Bphonon-gstreamer=5D_gstreamer=3A_Move_swaths_of_plu?=
From: Trever Fischer <wm161 () wm161 ! net>
Date: 2011-03-01 14:39:26
Message-ID: 20110301143926.587A8A60CE () git ! kde ! org
[Download RAW message or body]
Git commit ae379e2c11a9c07bac311e57b2ca2e67e3040d80 by Trever Fischer.
Committed on 01/03/2011 at 15:34.
Pushed by tdfischer into branch 'master'.
Move swaths of plugin installation code to the PluginInstaller
Cleanup is probably needed. The mediaobject is still pretty freaking
huge; its hard to catch everything. Plugin installation still behaves as
previously (broken in places, but works for mp3s and rsndvdbin).
M +40 -120 gstreamer/mediaobject.cpp
M +5 -9 gstreamer/mediaobject.h
M +145 -4 gstreamer/plugininstaller.cpp
M +35 -1 gstreamer/plugininstaller.h
http://commits.kde.org/phonon-gstreamer/ae379e2c11a9c07bac311e57b2ca2e67e3040d80
diff --git a/gstreamer/mediaobject.cpp b/gstreamer/mediaobject.cpp
index 10a1038..05aa24b 100644
--- a/gstreamer/mediaobject.cpp
+++ b/gstreamer/mediaobject.cpp
@@ -87,6 +87,7 @@ MediaObject::MediaObject(Backend *backend, QObject *parent)
, m_currentTitle(1)
, m_pendingTitle(1)
, m_installingPlugin(true)
+ , m_installer(new PluginInstaller(this))
{
qRegisterMetaType<GstCaps*>("GstCaps*");
qRegisterMetaType<State>("State");
@@ -112,6 +113,10 @@ MediaObject::MediaObject(Backend *backend, QObject *parent)
g_signal_connect(bus, "sync-message::warning", G_CALLBACK(cb_warning), \
this);
g_signal_connect(bus, "sync-message::error", G_CALLBACK(cb_error), this);
connect(m_tickTimer, SIGNAL(timeout()), SLOT(emitTick()));
+
+ connect(m_installer, SIGNAL(failure(const QString&)), this, \
SLOT(pluginInstallFailure(const QString&))); + connect(m_installer, \
SIGNAL(started()), this, SLOT(pluginInstallStarted())); + connect(m_installer, \
SIGNAL(success()), this, SLOT(pluginInstallComplete())); }
connect(this, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
this, SLOT(notifyStateChange(Phonon::State, Phonon::State)));
@@ -208,111 +213,6 @@ void MediaObject::cb_newpad (GstElement *decodebin,
media->newPadAvailable(pad);
}
-#ifdef PLUGIN_INSTALL_API
-void MediaObject::pluginInstallationResult(GstInstallPluginsReturn result)
-{
- if (!m_installingPlugin) {
- // Changed media while the installer was working, so we just do not care \
what happened.
- return;
- }
- bool wasInstalling = m_installingPlugin;
- m_installingPlugin = false;
- bool canPlay = (m_hasAudio || m_videoStreamFound);
- Phonon::ErrorType error = canPlay ? Phonon::NormalError : Phonon::FatalError;
- switch(result) {
- case GST_INSTALL_PLUGINS_INVALID:
- setError(QString(tr("Phonon attempted to install an invalid codec name.")));
- break;
- case GST_INSTALL_PLUGINS_CRASHED:
- setError(QString(tr("The codec installer crashed.")), error);
- break;
- case GST_INSTALL_PLUGINS_NOT_FOUND:
- setError(QString(tr("The required codec could not be found for \
installation.")), error);
- break;
- case GST_INSTALL_PLUGINS_ERROR:
- setError(QString(tr("An unspecified error occurred during codec \
installation.")), error);
- break;
- case GST_INSTALL_PLUGINS_PARTIAL_SUCCESS:
- setError(QString(tr("Not all codecs could be installed.")), error);
- break;
- case GST_INSTALL_PLUGINS_USER_ABORT:
- setError(QString(tr("User aborted codec installation")), error);
- break;
- //These four should never ever be passed in.
- //If they have, gstreamer has probably imploded in on itself.
- case GST_INSTALL_PLUGINS_STARTED_OK:
- case GST_INSTALL_PLUGINS_INTERNAL_FAILURE:
- case GST_INSTALL_PLUGINS_HELPER_MISSING:
- case GST_INSTALL_PLUGINS_INSTALL_IN_PROGRESS:
- //But this one is OK.
- case GST_INSTALL_PLUGINS_SUCCESS:
- m_backend->logMessage("Updating registry");
- if (gst_update_registry()) {
- m_backend->logMessage("Registry updated failed");
- }
- if (wasInstalling) {
- setSource(source());
- play();
- }
- break;
- }
-}
-
-void MediaObject::pluginInstallationDone(GstInstallPluginsReturn result, gpointer \
userData)
-{
- QPointer<MediaObject> *that = static_cast<QPointer<MediaObject>*>(userData);
- if (*that) {
- qRegisterMetaType<GstInstallPluginsReturn>("GstInstallPluginsReturn");
- QMetaObject::invokeMethod(*that, "pluginInstallationResult", \
Qt::QueuedConnection, Q_ARG(GstInstallPluginsReturn, result));
- }
-}
-#endif // PLUGIN_INSTALL_API
-
-void MediaObject::installMissingCodecs()
-{
- if (m_missingCodecs.size() > 0) {
- bool canPlay = (m_hasAudio || m_videoStreamFound);
- Phonon::ErrorType error = canPlay ? Phonon::NormalError : \
Phonon::FatalError;
-#ifdef PLUGIN_INSTALL_API
- GstInstallPluginsContext *ctx = gst_install_plugins_context_new();
- QWidget *activeWindow = QApplication::activeWindow();
- if (activeWindow) {
- gst_install_plugins_context_set_xid(ctx, \
static_cast<int>(activeWindow->winId()));
- }
- gchar *details[2];
- QByteArray missingCodec = m_missingCodecs.first().toLocal8Bit();
- details[0] = missingCodec.data();
- details[1] = NULL;
- GstInstallPluginsReturn status;
-
- status = gst_install_plugins_async(details, ctx, pluginInstallationDone, new \
QPointer<MediaObject>(this));
- gst_install_plugins_context_free(ctx);
-
- if (status != GST_INSTALL_PLUGINS_STARTED_OK) {
- if (status == GST_INSTALL_PLUGINS_HELPER_MISSING)
- setError(QString(tr("Missing codec helper script assistant.")), \
Phonon::FatalError);
- else
- setError(QString(tr("Plugin codec installation failed for plugin: \
%1"))
- .arg(m_missingCodecs[0].split('|')[3]), error);
- } else {
- m_installingPlugin = true;
- setState(Phonon::LoadingState);
- }
- m_missingCodecs.clear();
-#else
- QString codecs = m_missingCodecs.join(", ");
-
- if (error == Phonon::NormalError && m_hasVideo && !m_videoStreamFound) {
- m_hasVideo = false;
- emit hasVideoChanged(false);
- }
- setError(QString(tr("A required GStreamer plugin is missing. You need to \
install the following plugin(s) to play this content: %0"), "", \
codecs.size()).arg(codecs), error);
- m_missingCodecs.clear();
-#endif
- }
-}
-
-
void MediaObject::cb_unknown_type (GstElement *decodebin, GstPad *pad, GstCaps \
*caps, gpointer data) {
Q_UNUSED(decodebin);
@@ -320,8 +220,7 @@ void MediaObject::cb_unknown_type (GstElement *decodebin, GstPad \
*pad, GstCaps * MediaObject *media = static_cast<MediaObject*>(data);
Q_ASSERT(media);
- media->addMissingCodecName(PluginInstaller::buildInstallationString(caps, \
PluginInstaller::Codec));
-
+ media->m_installer->addPlugin(caps, PluginInstaller::Codec);
}
static void notifyVideoCaps(GObject *obj, GParamSpec *, gpointer data)
@@ -461,26 +360,20 @@ bool MediaObject::createPipefromDVD(const MediaSource &source)
// video output stream. The audio and video streams are then funneled into
// the audioGraph and videoGraph bins by way of connectAudio and decodebin,
// respectively.
-
+
+ m_installer->addPlugin("rsndvdbin", PluginInstaller::Element);
+ m_installer->addPlugin("dvdspu", PluginInstaller::Element);
+ if (m_installer->checkInstalledPlugins() != PluginInstaller::Installed)
+ return false;
m_datasource = gst_bin_new(NULL);
gst_bin_add(GST_BIN(m_pipeline), m_datasource);
GstElement *dvdsrc = gst_element_factory_make("rsndvdbin", NULL);
- if (!dvdsrc) {
- addMissingCodecName( PluginInstaller::buildInstallationString("rsndvdbin", \
PluginInstaller::Element) );
- installMissingCodecs();
- return false;
- }
// Check for the dvdspu element from gst-plugins-bad before continuing.
// Fedora keeps rsndvdbin and dvdspu in separate packages for some reason.
GstElement *spu = gst_element_factory_make("dvdspu", NULL);
- if (!spu) {
- addMissingCodecName( PluginInstaller::buildInstallationString("dvdspu", \
PluginInstaller::Element) );
- installMissingCodecs();
- return false;
- }
gst_bin_add(GST_BIN(m_datasource), dvdsrc);
QByteArray mediaDevice = QFile::encodeName(source.deviceName());
@@ -1114,7 +1007,7 @@ void MediaObject::setSource(const MediaSource &source)
m_source = source;
emit currentSourceChanged(m_source);
m_previousTickTime = -1;
- m_missingCodecs.clear();
+ m_installer->reset();
// Go into to loading state
changeState(Phonon::LoadingState);
@@ -1488,7 +1381,7 @@ void MediaObject::handleErrorMessage(GstMessage *gstMessage)
}
} else if ((err->domain == GST_CORE_ERROR && err->code == \
GST_CORE_ERROR_MISSING_PLUGIN)
|| (err->domain == GST_STREAM_ERROR && err->code == \
GST_STREAM_ERROR_CODEC_NOT_FOUND)) {
- installMissingCodecs();
+ m_installer->checkInstalledPlugins();
} else if (!(err->domain == GST_STREAM_ERROR && m_installingPlugin)) {
setError(err->message, Phonon::FatalError);
}
@@ -2037,6 +1930,33 @@ void MediaObject::setTrack(int title)
}
}
+void MediaObject::pluginInstallComplete()
+{
+ if (!m_installingPlugin)
+ return;
+
+ bool wasInstalling = m_installingPlugin;
+ m_installingPlugin = false;
+ if (wasInstalling) {
+ setSource(source());
+ play();
+ }
+}
+
+void MediaObject::pluginInstallStarted()
+{
+ setState(Phonon::LoadingState);
+ m_installingPlugin = true;
+}
+
+void MediaObject::pluginInstallFailure(const QString &msg)
+{
+ m_installingPlugin = false;
+ bool canPlay = (m_hasAudio || m_videoStreamFound);
+ Phonon::ErrorType error = canPlay ? Phonon::NormalError : Phonon::FatalError;
+ setError(msg, error);
+}
+
} // ns Gstreamer
} // ns Phonon
diff --git a/gstreamer/mediaobject.h b/gstreamer/mediaobject.h
index 0b88431..044a1ff 100644
--- a/gstreamer/mediaobject.h
+++ b/gstreamer/mediaobject.h
@@ -46,6 +46,7 @@ class VideoWidget;
class AudioPath;
class VideoPath;
class AudioOutput;
+class PluginInstaller;
class MediaObject : public QObject, public MediaObjectInterface
#ifndef QT_NO_PHONON_MEDIACONTROLLER
@@ -163,7 +164,6 @@ public:
static gboolean cb_warning(GstBus *bus, GstMessage *msg, gpointer data);
static gboolean cb_error(GstBus *bus, GstMessage *msg, gpointer data);
- void addMissingCodecName(const QString &codec) { m_missingCodecs.append(codec); \
} void invalidateGraph();
static void cb_newpad (GstElement *decodebin, GstPad *pad, gboolean last, \
gpointer data); @@ -233,15 +233,14 @@ protected:
}
private Q_SLOTS:
- void installMissingCodecs();
void getStreamInfo();
void emitTick();
void beginPlay();
void setVideoCaps(GstCaps *caps);
void notifyStateChange(Phonon::State newstate, Phonon::State oldstate);
-#ifdef PLUGIN_INSTALL_API
- void pluginInstallationResult(GstInstallPluginsReturn result);
-#endif // PLUGIN_INSTALL_API
+ void pluginInstallComplete();
+ void pluginInstallFailure(const QString &msg);
+ void pluginInstallStarted();
private:
// GStreamer specific :
@@ -258,9 +257,6 @@ private:
void _iface_setCurrentTitle(int title);
void setTrack(int title);
- // Plugin API callback
- static void pluginInstallationDone(GstInstallPluginsReturn result, gpointer \
userData);
-
bool m_resumeState;
State m_oldState;
quint64 m_oldPos;
@@ -305,13 +301,13 @@ private:
GstElement *m_videoGraph;
int m_previousTickTime;
bool m_resetNeeded;
- QStringList m_missingCodecs;
QMultiMap<QString, QString> m_metaData;
bool m_autoplayTitles;
int m_availableTitles;
int m_currentTitle;
int m_pendingTitle;
bool m_installingPlugin;
+ PluginInstaller *m_installer;
};
}
} //namespace Phonon::Gstreamer
diff --git a/gstreamer/plugininstaller.cpp b/gstreamer/plugininstaller.cpp
index f716729..5cac431 100644
--- a/gstreamer/plugininstaller.cpp
+++ b/gstreamer/plugininstaller.cpp
@@ -16,8 +16,14 @@
*/
#include "plugininstaller.h"
+#include <gst/gst.h>
#include <QtCore/QCoreApplication>
+#include <QtGui/QApplication>
+#include <QtGui/QWidget>
#include <QtCore/QLibrary>
+#include <QtCore/QPointer>
+#include <QtCore/QMetaType>
+#include <QtCore/QDebug>
QT_BEGIN_NAMESPACE
@@ -83,8 +89,7 @@ QString PluginInstaller::description(const GstCaps *caps, \
PluginType type) g_free (pluginDesc);
return pluginStr;
}
- GstStructure *str = gst_caps_get_structure (caps, 0);
- return QString::fromUtf8(gst_structure_get_name (str));;
+ return getCapType(caps);
}
QString PluginInstaller::description(const gchar *name, PluginType type)
@@ -129,12 +134,11 @@ QString PluginInstaller::buildInstallationString(const GstCaps \
*caps, PluginType return 0;
}
- GstStructure *str = gst_caps_get_structure(caps, 0);
return QString("gstreamer|0.10|%0|%1|%2-%3")
.arg( qApp->applicationName() )
.arg( description(caps, type) )
.arg( descType )
- .arg( QString::fromUtf8(gst_structure_get_name(str)) );
+ .arg( getCapType(caps) );
}
QString PluginInstaller::buildInstallationString(const gchar *name, PluginType type)
@@ -154,7 +158,144 @@ QString PluginInstaller::buildInstallationString(const gchar \
*name, PluginType t
.arg( name );
}
+PluginInstaller::PluginInstaller(QObject *parent)
+ : QObject(parent)
+{
+}
+
+void PluginInstaller::addPlugin(const QString &name, PluginType type)
+{
+ m_pluginList.insert(name, type);
+}
+
+void PluginInstaller::addPlugin(const GstCaps *caps, PluginType type)
+{
+ m_capList.insert(gst_caps_copy(caps), type);
+}
+
+#ifdef PLUGIN_INSTALL_API
+void PluginInstaller::run()
+{
+ GstInstallPluginsContext *ctx = gst_install_plugins_context_new();
+ QWidget *activeWindow = QApplication::activeWindow();
+ if (activeWindow) {
+ gst_install_plugins_context_set_xid(ctx, \
static_cast<int>(activeWindow->winId())); + }
+ gchar *details[m_pluginList.size()+m_capList.size()+1];
+ int i = 0;
+ foreach(QString plugin, m_pluginList.keys()) {
+ details[i] = strdup(buildInstallationString(plugin.toLocal8Bit().data(), \
m_pluginList[plugin]).toLocal8Bit().data()); + i++;
+ }
+ foreach(GstCaps *caps, m_capList.keys()) {
+ details[i] = strdup(buildInstallationString(caps, \
m_capList[caps]).toLocal8Bit().data()); + i++;
+ }
+ details[i] = NULL;
+
+ GstInstallPluginsReturn status;
+ status = gst_install_plugins_async(details, ctx, pluginInstallationDone, new \
QPointer<PluginInstaller>(this)); + gst_install_plugins_context_free(ctx);
+ if (status != GST_INSTALL_PLUGINS_STARTED_OK) {
+ if (status == GST_INSTALL_PLUGINS_HELPER_MISSING)
+ emit failure(tr("Missing codec helper script assistant."));
+ else
+ emit failure(tr("Plugin codec installation failed."));
+ } else {
+ emit started();
+ }
+ for(i;i>0;i--)
+ free(details[i]);
+ reset();
+}
+
+void PluginInstaller::pluginInstallationDone(GstInstallPluginsReturn result, \
gpointer data) +{
+ QPointer<PluginInstaller> *that = static_cast<QPointer<PluginInstaller>*>(data);
+ if (*that) {
+ qRegisterMetaType<GstInstallPluginsReturn>("GstInstallPluginsReturn");
+ (*that)->pluginInstallationResult(result);
+ }
+}
+
+void PluginInstaller::pluginInstallationResult(GstInstallPluginsReturn result)
+{
+ switch(result) {
+ case GST_INSTALL_PLUGINS_INVALID:
+ emit failure(tr("Phonon attempted to install an invalid codec name."));
+ break;
+ case GST_INSTALL_PLUGINS_CRASHED:
+ emit failure(tr("The codec installer crashed."));
+ break;
+ case GST_INSTALL_PLUGINS_NOT_FOUND:
+ emit failure(tr("The required codec could not be found for \
installation.")); + break;
+ case GST_INSTALL_PLUGINS_ERROR:
+ emit failure(tr("An unspecified error occurred during codec \
installation.")); + break;
+ case GST_INSTALL_PLUGINS_PARTIAL_SUCCESS:
+ emit failure(tr("Not all codecs could be installed."));
+ break;
+ case GST_INSTALL_PLUGINS_USER_ABORT:
+ emit failure(tr("User aborted codec installation"));
+ break;
+ //These four should never ever be passed in.
+ //If they have, gstreamer has probably imploded in on itself.
+ case GST_INSTALL_PLUGINS_STARTED_OK:
+ case GST_INSTALL_PLUGINS_INTERNAL_FAILURE:
+ case GST_INSTALL_PLUGINS_HELPER_MISSING:
+ case GST_INSTALL_PLUGINS_INSTALL_IN_PROGRESS:
+ //But this one is OK.
+ case GST_INSTALL_PLUGINS_SUCCESS:
+ if (!gst_update_registry()) {
+ emit failure(tr("Could not update plugin registry after update."));
+ } else {
+ emit success();
+ }
+ break;
+ }
+}
+#endif
+
+PluginInstaller::InstallStatus PluginInstaller::checkInstalledPlugins()
+{
+ bool allFound = true;
+ foreach(QString plugin, m_pluginList.keys()) {
+ if (!gst_default_registry_check_feature_version(plugin.toLocal8Bit().data(), \
0, 10, 0)) { + allFound = false;
+ break;
+ }
+ }
+ if (!allFound || m_capList.size() > 0) {
+#ifdef PLUGIN_INSTALL_API
+ run();
+ return Installing;
+#else
+ return Missing;
+#endif
+ } else {
+ return Installed;
+ }
+}
+
+QString PluginInstaller::getCapType(const GstCaps *caps)
+{
+ GstStructure *str = gst_caps_get_structure (caps, 0);
+ return QString::fromUtf8(gst_structure_get_name (str));;
+}
+
+void PluginInstaller::reset()
+{
+ foreach(GstCaps *caps, m_capList.keys()) {
+ gst_caps_unref(caps);
+ }
+ m_capList.clear();
+ m_pluginList.clear();
+}
+
} // ns Gstreamer
} // ns Phonon
QT_END_NAMESPACE
+
+#include "moc_plugininstaller.cpp"
diff --git a/gstreamer/plugininstaller.h b/gstreamer/plugininstaller.h
index e2a1191..d79e17d 100644
--- a/gstreamer/plugininstaller.h
+++ b/gstreamer/plugininstaller.h
@@ -19,7 +19,11 @@
#define Phonon_GSTREAMER_PLUGININSTALLER_H
#include "common.h"
+#include <QtCore/QObject>
#include <gst/gstcaps.h>
+#include <gst/pbutils/install-plugins.h>
+#include "phonon-config-gstreamer.h"
+
QT_BEGIN_NAMESPACE
@@ -40,7 +44,8 @@ typedef gchar* (*Ptr_gst_pb_utils_get_codec_description)(const \
GstCaps *);
* A class to help with installing missing gstreamer plugins
*/
-class PluginInstaller {
+class PluginInstaller : public QObject {
+ Q_OBJECT
public:
enum PluginType {
Source,
@@ -51,19 +56,48 @@ class PluginInstaller {
Codec
};
+ enum InstallStatus {
+ Idle,
+ Installed,
+ Installing,
+ Missing
+ };
+
+ PluginInstaller(QObject *parent = 0);
+
+ void addPlugin(const QString &name, PluginType type);
+ void addPlugin(const GstCaps *caps, PluginType type);
+
+ InstallStatus checkInstalledPlugins();
+#ifdef PLUGIN_INSTALL_API
+ static void pluginInstallationDone(GstInstallPluginsReturn result, gpointer \
data); + void pluginInstallationResult(GstInstallPluginsReturn result);
+ void run();
+#endif
+ void reset();
+
/**
* Returns the translated, user-friendly string that describes a plugin
*/
static QString description(const gchar *name, PluginType type);
static QString description(const GstCaps *caps, PluginType type);
+ static QString getCapType(const GstCaps *caps);
+
/**
* Builds a string suitable for passing to gst_install_plugins_*
*/
static QString buildInstallationString(const gchar *name, PluginType type);
static QString buildInstallationString(const GstCaps *caps, PluginType \
type);
+ Q_SIGNALS:
+ void started();
+ void success();
+ void failure(const QString &message);
+
private:
+ QHash<QString, PluginType> m_pluginList;
+ QHash<GstCaps *, PluginType> m_capList;
static bool init();
static bool s_ready;
static Ptr_gst_pb_utils_init p_gst_pb_utils_init;
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic