mirror of
https://github.com/strawberrymusicplayer/strawberry
synced 2024-12-21 13:04:42 +01:00
GstEnginePipeline: Add back volume sync for auto
We need to remove the volume sync when the element is deleted on "deep-element-removed", then re-add it on the next "deep-element-added" that isn't a fakesink. Fixes #1123
This commit is contained in:
parent
b95be526d3
commit
9bbffe150f
@ -131,6 +131,7 @@ GstEnginePipeline::GstEnginePipeline(QObject *parent)
|
|||||||
buffer_probe_cb_id_(0),
|
buffer_probe_cb_id_(0),
|
||||||
playbin_probe_cb_id_(0),
|
playbin_probe_cb_id_(0),
|
||||||
element_added_cb_id_(-1),
|
element_added_cb_id_(-1),
|
||||||
|
element_removed_cb_id_(-1),
|
||||||
pad_added_cb_id_(-1),
|
pad_added_cb_id_(-1),
|
||||||
notify_source_cb_id_(-1),
|
notify_source_cb_id_(-1),
|
||||||
about_to_finish_cb_id_(-1),
|
about_to_finish_cb_id_(-1),
|
||||||
@ -158,6 +159,10 @@ GstEnginePipeline::~GstEnginePipeline() {
|
|||||||
g_signal_handler_disconnect(G_OBJECT(audiobin_), element_added_cb_id_);
|
g_signal_handler_disconnect(G_OBJECT(audiobin_), element_added_cb_id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (element_removed_cb_id_ != -1) {
|
||||||
|
g_signal_handler_disconnect(G_OBJECT(audiobin_), element_removed_cb_id_);
|
||||||
|
}
|
||||||
|
|
||||||
if (pad_added_cb_id_ != -1) {
|
if (pad_added_cb_id_ != -1) {
|
||||||
g_signal_handler_disconnect(G_OBJECT(pipeline_), pad_added_cb_id_);
|
g_signal_handler_disconnect(G_OBJECT(pipeline_), pad_added_cb_id_);
|
||||||
}
|
}
|
||||||
@ -355,6 +360,23 @@ bool GstEnginePipeline::InitFromUrl(const QUrl &media_url, const QUrl &stream_ur
|
|||||||
|
|
||||||
if (!InitAudioBin(error)) return false;
|
if (!InitAudioBin(error)) return false;
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
if (volume_enabled_ && !volume_ && volume_sw_) {
|
||||||
|
SetupVolume(volume_sw_);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (volume_enabled_ && !volume_) {
|
||||||
|
if (output_ == GstEngine::kAutoSink) {
|
||||||
|
element_added_cb_id_ = CHECKED_GCONNECT(G_OBJECT(audiobin_), "deep-element-added", &ElementAddedCallback, this);
|
||||||
|
element_removed_cb_id_ = CHECKED_GCONNECT(G_OBJECT(audiobin_), "deep-element-removed", &ElementRemovedCallback, this);
|
||||||
|
}
|
||||||
|
else if (volume_sw_) {
|
||||||
|
qLog(Debug) << output_ << "does not have volume, using own volume.";
|
||||||
|
SetupVolume(volume_sw_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Set playbin's sink to be our custom audio-sink.
|
// Set playbin's sink to be our custom audio-sink.
|
||||||
g_object_set(GST_OBJECT(pipeline_), "audio-sink", audiobin_, nullptr);
|
g_object_set(GST_OBJECT(pipeline_), "audio-sink", audiobin_, nullptr);
|
||||||
|
|
||||||
@ -565,8 +587,6 @@ bool GstEnginePipeline::InitAudioBin(QString &error) {
|
|||||||
if (!volume_sw_) {
|
if (!volume_sw_) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
qLog(Debug) << output_ << "does not have volume, using own volume.";
|
|
||||||
SetupVolume(volume_sw_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fading_enabled_) {
|
if (fading_enabled_) {
|
||||||
@ -845,10 +865,27 @@ bool GstEnginePipeline::InitAudioBin(QString &error) {
|
|||||||
|
|
||||||
void GstEnginePipeline::SetupVolume(GstElement *element) {
|
void GstEnginePipeline::SetupVolume(GstElement *element) {
|
||||||
|
|
||||||
if (volume_) return;
|
if (volume_) {
|
||||||
|
qLog(Debug) << "Disonnecting volume notify on" << volume_;
|
||||||
|
g_signal_handler_disconnect(G_OBJECT(volume_), notify_volume_cb_id_);
|
||||||
|
notify_volume_cb_id_ = -1;
|
||||||
|
volume_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
volume_ = element;
|
qLog(Debug) << "Connecting volume notify on" << element;
|
||||||
notify_volume_cb_id_ = CHECKED_GCONNECT(G_OBJECT(element), "notify::volume", &NotifyVolumeCallback, this);
|
notify_volume_cb_id_ = CHECKED_GCONNECT(G_OBJECT(element), "notify::volume", &NotifyVolumeCallback, this);
|
||||||
|
volume_ = element;
|
||||||
|
volume_set_ = false;
|
||||||
|
|
||||||
|
// Make sure the unused volume element is set to 1.0.
|
||||||
|
if (volume_sw_ && volume_sw_ != volume_) {
|
||||||
|
double volume_internal = 1.0;
|
||||||
|
g_object_get(G_OBJECT(volume_sw_), "volume", &volume_internal, nullptr);
|
||||||
|
if (volume_internal != 1.0) {
|
||||||
|
volume_internal = 1.0;
|
||||||
|
g_object_set(G_OBJECT(volume_sw_), "volume", volume_internal, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -885,18 +922,19 @@ void GstEnginePipeline::ElementAddedCallback(GstBin *bin, GstBin*, GstElement *e
|
|||||||
|
|
||||||
GstEnginePipeline *instance = reinterpret_cast<GstEnginePipeline*>(self);
|
GstEnginePipeline *instance = reinterpret_cast<GstEnginePipeline*>(self);
|
||||||
|
|
||||||
if (bin != GST_BIN(instance->audiobin_) || GST_ELEMENT(gst_element_get_parent(element)) != instance->audiosink_ || instance->volume_) return;
|
gchar *element_name_char = gst_element_get_name(element);
|
||||||
|
const QString element_name(element_name_char);
|
||||||
|
g_free(element_name_char);
|
||||||
|
|
||||||
g_signal_handler_disconnect(G_OBJECT(instance->audiobin_), instance->element_added_cb_id_);
|
if (bin != GST_BIN(instance->audiobin_) || element_name == QStringLiteral("fake-audio-sink") || GST_ELEMENT(gst_element_get_parent(element)) != instance->audiosink_) return;
|
||||||
instance->element_added_cb_id_ = -1;
|
|
||||||
|
|
||||||
GstElement *volume = nullptr;
|
GstElement *volume = nullptr;
|
||||||
if (GST_IS_STREAM_VOLUME(element)) {
|
if (GST_IS_STREAM_VOLUME(element)) {
|
||||||
qLog(Debug) << instance->output_ << "has volume, enabling volume synchronization.";
|
qLog(Debug) << element_name << "has volume, enabling volume synchronization.";
|
||||||
volume = element;
|
volume = element;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
qLog(Debug) << instance->output_ << "does not have volume, using own volume.";
|
qLog(Debug) << element_name << "does not have volume, using own volume.";
|
||||||
volume = instance->volume_sw_;
|
volume = instance->volume_sw_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -905,6 +943,21 @@ void GstEnginePipeline::ElementAddedCallback(GstBin *bin, GstBin*, GstElement *e
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GstEnginePipeline::ElementRemovedCallback(GstBin *bin, GstBin*, GstElement *element, gpointer self) {
|
||||||
|
|
||||||
|
GstEnginePipeline *instance = reinterpret_cast<GstEnginePipeline*>(self);
|
||||||
|
|
||||||
|
if (bin != GST_BIN(instance->audiobin_)) return;
|
||||||
|
|
||||||
|
if (instance->notify_volume_cb_id_ != -1 && element == instance->volume_) {
|
||||||
|
qLog(Debug) << "Disconnecting volume notify on" << instance->volume_;
|
||||||
|
g_signal_handler_disconnect(G_OBJECT(instance->volume_), instance->notify_volume_cb_id_);
|
||||||
|
instance->notify_volume_cb_id_ = -1;
|
||||||
|
instance->volume_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void GstEnginePipeline::SourceSetupCallback(GstElement *playbin, GstElement *source, gpointer self) {
|
void GstEnginePipeline::SourceSetupCallback(GstElement *playbin, GstElement *source, gpointer self) {
|
||||||
|
|
||||||
Q_UNUSED(playbin)
|
Q_UNUSED(playbin)
|
||||||
|
@ -162,6 +162,7 @@ class GstEnginePipeline : public QObject {
|
|||||||
static GstPadProbeReturn BufferProbeCallback(GstPad *pad, GstPadProbeInfo *info, gpointer self);
|
static GstPadProbeReturn BufferProbeCallback(GstPad *pad, GstPadProbeInfo *info, gpointer self);
|
||||||
static GstPadProbeReturn PlaybinProbeCallback(GstPad *pad, GstPadProbeInfo *info, gpointer self);
|
static GstPadProbeReturn PlaybinProbeCallback(GstPad *pad, GstPadProbeInfo *info, gpointer self);
|
||||||
static void ElementAddedCallback(GstBin *bin, GstBin*, GstElement *element, gpointer self);
|
static void ElementAddedCallback(GstBin *bin, GstBin*, GstElement *element, gpointer self);
|
||||||
|
static void ElementRemovedCallback(GstBin *bin, GstBin*, GstElement *element, gpointer self);
|
||||||
static void PadAddedCallback(GstElement *element, GstPad *pad, gpointer self);
|
static void PadAddedCallback(GstElement *element, GstPad *pad, gpointer self);
|
||||||
static void SourceSetupCallback(GstElement *playbin, GstElement *source, gpointer self);
|
static void SourceSetupCallback(GstElement *playbin, GstElement *source, gpointer self);
|
||||||
static void NotifyVolumeCallback(GstElement *element, GParamSpec *param_spec, gpointer self);
|
static void NotifyVolumeCallback(GstElement *element, GParamSpec *param_spec, gpointer self);
|
||||||
@ -323,6 +324,7 @@ class GstEnginePipeline : public QObject {
|
|||||||
gulong buffer_probe_cb_id_;
|
gulong buffer_probe_cb_id_;
|
||||||
gulong playbin_probe_cb_id_;
|
gulong playbin_probe_cb_id_;
|
||||||
glong element_added_cb_id_;
|
glong element_added_cb_id_;
|
||||||
|
glong element_removed_cb_id_;
|
||||||
glong pad_added_cb_id_;
|
glong pad_added_cb_id_;
|
||||||
glong notify_source_cb_id_;
|
glong notify_source_cb_id_;
|
||||||
glong about_to_finish_cb_id_;
|
glong about_to_finish_cb_id_;
|
||||||
|
Loading…
Reference in New Issue
Block a user