Merge pull request #572 from cjcliffe/vso_shared_ptr_DemodulatorInstances

Let's see if I've broken something :)
This commit is contained in:
Vincent Sonnier 2017-08-27 14:47:10 +02:00 committed by GitHub
commit 2d01a279e9
35 changed files with 351 additions and 392 deletions

View File

@ -1709,10 +1709,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
} }
} }
//try to garbage collect the retired demodulators. DemodulatorInstancePtr demod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
wxGetApp().getDemodMgr().garbageCollect();
DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
if (demod && demod->isModemInitialized()) { if (demod && demod->isModemInitialized()) {
if (demod->isTracking()) { if (demod->isTracking()) {
@ -2129,11 +2126,12 @@ void AppFrame::saveSession(std::string fileName) {
DataNode *demods = s.rootNode()->newChild("demodulators"); DataNode *demods = s.rootNode()->newChild("demodulators");
std::vector<DemodulatorInstance *> &instances = wxGetApp().getDemodMgr().getDemodulators(); //make a local copy snapshot of the list
std::vector<DemodulatorInstancePtr> instances = wxGetApp().getDemodMgr().getDemodulators();
for (auto instance_i : instances) { for (auto instance : instances) {
DataNode *demod = demods->newChild("demodulator"); DataNode *demod = demods->newChild("demodulator");
wxGetApp().getDemodMgr().saveInstance(demod, instance_i); wxGetApp().getDemodMgr().saveInstance(demod, instance);
} //end for demodulators } //end for demodulators
// Make sure the file name actually ends in .xml // Make sure the file name actually ends in .xml
@ -2247,14 +2245,14 @@ bool AppFrame::loadSession(std::string fileName) {
wxGetApp().setSoloMode(false); wxGetApp().setSoloMode(false);
} }
DemodulatorInstance *loadedActiveDemod = nullptr; DemodulatorInstancePtr loadedActiveDemod = nullptr;
DemodulatorInstance *newDemod = nullptr; DemodulatorInstancePtr newDemod = nullptr;
if (l.rootNode()->hasAnother("demodulators")) { if (l.rootNode()->hasAnother("demodulators")) {
DataNode *demodulators = l.rootNode()->getNext("demodulators"); DataNode *demodulators = l.rootNode()->getNext("demodulators");
std::vector<DemodulatorInstance *> demodsLoaded; std::vector<DemodulatorInstancePtr> demodsLoaded;
while (demodulators->hasAnother("demodulator")) { while (demodulators->hasAnother("demodulator")) {
DataNode *demod = demodulators->getNext("demodulator"); DataNode *demod = demodulators->getNext("demodulator");
@ -2275,7 +2273,7 @@ bool AppFrame::loadSession(std::string fileName) {
} }
if (demodsLoaded.size()) { if (demodsLoaded.size()) {
wxGetApp().bindDemodulators(&demodsLoaded); wxGetApp().notifyDemodulatorsChanged();
} }
} // if l.rootNode()->hasAnother("demodulators") } // if l.rootNode()->hasAnother("demodulators")
@ -2404,14 +2402,14 @@ FrequencyDialog::FrequencyDialogTarget AppFrame::getFrequencyDialogTarget() {
return target; return target;
} }
void AppFrame::gkNudgeLeft(DemodulatorInstance *demod, int snap) { void AppFrame::gkNudgeLeft(DemodulatorInstancePtr demod, int snap) {
if (demod) { if (demod) {
demod->setFrequency(demod->getFrequency()-snap); demod->setFrequency(demod->getFrequency()-snap);
demod->updateLabel(demod->getFrequency()); demod->updateLabel(demod->getFrequency());
} }
} }
void AppFrame::gkNudgeRight(DemodulatorInstance *demod, int snap) { void AppFrame::gkNudgeRight(DemodulatorInstancePtr demod, int snap) {
if (demod) { if (demod) {
demod->setFrequency(demod->getFrequency()+snap); demod->setFrequency(demod->getFrequency()+snap);
demod->updateLabel(demod->getFrequency()); demod->updateLabel(demod->getFrequency());
@ -2437,7 +2435,10 @@ int AppFrame::OnGlobalKeyDown(wxKeyEvent &event) {
return -1; return -1;
} }
DemodulatorInstance *demod = nullptr, *lastDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); DemodulatorInstancePtr demod = nullptr;
DemodulatorInstancePtr lastDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
int snap = wxGetApp().getFrequencySnap(); int snap = wxGetApp().getFrequencySnap();
if (event.ControlDown()) { if (event.ControlDown()) {
@ -2562,8 +2563,8 @@ int AppFrame::OnGlobalKeyUp(wxKeyEvent &event) {
return 1; return 1;
} }
DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator(); DemodulatorInstancePtr activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator();
DemodulatorInstance *lastDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); DemodulatorInstancePtr lastDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
#ifdef wxHAS_RAW_KEY_CODES #ifdef wxHAS_RAW_KEY_CODES
switch (event.GetRawKeyCode()) { switch (event.GetRawKeyCode()) {

View File

@ -26,7 +26,8 @@
#include "FrequencyDialog.h" #include "FrequencyDialog.h"
#include "BookmarkView.h" #include "BookmarkView.h"
#include "AboutDialog.h" #include "AboutDialog.h"
#include "DemodulatorInstance.h"
#include "DemodulatorThread.h"
#include <map> #include <map>
#define wxID_RT_AUDIO_DEVICE 1000 #define wxID_RT_AUDIO_DEVICE 1000
@ -107,8 +108,8 @@ public:
void setMainWaterfallFFTSize(int fftSize); void setMainWaterfallFFTSize(int fftSize);
void setScopeDeviceName(std::string deviceName); void setScopeDeviceName(std::string deviceName);
void gkNudgeLeft(DemodulatorInstance *demod, int snap); void gkNudgeLeft(DemodulatorInstancePtr demod, int snap);
void gkNudgeRight(DemodulatorInstance *demod, int snap); void gkNudgeRight(DemodulatorInstancePtr demod, int snap);
int OnGlobalKeyDown(wxKeyEvent &event); int OnGlobalKeyDown(wxKeyEvent &event);
int OnGlobalKeyUp(wxKeyEvent &event); int OnGlobalKeyUp(wxKeyEvent &event);
@ -193,7 +194,7 @@ private:
wxBoxSizer *demodTray; wxBoxSizer *demodTray;
BookmarkView *bookmarkView; BookmarkView *bookmarkView;
DemodulatorInstance *activeDemodulator; DemodulatorInstancePtr activeDemodulator;
std::vector<RtAudio::DeviceInfo> devices; std::vector<RtAudio::DeviceInfo> devices;
std::map<int,RtAudio::DeviceInfo> inputDevices; std::map<int,RtAudio::DeviceInfo> inputDevices;

View File

@ -205,7 +205,7 @@ bool BookmarkMgr::hasBackup(std::string bookmarkFn) {
return backupFile.FileExists() && backupFile.IsFileReadable(); return backupFile.FileExists() && backupFile.IsFileReadable();
} }
void BookmarkMgr::addBookmark(std::string group, DemodulatorInstance *demod) { void BookmarkMgr::addBookmark(std::string group, DemodulatorInstancePtr demod) {
std::lock_guard < std::recursive_mutex > lock(busy_lock); std::lock_guard < std::recursive_mutex > lock(busy_lock);
//Create a BookmarkEntry from demod data, saving its //Create a BookmarkEntry from demod data, saving its
@ -392,7 +392,7 @@ void BookmarkMgr::updateBookmarks(std::string group) {
} }
void BookmarkMgr::addRecent(DemodulatorInstance *demod) { void BookmarkMgr::addRecent(DemodulatorInstancePtr demod) {
std::lock_guard < std::recursive_mutex > lock(busy_lock); std::lock_guard < std::recursive_mutex > lock(busy_lock);
recents.push_back(demodToBookmarkEntry(demod)); recents.push_back(demodToBookmarkEntry(demod));
@ -482,7 +482,7 @@ void BookmarkMgr::clearRanges() {
} }
BookmarkEntryPtr BookmarkMgr::demodToBookmarkEntry(DemodulatorInstance *demod) { BookmarkEntryPtr BookmarkMgr::demodToBookmarkEntry(DemodulatorInstancePtr demod) {
BookmarkEntryPtr be(new BookmarkEntry); BookmarkEntryPtr be(new BookmarkEntry);
@ -536,7 +536,7 @@ std::wstring BookmarkMgr::getBookmarkEntryDisplayName(BookmarkEntryPtr bmEnt) {
return dispName; return dispName;
} }
std::wstring BookmarkMgr::getActiveDisplayName(DemodulatorInstance *demod) { std::wstring BookmarkMgr::getActiveDisplayName(DemodulatorInstancePtr demod) {
std::wstring activeName = demod->getDemodulatorUserLabel(); std::wstring activeName = demod->getDemodulatorUserLabel();
if (activeName == "") { if (activeName == "") {
@ -547,7 +547,7 @@ std::wstring BookmarkMgr::getActiveDisplayName(DemodulatorInstance *demod) {
return activeName; return activeName;
} }
void BookmarkMgr::removeActive(DemodulatorInstance *demod) { void BookmarkMgr::removeActive(DemodulatorInstancePtr demod) {
std::lock_guard < std::recursive_mutex > lock(busy_lock); std::lock_guard < std::recursive_mutex > lock(busy_lock);

View File

@ -85,7 +85,7 @@ public:
bool hasLastLoad(std::string bookmarkFn); bool hasLastLoad(std::string bookmarkFn);
bool hasBackup(std::string bookmarkFn); bool hasBackup(std::string bookmarkFn);
void addBookmark(std::string group, DemodulatorInstance *demod); void addBookmark(std::string group, DemodulatorInstancePtr demod);
void addBookmark(std::string group, BookmarkEntryPtr be); void addBookmark(std::string group, BookmarkEntryPtr be);
void removeBookmark(std::string group, BookmarkEntryPtr be); void removeBookmark(std::string group, BookmarkEntryPtr be);
void removeBookmark(BookmarkEntryPtr be); void removeBookmark(BookmarkEntryPtr be);
@ -105,13 +105,13 @@ public:
void updateBookmarks(); void updateBookmarks();
void updateBookmarks(std::string group); void updateBookmarks(std::string group);
void addRecent(DemodulatorInstance *demod); void addRecent(DemodulatorInstancePtr demod);
void addRecent(BookmarkEntryPtr be); void addRecent(BookmarkEntryPtr be);
void removeRecent(BookmarkEntryPtr be); void removeRecent(BookmarkEntryPtr be);
const BookmarkList& getRecents(); const BookmarkList& getRecents();
void clearRecents(); void clearRecents();
void removeActive(DemodulatorInstance *demod); void removeActive(DemodulatorInstancePtr demod);
void addRange(BookmarkRangeEntryPtr re); void addRange(BookmarkRangeEntryPtr re);
void removeRange(BookmarkRangeEntryPtr re); void removeRange(BookmarkRangeEntryPtr re);
@ -119,13 +119,13 @@ public:
void clearRanges(); void clearRanges();
static std::wstring getBookmarkEntryDisplayName(BookmarkEntryPtr bmEnt); static std::wstring getBookmarkEntryDisplayName(BookmarkEntryPtr bmEnt);
static std::wstring getActiveDisplayName(DemodulatorInstance *demod); static std::wstring getActiveDisplayName(DemodulatorInstancePtr demod);
protected: protected:
void trimRecents(); void trimRecents();
BookmarkEntryPtr demodToBookmarkEntry(DemodulatorInstance *demod); BookmarkEntryPtr demodToBookmarkEntry(DemodulatorInstancePtr demod);
BookmarkEntryPtr nodeToBookmark(DataNode *node); BookmarkEntryPtr nodeToBookmark(DataNode *node);
BookmarkMap bmData; BookmarkMap bmData;

View File

@ -421,9 +421,6 @@ int CubicSDR::OnExit() {
std::cout << "Terminating All Demodulators.." << std::endl << std::flush; std::cout << "Terminating All Demodulators.." << std::endl << std::flush;
demodMgr.terminateAll(); demodMgr.terminateAll();
//wait for effective death of all demodulators before continuing.
terminationSequenceOK = terminationSequenceOK && demodMgr.garbageCollect(true, 3000);
std::cout << "Terminating Visual Processor threads.." << std::endl << std::flush; std::cout << "Terminating Visual Processor threads.." << std::endl << std::flush;
spectrumVisualThread->terminate(); spectrumVisualThread->terminate();
if (demodVisualThread) { if (demodVisualThread) {
@ -831,30 +828,21 @@ SDRThread *CubicSDR::getSDRThread() {
} }
void CubicSDR::bindDemodulator(DemodulatorInstance *demod) { void CubicSDR::notifyDemodulatorsChanged() {
if (!demod) {
return; sdrPostThread->notifyDemodulatorsChanged();
}
sdrPostThread->bindDemodulator(demod);
}
void CubicSDR::bindDemodulators(std::vector<DemodulatorInstance *> *demods) {
if (!demods) {
return;
}
sdrPostThread->bindDemodulators(demods);
} }
long long CubicSDR::getSampleRate() { long long CubicSDR::getSampleRate() {
return sampleRate; return sampleRate;
} }
void CubicSDR::removeDemodulator(DemodulatorInstance *demod) { void CubicSDR::removeDemodulator(DemodulatorInstancePtr demod) {
if (!demod) { if (!demod) {
return; return;
} }
demod->setActive(false); demod->setActive(false);
sdrPostThread->removeDemodulator(demod); sdrPostThread->notifyDemodulatorsChanged();
wxGetApp().getAppFrame()->notifyUpdateModemProperties(); wxGetApp().getAppFrame()->notifyUpdateModemProperties();
} }
@ -926,7 +914,7 @@ void CubicSDR::showFrequencyInput(FrequencyDialog::FrequencyDialogTarget targetM
void CubicSDR::showLabelInput() { void CubicSDR::showLabelInput() {
DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator(); DemodulatorInstancePtr activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator();
if (activeDemod != nullptr) { if (activeDemod != nullptr) {

View File

@ -121,9 +121,9 @@ public:
SDRPostThread *getSDRPostThread(); SDRPostThread *getSDRPostThread();
SDRThread *getSDRThread(); SDRThread *getSDRThread();
void bindDemodulator(DemodulatorInstance *demod); void notifyDemodulatorsChanged();
void bindDemodulators(std::vector<DemodulatorInstance *> *demods);
void removeDemodulator(DemodulatorInstance *demod); void removeDemodulator(DemodulatorInstancePtr demod);
void setFrequencySnap(int snap); void setFrequencySnap(int snap);
int getFrequencySnap(); int getFrequencySnap();

View File

@ -13,7 +13,7 @@ EVT_SHOW(DemodLabelDialog::OnShow)
wxEND_EVENT_TABLE() wxEND_EVENT_TABLE()
DemodLabelDialog::DemodLabelDialog(wxWindow * parent, wxWindowID id, const wxString & title, DemodLabelDialog::DemodLabelDialog(wxWindow * parent, wxWindowID id, const wxString & title,
DemodulatorInstance *demod, const wxPoint & position, DemodulatorInstancePtr demod, const wxPoint & position,
const wxSize & size, long style) : const wxSize & size, long style) :
wxDialog(parent, id, title, position, size, style) { wxDialog(parent, id, title, position, size, style) {

View File

@ -16,7 +16,7 @@ class DemodLabelDialog : public wxDialog
public: public:
DemodLabelDialog( wxWindow * parent, wxWindowID id, const wxString & title, DemodLabelDialog( wxWindow * parent, wxWindowID id, const wxString & title,
DemodulatorInstance *demod = NULL, DemodulatorInstancePtr demod = nullptr,
const wxPoint & pos = wxDefaultPosition, const wxPoint & pos = wxDefaultPosition,
const wxSize & size = wxDefaultSize, const wxSize & size = wxDefaultSize,
long style = wxDEFAULT_DIALOG_STYLE); long style = wxDEFAULT_DIALOG_STYLE);
@ -24,7 +24,7 @@ public:
wxTextCtrl * dialogText; wxTextCtrl * dialogText;
private: private:
DemodulatorInstance *activeDemod = nullptr; DemodulatorInstancePtr activeDemod = nullptr;
void OnEnter ( wxCommandEvent &event ); void OnEnter ( wxCommandEvent &event );
void OnChar ( wxKeyEvent &event ); void OnChar ( wxKeyEvent &event );
void OnShow(wxShowEvent &event); void OnShow(wxShowEvent &event);

View File

@ -12,11 +12,13 @@ EVT_CHAR_HOOK(FrequencyDialog::OnChar)
EVT_SHOW(FrequencyDialog::OnShow) EVT_SHOW(FrequencyDialog::OnShow)
wxEND_EVENT_TABLE() wxEND_EVENT_TABLE()
FrequencyDialog::FrequencyDialog(wxWindow * parent, wxWindowID id, const wxString & title, DemodulatorInstance *demod, const wxPoint & position, FrequencyDialog::FrequencyDialog(wxWindow * parent, wxWindowID id, const wxString & title, DemodulatorInstancePtr demod, const wxPoint & position,
const wxSize & size, long style, FrequencyDialogTarget targetMode, wxString initString) : const wxSize & size, long style, FrequencyDialogTarget targetMode, wxString initString) :
wxDialog(parent, id, title, position, size, style) { wxDialog(parent, id, title, position, size, style) {
wxString freqStr; wxString freqStr;
activeDemod = demod; activeDemod = demod;
this->targetMode = targetMode; this->targetMode = targetMode;
this->initialString = initString; this->initialString = initString;

View File

@ -24,7 +24,7 @@ public:
FDIALOG_TARGET_GAIN FDIALOG_TARGET_GAIN
} FrequencyDialogTarget; } FrequencyDialogTarget;
FrequencyDialog ( wxWindow * parent, wxWindowID id, const wxString & title, FrequencyDialog ( wxWindow * parent, wxWindowID id, const wxString & title,
DemodulatorInstance *demod = NULL, DemodulatorInstancePtr demod = nullptr,
const wxPoint & pos = wxDefaultPosition, const wxPoint & pos = wxDefaultPosition,
const wxSize & size = wxDefaultSize, const wxSize & size = wxDefaultSize,
long style = wxDEFAULT_DIALOG_STYLE, long style = wxDEFAULT_DIALOG_STYLE,
@ -34,7 +34,7 @@ public:
wxTextCtrl * dialogText; wxTextCtrl * dialogText;
private: private:
DemodulatorInstance *activeDemod; DemodulatorInstancePtr activeDemod;
void OnEnter ( wxCommandEvent &event ); void OnEnter ( wxCommandEvent &event );
void OnChar ( wxKeyEvent &event ); void OnChar ( wxKeyEvent &event );
void OnShow(wxShowEvent &event); void OnShow(wxShowEvent &event);

View File

@ -101,7 +101,7 @@ void ModemProperties::initDefaultProperties() {
defaultProps["._audio_output"] = addArgInfoProperty(m_propertyGrid, outputArg); defaultProps["._audio_output"] = addArgInfoProperty(m_propertyGrid, outputArg);
} }
void ModemProperties::initProperties(ModemArgInfoList newArgs, DemodulatorInstance *demodInstance) { void ModemProperties::initProperties(ModemArgInfoList newArgs, DemodulatorInstancePtr demodInstance) {
args = newArgs; args = newArgs;
demodContext = demodInstance; demodContext = demodInstance;

View File

@ -24,7 +24,7 @@ public:
~ModemProperties(); ~ModemProperties();
void initDefaultProperties(); void initDefaultProperties();
void initProperties(ModemArgInfoList newArgs, DemodulatorInstance *demodInstance); void initProperties(ModemArgInfoList newArgs, DemodulatorInstancePtr demodInstance);
bool isMouseInView(); bool isMouseInView();
void setCollapsed(bool state); void setCollapsed(bool state);
bool isCollapsed(); bool isCollapsed();
@ -46,7 +46,8 @@ private:
wxBoxSizer* bSizer; wxBoxSizer* bSizer;
wxPropertyGrid* m_propertyGrid; wxPropertyGrid* m_propertyGrid;
ModemArgInfoList args; ModemArgInfoList args;
DemodulatorInstance *demodContext; DemodulatorInstancePtr demodContext;
std::map<std::string, wxPGProperty *> props; std::map<std::string, wxPGProperty *> props;
bool mouseInView, collapsed; bool mouseInView, collapsed;

View File

@ -304,14 +304,12 @@ void AudioThread::setSampleRate(int sampleRate) {
srcmix->setSampleRate(sampleRate); srcmix->setSampleRate(sampleRate);
} }
std::vector<DemodulatorInstance *>::iterator demod_i; //make a local copy, snapshot of the list of demodulators
std::vector<DemodulatorInstance *> *demodulators; std::vector<DemodulatorInstancePtr> demodulators = wxGetApp().getDemodMgr().getDemodulators();
demodulators = &wxGetApp().getDemodMgr().getDemodulators(); for (auto demod : demodulators) {
if (demod->getOutputDevice() == outputDevice.load()) {
for (demod_i = demodulators->begin(); demod_i != demodulators->end(); demod_i++) { demod->setAudioSampleRate(sampleRate);
if ((*demod_i)->getOutputDevice() == outputDevice.load()) {
(*demod_i)->setAudioSampleRate(sampleRate);
} }
} }

View File

@ -35,6 +35,10 @@ public:
typedef std::shared_ptr<AudioThreadInput> AudioThreadInputPtr; typedef std::shared_ptr<AudioThreadInput> AudioThreadInputPtr;
typedef ThreadBlockingQueue<AudioThreadInputPtr> DemodulatorThreadOutputQueue;
typedef std::shared_ptr<DemodulatorThreadOutputQueue> DemodulatorThreadOutputQueuePtr;
class AudioThreadCommand { class AudioThreadCommand {
public: public:
enum AudioThreadCommandEnum { enum AudioThreadCommandEnum {

View File

@ -15,7 +15,6 @@
class DemodulatorThread; class DemodulatorThread;
class DemodulatorThreadControlCommand { class DemodulatorThreadControlCommand {
public: public:
enum DemodulatorThreadControlCommandEnum { enum DemodulatorThreadControlCommandEnum {

View File

@ -5,6 +5,10 @@
#include "DemodulatorInstance.h" #include "DemodulatorInstance.h"
#include "CubicSDR.h" #include "CubicSDR.h"
#include "DemodulatorThread.h"
#include "DemodulatorPreThread.h"
#if USE_HAMLIB #if USE_HAMLIB
#include "RigThread.h" #include "RigThread.h"
#endif #endif
@ -79,13 +83,37 @@ DemodulatorInstance::DemodulatorInstance() {
} }
DemodulatorInstance::~DemodulatorInstance() { DemodulatorInstance::~DemodulatorInstance() {
std::lock_guard < std::mutex > lockData(m_thread_control_mutex);
std::lock_guard < std::recursive_mutex > lockData(m_thread_control_mutex);
//now that DemodulatorInstance are managed through shared_ptr, we
//should enter here ONLY when it is no longer used by any piece of code, anywhere.
//so active wait on IsTerminated(), then die.
#define TERMINATION_SPIN_WAIT_MS (20)
#define MAX_WAIT_FOR_TERMINATION_MS (3000.0)
//this is a stupid busy plus sleep loop
int nbCyclesToWait = (MAX_WAIT_FOR_TERMINATION_MS / TERMINATION_SPIN_WAIT_MS) + 1;
int currentCycle = 0;
while (currentCycle < nbCyclesToWait) {
if (isTerminated()) {
std::cout << "Garbage collected demodulator instance '" << getLabel() << "'... " << std::endl << std::flush;
#if ENABLE_DIGITAL_LAB #if ENABLE_DIGITAL_LAB
delete activeOutput; delete activeOutput;
#endif #endif
delete audioThread; delete audioThread;
delete demodulatorThread; delete demodulatorThread;
delete demodulatorPreThread; delete demodulatorPreThread;
break;
}
else {
std::this_thread::sleep_for(std::chrono::milliseconds(TERMINATION_SPIN_WAIT_MS));
}
currentCycle++;
} //end while
} }
void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueuePtr tQueue) { void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueuePtr tQueue) {
@ -94,7 +122,7 @@ void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueuePtr t
void DemodulatorInstance::run() { void DemodulatorInstance::run() {
std::lock_guard < std::mutex > lockData(m_thread_control_mutex); std::lock_guard < std::recursive_mutex > lockData(m_thread_control_mutex);
if (active) { if (active) {
return; return;
@ -163,7 +191,7 @@ void DemodulatorInstance::setLabel(std::string labelStr) {
bool DemodulatorInstance::isTerminated() { bool DemodulatorInstance::isTerminated() {
std::lock_guard < std::mutex > lockData(m_thread_control_mutex); std::lock_guard < std::recursive_mutex > lockData(m_thread_control_mutex);
bool audioTerminated = audioThread->isTerminated(); bool audioTerminated = audioThread->isTerminated();
bool demodTerminated = demodulatorThread->isTerminated(); bool demodTerminated = demodulatorThread->isTerminated();
@ -224,7 +252,9 @@ void DemodulatorInstance::setActive(bool state) {
} }
#endif #endif
audioThread->setActive(state); audioThread->setActive(state);
DemodulatorThread::releaseSquelchLock(this); DemodulatorThread::releaseSquelchLock(this);
} else if (!active && state) { } else if (!active && state) {
#if ENABLE_DIGITAL_LAB #if ENABLE_DIGITAL_LAB
if (activeOutput && getModemType() == "digital") { if (activeOutput && getModemType() == "digital") {
@ -404,7 +434,7 @@ void DemodulatorInstance::setFrequency(long long freq) {
} }
#endif #endif
#if USE_HAMLIB #if USE_HAMLIB
if (wxGetApp().rigIsActive() && wxGetApp().getRigThread()->getFollowModem() && wxGetApp().getDemodMgr().getLastActiveDemodulator() == this) { if (wxGetApp().rigIsActive() && wxGetApp().getRigThread()->getFollowModem() && wxGetApp().getDemodMgr().getLastActiveDemodulator().get() == this) {
wxGetApp().getRigThread()->setFrequency(freq,true); wxGetApp().getRigThread()->setFrequency(freq,true);
} }
#endif #endif

View File

@ -6,12 +6,11 @@
#include <vector> #include <vector>
#include <map> #include <map>
#include <thread> #include <thread>
#include <memory>
#include "DemodulatorThread.h" #include "DemodDefs.h"
#include "DemodulatorPreThread.h"
#include "ModemDigital.h" #include "ModemDigital.h"
#include "ModemAnalog.h" #include "ModemAnalog.h"
#include "AudioThread.h"
#if ENABLE_DIGITAL_LAB #if ENABLE_DIGITAL_LAB
#include "DigitalConsole.h" #include "DigitalConsole.h"
@ -30,6 +29,8 @@ private:
std::atomic_int squelchBreak; std::atomic_int squelchBreak;
}; };
class DemodulatorThread;
class DemodulatorPreThread;
class DemodulatorInstance { class DemodulatorInstance {
public: public:
@ -139,7 +140,7 @@ private:
DemodulatorThreadControlCommandQueuePtr threadQueueControl; DemodulatorThreadControlCommandQueuePtr threadQueueControl;
//protects child thread creation and termination //protects child thread creation and termination
std::mutex m_thread_control_mutex; std::recursive_mutex m_thread_control_mutex;
std::atomic<std::string *> label; // std::atomic<std::string *> label; //
// User editable buffer, 16 bit string. // User editable buffer, 16 bit string.
@ -161,3 +162,5 @@ private:
ModemDigitalOutput *activeOutput; ModemDigitalOutput *activeOutput;
#endif #endif
}; };
typedef std::shared_ptr<DemodulatorInstance> DemodulatorInstancePtr;

View File

@ -17,13 +17,11 @@
#include "DataTree.h" #include "DataTree.h"
bool demodFreqCompare (DemodulatorInstance *i, DemodulatorInstance *j) { return (i->getFrequency()<j->getFrequency()); } bool demodFreqCompare (DemodulatorInstancePtr i, DemodulatorInstancePtr j) { return (i->getFrequency() < j->getFrequency()); }
bool inactiveCompare (DemodulatorInstance *i, DemodulatorInstance *j) { return (i->isActive()<j->isActive()); } bool inactiveCompare (DemodulatorInstancePtr i, DemodulatorInstancePtr j) { return (i->isActive() < j->isActive()); }
DemodulatorMgr::DemodulatorMgr() { DemodulatorMgr::DemodulatorMgr() {
activeDemodulator = NULL;
lastActiveDemodulator = NULL;
activeVisualDemodulator = NULL;
lastBandwidth = DEFAULT_DEMOD_BW; lastBandwidth = DEFAULT_DEMOD_BW;
lastDemodType = DEFAULT_DEMOD_TYPE; lastDemodType = DEFAULT_DEMOD_TYPE;
lastSquelchEnabled = false; lastSquelchEnabled = false;
@ -37,9 +35,11 @@ DemodulatorMgr::~DemodulatorMgr() {
terminateAll(); terminateAll();
} }
DemodulatorInstance *DemodulatorMgr::newThread() { DemodulatorInstancePtr DemodulatorMgr::newThread() {
std::lock_guard < std::recursive_mutex > lock(demods_busy); std::lock_guard < std::recursive_mutex > lock(demods_busy);
DemodulatorInstance *newDemod = new DemodulatorInstance;
//create a new instance of DemodulatorInstance here.
DemodulatorInstancePtr newDemod = std::make_shared<DemodulatorInstance>();
std::stringstream label; std::stringstream label;
label << demods.size(); label << demods.size();
@ -51,27 +51,34 @@ DemodulatorInstance *DemodulatorMgr::newThread() {
} }
void DemodulatorMgr::terminateAll() { void DemodulatorMgr::terminateAll() {
std::lock_guard < std::recursive_mutex > lock(demods_busy); std::lock_guard < std::recursive_mutex > lock(demods_busy);
while (demods.size()) { while (demods.size()) {
DemodulatorInstance *d = demods.back(); DemodulatorInstancePtr d = demods.back();
demods.pop_back(); demods.pop_back();
wxGetApp().removeDemodulator(d); wxGetApp().removeDemodulator(d);
deleteThread(d); deleteThread(d);
} }
} }
std::vector<DemodulatorInstance *> &DemodulatorMgr::getDemodulators() { std::vector<DemodulatorInstancePtr> DemodulatorMgr::getDemodulators() {
std::lock_guard < std::recursive_mutex > lock(demods_busy); std::lock_guard < std::recursive_mutex > lock(demods_busy);
return demods; return demods;
} }
std::vector<DemodulatorInstance *> DemodulatorMgr::getOrderedDemodulators(bool actives) { std::vector<DemodulatorInstancePtr> DemodulatorMgr::getOrderedDemodulators(bool actives) {
std::lock_guard < std::recursive_mutex > lock(demods_busy); std::lock_guard < std::recursive_mutex > lock(demods_busy);
std::vector<DemodulatorInstance *> demods_ordered = demods;
auto demods_ordered = demods;
if (actives) { if (actives) {
std::sort(demods_ordered.begin(), demods_ordered.end(), inactiveCompare); std::sort(demods_ordered.begin(), demods_ordered.end(), inactiveCompare);
std::vector<DemodulatorInstance *>::iterator i;
std::vector<DemodulatorInstancePtr>::iterator i;
for (i = demods_ordered.begin(); i != demods_ordered.end(); i++) { for (i = demods_ordered.begin(); i != demods_ordered.end(); i++) {
if ((*i)->isActive()) { if ((*i)->isActive()) {
break; break;
@ -88,13 +95,14 @@ std::vector<DemodulatorInstance *> DemodulatorMgr::getOrderedDemodulators(bool a
return demods_ordered; return demods_ordered;
} }
DemodulatorInstance *DemodulatorMgr::getPreviousDemodulator(DemodulatorInstance *demod, bool actives) { DemodulatorInstancePtr DemodulatorMgr::getPreviousDemodulator(DemodulatorInstancePtr demod, bool actives) {
std::lock_guard < std::recursive_mutex > lock(demods_busy); std::lock_guard < std::recursive_mutex > lock(demods_busy);
if (!getLastActiveDemodulator()) { if (!getLastActiveDemodulator()) {
return nullptr; return nullptr;
} }
std::vector<DemodulatorInstance *> demods_ordered = getOrderedDemodulators(actives); auto demods_ordered = getOrderedDemodulators(actives);
std::vector<DemodulatorInstance *>::iterator p = std::find(demods_ordered.begin(), demods_ordered.end(), demod); auto p = std::find(demods_ordered.begin(), demods_ordered.end(), demod);
if (p == demods_ordered.end()) { if (p == demods_ordered.end()) {
return nullptr; return nullptr;
} }
@ -104,13 +112,14 @@ DemodulatorInstance *DemodulatorMgr::getPreviousDemodulator(DemodulatorInstance
return *(--p); return *(--p);
} }
DemodulatorInstance *DemodulatorMgr::getNextDemodulator(DemodulatorInstance *demod, bool actives) { DemodulatorInstancePtr DemodulatorMgr::getNextDemodulator(DemodulatorInstancePtr demod, bool actives) {
std::lock_guard < std::recursive_mutex > lock(demods_busy); std::lock_guard < std::recursive_mutex > lock(demods_busy);
if (!getLastActiveDemodulator()) { if (!getLastActiveDemodulator()) {
return nullptr; return nullptr;
} }
std::vector<DemodulatorInstance *> demods_ordered = getOrderedDemodulators(actives); auto demods_ordered = getOrderedDemodulators(actives);
std::vector<DemodulatorInstance *>::iterator p = std::find(demods_ordered.begin(), demods_ordered.end(), demod); auto p = std::find(demods_ordered.begin(), demods_ordered.end(), demod);
if (actives) { if (actives) {
} }
@ -123,26 +132,25 @@ DemodulatorInstance *DemodulatorMgr::getNextDemodulator(DemodulatorInstance *dem
return *(++p); return *(++p);
} }
DemodulatorInstance *DemodulatorMgr::getLastDemodulator() { DemodulatorInstancePtr DemodulatorMgr::getLastDemodulator() {
std::lock_guard < std::recursive_mutex > lock(demods_busy); std::lock_guard < std::recursive_mutex > lock(demods_busy);
std::vector<DemodulatorInstance *> demods_ordered = getOrderedDemodulators();
return *(demods_ordered.end()); return getOrderedDemodulators().back();
} }
DemodulatorInstance *DemodulatorMgr::getFirstDemodulator() { DemodulatorInstancePtr DemodulatorMgr::getFirstDemodulator() {
std::lock_guard < std::recursive_mutex > lock(demods_busy); std::lock_guard < std::recursive_mutex > lock(demods_busy);
std::vector<DemodulatorInstance *> demods_ordered = getOrderedDemodulators();
return *(demods_ordered.begin()); return getOrderedDemodulators().front();
} }
void DemodulatorMgr::deleteThread(DemodulatorInstance *demod) { void DemodulatorMgr::deleteThread(DemodulatorInstancePtr demod) {
std::lock_guard < std::recursive_mutex > lock(demods_busy); std::lock_guard < std::recursive_mutex > lock(demods_busy);
wxGetApp().getBookmarkMgr().addRecent(demod); wxGetApp().getBookmarkMgr().addRecent(demod);
std::vector<DemodulatorInstance *>::iterator i; auto i = std::find(demods.begin(), demods.end(), demod);
i = std::find(demods.begin(), demods.end(), demod);
if (activeDemodulator == demod) { if (activeDemodulator == demod) {
activeDemodulator = nullptr; activeDemodulator = nullptr;
@ -161,19 +169,15 @@ void DemodulatorMgr::deleteThread(DemodulatorInstance *demod) {
//Ask for termination //Ask for termination
demod->setActive(false); demod->setActive(false);
demod->terminate(); demod->terminate();
//Do not cleanup immediatly
std::lock_guard < std::mutex > lock_deleted(deleted_demods_busy);
demods_deleted.push_back(demod);
} }
std::vector<DemodulatorInstance *> DemodulatorMgr::getDemodulatorsAt(long long freq, int bandwidth) { std::vector<DemodulatorInstancePtr> DemodulatorMgr::getDemodulatorsAt(long long freq, int bandwidth) {
std::lock_guard < std::recursive_mutex > lock(demods_busy); std::lock_guard < std::recursive_mutex > lock(demods_busy);
std::vector<DemodulatorInstance *> foundDemods; std::vector<DemodulatorInstancePtr> foundDemods;
for (int i = 0, iMax = demods.size(); i < iMax; i++) { for (int i = 0, iMax = demods.size(); i < iMax; i++) {
DemodulatorInstance *testDemod = demods[i]; DemodulatorInstancePtr testDemod = demods[i];
long long freqTest = testDemod->getFrequency(); long long freqTest = testDemod->getFrequency();
long long bandwidthTest = testDemod->getBandwidth(); long long bandwidthTest = testDemod->getBandwidth();
@ -192,7 +196,7 @@ std::vector<DemodulatorInstance *> DemodulatorMgr::getDemodulatorsAt(long long f
bool DemodulatorMgr::anyDemodulatorsAt(long long freq, int bandwidth) { bool DemodulatorMgr::anyDemodulatorsAt(long long freq, int bandwidth) {
std::lock_guard < std::recursive_mutex > lock(demods_busy); std::lock_guard < std::recursive_mutex > lock(demods_busy);
for (int i = 0, iMax = demods.size(); i < iMax; i++) { for (int i = 0, iMax = demods.size(); i < iMax; i++) {
DemodulatorInstance *testDemod = demods[i]; DemodulatorInstancePtr testDemod = demods[i];
long long freqTest = testDemod->getFrequency(); long long freqTest = testDemod->getFrequency();
long long bandwidthTest = testDemod->getBandwidth(); long long bandwidthTest = testDemod->getBandwidth();
@ -210,32 +214,34 @@ bool DemodulatorMgr::anyDemodulatorsAt(long long freq, int bandwidth) {
} }
void DemodulatorMgr::setActiveDemodulator(DemodulatorInstance *demod, bool temporary) { void DemodulatorMgr::setActiveDemodulator(DemodulatorInstancePtr demod, bool temporary) {
std::lock_guard < std::recursive_mutex > lock(demods_busy);
if (!temporary) { if (!temporary) {
if (activeDemodulator.load() != nullptr) { if (activeDemodulator != nullptr) {
lastActiveDemodulator = activeDemodulator.load(); lastActiveDemodulator = activeDemodulator;
updateLastState(); updateLastState();
} else { } else {
lastActiveDemodulator = demod; lastActiveDemodulator = demod;
} }
updateLastState(); updateLastState();
#if USE_HAMLIB #if USE_HAMLIB
if (wxGetApp().rigIsActive() && wxGetApp().getRigThread()->getFollowModem() && lastActiveDemodulator.load()) { if (wxGetApp().rigIsActive() && wxGetApp().getRigThread()->getFollowModem() && lastActiveDemodulator) {
wxGetApp().getRigThread()->setFrequency(lastActiveDemodulator.load()->getFrequency(),true); wxGetApp().getRigThread()->setFrequency(lastActiveDemodulator->getFrequency(),true);
} }
#endif #endif
wxGetApp().getBookmarkMgr().updateActiveList(); wxGetApp().getBookmarkMgr().updateActiveList();
} }
if (activeVisualDemodulator.load()) { if (activeVisualDemodulator) {
activeVisualDemodulator.load()->setVisualOutputQueue(nullptr); activeVisualDemodulator->setVisualOutputQueue(nullptr);
} }
if (demod) { if (demod) {
demod->setVisualOutputQueue(wxGetApp().getAudioVisualQueue()); demod->setVisualOutputQueue(wxGetApp().getAudioVisualQueue());
activeVisualDemodulator = demod; activeVisualDemodulator = demod;
} else { } else {
DemodulatorInstance *last = getLastActiveDemodulator(); DemodulatorInstancePtr last = getLastActiveDemodulator();
if (last) { if (last) {
last->setVisualOutputQueue(wxGetApp().getAudioVisualQueue()); last->setVisualOutputQueue(wxGetApp().getAudioVisualQueue());
} }
@ -246,25 +252,41 @@ void DemodulatorMgr::setActiveDemodulator(DemodulatorInstance *demod, bool tempo
} }
DemodulatorInstance *DemodulatorMgr::getActiveDemodulator() { //Dangerous: this is only intended by some internal classes
if (activeDemodulator.load() && !activeDemodulator.load()->isActive()) { void DemodulatorMgr::setActiveDemodulatorByRawPointer(DemodulatorInstance* demod, bool temporary) {
std::lock_guard < std::recursive_mutex > lock(demods_busy);
for (auto existing_demod : demods) {
if (existing_demod.get() == demod) {
setActiveDemodulator(existing_demod, temporary);
break;
}
}
}
DemodulatorInstancePtr DemodulatorMgr::getActiveDemodulator() {
std::lock_guard < std::recursive_mutex > lock(demods_busy);
if (activeDemodulator && !activeDemodulator->isActive()) {
activeDemodulator = getLastActiveDemodulator(); activeDemodulator = getLastActiveDemodulator();
} }
return activeDemodulator; return activeDemodulator;
} }
DemodulatorInstance *DemodulatorMgr::getLastActiveDemodulator() { DemodulatorInstancePtr DemodulatorMgr::getLastActiveDemodulator() {
return lastActiveDemodulator; return lastActiveDemodulator;
} }
DemodulatorInstance *DemodulatorMgr::getLastDemodulatorWith(const std::string& type, DemodulatorInstancePtr DemodulatorMgr::getLastDemodulatorWith(const std::string& type,
const std::wstring& userLabel, const std::wstring& userLabel,
long long frequency, long long frequency,
int bandwidth) { int bandwidth) {
std::lock_guard < std::recursive_mutex > lock(demods_busy); std::lock_guard < std::recursive_mutex > lock(demods_busy);
//backwards search: //backwards search:
for (std::vector<DemodulatorInstance *>::reverse_iterator it = demods.rbegin(); it != demods.rend(); it++) { for (auto it = demods.rbegin(); it != demods.rend(); it++) {
if ((*it)->getDemodulatorType() == type && if ((*it)->getDemodulatorType() == type &&
(*it)->getDemodulatorUserLabel() == userLabel && (*it)->getDemodulatorUserLabel() == userLabel &&
@ -278,86 +300,31 @@ DemodulatorInstance *DemodulatorMgr::getLastDemodulatorWith(const std::string& t
return nullptr; return nullptr;
} }
bool DemodulatorMgr::garbageCollect(bool forcedGC, int maxWaitForTerminationMs) {
#define SPIN_WAIT_SLEEP_MS 5
//this is a stupid busy plus sleep loop
int nbCyclesToWait = 0;
if (maxWaitForTerminationMs <= 0) {
nbCyclesToWait = std::numeric_limits<int>::max();
}
else {
nbCyclesToWait = (maxWaitForTerminationMs / SPIN_WAIT_SLEEP_MS) + 1;
}
int currentWaitCycle = 0;
std::lock_guard < std::mutex > lock(deleted_demods_busy);
while (!demods_deleted.empty()) {
std::vector<DemodulatorInstance *>::iterator it = demods_deleted.begin();
//make 1 pass over
while (it != demods_deleted.end()) {
if ((*it)->isTerminated()) {
DemodulatorInstance *deleted = (*it);
std::cout << "Garbage collected demodulator instance '" << deleted->getLabel() << "'... " << std::endl << std::flush;
it = demods_deleted.erase(it);
delete deleted;
//only garbage collect 1 demod at a time.
if (!forcedGC) {
return true;
}
}
else {
it++;
}
} //end while
//stupid busy-wait loop
std::this_thread::sleep_for(std::chrono::milliseconds(SPIN_WAIT_SLEEP_MS));
currentWaitCycle++;
if (currentWaitCycle >= nbCyclesToWait) {
std::cout << "ERROR: DemodulatorMgr::garbageCollect() has not terminated in time ! (> " << (currentWaitCycle * SPIN_WAIT_SLEEP_MS) << " ms)" << std::endl << std::flush;
return false;
}
} //end while not empty
return true;
}
void DemodulatorMgr::updateLastState() { void DemodulatorMgr::updateLastState() {
std::lock_guard < std::recursive_mutex > lock(demods_busy); std::lock_guard < std::recursive_mutex > lock(demods_busy);
if (std::find(demods.begin(), demods.end(), lastActiveDemodulator) == demods.end()) { if (std::find(demods.begin(), demods.end(), lastActiveDemodulator) == demods.end()) {
if (activeDemodulator.load() && activeDemodulator.load()->isActive()) { if (activeDemodulator && activeDemodulator->isActive()) {
lastActiveDemodulator = activeDemodulator.load(); lastActiveDemodulator = activeDemodulator;
} else if (activeDemodulator.load() && !activeDemodulator.load()->isActive()){ } else if (activeDemodulator && !activeDemodulator->isActive()){
activeDemodulator = nullptr; activeDemodulator = nullptr;
lastActiveDemodulator = nullptr; lastActiveDemodulator = nullptr;
} }
} }
if (lastActiveDemodulator.load() && !lastActiveDemodulator.load()->isActive()) { if (lastActiveDemodulator && !lastActiveDemodulator->isActive()) {
lastActiveDemodulator = nullptr; lastActiveDemodulator = nullptr;
} }
if (lastActiveDemodulator.load()) { if (lastActiveDemodulator) {
lastBandwidth = lastActiveDemodulator.load()->getBandwidth(); lastBandwidth = lastActiveDemodulator->getBandwidth();
lastDemodType = lastActiveDemodulator.load()->getDemodulatorType(); lastDemodType = lastActiveDemodulator->getDemodulatorType();
lastDemodLock = lastActiveDemodulator.load()->getDemodulatorLock()?true:false; lastDemodLock = lastActiveDemodulator->getDemodulatorLock()?true:false;
lastSquelchEnabled = lastActiveDemodulator.load()->isSquelchEnabled(); lastSquelchEnabled = lastActiveDemodulator->isSquelchEnabled();
lastSquelch = lastActiveDemodulator.load()->getSquelchLevel(); lastSquelch = lastActiveDemodulator->getSquelchLevel();
lastGain = lastActiveDemodulator.load()->getGain(); lastGain = lastActiveDemodulator->getGain();
lastModemSettings[lastDemodType] = lastActiveDemodulator.load()->readModemSettings(); lastModemSettings[lastDemodType] = lastActiveDemodulator->readModemSettings();
} }
} }
@ -436,7 +403,8 @@ void DemodulatorMgr::setOutputDevices(std::map<int,RtAudio::DeviceInfo> devs) {
outputDevices = devs; outputDevices = devs;
} }
void DemodulatorMgr::saveInstance(DataNode *node, DemodulatorInstance *inst) { void DemodulatorMgr::saveInstance(DataNode *node, DemodulatorInstancePtr inst) {
*node->newChild("bandwidth") = inst->getBandwidth(); *node->newChild("bandwidth") = inst->getBandwidth();
*node->newChild("frequency") = inst->getFrequency(); *node->newChild("frequency") = inst->getFrequency();
*node->newChild("type") = inst->getDemodulatorType(); *node->newChild("type") = inst->getDemodulatorType();
@ -465,11 +433,11 @@ void DemodulatorMgr::saveInstance(DataNode *node, DemodulatorInstance *inst) {
} }
} }
DemodulatorInstance *DemodulatorMgr::loadInstance(DataNode *node) { DemodulatorInstancePtr DemodulatorMgr::loadInstance(DataNode *node) {
std::lock_guard < std::recursive_mutex > lock(demods_busy); std::lock_guard < std::recursive_mutex > lock(demods_busy);
DemodulatorInstance *newDemod = nullptr; DemodulatorInstancePtr newDemod = nullptr;
node->rewindAll(); node->rewindAll();

View File

@ -16,23 +16,32 @@ public:
DemodulatorMgr(); DemodulatorMgr();
~DemodulatorMgr(); ~DemodulatorMgr();
DemodulatorInstance *newThread(); DemodulatorInstancePtr newThread();
std::vector<DemodulatorInstance *> &getDemodulators();
std::vector<DemodulatorInstance *> getOrderedDemodulators(bool actives = true); //return snapshot-copy of the list purposefully
std::vector<DemodulatorInstance *> getDemodulatorsAt(long long freq, int bandwidth); std::vector<DemodulatorInstancePtr> getDemodulators();
DemodulatorInstance *getPreviousDemodulator(DemodulatorInstance *demod, bool actives = true);
DemodulatorInstance *getNextDemodulator(DemodulatorInstance *demod, bool actives = true); std::vector<DemodulatorInstancePtr> getOrderedDemodulators(bool actives = true);
DemodulatorInstance *getLastDemodulator(); std::vector<DemodulatorInstancePtr> getDemodulatorsAt(long long freq, int bandwidth);
DemodulatorInstance *getFirstDemodulator();
DemodulatorInstancePtr getPreviousDemodulator(DemodulatorInstancePtr demod, bool actives = true);
DemodulatorInstancePtr getNextDemodulator(DemodulatorInstancePtr demod, bool actives = true);
DemodulatorInstancePtr getLastDemodulator();
DemodulatorInstancePtr getFirstDemodulator();
bool anyDemodulatorsAt(long long freq, int bandwidth); bool anyDemodulatorsAt(long long freq, int bandwidth);
void deleteThread(DemodulatorInstance *); void deleteThread(DemodulatorInstancePtr);
void terminateAll(); void terminateAll();
void setActiveDemodulator(DemodulatorInstance *demod, bool temporary = true); void setActiveDemodulator(DemodulatorInstancePtr demod, bool temporary = true);
DemodulatorInstance *getActiveDemodulator();
DemodulatorInstance *getLastActiveDemodulator(); //Dangerous: this is only intended by some internal classes,
DemodulatorInstance *getLastDemodulatorWith(const std::string& type, // and only set a pre-existing demod
void setActiveDemodulatorByRawPointer(DemodulatorInstance* demod, bool temporary = true);
DemodulatorInstancePtr getActiveDemodulator();
DemodulatorInstancePtr getLastActiveDemodulator();
DemodulatorInstancePtr getLastDemodulatorWith(const std::string& type,
const std::wstring& userLabel, const std::wstring& userLabel,
long long frequency, long long frequency,
int bandwidth); int bandwidth);
@ -64,28 +73,17 @@ public:
void updateLastState(); void updateLastState();
void setOutputDevices(std::map<int,RtAudio::DeviceInfo> devs); void setOutputDevices(std::map<int,RtAudio::DeviceInfo> devs);
void saveInstance(DataNode *node, DemodulatorInstance *inst); void saveInstance(DataNode *node, DemodulatorInstancePtr inst);
DemodulatorInstance *loadInstance(DataNode *node); DemodulatorInstancePtr loadInstance(DataNode *node);
//to be called periodically to cleanup removed demodulators.
//if forcedGC = true, the methods waits until
//all deleted demodulators are effectively GCed.
//else: (default) the method test for effective termination
//and GC one demod per call.
// if forcedGC = true and maxWaitForTerminationMs > 0, do not
//block the method more than maxWaitForTerminationMs millisecs before returning.
//Returns: true if forcedGC = false, else true only if all deleted demodulators were GCs before maxWaitForTerminationMs.
bool garbageCollect(bool forcedGC = false, int maxWaitForTerminationMs = 0);
private: private:
std::vector<DemodulatorInstance *> demods; std::vector<DemodulatorInstancePtr> demods;
std::vector<DemodulatorInstance *> demods_deleted;
std::atomic<DemodulatorInstance *> activeDemodulator; DemodulatorInstancePtr activeDemodulator;
std::atomic<DemodulatorInstance *> lastActiveDemodulator; DemodulatorInstancePtr lastActiveDemodulator;
std::atomic<DemodulatorInstance *> activeVisualDemodulator; DemodulatorInstancePtr activeVisualDemodulator;
int lastBandwidth; int lastBandwidth;
std::string lastDemodType; std::string lastDemodType;
@ -99,9 +97,7 @@ private:
//protects access to demods lists and such, need to be recursive //protects access to demods lists and such, need to be recursive
//because of the usage of public re-entrant methods //because of the usage of public re-entrant methods
std::recursive_mutex demods_busy; std::recursive_mutex demods_busy;
std::mutex deleted_demods_busy;
std::map<std::string, ModemSettings> lastModemSettings; std::map<std::string, ModemSettings> lastModemSettings;
std::map<int,RtAudio::DeviceInfo> outputDevices; std::map<int,RtAudio::DeviceInfo> outputDevices;
}; };

View File

@ -15,7 +15,7 @@
//50 ms //50 ms
#define HEARTBEAT_CHECK_PERIOD_MICROS (50 * 1000) #define HEARTBEAT_CHECK_PERIOD_MICROS (50 * 1000)
DemodulatorPreThread::DemodulatorPreThread(DemodulatorInstance *parent) : IOThread(), iqResampler(NULL), iqResampleRatio(1), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), iqOutputQueue(NULL) DemodulatorPreThread::DemodulatorPreThread(DemodulatorInstance* parent) : IOThread(), iqResampler(NULL), iqResampleRatio(1), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), iqOutputQueue(NULL)
{ {
initialized.store(false); initialized.store(false);
this->parent = parent; this->parent = parent;

View File

@ -17,7 +17,7 @@ class DemodulatorInstance;
class DemodulatorPreThread : public IOThread { class DemodulatorPreThread : public IOThread {
public: public:
DemodulatorPreThread(DemodulatorInstance *parent); DemodulatorPreThread(DemodulatorInstance* parent);
virtual ~DemodulatorPreThread(); virtual ~DemodulatorPreThread();
virtual void run(); virtual void run();
@ -50,7 +50,9 @@ public:
void writeModemSettings(ModemSettings settings); void writeModemSettings(ModemSettings settings);
protected: protected:
DemodulatorInstance *parent;
DemodulatorInstance* parent;
msresamp_crcf iqResampler; msresamp_crcf iqResampler;
double iqResampleRatio; double iqResampleRatio;
std::vector<liquid_float_complex> resampledData; std::vector<liquid_float_complex> resampledData;

View File

@ -19,10 +19,10 @@
#include <pthread.h> #include <pthread.h>
#endif #endif
std::atomic<DemodulatorInstance *> DemodulatorThread::squelchLock(nullptr); DemodulatorInstance* DemodulatorThread::squelchLock(nullptr);
std::mutex DemodulatorThread::squelchLockMutex; std::mutex DemodulatorThread::squelchLockMutex;
DemodulatorThread::DemodulatorThread(DemodulatorInstance *parent) DemodulatorThread::DemodulatorThread(DemodulatorInstance* parent)
: IOThread(), outputBuffers("DemodulatorThreadBuffers"), squelchLevel(-100), : IOThread(), outputBuffers("DemodulatorThreadBuffers"), squelchLevel(-100),
signalLevel(-100), signalFloor(-30), signalCeil(30), squelchEnabled(false) { signalLevel(-100), signalFloor(-30), signalCeil(30), squelchEnabled(false) {
@ -201,10 +201,10 @@ void DemodulatorThread::run() {
if (!squelched && !squelchBreak) { if (!squelched && !squelchBreak) {
if (wxGetApp().getSoloMode() && !wxGetApp().getAppFrame()->isUserDemodBusy()) { if (wxGetApp().getSoloMode() && !wxGetApp().getAppFrame()->isUserDemodBusy()) {
std::lock_guard < std::mutex > lock(squelchLockMutex); std::lock_guard < std::mutex > lock(squelchLockMutex);
if (squelchLock.load() == nullptr) { if (squelchLock == nullptr) {
squelchLock.store(demodInstance); squelchLock = demodInstance;
wxGetApp().getDemodMgr().setActiveDemodulator(nullptr); wxGetApp().getDemodMgr().setActiveDemodulator(nullptr);
wxGetApp().getDemodMgr().setActiveDemodulator(demodInstance, false); wxGetApp().getDemodMgr().setActiveDemodulatorByRawPointer(demodInstance, false);
squelchBreak = true; squelchBreak = true;
demodInstance->getVisualCue()->triggerSquelchBreak(120); demodInstance->getVisualCue()->triggerSquelchBreak(120);
} }
@ -310,7 +310,7 @@ void DemodulatorThread::run() {
} }
if (ati != nullptr) { if (ati != nullptr) {
if (!muted.load() && (!wxGetApp().getSoloMode() || (demodInstance == wxGetApp().getDemodMgr().getLastActiveDemodulator()))) { if (!muted.load() && (!wxGetApp().getSoloMode() || (demodInstance == wxGetApp().getDemodMgr().getLastActiveDemodulator().get()))) {
//non-blocking push needed for audio out //non-blocking push needed for audio out
if (!audioOutputQueue->try_push(ati)) { if (!audioOutputQueue->try_push(ati)) {
@ -385,9 +385,11 @@ bool DemodulatorThread::getSquelchBreak() {
return squelchBreak; return squelchBreak;
} }
void DemodulatorThread::releaseSquelchLock(DemodulatorInstance *inst) { void DemodulatorThread::releaseSquelchLock(DemodulatorInstance* inst) {
std::lock_guard < std::mutex > lock(squelchLockMutex); std::lock_guard < std::mutex > lock(squelchLockMutex);
if (inst == nullptr || squelchLock.load() == inst) {
squelchLock.store(nullptr); if (inst == nullptr || squelchLock == inst) {
squelchLock = nullptr;
} }
} }

View File

@ -11,10 +11,6 @@
#include "AudioThread.h" #include "AudioThread.h"
#include "Modem.h" #include "Modem.h"
typedef ThreadBlockingQueue<AudioThreadInputPtr> DemodulatorThreadOutputQueue;
typedef std::shared_ptr<DemodulatorThreadOutputQueue> DemodulatorThreadOutputQueuePtr;
#define DEMOD_VIS_SIZE 2048 #define DEMOD_VIS_SIZE 2048
#define DEMOD_SIGNAL_MIN -30 #define DEMOD_SIGNAL_MIN -30
#define DEMOD_SIGNAL_MAX 30 #define DEMOD_SIGNAL_MAX 30
@ -24,7 +20,7 @@ class DemodulatorInstance;
class DemodulatorThread : public IOThread { class DemodulatorThread : public IOThread {
public: public:
DemodulatorThread(DemodulatorInstance *parent); DemodulatorThread(DemodulatorInstance* parent);
virtual ~DemodulatorThread(); virtual ~DemodulatorThread();
void onBindOutput(std::string name, ThreadQueueBasePtr threadQueue); void onBindOutput(std::string name, ThreadQueueBasePtr threadQueue);
@ -43,13 +39,14 @@ public:
bool getSquelchBreak(); bool getSquelchBreak();
static void releaseSquelchLock(DemodulatorInstance *inst);
static void releaseSquelchLock(DemodulatorInstance* inst);
protected: protected:
double abMagnitude(float inphase, float quadrature); double abMagnitude(float inphase, float quadrature);
double linearToDb(double linear); double linearToDb(double linear);
DemodulatorInstance *demodInstance = nullptr; DemodulatorInstance* demodInstance;
ReBuffer<AudioThreadInput> outputBuffers; ReBuffer<AudioThreadInput> outputBuffers;
std::atomic_bool muted; std::atomic_bool muted;
@ -58,7 +55,7 @@ protected:
std::atomic<float> signalLevel, signalFloor, signalCeil; std::atomic<float> signalLevel, signalFloor, signalCeil;
bool squelchEnabled, squelchBreak; bool squelchEnabled, squelchBreak;
static std::atomic<DemodulatorInstance *> squelchLock; static DemodulatorInstance* squelchLock;
static std::mutex squelchLockMutex; static std::mutex squelchLockMutex;

View File

@ -9,9 +9,6 @@
//50 ms //50 ms
#define HEARTBEAT_CHECK_PERIOD_MICROS (50 * 1000) #define HEARTBEAT_CHECK_PERIOD_MICROS (50 * 1000)
//1s
#define MAX_BLOCKING_DURATION_MICROS (1000 * 1000)
DemodulatorWorkerThread::DemodulatorWorkerThread() : IOThread(), DemodulatorWorkerThread::DemodulatorWorkerThread() : IOThread(),
commandQueue(nullptr), resultQueue(nullptr), cModem(nullptr), cModemKit(nullptr) { commandQueue(nullptr), resultQueue(nullptr), cModem(nullptr), cModemKit(nullptr) {
} }
@ -111,7 +108,7 @@ void DemodulatorWorkerThread::run() {
result.modemName = cModemName; result.modemName = cModemName;
//VSO: blocking push //VSO: blocking push
resultQueue->push(result, MAX_BLOCKING_DURATION_MICROS, "resultQueue"); resultQueue->push(result);
} }
} }
// std::cout << "Demodulator worker thread done." << std::endl; // std::cout << "Demodulator worker thread done." << std::endl;

View File

@ -348,10 +348,9 @@ wxTreeItemId BookmarkView::refreshBookmarks() {
void BookmarkView::doUpdateActiveList() { void BookmarkView::doUpdateActiveList() {
std::vector<DemodulatorInstance *> &demods = wxGetApp().getDemodMgr().getDemodulators();
auto demods = wxGetApp().getDemodMgr().getDemodulators();
// DemodulatorInstance *activeDemodulator = wxGetApp().getDemodMgr().getActiveDemodulator(); auto lastActiveDemodulator = wxGetApp().getDemodMgr().getLastActiveDemodulator();
DemodulatorInstance *lastActiveDemodulator = wxGetApp().getDemodMgr().getLastActiveDemodulator();
//capture the previously selected item info BY COPY (because the original will be destroyed together with the destroyed tree items) to restore it again after //capture the previously selected item info BY COPY (because the original will be destroyed together with the destroyed tree items) to restore it again after
//having rebuilding the whole tree. //having rebuilding the whole tree.
@ -693,7 +692,8 @@ wxButton *BookmarkView::addButton(wxWindow *parent, std::string labelVal, wxObje
} }
void BookmarkView::doBookmarkActive(std::string group, DemodulatorInstance *demod) { void BookmarkView::doBookmarkActive(std::string group, DemodulatorInstancePtr demod) {
wxGetApp().getBookmarkMgr().addBookmark(group, demod); wxGetApp().getBookmarkMgr().addBookmark(group, demod);
wxGetApp().getBookmarkMgr().updateBookmarks(); wxGetApp().getBookmarkMgr().updateBookmarks();
} }
@ -717,7 +717,7 @@ void BookmarkView::doMoveBookmark(BookmarkEntryPtr be, std::string group) {
} }
void BookmarkView::doRemoveActive(DemodulatorInstance *demod) { void BookmarkView::doRemoveActive(DemodulatorInstancePtr demod) {
wxGetApp().getBookmarkMgr().removeActive(demod); wxGetApp().getBookmarkMgr().removeActive(demod);
wxGetApp().getBookmarkMgr().updateActiveList(); wxGetApp().getBookmarkMgr().updateActiveList();
@ -792,7 +792,7 @@ void BookmarkView::onBookmarkChoice( wxCommandEvent & /* event */ ) {
} }
void BookmarkView::activeSelection(DemodulatorInstance *dsel) { void BookmarkView::activeSelection(DemodulatorInstancePtr dsel) {
m_frequencyVal->SetLabelText(frequencyToStr(dsel->getFrequency())); m_frequencyVal->SetLabelText(frequencyToStr(dsel->getFrequency()));
m_bandwidthVal->SetLabelText(frequencyToStr(dsel->getBandwidth())); m_bandwidthVal->SetLabelText(frequencyToStr(dsel->getBandwidth()));
@ -835,7 +835,7 @@ void BookmarkView::activateBookmark(BookmarkEntryPtr bmEnt) {
//the already existing one: //the already existing one:
// we search among the list of existing demodulators the one matching // we search among the list of existing demodulators the one matching
//bmEnt and activate it. The search is made backwards, to select the most recently created one. //bmEnt and activate it. The search is made backwards, to select the most recently created one.
DemodulatorInstance *matchingDemod = wxGetApp().getDemodMgr().getLastDemodulatorWith( DemodulatorInstancePtr matchingDemod = wxGetApp().getDemodMgr().getLastDemodulatorWith(
bmEnt->type, bmEnt->type,
bmEnt->label, bmEnt->label,
bmEnt->frequency, bmEnt->frequency,
@ -845,7 +845,7 @@ void BookmarkView::activateBookmark(BookmarkEntryPtr bmEnt) {
matchingDemod = wxGetApp().getDemodMgr().loadInstance(bmEnt->node); matchingDemod = wxGetApp().getDemodMgr().loadInstance(bmEnt->node);
matchingDemod->run(); matchingDemod->run();
wxGetApp().bindDemodulator(matchingDemod); wxGetApp().notifyDemodulatorsChanged();
} }
matchingDemod->setActive(true); matchingDemod->setActive(true);

View File

@ -43,7 +43,7 @@ public:
BookmarkEntryPtr bookmarkEnt; BookmarkEntryPtr bookmarkEnt;
BookmarkRangeEntryPtr rangeEnt; BookmarkRangeEntryPtr rangeEnt;
DemodulatorInstance* demod; DemodulatorInstancePtr demod;
std::string groupName; std::string groupName;
}; };
@ -84,7 +84,7 @@ public:
static BookmarkRangeEntryPtr makeActiveRangeEntry(); static BookmarkRangeEntryPtr makeActiveRangeEntry();
protected: protected:
void activeSelection(DemodulatorInstance *dsel); void activeSelection(DemodulatorInstancePtr dsel);
void bookmarkSelection(BookmarkEntryPtr bmSel); void bookmarkSelection(BookmarkEntryPtr bmSel);
void rangeSelection(BookmarkRangeEntryPtr re); void rangeSelection(BookmarkRangeEntryPtr re);
@ -133,10 +133,10 @@ protected:
wxButton *makeButton(wxWindow *parent, std::string labelVal, wxObjectEventFunction handler); wxButton *makeButton(wxWindow *parent, std::string labelVal, wxObjectEventFunction handler);
wxButton *addButton(wxWindow *parent, std::string labelVal, wxObjectEventFunction handler); wxButton *addButton(wxWindow *parent, std::string labelVal, wxObjectEventFunction handler);
void doBookmarkActive(std::string group, DemodulatorInstance *demod); void doBookmarkActive(std::string group, DemodulatorInstancePtr demod);
void doBookmarkRecent(std::string group, BookmarkEntryPtr be); void doBookmarkRecent(std::string group, BookmarkEntryPtr be);
void doMoveBookmark(BookmarkEntryPtr be, std::string group); void doMoveBookmark(BookmarkEntryPtr be, std::string group);
void doRemoveActive(DemodulatorInstance *demod); void doRemoveActive(DemodulatorInstancePtr demod);
void doRemoveRecent(BookmarkEntryPtr be); void doRemoveRecent(BookmarkEntryPtr be);
void doClearRecents(); void doClearRecents();
@ -191,7 +191,7 @@ protected:
// Focus // Focus
BookmarkEntryPtr nextEnt; BookmarkEntryPtr nextEnt;
BookmarkRangeEntryPtr nextRange; BookmarkRangeEntryPtr nextRange;
DemodulatorInstance *nextDemod; DemodulatorInstancePtr nextDemod;
std::string nextGroup; std::string nextGroup;
// Search // Search

View File

@ -73,8 +73,8 @@ void RigThread::run() {
while (!stopping) { while (!stopping) {
std::this_thread::sleep_for(std::chrono::milliseconds(150)); std::this_thread::sleep_for(std::chrono::milliseconds(150));
DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator(); auto activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator();
DemodulatorInstance *lastDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); auto lastDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
if (freqChanged.load() && (controlMode.load() || setOneShot.load())) { if (freqChanged.load() && (controlMode.load() || setOneShot.load())) {
status = rig_get_freq(rig, RIG_VFO_CURR, &freq); status = rig_get_freq(rig, RIG_VFO_CURR, &freq);

View File

@ -16,12 +16,12 @@
#define MAX_BLOCKING_DURATION_MICROS (1000 * 1000) #define MAX_BLOCKING_DURATION_MICROS (1000 * 1000)
SDRPostThread::SDRPostThread() : IOThread(), buffers("SDRPostThreadBuffers"), visualDataBuffers("SDRPostThreadVisualDataBuffers"), frequency(0) { SDRPostThread::SDRPostThread() : IOThread(), buffers("SDRPostThreadBuffers"), visualDataBuffers("SDRPostThreadVisualDataBuffers"), frequency(0) {
iqDataInQueue = NULL; iqDataInQueue = nullptr;
iqDataOutQueue = NULL; iqDataOutQueue = nullptr;
iqVisualQueue = NULL; iqVisualQueue = nullptr;
numChannels = 0; numChannels = 0;
channelizer = NULL; channelizer = nullptr;
sampleRate = 0; sampleRate = 0;
nRunDemods = 0; nRunDemods = 0;
@ -36,44 +36,12 @@ SDRPostThread::SDRPostThread() : IOThread(), buffers("SDRPostThreadBuffers"), vi
SDRPostThread::~SDRPostThread() { SDRPostThread::~SDRPostThread() {
} }
void SDRPostThread::bindDemodulator(DemodulatorInstance *demod) { void SDRPostThread::notifyDemodulatorsChanged() {
std::lock_guard < std::mutex > lock(busy_demod);
demodulators.push_back(demod);
doRefresh.store(true); doRefresh.store(true);
} }
void SDRPostThread::bindDemodulators(std::vector<DemodulatorInstance *> *demods) {
if (!demods) {
return;
}
std::lock_guard < std::mutex > lock(busy_demod);
for (std::vector<DemodulatorInstance *>::iterator di = demods->begin(); di != demods->end(); di++) {
demodulators.push_back(*di);
doRefresh.store(true);
}
}
void SDRPostThread::removeDemodulator(DemodulatorInstance *demod) {
if (!demod) {
return;
}
std::lock_guard < std::mutex > lock(busy_demod);
std::vector<DemodulatorInstance *>::iterator i = std::find(demodulators.begin(), demodulators.end(), demod);
if (i != demodulators.end()) {
demodulators.erase(i);
doRefresh.store(true);
}
}
void SDRPostThread::initPFBChannelizer() { void SDRPostThread::initPFBChannelizer() {
// std::cout << "Initializing post-process FIR polyphase filterbank channelizer with " << numChannels << " channels." << std::endl; // std::cout << "Initializing post-process FIR polyphase filterbank channelizer with " << numChannels << " channels." << std::endl;
if (channelizer) { if (channelizer) {
@ -91,15 +59,16 @@ void SDRPostThread::initPFBChannelizer() {
void SDRPostThread::updateActiveDemodulators() { void SDRPostThread::updateActiveDemodulators() {
// In range? // In range?
std::vector<DemodulatorInstance *>::iterator demod_i;
nRunDemods = 0; nRunDemods = 0;
long long centerFreq = wxGetApp().getFrequency(); long long centerFreq = wxGetApp().getFrequency();
for (demod_i = demodulators.begin(); demod_i != demodulators.end(); demod_i++) { //retreive the current list of demodulators:
DemodulatorInstance *demod = *demod_i; auto demodulators = wxGetApp().getDemodMgr().getDemodulators();
for (auto demod : demodulators) {
// not in range? // not in range?
if (demod->isDeltaLock()) { if (demod->isDeltaLock()) {
if (demod->getFrequency() != centerFreq + demod->getDeltaLockOfs()) { if (demod->getFrequency() != centerFreq + demod->getDeltaLockOfs()) {
@ -123,7 +92,7 @@ void SDRPostThread::updateActiveDemodulators() {
} }
} else if (!demod->isActive()) { // in range, activate if not activated } else if (!demod->isActive()) { // in range, activate if not activated
demod->setActive(true); demod->setActive(true);
if (wxGetApp().getDemodMgr().getLastActiveDemodulator() == NULL) { if (wxGetApp().getDemodMgr().getLastActiveDemodulator() == nullptr) {
wxGetApp().getDemodMgr().setActiveDemodulator(demod); wxGetApp().getDemodMgr().setActiveDemodulator(demod);
} }
@ -194,9 +163,8 @@ void SDRPostThread::run() {
if (!iqDataInQueue->pop(data_in, HEARTBEAT_CHECK_PERIOD_MICROS)) { if (!iqDataInQueue->pop(data_in, HEARTBEAT_CHECK_PERIOD_MICROS)) {
continue; continue;
} }
// std::lock_guard < std::mutex > lock(data_in->m_mutex);
bool doUpdate = false;
std::lock_guard < std::mutex > lock(busy_demod);
if (data_in && data_in->data.size()) { if (data_in && data_in->data.size()) {
if(data_in->numChannels > 1) { if(data_in->numChannels > 1) {
@ -205,17 +173,16 @@ void SDRPostThread::run() {
runSingleCH(data_in.get()); runSingleCH(data_in.get());
} }
} }
bool doUpdate = false;
for (size_t j = 0; j < nRunDemods; j++) { for (size_t j = 0; j < nRunDemods; j++) {
DemodulatorInstance *demod = runDemods[j]; DemodulatorInstancePtr demod = runDemods[j];
if (abs(frequency - demod->getFrequency()) > (sampleRate / 2)) { if (abs(frequency - demod->getFrequency()) > (sampleRate / 2)) {
doUpdate = true; doUpdate = true;
} }
} }
//Only update the list of demodulators here //Only update the list of demodulators here
if (doUpdate) { if (doUpdate || doRefresh) {
updateActiveDemodulators(); updateActiveDemodulators();
} }
} //end while } //end while
@ -264,9 +231,9 @@ void SDRPostThread::runSingleCH(SDRThreadIQData *data_in) {
} }
size_t refCount = nRunDemods; size_t refCount = nRunDemods;
bool doIQDataOut = (iqDataOutQueue != NULL && !iqDataOutQueue->full()); bool doIQDataOut = (iqDataOutQueue != nullptr && !iqDataOutQueue->full());
bool doDemodVisOut = (nRunDemods && iqActiveDemodVisualQueue != NULL && !iqActiveDemodVisualQueue->full()); bool doDemodVisOut = (nRunDemods && iqActiveDemodVisualQueue != nullptr && !iqActiveDemodVisualQueue->full());
bool doVisOut = (iqVisualQueue != NULL && !iqVisualQueue->full()); bool doVisOut = (iqVisualQueue != nullptr && !iqVisualQueue->full());
if (doIQDataOut) { if (doIQDataOut) {
refCount++; refCount++;
@ -295,22 +262,26 @@ void SDRPostThread::runSingleCH(SDRThreadIQData *data_in) {
if (doDemodVisOut) { if (doDemodVisOut) {
//VSO: blocking push //VSO: blocking push
iqActiveDemodVisualQueue->push(demodDataOut, MAX_BLOCKING_DURATION_MICROS, "runSingleCH() iqActiveDemodVisualQueue"); iqActiveDemodVisualQueue->push(demodDataOut);
} }
if (doIQDataOut) { if (doIQDataOut) {
//VSO: blocking push //VSO: blocking push
iqDataOutQueue->push(demodDataOut, MAX_BLOCKING_DURATION_MICROS,"runSingleCH() iqDataOutQueue"); iqDataOutQueue->push(demodDataOut);
} }
if (doVisOut) { if (doVisOut) {
//VSO: blocking push //VSO: blocking push
iqVisualQueue->push(demodDataOut, MAX_BLOCKING_DURATION_MICROS, "runSingleCH() iqVisualQueue"); iqVisualQueue->push(demodDataOut);
} }
for (size_t i = 0; i < nRunDemods; i++) { for (size_t i = 0; i < nRunDemods; i++) {
//VSO: blocking push //VSO: timed-push
runDemods[i]->getIQInputDataPipe()->push(demodDataOut, MAX_BLOCKING_DURATION_MICROS, "runSingleCH() runDemods[i]->getIQInputDataPipe()"); if (!runDemods[i]->getIQInputDataPipe()->push(demodDataOut, MAX_BLOCKING_DURATION_MICROS, "runSingleCH() runDemods[i]->getIQInputDataPipe()")) {
//some runDemods are no longer there, bail out from runSingleCH() entirely.
doRefresh = true;
return;
}
} }
} }
} }
@ -338,7 +309,7 @@ void SDRPostThread::runPFBCH(SDRThreadIQData *data_in) {
bool doVis = false; bool doVis = false;
if (iqVisualQueue != NULL && !iqVisualQueue->full()) { if (iqVisualQueue != nullptr && !iqVisualQueue->full()) {
doVis = true; doVis = true;
} }
@ -347,11 +318,11 @@ void SDRPostThread::runPFBCH(SDRThreadIQData *data_in) {
iqDataOut->data.assign(data_in->data.begin(), data_in->data.begin() + dataSize); iqDataOut->data.assign(data_in->data.begin(), data_in->data.begin() + dataSize);
//VSO: blocking push //VSO: blocking push
iqDataOutQueue->push(iqDataOut, MAX_BLOCKING_DURATION_MICROS, "runPFBCH() iqDataOutQueue"); iqDataOutQueue->push(iqDataOut);
if (doVis) { if (doVis) {
//VSO: blocking push //VSO: blocking push
iqVisualQueue->push(iqDataOut, MAX_BLOCKING_DURATION_MICROS, "runPFBCH() iqVisualQueue"); iqVisualQueue->push(iqDataOut);
} }
} }
@ -366,7 +337,7 @@ void SDRPostThread::runPFBCH(SDRThreadIQData *data_in) {
doRefresh.store(false); doRefresh.store(false);
} }
DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); DemodulatorInstancePtr activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
int activeDemodChannel = -1; int activeDemodChannel = -1;
// Find active demodulators // Find active demodulators
@ -384,7 +355,7 @@ void SDRPostThread::runPFBCH(SDRThreadIQData *data_in) {
// Find nearest channel for each demodulator // Find nearest channel for each demodulator
for (size_t i = 0; i < nRunDemods; i++) { for (size_t i = 0; i < nRunDemods; i++) {
DemodulatorInstance *demod = runDemods[i]; DemodulatorInstancePtr demod = runDemods[i];
demodChannel[i] = getChannelAt(demod->getFrequency()); demodChannel[i] = getChannelAt(demod->getFrequency());
if (demod == activeDemod) { if (demod == activeDemod) {
activeDemodChannel = demodChannel[i]; activeDemodChannel = demodChannel[i];
@ -400,7 +371,7 @@ void SDRPostThread::runPFBCH(SDRThreadIQData *data_in) {
// Run channels // Run channels
for (int i = 0; i < numChannels+1; i++) { for (int i = 0; i < numChannels+1; i++) {
int doDemodVis = ((activeDemodChannel == i) && (iqActiveDemodVisualQueue != NULL) && !iqActiveDemodVisualQueue->full())?1:0; int doDemodVis = ((activeDemodChannel == i) && (iqActiveDemodVisualQueue != nullptr) && !iqActiveDemodVisualQueue->full())?1:0;
if (!doDemodVis && demodChannelActive[i] == 0) { if (!doDemodVis && demodChannelActive[i] == 0) {
continue; continue;
@ -447,16 +418,20 @@ void SDRPostThread::runPFBCH(SDRThreadIQData *data_in) {
if (doDemodVis) { if (doDemodVis) {
//VSO: blocking push //VSO: blocking push
iqActiveDemodVisualQueue->push(demodDataOut, MAX_BLOCKING_DURATION_MICROS, "runPFBCH() iqActiveDemodVisualQueue"); iqActiveDemodVisualQueue->push(demodDataOut);
} }
for (size_t j = 0; j < nRunDemods; j++) { for (size_t j = 0; j < nRunDemods; j++) {
if (demodChannel[j] == i) { if (demodChannel[j] == i) {
DemodulatorInstance *demod = runDemods[j];
//VSO: blocking push //VSO: timed- push
demod->getIQInputDataPipe()->push(demodDataOut, MAX_BLOCKING_DURATION_MICROS, "runPFBCH() demod->getIQInputDataPipe()"); if (!runDemods[j]->getIQInputDataPipe()->push(demodDataOut, MAX_BLOCKING_DURATION_MICROS, "runPFBCH() runDemods[j]->getIQInputDataPipe()")) {
//Some runDemods are no longer there, bail out from runPFBCH() entirely.
doRefresh = true;
return;
}
} }
} } //end for
} }
} }
} }

View File

@ -11,10 +11,8 @@ public:
SDRPostThread(); SDRPostThread();
~SDRPostThread(); ~SDRPostThread();
void bindDemodulator(DemodulatorInstance *demod); void notifyDemodulatorsChanged();
void bindDemodulators(std::vector<DemodulatorInstance *> *demods);
void removeDemodulator(DemodulatorInstance *demod);
virtual void run(); virtual void run();
virtual void terminate(); virtual void terminate();
@ -27,12 +25,6 @@ protected:
DemodulatorThreadInputQueuePtr iqDataOutQueue; DemodulatorThreadInputQueuePtr iqDataOutQueue;
DemodulatorThreadInputQueuePtr iqVisualQueue; DemodulatorThreadInputQueuePtr iqVisualQueue;
DemodulatorThreadInputQueuePtr iqActiveDemodVisualQueue; DemodulatorThreadInputQueuePtr iqActiveDemodVisualQueue;
//protects access to demodulators lists and such
std::mutex busy_demod;
std::vector<DemodulatorInstance *> demodulators;
private: private:
@ -48,7 +40,7 @@ private:
long long chanBw = 0; long long chanBw = 0;
size_t nRunDemods; size_t nRunDemods;
std::vector<DemodulatorInstance *> runDemods; std::vector<DemodulatorInstancePtr> runDemods;
std::vector<int> demodChannel; std::vector<int> demodChannel;
std::vector<int> demodChannelActive; std::vector<int> demodChannelActive;

View File

@ -13,10 +13,10 @@
#define TARGET_DISPLAY_FPS 60 #define TARGET_DISPLAY_FPS 60
SDRThread::SDRThread() : IOThread(), buffers("SDRThreadBuffers") { SDRThread::SDRThread() : IOThread(), buffers("SDRThreadBuffers") {
device = NULL; device = nullptr;
deviceConfig.store(NULL); deviceConfig.store(nullptr);
deviceInfo.store(NULL); deviceInfo.store(nullptr);
sampleRate.store(DEFAULT_SAMPLE_RATE); sampleRate.store(DEFAULT_SAMPLE_RATE);
frequency.store(0); frequency.store(0);

View File

@ -62,7 +62,7 @@ PrimaryGLContext::PrimaryGLContext(wxGLCanvas *canvas, wxGLContext *sharedContex
//#endif //#endif
} }
void PrimaryGLContext::DrawDemodInfo(DemodulatorInstance *demod, RGBA4f color, long long center_freq, long long srate, bool centerline) { void PrimaryGLContext::DrawDemodInfo(DemodulatorInstancePtr demod, RGBA4f color, long long center_freq, long long srate, bool centerline) {
if (!demod) { if (!demod) {
return; return;
} }
@ -287,7 +287,7 @@ void PrimaryGLContext::DrawFreqBwInfo(long long freq, int bw, RGBA4f color, long
glDisable(GL_BLEND); glDisable(GL_BLEND);
} }
void PrimaryGLContext::DrawDemod(DemodulatorInstance *demod, RGBA4f color, long long center_freq, long long srate) { void PrimaryGLContext::DrawDemod(DemodulatorInstancePtr demod, RGBA4f color, long long center_freq, long long srate) {
if (!demod) { if (!demod) {
return; return;
} }
@ -409,7 +409,8 @@ void PrimaryGLContext::drawSingleDemodLabel(const std::wstring& demodStr, float
} }
void PrimaryGLContext::DrawFreqSelector(float uxPos, RGBA4f color, float w, long long /* center_freq */, long long srate) { void PrimaryGLContext::DrawFreqSelector(float uxPos, RGBA4f color, float w, long long /* center_freq */, long long srate) {
DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
DemodulatorInstancePtr demod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
long long bw = 0; long long bw = 0;

View File

@ -26,9 +26,9 @@ public:
void DrawFreqSelector(float uxPos, RGBA4f color, float w = 0, long long center_freq = -1, long long srate = 0); void DrawFreqSelector(float uxPos, RGBA4f color, float w = 0, long long center_freq = -1, long long srate = 0);
void DrawRangeSelector(float uxPos1, float uxPos2, RGBA4f color); void DrawRangeSelector(float uxPos1, float uxPos2, RGBA4f color);
void DrawDemod(DemodulatorInstance *demod, RGBA4f color, long long center_freq = -1, long long srate = 0); void DrawDemod(DemodulatorInstancePtr demod, RGBA4f color, long long center_freq = -1, long long srate = 0);
void DrawDemodInfo(DemodulatorInstance *demod, RGBA4f color, long long center_freq = -1, long long srate = 0, bool centerline = false); void DrawDemodInfo(DemodulatorInstancePtr demod, RGBA4f color, long long center_freq = -1, long long srate = 0, bool centerline = false);
void DrawFreqBwInfo(long long freq, int bw, RGBA4f color, long long center_freq = - 1, long long srate = 0, bool stack = false, bool centerline = false); void DrawFreqBwInfo(long long freq, int bw, RGBA4f color, long long center_freq = - 1, long long srate = 0, bool stack = false, bool centerline = false);
void setHoverAlpha(float hoverAlpha); void setHoverAlpha(float hoverAlpha);

View File

@ -90,9 +90,8 @@ void SpectrumCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
glLoadIdentity(); glLoadIdentity();
std::vector<DemodulatorInstance *> &demods = wxGetApp().getDemodMgr().getDemodulators(); auto demods = wxGetApp().getDemodMgr().getDemodulators();
auto activeDemodulator = wxGetApp().getDemodMgr().getActiveDemodulator();
DemodulatorInstance *activeDemodulator = wxGetApp().getDemodMgr().getActiveDemodulator();
for (int i = 0, iMax = demods.size(); i < iMax; i++) { for (int i = 0, iMax = demods.size(); i < iMax; i++) {
if (!demods[i]->isActive()) { if (!demods[i]->isActive()) {
@ -112,7 +111,7 @@ void SpectrumCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
freq = roundf((float)freq/(float)snap)*snap; freq = roundf((float)freq/(float)snap)*snap;
} }
DemodulatorInstance *lastActiveDemodulator = wxGetApp().getDemodMgr().getLastActiveDemodulator(); auto lastActiveDemodulator = wxGetApp().getDemodMgr().getLastActiveDemodulator();
bool isNew = (((waterfallCanvas->isShiftDown() || (lastActiveDemodulator && !lastActiveDemodulator->isActive())) && lastActiveDemodulator) || (!lastActiveDemodulator)); bool isNew = (((waterfallCanvas->isShiftDown() || (lastActiveDemodulator && !lastActiveDemodulator->isActive())) && lastActiveDemodulator) || (!lastActiveDemodulator));

View File

@ -61,7 +61,8 @@ TuningCanvas::~TuningCanvas() {
} }
bool TuningCanvas::changed() { bool TuningCanvas::changed() {
DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
auto activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
long long current_freq = 0; long long current_freq = 0;
if (activeDemod != NULL) { if (activeDemod != NULL) {
@ -92,7 +93,7 @@ void TuningCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
glContext->DrawBegin(); glContext->DrawBegin();
DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); auto activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
freq = 0; freq = 0;
if (activeDemod != NULL) { if (activeDemod != NULL) {
@ -170,7 +171,7 @@ void TuningCanvas::StepTuner(ActiveState state, int exponent, bool up) {
amount *= 2; amount *= 2;
} }
DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); auto activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
if (state == TUNING_HOVER_FREQ && activeDemod) { if (state == TUNING_HOVER_FREQ && activeDemod) {
long long freq = activeDemod->getFrequency(); long long freq = activeDemod->getFrequency();
long long diff = abs(wxGetApp().getFrequency() - freq); long long diff = abs(wxGetApp().getFrequency() - freq);
@ -330,7 +331,7 @@ void TuningCanvas::OnMouseMoved(wxMouseEvent& event) {
if (hoverState == TUNING_HOVER_BW || hoverState == TUNING_HOVER_FREQ) { if (hoverState == TUNING_HOVER_BW || hoverState == TUNING_HOVER_FREQ) {
wxGetApp().getDemodMgr().setActiveDemodulator(wxGetApp().getDemodMgr().getLastActiveDemodulator()); wxGetApp().getDemodMgr().setActiveDemodulator(wxGetApp().getDemodMgr().getLastActiveDemodulator());
} else { } else {
wxGetApp().getDemodMgr().setActiveDemodulator(NULL); wxGetApp().getDemodMgr().setActiveDemodulator(nullptr);
} }
} }
@ -400,7 +401,7 @@ void TuningCanvas::OnMouseLeftWindow(wxMouseEvent& event) {
SetCursor(wxCURSOR_CROSS); SetCursor(wxCURSOR_CROSS);
hoverIndex = 0; hoverIndex = 0;
hoverState = TUNING_HOVER_NONE; hoverState = TUNING_HOVER_NONE;
wxGetApp().getDemodMgr().setActiveDemodulator(NULL); wxGetApp().getDemodMgr().setActiveDemodulator(nullptr);
if (currentPPM != lastPPM) { if (currentPPM != lastPPM) {
wxGetApp().saveConfig(); wxGetApp().saveConfig();

View File

@ -24,6 +24,8 @@
#include <wx/numformatter.h> #include <wx/numformatter.h>
#include "DemodulatorThread.h"
wxBEGIN_EVENT_TABLE(WaterfallCanvas, wxGLCanvas) wxBEGIN_EVENT_TABLE(WaterfallCanvas, wxGLCanvas)
EVT_PAINT(WaterfallCanvas::OnPaint) EVT_PAINT(WaterfallCanvas::OnPaint)
EVT_IDLE(WaterfallCanvas::OnIdle) EVT_IDLE(WaterfallCanvas::OnIdle)
@ -263,10 +265,10 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
waterfallPanel.calcTransform(CubicVR::mat4::identity()); waterfallPanel.calcTransform(CubicVR::mat4::identity());
waterfallPanel.draw(); waterfallPanel.draw();
std::vector<DemodulatorInstance *> &demods = wxGetApp().getDemodMgr().getDemodulators(); auto demods = wxGetApp().getDemodMgr().getDemodulators();
DemodulatorInstance *activeDemodulator = wxGetApp().getDemodMgr().getActiveDemodulator(); auto activeDemodulator = wxGetApp().getDemodMgr().getActiveDemodulator();
DemodulatorInstance *lastActiveDemodulator = wxGetApp().getDemodMgr().getLastActiveDemodulator(); auto lastActiveDemodulator = wxGetApp().getDemodMgr().getLastActiveDemodulator();
bool isNew = shiftDown bool isNew = shiftDown
|| (wxGetApp().getDemodMgr().getLastActiveDemodulator() && !wxGetApp().getDemodMgr().getLastActiveDemodulator()->isActive()); || (wxGetApp().getDemodMgr().getLastActiveDemodulator() && !wxGetApp().getDemodMgr().getLastActiveDemodulator()->isActive());
@ -307,9 +309,9 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
} }
} else { } else {
if (lastActiveDemodulator) { if (lastActiveDemodulator) {
glContext->DrawDemod(lastActiveDemodulator, ((isNew && activeDemodulator == NULL) || (activeDemodulator != NULL))?currentTheme->waterfallHighlight:currentTheme->waterfallDestroy, currentCenterFreq, currentBandwidth); glContext->DrawDemod(lastActiveDemodulator, ((isNew && activeDemodulator == nullptr) || (activeDemodulator != nullptr))?currentTheme->waterfallHighlight:currentTheme->waterfallDestroy, currentCenterFreq, currentBandwidth);
} }
if (activeDemodulator == NULL) { if (activeDemodulator == nullptr) {
glContext->DrawFreqSelector(mouseTracker.getMouseX(), ((isNew && lastActiveDemodulator) || (!lastActiveDemodulator) )?currentTheme->waterfallNew:currentTheme->waterfallHover, 0, currentCenterFreq, currentBandwidth); glContext->DrawFreqSelector(mouseTracker.getMouseX(), ((isNew && lastActiveDemodulator) || (!lastActiveDemodulator) )?currentTheme->waterfallNew:currentTheme->waterfallHover, 0, currentCenterFreq, currentBandwidth);
} else { } else {
glContext->DrawDemod(activeDemodulator, currentTheme->waterfallHover, currentCenterFreq, currentBandwidth); glContext->DrawDemod(activeDemodulator, currentTheme->waterfallHover, currentCenterFreq, currentBandwidth);
@ -390,7 +392,7 @@ void WaterfallCanvas::OnKeyUp(wxKeyEvent& event) {
void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) { void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) {
InteractiveCanvas::OnKeyDown(event); InteractiveCanvas::OnKeyDown(event);
DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator(); auto activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator();
long long originalFreq = getCenterFrequency(); long long originalFreq = getCenterFrequency();
long long freq = originalFreq; long long freq = originalFreq;
@ -490,9 +492,9 @@ void WaterfallCanvas::OnIdle(wxIdleEvent &event) {
void WaterfallCanvas::updateHoverState() { void WaterfallCanvas::updateHoverState() {
long long freqPos = getFrequencyAt(mouseTracker.getMouseX()); long long freqPos = getFrequencyAt(mouseTracker.getMouseX());
std::vector<DemodulatorInstance *> demodsHover = wxGetApp().getDemodMgr().getDemodulatorsAt(freqPos, 15000); auto demodsHover = wxGetApp().getDemodMgr().getDemodulatorsAt(freqPos, 15000);
wxGetApp().getDemodMgr().setActiveDemodulator(NULL); wxGetApp().getDemodMgr().setActiveDemodulator(nullptr);
if (altDown) { if (altDown) {
nextDragState = WF_DRAG_RANGE; nextDragState = WF_DRAG_RANGE;
@ -506,10 +508,10 @@ void WaterfallCanvas::updateHoverState() {
} else if (demodsHover.size() && !shiftDown) { } else if (demodsHover.size() && !shiftDown) {
long near_dist = getBandwidth(); long near_dist = getBandwidth();
DemodulatorInstance *activeDemodulator = NULL; DemodulatorInstancePtr activeDemodulator = nullptr;
for (int i = 0, iMax = demodsHover.size(); i < iMax; i++) { for (int i = 0, iMax = demodsHover.size(); i < iMax; i++) {
DemodulatorInstance *demod = demodsHover[i]; auto demod = demodsHover[i];
long long freqDiff = demod->getFrequency() - freqPos; long long freqDiff = demod->getFrequency() - freqPos;
long halfBw = (demod->getBandwidth() / 2); long halfBw = (demod->getBandwidth() / 2);
long long currentBw = getBandwidth(); long long currentBw = getBandwidth();
@ -537,7 +539,7 @@ void WaterfallCanvas::updateHoverState() {
} }
} }
if (activeDemodulator == NULL) { if (activeDemodulator == nullptr) {
nextDragState = WF_DRAG_NONE; nextDragState = WF_DRAG_NONE;
SetCursor(wxCURSOR_CROSS); SetCursor(wxCURSOR_CROSS);
return; return;
@ -588,10 +590,10 @@ void WaterfallCanvas::updateHoverState() {
void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) { void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) {
InteractiveCanvas::OnMouseMoved(event); InteractiveCanvas::OnMouseMoved(event);
DemodulatorInstance *demod = wxGetApp().getDemodMgr().getActiveDemodulator(); auto demod = wxGetApp().getDemodMgr().getActiveDemodulator();
if (mouseTracker.mouseDown()) { if (mouseTracker.mouseDown()) {
if (demod == NULL) { if (demod == nullptr) {
return; return;
} }
if (dragState == WF_DRAG_BANDWIDTH_LEFT || dragState == WF_DRAG_BANDWIDTH_RIGHT) { if (dragState == WF_DRAG_BANDWIDTH_LEFT || dragState == WF_DRAG_BANDWIDTH_RIGHT) {
@ -650,7 +652,7 @@ void WaterfallCanvas::OnMouseDown(wxMouseEvent& event) {
wxGetApp().getDemodMgr().updateLastState(); wxGetApp().getDemodMgr().updateLastState();
if (dragState && dragState != WF_DRAG_RANGE) { if (dragState && dragState != WF_DRAG_RANGE) {
DemodulatorInstance *demod = wxGetApp().getDemodMgr().getActiveDemodulator(); auto demod = wxGetApp().getDemodMgr().getActiveDemodulator();
if (demod) { if (demod) {
dragOfs = (long long) (mouseTracker.getMouseX() * (float) getBandwidth()) + getCenterFrequency() - (getBandwidth() / 2) - demod->getFrequency(); dragOfs = (long long) (mouseTracker.getMouseX() * (float) getBandwidth()) + getCenterFrequency() - (getBandwidth() / 2) - demod->getFrequency();
dragBW = demod->getBandwidth(); dragBW = demod->getBandwidth();
@ -670,14 +672,14 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
InteractiveCanvas::OnMouseReleased(event); InteractiveCanvas::OnMouseReleased(event);
wxGetApp().getDemodMgr().updateLastState(); wxGetApp().getDemodMgr().updateLastState();
bool isNew = shiftDown || (wxGetApp().getDemodMgr().getLastActiveDemodulator() == NULL) bool isNew = shiftDown || (wxGetApp().getDemodMgr().getLastActiveDemodulator() == nullptr)
|| (wxGetApp().getDemodMgr().getLastActiveDemodulator() && !wxGetApp().getDemodMgr().getLastActiveDemodulator()->isActive()); || (wxGetApp().getDemodMgr().getLastActiveDemodulator() && !wxGetApp().getDemodMgr().getLastActiveDemodulator()->isActive());
mouseTracker.setVertDragLock(false); mouseTracker.setVertDragLock(false);
mouseTracker.setHorizDragLock(false); mouseTracker.setHorizDragLock(false);
DemodulatorInstance *demod = isNew?NULL:wxGetApp().getDemodMgr().getLastActiveDemodulator(); DemodulatorInstancePtr demod = isNew?nullptr:wxGetApp().getDemodMgr().getLastActiveDemodulator();
DemodulatorInstance *activeDemod = isNew?NULL:wxGetApp().getDemodMgr().getActiveDemodulator(); DemodulatorInstancePtr activeDemod = isNew?nullptr:wxGetApp().getDemodMgr().getActiveDemodulator();
DemodulatorMgr *mgr = &wxGetApp().getDemodMgr(); DemodulatorMgr *mgr = &wxGetApp().getDemodMgr();
@ -727,7 +729,7 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
demod->writeModemSettings(mgr->getLastModemSettings(mgr->getLastDemodulatorType())); demod->writeModemSettings(mgr->getLastModemSettings(mgr->getLastDemodulatorType()));
demod->run(); demod->run();
wxGetApp().bindDemodulator(demod); wxGetApp().notifyDemodulatorsChanged();
DemodulatorThread::releaseSquelchLock(nullptr); DemodulatorThread::releaseSquelchLock(nullptr);
} }
@ -827,10 +829,10 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
demod->run(); demod->run();
wxGetApp().bindDemodulator(demod); wxGetApp().notifyDemodulatorsChanged();
} }
if (demod == NULL) { if (demod == nullptr) {
dragState = WF_DRAG_NONE; dragState = WF_DRAG_NONE;
return; return;
} }
@ -850,7 +852,7 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
void WaterfallCanvas::OnMouseLeftWindow(wxMouseEvent& event) { void WaterfallCanvas::OnMouseLeftWindow(wxMouseEvent& event) {
InteractiveCanvas::OnMouseLeftWindow(event); InteractiveCanvas::OnMouseLeftWindow(event);
SetCursor(wxCURSOR_CROSS); SetCursor(wxCURSOR_CROSS);
wxGetApp().getDemodMgr().setActiveDemodulator(NULL); wxGetApp().getDemodMgr().setActiveDemodulator(nullptr);
mouseZoom = 1.0; mouseZoom = 1.0;
} }