Replace use of deprecated gstreamer low-percent

- Add settings for low-watermark and high-watermark
- Add button to reset buffer settings to defaults
This commit is contained in:
Jonas Kvinge 2020-10-07 20:29:26 +02:00
parent cd695a4522
commit 74a5233b5d
8 changed files with 190 additions and 95 deletions

View File

@ -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();

View File

@ -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_;

View File

@ -758,7 +758,8 @@ std::shared_ptr<GstEnginePipeline> 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_) {

View File

@ -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<GstEnginePipeline*>(self);

View File

@ -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

View File

@ -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);
}

View File

@ -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_;

View File

@ -235,64 +235,134 @@
<property name="title">
<string>Buffer</string>
</property>
<layout class="QFormLayout" name="layout_buffer">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="1" column="0">
<widget class="QLabel" name="label_bufferduration">
<property name="text">
<string>Buffer duration</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinbox_bufferduration">
<property name="suffix">
<string> ms</string>
</property>
<property name="maximum">
<number>60000</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_bufferminfill">
<property name="text">
<string>Minimum buffer fill</string>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_buffer">
<item>
<widget class="QLabel" name="label_bufferminfillvalue">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="layout_buffer">
<item row="0" column="1">
<widget class="QSpinBox" name="spinbox_bufferduration">
<property name="suffix">
<string> ms</string>
</property>
<property name="maximum">
<number>60000</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
<property name="value">
<number>4000</number>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="spinbox_high_watermark">
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.990000000000000</double>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_bufferduration">
<property name="text">
<string/>
<string>Buffer duration</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_highwatermark">
<property name="text">
<string>High watermark</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_lowwatermark">
<property name="text">
<string>Low watermark</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="spinbox_low_watermark">
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.330000000000000</double>
</property>
</widget>
</item>
<item row="2" column="2">
<spacer name="spacer_buffer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="2">
<spacer name="spacer_buffer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="2">
<spacer name="spacer_buffer_1">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="layout_buffer_defaults">
<item>
<widget class="QPushButton" name="button_buffer_defaults">
<property name="text">
<string>Defaults</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="slider_bufferminfill">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>50</number>
</property>
<property name="value">
<number>33</number>
</property>
<spacer name="spacer_buffer_defaults">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickInterval">
<number>1</number>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</widget>
</spacer>
</item>
</layout>
</item>
@ -365,7 +435,7 @@
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<layout class="QHBoxLayout" name="layout_replayagainpreamp">
<item>
<widget class="QLabel" name="label_replaygainpreamp"/>
</item>
@ -587,8 +657,6 @@
<tabstop>radiobutton_alsa_hw</tabstop>
<tabstop>radiobutton_alsa_plughw</tabstop>
<tabstop>checkbox_volume_control</tabstop>
<tabstop>spinbox_bufferduration</tabstop>
<tabstop>slider_bufferminfill</tabstop>
<tabstop>checkbox_replaygain</tabstop>
<tabstop>combobox_replaygainmode</tabstop>
<tabstop>stickslider_replaygainpreamp</tabstop>