mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2024-11-26 13:48:38 -05:00
Merge pull request #572 from cjcliffe/vso_shared_ptr_DemodulatorInstances
Let's see if I've broken something :)
This commit is contained in:
commit
2d01a279e9
@ -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<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");
|
||||
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<DemodulatorInstance *> demodsLoaded;
|
||||
std::vector<DemodulatorInstancePtr> 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()) {
|
||||
|
@ -26,7 +26,8 @@
|
||||
#include "FrequencyDialog.h"
|
||||
#include "BookmarkView.h"
|
||||
#include "AboutDialog.h"
|
||||
|
||||
#include "DemodulatorInstance.h"
|
||||
#include "DemodulatorThread.h"
|
||||
#include <map>
|
||||
|
||||
#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<RtAudio::DeviceInfo> devices;
|
||||
std::map<int,RtAudio::DeviceInfo> inputDevices;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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<DemodulatorInstance *> *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) {
|
||||
|
||||
|
@ -121,9 +121,9 @@ public:
|
||||
SDRPostThread *getSDRPostThread();
|
||||
SDRThread *getSDRThread();
|
||||
|
||||
void bindDemodulator(DemodulatorInstance *demod);
|
||||
void bindDemodulators(std::vector<DemodulatorInstance *> *demods);
|
||||
void removeDemodulator(DemodulatorInstance *demod);
|
||||
void notifyDemodulatorsChanged();
|
||||
|
||||
void removeDemodulator(DemodulatorInstancePtr demod);
|
||||
|
||||
void setFrequencySnap(int snap);
|
||||
int getFrequencySnap();
|
||||
|
@ -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) {
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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<std::string, wxPGProperty *> props;
|
||||
bool mouseInView, collapsed;
|
||||
|
||||
|
@ -304,14 +304,12 @@ void AudioThread::setSampleRate(int sampleRate) {
|
||||
srcmix->setSampleRate(sampleRate);
|
||||
}
|
||||
|
||||
std::vector<DemodulatorInstance *>::iterator demod_i;
|
||||
std::vector<DemodulatorInstance *> *demodulators;
|
||||
//make a local copy, snapshot of the list of demodulators
|
||||
std::vector<DemodulatorInstancePtr> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,10 @@ public:
|
||||
|
||||
typedef std::shared_ptr<AudioThreadInput> AudioThreadInputPtr;
|
||||
|
||||
typedef ThreadBlockingQueue<AudioThreadInputPtr> DemodulatorThreadOutputQueue;
|
||||
|
||||
typedef std::shared_ptr<DemodulatorThreadOutputQueue> DemodulatorThreadOutputQueuePtr;
|
||||
|
||||
class AudioThreadCommand {
|
||||
public:
|
||||
enum AudioThreadCommandEnum {
|
||||
|
@ -15,7 +15,6 @@
|
||||
|
||||
class DemodulatorThread;
|
||||
|
||||
|
||||
class DemodulatorThreadControlCommand {
|
||||
public:
|
||||
enum DemodulatorThreadControlCommandEnum {
|
||||
|
@ -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
|
||||
|
@ -6,12 +6,11 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <thread>
|
||||
|
||||
#include "DemodulatorThread.h"
|
||||
#include "DemodulatorPreThread.h"
|
||||
|
||||
#include <memory>
|
||||
#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<std::string *> label; //
|
||||
// User editable buffer, 16 bit string.
|
||||
@ -161,3 +162,5 @@ private:
|
||||
ModemDigitalOutput *activeOutput;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<DemodulatorInstance> DemodulatorInstancePtr;
|
||||
|
@ -17,13 +17,11 @@
|
||||
|
||||
#include "DataTree.h"
|
||||
|
||||
bool demodFreqCompare (DemodulatorInstance *i, DemodulatorInstance *j) { return (i->getFrequency()<j->getFrequency()); }
|
||||
bool inactiveCompare (DemodulatorInstance *i, DemodulatorInstance *j) { return (i->isActive()<j->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<DemodulatorInstance>();
|
||||
|
||||
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<DemodulatorInstance *> &DemodulatorMgr::getDemodulators() {
|
||||
std::vector<DemodulatorInstancePtr> DemodulatorMgr::getDemodulators() {
|
||||
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
||||
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::vector<DemodulatorInstance *> demods_ordered = demods;
|
||||
|
||||
auto demods_ordered = demods;
|
||||
|
||||
if (actives) {
|
||||
|
||||
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++) {
|
||||
if ((*i)->isActive()) {
|
||||
break;
|
||||
@ -88,13 +95,14 @@ std::vector<DemodulatorInstance *> 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<DemodulatorInstance *> demods_ordered = getOrderedDemodulators(actives);
|
||||
std::vector<DemodulatorInstance *>::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<DemodulatorInstance *> demods_ordered = getOrderedDemodulators(actives);
|
||||
std::vector<DemodulatorInstance *>::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<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::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);
|
||||
|
||||
wxGetApp().getBookmarkMgr().addRecent(demod);
|
||||
|
||||
std::vector<DemodulatorInstance *>::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<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::vector<DemodulatorInstance *> foundDemods;
|
||||
std::vector<DemodulatorInstancePtr> 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<DemodulatorInstance *> 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<DemodulatorInstance *>::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<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() {
|
||||
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<int,RtAudio::DeviceInfo> 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();
|
||||
|
||||
|
@ -16,23 +16,32 @@ public:
|
||||
DemodulatorMgr();
|
||||
~DemodulatorMgr();
|
||||
|
||||
DemodulatorInstance *newThread();
|
||||
std::vector<DemodulatorInstance *> &getDemodulators();
|
||||
std::vector<DemodulatorInstance *> getOrderedDemodulators(bool actives = true);
|
||||
std::vector<DemodulatorInstance *> 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<DemodulatorInstancePtr> getDemodulators();
|
||||
|
||||
std::vector<DemodulatorInstancePtr> getOrderedDemodulators(bool actives = true);
|
||||
std::vector<DemodulatorInstancePtr> 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<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:
|
||||
|
||||
std::vector<DemodulatorInstance *> demods;
|
||||
std::vector<DemodulatorInstance *> demods_deleted;
|
||||
std::vector<DemodulatorInstancePtr> demods;
|
||||
|
||||
std::atomic<DemodulatorInstance *> activeDemodulator;
|
||||
std::atomic<DemodulatorInstance *> lastActiveDemodulator;
|
||||
std::atomic<DemodulatorInstance *> 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<std::string, ModemSettings> lastModemSettings;
|
||||
std::map<int,RtAudio::DeviceInfo> outputDevices;
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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<liquid_float_complex> resampledData;
|
||||
|
@ -19,10 +19,10 @@
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
std::atomic<DemodulatorInstance *> 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;
|
||||
}
|
||||
}
|
@ -11,10 +11,6 @@
|
||||
#include "AudioThread.h"
|
||||
#include "Modem.h"
|
||||
|
||||
typedef ThreadBlockingQueue<AudioThreadInputPtr> DemodulatorThreadOutputQueue;
|
||||
|
||||
typedef std::shared_ptr<DemodulatorThreadOutputQueue> 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<AudioThreadInput> outputBuffers;
|
||||
|
||||
std::atomic_bool muted;
|
||||
@ -58,7 +55,7 @@ protected:
|
||||
std::atomic<float> signalLevel, signalFloor, signalCeil;
|
||||
bool squelchEnabled, squelchBreak;
|
||||
|
||||
static std::atomic<DemodulatorInstance *> squelchLock;
|
||||
static DemodulatorInstance* squelchLock;
|
||||
static std::mutex squelchLockMutex;
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -348,10 +348,9 @@ wxTreeItemId BookmarkView::refreshBookmarks() {
|
||||
|
||||
|
||||
void BookmarkView::doUpdateActiveList() {
|
||||
std::vector<DemodulatorInstance *> &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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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<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() {
|
||||
// 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<DemodulatorInstance *>::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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,10 +11,8 @@ public:
|
||||
SDRPostThread();
|
||||
~SDRPostThread();
|
||||
|
||||
void bindDemodulator(DemodulatorInstance *demod);
|
||||
void bindDemodulators(std::vector<DemodulatorInstance *> *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<DemodulatorInstance *> demodulators;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@ -48,7 +40,7 @@ private:
|
||||
long long chanBw = 0;
|
||||
|
||||
size_t nRunDemods;
|
||||
std::vector<DemodulatorInstance *> runDemods;
|
||||
std::vector<DemodulatorInstancePtr> runDemods;
|
||||
std::vector<int> demodChannel;
|
||||
std::vector<int> demodChannelActive;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -90,9 +90,8 @@ void SpectrumCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
||||
|
||||
glLoadIdentity();
|
||||
|
||||
std::vector<DemodulatorInstance *> &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));
|
||||
|
||||
|
@ -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();
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
#include <wx/numformatter.h>
|
||||
|
||||
#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<DemodulatorInstance *> &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<DemodulatorInstance *> 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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user