diff options
Diffstat (limited to 'kttsd/players/gstplayer/gstreamerplayer.cpp')
-rw-r--r-- | kttsd/players/gstplayer/gstreamerplayer.cpp | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/kttsd/players/gstplayer/gstreamerplayer.cpp b/kttsd/players/gstplayer/gstreamerplayer.cpp new file mode 100644 index 0000000..64aa1c4 --- /dev/null +++ b/kttsd/players/gstplayer/gstreamerplayer.cpp @@ -0,0 +1,258 @@ +/*************************************************************************** + copyright : (C) 2004 Scott Wheeler + email : wheeler@kde.org +***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +// Qt includes. +#include <qfile.h> + +// KDE includes. +#include <kapplication.h> +#include <kconfig.h> +#include <kglobal.h> +#include <kdebug.h> + +// GStreamerPlayer includes. +#include "gstreamerplayer.h" +#include "gstreamerplayer.moc" + +//////////////////////////////////////////////////////////////////////////////// +// public methods +//////////////////////////////////////////////////////////////////////////////// + +GStreamerPlayer::GStreamerPlayer(QObject* parent, const char* name, const QStringList& args) : + Player(parent, name, args), + m_initialized(false), + m_pipeline(0), + m_source(0), + m_decoder(0), + m_volume(0), + m_sink(0) +{ + // readConfig(); + setupPipeline(); +} + +GStreamerPlayer::~GStreamerPlayer() +{ + stop(); + gst_object_unref(GST_OBJECT(m_pipeline)); +} + +//void GStreamerPlayer::play(const FileHandle &file) +void GStreamerPlayer::startPlay(const QString &file) +{ + if(!file.isNull()) { + stop(); + // g_object_set(G_OBJECT(m_source), "location", file.absFilePath().local8Bit().data(), 0); + g_object_set(G_OBJECT(m_source),"location",file.local8Bit().data(),NULL); + } + + gst_element_set_state(m_pipeline, GST_STATE_PLAYING); +} + +void GStreamerPlayer::pause() +{ + gst_element_set_state(m_pipeline, GST_STATE_PAUSED); +} + +void GStreamerPlayer::stop() +{ + gst_element_set_state(m_pipeline, GST_STATE_NULL); +} + +void GStreamerPlayer::setVolume(float volume) +{ + g_object_set(G_OBJECT(m_volume), "volume", volume, NULL); +} + +float GStreamerPlayer::volume() const +{ + gfloat value; + g_object_get(G_OBJECT(m_volume), "volume", &value, NULL); + return value; +} + +bool GStreamerPlayer::playing() const +{ + return gst_element_get_state(m_pipeline) == GST_STATE_PLAYING; +} + +bool GStreamerPlayer::paused() const +{ + return gst_element_get_state(m_pipeline) == GST_STATE_PAUSED; +} + +int GStreamerPlayer::totalTime() const +{ + return time(GST_QUERY_TOTAL) / GST_SECOND; +} + +int GStreamerPlayer::currentTime() const +{ + return time(GST_QUERY_POSITION) / GST_SECOND; +} + +int GStreamerPlayer::position() const +{ + long long total = time(GST_QUERY_TOTAL); + long long current = time(GST_QUERY_POSITION); + return total > 0 ? int((double(current) / double(total)) * double(1000) + 0.5) : 0; +} + +void GStreamerPlayer::seek(int seekTime) +{ + int type = (GST_FORMAT_TIME | GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH); + gst_element_seek(m_sink, GstSeekType(type), seekTime * GST_SECOND); +} + +void GStreamerPlayer::seekPosition(int position) +{ + long long total = time(GST_QUERY_TOTAL); + if(total > 0) + seek(int(double(position) / double(1000) * double(totalTime()) + 0.5)); +} + +/** + * Returns a list of GStreamer plugins of the specified class. + * @param classname Desired class. Use "Sink/Audio" for sinks. + * @return List of plugin names. + */ +QStringList GStreamerPlayer::getPluginList( const QCString& classname ) +{ + GList * pool_registries = NULL; + GList* registries = NULL; + GList* plugins = NULL; + GList* features = NULL; + QString name; + QStringList results; + + if(!m_initialized) { + int argc = kapp->argc(); + char **argv = kapp->argv(); + gst_init(&argc, &argv); + m_initialized = true; + } + + pool_registries = gst_registry_pool_list (); + registries = pool_registries; + + while ( registries ) { + GstRegistry * registry = GST_REGISTRY ( registries->data ); + plugins = registry->plugins; + + while ( plugins ) { + GstPlugin * plugin = GST_PLUGIN ( plugins->data ); + features = gst_plugin_get_feature_list ( plugin ); + + while ( features ) { + GstPluginFeature * feature = GST_PLUGIN_FEATURE ( features->data ); + + if ( GST_IS_ELEMENT_FACTORY ( feature ) ) { + GstElementFactory * factory = GST_ELEMENT_FACTORY ( feature ); + + if ( g_strrstr ( factory->details.klass, classname ) ) { + name = g_strdup ( GST_OBJECT_NAME ( factory ) ); + if ( name != "artsdsink" ) results << name; + } + } + features = g_list_next ( features ); + } + plugins = g_list_next ( plugins ); + } + registries = g_list_next ( registries ); + } + g_list_free ( pool_registries ); + pool_registries = NULL; + + return results; +} + +bool GStreamerPlayer::requireVersion(uint major, uint minor, uint micro) +{ + guint gmajor, gminor, gmicro; + + if(!m_initialized) { + int argc = kapp->argc(); + char **argv = kapp->argv(); + gst_init(&argc, &argv); + m_initialized = true; + } + + gst_version(&gmajor, &gminor, &gmicro); + // kdDebug() << QString("GStreamerPlayer::requireVersion: You have gstreamer %1.%2.%3 installed.").arg(gmajor).arg(gminor).arg(gmicro) << endl; + if (gmajor > major) return true; + if (gminor > minor) return true; + if (gmicro >= micro) return true; + kdDebug() << QString("GStreamerPlayer::requireVersion: You have gstreamer %1.%2.%3 installed.").arg(gmajor).arg(gminor).arg(gmicro) << endl; + kdDebug() << QString("GStreamerPlayer::requireVersion: This application requires %1.%2.%3 or greater.").arg(major).arg(minor).arg(micro) << endl; + return false; +} + +void GStreamerPlayer::setSinkName(const QString &sinkName) { m_sinkName = sinkName; } + +//////////////////////////////////////////////////////////////////////////////// +// private methods +//////////////////////////////////////////////////////////////////////////////// + +void GStreamerPlayer::readConfig() +{ + KConfigGroup config(KGlobal::config(), "GStreamerPlayer"); + m_sinkName = config.readEntry("SinkName", QString::null); +} + +void GStreamerPlayer::setupPipeline() +{ + if(!m_initialized) { + int argc = kapp->argc(); + char **argv = kapp->argv(); + gst_init(&argc, &argv); + m_initialized = true; + } + + m_pipeline = gst_thread_new("pipeline"); + m_source = gst_element_factory_make("filesrc", "source"); + m_decoder = gst_element_factory_make("spider", "decoder"); + m_volume = gst_element_factory_make("volume", "volume"); + + if(!m_sinkName.isNull()) + m_sink = gst_element_factory_make(m_sinkName.utf8().data(), "sink"); + if (!m_sink) + { + // m_sink = gst_element_factory_make("alsasink", "sink"); + // if(!m_sink) + // m_sink = gst_element_factory_make("osssink", "sink"); + + // Reversing order. OSS seems to work. Alsa sink produces ugly echo of last + // couple of words in each wav file. argh! + // kdDebug() << "GStreamerPlayer::setupPipeline: trying oss sink." << endl; + m_sink = gst_element_factory_make("osssink", "sink"); + if(!m_sink) + { + // kdDebug() << "GStreamerPlayer::setupPipeline: reverting to alsa sink." << endl; + m_sink = gst_element_factory_make("alsasink", "sink"); + } + } + + gst_bin_add_many(GST_BIN(m_pipeline), m_source, m_decoder, m_volume, m_sink, 0); + gst_element_link_many(m_source, m_decoder, m_volume, m_sink, 0); +} + +long long GStreamerPlayer::time(GstQueryType type) const +{ + gint64 ns = 0; + GstFormat format = GST_FORMAT_TIME; + gst_element_query(m_sink, type, &format, &ns); + return ns; +} + +// vim: set et sw=4: |