diff --git a/src/common/Configuration.cpp b/src/common/Configuration.cpp index 6672122..222d1c7 100644 --- a/src/common/Configuration.cpp +++ b/src/common/Configuration.cpp @@ -40,7 +40,7 @@ Configuration& Configuration::getConfig() { Configuration::Configuration() : _generalConfig(*this, path::config_base_path), _socketConfig(*this, path::config_base_path), _demodConfig(*this, path::config_base_path), - _rtspConfig(*this, path::config_base_path) { + _rtspConfig(*this, path::config_base_path), _tunerList(*this, path::config_base_path) { _configPath = DATABASE_PATH; } @@ -104,7 +104,7 @@ void Configuration::loadAll(){ _socketConfig.load(); _demodConfig.load(); _rtspConfig.load(); - + _tunerList.load(); } void Configuration::saveAll(){ @@ -112,6 +112,7 @@ void Configuration::saveAll(){ _socketConfig.save(); _demodConfig.save(); _rtspConfig.save(); + _tunerList.save(); } std::string Configuration::getLogDirectory(){ @@ -156,6 +157,8 @@ void Configuration::invalidate() { } /* Config implementations */ +GeneralConfig::GeneralConfig(ConfigManager& cm, std::string path) : ConfigBase(cm, std::move(path)) {}; + void GeneralConfig::load() { logfileVerbosity = base.pTree().get(basePath + path::path_seperator + "general" + path::path_seperator + "log_verbosity", DEFAULT_LOGFILE_VERBOSITY); } @@ -165,6 +168,8 @@ void GeneralConfig::save() { base.invalidate(); } +SocketServerConfig::SocketServerConfig(ConfigManager& cm, std::string path) : ConfigBase(cm, std::move(path)) {}; + void SocketServerConfig::load() { maxConnections = base.pTree().get(basePath + path::path_seperator + "socket" + path::path_seperator + "max_connections", MAX_TCP_CONNECTIONS); tcpPort = base.pTree().get(basePath + path::path_seperator + "socket" + path::path_seperator + "port", DEFAULT_TCP_PORT); @@ -181,6 +186,8 @@ void SocketServerConfig::save() { base.pTree().put(basePath + path::path_seperator + "socket" + path::path_seperator + "python_path", pythonBinary); base.invalidate(); } + +DemodConfig::DemodConfig(ConfigManager& cm, std::string path) : ConfigBase(cm, std::move(path)) {}; void DemodConfig::load() { retuneDelay = base.pTree().get(basePath + path::path_seperator + "demod" + path::path_seperator + "retune_delay", static_cast(TUNER_RETUNE_TIME)); @@ -194,6 +201,8 @@ void DemodConfig::save() { base.pTree().put(basePath + path::path_seperator + "demod" + path::path_seperator + "squelch_mode", squelchType); base.invalidate(); } + +AudioServerConfig::AudioServerConfig(ConfigManager& cm, std::string path) : ConfigBase(cm, std::move(path)) {}; void AudioServerConfig::load() { rtspPort = base.pTree().get(basePath + path::path_seperator + "audio_stream" + path::path_seperator + "rtsp_port", DEFAULT_RTSP_PORT); @@ -206,5 +215,49 @@ void AudioServerConfig::save() { base.invalidate(); } +TunerList::TunerList(ConfigManager& cm, std::string path) : ConfigBase(cm, std::move(path)) {}; + +void TunerList::load() { + try { + BOOST_FOREACH(ptree::value_type& v, base.pTree().get_child(basePath + path::path_seperator + "tuners")){ + ptree tunerPT = v.second; + TunerConfig tuner; + tuner.rank = tunerPT.get("rank", 0); + tuner.descriptor = tunerPT.get("descriptor", "null"); + tuner.driver = tunerPT.get("driver", "null"); + tuner.ppmCorrection = tunerPT.get("ppm_correction", 0); + tuner.sampleRate = tunerPT.get("sample_rate", 2048000); + + RAW_LOG_F(2, "Tuner:"); + RAW_LOG_F(2, "\tRank: %i", tuner.rank); + RAW_LOG_F(2, "\tDescriptor: %s", tuner.descriptor.c_str()); + RAW_LOG_F(2, "\tDriver: %s", tuner.driver.c_str()); + RAW_LOG_F(2, "\tPPM: %i", tuner.ppmCorrection); + RAW_LOG_F(2, "\tSample rate: %li", tuner.sampleRate); + + tuners.insert(std::move(tuner)); + } + } catch (std::exception& e) { + + } +} + +void TunerList::save() { + ptree tunerList, p; + + base.pTree().erase(basePath + path::path_seperator + "tuners"); + + BOOST_FOREACH(const TunerConfig& c, tuners){ + p.put("rank", c.rank); + p.put("descriptor", c.descriptor); + p.put("driver", c.driver); + p.put("ppm_correction", c.ppmCorrection); + p.put("sample_rate", c.sampleRate); + tunerList.push_back(std::make_pair("", p)); + } + + base.pTree().put_child(basePath + path::path_seperator + "tuners", tunerList); +} + } } diff --git a/src/common/Configuration.h b/src/common/Configuration.h index b77669c..7377fed 100644 --- a/src/common/Configuration.h +++ b/src/common/Configuration.h @@ -9,6 +9,7 @@ #include #include +#include #include #include "constants.h" @@ -52,7 +53,7 @@ protected: struct GeneralConfig : public ConfigBase { public: - GeneralConfig(ConfigManager& cm, std::string path) : ConfigBase(cm, std::move(path)) {}; + GeneralConfig(ConfigManager& cm, std::string path); int logfileVerbosity = DEFAULT_LOGFILE_VERBOSITY; @@ -68,7 +69,7 @@ public: struct SocketServerConfig : public ConfigBase { public: - SocketServerConfig(ConfigManager& cm, std::string path) : ConfigBase(cm, std::move(path)) {}; + SocketServerConfig(ConfigManager& cm, std::string path); int tcpPort = DEFAULT_TCP_PORT; int maxConnections = MAX_TCP_CONNECTIONS; @@ -90,7 +91,7 @@ public: #define DEFAULT_SQUELCH_MODE (SQUELCH_DBM) struct DemodConfig : public ConfigBase { - DemodConfig(ConfigManager& cm, std::string path) : ConfigBase(cm, std::move(path)) {}; + DemodConfig(ConfigManager& cm, std::string path); long int retuneDelay = TUNER_RETUNE_TIME; long int demodDelay = DEMOD_BUFFER_TIME; @@ -101,24 +102,40 @@ struct DemodConfig : public ConfigBase { }; #define DEFAULT_RANK 0 -#define DEFAULT_DESC "NULL" +#define DEFAULT_DESC "null" #define DEFAULT_DRIVER "null" #define DEFAULT_PPM 0 #define DEFAULT_TUNER_SAMPLE_RATE 2048000 struct TunerConfig { int rank = DEFAULT_RANK; - std::string description = DEFAULT_DESC; + std::string descriptor = DEFAULT_DESC; std::string driver = DEFAULT_DRIVER; int ppmCorrection = DEFAULT_PPM; long int sampleRate = DEFAULT_TUNER_SAMPLE_RATE; }; +struct TunerList : public ConfigBase { + class TunerComparator : public std::less { + public: + constexpr bool operator()(const TunerConfig& left, const TunerConfig& right) const { + return left.rank < right.rank; + } + }; +public: + + TunerList(ConfigManager& cm, std::string path); + std::set tuners; + + virtual void save(); + virtual void load(); +}; + #define DEFAULT_RTSP_PORT 8554 #define DEFAULT_RTSP_OVER_HTTP false struct AudioServerConfig : public ConfigBase { - AudioServerConfig(ConfigManager& cm, std::string path) : ConfigBase(cm, std::move(path)) {}; + AudioServerConfig(ConfigManager& cm, std::string path); int rtspPort = DEFAULT_RTSP_PORT; bool httpTunneling = DEFAULT_RTSP_OVER_HTTP; @@ -175,6 +192,7 @@ public: SocketServerConfig& getSocketConfig() { return _socketConfig; }; DemodConfig& getDemodConfig() { return _demodConfig; }; AudioServerConfig& getAudioServerConfig() { return _rtspConfig; }; + TunerList& getTunerList() { return _tunerList; }; std::string getLogDirectory(); std::string getDatedLogPath(); @@ -191,6 +209,7 @@ private: SocketServerConfig _socketConfig; DemodConfig _demodConfig; AudioServerConfig _rtspConfig; + TunerList _tunerList; Configuration(); diff --git a/src/sigproc/TunerManager.cpp b/src/sigproc/TunerManager.cpp index f770934..d693cf8 100644 --- a/src/sigproc/TunerManager.cpp +++ b/src/sigproc/TunerManager.cpp @@ -1,11 +1,13 @@ #include +#include "PiScan.h" #include "TunerManager.h" #include "CubicSDR.h" #include "loguru.hpp" #define AUDIO_DRIVER "audio" +using TunerList = piscan::config::TunerList; namespace piscan{ namespace sigproc { @@ -56,7 +58,7 @@ bool TunerManager::selectFirstAvailableDevice() { SDRDeviceInfo* device = (*(_devs.begin())).second; _selectedTuner.device = device; _selectedTuner.config.driver = device->getDriver(); - _selectedTuner.config.description = device->getName(); + _selectedTuner.config.descriptor = device->getName(); return true; } @@ -94,27 +96,62 @@ long TunerManager::nearestSampleRate(long desired, std::vector& supportedR * @return False if a tuner could not be selected */ bool TunerManager::autoSelectTuner() { + TunerList& tunerList = piscan::app::system::getConfig().getTunerList(); + if(_devs.empty()) { LOG_F(WARNING, "No SDR devices were found"); return false; } - if (_savedTuners.empty()) { + if (tunerList.tuners.empty()) { + // TODO temporary LOG_F(INFO, "No saved tuners found in config, defaulting to first available"); selectFirstAvailableDevice(); LOG_F(INFO, "New tuner will be saved to config"); - _savedTuners.push(_selectedTuner.config); + _selectedTuner.config.rank = tunerList.tuners.size(); + tunerList.tuners.insert(_selectedTuner.config); + } + else { + bool foundTuner = false; + LOG_F(1, "Searching for known tuners..."); + for (piscan::config::TunerConfig t : tunerList.tuners) { + auto dev = _devs.find(t.descriptor); + if (dev != _devs.end()) { + if (!(*dev).second->isAvailable()) { + LOG_F(WARNING, "Found tuner %s but it is unavailable", t.descriptor.c_str()); + continue; + } + + LOG_F(1, "Found tuner %s with rank %i", t.descriptor.c_str(), t.rank); + + _selectedTuner.config = t; + _selectedTuner.device = (*dev).second; + + foundTuner = true; + break; + } + } + + // TODO temporary + if (!foundTuner) { + LOG_F(INFO, "No saved tuners were detected, defaulting to first available"); + selectFirstAvailableDevice(); + + LOG_F(INFO, "New tuner will be saved to config"); + _selectedTuner.config.rank = tunerList.tuners.size(); + tunerList.tuners.insert(_selectedTuner.config); + } } LOG_F(INFO, "Auto selecting sample rate"); std::vector srates(std::move(_selectedTuner.device->getSampleRates(SOAPY_SDR_RX, 0))); - RAW_LOG_F(1, "Supported sample rates for tuner:"); + RAW_LOG_F(2, "Supported sample rates for tuner:"); for (long rate : srates) - RAW_LOG_F(1, "\t%li", rate); + RAW_LOG_F(2, "\t%li", rate); - _selectedTuner.config.sampleRate = nearestSampleRate(DEFAULT_TUNER_SAMPLE_RATE, srates); // TODO hardcoded sample rate temporary + _selectedTuner.config.sampleRate = nearestSampleRate(_selectedTuner.config.sampleRate, srates); // TODO hardcoded sample rate temporary LOG_F(INFO, "Auto selected: %s", _selectedTuner.device->getName().c_str()); diff --git a/src/sigproc/TunerManager.h b/src/sigproc/TunerManager.h index 277bd5b..984783f 100644 --- a/src/sigproc/TunerManager.h +++ b/src/sigproc/TunerManager.h @@ -3,7 +3,6 @@ #include #include #include -#include #include "Configuration.h" @@ -12,13 +11,6 @@ class SDRDeviceInfo; namespace piscan { namespace sigproc { - class TunerComparator : public std::less { - public: - constexpr bool operator()(piscan::config::TunerConfig& left, piscan::config::TunerConfig& right) const { - return left.rank < right.rank; - } - }; - struct ConfiguredTuner { piscan::config::TunerConfig config; // TODO may be changed to ref or shared_ptr SDRDeviceInfo* device; @@ -43,7 +35,6 @@ namespace sigproc { private: std::shared_ptr _cubic; std::unordered_map _devs; - std::priority_queue, TunerComparator> _savedTuners; ConfiguredTuner _selectedTuner; }; }