mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2024-12-26 02:48:31 +01:00
limit stream configuration to creator
This commit is contained in:
parent
75800e0ca2
commit
139f63ad25
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user