Add support for bs2b
Improve headphone listening of stereo audio records
This commit is contained in:
@@ -67,6 +67,7 @@ Engine::Base::Base(const EngineType type, QObject *parent)
|
|||||||
proxy_authentication_(false),
|
proxy_authentication_(false),
|
||||||
channels_enabled_(false),
|
channels_enabled_(false),
|
||||||
channels_(0),
|
channels_(0),
|
||||||
|
bs2b_enabled_(false),
|
||||||
about_to_end_emitted_(false) {}
|
about_to_end_emitted_(false) {}
|
||||||
|
|
||||||
Engine::Base::~Base() = default;
|
Engine::Base::~Base() = default;
|
||||||
@@ -142,6 +143,8 @@ void Engine::Base::ReloadSettings() {
|
|||||||
fadeout_pause_duration_ = s.value("FadeoutPauseDuration", 250).toLongLong();
|
fadeout_pause_duration_ = s.value("FadeoutPauseDuration", 250).toLongLong();
|
||||||
fadeout_pause_duration_nanosec_ = (fadeout_pause_duration_ * kNsecPerMsec);
|
fadeout_pause_duration_nanosec_ = (fadeout_pause_duration_ * kNsecPerMsec);
|
||||||
|
|
||||||
|
bs2b_enabled_ = s.value("bs2b", false).toBool();
|
||||||
|
|
||||||
s.endGroup();
|
s.endGroup();
|
||||||
|
|
||||||
s.beginGroup(NetworkProxySettingsPage::kSettingsGroup);
|
s.beginGroup(NetworkProxySettingsPage::kSettingsGroup);
|
||||||
|
|||||||
@@ -210,6 +210,9 @@ class Base : public QObject {
|
|||||||
bool channels_enabled_;
|
bool channels_enabled_;
|
||||||
int channels_;
|
int channels_;
|
||||||
|
|
||||||
|
// Options
|
||||||
|
bool bs2b_enabled_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool about_to_end_emitted_;
|
bool about_to_end_emitted_;
|
||||||
Q_DISABLE_COPY(Base)
|
Q_DISABLE_COPY(Base)
|
||||||
|
|||||||
@@ -801,6 +801,7 @@ std::shared_ptr<GstEnginePipeline> GstEngine::CreatePipeline() {
|
|||||||
ret->set_buffer_high_watermark(buffer_high_watermark_);
|
ret->set_buffer_high_watermark(buffer_high_watermark_);
|
||||||
ret->set_proxy_settings(proxy_address_, proxy_authentication_, proxy_user_, proxy_pass_);
|
ret->set_proxy_settings(proxy_address_, proxy_authentication_, proxy_user_, proxy_pass_);
|
||||||
ret->set_channels(channels_enabled_, channels_);
|
ret->set_channels(channels_enabled_, channels_);
|
||||||
|
ret->set_bs2b_enabled(bs2b_enabled_);
|
||||||
|
|
||||||
ret->AddBufferConsumer(this);
|
ret->AddBufferConsumer(this);
|
||||||
for (GstBufferConsumer *consumer : buffer_consumers_) {
|
for (GstBufferConsumer *consumer : buffer_consumers_) {
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ GstEnginePipeline::GstEnginePipeline(QObject *parent)
|
|||||||
proxy_authentication_(false),
|
proxy_authentication_(false),
|
||||||
channels_enabled_(false),
|
channels_enabled_(false),
|
||||||
channels_(0),
|
channels_(0),
|
||||||
|
bs2b_enabled_(false),
|
||||||
segment_start_(0),
|
segment_start_(0),
|
||||||
segment_start_received_(false),
|
segment_start_received_(false),
|
||||||
end_offset_nanosec_(-1),
|
end_offset_nanosec_(-1),
|
||||||
@@ -216,6 +217,10 @@ void GstEnginePipeline::set_channels(const bool enabled, const int channels) {
|
|||||||
channels_ = channels;
|
channels_ = channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GstEnginePipeline::set_bs2b_enabled(const bool enabled) {
|
||||||
|
bs2b_enabled_ = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
GstElement *GstEnginePipeline::CreateElement(const QString &factory_name, const QString &name, GstElement *bin, QString &error) const {
|
GstElement *GstEnginePipeline::CreateElement(const QString &factory_name, const QString &name, GstElement *bin, QString &error) const {
|
||||||
|
|
||||||
QString unique_name = QString("pipeline") + "-" + QString::number(id_) + "-" + (name.isEmpty() ? factory_name : name);
|
QString unique_name = QString("pipeline") + "-" + QString::number(id_) + "-" + (name.isEmpty() ? factory_name : name);
|
||||||
@@ -515,6 +520,16 @@ bool GstEnginePipeline::InitAudioBin(QString &error) {
|
|||||||
g_object_set(G_OBJECT(rglimiter), "enabled", static_cast<int>(rg_compression_), nullptr);
|
g_object_set(G_OBJECT(rglimiter), "enabled", static_cast<int>(rg_compression_), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GstElement *bs2b = nullptr;
|
||||||
|
if (bs2b_enabled_) {
|
||||||
|
bs2b = CreateElement("bs2b", "bs2b", audiobin_, error);
|
||||||
|
if (!bs2b) {
|
||||||
|
gst_object_unref(GST_OBJECT(audiobin_));
|
||||||
|
audiobin_ = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{ // Create a pad on the outside of the audiobin and connect it to the pad of the first element.
|
{ // Create a pad on the outside of the audiobin and connect it to the pad of the first element.
|
||||||
GstPad *pad = gst_element_get_static_pad(audioqueue_, "sink");
|
GstPad *pad = gst_element_get_static_pad(audioqueue_, "sink");
|
||||||
if (pad) {
|
if (pad) {
|
||||||
@@ -595,6 +610,18 @@ bool GstEnginePipeline::InitAudioBin(QString &error) {
|
|||||||
next = volume_;
|
next = volume_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Link bs2b element if enabled.
|
||||||
|
if (bs2b_enabled_ && bs2b) {
|
||||||
|
qLog(Debug) << "Enabling bs2b";
|
||||||
|
if (!gst_element_link(next, bs2b)) {
|
||||||
|
gst_object_unref(GST_OBJECT(audiobin_));
|
||||||
|
audiobin_ = nullptr;
|
||||||
|
error = "gst_element_link() failed.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
next = bs2b;
|
||||||
|
}
|
||||||
|
|
||||||
if (!gst_element_link(next, audioconverter)) {
|
if (!gst_element_link(next, audioconverter)) {
|
||||||
gst_object_unref(GST_OBJECT(audiobin_));
|
gst_object_unref(GST_OBJECT(audiobin_));
|
||||||
audiobin_ = nullptr;
|
audiobin_ = nullptr;
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ class GstEnginePipeline : public QObject {
|
|||||||
void set_buffer_high_watermark(const double value);
|
void set_buffer_high_watermark(const double value);
|
||||||
void set_proxy_settings(const QString &address, const bool authentication, const QString &user, const QString &pass);
|
void set_proxy_settings(const QString &address, const bool authentication, const QString &user, const QString &pass);
|
||||||
void set_channels(const bool enabled, const int channels);
|
void set_channels(const bool enabled, const int channels);
|
||||||
|
void set_bs2b_enabled(const bool enabled);
|
||||||
|
|
||||||
// Creates the pipeline, returns false on error
|
// Creates the pipeline, returns false on error
|
||||||
bool InitFromUrl(const QByteArray &stream_url, const QUrl &original_url, const qint64 end_nanosec, QString &error);
|
bool InitFromUrl(const QByteArray &stream_url, const QUrl &original_url, const qint64 end_nanosec, QString &error);
|
||||||
@@ -221,6 +222,9 @@ class GstEnginePipeline : public QObject {
|
|||||||
bool channels_enabled_;
|
bool channels_enabled_;
|
||||||
int channels_;
|
int channels_;
|
||||||
|
|
||||||
|
// Options
|
||||||
|
bool bs2b_enabled_;
|
||||||
|
|
||||||
// These get called when there is a new audio buffer available
|
// These get called when there is a new audio buffer available
|
||||||
QList<GstBufferConsumer*> buffer_consumers_;
|
QList<GstBufferConsumer*> buffer_consumers_;
|
||||||
QMutex buffer_consumers_mutex_;
|
QMutex buffer_consumers_mutex_;
|
||||||
|
|||||||
@@ -164,6 +164,8 @@ void BackendSettingsPage::Load() {
|
|||||||
ui_->spinbox_channels->setValue(s.value("channels", 2).toInt());
|
ui_->spinbox_channels->setValue(s.value("channels", 2).toInt());
|
||||||
ui_->widget_channels->setEnabled(ui_->checkbox_channels->isChecked());
|
ui_->widget_channels->setEnabled(ui_->checkbox_channels->isChecked());
|
||||||
|
|
||||||
|
ui_->checkbox_bs2b->setChecked(s.value("bs2b", false).toBool());
|
||||||
|
|
||||||
ui_->spinbox_bufferduration->setValue(s.value("bufferduration", kDefaultBufferDuration).toInt());
|
ui_->spinbox_bufferduration->setValue(s.value("bufferduration", kDefaultBufferDuration).toInt());
|
||||||
ui_->spinbox_low_watermark->setValue(s.value("bufferlowwatermark", kDefaultBufferLowWatermark).toDouble());
|
ui_->spinbox_low_watermark->setValue(s.value("bufferlowwatermark", kDefaultBufferLowWatermark).toDouble());
|
||||||
ui_->spinbox_high_watermark->setValue(s.value("bufferhighwatermark", kDefaultBufferHighWatermark).toDouble());
|
ui_->spinbox_high_watermark->setValue(s.value("bufferhighwatermark", kDefaultBufferHighWatermark).toDouble());
|
||||||
@@ -460,6 +462,20 @@ void BackendSettingsPage::Save() {
|
|||||||
s.setValue("output", output_name);
|
s.setValue("output", output_name);
|
||||||
s.setValue("device", device_value);
|
s.setValue("device", device_value);
|
||||||
|
|
||||||
|
#ifdef HAVE_ALSA
|
||||||
|
if (ui_->radiobutton_alsa_hw->isChecked()) s.setValue("alsaplugin", static_cast<int>(alsa_plugin::alsa_hw));
|
||||||
|
else if (ui_->radiobutton_alsa_plughw->isChecked()) s.setValue("alsaplugin", static_cast<int>(alsa_plugin::alsa_plughw));
|
||||||
|
else if (ui_->radiobutton_alsa_pcm->isChecked()) s.setValue("alsaplugin", static_cast<int>(alsa_plugin::alsa_pcm));
|
||||||
|
else s.remove("alsaplugin");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
s.setValue("volume_control", ui_->checkbox_volume_control->isChecked());
|
||||||
|
|
||||||
|
s.setValue("channels_enabled", ui_->checkbox_channels->isChecked());
|
||||||
|
s.setValue("channels", ui_->spinbox_channels->value());
|
||||||
|
|
||||||
|
s.setValue("bs2b", ui_->checkbox_bs2b->isChecked());
|
||||||
|
|
||||||
s.setValue("bufferduration", ui_->spinbox_bufferduration->value());
|
s.setValue("bufferduration", ui_->spinbox_bufferduration->value());
|
||||||
s.setValue("bufferlowwatermark", ui_->spinbox_low_watermark->value());
|
s.setValue("bufferlowwatermark", ui_->spinbox_low_watermark->value());
|
||||||
s.setValue("bufferhighwatermark", ui_->spinbox_high_watermark->value());
|
s.setValue("bufferhighwatermark", ui_->spinbox_high_watermark->value());
|
||||||
@@ -478,18 +494,6 @@ void BackendSettingsPage::Save() {
|
|||||||
s.setValue("FadeoutDuration", ui_->spinbox_fadeduration->value());
|
s.setValue("FadeoutDuration", ui_->spinbox_fadeduration->value());
|
||||||
s.setValue("FadeoutPauseDuration", ui_->spinbox_fadeduration_pauseresume->value());
|
s.setValue("FadeoutPauseDuration", ui_->spinbox_fadeduration_pauseresume->value());
|
||||||
|
|
||||||
#ifdef HAVE_ALSA
|
|
||||||
if (ui_->radiobutton_alsa_hw->isChecked()) s.setValue("alsaplugin", static_cast<int>(alsa_plugin::alsa_hw));
|
|
||||||
else if (ui_->radiobutton_alsa_plughw->isChecked()) s.setValue("alsaplugin", static_cast<int>(alsa_plugin::alsa_plughw));
|
|
||||||
else if (ui_->radiobutton_alsa_pcm->isChecked()) s.setValue("alsaplugin", static_cast<int>(alsa_plugin::alsa_pcm));
|
|
||||||
else s.remove("alsaplugin");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
s.setValue("volume_control", ui_->checkbox_volume_control->isChecked());
|
|
||||||
|
|
||||||
s.setValue("channels_enabled", ui_->checkbox_channels->isChecked());
|
|
||||||
s.setValue("channels", ui_->spinbox_channels->value());
|
|
||||||
|
|
||||||
s.endGroup();
|
s.endGroup();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>583</width>
|
<width>583</width>
|
||||||
<height>880</height>
|
<height>1080</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@@ -153,6 +153,15 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Options</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="checkbox_volume_control">
|
<widget class="QCheckBox" name="checkbox_volume_control">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -236,6 +245,13 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="checkbox_bs2b">
|
||||||
|
<property name="text">
|
||||||
|
<string>Improve headphone listening of stereo audio records (bs2b)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -699,7 +715,6 @@
|
|||||||
<tabstop>radiobutton_alsa_hw</tabstop>
|
<tabstop>radiobutton_alsa_hw</tabstop>
|
||||||
<tabstop>radiobutton_alsa_plughw</tabstop>
|
<tabstop>radiobutton_alsa_plughw</tabstop>
|
||||||
<tabstop>radiobutton_alsa_pcm</tabstop>
|
<tabstop>radiobutton_alsa_pcm</tabstop>
|
||||||
<tabstop>checkbox_volume_control</tabstop>
|
|
||||||
<tabstop>checkbox_channels</tabstop>
|
<tabstop>checkbox_channels</tabstop>
|
||||||
<tabstop>spinbox_channels</tabstop>
|
<tabstop>spinbox_channels</tabstop>
|
||||||
<tabstop>spinbox_bufferduration</tabstop>
|
<tabstop>spinbox_bufferduration</tabstop>
|
||||||
|
|||||||
Reference in New Issue
Block a user