diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 56e4376..7f3b120 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -1709,10 +1709,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) { } } - //try to garbage collect the retired demodulators. - wxGetApp().getDemodMgr().garbageCollect(); - - DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); + DemodulatorInstancePtr demod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); if (demod && demod->isModemInitialized()) { if (demod->isTracking()) { @@ -2129,11 +2126,12 @@ void AppFrame::saveSession(std::string fileName) { DataNode *demods = s.rootNode()->newChild("demodulators"); - std::vector &instances = wxGetApp().getDemodMgr().getDemodulators(); + //make a local copy snapshot of the list + std::vector instances = wxGetApp().getDemodMgr().getDemodulators(); - for (auto instance_i : instances) { + for (auto instance : instances) { DataNode *demod = demods->newChild("demodulator"); - wxGetApp().getDemodMgr().saveInstance(demod, instance_i); + wxGetApp().getDemodMgr().saveInstance(demod, instance); } //end for demodulators // Make sure the file name actually ends in .xml @@ -2247,14 +2245,14 @@ bool AppFrame::loadSession(std::string fileName) { wxGetApp().setSoloMode(false); } - DemodulatorInstance *loadedActiveDemod = nullptr; - DemodulatorInstance *newDemod = nullptr; + DemodulatorInstancePtr loadedActiveDemod = nullptr; + DemodulatorInstancePtr newDemod = nullptr; if (l.rootNode()->hasAnother("demodulators")) { DataNode *demodulators = l.rootNode()->getNext("demodulators"); - std::vector demodsLoaded; + std::vector demodsLoaded; while (demodulators->hasAnother("demodulator")) { DataNode *demod = demodulators->getNext("demodulator"); @@ -2275,7 +2273,7 @@ bool AppFrame::loadSession(std::string fileName) { } if (demodsLoaded.size()) { - wxGetApp().bindDemodulators(&demodsLoaded); + wxGetApp().notifyDemodulatorsChanged(); } } // if l.rootNode()->hasAnother("demodulators") @@ -2404,14 +2402,14 @@ FrequencyDialog::FrequencyDialogTarget AppFrame::getFrequencyDialogTarget() { return target; } -void AppFrame::gkNudgeLeft(DemodulatorInstance *demod, int snap) { +void AppFrame::gkNudgeLeft(DemodulatorInstancePtr demod, int snap) { if (demod) { demod->setFrequency(demod->getFrequency()-snap); demod->updateLabel(demod->getFrequency()); } } -void AppFrame::gkNudgeRight(DemodulatorInstance *demod, int snap) { +void AppFrame::gkNudgeRight(DemodulatorInstancePtr demod, int snap) { if (demod) { demod->setFrequency(demod->getFrequency()+snap); demod->updateLabel(demod->getFrequency()); @@ -2437,7 +2435,10 @@ int AppFrame::OnGlobalKeyDown(wxKeyEvent &event) { return -1; } - DemodulatorInstance *demod = nullptr, *lastDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); + DemodulatorInstancePtr demod = nullptr; + + DemodulatorInstancePtr lastDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); + int snap = wxGetApp().getFrequencySnap(); if (event.ControlDown()) { @@ -2562,8 +2563,8 @@ int AppFrame::OnGlobalKeyUp(wxKeyEvent &event) { return 1; } - DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator(); - DemodulatorInstance *lastDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); + DemodulatorInstancePtr activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator(); + DemodulatorInstancePtr lastDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); #ifdef wxHAS_RAW_KEY_CODES switch (event.GetRawKeyCode()) { diff --git a/src/AppFrame.h b/src/AppFrame.h index 2cab9d6..7266314 100644 --- a/src/AppFrame.h +++ b/src/AppFrame.h @@ -26,7 +26,8 @@ #include "FrequencyDialog.h" #include "BookmarkView.h" #include "AboutDialog.h" - +#include "DemodulatorInstance.h" +#include "DemodulatorThread.h" #include #define wxID_RT_AUDIO_DEVICE 1000 @@ -107,8 +108,8 @@ public: void setMainWaterfallFFTSize(int fftSize); void setScopeDeviceName(std::string deviceName); - void gkNudgeLeft(DemodulatorInstance *demod, int snap); - void gkNudgeRight(DemodulatorInstance *demod, int snap); + void gkNudgeLeft(DemodulatorInstancePtr demod, int snap); + void gkNudgeRight(DemodulatorInstancePtr demod, int snap); int OnGlobalKeyDown(wxKeyEvent &event); int OnGlobalKeyUp(wxKeyEvent &event); @@ -193,7 +194,7 @@ private: wxBoxSizer *demodTray; BookmarkView *bookmarkView; - DemodulatorInstance *activeDemodulator; + DemodulatorInstancePtr activeDemodulator; std::vector devices; std::map inputDevices; diff --git a/src/BookmarkMgr.cpp b/src/BookmarkMgr.cpp index c9c5d4f..fb9e58e 100644 --- a/src/BookmarkMgr.cpp +++ b/src/BookmarkMgr.cpp @@ -205,7 +205,7 @@ bool BookmarkMgr::hasBackup(std::string bookmarkFn) { 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); //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); 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); @@ -536,7 +536,7 @@ std::wstring BookmarkMgr::getBookmarkEntryDisplayName(BookmarkEntryPtr bmEnt) { return dispName; } -std::wstring BookmarkMgr::getActiveDisplayName(DemodulatorInstance *demod) { +std::wstring BookmarkMgr::getActiveDisplayName(DemodulatorInstancePtr demod) { std::wstring activeName = demod->getDemodulatorUserLabel(); if (activeName == "") { @@ -547,7 +547,7 @@ std::wstring BookmarkMgr::getActiveDisplayName(DemodulatorInstance *demod) { return activeName; } -void BookmarkMgr::removeActive(DemodulatorInstance *demod) { +void BookmarkMgr::removeActive(DemodulatorInstancePtr demod) { std::lock_guard < std::recursive_mutex > lock(busy_lock); diff --git a/src/BookmarkMgr.h b/src/BookmarkMgr.h index 1530a4f..1fec76e 100644 --- a/src/BookmarkMgr.h +++ b/src/BookmarkMgr.h @@ -85,7 +85,7 @@ public: bool hasLastLoad(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 removeBookmark(std::string group, BookmarkEntryPtr be); void removeBookmark(BookmarkEntryPtr be); @@ -105,13 +105,13 @@ public: void updateBookmarks(); void updateBookmarks(std::string group); - void addRecent(DemodulatorInstance *demod); + void addRecent(DemodulatorInstancePtr demod); void addRecent(BookmarkEntryPtr be); void removeRecent(BookmarkEntryPtr be); const BookmarkList& getRecents(); void clearRecents(); - void removeActive(DemodulatorInstance *demod); + void removeActive(DemodulatorInstancePtr demod); void addRange(BookmarkRangeEntryPtr re); void removeRange(BookmarkRangeEntryPtr re); @@ -119,13 +119,13 @@ public: void clearRanges(); static std::wstring getBookmarkEntryDisplayName(BookmarkEntryPtr bmEnt); - static std::wstring getActiveDisplayName(DemodulatorInstance *demod); + static std::wstring getActiveDisplayName(DemodulatorInstancePtr demod); protected: void trimRecents(); - BookmarkEntryPtr demodToBookmarkEntry(DemodulatorInstance *demod); + BookmarkEntryPtr demodToBookmarkEntry(DemodulatorInstancePtr demod); BookmarkEntryPtr nodeToBookmark(DataNode *node); BookmarkMap bmData; diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index e58d821..f4cb6aa 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -421,9 +421,6 @@ int CubicSDR::OnExit() { std::cout << "Terminating All Demodulators.." << std::endl << std::flush; 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; spectrumVisualThread->terminate(); if (demodVisualThread) { @@ -831,30 +828,21 @@ SDRThread *CubicSDR::getSDRThread() { } -void CubicSDR::bindDemodulator(DemodulatorInstance *demod) { - if (!demod) { - return; - } - sdrPostThread->bindDemodulator(demod); -} - -void CubicSDR::bindDemodulators(std::vector *demods) { - if (!demods) { - return; - } - sdrPostThread->bindDemodulators(demods); +void CubicSDR::notifyDemodulatorsChanged() { + + sdrPostThread->notifyDemodulatorsChanged(); } long long CubicSDR::getSampleRate() { return sampleRate; } -void CubicSDR::removeDemodulator(DemodulatorInstance *demod) { +void CubicSDR::removeDemodulator(DemodulatorInstancePtr demod) { if (!demod) { return; } demod->setActive(false); - sdrPostThread->removeDemodulator(demod); + sdrPostThread->notifyDemodulatorsChanged(); wxGetApp().getAppFrame()->notifyUpdateModemProperties(); } @@ -926,7 +914,7 @@ void CubicSDR::showFrequencyInput(FrequencyDialog::FrequencyDialogTarget targetM void CubicSDR::showLabelInput() { - DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator(); + DemodulatorInstancePtr activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator(); if (activeDemod != nullptr) { diff --git a/src/CubicSDR.h b/src/CubicSDR.h index 7807097..c167509 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -121,9 +121,9 @@ public: SDRPostThread *getSDRPostThread(); SDRThread *getSDRThread(); - void bindDemodulator(DemodulatorInstance *demod); - void bindDemodulators(std::vector *demods); - void removeDemodulator(DemodulatorInstance *demod); + void notifyDemodulatorsChanged(); + + void removeDemodulator(DemodulatorInstancePtr demod); void setFrequencySnap(int snap); int getFrequencySnap(); diff --git a/src/DemodLabelDialog.cpp b/src/DemodLabelDialog.cpp index 251c356..139793f 100644 --- a/src/DemodLabelDialog.cpp +++ b/src/DemodLabelDialog.cpp @@ -13,7 +13,7 @@ EVT_SHOW(DemodLabelDialog::OnShow) wxEND_EVENT_TABLE() DemodLabelDialog::DemodLabelDialog(wxWindow * parent, wxWindowID id, const wxString & title, - DemodulatorInstance *demod, const wxPoint & position, + DemodulatorInstancePtr demod, const wxPoint & position, const wxSize & size, long style) : wxDialog(parent, id, title, position, size, style) { diff --git a/src/DemodLabelDialog.h b/src/DemodLabelDialog.h index cee9cff..ab13aa9 100644 --- a/src/DemodLabelDialog.h +++ b/src/DemodLabelDialog.h @@ -16,7 +16,7 @@ class DemodLabelDialog : public wxDialog public: DemodLabelDialog( wxWindow * parent, wxWindowID id, const wxString & title, - DemodulatorInstance *demod = NULL, + DemodulatorInstancePtr demod = nullptr, const wxPoint & pos = wxDefaultPosition, const wxSize & size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE); @@ -24,7 +24,7 @@ public: wxTextCtrl * dialogText; private: - DemodulatorInstance *activeDemod = nullptr; + DemodulatorInstancePtr activeDemod = nullptr; void OnEnter ( wxCommandEvent &event ); void OnChar ( wxKeyEvent &event ); void OnShow(wxShowEvent &event); diff --git a/src/FrequencyDialog.cpp b/src/FrequencyDialog.cpp index 46e3d1d..788c354 100644 --- a/src/FrequencyDialog.cpp +++ b/src/FrequencyDialog.cpp @@ -12,11 +12,13 @@ EVT_CHAR_HOOK(FrequencyDialog::OnChar) EVT_SHOW(FrequencyDialog::OnShow) 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) : wxDialog(parent, id, title, position, size, style) { wxString freqStr; + activeDemod = demod; + this->targetMode = targetMode; this->initialString = initString; diff --git a/src/FrequencyDialog.h b/src/FrequencyDialog.h index 259de20..6d260b9 100644 --- a/src/FrequencyDialog.h +++ b/src/FrequencyDialog.h @@ -24,7 +24,7 @@ public: FDIALOG_TARGET_GAIN } FrequencyDialogTarget; FrequencyDialog ( wxWindow * parent, wxWindowID id, const wxString & title, - DemodulatorInstance *demod = NULL, + DemodulatorInstancePtr demod = nullptr, const wxPoint & pos = wxDefaultPosition, const wxSize & size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE, @@ -34,7 +34,7 @@ public: wxTextCtrl * dialogText; private: - DemodulatorInstance *activeDemod; + DemodulatorInstancePtr activeDemod; void OnEnter ( wxCommandEvent &event ); void OnChar ( wxKeyEvent &event ); void OnShow(wxShowEvent &event); diff --git a/src/ModemProperties.cpp b/src/ModemProperties.cpp index 9984bdc..4fa02df 100644 --- a/src/ModemProperties.cpp +++ b/src/ModemProperties.cpp @@ -101,7 +101,7 @@ void ModemProperties::initDefaultProperties() { defaultProps["._audio_output"] = addArgInfoProperty(m_propertyGrid, outputArg); } -void ModemProperties::initProperties(ModemArgInfoList newArgs, DemodulatorInstance *demodInstance) { +void ModemProperties::initProperties(ModemArgInfoList newArgs, DemodulatorInstancePtr demodInstance) { args = newArgs; demodContext = demodInstance; diff --git a/src/ModemProperties.h b/src/ModemProperties.h index 268e366..c708f61 100644 --- a/src/ModemProperties.h +++ b/src/ModemProperties.h @@ -24,7 +24,7 @@ public: ~ModemProperties(); void initDefaultProperties(); - void initProperties(ModemArgInfoList newArgs, DemodulatorInstance *demodInstance); + void initProperties(ModemArgInfoList newArgs, DemodulatorInstancePtr demodInstance); bool isMouseInView(); void setCollapsed(bool state); bool isCollapsed(); @@ -46,7 +46,8 @@ private: wxBoxSizer* bSizer; wxPropertyGrid* m_propertyGrid; ModemArgInfoList args; - DemodulatorInstance *demodContext; + DemodulatorInstancePtr demodContext; + std::map props; bool mouseInView, collapsed; diff --git a/src/audio/AudioThread.cpp b/src/audio/AudioThread.cpp index 57f8d5b..c837edf 100644 --- a/src/audio/AudioThread.cpp +++ b/src/audio/AudioThread.cpp @@ -304,14 +304,12 @@ void AudioThread::setSampleRate(int sampleRate) { srcmix->setSampleRate(sampleRate); } - std::vector::iterator demod_i; - std::vector *demodulators; + //make a local copy, snapshot of the list of demodulators + std::vector demodulators = wxGetApp().getDemodMgr().getDemodulators(); - demodulators = &wxGetApp().getDemodMgr().getDemodulators(); - - for (demod_i = demodulators->begin(); demod_i != demodulators->end(); demod_i++) { - if ((*demod_i)->getOutputDevice() == outputDevice.load()) { - (*demod_i)->setAudioSampleRate(sampleRate); + for (auto demod : demodulators) { + if (demod->getOutputDevice() == outputDevice.load()) { + demod->setAudioSampleRate(sampleRate); } } diff --git a/src/audio/AudioThread.h b/src/audio/AudioThread.h index fd811f1..c8c13ac 100644 --- a/src/audio/AudioThread.h +++ b/src/audio/AudioThread.h @@ -35,6 +35,10 @@ public: typedef std::shared_ptr AudioThreadInputPtr; +typedef ThreadBlockingQueue DemodulatorThreadOutputQueue; + +typedef std::shared_ptr DemodulatorThreadOutputQueuePtr; + class AudioThreadCommand { public: enum AudioThreadCommandEnum { diff --git a/src/demod/DemodDefs.h b/src/demod/DemodDefs.h index 6d22495..bb0a63c 100644 --- a/src/demod/DemodDefs.h +++ b/src/demod/DemodDefs.h @@ -15,7 +15,6 @@ class DemodulatorThread; - class DemodulatorThreadControlCommand { public: enum DemodulatorThreadControlCommandEnum { diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index bbeded7..3efc504 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -5,6 +5,10 @@ #include "DemodulatorInstance.h" #include "CubicSDR.h" +#include "DemodulatorThread.h" +#include "DemodulatorPreThread.h" + + #if USE_HAMLIB #include "RigThread.h" #endif @@ -79,13 +83,37 @@ 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 - delete activeOutput; + delete activeOutput; #endif - delete audioThread; - delete demodulatorThread; - delete demodulatorPreThread; + delete audioThread; + delete demodulatorThread; + delete demodulatorPreThread; + + break; + } + else { + std::this_thread::sleep_for(std::chrono::milliseconds(TERMINATION_SPIN_WAIT_MS)); + } + currentCycle++; + } //end while } void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueuePtr tQueue) { @@ -94,7 +122,7 @@ void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueuePtr t 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) { return; @@ -163,7 +191,7 @@ void DemodulatorInstance::setLabel(std::string labelStr) { 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 demodTerminated = demodulatorThread->isTerminated(); @@ -224,7 +252,9 @@ void DemodulatorInstance::setActive(bool state) { } #endif audioThread->setActive(state); + DemodulatorThread::releaseSquelchLock(this); + } else if (!active && state) { #if ENABLE_DIGITAL_LAB if (activeOutput && getModemType() == "digital") { @@ -404,7 +434,7 @@ void DemodulatorInstance::setFrequency(long long freq) { } #endif #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); } #endif diff --git a/src/demod/DemodulatorInstance.h b/src/demod/DemodulatorInstance.h index ac1aa64..846aa86 100644 --- a/src/demod/DemodulatorInstance.h +++ b/src/demod/DemodulatorInstance.h @@ -6,12 +6,11 @@ #include #include #include - -#include "DemodulatorThread.h" -#include "DemodulatorPreThread.h" - +#include +#include "DemodDefs.h" #include "ModemDigital.h" #include "ModemAnalog.h" +#include "AudioThread.h" #if ENABLE_DIGITAL_LAB #include "DigitalConsole.h" @@ -30,6 +29,8 @@ private: std::atomic_int squelchBreak; }; +class DemodulatorThread; +class DemodulatorPreThread; class DemodulatorInstance { public: @@ -139,7 +140,7 @@ private: DemodulatorThreadControlCommandQueuePtr threadQueueControl; //protects child thread creation and termination - std::mutex m_thread_control_mutex; + std::recursive_mutex m_thread_control_mutex; std::atomic label; // // User editable buffer, 16 bit string. @@ -161,3 +162,5 @@ private: ModemDigitalOutput *activeOutput; #endif }; + +typedef std::shared_ptr DemodulatorInstancePtr; diff --git a/src/demod/DemodulatorMgr.cpp b/src/demod/DemodulatorMgr.cpp index c3f25dc..9b449c6 100644 --- a/src/demod/DemodulatorMgr.cpp +++ b/src/demod/DemodulatorMgr.cpp @@ -17,13 +17,11 @@ #include "DataTree.h" -bool demodFreqCompare (DemodulatorInstance *i, DemodulatorInstance *j) { return (i->getFrequency()getFrequency()); } -bool inactiveCompare (DemodulatorInstance *i, DemodulatorInstance *j) { return (i->isActive()isActive()); } +bool demodFreqCompare (DemodulatorInstancePtr i, DemodulatorInstancePtr j) { return (i->getFrequency() < j->getFrequency()); } +bool inactiveCompare (DemodulatorInstancePtr i, DemodulatorInstancePtr j) { return (i->isActive() < j->isActive()); } DemodulatorMgr::DemodulatorMgr() { - activeDemodulator = NULL; - lastActiveDemodulator = NULL; - activeVisualDemodulator = NULL; + lastBandwidth = DEFAULT_DEMOD_BW; lastDemodType = DEFAULT_DEMOD_TYPE; lastSquelchEnabled = false; @@ -37,9 +35,11 @@ DemodulatorMgr::~DemodulatorMgr() { terminateAll(); } -DemodulatorInstance *DemodulatorMgr::newThread() { +DemodulatorInstancePtr DemodulatorMgr::newThread() { 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(); std::stringstream label; label << demods.size(); @@ -51,27 +51,34 @@ DemodulatorInstance *DemodulatorMgr::newThread() { } void DemodulatorMgr::terminateAll() { + std::lock_guard < std::recursive_mutex > lock(demods_busy); + while (demods.size()) { - DemodulatorInstance *d = demods.back(); + DemodulatorInstancePtr d = demods.back(); demods.pop_back(); wxGetApp().removeDemodulator(d); deleteThread(d); } } -std::vector &DemodulatorMgr::getDemodulators() { +std::vector DemodulatorMgr::getDemodulators() { std::lock_guard < std::recursive_mutex > lock(demods_busy); return demods; } -std::vector DemodulatorMgr::getOrderedDemodulators(bool actives) { +std::vector DemodulatorMgr::getOrderedDemodulators(bool actives) { std::lock_guard < std::recursive_mutex > lock(demods_busy); - std::vector demods_ordered = demods; + + auto demods_ordered = demods; + if (actives) { + std::sort(demods_ordered.begin(), demods_ordered.end(), inactiveCompare); - std::vector::iterator i; + + std::vector::iterator i; + for (i = demods_ordered.begin(); i != demods_ordered.end(); i++) { if ((*i)->isActive()) { break; @@ -88,13 +95,14 @@ std::vector DemodulatorMgr::getOrderedDemodulators(bool a 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); if (!getLastActiveDemodulator()) { return nullptr; } - std::vector demods_ordered = getOrderedDemodulators(actives); - std::vector::iterator p = std::find(demods_ordered.begin(), demods_ordered.end(), demod); + auto demods_ordered = getOrderedDemodulators(actives); + auto p = std::find(demods_ordered.begin(), demods_ordered.end(), demod); + if (p == demods_ordered.end()) { return nullptr; } @@ -104,13 +112,14 @@ DemodulatorInstance *DemodulatorMgr::getPreviousDemodulator(DemodulatorInstance 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); if (!getLastActiveDemodulator()) { return nullptr; } - std::vector demods_ordered = getOrderedDemodulators(actives); - std::vector::iterator p = std::find(demods_ordered.begin(), demods_ordered.end(), demod); + auto demods_ordered = getOrderedDemodulators(actives); + auto p = std::find(demods_ordered.begin(), demods_ordered.end(), demod); + if (actives) { } @@ -123,26 +132,25 @@ DemodulatorInstance *DemodulatorMgr::getNextDemodulator(DemodulatorInstance *dem return *(++p); } -DemodulatorInstance *DemodulatorMgr::getLastDemodulator() { +DemodulatorInstancePtr DemodulatorMgr::getLastDemodulator() { std::lock_guard < std::recursive_mutex > lock(demods_busy); - std::vector 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::vector 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); wxGetApp().getBookmarkMgr().addRecent(demod); - - std::vector::iterator i; - - i = std::find(demods.begin(), demods.end(), demod); + + auto i = std::find(demods.begin(), demods.end(), demod); if (activeDemodulator == demod) { activeDemodulator = nullptr; @@ -161,19 +169,15 @@ void DemodulatorMgr::deleteThread(DemodulatorInstance *demod) { //Ask for termination demod->setActive(false); demod->terminate(); - - //Do not cleanup immediatly - std::lock_guard < std::mutex > lock_deleted(deleted_demods_busy); - demods_deleted.push_back(demod); } -std::vector DemodulatorMgr::getDemodulatorsAt(long long freq, int bandwidth) { +std::vector DemodulatorMgr::getDemodulatorsAt(long long freq, int bandwidth) { std::lock_guard < std::recursive_mutex > lock(demods_busy); - std::vector foundDemods; + std::vector foundDemods; 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 bandwidthTest = testDemod->getBandwidth(); @@ -192,7 +196,7 @@ std::vector DemodulatorMgr::getDemodulatorsAt(long long f bool DemodulatorMgr::anyDemodulatorsAt(long long freq, int bandwidth) { std::lock_guard < std::recursive_mutex > lock(demods_busy); 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 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 (activeDemodulator.load() != nullptr) { - lastActiveDemodulator = activeDemodulator.load(); + if (activeDemodulator != nullptr) { + lastActiveDemodulator = activeDemodulator; updateLastState(); } else { lastActiveDemodulator = demod; } updateLastState(); #if USE_HAMLIB - if (wxGetApp().rigIsActive() && wxGetApp().getRigThread()->getFollowModem() && lastActiveDemodulator.load()) { - wxGetApp().getRigThread()->setFrequency(lastActiveDemodulator.load()->getFrequency(),true); + if (wxGetApp().rigIsActive() && wxGetApp().getRigThread()->getFollowModem() && lastActiveDemodulator) { + wxGetApp().getRigThread()->setFrequency(lastActiveDemodulator->getFrequency(),true); } #endif wxGetApp().getBookmarkMgr().updateActiveList(); } - if (activeVisualDemodulator.load()) { - activeVisualDemodulator.load()->setVisualOutputQueue(nullptr); + if (activeVisualDemodulator) { + activeVisualDemodulator->setVisualOutputQueue(nullptr); } if (demod) { demod->setVisualOutputQueue(wxGetApp().getAudioVisualQueue()); activeVisualDemodulator = demod; } else { - DemodulatorInstance *last = getLastActiveDemodulator(); + DemodulatorInstancePtr last = getLastActiveDemodulator(); if (last) { last->setVisualOutputQueue(wxGetApp().getAudioVisualQueue()); } @@ -246,25 +252,41 @@ void DemodulatorMgr::setActiveDemodulator(DemodulatorInstance *demod, bool tempo } -DemodulatorInstance *DemodulatorMgr::getActiveDemodulator() { - if (activeDemodulator.load() && !activeDemodulator.load()->isActive()) { +//Dangerous: this is only intended by some internal classes +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(); } return activeDemodulator; } -DemodulatorInstance *DemodulatorMgr::getLastActiveDemodulator() { +DemodulatorInstancePtr DemodulatorMgr::getLastActiveDemodulator() { return lastActiveDemodulator; } -DemodulatorInstance *DemodulatorMgr::getLastDemodulatorWith(const std::string& type, +DemodulatorInstancePtr DemodulatorMgr::getLastDemodulatorWith(const std::string& type, const std::wstring& userLabel, long long frequency, int bandwidth) { std::lock_guard < std::recursive_mutex > lock(demods_busy); //backwards search: - for (std::vector::reverse_iterator it = demods.rbegin(); it != demods.rend(); it++) { + for (auto it = demods.rbegin(); it != demods.rend(); it++) { if ((*it)->getDemodulatorType() == type && (*it)->getDemodulatorUserLabel() == userLabel && @@ -278,86 +300,31 @@ DemodulatorInstance *DemodulatorMgr::getLastDemodulatorWith(const std::string& t 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::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::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() { std::lock_guard < std::recursive_mutex > lock(demods_busy); if (std::find(demods.begin(), demods.end(), lastActiveDemodulator) == demods.end()) { - if (activeDemodulator.load() && activeDemodulator.load()->isActive()) { - lastActiveDemodulator = activeDemodulator.load(); - } else if (activeDemodulator.load() && !activeDemodulator.load()->isActive()){ + if (activeDemodulator && activeDemodulator->isActive()) { + lastActiveDemodulator = activeDemodulator; + } else if (activeDemodulator && !activeDemodulator->isActive()){ activeDemodulator = nullptr; lastActiveDemodulator = nullptr; } } - if (lastActiveDemodulator.load() && !lastActiveDemodulator.load()->isActive()) { + if (lastActiveDemodulator && !lastActiveDemodulator->isActive()) { lastActiveDemodulator = nullptr; } - if (lastActiveDemodulator.load()) { - lastBandwidth = lastActiveDemodulator.load()->getBandwidth(); - lastDemodType = lastActiveDemodulator.load()->getDemodulatorType(); - lastDemodLock = lastActiveDemodulator.load()->getDemodulatorLock()?true:false; - lastSquelchEnabled = lastActiveDemodulator.load()->isSquelchEnabled(); - lastSquelch = lastActiveDemodulator.load()->getSquelchLevel(); - lastGain = lastActiveDemodulator.load()->getGain(); - lastModemSettings[lastDemodType] = lastActiveDemodulator.load()->readModemSettings(); + if (lastActiveDemodulator) { + lastBandwidth = lastActiveDemodulator->getBandwidth(); + lastDemodType = lastActiveDemodulator->getDemodulatorType(); + lastDemodLock = lastActiveDemodulator->getDemodulatorLock()?true:false; + lastSquelchEnabled = lastActiveDemodulator->isSquelchEnabled(); + lastSquelch = lastActiveDemodulator->getSquelchLevel(); + lastGain = lastActiveDemodulator->getGain(); + lastModemSettings[lastDemodType] = lastActiveDemodulator->readModemSettings(); } } @@ -436,7 +403,8 @@ void DemodulatorMgr::setOutputDevices(std::map devs) { outputDevices = devs; } -void DemodulatorMgr::saveInstance(DataNode *node, DemodulatorInstance *inst) { +void DemodulatorMgr::saveInstance(DataNode *node, DemodulatorInstancePtr inst) { + *node->newChild("bandwidth") = inst->getBandwidth(); *node->newChild("frequency") = inst->getFrequency(); *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); - DemodulatorInstance *newDemod = nullptr; + DemodulatorInstancePtr newDemod = nullptr; node->rewindAll(); diff --git a/src/demod/DemodulatorMgr.h b/src/demod/DemodulatorMgr.h index e0f715a..b080e5f 100644 --- a/src/demod/DemodulatorMgr.h +++ b/src/demod/DemodulatorMgr.h @@ -16,23 +16,32 @@ public: DemodulatorMgr(); ~DemodulatorMgr(); - DemodulatorInstance *newThread(); - std::vector &getDemodulators(); - std::vector getOrderedDemodulators(bool actives = true); - std::vector getDemodulatorsAt(long long freq, int bandwidth); - DemodulatorInstance *getPreviousDemodulator(DemodulatorInstance *demod, bool actives = true); - DemodulatorInstance *getNextDemodulator(DemodulatorInstance *demod, bool actives = true); - DemodulatorInstance *getLastDemodulator(); - DemodulatorInstance *getFirstDemodulator(); + DemodulatorInstancePtr newThread(); + + //return snapshot-copy of the list purposefully + std::vector getDemodulators(); + + std::vector getOrderedDemodulators(bool actives = true); + std::vector getDemodulatorsAt(long long freq, int bandwidth); + + 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); - void deleteThread(DemodulatorInstance *); + void deleteThread(DemodulatorInstancePtr); void terminateAll(); - void setActiveDemodulator(DemodulatorInstance *demod, bool temporary = true); - DemodulatorInstance *getActiveDemodulator(); - DemodulatorInstance *getLastActiveDemodulator(); - DemodulatorInstance *getLastDemodulatorWith(const std::string& type, + void setActiveDemodulator(DemodulatorInstancePtr demod, bool temporary = true); + + //Dangerous: this is only intended by some internal classes, + // 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, long long frequency, int bandwidth); @@ -64,28 +73,17 @@ public: void updateLastState(); void setOutputDevices(std::map 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: - std::vector demods; - std::vector demods_deleted; + std::vector demods; - std::atomic activeDemodulator; - std::atomic lastActiveDemodulator; - std::atomic activeVisualDemodulator; + DemodulatorInstancePtr activeDemodulator; + DemodulatorInstancePtr lastActiveDemodulator; + DemodulatorInstancePtr activeVisualDemodulator; int lastBandwidth; std::string lastDemodType; @@ -99,9 +97,7 @@ private: //protects access to demods lists and such, need to be recursive //because of the usage of public re-entrant methods std::recursive_mutex demods_busy; - - std::mutex deleted_demods_busy; - + std::map lastModemSettings; std::map outputDevices; }; diff --git a/src/demod/DemodulatorPreThread.cpp b/src/demod/DemodulatorPreThread.cpp index 415c16f..dff7b30 100644 --- a/src/demod/DemodulatorPreThread.cpp +++ b/src/demod/DemodulatorPreThread.cpp @@ -15,7 +15,7 @@ //50 ms #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); this->parent = parent; diff --git a/src/demod/DemodulatorPreThread.h b/src/demod/DemodulatorPreThread.h index 67523d4..3913d11 100644 --- a/src/demod/DemodulatorPreThread.h +++ b/src/demod/DemodulatorPreThread.h @@ -17,7 +17,7 @@ class DemodulatorInstance; class DemodulatorPreThread : public IOThread { public: - DemodulatorPreThread(DemodulatorInstance *parent); + DemodulatorPreThread(DemodulatorInstance* parent); virtual ~DemodulatorPreThread(); virtual void run(); @@ -50,7 +50,9 @@ public: void writeModemSettings(ModemSettings settings); protected: - DemodulatorInstance *parent; + + DemodulatorInstance* parent; + msresamp_crcf iqResampler; double iqResampleRatio; std::vector resampledData; diff --git a/src/demod/DemodulatorThread.cpp b/src/demod/DemodulatorThread.cpp index 8c3ccc6..64ceaf1 100644 --- a/src/demod/DemodulatorThread.cpp +++ b/src/demod/DemodulatorThread.cpp @@ -19,10 +19,10 @@ #include #endif -std::atomic DemodulatorThread::squelchLock(nullptr); +DemodulatorInstance* DemodulatorThread::squelchLock(nullptr); std::mutex DemodulatorThread::squelchLockMutex; -DemodulatorThread::DemodulatorThread(DemodulatorInstance *parent) +DemodulatorThread::DemodulatorThread(DemodulatorInstance* parent) : IOThread(), outputBuffers("DemodulatorThreadBuffers"), squelchLevel(-100), signalLevel(-100), signalFloor(-30), signalCeil(30), squelchEnabled(false) { @@ -201,10 +201,10 @@ void DemodulatorThread::run() { if (!squelched && !squelchBreak) { if (wxGetApp().getSoloMode() && !wxGetApp().getAppFrame()->isUserDemodBusy()) { std::lock_guard < std::mutex > lock(squelchLockMutex); - if (squelchLock.load() == nullptr) { - squelchLock.store(demodInstance); + if (squelchLock == nullptr) { + squelchLock = demodInstance; wxGetApp().getDemodMgr().setActiveDemodulator(nullptr); - wxGetApp().getDemodMgr().setActiveDemodulator(demodInstance, false); + wxGetApp().getDemodMgr().setActiveDemodulatorByRawPointer(demodInstance, false); squelchBreak = true; demodInstance->getVisualCue()->triggerSquelchBreak(120); } @@ -310,7 +310,7 @@ void DemodulatorThread::run() { } 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 if (!audioOutputQueue->try_push(ati)) { @@ -385,9 +385,11 @@ bool DemodulatorThread::getSquelchBreak() { return squelchBreak; } -void DemodulatorThread::releaseSquelchLock(DemodulatorInstance *inst) { +void DemodulatorThread::releaseSquelchLock(DemodulatorInstance* inst) { + std::lock_guard < std::mutex > lock(squelchLockMutex); - if (inst == nullptr || squelchLock.load() == inst) { - squelchLock.store(nullptr); + + if (inst == nullptr || squelchLock == inst) { + squelchLock = nullptr; } } \ No newline at end of file diff --git a/src/demod/DemodulatorThread.h b/src/demod/DemodulatorThread.h index 3970601..c713596 100644 --- a/src/demod/DemodulatorThread.h +++ b/src/demod/DemodulatorThread.h @@ -11,10 +11,6 @@ #include "AudioThread.h" #include "Modem.h" -typedef ThreadBlockingQueue DemodulatorThreadOutputQueue; - -typedef std::shared_ptr DemodulatorThreadOutputQueuePtr; - #define DEMOD_VIS_SIZE 2048 #define DEMOD_SIGNAL_MIN -30 #define DEMOD_SIGNAL_MAX 30 @@ -24,7 +20,7 @@ class DemodulatorInstance; class DemodulatorThread : public IOThread { public: - DemodulatorThread(DemodulatorInstance *parent); + DemodulatorThread(DemodulatorInstance* parent); virtual ~DemodulatorThread(); void onBindOutput(std::string name, ThreadQueueBasePtr threadQueue); @@ -43,13 +39,14 @@ public: bool getSquelchBreak(); - static void releaseSquelchLock(DemodulatorInstance *inst); + + static void releaseSquelchLock(DemodulatorInstance* inst); protected: double abMagnitude(float inphase, float quadrature); double linearToDb(double linear); - DemodulatorInstance *demodInstance = nullptr; + DemodulatorInstance* demodInstance; ReBuffer outputBuffers; std::atomic_bool muted; @@ -58,7 +55,7 @@ protected: std::atomic signalLevel, signalFloor, signalCeil; bool squelchEnabled, squelchBreak; - static std::atomic squelchLock; + static DemodulatorInstance* squelchLock; static std::mutex squelchLockMutex; diff --git a/src/demod/DemodulatorWorkerThread.cpp b/src/demod/DemodulatorWorkerThread.cpp index 00010f1..a2bd35d 100644 --- a/src/demod/DemodulatorWorkerThread.cpp +++ b/src/demod/DemodulatorWorkerThread.cpp @@ -9,9 +9,6 @@ //50 ms #define HEARTBEAT_CHECK_PERIOD_MICROS (50 * 1000) -//1s -#define MAX_BLOCKING_DURATION_MICROS (1000 * 1000) - DemodulatorWorkerThread::DemodulatorWorkerThread() : IOThread(), commandQueue(nullptr), resultQueue(nullptr), cModem(nullptr), cModemKit(nullptr) { } @@ -111,7 +108,7 @@ void DemodulatorWorkerThread::run() { result.modemName = cModemName; //VSO: blocking push - resultQueue->push(result, MAX_BLOCKING_DURATION_MICROS, "resultQueue"); + resultQueue->push(result); } } // std::cout << "Demodulator worker thread done." << std::endl; diff --git a/src/forms/Bookmark/BookmarkView.cpp b/src/forms/Bookmark/BookmarkView.cpp index 699ef9d..4cb9888 100644 --- a/src/forms/Bookmark/BookmarkView.cpp +++ b/src/forms/Bookmark/BookmarkView.cpp @@ -348,10 +348,9 @@ wxTreeItemId BookmarkView::refreshBookmarks() { void BookmarkView::doUpdateActiveList() { - std::vector &demods = wxGetApp().getDemodMgr().getDemodulators(); - -// DemodulatorInstance *activeDemodulator = wxGetApp().getDemodMgr().getActiveDemodulator(); - DemodulatorInstance *lastActiveDemodulator = wxGetApp().getDemodMgr().getLastActiveDemodulator(); + + auto demods = wxGetApp().getDemodMgr().getDemodulators(); + auto 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 //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().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().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_bandwidthVal->SetLabelText(frequencyToStr(dsel->getBandwidth())); @@ -835,7 +835,7 @@ void BookmarkView::activateBookmark(BookmarkEntryPtr bmEnt) { //the already existing one: // 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. - DemodulatorInstance *matchingDemod = wxGetApp().getDemodMgr().getLastDemodulatorWith( + DemodulatorInstancePtr matchingDemod = wxGetApp().getDemodMgr().getLastDemodulatorWith( bmEnt->type, bmEnt->label, bmEnt->frequency, @@ -845,7 +845,7 @@ void BookmarkView::activateBookmark(BookmarkEntryPtr bmEnt) { matchingDemod = wxGetApp().getDemodMgr().loadInstance(bmEnt->node); matchingDemod->run(); - wxGetApp().bindDemodulator(matchingDemod); + wxGetApp().notifyDemodulatorsChanged(); } matchingDemod->setActive(true); diff --git a/src/forms/Bookmark/BookmarkView.h b/src/forms/Bookmark/BookmarkView.h index 6470bd5..8ed1bff 100644 --- a/src/forms/Bookmark/BookmarkView.h +++ b/src/forms/Bookmark/BookmarkView.h @@ -43,7 +43,7 @@ public: BookmarkEntryPtr bookmarkEnt; BookmarkRangeEntryPtr rangeEnt; - DemodulatorInstance* demod; + DemodulatorInstancePtr demod; std::string groupName; }; @@ -84,7 +84,7 @@ public: static BookmarkRangeEntryPtr makeActiveRangeEntry(); protected: - void activeSelection(DemodulatorInstance *dsel); + void activeSelection(DemodulatorInstancePtr dsel); void bookmarkSelection(BookmarkEntryPtr bmSel); void rangeSelection(BookmarkRangeEntryPtr re); @@ -133,10 +133,10 @@ protected: wxButton *makeButton(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 doMoveBookmark(BookmarkEntryPtr be, std::string group); - void doRemoveActive(DemodulatorInstance *demod); + void doRemoveActive(DemodulatorInstancePtr demod); void doRemoveRecent(BookmarkEntryPtr be); void doClearRecents(); @@ -191,7 +191,7 @@ protected: // Focus BookmarkEntryPtr nextEnt; BookmarkRangeEntryPtr nextRange; - DemodulatorInstance *nextDemod; + DemodulatorInstancePtr nextDemod; std::string nextGroup; // Search diff --git a/src/rig/RigThread.cpp b/src/rig/RigThread.cpp index 7bdcf4b..29ba0aa 100644 --- a/src/rig/RigThread.cpp +++ b/src/rig/RigThread.cpp @@ -73,8 +73,8 @@ void RigThread::run() { while (!stopping) { std::this_thread::sleep_for(std::chrono::milliseconds(150)); - DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator(); - DemodulatorInstance *lastDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); + auto activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator(); + auto lastDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); if (freqChanged.load() && (controlMode.load() || setOneShot.load())) { status = rig_get_freq(rig, RIG_VFO_CURR, &freq); diff --git a/src/sdr/SDRPostThread.cpp b/src/sdr/SDRPostThread.cpp index 7ad2b35..afdc16f 100644 --- a/src/sdr/SDRPostThread.cpp +++ b/src/sdr/SDRPostThread.cpp @@ -16,12 +16,12 @@ #define MAX_BLOCKING_DURATION_MICROS (1000 * 1000) SDRPostThread::SDRPostThread() : IOThread(), buffers("SDRPostThreadBuffers"), visualDataBuffers("SDRPostThreadVisualDataBuffers"), frequency(0) { - iqDataInQueue = NULL; - iqDataOutQueue = NULL; - iqVisualQueue = NULL; + iqDataInQueue = nullptr; + iqDataOutQueue = nullptr; + iqVisualQueue = nullptr; numChannels = 0; - channelizer = NULL; + channelizer = nullptr; sampleRate = 0; nRunDemods = 0; @@ -36,44 +36,12 @@ SDRPostThread::SDRPostThread() : IOThread(), buffers("SDRPostThreadBuffers"), vi SDRPostThread::~SDRPostThread() { } -void SDRPostThread::bindDemodulator(DemodulatorInstance *demod) { - - std::lock_guard < std::mutex > lock(busy_demod); - - demodulators.push_back(demod); +void SDRPostThread::notifyDemodulatorsChanged() { + doRefresh.store(true); } -void SDRPostThread::bindDemodulators(std::vector *demods) { - if (!demods) { - return; - } - std::lock_guard < std::mutex > lock(busy_demod); - - for (std::vector::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::iterator i = std::find(demodulators.begin(), demodulators.end(), demod); - - if (i != demodulators.end()) { - demodulators.erase(i); - doRefresh.store(true); - } - -} - void SDRPostThread::initPFBChannelizer() { // std::cout << "Initializing post-process FIR polyphase filterbank channelizer with " << numChannels << " channels." << std::endl; if (channelizer) { @@ -91,15 +59,16 @@ void SDRPostThread::initPFBChannelizer() { void SDRPostThread::updateActiveDemodulators() { // In range? - std::vector::iterator demod_i; nRunDemods = 0; long long centerFreq = wxGetApp().getFrequency(); - for (demod_i = demodulators.begin(); demod_i != demodulators.end(); demod_i++) { - DemodulatorInstance *demod = *demod_i; - + //retreive the current list of demodulators: + auto demodulators = wxGetApp().getDemodMgr().getDemodulators(); + + for (auto demod : demodulators) { + // not in range? if (demod->isDeltaLock()) { if (demod->getFrequency() != centerFreq + demod->getDeltaLockOfs()) { @@ -123,7 +92,7 @@ void SDRPostThread::updateActiveDemodulators() { } } else if (!demod->isActive()) { // in range, activate if not activated demod->setActive(true); - if (wxGetApp().getDemodMgr().getLastActiveDemodulator() == NULL) { + if (wxGetApp().getDemodMgr().getLastActiveDemodulator() == nullptr) { wxGetApp().getDemodMgr().setActiveDemodulator(demod); } @@ -194,9 +163,8 @@ void SDRPostThread::run() { if (!iqDataInQueue->pop(data_in, HEARTBEAT_CHECK_PERIOD_MICROS)) { continue; } - // std::lock_guard < std::mutex > lock(data_in->m_mutex); - - std::lock_guard < std::mutex > lock(busy_demod); + + bool doUpdate = false; if (data_in && data_in->data.size()) { if(data_in->numChannels > 1) { @@ -205,17 +173,16 @@ void SDRPostThread::run() { runSingleCH(data_in.get()); } } - - bool doUpdate = false; + for (size_t j = 0; j < nRunDemods; j++) { - DemodulatorInstance *demod = runDemods[j]; + DemodulatorInstancePtr demod = runDemods[j]; if (abs(frequency - demod->getFrequency()) > (sampleRate / 2)) { doUpdate = true; } } //Only update the list of demodulators here - if (doUpdate) { + if (doUpdate || doRefresh) { updateActiveDemodulators(); } } //end while @@ -264,9 +231,9 @@ void SDRPostThread::runSingleCH(SDRThreadIQData *data_in) { } size_t refCount = nRunDemods; - bool doIQDataOut = (iqDataOutQueue != NULL && !iqDataOutQueue->full()); - bool doDemodVisOut = (nRunDemods && iqActiveDemodVisualQueue != NULL && !iqActiveDemodVisualQueue->full()); - bool doVisOut = (iqVisualQueue != NULL && !iqVisualQueue->full()); + bool doIQDataOut = (iqDataOutQueue != nullptr && !iqDataOutQueue->full()); + bool doDemodVisOut = (nRunDemods && iqActiveDemodVisualQueue != nullptr && !iqActiveDemodVisualQueue->full()); + bool doVisOut = (iqVisualQueue != nullptr && !iqVisualQueue->full()); if (doIQDataOut) { refCount++; @@ -295,22 +262,26 @@ void SDRPostThread::runSingleCH(SDRThreadIQData *data_in) { if (doDemodVisOut) { //VSO: blocking push - iqActiveDemodVisualQueue->push(demodDataOut, MAX_BLOCKING_DURATION_MICROS, "runSingleCH() iqActiveDemodVisualQueue"); + iqActiveDemodVisualQueue->push(demodDataOut); } if (doIQDataOut) { //VSO: blocking push - iqDataOutQueue->push(demodDataOut, MAX_BLOCKING_DURATION_MICROS,"runSingleCH() iqDataOutQueue"); + iqDataOutQueue->push(demodDataOut); } if (doVisOut) { //VSO: blocking push - iqVisualQueue->push(demodDataOut, MAX_BLOCKING_DURATION_MICROS, "runSingleCH() iqVisualQueue"); + iqVisualQueue->push(demodDataOut); } for (size_t i = 0; i < nRunDemods; i++) { - //VSO: blocking push - runDemods[i]->getIQInputDataPipe()->push(demodDataOut, MAX_BLOCKING_DURATION_MICROS, "runSingleCH() runDemods[i]->getIQInputDataPipe()"); + //VSO: timed-push + 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; - if (iqVisualQueue != NULL && !iqVisualQueue->full()) { + if (iqVisualQueue != nullptr && !iqVisualQueue->full()) { doVis = true; } @@ -347,11 +318,11 @@ void SDRPostThread::runPFBCH(SDRThreadIQData *data_in) { iqDataOut->data.assign(data_in->data.begin(), data_in->data.begin() + dataSize); //VSO: blocking push - iqDataOutQueue->push(iqDataOut, MAX_BLOCKING_DURATION_MICROS, "runPFBCH() iqDataOutQueue"); + iqDataOutQueue->push(iqDataOut); if (doVis) { //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); } - DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); + DemodulatorInstancePtr activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); int activeDemodChannel = -1; // Find active demodulators @@ -384,7 +355,7 @@ void SDRPostThread::runPFBCH(SDRThreadIQData *data_in) { // Find nearest channel for each demodulator for (size_t i = 0; i < nRunDemods; i++) { - DemodulatorInstance *demod = runDemods[i]; + DemodulatorInstancePtr demod = runDemods[i]; demodChannel[i] = getChannelAt(demod->getFrequency()); if (demod == activeDemod) { activeDemodChannel = demodChannel[i]; @@ -400,7 +371,7 @@ void SDRPostThread::runPFBCH(SDRThreadIQData *data_in) { // Run channels 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) { continue; @@ -447,16 +418,20 @@ void SDRPostThread::runPFBCH(SDRThreadIQData *data_in) { if (doDemodVis) { //VSO: blocking push - iqActiveDemodVisualQueue->push(demodDataOut, MAX_BLOCKING_DURATION_MICROS, "runPFBCH() iqActiveDemodVisualQueue"); + iqActiveDemodVisualQueue->push(demodDataOut); } for (size_t j = 0; j < nRunDemods; j++) { if (demodChannel[j] == i) { - DemodulatorInstance *demod = runDemods[j]; - //VSO: blocking push - demod->getIQInputDataPipe()->push(demodDataOut, MAX_BLOCKING_DURATION_MICROS, "runPFBCH() demod->getIQInputDataPipe()"); + + //VSO: timed- push + 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 } } } diff --git a/src/sdr/SDRPostThread.h b/src/sdr/SDRPostThread.h index 8dd7693..99a5e16 100644 --- a/src/sdr/SDRPostThread.h +++ b/src/sdr/SDRPostThread.h @@ -11,10 +11,8 @@ public: SDRPostThread(); ~SDRPostThread(); - void bindDemodulator(DemodulatorInstance *demod); - void bindDemodulators(std::vector *demods); - void removeDemodulator(DemodulatorInstance *demod); - + void notifyDemodulatorsChanged(); + virtual void run(); virtual void terminate(); @@ -27,12 +25,6 @@ protected: DemodulatorThreadInputQueuePtr iqDataOutQueue; DemodulatorThreadInputQueuePtr iqVisualQueue; DemodulatorThreadInputQueuePtr iqActiveDemodVisualQueue; - - //protects access to demodulators lists and such - std::mutex busy_demod; - std::vector demodulators; - - private: @@ -48,7 +40,7 @@ private: long long chanBw = 0; size_t nRunDemods; - std::vector runDemods; + std::vector runDemods; std::vector demodChannel; std::vector demodChannelActive; diff --git a/src/sdr/SoapySDRThread.cpp b/src/sdr/SoapySDRThread.cpp index ece5e94..ecd1d54 100644 --- a/src/sdr/SoapySDRThread.cpp +++ b/src/sdr/SoapySDRThread.cpp @@ -13,10 +13,10 @@ #define TARGET_DISPLAY_FPS 60 SDRThread::SDRThread() : IOThread(), buffers("SDRThreadBuffers") { - device = NULL; + device = nullptr; - deviceConfig.store(NULL); - deviceInfo.store(NULL); + deviceConfig.store(nullptr); + deviceInfo.store(nullptr); sampleRate.store(DEFAULT_SAMPLE_RATE); frequency.store(0); diff --git a/src/visual/PrimaryGLContext.cpp b/src/visual/PrimaryGLContext.cpp index fb0385e..5211d5e 100644 --- a/src/visual/PrimaryGLContext.cpp +++ b/src/visual/PrimaryGLContext.cpp @@ -62,7 +62,7 @@ PrimaryGLContext::PrimaryGLContext(wxGLCanvas *canvas, wxGLContext *sharedContex //#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) { return; } @@ -287,7 +287,7 @@ void PrimaryGLContext::DrawFreqBwInfo(long long freq, int bw, RGBA4f color, long 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) { 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) { - DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); + + DemodulatorInstancePtr demod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); long long bw = 0; diff --git a/src/visual/PrimaryGLContext.h b/src/visual/PrimaryGLContext.h index f421def..a799e75 100644 --- a/src/visual/PrimaryGLContext.h +++ b/src/visual/PrimaryGLContext.h @@ -26,9 +26,9 @@ public: 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 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 setHoverAlpha(float hoverAlpha); diff --git a/src/visual/SpectrumCanvas.cpp b/src/visual/SpectrumCanvas.cpp index 7bd75fa..4630f9b 100644 --- a/src/visual/SpectrumCanvas.cpp +++ b/src/visual/SpectrumCanvas.cpp @@ -90,9 +90,8 @@ void SpectrumCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { glLoadIdentity(); - std::vector &demods = wxGetApp().getDemodMgr().getDemodulators(); - - DemodulatorInstance *activeDemodulator = wxGetApp().getDemodMgr().getActiveDemodulator(); + auto demods = wxGetApp().getDemodMgr().getDemodulators(); + auto activeDemodulator = wxGetApp().getDemodMgr().getActiveDemodulator(); for (int i = 0, iMax = demods.size(); i < iMax; i++) { if (!demods[i]->isActive()) { @@ -112,7 +111,7 @@ void SpectrumCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { 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)); diff --git a/src/visual/TuningCanvas.cpp b/src/visual/TuningCanvas.cpp index 2604926..ba95132 100644 --- a/src/visual/TuningCanvas.cpp +++ b/src/visual/TuningCanvas.cpp @@ -61,7 +61,8 @@ TuningCanvas::~TuningCanvas() { } bool TuningCanvas::changed() { - DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); + + auto activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); long long current_freq = 0; if (activeDemod != NULL) { @@ -92,7 +93,7 @@ void TuningCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { glContext->DrawBegin(); - DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); + auto activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); freq = 0; if (activeDemod != NULL) { @@ -170,7 +171,7 @@ void TuningCanvas::StepTuner(ActiveState state, int exponent, bool up) { amount *= 2; } - DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); + auto activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator(); if (state == TUNING_HOVER_FREQ && activeDemod) { long long freq = activeDemod->getFrequency(); 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) { wxGetApp().getDemodMgr().setActiveDemodulator(wxGetApp().getDemodMgr().getLastActiveDemodulator()); } else { - wxGetApp().getDemodMgr().setActiveDemodulator(NULL); + wxGetApp().getDemodMgr().setActiveDemodulator(nullptr); } } @@ -400,7 +401,7 @@ void TuningCanvas::OnMouseLeftWindow(wxMouseEvent& event) { SetCursor(wxCURSOR_CROSS); hoverIndex = 0; hoverState = TUNING_HOVER_NONE; - wxGetApp().getDemodMgr().setActiveDemodulator(NULL); + wxGetApp().getDemodMgr().setActiveDemodulator(nullptr); if (currentPPM != lastPPM) { wxGetApp().saveConfig(); diff --git a/src/visual/WaterfallCanvas.cpp b/src/visual/WaterfallCanvas.cpp index 19f27de..a951a1f 100644 --- a/src/visual/WaterfallCanvas.cpp +++ b/src/visual/WaterfallCanvas.cpp @@ -24,6 +24,8 @@ #include +#include "DemodulatorThread.h" + wxBEGIN_EVENT_TABLE(WaterfallCanvas, wxGLCanvas) EVT_PAINT(WaterfallCanvas::OnPaint) EVT_IDLE(WaterfallCanvas::OnIdle) @@ -263,10 +265,10 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { waterfallPanel.calcTransform(CubicVR::mat4::identity()); waterfallPanel.draw(); - std::vector &demods = wxGetApp().getDemodMgr().getDemodulators(); + auto demods = wxGetApp().getDemodMgr().getDemodulators(); - DemodulatorInstance *activeDemodulator = wxGetApp().getDemodMgr().getActiveDemodulator(); - DemodulatorInstance *lastActiveDemodulator = wxGetApp().getDemodMgr().getLastActiveDemodulator(); + auto activeDemodulator = wxGetApp().getDemodMgr().getActiveDemodulator(); + auto lastActiveDemodulator = wxGetApp().getDemodMgr().getLastActiveDemodulator(); bool isNew = shiftDown || (wxGetApp().getDemodMgr().getLastActiveDemodulator() && !wxGetApp().getDemodMgr().getLastActiveDemodulator()->isActive()); @@ -307,9 +309,9 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { } } else { 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); } else { glContext->DrawDemod(activeDemodulator, currentTheme->waterfallHover, currentCenterFreq, currentBandwidth); @@ -390,7 +392,7 @@ void WaterfallCanvas::OnKeyUp(wxKeyEvent& event) { void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) { InteractiveCanvas::OnKeyDown(event); - DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator(); + auto activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator(); long long originalFreq = getCenterFrequency(); long long freq = originalFreq; @@ -490,9 +492,9 @@ void WaterfallCanvas::OnIdle(wxIdleEvent &event) { void WaterfallCanvas::updateHoverState() { long long freqPos = getFrequencyAt(mouseTracker.getMouseX()); - std::vector demodsHover = wxGetApp().getDemodMgr().getDemodulatorsAt(freqPos, 15000); + auto demodsHover = wxGetApp().getDemodMgr().getDemodulatorsAt(freqPos, 15000); - wxGetApp().getDemodMgr().setActiveDemodulator(NULL); + wxGetApp().getDemodMgr().setActiveDemodulator(nullptr); if (altDown) { nextDragState = WF_DRAG_RANGE; @@ -506,10 +508,10 @@ void WaterfallCanvas::updateHoverState() { } else if (demodsHover.size() && !shiftDown) { long near_dist = getBandwidth(); - DemodulatorInstance *activeDemodulator = NULL; + DemodulatorInstancePtr activeDemodulator = nullptr; 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 halfBw = (demod->getBandwidth() / 2); long long currentBw = getBandwidth(); @@ -537,7 +539,7 @@ void WaterfallCanvas::updateHoverState() { } } - if (activeDemodulator == NULL) { + if (activeDemodulator == nullptr) { nextDragState = WF_DRAG_NONE; SetCursor(wxCURSOR_CROSS); return; @@ -588,10 +590,10 @@ void WaterfallCanvas::updateHoverState() { void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) { InteractiveCanvas::OnMouseMoved(event); - DemodulatorInstance *demod = wxGetApp().getDemodMgr().getActiveDemodulator(); + auto demod = wxGetApp().getDemodMgr().getActiveDemodulator(); if (mouseTracker.mouseDown()) { - if (demod == NULL) { + if (demod == nullptr) { return; } if (dragState == WF_DRAG_BANDWIDTH_LEFT || dragState == WF_DRAG_BANDWIDTH_RIGHT) { @@ -650,7 +652,7 @@ void WaterfallCanvas::OnMouseDown(wxMouseEvent& event) { wxGetApp().getDemodMgr().updateLastState(); if (dragState && dragState != WF_DRAG_RANGE) { - DemodulatorInstance *demod = wxGetApp().getDemodMgr().getActiveDemodulator(); + auto demod = wxGetApp().getDemodMgr().getActiveDemodulator(); if (demod) { dragOfs = (long long) (mouseTracker.getMouseX() * (float) getBandwidth()) + getCenterFrequency() - (getBandwidth() / 2) - demod->getFrequency(); dragBW = demod->getBandwidth(); @@ -670,14 +672,14 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) { InteractiveCanvas::OnMouseReleased(event); wxGetApp().getDemodMgr().updateLastState(); - bool isNew = shiftDown || (wxGetApp().getDemodMgr().getLastActiveDemodulator() == NULL) + bool isNew = shiftDown || (wxGetApp().getDemodMgr().getLastActiveDemodulator() == nullptr) || (wxGetApp().getDemodMgr().getLastActiveDemodulator() && !wxGetApp().getDemodMgr().getLastActiveDemodulator()->isActive()); mouseTracker.setVertDragLock(false); mouseTracker.setHorizDragLock(false); - DemodulatorInstance *demod = isNew?NULL:wxGetApp().getDemodMgr().getLastActiveDemodulator(); - DemodulatorInstance *activeDemod = isNew?NULL:wxGetApp().getDemodMgr().getActiveDemodulator(); + DemodulatorInstancePtr demod = isNew?nullptr:wxGetApp().getDemodMgr().getLastActiveDemodulator(); + DemodulatorInstancePtr activeDemod = isNew?nullptr:wxGetApp().getDemodMgr().getActiveDemodulator(); DemodulatorMgr *mgr = &wxGetApp().getDemodMgr(); @@ -727,7 +729,7 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) { demod->writeModemSettings(mgr->getLastModemSettings(mgr->getLastDemodulatorType())); demod->run(); - wxGetApp().bindDemodulator(demod); + wxGetApp().notifyDemodulatorsChanged(); DemodulatorThread::releaseSquelchLock(nullptr); } @@ -827,10 +829,10 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) { demod->run(); - wxGetApp().bindDemodulator(demod); + wxGetApp().notifyDemodulatorsChanged(); } - if (demod == NULL) { + if (demod == nullptr) { dragState = WF_DRAG_NONE; return; } @@ -850,7 +852,7 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) { void WaterfallCanvas::OnMouseLeftWindow(wxMouseEvent& event) { InteractiveCanvas::OnMouseLeftWindow(event); SetCursor(wxCURSOR_CROSS); - wxGetApp().getDemodMgr().setActiveDemodulator(NULL); + wxGetApp().getDemodMgr().setActiveDemodulator(nullptr); mouseZoom = 1.0; }