1 // Copyright (c) Charles J. Cliffe
2 // SPDX-License-Identifier: GPL-2.0+
3 
4 #include "AppConfig.h"
5 #include "CubicSDR.h"
6 
7 #include <wx/msgdlg.h>
8 
DeviceConfig()9 DeviceConfig::DeviceConfig() {
10 	ppm.store(0);
11 	offset.store(0);
12     agcMode.store(true);
13     sampleRate.store(0);
14 }
15 
DeviceConfig(std::string deviceId_in)16 DeviceConfig::DeviceConfig(std::string deviceId_in) : DeviceConfig() {
17     deviceId = deviceId_in;
18 }
19 
setPPM(int ppm_in)20 void DeviceConfig::setPPM(int ppm_in) {
21     ppm.store(ppm_in);
22 }
23 
getPPM()24 int DeviceConfig::getPPM() {
25     return ppm.load();
26 }
27 
setOffset(long long offset_in)28 void DeviceConfig::setOffset(long long offset_in) {
29     offset.store(offset_in);
30 }
31 
getOffset()32 long long DeviceConfig::getOffset() {
33     return offset.load();
34 }
35 
setSampleRate(long sampleRate_in)36 void DeviceConfig::setSampleRate(long sampleRate_in) {
37     sampleRate.store(sampleRate_in);
38 }
39 
getSampleRate()40 long DeviceConfig::getSampleRate() {
41     return sampleRate.load();
42 }
43 
setAntennaName(const std::string & name)44 void DeviceConfig::setAntennaName(const std::string& name) {
45     antennaName = name;
46 }
47 
getAntennaName()48 const std::string& DeviceConfig::getAntennaName() {
49     return antennaName;
50 }
51 
setAGCMode(bool agcMode_in)52 void DeviceConfig::setAGCMode(bool agcMode_in) {
53     agcMode.store(agcMode_in);
54 }
55 
getAGCMode()56 bool DeviceConfig::getAGCMode() {
57     return agcMode.load();
58 }
59 
60 
setDeviceId(std::string deviceId_in)61 void DeviceConfig::setDeviceId(std::string deviceId_in) {
62     std::lock_guard < std::mutex > lock(busy_lock);
63     deviceId = deviceId_in;
64 
65 }
66 
getDeviceId()67 std::string DeviceConfig::getDeviceId() {
68     std::string tmp;
69 
70     std::lock_guard < std::mutex > lock(busy_lock);
71     tmp = deviceId;
72 
73 
74     return tmp;
75 }
76 
setDeviceName(std::string deviceName_in)77 void DeviceConfig::setDeviceName(std::string deviceName_in) {
78     std::lock_guard < std::mutex > lock(busy_lock);
79     deviceName = deviceName_in;
80 }
81 
getDeviceName()82 std::string DeviceConfig::getDeviceName() {
83     std::string tmp;
84 
85     std::lock_guard < std::mutex > lock(busy_lock);
86     tmp = deviceName.empty()?deviceId:deviceName;
87 
88     return tmp;
89 }
90 
save(DataNode * node)91 void DeviceConfig::save(DataNode *node) {
92 
93     std::lock_guard < std::mutex > lock(busy_lock);
94 
95     *node->newChild("id") = deviceId;
96     *node->newChild("name") = deviceName;
97     *node->newChild("ppm") = ppm.load();
98     *node->newChild("offset") = offset.load();
99     *node->newChild("sample_rate") = sampleRate.load();
100     *node->newChild("agc_mode") = agcMode.load()?1:0;
101 
102     if (!antennaName.empty()) {
103         *node->newChild("antenna") = antennaName;
104     }
105 
106     if (!streamOpts.empty()) {
107         DataNode *streamOptsNode = node->newChild("streamOpts");
108         for (ConfigSettings::const_iterator opt_i = streamOpts.begin(); opt_i != streamOpts.end(); opt_i++) {
109             *streamOptsNode->newChild(opt_i->first.c_str()) = opt_i->second;
110         }
111     }
112     if (!settings.empty()) {
113         DataNode *settingsNode = node->newChild("settings");
114         for (ConfigSettings::const_iterator set_i = settings.begin(); set_i != settings.end(); set_i++) {
115             *settingsNode->newChild(set_i->first.c_str()) = set_i->second;
116         }
117     }
118     if (!rigIF.empty()) {
119         DataNode *rigIFs = node->newChild("rig_ifs");
120         for (std::map<int, long long>::const_iterator rigIF_i = rigIF.begin(); rigIF_i != rigIF.end(); rigIF_i++) {
121             DataNode *ifNode = rigIFs->newChild("rig_if");
122             *ifNode->newChild("model") = rigIF_i->first;
123             *ifNode->newChild("sdr_if") = rigIF_i->second;
124         }
125     }
126     if (!gains.empty()) {
127         DataNode *gainsNode = node->newChild("gains");
128         for (ConfigGains::const_iterator gain_i = gains.begin(); gain_i != gains.end(); gain_i++) {
129             DataNode *gainNode = gainsNode->newChild("gain");
130             *gainNode->newChild("id") = gain_i->first;
131             *gainNode->newChild("value") = gain_i->second;
132         }
133     }
134 
135 }
136 
load(DataNode * node)137 void DeviceConfig::load(DataNode *node) {
138     std::lock_guard < std::mutex > lock(busy_lock);
139     if (node->hasAnother("name")) {
140         deviceName = node->getNext("name")->element()->toString();
141     }
142     if (node->hasAnother("ppm")) {
143         DataNode *ppm_node = node->getNext("ppm");
144         int ppmValue = 0;
145         ppm_node->element()->get(ppmValue);
146         setPPM(ppmValue);
147     }
148     if (node->hasAnother("offset")) {
149         DataNode *offset_node = node->getNext("offset");
150         long long offsetValue = 0;
151         offset_node->element()->get(offsetValue);
152         setOffset(offsetValue);
153     }
154     if (node->hasAnother("agc_mode")) {
155         DataNode *agc_node = node->getNext("agc_mode");
156         int agcModeValue = 0;
157         agc_node->element()->get(agcModeValue);
158         setAGCMode(agcModeValue != 0);
159     }
160     if (node->hasAnother("sample_rate")) {
161         DataNode *sample_rate_node = node->getNext("sample_rate");
162         long sampleRateValue = 0;
163         sample_rate_node->element()->get(sampleRateValue);
164         setSampleRate(sampleRateValue);
165     }
166     if (node->hasAnother("antenna")) {
167         DataNode *antenna_node = node->getNext("antenna");
168         std::string antennaNameValue;
169         antenna_node->element()->get(antennaNameValue);
170         setAntennaName(antennaNameValue);
171     }
172     if (node->hasAnother("streamOpts")) {
173         DataNode *streamOptsNode = node->getNext("streamOpts");
174         for (int i = 0, iMax = streamOptsNode->numChildren(); i<iMax; i++) {
175             DataNode *streamOptNode = streamOptsNode->child(i);
176             std::string keyName = streamOptNode->getName();
177             std::string strSettingValue = streamOptNode->element()->toString();
178 
179             if (!keyName.empty()) {
180                 setStreamOpt(keyName, strSettingValue);
181             }
182         }
183     }
184     if (node->hasAnother("settings")) {
185         DataNode *settingsNode = node->getNext("settings");
186         for (int i = 0, iMax = settingsNode->numChildren(); i<iMax; i++) {
187             DataNode *settingNode = settingsNode->child(i);
188             std::string keyName = settingNode->getName();
189             std::string strSettingValue = settingNode->element()->toString();
190 
191             if (!keyName.empty()) {
192                 setSetting(keyName, strSettingValue);
193             }
194         }
195     }
196     if (node->hasAnother("rig_ifs")) {
197         DataNode *rigIFNodes = node->getNext("rig_ifs");
198         while (rigIFNodes->hasAnother("rig_if")) {
199             DataNode *rigIFNode = rigIFNodes->getNext("rig_if");
200             if (rigIFNode->hasAnother("model") && rigIFNode->hasAnother("sdr_if")) {
201                 int load_model;
202                 long long load_freq = 0;
203 
204                 rigIFNode->getNext("model")->element()->get(load_model);
205                 rigIFNode->getNext("sdr_if")->element()->get(load_freq);
206 
207                 rigIF[load_model] = load_freq;
208             }
209         }
210     }
211     if (node->hasAnother("gains")) {
212         DataNode *gainsNode = node->getNext("gains");
213         while (gainsNode->hasAnother("gain")) {
214             DataNode *gainNode = gainsNode->getNext("gain");
215             std::string keyName;
216             float fltSettingValue = 0;
217 
218             gainNode->getNext("id")->element()->get(keyName);
219             gainNode->getNext("value")->element()->get(fltSettingValue);
220 
221             if (!keyName.empty() && !(fltSettingValue!=fltSettingValue)) {
222                 setGain(keyName, fltSettingValue);
223             }
224         }
225     }
226 
227 }
228 
setStreamOpts(ConfigSettings opts)229 void DeviceConfig::setStreamOpts(ConfigSettings opts) {
230     streamOpts = opts;
231 }
232 
getStreamOpts()233 ConfigSettings DeviceConfig::getStreamOpts() {
234     return streamOpts;
235 }
236 
setStreamOpt(const std::string & key,std::string value)237 void DeviceConfig::setStreamOpt(const std::string& key, std::string value) {
238     streamOpts[key] = value;
239 }
240 
getStreamOpt(const std::string & key,std::string defaultValue)241 std::string DeviceConfig::getStreamOpt(const std::string& key, std::string defaultValue) {
242     if (streamOpts.find(key) == streamOpts.end()) {
243         return defaultValue;
244     }
245 
246     return streamOpts[key];
247 }
248 
setSettings(ConfigSettings settings_in)249 void DeviceConfig::setSettings(ConfigSettings settings_in) {
250     settings = settings_in;
251 }
252 
setSetting(const std::string & key,std::string value)253 void DeviceConfig::setSetting(const std::string& key, std::string value) {
254     settings[key] = value;
255 }
256 
getSetting(const std::string & key,std::string defaultValue)257 std::string DeviceConfig::getSetting(const std::string& key, std::string defaultValue) {
258     if (settings.find(key) == settings.end()) {
259         return defaultValue;
260     }
261     return settings[key];
262 }
263 
getSettings()264 ConfigSettings DeviceConfig::getSettings() {
265     return settings;
266 }
267 
268 
setGains(ConfigGains gains_in)269 void DeviceConfig::setGains(ConfigGains gains_in) {
270     gains = gains_in;
271 }
272 
getGains()273 ConfigGains DeviceConfig::getGains() {
274     return gains;
275 }
276 
setGain(const std::string & key,float value)277 void DeviceConfig::setGain(const std::string& key, float value) {
278     gains[key] = value;
279 }
280 
getGain(const std::string & key,float defaultValue)281 float DeviceConfig::getGain(const std::string& key, float defaultValue) {
282     if (gains.find(key) != gains.end()) {
283         return gains[key];
284     }
285     return defaultValue;
286 }
287 
288 
setRigIF(int rigType,long long freq)289 void DeviceConfig::setRigIF(int rigType, long long freq) {
290     rigIF[rigType] = freq;
291 }
292 
getRigIF(int rigType)293 long long DeviceConfig::getRigIF(int rigType) {
294     if (rigIF.find(rigType) != rigIF.end()) {
295         return rigIF[rigType];
296     }
297     return 0;
298 }
299 
AppConfig()300 AppConfig::AppConfig() {
301     winX.store(0);
302     winY.store(0);
303     winW.store(0);
304     winH.store(0);
305     winMax.store(false);
306     showTips.store(true);
307     perfMode.store(PERF_NORMAL);
308     themeId.store(0);
309     fontScale.store(0);
310     snap.store(1);
311     centerFreq.store(100000000);
312     waterfallLinesPerSec.store(DEFAULT_WATERFALL_LPS);
313     spectrumAvgSpeed.store(0.65f);
314     dbOffset.store(0);
315     modemPropsCollapsed.store(false);
316     mainSplit = -1;
317     visSplit = -1;
318     bookmarkSplit = 200;
319 #ifdef CUBICSDR_DEFAULT_HIDE_BOOKMARKS
320     bookmarksVisible.store(false);
321 #else
322     bookmarksVisible.store(true);
323 #endif
324 
325 #ifdef USE_HAMLIB
326     rigEnabled.store(false);
327     rigModel.store(1);
328     rigRate.store(57600);
329     rigPort = "/dev/ttyUSB0";
330     rigControlMode.store(true);
331     rigFollowMode.store(true);
332 #endif
333 }
334 
getDevice(const std::string & deviceId)335 DeviceConfig *AppConfig::getDevice(const std::string& deviceId) {
336 	if (deviceConfig.find(deviceId) == deviceConfig.end()) {
337 		deviceConfig[deviceId] = new DeviceConfig();
338 	}
339     DeviceConfig *conf = deviceConfig[deviceId];
340     conf->setDeviceId(deviceId);
341     return conf;
342 }
343 
getConfigDir()344 std::string AppConfig::getConfigDir() {
345     std::string dataDir = wxStandardPaths::Get().GetUserDataDir().ToStdString();
346 
347     bool mkStatus = false;
348 
349     if (!wxDir::Exists(dataDir)) {
350         mkStatus = wxDir::Make(dataDir);
351     } else {
352         mkStatus = true;
353     }
354 
355     if (!mkStatus) {
356         std::cout << "Warning, unable to initialize user data directory." << std::endl;
357     }
358 
359     return dataDir;
360 }
361 
362 
setWindow(wxPoint winXY,wxSize winWH)363 void AppConfig::setWindow(wxPoint winXY, wxSize winWH) {
364     winX.store(winXY.x);
365     winY.store(winXY.y);
366     winW.store(winWH.x);
367     winH.store(winWH.y);
368 }
369 
setWindowMaximized(bool max)370 void AppConfig::setWindowMaximized(bool max) {
371     winMax.store(max);
372 }
373 
getWindowMaximized()374 bool AppConfig::getWindowMaximized() {
375     return winMax.load();
376 }
377 
setModemPropsCollapsed(bool collapse)378 void AppConfig::setModemPropsCollapsed(bool collapse) {
379     modemPropsCollapsed.store(collapse);
380 }
381 
getModemPropsCollapsed()382 bool AppConfig::getModemPropsCollapsed() {
383     return modemPropsCollapsed.load();
384 }
385 
setShowTips(bool show)386 void AppConfig::setShowTips(bool show) {
387     showTips.store(show);
388 }
389 
getShowTips()390 bool AppConfig::getShowTips() {
391     return showTips.load();
392 }
393 
setPerfMode(PerfModeEnum show)394 void AppConfig::setPerfMode(PerfModeEnum show) {
395     perfMode.store(show);
396 }
397 
getPerfMode()398 AppConfig::PerfModeEnum AppConfig::getPerfMode() {
399     return perfMode.load();
400 }
401 
getWindow()402 wxRect *AppConfig::getWindow() {
403     wxRect *r = nullptr;
404     if (winH.load() && winW.load()) {
405         r = new wxRect(winX.load(),winY.load(),winW.load(),winH.load());
406     }
407     return r;
408 }
409 
setTheme(int themeId_in)410 void AppConfig::setTheme(int themeId_in) {
411     themeId.store(themeId_in);
412 }
413 
getTheme()414 int AppConfig::getTheme() {
415     return themeId.load();
416 }
417 
setFontScale(int fontScale_in)418 void AppConfig::setFontScale(int fontScale_in) {
419     fontScale.store(fontScale_in);
420 }
421 
getFontScale()422 int AppConfig::getFontScale() {
423     return fontScale.load();
424 }
425 
426 
setSnap(long long snapVal)427 void AppConfig::setSnap(long long snapVal) {
428     this->snap.store(snapVal);
429 }
430 
getSnap()431 long long AppConfig::getSnap() {
432     return snap.load();
433 }
434 
setCenterFreq(long long freqVal)435 void AppConfig::setCenterFreq(long long freqVal) {
436     centerFreq.store(freqVal);
437 }
438 
getCenterFreq()439 long long AppConfig::getCenterFreq() {
440     return centerFreq.load();
441 }
442 
443 
setWaterfallLinesPerSec(int lps)444 void AppConfig::setWaterfallLinesPerSec(int lps) {
445     waterfallLinesPerSec.store(lps);
446 }
447 
getWaterfallLinesPerSec()448 int AppConfig::getWaterfallLinesPerSec() {
449     return waterfallLinesPerSec.load();
450 }
451 
setSpectrumAvgSpeed(float avgSpeed)452 void AppConfig::setSpectrumAvgSpeed(float avgSpeed) {
453     spectrumAvgSpeed.store(avgSpeed);
454 }
455 
getSpectrumAvgSpeed()456 float AppConfig::getSpectrumAvgSpeed() {
457     return spectrumAvgSpeed.load();
458 }
459 
setDBOffset(int offset)460 void AppConfig::setDBOffset(int offset) {
461     this->dbOffset.store(offset);
462 }
463 
getDBOffset()464 int AppConfig::getDBOffset() {
465     return dbOffset.load();
466 }
467 
setManualDevices(std::vector<SDRManualDef> manuals)468 void AppConfig::setManualDevices(std::vector<SDRManualDef> manuals) {
469     manualDevices = manuals;
470 }
471 
getManualDevices()472 std::vector<SDRManualDef> AppConfig::getManualDevices() {
473     return manualDevices;
474 }
475 
setMainSplit(float value)476 void AppConfig::setMainSplit(float value) {
477     mainSplit.store(value);
478 }
479 
getMainSplit()480 float AppConfig::getMainSplit() {
481     return mainSplit.load();
482 }
483 
setVisSplit(float value)484 void AppConfig::setVisSplit(float value) {
485     visSplit.store(value);
486 }
487 
getVisSplit()488 float AppConfig::getVisSplit() {
489     return visSplit.load();
490 }
491 
setBookmarkSplit(float value)492 void AppConfig::setBookmarkSplit(float value) {
493     bookmarkSplit.store(value);
494 }
495 
getBookmarkSplit()496 float AppConfig::getBookmarkSplit() {
497     return bookmarkSplit.load();
498 }
499 
setBookmarksVisible(bool state)500 void AppConfig::setBookmarksVisible(bool state) {
501     bookmarksVisible.store(state);
502 }
503 
getBookmarksVisible()504 bool AppConfig::getBookmarksVisible() {
505     return bookmarksVisible.load();
506 }
507 
setRecordingPath(std::string recPath)508 void AppConfig::setRecordingPath(std::string recPath) {
509     recordingPath = recPath;
510 }
511 
getRecordingPath()512 std::string AppConfig::getRecordingPath() {
513     return recordingPath;
514 }
515 
verifyRecordingPath()516 bool AppConfig::verifyRecordingPath() {
517     string recPathStr = wxGetApp().getConfig()->getRecordingPath();
518 
519     if (recPathStr.empty()) {
520         wxMessageBox( wxT("Recording path is not set.  Please use 'Set Recording Path' from the 'Recording' Menu."), wxT("Recording Path Error"), wxICON_INFORMATION);
521 
522         return false;
523     }
524 
525     wxFileName recPath(recPathStr);
526 
527     if (!recPath.Exists() || !recPath.IsDirWritable()) {
528         wxMessageBox( wxT("Recording path does not exist or is not writable.  Please use 'Set Recording Path' from the 'Recording' Menu."), wxT("Recording Path Error"), wxICON_INFORMATION);
529 
530         return false;
531     }
532 
533     return true;
534 }
535 
536 
setRecordingSquelchOption(int enumChoice)537 void  AppConfig::setRecordingSquelchOption(int enumChoice) {
538 	recordingSquelchOption = enumChoice;
539 }
540 
getRecordingSquelchOption() const541 int  AppConfig::getRecordingSquelchOption() const {
542 	return recordingSquelchOption;
543 }
544 
setRecordingFileTimeLimit(int nbSeconds)545 void  AppConfig::setRecordingFileTimeLimit(int nbSeconds) {
546 	recordingFileTimeLimitSeconds = nbSeconds;
547 }
548 
getRecordingFileTimeLimit() const549 int  AppConfig::getRecordingFileTimeLimit() const {
550 	return recordingFileTimeLimitSeconds;
551 }
552 
553 
setConfigName(std::string configName_in)554 void AppConfig::setConfigName(std::string configName_in) {
555     configName = configName_in;
556 }
557 
getConfigFileName(bool ignoreName)558 std::string AppConfig::getConfigFileName(bool ignoreName) {
559     std::string cfgFileDir = getConfigDir();
560 
561     wxFileName cfgFile;
562     if (configName.length() && !ignoreName) {
563         std::string tempFn("config-");
564         tempFn.append(configName);
565         tempFn.append(".xml");
566         cfgFile = wxFileName(cfgFileDir, tempFn);
567     } else {
568         cfgFile = wxFileName(cfgFileDir, "config.xml");
569     }
570 
571     std::string cfgFileName = cfgFile.GetFullPath(wxPATH_NATIVE).ToStdString();
572 
573     return cfgFileName;
574 }
575 
save()576 bool AppConfig::save() {
577     DataTree cfg;
578 
579     cfg.rootNode()->setName("cubicsdr_config");
580 
581     if (winW.load() && winH.load()) {
582         DataNode *window_node = cfg.rootNode()->newChild("window");
583 
584         *window_node->newChild("x") = winX.load();
585         *window_node->newChild("y") = winY.load();
586         *window_node->newChild("w") = winW.load();
587         *window_node->newChild("h") = winH.load();
588 
589         *window_node->newChild("max") = winMax.load();
590         *window_node->newChild("tips") = showTips.load();
591         *window_node->newChild("perf_mode") = (int)perfMode.load();
592         *window_node->newChild("theme") = themeId.load();
593         *window_node->newChild("font_scale") = fontScale.load();
594         *window_node->newChild("snap") = snap.load();
595         *window_node->newChild("center_freq") = centerFreq.load();
596         *window_node->newChild("waterfall_lps") = waterfallLinesPerSec.load();
597         *window_node->newChild("spectrum_avg") = spectrumAvgSpeed.load();
598         *window_node->newChild("modemprops_collapsed") = modemPropsCollapsed.load();
599         *window_node->newChild("db_offset") = dbOffset.load();
600 
601         *window_node->newChild("main_split") = mainSplit.load();
602         *window_node->newChild("vis_split") = visSplit.load();
603         *window_node->newChild("bookmark_split") = bookmarkSplit.load();
604         *window_node->newChild("bookmark_visible") = bookmarksVisible.load();
605     }
606 
607 	//Recording settings:
608     DataNode *rec_node = cfg.rootNode()->newChild("recording");
609     *rec_node->newChild("path") = recordingPath;
610 	*rec_node->newChild("squelch") = recordingSquelchOption;
611 	*rec_node->newChild("file_time_limit") = recordingFileTimeLimitSeconds;
612 
613     DataNode *devices_node = cfg.rootNode()->newChild("devices");
614 
615     std::map<std::string, DeviceConfig *>::iterator device_config_i;
616     for (device_config_i = deviceConfig.begin(); device_config_i != deviceConfig.end(); device_config_i++) {
617         DataNode *device_node = devices_node->newChild("device");
618         device_config_i->second->save(device_node);
619     }
620 
621     if (!manualDevices.empty()) {
622         DataNode *manual_node = cfg.rootNode()->newChild("manual_devices");
623         for (const auto & manualDevice : manualDevices) {
624             DataNode *rig_node = manual_node->newChild("device");
625             *rig_node->newChild("factory") = manualDevice.factory;
626             *rig_node->newChild("params") = manualDevice.params;
627         }
628     }
629 
630 #ifdef USE_HAMLIB
631     DataNode *rig_node = cfg.rootNode()->newChild("rig");
632     *rig_node->newChild("enabled") = rigEnabled.load()?1:0;
633     *rig_node->newChild("model") = rigModel.load();
634     *rig_node->newChild("rate") = rigRate.load();
635     *rig_node->newChild("port") = rigPort;
636     *rig_node->newChild("control") = rigControlMode.load()?1:0;
637     *rig_node->newChild("follow") = rigFollowMode.load()?1:0;
638     *rig_node->newChild("center_lock") = rigCenterLock.load()?1:0;
639     *rig_node->newChild("follow_modem") = rigFollowModem.load()?1:0;
640 #endif
641 
642     std::string cfgFileName = getConfigFileName();
643 
644     if (!cfg.SaveToFileXML(cfgFileName)) {
645         std::cout << "Error saving :: configuration file '" << cfgFileName << "' is not writable!" << std::endl;
646         return false;
647     }
648 
649     return true;
650 }
651 
load()652 bool AppConfig::load() {
653     DataTree cfg;
654     std::string cfgFileDir = getConfigDir();
655 
656     std::string cfgFileName = getConfigFileName();
657     wxFileName cfgFile = wxFileName(cfgFileName);
658 
659     if (!cfgFile.Exists()) {
660         if (configName.length()) {
661             wxFileName baseConfig = wxFileName(getConfigFileName(true));
662             if (baseConfig.Exists()) {
663                 std::string baseConfigFileName = baseConfig.GetFullPath(wxPATH_NATIVE).ToStdString();
664                 std::cout << "Creating new configuration file '" << cfgFileName << "' by copying '" << baseConfigFileName << "'..";
665                 wxCopyFile(baseConfigFileName, cfgFileName);
666                 if (!cfgFile.Exists()) {
667                     std::cout << "failed." << std::endl;
668                     return true;
669                 }
670                 std::cout << "ok." << std::endl;
671             } else {
672                 return true;
673             }
674         } else {
675             return true;
676         }
677     }
678 
679     if (cfgFile.IsFileReadable()) {
680         std::cout << "Loading:: configuration file '" << cfgFileName << "'" << std::endl;
681 
682         cfg.LoadFromFileXML(cfgFileName);
683     } else {
684         std::cout << "Error loading:: configuration file '" << cfgFileName << "' is not readable!" << std::endl;
685         return false;
686     }
687 
688     if (cfg.rootNode()->hasAnother("window")) {
689         int x = 0 ,y = 0 ,w = 0 ,h = 0;
690         int max = 0 ,tips = 0 ,perf_mode = 0 ,mpc = 0;
691 
692         DataNode *win_node = cfg.rootNode()->getNext("window");
693 
694         if (win_node->hasAnother("w") && win_node->hasAnother("h") && win_node->hasAnother("x") && win_node->hasAnother("y")) {
695 
696             win_node->getNext("x")->element()->get(x);
697             win_node->getNext("y")->element()->get(y);
698             win_node->getNext("w")->element()->get(w);
699             win_node->getNext("h")->element()->get(h);
700 
701             winX.store(x);
702             winY.store(y);
703             winW.store(w);
704             winH.store(h);
705         }
706 
707         if (win_node->hasAnother("max")) {
708             win_node->getNext("max")->element()->get(max);
709             winMax.store(max != 0);
710         }
711 
712         if (win_node->hasAnother("tips")) {
713             win_node->getNext("tips")->element()->get(tips);
714             showTips.store(tips != 0);
715         }
716 
717         // default:
718         perfMode.store(PERF_NORMAL);
719 
720         if (win_node->hasAnother("perf_mode")) {
721             win_node->getNext("perf_mode")->element()->get(perf_mode);
722 
723             if (perf_mode == (int)PERF_LOW) {
724                 perfMode.store(PERF_LOW);
725             } else if (perf_mode == (int)PERF_HIGH) {
726                 perfMode.store(PERF_HIGH);
727             }
728         }
729 
730         if (win_node->hasAnother("theme")) {
731             int theme = 0;
732             win_node->getNext("theme")->element()->get(theme);
733             themeId.store(theme);
734         }
735 
736         if (win_node->hasAnother("font_scale")) {
737             int fscale = 0;
738             win_node->getNext("font_scale")->element()->get(fscale);
739             fontScale.store(fscale);
740         }
741 
742         if (win_node->hasAnother("snap")) {
743 			long long snapVal = 0;
744 			win_node->getNext("snap")->element()->get(snapVal);
745 			snap.store(snapVal);
746 		}
747 
748         if (win_node->hasAnother("center_freq")) {
749             long long freqVal = 0;
750             win_node->getNext("center_freq")->element()->get(freqVal);
751             centerFreq.store(freqVal);
752         }
753 
754         if (win_node->hasAnother("waterfall_lps")) {
755             int lpsVal = 30;
756             win_node->getNext("waterfall_lps")->element()->get(lpsVal);
757             waterfallLinesPerSec.store(lpsVal);
758         }
759 
760         if (win_node->hasAnother("spectrum_avg")) {
761             float avgVal;
762             win_node->getNext("spectrum_avg")->element()->get(avgVal);
763             spectrumAvgSpeed.store(avgVal);
764         }
765 
766         if (win_node->hasAnother("modemprops_collapsed")) {
767             win_node->getNext("modemprops_collapsed")->element()->get(mpc);
768             modemPropsCollapsed.store(mpc != 0);
769         }
770 
771         if (win_node->hasAnother("db_offset")) {
772             DataNode *offset_node = win_node->getNext("db_offset");
773             int offsetValue = 0;
774             offset_node->element()->get(offsetValue);
775             setDBOffset(offsetValue);
776         }
777 
778         if (win_node->hasAnother("main_split")) {
779             float gVal;
780             win_node->getNext("main_split")->element()->get(gVal);
781             mainSplit.store(gVal);
782         }
783 
784         if (win_node->hasAnother("vis_split")) {
785             float gVal;
786             win_node->getNext("vis_split")->element()->get(gVal);
787             visSplit.store(gVal);
788         }
789 
790         if (win_node->hasAnother("bookmark_split")) {
791             float gVal;
792             win_node->getNext("bookmark_split")->element()->get(gVal);
793             bookmarkSplit.store(gVal);
794         }
795 
796         if (win_node->hasAnother("bookmark_visible")) {
797             int bVal;
798             win_node->getNext("bookmark_visible")->element()->get(bVal);
799             bookmarksVisible.store(bVal);
800         }
801     }
802 
803 	//Recording settings:
804     if (cfg.rootNode()->hasAnother("recording")) {
805         DataNode *rec_node = cfg.rootNode()->getNext("recording");
806 
807         if (rec_node->hasAnother("path")) {
808             DataNode *rec_path = rec_node->getNext("path");
809             recordingPath = rec_path->element()->toString();
810         }
811 
812 		if (rec_node->hasAnother("squelch")) {
813 			DataNode *rec_squelch = rec_node->getNext("squelch");
814 			rec_squelch->element()->get(recordingSquelchOption);
815 		}
816 
817 		if (rec_node->hasAnother("file_time_limit")) {
818 			DataNode *rec_file_time_limit = rec_node->getNext("file_time_limit");
819 			rec_file_time_limit->element()->get(recordingFileTimeLimitSeconds);
820 		}
821     }
822 
823     if (cfg.rootNode()->hasAnother("devices")) {
824         DataNode *devices_node = cfg.rootNode()->getNext("devices");
825 
826         while (devices_node->hasAnother("device")) {
827             DataNode *device_node = devices_node->getNext("device");
828             if (device_node->hasAnother("id")) {
829                 std::string deviceId = device_node->getNext("id")->element()->toString();
830 
831                 getDevice(deviceId)->load(device_node);
832             }
833         }
834     }
835 
836     if (cfg.rootNode()->hasAnother("manual_devices")) {
837         DataNode *manuals_node = cfg.rootNode()->getNext("manual_devices");
838 
839         while (manuals_node->hasAnother("device")) {
840             DataNode *manual_node = manuals_node->getNext("device");
841             if (manual_node->hasAnother("factory") && manual_node->hasAnother("params")) {
842                 SDRManualDef mdef;
843 
844                 mdef.factory = manual_node->getNext("factory")->element()->toString();
845                 mdef.params = manual_node->getNext("params")->element()->toString();
846 
847                 manualDevices.push_back(mdef);
848             }
849         }
850     }
851 
852 #ifdef USE_HAMLIB
853     if (cfg.rootNode()->hasAnother("rig")) {
854         DataNode *rig_node = cfg.rootNode()->getNext("rig");
855 
856         if (rig_node->hasAnother("enabled")) {
857             int loadEnabled;
858             rig_node->getNext("enabled")->element()->get(loadEnabled);
859             rigEnabled.store(loadEnabled != 0);
860         }
861         if (rig_node->hasAnother("model")) {
862             int loadModel;
863             rig_node->getNext("model")->element()->get(loadModel);
864             rigModel.store(loadModel?loadModel:1);
865         }
866         if (rig_node->hasAnother("rate")) {
867             int loadRate;
868             rig_node->getNext("rate")->element()->get(loadRate);
869             rigRate.store(loadRate?loadRate:57600);
870         }
871         if (rig_node->hasAnother("port")) {
872             rigPort = rig_node->getNext("port")->element()->toString();
873         }
874         if (rig_node->hasAnother("control")) {
875             int loadControl;
876             rig_node->getNext("control")->element()->get(loadControl);
877             rigControlMode.store(loadControl != 0);
878         }
879         if (rig_node->hasAnother("follow")) {
880             int loadFollow;
881             rig_node->getNext("follow")->element()->get(loadFollow);
882             rigFollowMode.store(loadFollow != 0);
883         }
884         if (rig_node->hasAnother("center_lock")) {
885             int loadCenterLock;
886             rig_node->getNext("center_lock")->element()->get(loadCenterLock);
887             rigCenterLock.store(loadCenterLock != 0);
888         }
889         if (rig_node->hasAnother("follow_modem")) {
890             int loadFollow;
891             rig_node->getNext("follow_modem")->element()->get(loadFollow);
892             rigFollowModem.store(loadFollow != 0);
893         }
894     }
895 #endif
896 
897 
898     return true;
899 }
900 
reset()901 bool AppConfig::reset() {
902 
903     return true;
904 }
905 
906 
907 #if USE_HAMLIB
908 
getRigModel()909 int AppConfig::getRigModel() {
910     return rigModel.load();
911 }
912 
setRigModel(int rigModel_in)913 void AppConfig::setRigModel(int rigModel_in) {
914     rigModel.store(rigModel_in);
915 }
916 
getRigRate()917 int AppConfig::getRigRate() {
918     return rigRate.load();
919 }
920 
setRigRate(int rigRate_in)921 void AppConfig::setRigRate(int rigRate_in) {
922     rigRate.store(rigRate_in);
923 }
924 
getRigPort()925 std::string AppConfig::getRigPort() {
926     return rigPort;
927 }
928 
setRigPort(std::string rigPort_in)929 void AppConfig::setRigPort(std::string rigPort_in) {
930     rigPort = rigPort_in;
931 }
932 
setRigControlMode(bool cMode)933 void AppConfig::setRigControlMode(bool cMode) {
934     rigControlMode.store(cMode);
935 }
936 
getRigControlMode()937 bool AppConfig::getRigControlMode() {
938     return rigControlMode.load();
939 }
940 
setRigFollowMode(bool fMode)941 void AppConfig::setRigFollowMode(bool fMode) {
942     rigFollowMode.store(fMode);
943 }
944 
getRigFollowMode()945 bool AppConfig::getRigFollowMode() {
946     return rigFollowMode.load();
947 }
948 
setRigCenterLock(bool cLock)949 void AppConfig::setRigCenterLock(bool cLock) {
950     rigCenterLock.store(cLock);
951 }
952 
getRigCenterLock()953 bool AppConfig::getRigCenterLock() {
954     return rigCenterLock.load();
955 }
956 
setRigFollowModem(bool fMode)957 void AppConfig::setRigFollowModem(bool fMode) {
958     rigFollowModem.store(fMode);
959 }
960 
getRigFollowModem()961 bool AppConfig::getRigFollowModem() {
962     return rigFollowModem.load();
963 }
964 
setRigEnabled(bool enabled)965 void AppConfig::setRigEnabled(bool enabled) {
966     rigEnabled.store(enabled);
967 }
968 
getRigEnabled()969 bool AppConfig::getRigEnabled() {
970     return rigEnabled.load();
971 }
972 
973 #endif
974