From f97ca9ac057b08bb029189a039dfacf6f7339260 Mon Sep 17 00:00:00 2001 From: AlexandreRouma Date: Wed, 23 Nov 2022 10:22:29 +0100 Subject: [PATCH] almost done with the new recorder --- core/src/utils/optionlist.h | 4 ++ misc_modules/recorder/src/main.cpp | 90 ++++++++++++++++++++++++++---- 2 files changed, 84 insertions(+), 10 deletions(-) diff --git a/core/src/utils/optionlist.h b/core/src/utils/optionlist.h index 97f71da3..06e18ce9 100644 --- a/core/src/utils/optionlist.h +++ b/core/src/utils/optionlist.h @@ -50,6 +50,10 @@ public: return keys.size(); } + bool empty() { + return keys.empty(); + } + bool keyExists(K key) { if (std::find(keys.begin(), keys.end(), key) != keys.end()) { return true; } return false; diff --git a/misc_modules/recorder/src/main.cpp b/misc_modules/recorder/src/main.cpp index 9d06bafc..597beaf3 100644 --- a/misc_modules/recorder/src/main.cpp +++ b/misc_modules/recorder/src/main.cpp @@ -42,7 +42,7 @@ public: // Define option lists formats.define("WAV", wav::FORMAT_WAV); - formats.define("RF64", wav::FORMAT_RF64); + // formats.define("RF64", wav::FORMAT_RF64); // Disabled for now sampleDepths.define(wav::SAMP_DEPTH_8BIT, "8-Bit", wav::SAMP_DEPTH_8BIT); sampleDepths.define(wav::SAMP_DEPTH_16BIT, "16-Bit", wav::SAMP_DEPTH_16BIT); sampleDepths.define(wav::SAMP_DEPTH_32BIT, "32-Bit", wav::SAMP_DEPTH_32BIT); @@ -98,6 +98,22 @@ public: } void postInit() { + // Enumerate streams + audioStreams.clear(); + auto names = sigpath::sinkManager.getStreamNames(); + for (const auto& name : names) { + audioStreams.define(name, name, name); + } + + // Bind stream register/unregister handlers + onStreamRegisteredHandler.ctx = this; + onStreamRegisteredHandler.handler = streamRegisteredHandler; + sigpath::sinkManager.onStreamRegistered.bindHandler(&onStreamRegisteredHandler); + onStreamUnregisterHandler.ctx = this; + onStreamUnregisterHandler.handler = streamUnregisterHandler; + sigpath::sinkManager.onStreamUnregister.bindHandler(&onStreamUnregisterHandler); + + // Select the stream selectStream(selectedStreamName); } @@ -138,10 +154,8 @@ public: } // Open audio stream or baseband - // TODO: DO NOT HARDCODE THE STREAM NAME if (recMode == RECORDER_MODE_AUDIO) { - // TODO: HAS TO BE DONE PROPERLY - stereoStream = sigpath::sinkManager.bindStream("Radio"); + stereoStream = sigpath::sinkManager.bindStream(selectedStreamName); stereoSink.setInput(stereoStream); stereoSink.start(); } @@ -164,7 +178,7 @@ public: if (recMode == RECORDER_MODE_AUDIO) { // TODO: HAS TO BE DONE PROPERLY stereoSink.stop(); - sigpath::sinkManager.unbindStream("Radio", stereoStream); + sigpath::sinkManager.unbindStream(selectedStreamName, stereoStream); } else { // Unbind and destroy IQ stream @@ -231,7 +245,16 @@ private: } // Show additional audio options - if (_this->recMode == RECORDER_MODE_AUDIO) { + if (_this->recMode == RECORDER_MODE_AUDIO) { + ImGui::LeftLabel("Stream"); + ImGui::FillWidth(); + if (ImGui::Combo(CONCAT("##_recorder_stream_", _this->name), &_this->streamId, _this->audioStreams.txt)) { + _this->selectStream(_this->audioStreams.value(_this->streamId)); + config.acquire(); + config.conf[_this->name]["audioStream"] = _this->audioStreams.key(_this->streamId); + config.release(true); + } + _this->updateAudioMeter(_this->audioLvl); ImGui::FillWidth(); ImGui::VolumeMeter(_this->audioLvl.l, _this->audioLvl.l, -60, 10); @@ -240,13 +263,11 @@ private: ImGui::FillWidth(); if (ImGui::SliderFloat(CONCAT("##_recorder_vol_", _this->name), &_this->audioVolume, 0, 1, "")) { - // TODO: ADD VOLUME CONTROL _this->volume.setVolume(_this->audioVolume); config.acquire(); config.conf[_this->name]["audioVolume"] = _this->audioVolume; config.release(true); } - //ImGui::PopItemWidth(); if (_this->recording) { style::beginDisabled(); } if (ImGui::Checkbox(CONCAT("Stereo##_recorder_stereo_", _this->name), &_this->stereo)) { @@ -286,20 +307,34 @@ private: void selectStream(std::string name) { std::lock_guard lck(recMtx); deselectStream(); + + if (audioStreams.empty()) { + selectedStreamName.clear(); + return; + } + else if (!audioStreams.keyExists(name)) { + selectStream(audioStreams.key(0)); + return; + } + audioStream = sigpath::sinkManager.bindStream(name); if (!audioStream) { return; } selectedStreamName = name; + streamId = audioStreams.keyId(name); volume.setInput(audioStream); startAudioPath(); } void deselectStream() { std::lock_guard lck(recMtx); - if (selectedStreamName.empty() || !audioStream) { return; } + if (selectedStreamName.empty() || !audioStream) { + selectedStreamName.clear(); + return; + } if (recording && recMode == RECORDER_MODE_AUDIO) { stop(); } stopAudioPath(); sigpath::sinkManager.unbindStream(selectedStreamName, audioStream); - selectedStreamName = ""; + selectedStreamName.clear(); audioStream = NULL; } @@ -315,6 +350,36 @@ private: meter.stop(); } + static void streamRegisteredHandler(std::string name, void* ctx) { + RecorderModule* _this = (RecorderModule*)ctx; + + // Add new stream to the list + _this->audioStreams.define(name, name, name); + + // If no stream is selected, select new stream. If not, update the menu ID. + if (_this->selectedStreamName.empty()) { + _this->selectStream(name); + } + else { + _this->streamId = _this->audioStreams.keyId(_this->selectedStreamName); + } + } + + static void streamUnregisterHandler(std::string name, void* ctx) { + RecorderModule* _this = (RecorderModule*)ctx; + + // Remove stream from list + _this->audioStreams.undefineKey(name); + + // If the stream is in used, deselect it and reselect default. Otherwise, update ID. + if (_this->selectedStreamName == name) { + _this->selectStream(""); + } + else { + _this->streamId = _this->audioStreams.keyId(_this->selectedStreamName); + } + } + void updateAudioMeter(dsp::stereo_t& lvl) { // Note: Yes, using the natural log is on purpose, it just gives a more beautiful result. double frameTime = 1.0 / ImGui::GetIO().Framerate; @@ -385,6 +450,8 @@ private: dsp::sink::Handler stereoSink; dsp::sink::Handler monoSink; + OptionList audioStreams; + int streamId = 0; dsp::stream* audioStream = NULL; dsp::audio::Volume volume; dsp::routing::Splitter splitter; @@ -393,6 +460,9 @@ private: uint64_t samplerate = 48000; + EventHandler onStreamRegisteredHandler; + EventHandler onStreamUnregisterHandler; + }; MOD_EXPORT void _INIT_() {