From 139f63ad25d8b3b7f1990e4e899bcabe13ad2cd5 Mon Sep 17 00:00:00 2001 From: AlexandreRouma Date: Tue, 30 Jan 2024 20:28:32 +0100 Subject: [PATCH] limit stream configuration to creator --- core/src/signal_path/stream.cpp | 164 ++++++++++++----------- core/src/signal_path/stream.h | 105 +++++++-------- decoder_modules/radio/src/radio_module.h | 2 +- 3 files changed, 138 insertions(+), 133 deletions(-) diff --git a/core/src/signal_path/stream.cpp b/core/src/signal_path/stream.cpp index 8255fb0a..9778d1ac 100644 --- a/core/src/signal_path/stream.cpp +++ b/core/src/signal_path/stream.cpp @@ -11,7 +11,7 @@ Sink::Sink(SinkEntry* entry, dsp::stream* stream, const std::str void Sink::showMenu() {} -SinkEntry::SinkEntry(StreamManager* manager, AudioStream* parentStream, const std::string& type, SinkID id, double inputSamplerate) : +SinkEntry::SinkEntry(StreamManager* manager, Stream* parentStream, const std::string& type, SinkID id, double inputSamplerate) : manager(manager), parentStream(parentStream), id(id) @@ -156,7 +156,7 @@ std::string SinkEntry::getStringID() const { return stringId; } -AudioStream::AudioStream(StreamManager* manager, const std::string& name, dsp::stream* stream, double samplerate) : +Stream::Stream(StreamManager* manager, const std::string& name, dsp::stream* stream, double samplerate) : manager(manager), name(name) { @@ -166,7 +166,7 @@ AudioStream::AudioStream(StreamManager* manager, const std::string& name, dsp::s split.init(stream); } -AudioStream::~AudioStream() { +Stream::~Stream() { // Copy sink IDs std::vector ids; for (auto& [id, sink] : sinks) { @@ -179,75 +179,11 @@ AudioStream::~AudioStream() { } } -void AudioStream::setInput(dsp::stream* stream, double samplerate) { - std::unique_lock lck(sinksMtx); - - // If all that's needed is to set the input, do it and return - if (samplerate == 0.0) { - split.setInput(stream); - return; - } - - // Update samplerate - this->samplerate = samplerate; - - // Stop DSP - if (running) { - split.stop(); - for (auto& [id, sink] : sinks) { - sink->stopDSP(); - } - } - - - // Set input and samplerate - split.setInput(stream); - for (auto& [id, sink] : sinks) { - sink->setInputSamplerate(samplerate); - } - - // Start DSP - if (running) { - for (auto& [id, sink] : sinks) { - sink->startDSP(); - } - split.start(); - } -} - -void AudioStream::setSamplerate(double samplerate) { - std::unique_lock lck(sinksMtx); - - // Update samplerate - this->samplerate = samplerate; - - // Stop DSP - if (running) { - split.stop(); - for (auto& [id, sink] : sinks) { - sink->stopDSP(); - } - } - - // Set samplerate - for (auto& [id, sink] : sinks) { - sink->setInputSamplerate(samplerate); - } - - // Start DSP - if (running) { - for (auto& [id, sink] : sinks) { - sink->startDSP(); - } - split.start(); - } -} - -const std::string& AudioStream::getName() const { +const std::string& Stream::getName() const { return name; } -SinkID AudioStream::addSink(const std::string& type, SinkID id) { +SinkID Stream::addSink(const std::string& type, SinkID id) { std::unique_lock lck(sinksMtx); // Find a free ID if not provided @@ -289,7 +225,7 @@ SinkID AudioStream::addSink(const std::string& type, SinkID id) { return id; } -void AudioStream::removeSink(SinkID id, bool forgetSettings) { +void Stream::removeSink(SinkID id, bool forgetSettings) { // Acquire shared lock std::shared_ptr sink; { @@ -333,15 +269,85 @@ void AudioStream::removeSink(SinkID id, bool forgetSettings) { } } -std::shared_lock AudioStream::getSinksLock() { +std::shared_lock Stream::getSinksLock() { return std::shared_lock(sinksMtx); } -const std::map>& AudioStream::getSinks() const { +const std::map>& Stream::getSinks() const { return sinks; } -void AudioStream::startDSP() { +MasterStream::MasterStream(StreamManager* manager, const std::string& name, dsp::stream* stream, double samplerate) : + Stream(manager, name, stream, samplerate) +{} + +void MasterStream::setInput(dsp::stream* stream, double samplerate) { + std::unique_lock lck(sinksMtx); + + // If all that's needed is to set the input, do it and return + if (samplerate == 0.0) { + split.setInput(stream); + return; + } + + // Update samplerate + this->samplerate = samplerate; + + // Stop DSP + if (running) { + split.stop(); + for (auto& [id, sink] : sinks) { + sink->stopDSP(); + } + } + + + // Set input and samplerate + split.setInput(stream); + for (auto& [id, sink] : sinks) { + sink->setInputSamplerate(samplerate); + } + + // Start DSP + if (running) { + for (auto& [id, sink] : sinks) { + sink->startDSP(); + } + split.start(); + } +} + +void MasterStream::setSamplerate(double samplerate) { + std::unique_lock lck(sinksMtx); + + // Update samplerate + this->samplerate = samplerate; + + // TODO: Maybe simply disallow while running? + + // Stop DSP if it was running + if (running) { + split.stop(); + for (auto& [id, sink] : sinks) { + sink->stopDSP(); + } + } + + // Set samplerate + for (auto& [id, sink] : sinks) { + sink->setInputSamplerate(samplerate); + } + + // Start DSP if it was running + if (running) { + for (auto& [id, sink] : sinks) { + sink->startDSP(); + } + split.start(); + } +} + +void MasterStream::startDSP() { // TODO: Maybe add a different mutex for the stream? std::unique_lock lck(sinksMtx); @@ -356,7 +362,7 @@ void AudioStream::startDSP() { running = true; } -void AudioStream::stopDSP() { +void MasterStream::stopDSP() { // TODO: Maybe add a different mutex for the stream? std::unique_lock lck(sinksMtx); @@ -371,7 +377,7 @@ void AudioStream::stopDSP() { running = false; } -std::shared_ptr StreamManager::createStream(const std::string& name, dsp::stream* stream, double samplerate) { +std::shared_ptr StreamManager::createStream(const std::string& name, dsp::stream* stream, double samplerate) { std::unique_lock lck(streamsMtx); // Check that no stream with that name already exists @@ -381,7 +387,7 @@ std::shared_ptr StreamManager::createStream(const std::string& name } // Create and save stream - auto newStream = std::make_shared(this, name, stream, samplerate); + std::shared_ptr newStream(new MasterStream(this, name, stream, samplerate)); streams[name] = newStream; // Release lock and emit event @@ -391,7 +397,7 @@ std::shared_ptr StreamManager::createStream(const std::string& name return newStream; } -void StreamManager::destroyStream(std::shared_ptr& stream) { +void StreamManager::destroyStream(std::shared_ptr& stream) { // Emit event onStreamDestroy(stream); @@ -400,7 +406,7 @@ void StreamManager::destroyStream(std::shared_ptr& stream) { std::unique_lock lck(streamsMtx); // Get iterator of the stream - auto it = std::find_if(streams.begin(), streams.end(), [&stream](std::pair> e) { + auto it = std::find_if(streams.begin(), streams.end(), [&stream](std::pair> e) { return e.second == stream; }); if (it == streams.end()) { @@ -421,7 +427,7 @@ std::shared_lock StreamManager::getStreamsLock() { return std::shared_lock(streamsMtx); } -const std::map>& StreamManager::getStreams() const { +const std::map>& StreamManager::getStreams() const { return streams; } diff --git a/core/src/signal_path/stream.h b/core/src/signal_path/stream.h index 839f5f63..38dd4e5c 100644 --- a/core/src/signal_path/stream.h +++ b/core/src/signal_path/stream.h @@ -11,12 +11,13 @@ #include #include -class AudioStream; +class SinkEntry; +class Stream; +class MasterStream; +class StreamManager; using SinkID = int; -class SinkEntry; - class Sink { public: Sink(SinkEntry* entry, dsp::stream* stream, const std::string& name, SinkID id, const std::string& stringId); @@ -58,14 +59,13 @@ public: SinkEntryCreateException(const char* what) : std::runtime_error(what) {} }; -class StreamManager; - // TODO: Would be cool to have data and audio sinks instead of just audio. class SinkEntry { - friend AudioStream; friend Sink; + friend Stream; + friend MasterStream; public: - SinkEntry(StreamManager* manager, AudioStream* parentStream, const std::string& type, SinkID id, double inputSamplerate); + SinkEntry(StreamManager* manager, Stream* parentStream, const std::string& type, SinkID id, double inputSamplerate); /** * Get the type of the sink. @@ -165,7 +165,7 @@ private: std::string type; const SinkID id; double inputSamplerate; - AudioStream* const parentStream; + Stream* const parentStream; StreamManager* const manager; std::string stringId; @@ -175,28 +175,11 @@ private: float panning = 0.0f; }; -class StreamManager; - -class AudioStream { - friend StreamManager; +class Stream { +protected: + Stream(StreamManager* manager, const std::string& name, dsp::stream* stream, double samplerate); public: - AudioStream(StreamManager* manager, const std::string& name, dsp::stream* stream, double samplerate); - ~AudioStream(); - - /** - * Set DSP stream input. - * @param stream DSP stream. - * @param samplerate New samplerate (optional, 0.0 if not used). - */ - void setInput(dsp::stream* stream, double samplerate = 0.0); - - // TODO: There must be a way to pre-stop things to avoid having weird shit happen - - /** - * Set the samplerate of the input stream. - * @param samplerate Samplerate in Hz. - */ - void setSamplerate(double samplerate); + ~Stream(); /** * Get the name of the stream. @@ -231,7 +214,40 @@ public: */ const std::map>& getSinks() const; - // TODO: This should only be callable by the module that created the stream + // Emitted when the samplerate of the stream was changed + NewEvent onSamplerateChanged; + // Emitted when a sink was added + NewEvent> onSinkAdded; + // Emitted when a sink is being removed + NewEvent> onSinkRemove; + +protected: + StreamManager* const manager; + const std::string name; + double samplerate; + dsp::routing::Splitter split; + bool running = false; + + std::map> sinks; + std::shared_mutex sinksMtx; +}; + +class MasterStream : public Stream { + friend StreamManager; + MasterStream(StreamManager* manager, const std::string& name, dsp::stream* stream, double samplerate); +public: + /** + * Set DSP stream input. + * @param stream DSP stream. + * @param samplerate New samplerate (optional, 0.0 if not used). + */ + void setInput(dsp::stream* stream, double samplerate = 0.0); + + /** + * Set the samplerate of the input stream. + * @param samplerate Samplerate in Hz. + */ + void setSamplerate(double samplerate); /** * Start the DSP. @@ -242,23 +258,6 @@ public: * Stop the DSP. */ void stopDSP(); - - // Emitted when the samplerate of the stream was changed - NewEvent onSamplerateChanged; - // Emitted when a sink was added - NewEvent> onSinkAdded; - // Emitted when a sink is being removed - NewEvent> onSinkRemove; - -private: - StreamManager* const manager; - const std::string name; - double samplerate; - dsp::routing::Splitter split; - bool running = false; - - std::map> sinks; - std::shared_mutex sinksMtx; }; class StreamManager { @@ -271,13 +270,13 @@ public: * @param samplerate Samplerate of the audio data. * @return Audio stream instance. */ - std::shared_ptr createStream(const std::string& name, dsp::stream* stream, double samplerate); + std::shared_ptr createStream(const std::string& name, dsp::stream* stream, double samplerate); /** * Destroy an audio stream. * @param stream Stream to destroy. The passed shared pointer will be automatically reset. */ - void destroyStream(std::shared_ptr& stream); + void destroyStream(std::shared_ptr& stream); /** * Aquire a lock for the stream list. @@ -289,7 +288,7 @@ public: * Get a list of streams and their associated names. * @return Map of names to stream instance. */ - const std::map>& getStreams() const; + const std::map>& getStreams() const; /** * Register a sink provider. @@ -317,16 +316,16 @@ public: const std::vector& getSinkTypes() const; // Emitted when a stream was created - NewEvent> onStreamCreated; + NewEvent> onStreamCreated; // Emitted when a stream is about to be destroyed - NewEvent> onStreamDestroy; + NewEvent> onStreamDestroy; // Emitted when a sink provider was registered NewEvent onSinkProviderRegistered; // Emitted when a sink provider is about to be unregistered NewEvent onSinkProviderUnregister; private: - std::map> streams; + std::map> streams; std::shared_mutex streamsMtx; std::map providers; diff --git a/decoder_modules/radio/src/radio_module.h b/decoder_modules/radio/src/radio_module.h index b04a1468..518b76d3 100644 --- a/decoder_modules/radio/src/radio_module.h +++ b/decoder_modules/radio/src/radio_module.h @@ -634,7 +634,7 @@ private: dsp::chain afChain; dsp::filter::Deemphasis deemp; - std::shared_ptr stream; + std::shared_ptr stream; demod::Demodulator* selectedDemod = NULL;