mirror of
https://github.com/clementine-player/Clementine
synced 2025-02-07 14:43:37 +01:00
Add a UI for choosing which gstreamer audio sink to use
This commit is contained in:
parent
f8240e8b7c
commit
256648f5e3
@ -257,6 +257,9 @@ namespace Engine
|
||||
|
||||
static const char* kSettingsGroup;
|
||||
|
||||
public slots:
|
||||
virtual void ReloadSettings() {}
|
||||
|
||||
protected:
|
||||
Base();
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <QRegExp>
|
||||
#include <QFile>
|
||||
#include <QMessageBox>
|
||||
#include <QSettings>
|
||||
#include <QtDebug>
|
||||
|
||||
#include <gst/gst.h>
|
||||
@ -42,7 +43,9 @@
|
||||
|
||||
using std::vector;
|
||||
|
||||
GstEngine* GstEngine::sInstance;
|
||||
GstEngine* GstEngine::sInstance = NULL;
|
||||
const char* GstEngine::kSettingsGroup = "GstEngine";
|
||||
const char* GstEngine::kAutoSink = "autoaudiosink";
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -61,7 +64,7 @@ gboolean GstEngine::BusCallback(GstBus*, GstMessage* msg, gpointer) {
|
||||
|
||||
instance()->gst_error_ = QString::fromAscii( error->message );
|
||||
instance()->gst_debug_ = QString::fromAscii( debugs );
|
||||
QTimer::singleShot( 0, instance(), SLOT( handlePipelineError() ) );
|
||||
QMetaObject::invokeMethod(instance(), "HandlePipelineError", Qt::QueuedConnection);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -176,6 +179,7 @@ GstEngine::GstEngine()
|
||||
can_decode_src_(NULL),
|
||||
can_decode_bin_(NULL)
|
||||
{
|
||||
ReloadSettings();
|
||||
}
|
||||
|
||||
GstEngine::~GstEngine() {
|
||||
@ -220,6 +224,13 @@ bool GstEngine::init() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void GstEngine::ReloadSettings() {
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
|
||||
sink_ = s.value("sink", kAutoSink).toString();
|
||||
}
|
||||
|
||||
|
||||
bool GstEngine::canDecode(const QUrl &url) {
|
||||
// We had some bug reports claiming that video files cause crashes in canDecode(),
|
||||
@ -714,38 +725,41 @@ GstElement* GstEngine::CreateElement(
|
||||
}
|
||||
|
||||
|
||||
QStringList GstEngine::GetPluginList( const QString& classname ) const {
|
||||
GList* features = NULL;
|
||||
QString name;
|
||||
QStringList results;
|
||||
GstEngine::PluginDetailsList
|
||||
GstEngine::GetPluginList(const QString& classname) const {
|
||||
PluginDetailsList ret;
|
||||
|
||||
GstRegistry* registry = gst_registry_get_default();
|
||||
features = gst_registry_get_feature_list(registry,GST_TYPE_ELEMENT_FACTORY);
|
||||
while ( features ) {
|
||||
GstElementFactory * factory = GST_ELEMENT_FACTORY ( features->data );
|
||||
if ( g_strrstr ( factory->details.klass, classname.toAscii().constData() ) ) {
|
||||
name = g_strdup ( GST_PLUGIN_FEATURE_NAME ( features->data ) );
|
||||
if ( name != "autoaudiosink" )
|
||||
results << name;
|
||||
GList* features =
|
||||
gst_registry_get_feature_list(registry, GST_TYPE_ELEMENT_FACTORY);
|
||||
|
||||
while (features) {
|
||||
GstElementFactory* factory = GST_ELEMENT_FACTORY(features->data);
|
||||
if (QString(factory->details.klass).contains(classname)) {
|
||||
PluginDetails details;
|
||||
details.name = QString::fromUtf8(GST_PLUGIN_FEATURE_NAME(features->data));
|
||||
details.long_name = QString::fromUtf8(factory->details.longname);
|
||||
details.description = QString::fromUtf8(factory->details.description);
|
||||
details.author = QString::fromUtf8(factory->details.author);
|
||||
ret << details;
|
||||
}
|
||||
features = g_list_next ( features );
|
||||
}
|
||||
|
||||
gst_plugin_feature_list_free(features);
|
||||
return results;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool GstEngine::CreatePipeline() {
|
||||
DestroyPipeline();
|
||||
|
||||
QString output = "autoaudiosink";
|
||||
|
||||
gst_pipeline_ = gst_pipeline_new( "pipeline" );
|
||||
gst_audiobin_ = gst_bin_new( "audiobin" );
|
||||
|
||||
|
||||
if ( !( gst_audiosink_ = CreateElement( output, gst_audiobin_ ) ) ) {
|
||||
QTimer::singleShot( 0, this, SLOT( errorNoOutput() ) );
|
||||
if ( !( gst_audiosink_ = CreateElement( sink_, gst_audiobin_ ) ) ) {
|
||||
QMetaObject::invokeMethod(this, "ErrorNoOutput", Qt::QueuedConnection);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,17 @@ class GstEngine : public Engine::Base {
|
||||
GstEngine();
|
||||
~GstEngine();
|
||||
|
||||
struct PluginDetails {
|
||||
QString name;
|
||||
QString long_name;
|
||||
QString author;
|
||||
QString description;
|
||||
};
|
||||
typedef QList<PluginDetails> PluginDetailsList;
|
||||
|
||||
static const char* kSettingsGroup;
|
||||
static const char* kAutoSink;
|
||||
|
||||
bool init();
|
||||
|
||||
bool canDecode(const QUrl& url);
|
||||
@ -64,6 +75,8 @@ class GstEngine : public Engine::Base {
|
||||
void gstStatusText(const QString& str) { emit statusText( str ); }
|
||||
void gstMetaData(Engine::SimpleMetaBundle &bundle) { emit metaData( bundle ); }
|
||||
|
||||
PluginDetailsList GetOutputsList() const { return GetPluginList( "Sink/Audio" ); }
|
||||
|
||||
public slots:
|
||||
bool load(const QUrl&, bool stream);
|
||||
bool play(uint offset);
|
||||
@ -78,6 +91,8 @@ class GstEngine : public Engine::Base {
|
||||
/** Set equalizer preamp and gains, range -100..100. Gains are 10 values. */
|
||||
void setEqualizerParameters(int preamp, const QList<int>& bandGains);
|
||||
|
||||
void ReloadSettings();
|
||||
|
||||
protected:
|
||||
void setVolumeSW(uint percent);
|
||||
void timerEvent(QTimerEvent*);
|
||||
@ -105,12 +120,6 @@ class GstEngine : public Engine::Base {
|
||||
static GstElement* CreateElement(
|
||||
const QString& factoryName, GstElement* bin = 0, const QString& name = 0);
|
||||
|
||||
/**
|
||||
* Fetches a list of available output sink plugins
|
||||
* @return List of output sinks
|
||||
*/
|
||||
QStringList GetOutputsList() const { return GetPluginList( "Sink/Audio" ); }
|
||||
|
||||
// CALLBACKS:
|
||||
/** Bus message */
|
||||
//static GstBusSyncReply bus_cb( GstBus*, GstMessage*, gpointer );
|
||||
@ -127,7 +136,7 @@ class GstEngine : public Engine::Base {
|
||||
static void HandoffCallback( GstPad*, GstBuffer*, gpointer );
|
||||
|
||||
/** Get a list of available plugins from a specified Class */
|
||||
QStringList GetPluginList(const QString& classname) const;
|
||||
PluginDetailsList GetPluginList(const QString& classname) const;
|
||||
|
||||
/** Construct the output pipeline */
|
||||
bool CreatePipeline();
|
||||
@ -148,6 +157,8 @@ class GstEngine : public Engine::Base {
|
||||
static const int kTimerInterval = 40; //msec
|
||||
static const int kGstStateTimeout = 10000000;
|
||||
|
||||
QString sink_;
|
||||
|
||||
static GstEngine* sInstance;
|
||||
|
||||
GstElement* gst_pipeline_;
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "xspfparser.h"
|
||||
#include "playlistsequence.h"
|
||||
#include "groupbydialog.h"
|
||||
#include "engines/gstengine.h"
|
||||
|
||||
#include "globalshortcuts/globalshortcuts.h"
|
||||
|
||||
@ -96,6 +97,9 @@ MainWindow::MainWindow(QNetworkAccessManager* network, QWidget *parent)
|
||||
// Start initialising the player
|
||||
player_->Init();
|
||||
|
||||
if (GstEngine* engine = qobject_cast<GstEngine*>(player_->GetEngine()))
|
||||
settings_dialog_->SetGstEngine(engine);
|
||||
|
||||
// Models
|
||||
library_sort_model_->setSourceModel(library_);
|
||||
library_sort_model_->setSortRole(Library::Role_SortText);
|
||||
@ -327,6 +331,7 @@ MainWindow::MainWindow(QNetworkAccessManager* network, QWidget *parent)
|
||||
connect(settings_dialog_, SIGNAL(accepted()), player_, SLOT(ReloadSettings()));
|
||||
connect(settings_dialog_, SIGNAL(accepted()), osd_, SLOT(ReloadSettings()));
|
||||
connect(settings_dialog_, SIGNAL(accepted()), ui_.library_view, SLOT(ReloadSettings()));
|
||||
connect(settings_dialog_, SIGNAL(accepted()), player_->GetEngine(), SLOT(ReloadSettings()));
|
||||
|
||||
// Add stream dialog
|
||||
connect(add_stream_dialog_, SIGNAL(accepted()), SLOT(AddStreamAccepted()));
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "osd.h"
|
||||
#include "osdpretty.h"
|
||||
#include "mainwindow.h"
|
||||
#include "engines/gstengine.h"
|
||||
|
||||
#include <QSettings>
|
||||
#include <QColorDialog>
|
||||
@ -113,6 +114,10 @@ void SettingsDialog::accept() {
|
||||
s.setValue("FadeoutDuration", ui_.fadeout_duration->value());
|
||||
s.endGroup();
|
||||
|
||||
s.beginGroup(GstEngine::kSettingsGroup);
|
||||
s.setValue("sink", ui_.gst_plugin->itemData(ui_.gst_plugin->currentIndex()).toString());
|
||||
s.endGroup();
|
||||
|
||||
// Notifications
|
||||
OSD::Behaviour osd_behaviour;
|
||||
if (ui_.notifications_none->isChecked()) osd_behaviour = OSD::Disabled;
|
||||
@ -168,6 +173,17 @@ void SettingsDialog::showEvent(QShowEvent*) {
|
||||
ui_.fadeout_duration->setValue(s.value("FadeoutDuration", 2000).toInt());
|
||||
s.endGroup();
|
||||
|
||||
s.beginGroup(GstEngine::kSettingsGroup);
|
||||
QString sink = s.value("sink", GstEngine::kAutoSink).toString();
|
||||
ui_.gst_plugin->setCurrentIndex(0);
|
||||
for (int i=0 ; i<ui_.gst_plugin->count() ; ++i) {
|
||||
if (ui_.gst_plugin->itemData(i).toString() == sink) {
|
||||
ui_.gst_plugin->setCurrentIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
s.endGroup();
|
||||
|
||||
// Notifications
|
||||
s.beginGroup(OSD::kSettingsGroup);
|
||||
OSD::Behaviour osd_behaviour = OSD::Behaviour(s.value("Behaviour", OSD::Native).toInt());
|
||||
@ -282,3 +298,16 @@ void SettingsDialog::ShowTrayIconToggled(bool on) {
|
||||
if (!on && ui_.b_always_hide_->isChecked())
|
||||
ui_.b_remember_->setChecked(true);
|
||||
}
|
||||
|
||||
void SettingsDialog::SetGstEngine(const GstEngine *engine) {
|
||||
GstEngine::PluginDetailsList list = engine->GetOutputsList();
|
||||
|
||||
ui_.gst_plugin->setItemData(0, GstEngine::kAutoSink);
|
||||
foreach (const GstEngine::PluginDetails& details, list) {
|
||||
if (details.name == "autoaudiosink")
|
||||
continue;
|
||||
|
||||
ui_.gst_plugin->addItem(details.long_name, details.name);
|
||||
}
|
||||
ui_.gst_group->setEnabled(true);
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
class LibraryDirectoryModel;
|
||||
class OSDPretty;
|
||||
class GstEngine;
|
||||
|
||||
class SettingsDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
@ -32,6 +33,7 @@ class SettingsDialog : public QDialog {
|
||||
~SettingsDialog();
|
||||
|
||||
void SetLibraryDirectoryModel(LibraryDirectoryModel* model);
|
||||
void SetGstEngine(const GstEngine* engine);
|
||||
|
||||
// QDialog
|
||||
void accept();
|
||||
|
@ -108,7 +108,7 @@
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stacked_widget">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="playback_page">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
@ -187,6 +187,34 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gst_group">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>GStreamer audio engine</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Output plugin</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="gst_plugin">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Choose automatically</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -620,6 +620,15 @@ msgstr ""
|
||||
msgid " ms"
|
||||
msgstr ""
|
||||
|
||||
msgid "GStreamer audio engine"
|
||||
msgstr ""
|
||||
|
||||
msgid "Output plugin"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose automatically"
|
||||
msgstr ""
|
||||
|
||||
msgid "Show tray icon"
|
||||
msgstr ""
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user