mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2024-11-26 13:48:38 -05:00
Save/Load and persist SoapySDR device settings
This commit is contained in:
parent
f91a508da6
commit
571ccd3f48
@ -47,6 +47,14 @@ void DeviceConfig::save(DataNode *node) {
|
||||
*node->newChild("id") = deviceId;
|
||||
*node->newChild("ppm") = (int)ppm;
|
||||
*node->newChild("offset") = offset;
|
||||
DataNode *streamOptsNode = node->newChild("streamOpts");
|
||||
for (ConfigSettings::const_iterator opt_i = streamOpts.begin(); opt_i != streamOpts.end(); opt_i++) {
|
||||
*streamOptsNode->newChild(opt_i->first.c_str()) = opt_i->second;
|
||||
}
|
||||
DataNode *settingsNode = node->newChild("settings");
|
||||
for (ConfigSettings::const_iterator set_i = settings.begin(); set_i != settings.end(); set_i++) {
|
||||
*settingsNode->newChild(set_i->first.c_str()) = set_i->second;
|
||||
}
|
||||
busy_lock.unlock();
|
||||
}
|
||||
|
||||
@ -66,9 +74,73 @@ void DeviceConfig::load(DataNode *node) {
|
||||
setOffset(offsetValue);
|
||||
std::cout << "Loaded offset for device '" << deviceId << "' at " << offsetValue << "Hz" << std::endl;
|
||||
}
|
||||
if (node->hasAnother("streamOpts")) {
|
||||
DataNode *streamOptsNode = node->getNext("streamOpts");
|
||||
for (int i = 0, iMax = streamOptsNode->numChildren(); i<iMax; i++) {
|
||||
DataNode *streamOptNode = streamOptsNode->child(i);
|
||||
std::string keyName = streamOptNode->getName();
|
||||
std::string strSettingValue = streamOptNode->element()->toString();
|
||||
|
||||
if (keyName != "" && strSettingValue != "") {
|
||||
setStreamOpt(keyName, strSettingValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node->hasAnother("settings")) {
|
||||
DataNode *settingsNode = node->getNext("settings");
|
||||
for (int i = 0, iMax = settingsNode->numChildren(); i<iMax; i++) {
|
||||
DataNode *settingNode = settingsNode->child(i);
|
||||
std::string keyName = settingNode->getName();
|
||||
std::string strSettingValue = settingNode->element()->toString();
|
||||
|
||||
if (keyName != "" && strSettingValue != "") {
|
||||
setSetting(keyName, strSettingValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
busy_lock.unlock();
|
||||
}
|
||||
|
||||
void DeviceConfig::setStreamOpts(ConfigSettings opts) {
|
||||
streamOpts = opts;
|
||||
}
|
||||
|
||||
ConfigSettings DeviceConfig::getStreamOpts() {
|
||||
return streamOpts;
|
||||
}
|
||||
|
||||
void DeviceConfig::setStreamOpt(std::string key, std::string value) {
|
||||
streamOpts[key] = value;
|
||||
}
|
||||
|
||||
std::string DeviceConfig::getStreamOpt(std::string key, std::string defaultValue) {
|
||||
if (streamOpts.find(key) == streamOpts.end()) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return streamOpts[key];
|
||||
}
|
||||
|
||||
void DeviceConfig::setSettings(ConfigSettings settings) {
|
||||
this->settings = settings;
|
||||
}
|
||||
|
||||
void DeviceConfig::setSetting(std::string key, std::string value) {
|
||||
this->settings[key] = value;
|
||||
}
|
||||
|
||||
std::string DeviceConfig::getSetting(std::string key, std::string defaultValue) {
|
||||
if (settings.find(key) == settings.end()) {
|
||||
return defaultValue;
|
||||
}
|
||||
return settings[key];
|
||||
}
|
||||
|
||||
ConfigSettings DeviceConfig::getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
|
||||
AppConfig::AppConfig() : configName("") {
|
||||
winX.store(0);
|
||||
winY.store(0);
|
||||
@ -82,8 +154,6 @@ AppConfig::AppConfig() : configName("") {
|
||||
spectrumAvgSpeed.store(0.65f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
DeviceConfig *AppConfig::getDevice(std::string deviceId) {
|
||||
if (deviceConfig.find(deviceId) == deviceConfig.end()) {
|
||||
deviceConfig[deviceId] = new DeviceConfig();
|
||||
@ -135,7 +205,6 @@ wxRect *AppConfig::getWindow() {
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
void AppConfig::setTheme(int themeId) {
|
||||
this->themeId.store(themeId);
|
||||
}
|
||||
|
@ -9,6 +9,8 @@
|
||||
|
||||
#include "DataTree.h"
|
||||
|
||||
typedef std::map<std::string, std::string> ConfigSettings;
|
||||
|
||||
class DeviceConfig {
|
||||
public:
|
||||
DeviceConfig();
|
||||
@ -23,6 +25,16 @@ public:
|
||||
void setDeviceId(std::string deviceId);
|
||||
std::string getDeviceId();
|
||||
|
||||
void setStreamOpts(ConfigSettings opts);
|
||||
ConfigSettings getStreamOpts();
|
||||
void setStreamOpt(std::string key, std::string value);
|
||||
std::string getStreamOpt(std::string key, std::string defaultValue);
|
||||
|
||||
void setSettings(ConfigSettings settings);
|
||||
ConfigSettings getSettings();
|
||||
void setSetting(std::string key, std::string value);
|
||||
std::string getSetting(std::string key, std::string defaultValue);
|
||||
|
||||
void save(DataNode *node);
|
||||
void load(DataNode *node);
|
||||
|
||||
@ -32,6 +44,8 @@ private:
|
||||
|
||||
std::atomic_int ppm;
|
||||
std::atomic_llong offset;
|
||||
ConfigSettings streamOpts;
|
||||
std::map<std::string, std::string> settings;
|
||||
};
|
||||
|
||||
class AppConfig {
|
||||
|
@ -1238,25 +1238,7 @@ bool AppFrame::loadSession(std::string fileName) {
|
||||
for (int msi = 0, numSettings = modemSettings->numChildren(); msi < numSettings; msi++) {
|
||||
DataNode *settingNode = modemSettings->child(msi);
|
||||
std::string keyName = settingNode->getName();
|
||||
std::string strSettingValue = "";
|
||||
|
||||
int dataType = settingNode->element()->getDataType();
|
||||
|
||||
try {
|
||||
if (dataType == DATA_STRING) {
|
||||
settingNode->element()->get(strSettingValue);
|
||||
} else if (dataType == DATA_INT || dataType == DATA_LONG || dataType == DATA_LONGLONG) {
|
||||
long long intSettingValue = *settingNode;
|
||||
strSettingValue = std::to_string(intSettingValue);
|
||||
} else if (dataType == DATA_FLOAT || dataType == DATA_DOUBLE) {
|
||||
double floatSettingValue = *settingNode;
|
||||
strSettingValue = std::to_string(floatSettingValue);
|
||||
} else {
|
||||
std::cout << "Unhandled setting data type: " << dataType << std::endl;
|
||||
}
|
||||
} catch (DataTypeMismatchException e) {
|
||||
std::cout << "Setting data type mismatch: " << dataType << std::endl;
|
||||
}
|
||||
std::string strSettingValue = settingNode->element()->toString();
|
||||
|
||||
if (keyName != "" && strSettingValue != "") {
|
||||
mSettings[keyName] = strSettingValue;
|
||||
|
@ -109,6 +109,16 @@ void SDRDevicesDialog::OnSelectionChanged( wxTreeEvent& event ) {
|
||||
|
||||
if (dev->getRxChannel()) {
|
||||
args = dev->getRxChannel()->getStreamArgsInfo();
|
||||
|
||||
DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(dev->getDeviceId());
|
||||
ConfigSettings devStreamOpts = devConfig->getStreamOpts();
|
||||
if (devStreamOpts.size()) {
|
||||
for (int j = 0, jMax = args.size(); j < jMax; j++) {
|
||||
if (devStreamOpts.find(args[j].key) != devStreamOpts.end()) {
|
||||
args[j].value = devStreamOpts[args[j].key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (args.size()) {
|
||||
m_propertyGrid->Append(new wxPropertyCategory("Stream Settings"));
|
||||
@ -202,7 +212,10 @@ void SDRDevicesDialog::OnUseSelected( wxMouseEvent& event ) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AppConfig *cfg = wxGetApp().getConfig();
|
||||
DeviceConfig *devConfig = cfg->getDevice(dev->getDeviceId());
|
||||
devConfig->setSettings(settingArgs);
|
||||
devConfig->setStreamOpts(streamArgs);
|
||||
wxGetApp().setDeviceArgs(settingArgs);
|
||||
wxGetApp().setStreamArgs(streamArgs);
|
||||
wxGetApp().setDevice(dev);
|
||||
|
@ -141,6 +141,8 @@ std::vector<SDRDeviceInfo *> *SDREnumerator::enumerate_devices(std::string remot
|
||||
}
|
||||
}
|
||||
|
||||
DeviceConfig *cfg = wxGetApp().getConfig()->getDevice(dev->getDeviceId());
|
||||
|
||||
if (deviceArgs.count("remote")) {
|
||||
isRemote = true;
|
||||
} else {
|
||||
@ -148,12 +150,10 @@ std::vector<SDRDeviceInfo *> *SDREnumerator::enumerate_devices(std::string remot
|
||||
}
|
||||
|
||||
dev->setRemote(isRemote);
|
||||
|
||||
dev->setDeviceArgs(deviceArgs);
|
||||
|
||||
std::cout << "Make device " << i << std::endl;
|
||||
try {
|
||||
SoapySDR::Device *device = SoapySDR::Device::make(dev->getDeviceArgs());
|
||||
SoapySDR::Device *device = SoapySDR::Device::make(deviceArgs);
|
||||
SoapySDR::Kwargs info = device->getHardwareInfo();
|
||||
for (SoapySDR::Kwargs::const_iterator it = info.begin(); it != info.end(); ++it) {
|
||||
std::cout << " " << it->first << "=" << it->second << std::endl;
|
||||
@ -167,7 +167,24 @@ std::vector<SDRDeviceInfo *> *SDREnumerator::enumerate_devices(std::string remot
|
||||
} else {
|
||||
wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Querying device #") + std::to_string(i) + ": " + dev->getName());
|
||||
}
|
||||
|
||||
SoapySDR::ArgInfoList settingsInfo = device->getSettingInfo();
|
||||
|
||||
ConfigSettings devSettings = cfg->getSettings();
|
||||
if (devSettings.size()) {
|
||||
for (ConfigSettings::const_iterator set_i = devSettings.begin(); set_i != devSettings.end(); set_i++) {
|
||||
deviceArgs[set_i->first] = set_i->second;
|
||||
}
|
||||
for (int j = 0; j < settingsInfo.size(); j++) {
|
||||
if (deviceArgs.find(settingsInfo[j].key) != deviceArgs.end()) {
|
||||
settingsInfo[j].value = deviceArgs[settingsInfo[j].key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dev->setDeviceArgs(deviceArgs);
|
||||
dev->setSettingsInfo(settingsInfo);
|
||||
|
||||
int numChan = device->getNumChannels(SOAPY_SDR_RX);
|
||||
for (int i = 0; i < numChan; i++) {
|
||||
SDRDeviceChannel *chan = new SDRDeviceChannel();
|
||||
@ -200,7 +217,21 @@ std::vector<SDRDeviceInfo *> *SDREnumerator::enumerate_devices(std::string remot
|
||||
chan->getSampleRates().push_back((long)(*i));
|
||||
}
|
||||
|
||||
chan->setStreamArgsInfo(device->getStreamArgsInfo(SOAPY_SDR_RX, i));
|
||||
ConfigSettings devStreamOpts = cfg->getStreamOpts();
|
||||
if (devStreamOpts.size()) {
|
||||
dev->setStreamArgs(devStreamOpts);
|
||||
}
|
||||
|
||||
SoapySDR::ArgInfoList optArgs = device->getStreamArgsInfo(SOAPY_SDR_RX, i);
|
||||
|
||||
if (devStreamOpts.size()) {
|
||||
for (int j = 0, jMax = optArgs.size(); j < jMax; j++) {
|
||||
if (devStreamOpts.find(optArgs[j].key) != devStreamOpts.end()) {
|
||||
optArgs[j].value = devStreamOpts[optArgs[j].key];
|
||||
}
|
||||
}
|
||||
}
|
||||
chan->setStreamArgsInfo(optArgs);
|
||||
|
||||
std::vector<std::string> gainNames = device->listGains(SOAPY_SDR_RX, i);
|
||||
|
||||
@ -211,8 +242,6 @@ std::vector<SDRDeviceInfo *> *SDREnumerator::enumerate_devices(std::string remot
|
||||
dev->addChannel(chan);
|
||||
}
|
||||
|
||||
dev->setSettingsInfo(device->getSettingInfo());
|
||||
|
||||
SoapySDR::Device::unmake(device);
|
||||
|
||||
dev->setAvailable(true);
|
||||
|
@ -66,7 +66,10 @@ void SDRThread::init() {
|
||||
|
||||
wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Initializing device."));
|
||||
device = SoapySDR::Device::make(args);
|
||||
stream = device->setupStream(SOAPY_SDR_RX,"CF32", std::vector<size_t>(), combineArgs(devInfo->getStreamArgs(),streamArgs));
|
||||
SoapySDR::Kwargs currentStreamArgs = combineArgs(devInfo->getStreamArgs(),streamArgs);
|
||||
stream = device->setupStream(SOAPY_SDR_RX,"CF32", std::vector<size_t>(), currentStreamArgs);
|
||||
deviceInfo.load()->setStreamArgs(currentStreamArgs);
|
||||
deviceConfig.load()->setStreamOpts(currentStreamArgs);
|
||||
|
||||
wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Activating stream."));
|
||||
device->setSampleRate(SOAPY_SDR_RX,0,sampleRate.load());
|
||||
@ -115,6 +118,17 @@ void SDRThread::init() {
|
||||
}
|
||||
}
|
||||
setting_value_changed.store(false);
|
||||
|
||||
SoapySDR::ArgInfoList devSettings = deviceInfo.load()->getSettingsArgInfo();
|
||||
if (devSettings.size()) {
|
||||
for (int j = 0; j < settingsInfo.size(); j++) {
|
||||
if (settings.find(settingsInfo[j].key) != settings.end()) {
|
||||
devSettings[j].value = settings[devSettings[j].key];
|
||||
}
|
||||
}
|
||||
}
|
||||
deviceInfo.load()->setSettingsInfo(devSettings);
|
||||
|
||||
setting_busy.unlock();
|
||||
|
||||
wxGetApp().sdrThreadNotify(SDRThread::SDR_THREAD_INITIALIZED, std::string("Device Initialized."));
|
||||
@ -404,6 +418,9 @@ void SDRThread::writeSetting(std::string name, std::string value) {
|
||||
settings[name] = value;
|
||||
settingChanged[name] = true;
|
||||
setting_value_changed.store(true);
|
||||
if (deviceConfig.load() != nullptr) {
|
||||
deviceConfig.load()->setSetting(name, value);
|
||||
}
|
||||
setting_busy.unlock();
|
||||
}
|
||||
|
||||
|
@ -356,6 +356,31 @@ DataElementGetNumericVectorDef(DATA_FLOAT_VECTOR, float, DATA_DOUBLE_VECTOR, DAT
|
||||
DataElementGetNumericVectorDef(DATA_DOUBLE_VECTOR, double, DATA_FLOAT_VECTOR, DATA_LONGDOUBLE_VECTOR);
|
||||
DataElementGetNumericVectorDef(DATA_LONGDOUBLE_VECTOR, long double, DATA_DOUBLE_VECTOR, DATA_FLOAT_VECTOR);
|
||||
|
||||
std::string DataElement::toString() {
|
||||
int dataType = getDataType();
|
||||
std::string strValue = "";
|
||||
|
||||
try {
|
||||
if (dataType == DATA_STRING) {
|
||||
get(strValue);
|
||||
} else if (dataType == DATA_INT || dataType == DATA_LONG || dataType == DATA_LONGLONG) {
|
||||
long long intSettingValue;
|
||||
get(intSettingValue);
|
||||
strValue = std::to_string(intSettingValue);
|
||||
} else if (dataType == DATA_FLOAT || dataType == DATA_DOUBLE) {
|
||||
double floatSettingValue;
|
||||
get(floatSettingValue);
|
||||
strValue = std::to_string(floatSettingValue);
|
||||
} else {
|
||||
std::cout << "Unhandled DataElement toString for type: " << dataType << std::endl;
|
||||
}
|
||||
} catch (DataTypeMismatchException e) {
|
||||
std::cout << "toString() DataTypeMismatch: " << dataType << std::endl;
|
||||
}
|
||||
|
||||
return strValue;
|
||||
}
|
||||
|
||||
|
||||
long DataElement::getSerializedSize() {
|
||||
return sizeof(int) + sizeof(long) + data_size;
|
||||
|
@ -207,6 +207,7 @@ public:
|
||||
double getDouble() throw (DataTypeMismatchException) { double d_get; get(d_get); return d_get; };
|
||||
long double getLongDouble() throw (DataTypeMismatchException) { long double d_get; get(d_get); return d_get; };
|
||||
|
||||
std::string toString();
|
||||
|
||||
/* serialize functions */
|
||||
long getSerializedSize();
|
||||
|
Loading…
Reference in New Issue
Block a user