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() {}
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<dsp::stereo_t>* stream, double samplerate) :
Stream::Stream(StreamManager* manager, const std::string& name, dsp::stream<dsp::stereo_t>* 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<SinkID> ids;
for (auto& [id, sink] : sinks) {
@ -179,75 +179,11 @@ AudioStream::~AudioStream() {
}
}
void AudioStream::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 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 {
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<std::shared_mutex> 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<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);
}
const std::map<SinkID, std::shared_ptr<SinkEntry>>& AudioStream::getSinks() const {
const std::map<SinkID, std::shared_ptr<SinkEntry>>& Stream::getSinks() const {
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?
std::unique_lock<std::shared_mutex> 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<std::shared_mutex> lck(sinksMtx);
@ -371,7 +377,7 @@ void AudioStream::stopDSP() {
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);
// 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
auto newStream = std::make_shared<AudioStream>(this, name, stream, samplerate);
std::shared_ptr<MasterStream> newStream(new MasterStream(this, name, stream, samplerate));
streams[name] = newStream;
// Release lock and emit event
@ -391,7 +397,7 @@ std::shared_ptr<AudioStream> StreamManager::createStream(const std::string& name
return newStream;
}
void StreamManager::destroyStream(std::shared_ptr<AudioStream>& stream) {
void StreamManager::destroyStream(std::shared_ptr<MasterStream>& stream) {
// Emit event
onStreamDestroy(stream);
@ -400,7 +406,7 @@ void StreamManager::destroyStream(std::shared_ptr<AudioStream>& stream) {
std::unique_lock<std::shared_mutex> lck(streamsMtx);
// 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;
});
if (it == streams.end()) {
@ -421,7 +427,7 @@ std::shared_lock<std::shared_mutex> StreamManager::getStreamsLock() {
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;
}

View File

@ -11,12 +11,13 @@
#include <shared_mutex>
#include <stdexcept>
class AudioStream;
class SinkEntry;
class Stream;
class MasterStream;
class StreamManager;
using SinkID = int;
class SinkEntry;
class Sink {
public:
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) {}
};
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<dsp::stereo_t>* stream, double samplerate);
public:
AudioStream(StreamManager* manager, const std::string& name, dsp::stream<dsp::stereo_t>* 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<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);
~Stream();
/**
* Get the name of the stream.
@ -231,7 +214,40 @@ public:
*/
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.
@ -242,23 +258,6 @@ public:
* Stop the DSP.
*/
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 {
@ -271,13 +270,13 @@ public:
* @param samplerate Samplerate of the audio data.
* @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.
* @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.
@ -289,7 +288,7 @@ public:
* Get a list of streams and their associated names.
* @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.
@ -317,16 +316,16 @@ public:
const std::vector<std::string>& getSinkTypes() const;
// 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
NewEvent<std::shared_ptr<AudioStream>> onStreamDestroy;
NewEvent<std::shared_ptr<Stream>> onStreamDestroy;
// Emitted when a sink provider was registered
NewEvent<const std::string&> onSinkProviderRegistered;
// Emitted when a sink provider is about to be unregistered
NewEvent<const std::string&> onSinkProviderUnregister;
private:
std::map<std::string, std::shared_ptr<AudioStream>> streams;
std::map<std::string, std::shared_ptr<Stream>> streams;
std::shared_mutex streamsMtx;
std::map<std::string, SinkProvider*> providers;

View File

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