You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeaccessibility/kttsd/players/gstplayer/gstreamerplayer.cpp

257 lines
8.0 KiB

/***************************************************************************
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. *
* *
***************************************************************************/
// TQt includes.
#include <tqfile.h>
// KDE includes.
#include <tdeapplication.h>
#include <tdeconfig.h>
#include <tdeglobal.h>
#include <kdebug.h>
// GStreamerPlayer includes.
#include "gstreamerplayer.h"
#include "gstreamerplayer.moc"
////////////////////////////////////////////////////////////////////////////////
// public methods
////////////////////////////////////////////////////////////////////////////////
GStreamerPlayer::GStreamerPlayer(TQObject* parent, const char* name, const TQStringList& 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 TQString &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.
*/
TQStringList GStreamerPlayer::getPluginList( const TQCString& classname )
{
GList * pool_registries = NULL;
GList* registries = NULL;
GList* plugins = NULL;
GList* features = NULL;
TQString name;
TQStringList 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() << TQString("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() << TQString("GStreamerPlayer::requireVersion: You have gstreamer %1.%2.%3 installed.").arg(gmajor).arg(gminor).arg(gmicro) << endl;
kdDebug() << TQString("GStreamerPlayer::requireVersion: This application requires %1.%2.%3 or greater.").arg(major).arg(minor).arg(micro) << endl;
return false;
}
void GStreamerPlayer::setSinkName(const TQString &sinkName) { m_sinkName = sinkName; }
////////////////////////////////////////////////////////////////////////////////
// private methods
////////////////////////////////////////////////////////////////////////////////
void GStreamerPlayer::readConfig()
{
TDEConfigGroup config(TDEGlobal::config(), "GStreamerPlayer");
m_sinkName = config.readEntry("SinkName", TQString());
}
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;
}