Move Session stuff to SessionMgr

This commit is contained in:
Charles J. Cliffe 2019-01-30 23:24:33 -05:00
parent 1f70f9189e
commit a958912da6
7 changed files with 253 additions and 197 deletions

View File

@ -326,6 +326,7 @@ SET (cubicsdr_sources
src/IOThread.cpp
src/ModemProperties.cpp
src/BookmarkMgr.cpp
src/SessionMgr.cpp
src/sdr/SDRDeviceInfo.cpp
src/sdr/SDRPostThread.cpp
src/sdr/SDREnumerator.cpp
@ -433,6 +434,7 @@ SET (cubicsdr_headers
src/IOThread.h
src/ModemProperties.h
src/BookmarkMgr.h
src/SessionMgr.h
src/sdr/SDRDeviceInfo.h
src/sdr/SDRPostThread.h
src/sdr/SDREnumerator.h

View File

@ -2500,42 +2500,7 @@ void AppFrame::OnAboutDialogClose(wxCommandEvent& /* event */) {
}
void AppFrame::saveSession(std::string fileName) {
DataTree s("cubicsdr_session");
DataNode *header = s.rootNode()->newChild("header");
//save as wstring to prevent problems
header->newChild("version")->element()->set(wxString(CUBICSDR_VERSION).ToStdWstring());
*header->newChild("center_freq") = wxGetApp().getFrequency();
*header->newChild("sample_rate") = wxGetApp().getSampleRate();
*header->newChild("solo_mode") = wxGetApp().getSoloMode()?1:0;
if (waterfallCanvas->getViewState()) {
DataNode *viewState = header->newChild("view_state");
*viewState->newChild("center_freq") = waterfallCanvas->getCenterFrequency();
*viewState->newChild("bandwidth") = waterfallCanvas->getBandwidth();
}
DataNode *demods = s.rootNode()->newChild("demodulators");
//make a local copy snapshot of the list
std::vector<DemodulatorInstancePtr> instances = wxGetApp().getDemodMgr().getDemodulators();
for (auto instance : instances) {
DataNode *demod = demods->newChild("demodulator");
wxGetApp().getDemodMgr().saveInstance(demod, instance);
} //end for demodulators
// Make sure the file name actually ends in .xml
std::string lcFileName = fileName;
std::transform(lcFileName.begin(), lcFileName.end(), lcFileName.begin(), ::tolower);
if (lcFileName.find_last_of(".xml") != lcFileName.length()-1) {
fileName.append(".xml");
}
s.SaveToFileXML(fileName);
wxGetApp().getSessionMgr().saveSession(fileName);
currentSessionFile = fileName;
std::string filePart = fileName.substr(fileName.find_last_of(filePathSeparator) + 1);
@ -2544,167 +2509,31 @@ void AppFrame::saveSession(std::string fileName) {
}
bool AppFrame::loadSession(std::string fileName) {
bool result = wxGetApp().getSessionMgr().loadSession(fileName);
DataTree l;
if (!l.LoadFromFileXML(fileName)) {
return false;
int sample_rate = wxGetApp().getSampleRate();
//scan the available sample rates and see if it matches a predifined one
int menuIndex = -1;
for (auto discreteRate : sampleRates) {
if (discreteRate == sample_rate) {
menuIndex++;
//activate Bandwidth Menu entry matching this predefined sample_rate.
sampleRateMenuItems[wxID_BANDWIDTH_BASE + menuIndex]->Check(true);
break;
}
} //end for
//this is a manual entry
if (menuIndex == -1) {
manualSampleRate = sample_rate;
sampleRateMenuItems[wxID_BANDWIDTH_MANUAL]->Enable(true);
// Apply the manual value, activate the menu entry
sampleRateMenuItems[wxID_BANDWIDTH_MANUAL]->SetItemLabel(wxString("Manual Entry : ") + frequencyToStr(sample_rate));
sampleRateMenuItems[wxID_BANDWIDTH_MANUAL]->Check(true);
}
//Check if it is a session file, read the root node.
if (l.rootNode()->getName() != "cubicsdr_session") {
return false;
}
wxGetApp().getDemodMgr().setActiveDemodulator(nullptr, false);
wxGetApp().getDemodMgr().terminateAll();
try {
if (!l.rootNode()->hasAnother("header")) {
return false;
}
DataNode *header = l.rootNode()->getNext("header");
if (header->hasAnother("version")) {
//"Force" the retreiving of the value as string, even if its look like a number internally ! (ex: "0.2.0")
DataNode *versionNode = header->getNext("version");
std::wstring version;
try {
versionNode->element()->get(version);
std::cout << "Loading session file version: '" << version << "'..." << std::endl;
}
catch (DataTypeMismatchException e) {
//this is for managing the old session format NOT encoded as std:wstring,
//force current version
std::cout << "Warning while Loading session file version, probably old format :'" << e.what() << "' please consider re-saving the current session..." << std::endl << std::flush;
version = wxString(CUBICSDR_VERSION).ToStdWstring();
}
}
if (header->hasAnother("sample_rate")) {
long sample_rate = *header->getNext("sample_rate");
SDRDeviceInfo *dev = wxGetApp().getSDRThread()->getDevice();
if (dev) {
//retreive the available sample rates. A valid previously chosen manual
//value is constrained within these limits. If it doesn't behave, lets the device choose
//for us.
long minRate = MANUAL_SAMPLE_RATE_MIN;
long maxRate = MANUAL_SAMPLE_RATE_MAX;
std::vector<long> sampleRates = dev->getSampleRates(SOAPY_SDR_RX, 0);
if (sampleRates.size()) {
minRate = sampleRates.front();
maxRate = sampleRates.back();
}
//If it is beyond limits, make device choose a reasonable value
if (sample_rate < minRate || sample_rate > maxRate) {
sample_rate = dev->getSampleRateNear(SOAPY_SDR_RX, 0, sample_rate);
}
//scan the available sample rates and see if it matches a predifined one
int menuIndex = -1;
for (auto discreteRate : sampleRates) {
if (discreteRate == sample_rate) {
menuIndex++;
//activate Bandwidth Menu entry matching this predefined sample_rate.
sampleRateMenuItems[wxID_BANDWIDTH_BASE + menuIndex]->Check(true);
break;
}
} //end for
//this is a manual entry
if (menuIndex == -1) {
manualSampleRate = sample_rate;
sampleRateMenuItems[wxID_BANDWIDTH_MANUAL]->Enable(true);
// Apply the manual value, activate the menu entry
sampleRateMenuItems[wxID_BANDWIDTH_MANUAL]->SetItemLabel(wxString("Manual Entry : ") + frequencyToStr(sample_rate));
sampleRateMenuItems[wxID_BANDWIDTH_MANUAL]->Check(true);
}
//update applied value
wxGetApp().setSampleRate(sample_rate);
deviceChanged.store(true);
} else {
wxGetApp().setSampleRate(sample_rate);
}
}
if (header->hasAnother("solo_mode")) {
int solo_mode_activated = *header->getNext("solo_mode");
wxGetApp().setSoloMode((solo_mode_activated > 0) ? true : false);
}
else {
wxGetApp().setSoloMode(false);
}
DemodulatorInstancePtr loadedActiveDemod = nullptr;
DemodulatorInstancePtr newDemod = nullptr;
if (l.rootNode()->hasAnother("demodulators")) {
DataNode *demodulators = l.rootNode()->getNext("demodulators");
std::vector<DemodulatorInstancePtr> demodsLoaded;
while (demodulators->hasAnother("demodulator")) {
DataNode *demod = demodulators->getNext("demodulator");
if (!demod->hasAnother("bandwidth") || !demod->hasAnother("frequency")) {
continue;
}
newDemod = wxGetApp().getDemodMgr().loadInstance(demod);
if (demod->hasAnother("active")) {
loadedActiveDemod = newDemod;
}
newDemod->run();
newDemod->setActive(true);
demodsLoaded.push_back(newDemod);
}
if (demodsLoaded.size()) {
wxGetApp().notifyDemodulatorsChanged();
}
} // if l.rootNode()->hasAnother("demodulators")
if (header->hasAnother("center_freq")) {
long long center_freq = *header->getNext("center_freq");
wxGetApp().setFrequency(center_freq);
// std::cout << "\tCenter Frequency: " << center_freq << std::endl;
}
if (header->hasAnother("view_state")) {
DataNode *viewState = header->getNext("view_state");
if (viewState->hasAnother("center_freq") && viewState->hasAnother("bandwidth")) {
long long center_freq = *viewState->getNext("center_freq");
int bandwidth = *viewState->getNext("bandwidth");
spectrumCanvas->setView(center_freq, bandwidth);
waterfallCanvas->setView(center_freq, bandwidth);
}
} else {
spectrumCanvas->disableView();
waterfallCanvas->disableView();
spectrumCanvas->setCenterFrequency(wxGetApp().getFrequency());
waterfallCanvas->setCenterFrequency(wxGetApp().getFrequency());
}
if (loadedActiveDemod || newDemod) {
wxGetApp().getDemodMgr().setActiveDemodulator(loadedActiveDemod?loadedActiveDemod:newDemod, false);
}
} catch (DataTypeMismatchException e) {
std::cout << e.what() << std::endl;
return false;
}
deviceChanged.store(true);
currentSessionFile = fileName;
@ -2715,13 +2544,20 @@ bool AppFrame::loadSession(std::string fileName) {
wxGetApp().getBookmarkMgr().updateActiveList();
return true;
return result;
}
FFTVisualDataThread *AppFrame::getWaterfallDataThread() {
return waterfallDataThread;
}
WaterfallCanvas *AppFrame::getWaterfallCanvas() {
return waterfallCanvas;
}
SpectrumCanvas *AppFrame::getSpectrumCanvas() {
return spectrumCanvas;
}
void AppFrame::notifyUpdateModemProperties() {
modemPropertiesUpdated.store(true);

View File

@ -122,6 +122,8 @@ public:
bool loadSession(std::string fileName);
FFTVisualDataThread *getWaterfallDataThread();
WaterfallCanvas *getWaterfallCanvas();
SpectrumCanvas *getSpectrumCanvas();
void notifyUpdateModemProperties();
void setMainWaterfallFFTSize(int fftSize);

View File

@ -864,12 +864,16 @@ DemodulatorThreadInputQueuePtr CubicSDR::getWaterfallVisualQueue() {
return pipeWaterfallIQVisualData;
}
BookmarkMgr &CubicSDR::getBookmarkMgr() {
return bookmarkMgr;
}
DemodulatorMgr &CubicSDR::getDemodMgr() {
return demodMgr;
}
BookmarkMgr &CubicSDR::getBookmarkMgr() {
return bookmarkMgr;
SessionMgr &CubicSDR::getSessionMgr() {
return sessionMgr;
}
SDRPostThread *CubicSDR::getSDRPostThread() {

View File

@ -23,6 +23,7 @@
#include "FrequencyDialog.h"
#include "DemodLabelDialog.h"
#include "BookmarkMgr.h"
#include "SessionMgr.h"
#include "ScopeVisualProcessor.h"
#include "SpectrumVisualProcessor.h"
@ -119,6 +120,7 @@ public:
DemodulatorMgr &getDemodMgr();
BookmarkMgr &getBookmarkMgr();
SessionMgr &getSessionMgr();
SDRPostThread *getSDRPostThread();
SDRThread *getSDRThread();
@ -194,6 +196,7 @@ private:
DemodulatorMgr demodMgr;
BookmarkMgr bookmarkMgr;
SessionMgr sessionMgr;
std::atomic_llong frequency;
std::atomic_llong offset;

195
src/SessionMgr.cpp Normal file
View File

@ -0,0 +1,195 @@
// Copyright (c) Charles J. Cliffe
// SPDX-License-Identifier: GPL-2.0+
#include "SessionMgr.h"
#include "CubicSDR.h"
void SessionMgr::saveSession(std::string fileName) {
DataTree s("cubicsdr_session");
DataNode *header = s.rootNode()->newChild("header");
//save as wstring to prevent problems
header->newChild("version")->element()->set(wxString(CUBICSDR_VERSION).ToStdWstring());
*header->newChild("center_freq") = wxGetApp().getFrequency();
*header->newChild("sample_rate") = wxGetApp().getSampleRate();
*header->newChild("solo_mode") = wxGetApp().getSoloMode()?1:0;
WaterfallCanvas *waterfallCanvas = wxGetApp().getAppFrame()->getWaterfallCanvas();
if (waterfallCanvas->getViewState()) {
DataNode *viewState = header->newChild("view_state");
*viewState->newChild("center_freq") = waterfallCanvas->getCenterFrequency();
*viewState->newChild("bandwidth") = waterfallCanvas->getBandwidth();
}
DataNode *demods = s.rootNode()->newChild("demodulators");
//make a local copy snapshot of the list
std::vector<DemodulatorInstancePtr> instances = wxGetApp().getDemodMgr().getDemodulators();
for (const auto &instance : instances) {
DataNode *demod = demods->newChild("demodulator");
wxGetApp().getDemodMgr().saveInstance(demod, instance);
} //end for demodulators
// Make sure the file name actually ends in .xml
std::string lcFileName = fileName;
std::transform(lcFileName.begin(), lcFileName.end(), lcFileName.begin(), ::tolower);
if (lcFileName.find_last_of(".xml") != lcFileName.length()-1) {
fileName.append(".xml");
}
s.SaveToFileXML(fileName);
}
bool SessionMgr::loadSession(std::string fileName) {
DataTree l;
if (!l.LoadFromFileXML(fileName)) {
return false;
}
//Check if it is a session file, read the root node.
if (l.rootNode()->getName() != "cubicsdr_session") {
return false;
}
wxGetApp().getDemodMgr().setActiveDemodulator(nullptr, false);
wxGetApp().getDemodMgr().terminateAll();
WaterfallCanvas *waterfallCanvas = wxGetApp().getAppFrame()->getWaterfallCanvas();
SpectrumCanvas *spectrumCanvas = wxGetApp().getAppFrame()->getSpectrumCanvas();
try {
if (!l.rootNode()->hasAnother("header")) {
return false;
}
DataNode *header = l.rootNode()->getNext("header");
if (header->hasAnother("version")) {
//"Force" the retreiving of the value as string, even if its look like a number internally ! (ex: "0.2.0")
DataNode *versionNode = header->getNext("version");
std::wstring version;
try {
versionNode->element()->get(version);
std::cout << "Loading session file version: '" << version << "'..." << std::endl;
}
catch (DataTypeMismatchException &e) {
//this is for managing the old session format NOT encoded as std:wstring,
//force current version
std::cout << "Warning while Loading session file version, probably old format :'" << e.what() << "' please consider re-saving the current session..." << std::endl << std::flush;
version = wxString(CUBICSDR_VERSION).ToStdWstring();
}
}
if (header->hasAnother("sample_rate")) {
long sample_rate = *header->getNext("sample_rate");
SDRDeviceInfo *dev = wxGetApp().getSDRThread()->getDevice();
if (dev) {
//retreive the available sample rates. A valid previously chosen manual
//value is constrained within these limits. If it doesn't behave, lets the device choose
//for us.
long minRate = MANUAL_SAMPLE_RATE_MIN;
long maxRate = MANUAL_SAMPLE_RATE_MAX;
std::vector<long> sampleRates = dev->getSampleRates(SOAPY_SDR_RX, 0);
if (!sampleRates.empty()) {
minRate = sampleRates.front();
maxRate = sampleRates.back();
}
//If it is beyond limits, make device choose a reasonable value
if (sample_rate < minRate || sample_rate > maxRate) {
sample_rate = dev->getSampleRateNear(SOAPY_SDR_RX, 0, sample_rate);
}
//update applied value
wxGetApp().setSampleRate(sample_rate);
} else {
wxGetApp().setSampleRate(sample_rate);
}
}
if (header->hasAnother("solo_mode")) {
int solo_mode_activated = *header->getNext("solo_mode");
wxGetApp().setSoloMode(solo_mode_activated > 0);
}
else {
wxGetApp().setSoloMode(false);
}
DemodulatorInstancePtr loadedActiveDemod = nullptr;
DemodulatorInstancePtr newDemod = nullptr;
if (l.rootNode()->hasAnother("demodulators")) {
DataNode *demodulators = l.rootNode()->getNext("demodulators");
std::vector<DemodulatorInstancePtr> demodsLoaded;
while (demodulators->hasAnother("demodulator")) {
DataNode *demod = demodulators->getNext("demodulator");
if (!demod->hasAnother("bandwidth") || !demod->hasAnother("frequency")) {
continue;
}
newDemod = wxGetApp().getDemodMgr().loadInstance(demod);
if (demod->hasAnother("active")) {
loadedActiveDemod = newDemod;
}
newDemod->run();
newDemod->setActive(true);
demodsLoaded.push_back(newDemod);
}
if (!demodsLoaded.empty()) {
wxGetApp().notifyDemodulatorsChanged();
}
} // if l.rootNode()->hasAnother("demodulators")
if (header->hasAnother("center_freq")) {
long long center_freq = *header->getNext("center_freq");
wxGetApp().setFrequency(center_freq);
// std::cout << "\tCenter Frequency: " << center_freq << std::endl;
}
if (header->hasAnother("view_state")) {
DataNode *viewState = header->getNext("view_state");
if (viewState->hasAnother("center_freq") && viewState->hasAnother("bandwidth")) {
long long center_freq = *viewState->getNext("center_freq");
int bandwidth = *viewState->getNext("bandwidth");
spectrumCanvas->setView(center_freq, bandwidth);
waterfallCanvas->setView(center_freq, bandwidth);
}
} else {
spectrumCanvas->disableView();
waterfallCanvas->disableView();
spectrumCanvas->setCenterFrequency(wxGetApp().getFrequency());
waterfallCanvas->setCenterFrequency(wxGetApp().getFrequency());
}
if (loadedActiveDemod || newDemod) {
wxGetApp().getDemodMgr().setActiveDemodulator(loadedActiveDemod?loadedActiveDemod:newDemod, false);
}
} catch (DataTypeMismatchException &e) {
std::cout << e.what() << std::endl;
return false;
}
return true;
}

14
src/SessionMgr.h Normal file
View File

@ -0,0 +1,14 @@
// Copyright (c) Charles J. Cliffe
// SPDX-License-Identifier: GPL-2.0+
#pragma once
#include "DataTree.h"
#include "AppFrame.h"
class SessionMgr {
public:
void saveSession(std::string fileName);
bool loadSession(std::string fileName);
};