diff --git a/src/engines/enginebase.cpp b/src/engines/enginebase.cpp index 3d1366698..2e0576e79 100644 --- a/src/engines/enginebase.cpp +++ b/src/engines/enginebase.cpp @@ -32,6 +32,7 @@ Engine::Base::Base() fadeout_enabled_(true), fadeout_duration_(2000), crossfade_enabled_(true), + next_background_stream_id_(0), about_to_end_emitted_(false) { } @@ -73,3 +74,7 @@ void Engine::Base::EmitAboutToEnd() { about_to_end_emitted_ = true; emit TrackAboutToEnd(); } + +int Engine::Base::AddBackgroundStream(const QUrl& url) { + return -1; +} diff --git a/src/engines/enginebase.h b/src/engines/enginebase.h index 105d776e3..93b238845 100644 --- a/src/engines/enginebase.h +++ b/src/engines/enginebase.h @@ -51,6 +51,9 @@ class Base : public QObject, boost::noncopyable { virtual void Unpause() = 0; virtual void Seek( uint ms ) = 0; + virtual int AddBackgroundStream(const QUrl& url); + virtual void StopBackgroundStream(int id) {} + virtual State state() const = 0; virtual uint position() const = 0; virtual uint length() const { return 0; } @@ -60,6 +63,7 @@ class Base : public QObject, boost::noncopyable { bool Play(const QUrl &u, TrackChangeType c) { return Load(u, c) && Play(); } void SetVolume( uint value ); + // Simple accessors inline uint volume() const { return volume_; } virtual const Scope &scope() { return scope_; } @@ -105,6 +109,7 @@ class Base : public QObject, boost::noncopyable { int fadeout_duration_; bool crossfade_enabled_; bool autocrossfade_enabled_; + int next_background_stream_id_; private: bool about_to_end_emitted_; diff --git a/src/engines/gstengine.cpp b/src/engines/gstengine.cpp index 91a92c656..c43ea012b 100644 --- a/src/engines/gstengine.cpp +++ b/src/engines/gstengine.cpp @@ -739,3 +739,32 @@ void GstEngine::RemoveBufferConsumer(BufferConsumer *consumer) { if (current_pipeline_) current_pipeline_->RemoveBufferConsumer(consumer); } + +int GstEngine::AddBackgroundStream(const QUrl& url) { + shared_ptr pipeline = CreatePipeline(url); + if (!pipeline) { + return -1; + } + // We don't want to get metadata messages or end notifications. + disconnect(pipeline.get(), SIGNAL(MetadataFound(Engine::SimpleMetaBundle)), this, 0); + disconnect(pipeline.get(), SIGNAL(EndOfStreamReached(bool)), this, 0); + connect(pipeline.get(), SIGNAL(EndOfStreamReached(bool)), SLOT(BackgroundStreamFinished())); + if (!pipeline->SetState(GST_STATE_PLAYING)) { + qWarning() << "Could not set thread to PLAYING."; + pipeline.reset(); + return -1; + } + pipeline->SetNextUrl(url); + int stream_id = next_background_stream_id_++; + background_streams_[stream_id] = pipeline; + return stream_id; +} + +void GstEngine::StopBackgroundStream(int id) { + background_streams_.remove(id); // Removes last shared_ptr reference. +} + +void GstEngine::BackgroundStreamFinished() { + GstEnginePipeline* pipeline = qobject_cast(sender()); + pipeline->SetNextUrl(pipeline->url()); +} diff --git a/src/engines/gstengine.h b/src/engines/gstengine.h index 7119f4d22..4b9de019f 100644 --- a/src/engines/gstengine.h +++ b/src/engines/gstengine.h @@ -25,10 +25,11 @@ #include "enginebase.h" #include "bufferconsumer.h" -#include -#include +#include #include +#include #include +#include #include #include @@ -65,6 +66,9 @@ class GstEngine : public Engine::Base, public BufferConsumer { bool CanDecode(const QUrl& url); + int AddBackgroundStream(const QUrl& url); + void StopBackgroundStream(int id); + uint position() const; uint length() const; Engine::State state() const; @@ -111,6 +115,7 @@ class GstEngine : public Engine::Base, public BufferConsumer { void AddBufferToScope(GstBuffer* buf, GstEnginePipeline* pipeline); void FadeoutFinished(); void SeekNow(); + void BackgroundStreamFinished(); private: // Callbacks @@ -168,6 +173,8 @@ class GstEngine : public Engine::Base, public BufferConsumer { uint seek_pos_; int timer_id_; + + QHash > background_streams_; };