From 646fe4fd02e846b49cd961a8bef58424b8cb88e7 Mon Sep 17 00:00:00 2001 From: Ryzerth Date: Mon, 26 Jul 2021 15:54:33 +0200 Subject: [PATCH] more bugfix on the module manager and audio streams --- audio_sink/src/main.cpp | 3 +- core/src/signal_path/sink.cpp | 86 ++++++++++++++++++++++++++++----- core/src/signal_path/sink.h | 8 +++ new_portaudio_sink/src/main.cpp | 1 + portaudio_sink/src/main.cpp | 1 + recorder/src/main.cpp | 4 +- 6 files changed, 89 insertions(+), 14 deletions(-) diff --git a/audio_sink/src/main.cpp b/audio_sink/src/main.cpp index 37b754ef..d4feed9c 100644 --- a/audio_sink/src/main.cpp +++ b/audio_sink/src/main.cpp @@ -248,7 +248,8 @@ public: } ~AudioSinkModule() { - + // Unregister sink, this will automatically stop and delete all instances of the audio sink + sigpath::sinkManager.unregisterSinkProvider("Audio"); } void postInit() {} diff --git a/core/src/signal_path/sink.cpp b/core/src/signal_path/sink.cpp index ce850532..7902e777 100644 --- a/core/src/signal_path/sink.cpp +++ b/core/src/signal_path/sink.cpp @@ -87,11 +87,52 @@ void SinkManager::Stream::setSampleRate(float sampleRate) { void SinkManager::registerSinkProvider(std::string name, SinkProvider provider) { if (providers.find(name) != providers.end()) { - spdlog::error("Cannot create sink provider '{0}', this name is already taken", name); + spdlog::error("Cannot register sink provider '{0}', this name is already taken", name); return; } + + // Add the provider to the lists providers[name] = provider; providerNames.push_back(name); + + // Recreatd the text list for the menu + refreshProviders(); + + // Update the IDs of every stream + for (auto& [streamName, stream] : streams) { + stream->providerId = std::distance(providerNames.begin(), std::find(providerNames.begin(), providerNames.end(), stream->providerName)); + } + + onSinkProviderRegistered.emit(name); +} + +void SinkManager::unregisterSinkProvider(std::string name) { + if (providers.find(name) == providers.end()) { + spdlog::error("Cannot unregister sink provider '{0}', no such provider exists.", name); + return; + } + + onSinkProviderUnregister.emit(name); + + // Switch all sinks using it to a null sink + for (auto& [streamName, stream] : streams) { + if (providerNames[stream->providerId] != name) { continue; } + setStreamSink(streamName, "None"); + } + + // Erase the provider from the lists + providers.erase(name); + providerNames.erase(std::find(providerNames.begin(), providerNames.end(), name)); + + // Recreatd the text list for the menu + refreshProviders(); + + // Update the IDs of every stream + for (auto& [streamName, stream] : streams) { + stream->providerId = std::distance(providerNames.begin(), std::find(providerNames.begin(), providerNames.end(), stream->providerName)); + } + + onSinkProviderUnregistered.emit(name); } void SinkManager::registerStream(std::string name, SinkManager::Stream* stream) { @@ -105,6 +146,8 @@ void SinkManager::registerStream(std::string name, SinkManager::Stream* stream) provider = providers["None"]; stream->sink = provider.create(stream, name, provider.ctx); + stream->providerId = std::distance(providerNames.begin(), std::find(providerNames.begin(), providerNames.end(), "None")); + stream->providerName = "None"; streams[name] = stream; streamNames.push_back(name); @@ -173,7 +216,27 @@ void SinkManager::unbindStream(std::string name, dsp::stream* str } void SinkManager::setStreamSink(std::string name, std::string providerName) { - spdlog::warn("setStreamSink is NOT implemented!!!"); + if (streams.find(name) == streams.end()) { + spdlog::error("Cannot set sink for stream '{0}'. Stream doesn't exist", name); + return; + } + Stream* stream = streams[name]; + if (providers.find(providerName) == providers.end()) { + spdlog::error("Unknown sink provider '{0}'", providerName); + return; + } + + if (stream->running) { + stream->sink->stop(); + } + delete stream->sink; + stream->providerId = std::distance(providerNames.begin(), std::find(providerNames.begin(), providerNames.end(), providerName)); + stream->providerName = providerName; + SinkManager::SinkProvider prov = providers[providerName]; + stream->sink = prov.create(stream, name, prov.ctx); + if (stream->running) { + stream->sink->start(); + } } void SinkManager::showVolumeSlider(std::string name, std::string prefix, float width, float btnHeight, int btwBorder, bool sameLine) { @@ -251,6 +314,7 @@ void SinkManager::loadStreamConfig(std::string name) { delete stream->sink; SinkManager::SinkProvider prov = providers[provName]; stream->providerId = std::distance(providerNames.begin(), std::find(providerNames.begin(), providerNames.end(), provName)); + stream->providerName = provName; stream->sink = prov.create(stream, name, prov.ctx); if (stream->running) { stream->sink->start(); @@ -293,15 +357,7 @@ void SinkManager::showMenu() { ImGui::SetNextItemWidth(menuWidth); if (ImGui::Combo(CONCAT("##_sdrpp_sink_select_", name), &stream->providerId, provStr.c_str())) { - if (stream->running) { - stream->sink->stop(); - } - delete stream->sink; - SinkManager::SinkProvider prov = providers[providerNames[stream->providerId]]; - stream->sink = prov.create(stream, name, prov.ctx); - if (stream->running) { - stream->sink->start(); - } + setStreamSink(name, providerNames[stream->providerId]); core::configManager.acquire(); saveStreamConfig(name); core::configManager.release(true); @@ -322,4 +378,12 @@ void SinkManager::showMenu() { std::vector SinkManager::getStreamNames() { return streamNames; +} + +void SinkManager::refreshProviders() { + providerNamesTxt.clear(); + for (auto& provName : providerNames) { + providerNamesTxt += provName; + providerNamesTxt += '\0'; + } } \ No newline at end of file diff --git a/core/src/signal_path/sink.h b/core/src/signal_path/sink.h index 950c7008..b1f68690 100644 --- a/core/src/signal_path/sink.h +++ b/core/src/signal_path/sink.h @@ -59,6 +59,7 @@ public: std::mutex ctrlMtx; float _sampleRate; int providerId = 0; + std::string providerName = ""; bool running = false; float guiVolume = 1.0f; @@ -89,6 +90,7 @@ public: }; void registerSinkProvider(std::string name, SinkProvider provider); + void unregisterSinkProvider(std::string name); void registerStream(std::string name, Stream* stream); void unregisterStream(std::string name); @@ -110,6 +112,10 @@ public: std::vector getStreamNames(); + Event onSinkProviderRegistered; + Event onSinkProviderUnregister; + Event onSinkProviderUnregistered; + Event onStreamRegistered; Event onStreamUnregister; Event onStreamUnregistered; @@ -117,10 +123,12 @@ public: private: void loadStreamConfig(std::string name); void saveStreamConfig(std::string name); + void refreshProviders(); std::map providers; std::map streams; std::vector providerNames; + std::string providerNamesTxt; std::vector streamNames; }; \ No newline at end of file diff --git a/new_portaudio_sink/src/main.cpp b/new_portaudio_sink/src/main.cpp index 7794f07b..745d286b 100644 --- a/new_portaudio_sink/src/main.cpp +++ b/new_portaudio_sink/src/main.cpp @@ -395,6 +395,7 @@ public: } ~AudioSinkModule() { + sigpath::sinkManager.unregisterSinkProvider("New Audio"); Pa_Terminate(); } diff --git a/portaudio_sink/src/main.cpp b/portaudio_sink/src/main.cpp index 3f606f3b..a1e8cc3f 100644 --- a/portaudio_sink/src/main.cpp +++ b/portaudio_sink/src/main.cpp @@ -293,6 +293,7 @@ public: } ~AudioSinkModule() { + sigpath::sinkManager.unregisterSinkProvider("Audio"); Pa_Terminate(); } diff --git a/recorder/src/main.cpp b/recorder/src/main.cpp index 95a05115..f5e6fb1c 100644 --- a/recorder/src/main.cpp +++ b/recorder/src/main.cpp @@ -398,8 +398,7 @@ private: } if (_this->selectedStreamName.empty()) { - _this->streamId = 0; - _this->selectedStreamName = _this->streamNames[0]; + _this->selectStream(_this->streamNames[0]); return; } @@ -420,6 +419,7 @@ private: if (_this->recording) { _this->stopRecording(); } if (_this->audioInput != NULL) { sigpath::sinkManager.unbindStream(_this->selectedStreamName, _this->audioInput); + _this->vol.setInput(&_this->dummyStream); _this->audioInput = NULL; } }