diff --git a/src/engines/gstengine.cpp b/src/engines/gstengine.cpp index 656a29200..59f3e045e 100644 --- a/src/engines/gstengine.cpp +++ b/src/engines/gstengine.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -100,6 +101,8 @@ void GstEngine::ReloadSettings() { sink_ = s.value("sink", kAutoSink).toString(); device_ = s.value("device").toString(); + fadeout_enabled_ = s.value("FadeoutEnabled", true).toBool(); + fadeout_duration_ = s.value("FadeoutDuration", 2000).toInt(); } @@ -307,6 +310,9 @@ bool GstEngine::play( uint offset ) { return false; } + // Stop any active fadeout + fadeout_pipeline_.reset(); + // If "Resume playback on start" is enabled, we must seek to the last position if (offset) seek(offset); @@ -320,10 +326,27 @@ bool GstEngine::play( uint offset ) { void GstEngine::stop() { m_url = QUrl(); // To ensure we return Empty from state() + if (fadeout_enabled_) { + fadeout_pipeline_ = current_pipeline_; + disconnect(fadeout_pipeline_.get(), 0, 0, 0); + ClearScopeQ(); + + QTimeLine* fadeout = new QTimeLine(fadeout_duration_, this); + connect(fadeout, SIGNAL(valueChanged(qreal)), fadeout_pipeline_.get(), SLOT(SetVolumeModifier(qreal))); + connect(fadeout, SIGNAL(finished()), SLOT(FadeoutFinished())); + connect(fadeout_pipeline_.get(), SIGNAL(destroyed()), fadeout, SLOT(deleteLater())); + fadeout->setDirection(QTimeLine::Backward); + fadeout->start(); + } + current_pipeline_.reset(); emit stateChanged(Engine::Empty); } +void GstEngine::FadeoutFinished() { + fadeout_pipeline_.reset(); +} + void GstEngine::pause() { if (!current_pipeline_) return; diff --git a/src/engines/gstengine.h b/src/engines/gstengine.h index 0e0312ffa..da50dcc3c 100644 --- a/src/engines/gstengine.h +++ b/src/engines/gstengine.h @@ -103,6 +103,7 @@ class GstEngine : public Engine::Base { void NewMetaData(const Engine::SimpleMetaBundle& bundle); void NewBuffer(GstBuffer* buf); void ClearScopeQ(); + void FadeoutFinished(); private: // Callbacks @@ -127,7 +128,11 @@ class GstEngine : public Engine::Base { QString sink_; QString device_; + bool fadeout_enabled_; + int fadeout_duration_; + boost::shared_ptr current_pipeline_; + boost::shared_ptr fadeout_pipeline_; ////////// // scope diff --git a/src/engines/gstenginepipeline.cpp b/src/engines/gstenginepipeline.cpp index cc08a7813..a3ef3d293 100644 --- a/src/engines/gstenginepipeline.cpp +++ b/src/engines/gstenginepipeline.cpp @@ -24,6 +24,8 @@ GstEnginePipeline::GstEnginePipeline() : QObject(NULL), valid_(false), sink_(GstEngine::kAutoSink), + volume_percent_(100), + volume_modifier_(1.0), pipeline_(NULL), src_(NULL), decodebin_(NULL), @@ -293,5 +295,16 @@ void GstEnginePipeline::SetEqualizerParams(int preamp, const QList& band_ga } void GstEnginePipeline::SetVolume(int percent) { - g_object_set(G_OBJECT(volume_), "volume", double(percent) * 0.01, NULL); + volume_percent_ = percent; + UpdateVolume(); +} + +void GstEnginePipeline::SetVolumeModifier(qreal mod) { + volume_modifier_ = mod; + UpdateVolume(); +} + +void GstEnginePipeline::UpdateVolume() { + float vol = double(volume_percent_) * 0.01 * volume_modifier_; + g_object_set(G_OBJECT(volume_), "volume", vol, NULL); } diff --git a/src/engines/gstenginepipeline.h b/src/engines/gstenginepipeline.h index 4077221fe..0a7da6108 100644 --- a/src/engines/gstenginepipeline.h +++ b/src/engines/gstenginepipeline.h @@ -53,6 +53,9 @@ class GstEnginePipeline : public QObject { qint64 length() const; GstState state() const; + public slots: + void SetVolumeModifier(qreal mod); + signals: void EndOfStreamReached(); void MetadataFound(const Engine::SimpleMetaBundle& bundle); @@ -68,6 +71,8 @@ class GstEnginePipeline : public QObject { static void HandoffCallback(GstPad*, GstBuffer*, gpointer); static void EventCallback(GstPad*, GstEvent*, gpointer); + void UpdateVolume(); + private: static const int kGstStateTimeout = 10000000; @@ -76,6 +81,9 @@ class GstEnginePipeline : public QObject { QString device_; bool forwards_buffers_; + int volume_percent_; + qreal volume_modifier_; + GstElement* pipeline_; // Bins