From 74a5233b5d71123415202000325e966ea98d5cc5 Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Wed, 7 Oct 2020 20:29:26 +0200 Subject: [PATCH] Replace use of deprecated gstreamer low-percent - Add settings for low-watermark and high-watermark - Add button to reset buffer settings to defaults --- src/engine/enginebase.cpp | 10 +- src/engine/enginebase.h | 3 +- src/engine/gstengine.cpp | 3 +- src/engine/gstenginepipeline.cpp | 22 ++-- src/engine/gstenginepipeline.h | 8 +- src/settings/backendsettingspage.cpp | 46 ++++--- src/settings/backendsettingspage.h | 21 ++-- src/settings/backendsettingspage.ui | 172 +++++++++++++++++++-------- 8 files changed, 190 insertions(+), 95 deletions(-) diff --git a/src/engine/enginebase.cpp b/src/engine/enginebase.cpp index 5f5a5f21d..0b2ba56eb 100644 --- a/src/engine/enginebase.cpp +++ b/src/engine/enginebase.cpp @@ -46,8 +46,9 @@ Engine::Base::Base() rg_mode_(0), rg_preamp_(0), rg_compression_(true), - buffer_duration_nanosec_(4000), - buffer_min_fill_(33), + buffer_duration_nanosec_(BackendSettingsPage::kDefaultBufferDuration * kNsecPerMsec), + buffer_low_watermark_(BackendSettingsPage::kDefaultBufferLowWatermark), + buffer_high_watermark_(BackendSettingsPage::kDefaultBufferHighWatermark), fadeout_enabled_(true), crossfade_enabled_(true), autocrossfade_enabled_(false), @@ -105,8 +106,9 @@ void Engine::Base::ReloadSettings() { volume_control_ = s.value("volume_control", true).toBool(); - buffer_duration_nanosec_ = s.value("bufferduration", 4000).toLongLong() * kNsecPerMsec; - buffer_min_fill_ = s.value("bufferminfill", 33).toInt(); + buffer_duration_nanosec_ = s.value("bufferduration", BackendSettingsPage::kDefaultBufferDuration).toLongLong() * kNsecPerMsec; + buffer_low_watermark_ = s.value("bufferlowwatermark", BackendSettingsPage::kDefaultBufferLowWatermark).toDouble(); + buffer_high_watermark_ = s.value("bufferhighwatermark", BackendSettingsPage::kDefaultBufferHighWatermark).toDouble(); rg_enabled_ = s.value("rgenabled", false).toBool(); rg_mode_ = s.value("rgmode", 0).toInt(); diff --git a/src/engine/enginebase.h b/src/engine/enginebase.h index db296123d..ba103ebf0 100644 --- a/src/engine/enginebase.h +++ b/src/engine/enginebase.h @@ -186,7 +186,8 @@ public: // Buffering quint64 buffer_duration_nanosec_; - int buffer_min_fill_; + double buffer_low_watermark_; + double buffer_high_watermark_; // Fadeout bool fadeout_enabled_; diff --git a/src/engine/gstengine.cpp b/src/engine/gstengine.cpp index c06252c25..f40131645 100644 --- a/src/engine/gstengine.cpp +++ b/src/engine/gstengine.cpp @@ -758,7 +758,8 @@ std::shared_ptr GstEngine::CreatePipeline() { ret->set_equalizer_enabled(equalizer_enabled_); ret->set_replaygain(rg_enabled_, rg_mode_, rg_preamp_, rg_compression_); ret->set_buffer_duration_nanosec(buffer_duration_nanosec_); - ret->set_buffer_min_fill(buffer_min_fill_); + ret->set_buffer_low_watermark(buffer_low_watermark_); + ret->set_buffer_high_watermark(buffer_high_watermark_); ret->AddBufferConsumer(this); for (GstBufferConsumer *consumer : buffer_consumers_) { diff --git a/src/engine/gstenginepipeline.cpp b/src/engine/gstenginepipeline.cpp index 457b16683..d306ca8da 100644 --- a/src/engine/gstenginepipeline.cpp +++ b/src/engine/gstenginepipeline.cpp @@ -50,6 +50,7 @@ #include "core/signalchecker.h" #include "core/timeconstants.h" #include "core/song.h" +#include "settings/backendsettingspage.h" #include "enginebase.h" #include "gstengine.h" #include "gstenginepipeline.h" @@ -80,8 +81,9 @@ GstEnginePipeline::GstEnginePipeline(GstEngine *engine) rg_mode_(0), rg_preamp_(0.0), rg_compression_(true), - buffer_duration_nanosec_(1 * kNsecPerSec), - buffer_min_fill_(33), + buffer_duration_nanosec_(BackendSettingsPage::kDefaultBufferDuration * kNsecPerMsec), + buffer_low_watermark_(BackendSettingsPage::kDefaultBufferLowWatermark), + buffer_high_watermark_(BackendSettingsPage::kDefaultBufferHighWatermark), buffering_(false), segment_start_(0), segment_start_received_(false), @@ -203,8 +205,12 @@ void GstEnginePipeline::set_buffer_duration_nanosec(const qint64 buffer_duration buffer_duration_nanosec_ = buffer_duration_nanosec; } -void GstEnginePipeline::set_buffer_min_fill(int percent) { - buffer_min_fill_ = percent; +void GstEnginePipeline::set_buffer_low_watermark(const double value) { + buffer_low_watermark_ = value; +} + +void GstEnginePipeline::set_buffer_high_watermark(const double value) { + buffer_high_watermark_ = value; } bool GstEnginePipeline::InitFromUrl(const QByteArray &stream_url, const QUrl original_url, const qint64 end_nanosec) { @@ -382,10 +388,12 @@ bool GstEnginePipeline::InitAudioBin() { g_object_set(G_OBJECT(audioqueue_), "max-size-buffers", 0, nullptr); g_object_set(G_OBJECT(audioqueue_), "max-size-bytes", 0, nullptr); - g_object_set(G_OBJECT(audioqueue_), "max-size-time", buffer_duration_nanosec_, nullptr); - g_object_set(G_OBJECT(audioqueue_), "low-percent", buffer_min_fill_, nullptr); if (buffer_duration_nanosec_ > 0) { + qLog(Info) << "Setting buffer duration:" << buffer_duration_nanosec_ << "low watermark:" << buffer_low_watermark_ << "high watermark:" << buffer_high_watermark_; g_object_set(G_OBJECT(audioqueue_), "use-buffering", true, nullptr); + g_object_set(G_OBJECT(audioqueue_), "max-size-time", buffer_duration_nanosec_, nullptr); + g_object_set(G_OBJECT(audioqueue_), "low-watermark", buffer_low_watermark_, nullptr); + g_object_set(G_OBJECT(audioqueue_), "high-watermark", buffer_high_watermark_, nullptr); } // Link all elements @@ -748,7 +756,7 @@ gboolean GstEnginePipeline::BusCallback(GstBus*, GstMessage *msg, gpointer self) } -GstBusSyncReply GstEnginePipeline::BusCallbackSync(GstBus *, GstMessage *msg, gpointer self) { +GstBusSyncReply GstEnginePipeline::BusCallbackSync(GstBus*, GstMessage *msg, gpointer self) { GstEnginePipeline *instance = reinterpret_cast(self); diff --git a/src/engine/gstenginepipeline.h b/src/engine/gstenginepipeline.h index 8c8a4004a..d6aedeaa5 100644 --- a/src/engine/gstenginepipeline.h +++ b/src/engine/gstenginepipeline.h @@ -71,8 +71,9 @@ class GstEnginePipeline : public QObject { void set_stereo_balancer_enabled(const bool enabled); void set_equalizer_enabled(const bool enabled); void set_replaygain(const bool enabled, const int mode, const float preamp, const bool compression); - void set_buffer_duration_nanosec(qint64 duration_nanosec); - void set_buffer_min_fill(int percent); + void set_buffer_duration_nanosec(const qint64 duration_nanosec); + void set_buffer_low_watermark(const double value); + void set_buffer_high_watermark(const double value); // Creates the pipeline, returns false on error bool InitFromUrl(const QByteArray &stream_url, const QUrl original_url, const qint64 end_nanosec); @@ -211,7 +212,8 @@ class GstEnginePipeline : public QObject { // Buffering quint64 buffer_duration_nanosec_; - int buffer_min_fill_; + double buffer_low_watermark_; + double buffer_high_watermark_; bool buffering_; // These get called when there is a new audio buffer available diff --git a/src/settings/backendsettingspage.cpp b/src/settings/backendsettingspage.cpp index f3b3ed6f2..d9557de47 100644 --- a/src/settings/backendsettingspage.cpp +++ b/src/settings/backendsettingspage.cpp @@ -57,6 +57,9 @@ #include "ui_backendsettingspage.h" const char *BackendSettingsPage::kSettingsGroup = "Backend"; +const qint64 BackendSettingsPage::kDefaultBufferDuration = 4000; +const double BackendSettingsPage::kDefaultBufferLowWatermark = 0.33; +const double BackendSettingsPage::kDefaultBufferHighWatermark = 0.99; BackendSettingsPage::BackendSettingsPage(SettingsDialog *dialog) : SettingsPage(dialog), ui_(new Ui_BackendSettingsPage) { @@ -64,10 +67,8 @@ BackendSettingsPage::BackendSettingsPage(SettingsDialog *dialog) : SettingsPage( setWindowIcon(IconLoader::Load("soundcard")); #if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) - ui_->label_bufferminfillvalue->setMinimumWidth(QFontMetrics(ui_->label_bufferminfillvalue->font()).horizontalAdvance("WW%")); ui_->label_replaygainpreamp->setMinimumWidth(QFontMetrics(ui_->label_replaygainpreamp->font()).horizontalAdvance("-WW.W dB")); #else - ui_->label_bufferminfillvalue->setMinimumWidth(QFontMetrics(ui_->label_bufferminfillvalue->font()).width("WW%")); ui_->label_replaygainpreamp->setMinimumWidth(QFontMetrics(ui_->label_replaygainpreamp->font()).width("-WW.W dB")); #endif @@ -109,8 +110,10 @@ void BackendSettingsPage::Load() { ui_->checkbox_volume_control->setChecked(s.value("volume_control", true).toBool()); - ui_->spinbox_bufferduration->setValue(s.value("bufferduration", 4000).toInt()); - ui_->slider_bufferminfill->setValue(s.value("bufferminfill", 33).toInt()); + ui_->spinbox_bufferduration->setValue(s.value("bufferduration", kDefaultBufferDuration).toInt()); + + ui_->spinbox_low_watermark->setValue(s.value("bufferlowwatermark", kDefaultBufferLowWatermark).toDouble()); + ui_->spinbox_high_watermark->setValue(s.value("bufferhighwatermark", kDefaultBufferHighWatermark).toDouble()); ui_->checkbox_replaygain->setChecked(s.value("rgenabled", false).toBool()); ui_->combobox_replaygainmode->setCurrentIndex(s.value("rgmode", 0).toInt()); @@ -171,12 +174,13 @@ void BackendSettingsPage::Load() { connect(ui_->radiobutton_alsa_hw, SIGNAL(clicked(bool)), SLOT(radiobutton_alsa_hw_clicked(bool))); connect(ui_->radiobutton_alsa_plughw, SIGNAL(clicked(bool)), SLOT(radiobutton_alsa_plughw_clicked(bool))); #endif - connect(ui_->slider_bufferminfill, SIGNAL(valueChanged(int)), SLOT(BufferMinFillChanged(int))); + //connect(ui_->slider_bufferminfill, SIGNAL(valueChanged(int)), SLOT(BufferMinFillChanged(int))); connect(ui_->stickslider_replaygainpreamp, SIGNAL(valueChanged(int)), SLOT(RgPreampChanged(int))); connect(ui_->checkbox_fadeout_stop, SIGNAL(toggled(bool)), SLOT(FadingOptionsChanged())); connect(ui_->checkbox_fadeout_cross, SIGNAL(toggled(bool)), SLOT(FadingOptionsChanged())); connect(ui_->checkbox_fadeout_auto, SIGNAL(toggled(bool)), SLOT(FadingOptionsChanged())); connect(ui_->checkbox_volume_control, SIGNAL(toggled(bool)), SLOT(FadingOptionsChanged())); + connect(ui_->button_buffer_defaults, SIGNAL(clicked()), SLOT(BufferDefaults())); FadingOptionsChanged(); RgPreampChanged(ui_->stickslider_replaygainpreamp->value()); @@ -215,7 +219,7 @@ bool BackendSettingsPage::EngineInitialised() { } -void BackendSettingsPage::Load_Engine(Engine::EngineType enginetype) { +void BackendSettingsPage::Load_Engine(const Engine::EngineType enginetype) { if (!EngineInitialised()) return; @@ -297,7 +301,7 @@ void BackendSettingsPage::Load_Output(QString output, QVariant device) { } -void BackendSettingsPage::Load_Device(QString output, QVariant device) { +void BackendSettingsPage::Load_Device(const QString &output, const QVariant &device) { if (!EngineInitialised()) return; @@ -408,7 +412,8 @@ void BackendSettingsPage::Save() { s.setValue("device", device_value); s.setValue("bufferduration", ui_->spinbox_bufferduration->value()); - s.setValue("bufferminfill", ui_->slider_bufferminfill->value()); + s.setValue("bufferlowwatermark", ui_->spinbox_low_watermark->value()); + s.setValue("bufferhighwatermark", ui_->spinbox_high_watermark->value()); s.setValue("rgenabled", ui_->checkbox_replaygain->isChecked()); s.setValue("rgmode", ui_->combobox_replaygainmode->currentIndex()); @@ -442,7 +447,7 @@ void BackendSettingsPage::Cancel() { } } -void BackendSettingsPage::EngineChanged(int index) { +void BackendSettingsPage::EngineChanged(const int index) { if (!configloaded_ || !EngineInitialised()) return; @@ -462,7 +467,7 @@ void BackendSettingsPage::EngineChanged(int index) { } -void BackendSettingsPage::OutputChanged(int index) { +void BackendSettingsPage::OutputChanged(const int index) { if (!configloaded_ || !EngineInitialised()) return; @@ -549,7 +554,7 @@ void BackendSettingsPage::DeviceStringChanged() { } -void BackendSettingsPage::RgPreampChanged(int value) { +void BackendSettingsPage::RgPreampChanged(const int value) { float db = float(value) / 10 - 15; QString db_str = QString::asprintf("%+.1f dB", db); @@ -557,12 +562,8 @@ void BackendSettingsPage::RgPreampChanged(int value) { } -void BackendSettingsPage::BufferMinFillChanged(int value) { - ui_->label_bufferminfillvalue->setText(QString::number(value) + "%"); -} - #ifdef HAVE_ALSA -void BackendSettingsPage::SwitchALSADevices(alsa_plugin alsaplugin) { +void BackendSettingsPage::SwitchALSADevices(const alsa_plugin alsaplugin) { // All ALSA devices are listed twice, one for "hw" and one for "plughw" // Only show one of them by making the other ones invisible based on the alsa plugin radiobuttons @@ -583,7 +584,7 @@ void BackendSettingsPage::SwitchALSADevices(alsa_plugin alsaplugin) { } #endif -void BackendSettingsPage::radiobutton_alsa_hw_clicked(bool checked) { +void BackendSettingsPage::radiobutton_alsa_hw_clicked(const bool checked) { Q_UNUSED(checked); @@ -614,7 +615,7 @@ void BackendSettingsPage::radiobutton_alsa_hw_clicked(bool checked) { } -void BackendSettingsPage::radiobutton_alsa_plughw_clicked(bool checked) { +void BackendSettingsPage::radiobutton_alsa_plughw_clicked(const bool checked) { Q_UNUSED(checked); @@ -663,3 +664,12 @@ void BackendSettingsPage::FadingOptionsChanged() { ui_->widget_fading_options->setEnabled(ui_->checkbox_fadeout_stop->isChecked() || ui_->checkbox_fadeout_cross->isChecked() || ui_->checkbox_fadeout_auto->isChecked()); } + + +void BackendSettingsPage::BufferDefaults() { + + ui_->spinbox_bufferduration->setValue(kDefaultBufferDuration); + ui_->spinbox_low_watermark->setValue(kDefaultBufferLowWatermark); + ui_->spinbox_high_watermark->setValue(kDefaultBufferHighWatermark); + +} diff --git a/src/settings/backendsettingspage.h b/src/settings/backendsettingspage.h index b8d89a4a8..b73a97c42 100644 --- a/src/settings/backendsettingspage.h +++ b/src/settings/backendsettingspage.h @@ -45,6 +45,9 @@ public: ~BackendSettingsPage() override; static const char *kSettingsGroup; + static const qint64 kDefaultBufferDuration; + static const double kDefaultBufferLowWatermark; + static const double kDefaultBufferHighWatermark; void Load() override; void Save() override; @@ -53,15 +56,15 @@ public: EngineBase *engine() const { return dialog()->app()->player()->engine(); } private slots: - void EngineChanged(int index); - void OutputChanged(int index); - void DeviceSelectionChanged(int index); + void EngineChanged(const int index); + void OutputChanged(const int index); + void DeviceSelectionChanged(const int index); void DeviceStringChanged(); - void RgPreampChanged(int value); - void BufferMinFillChanged(int value); - void radiobutton_alsa_hw_clicked(bool checked); - void radiobutton_alsa_plughw_clicked(bool checked); + void RgPreampChanged(const int value); + void radiobutton_alsa_hw_clicked(const bool checked); + void radiobutton_alsa_plughw_clicked(const bool checked); void FadingOptionsChanged(); + void BufferDefaults(); private: #ifdef HAVE_ALSA @@ -79,9 +82,9 @@ private: void Load_Engine(Engine::EngineType enginetype); void Load_Output(QString output, QVariant device); - void Load_Device(QString output, QVariant device); + void Load_Device(const QString &output, const QVariant &device); #ifdef HAVE_ALSA - void SwitchALSADevices(alsa_plugin alsaplugin); + void SwitchALSADevices(const alsa_plugin alsaplugin); #endif bool configloaded_; diff --git a/src/settings/backendsettingspage.ui b/src/settings/backendsettingspage.ui index b1e407276..ef4ff38d8 100644 --- a/src/settings/backendsettingspage.ui +++ b/src/settings/backendsettingspage.ui @@ -235,64 +235,134 @@ Buffer - - - QFormLayout::AllNonFixedFieldsGrow - - - - - Buffer duration - - - - - - - ms - - - 60000 - - - 100 - - - - - - - Minimum buffer fill - - - - - - - + + + + + + + ms + + + 60000 + + + 100 + + + 4000 + + + + + + + 1.000000000000000 + + + 0.010000000000000 + + + 0.990000000000000 + + + + + - + Buffer duration + + + + + + + High watermark + + + + + + + Low watermark + + + + + + + 1.000000000000000 + + + 0.010000000000000 + + + 0.330000000000000 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Defaults - - - 1 - - - 50 - - - 33 - + Qt::Horizontal - - 1 + + + 40 + 20 + - + @@ -365,7 +435,7 @@ - + @@ -587,8 +657,6 @@ radiobutton_alsa_hw radiobutton_alsa_plughw checkbox_volume_control - spinbox_bufferduration - slider_bufferminfill checkbox_replaygain combobox_replaygainmode stickslider_replaygainpreamp