limit stream configuration to creator

This commit is contained in:
AlexandreRouma 2024-01-30 20:28:32 +01:00
parent 75800e0ca2
commit 139f63ad25
3 changed files with 138 additions and 133 deletions

View File

@ -11,7 +11,7 @@ Sink::Sink(SinkEntry* entry, dsp::stream<dsp::stereo_t>* stream, const std::str
void Sink::showMenu() {} 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), manager(manager),
parentStream(parentStream), parentStream(parentStream),
id(id) id(id)
@ -156,7 +156,7 @@ std::string SinkEntry::getStringID() const {
return stringId; return stringId;
} }
AudioStream::AudioStream(StreamManager* manager, const std::string& name, dsp::stream<dsp::stereo_t>* stream, double samplerate) : Stream::Stream(StreamManager* manager, const std::string& name, dsp::stream<dsp::stereo_t>* stream, double samplerate) :
manager(manager), manager(manager),
name(name) name(name)
{ {
@ -166,7 +166,7 @@ AudioStream::AudioStream(StreamManager* manager, const std::string& name, dsp::s
split.init(stream); split.init(stream);
} }
AudioStream::~AudioStream() { Stream::~Stream() {
// Copy sink IDs // Copy sink IDs
std::vector<SinkID> ids; std::vector<SinkID> ids;
for (auto& [id, sink] : sinks) { for (auto& [id, sink] : sinks) {
@ -179,75 +179,11 @@ AudioStream::~AudioStream() {
} }
} }
void AudioStream::setInput(dsp::stream<dsp::stereo_t>* stream, double samplerate) { const std::string& Stream::getName() const {
std::unique_lock<std::shared_mutex> 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<std::shared_mutex> 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 {
return name; return name;
} }
SinkID AudioStream::addSink(const std::string& type, SinkID id) { SinkID Stream::addSink(const std::string& type, SinkID id) {
std::unique_lock<std::shared_mutex> lck(sinksMtx); std::unique_lock<std::shared_mutex> lck(sinksMtx);
// Find a free ID if not provided // Find a free ID if not provided
@ -289,7 +225,7 @@ SinkID AudioStream::addSink(const std::string& type, SinkID id) {
return id; return id;
} }
void AudioStream::removeSink(SinkID id, bool forgetSettings) { void Stream::removeSink(SinkID id, bool forgetSettings) {
// Acquire shared lock // Acquire shared lock
std::shared_ptr<SinkEntry> sink; std::shared_ptr<SinkEntry> sink;
{ {
@ -333,15 +269,85 @@ void AudioStream::removeSink(SinkID id, bool forgetSettings) {
} }
} }
std::shared_lock<std::shared_mutex> AudioStream::getSinksLock() { std::shared_lock<std::shared_mutex> Stream::getSinksLock() {
return std::shared_lock<std::shared_mutex>(sinksMtx); return std::shared_lock<std::shared_mutex>(sinksMtx);
} }
const std::map<SinkID, std::shared_ptr<SinkEntry>>& AudioStream::getSinks() const { const std::map<SinkID, std::shared_ptr<SinkEntry>>& Stream::getSinks() const {
return sinks; return sinks;
} }
void AudioStream::startDSP() { MasterStream::MasterStream(StreamManager* manager, const std::string& name, dsp::stream<dsp::stereo_t>* stream, double samplerate) :
Stream(manager, name, stream, samplerate)
{}
void MasterStream::setInput(dsp::stream<dsp::stereo_t>* stream, double samplerate) {
std::unique_lock<std::shared_mutex> 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<std::shared_mutex> 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? // TODO: Maybe add a different mutex for the stream?
std::unique_lock<std::shared_mutex> lck(sinksMtx); std::unique_lock<std::shared_mutex> lck(sinksMtx);
@ -356,7 +362,7 @@ void AudioStream::startDSP() {
running = true; running = true;
} }
void AudioStream::stopDSP() { void MasterStream::stopDSP() {
// TODO: Maybe add a different mutex for the stream? // TODO: Maybe add a different mutex for the stream?
std::unique_lock<std::shared_mutex> lck(sinksMtx); std::unique_lock<std::shared_mutex> lck(sinksMtx);
@ -371,7 +377,7 @@ void AudioStream::stopDSP() {
running = false; running = false;
} }
std::shared_ptr<AudioStream> StreamManager::createStream(const std::string& name, dsp::stream<dsp::stereo_t>* stream, double samplerate) { std::shared_ptr<MasterStream> StreamManager::createStream(const std::string& name, dsp::stream<dsp::stereo_t>* stream, double samplerate) {
std::unique_lock<std::shared_mutex> lck(streamsMtx); std::unique_lock<std::shared_mutex> lck(streamsMtx);
// Check that no stream with that name already exists // Check that no stream with that name already exists
@ -381,7 +387,7 @@ std::shared_ptr<AudioStream> StreamManager::createStream(const std::string& name
} }
// Create and save stream // Create and save stream
auto newStream = std::make_shared<AudioStream>(this, name, stream, samplerate); std::shared_ptr<MasterStream> newStream(new MasterStream(this, name, stream, samplerate));
streams[name] = newStream; streams[name] = newStream;
// Release lock and emit event // Release lock and emit event
@ -391,7 +397,7 @@ std::shared_ptr<AudioStream> StreamManager::createStream(const std::string& name
return newStream; return newStream;
} }
void StreamManager::destroyStream(std::shared_ptr<AudioStream>& stream) { void StreamManager::destroyStream(std::shared_ptr<MasterStream>& stream) {
// Emit event // Emit event
onStreamDestroy(stream); onStreamDestroy(stream);
@ -400,7 +406,7 @@ void StreamManager::destroyStream(std::shared_ptr<AudioStream>& stream) {
std::unique_lock<std::shared_mutex> lck(streamsMtx); std::unique_lock<std::shared_mutex> lck(streamsMtx);
// Get iterator of the stream // Get iterator of the stream
auto it = std::find_if(streams.begin(), streams.end(), [&stream](std::pair<const std::string, std::shared_ptr<AudioStream>> e) { auto it = std::find_if(streams.begin(), streams.end(), [&stream](std::pair<const std::string, std::shared_ptr<Stream>> e) {
return e.second == stream; return e.second == stream;
}); });
if (it == streams.end()) { if (it == streams.end()) {
@ -421,7 +427,7 @@ std::shared_lock<std::shared_mutex> StreamManager::getStreamsLock() {
return std::shared_lock<std::shared_mutex>(streamsMtx); return std::shared_lock<std::shared_mutex>(streamsMtx);
} }
const std::map<std::string, std::shared_ptr<AudioStream>>& StreamManager::getStreams() const { const std::map<std::string, std::shared_ptr<Stream>>& StreamManager::getStreams() const {
return streams; return streams;
} }

View File

@ -11,12 +11,13 @@
#include <shared_mutex> #include <shared_mutex>
#include <stdexcept> #include <stdexcept>
class AudioStream; class SinkEntry;
class Stream;
class MasterStream;
class StreamManager;
using SinkID = int; using SinkID = int;
class SinkEntry;
class Sink { class Sink {
public: public:
Sink(SinkEntry* entry, dsp::stream<dsp::stereo_t>* stream, const std::string& name, SinkID id, const std::string& stringId); Sink(SinkEntry* entry, dsp::stream<dsp::stereo_t>* stream, const std::string& name, SinkID id, const std::string& stringId);
@ -58,14 +59,13 @@ public:
SinkEntryCreateException(const char* what) : std::runtime_error(what) {} SinkEntryCreateException(const char* what) : std::runtime_error(what) {}
}; };
class StreamManager;
// TODO: Would be cool to have data and audio sinks instead of just audio. // TODO: Would be cool to have data and audio sinks instead of just audio.
class SinkEntry { class SinkEntry {
friend AudioStream;
friend Sink; friend Sink;
friend Stream;
friend MasterStream;
public: 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. * Get the type of the sink.
@ -165,7 +165,7 @@ private:
std::string type; std::string type;
const SinkID id; const SinkID id;
double inputSamplerate; double inputSamplerate;
AudioStream* const parentStream; Stream* const parentStream;
StreamManager* const manager; StreamManager* const manager;
std::string stringId; std::string stringId;
@ -175,28 +175,11 @@ private:
float panning = 0.0f; float panning = 0.0f;
}; };
class StreamManager; class Stream {
protected:
class AudioStream { Stream(StreamManager* manager, const std::string& name, dsp::stream<dsp::stereo_t>* stream, double samplerate);
friend StreamManager;
public: public:
AudioStream(StreamManager* manager, const std::string& name, dsp::stream<dsp::stereo_t>* stream, double samplerate); ~Stream();
~AudioStream();
/**
* Set DSP stream input.
* @param stream DSP stream.
* @param samplerate New samplerate (optional, 0.0 if not used).
*/
void setInput(dsp::stream<dsp::stereo_t>* 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);
/** /**
* Get the name of the stream. * Get the name of the stream.
@ -231,7 +214,40 @@ public:
*/ */
const std::map<SinkID, std::shared_ptr<SinkEntry>>& getSinks() const; const std::map<SinkID, std::shared_ptr<SinkEntry>>& 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<double> onSamplerateChanged;
// Emitted when a sink was added
NewEvent<std::shared_ptr<SinkEntry>> onSinkAdded;
// Emitted when a sink is being removed
NewEvent<std::shared_ptr<SinkEntry>> onSinkRemove;
protected:
StreamManager* const manager;
const std::string name;
double samplerate;
dsp::routing::Splitter<dsp::stereo_t> split;
bool running = false;
std::map<SinkID, std::shared_ptr<SinkEntry>> sinks;
std::shared_mutex sinksMtx;
};
class MasterStream : public Stream {
friend StreamManager;
MasterStream(StreamManager* manager, const std::string& name, dsp::stream<dsp::stereo_t>* 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<dsp::stereo_t>* stream, double samplerate = 0.0);
/**
* Set the samplerate of the input stream.
* @param samplerate Samplerate in Hz.
*/
void setSamplerate(double samplerate);
/** /**
* Start the DSP. * Start the DSP.
@ -242,23 +258,6 @@ public:
* Stop the DSP. * Stop the DSP.
*/ */
void stopDSP(); void stopDSP();
// Emitted when the samplerate of the stream was changed
NewEvent<double> onSamplerateChanged;
// Emitted when a sink was added
NewEvent<std::shared_ptr<SinkEntry>> onSinkAdded;
// Emitted when a sink is being removed
NewEvent<std::shared_ptr<SinkEntry>> onSinkRemove;
private:
StreamManager* const manager;
const std::string name;
double samplerate;
dsp::routing::Splitter<dsp::stereo_t> split;
bool running = false;
std::map<SinkID, std::shared_ptr<SinkEntry>> sinks;
std::shared_mutex sinksMtx;
}; };
class StreamManager { class StreamManager {
@ -271,13 +270,13 @@ public:
* @param samplerate Samplerate of the audio data. * @param samplerate Samplerate of the audio data.
* @return Audio stream instance. * @return Audio stream instance.
*/ */
std::shared_ptr<AudioStream> createStream(const std::string& name, dsp::stream<dsp::stereo_t>* stream, double samplerate); std::shared_ptr<MasterStream> createStream(const std::string& name, dsp::stream<dsp::stereo_t>* stream, double samplerate);
/** /**
* Destroy an audio stream. * Destroy an audio stream.
* @param stream Stream to destroy. The passed shared pointer will be automatically reset. * @param stream Stream to destroy. The passed shared pointer will be automatically reset.
*/ */
void destroyStream(std::shared_ptr<AudioStream>& stream); void destroyStream(std::shared_ptr<MasterStream>& stream);
/** /**
* Aquire a lock for the stream list. * Aquire a lock for the stream list.
@ -289,7 +288,7 @@ public:
* Get a list of streams and their associated names. * Get a list of streams and their associated names.
* @return Map of names to stream instance. * @return Map of names to stream instance.
*/ */
const std::map<std::string, std::shared_ptr<AudioStream>>& getStreams() const; const std::map<std::string, std::shared_ptr<Stream>>& getStreams() const;
/** /**
* Register a sink provider. * Register a sink provider.
@ -317,16 +316,16 @@ public:
const std::vector<std::string>& getSinkTypes() const; const std::vector<std::string>& getSinkTypes() const;
// Emitted when a stream was created // Emitted when a stream was created
NewEvent<std::shared_ptr<AudioStream>> onStreamCreated; NewEvent<std::shared_ptr<Stream>> onStreamCreated;
// Emitted when a stream is about to be destroyed // Emitted when a stream is about to be destroyed
NewEvent<std::shared_ptr<AudioStream>> onStreamDestroy; NewEvent<std::shared_ptr<Stream>> onStreamDestroy;
// Emitted when a sink provider was registered // Emitted when a sink provider was registered
NewEvent<const std::string&> onSinkProviderRegistered; NewEvent<const std::string&> onSinkProviderRegistered;
// Emitted when a sink provider is about to be unregistered // Emitted when a sink provider is about to be unregistered
NewEvent<const std::string&> onSinkProviderUnregister; NewEvent<const std::string&> onSinkProviderUnregister;
private: private:
std::map<std::string, std::shared_ptr<AudioStream>> streams; std::map<std::string, std::shared_ptr<Stream>> streams;
std::shared_mutex streamsMtx; std::shared_mutex streamsMtx;
std::map<std::string, SinkProvider*> providers; std::map<std::string, SinkProvider*> providers;

View File

@ -634,7 +634,7 @@ private:
dsp::chain<dsp::stereo_t> afChain; dsp::chain<dsp::stereo_t> afChain;
dsp::filter::Deemphasis<dsp::stereo_t> deemp; dsp::filter::Deemphasis<dsp::stereo_t> deemp;
std::shared_ptr<AudioStream> stream; std::shared_ptr<MasterStream> stream;
demod::Demodulator* selectedDemod = NULL; demod::Demodulator* selectedDemod = NULL;