mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2024-11-29 23:28:39 -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.
|
DemodulatorInstancePtr demod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
||||||
wxGetApp().getDemodMgr().garbageCollect();
|
|
||||||
|
|
||||||
DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
|
||||||
|
|
||||||
if (demod && demod->isModemInitialized()) {
|
if (demod && demod->isModemInitialized()) {
|
||||||
if (demod->isTracking()) {
|
if (demod->isTracking()) {
|
||||||
@ -2129,11 +2126,12 @@ void AppFrame::saveSession(std::string fileName) {
|
|||||||
|
|
||||||
DataNode *demods = s.rootNode()->newChild("demodulators");
|
DataNode *demods = s.rootNode()->newChild("demodulators");
|
||||||
|
|
||||||
std::vector<DemodulatorInstance *> &instances = wxGetApp().getDemodMgr().getDemodulators();
|
//make a local copy snapshot of the list
|
||||||
|
std::vector<DemodulatorInstancePtr> instances = wxGetApp().getDemodMgr().getDemodulators();
|
||||||
|
|
||||||
for (auto instance_i : instances) {
|
for (auto instance : instances) {
|
||||||
DataNode *demod = demods->newChild("demodulator");
|
DataNode *demod = demods->newChild("demodulator");
|
||||||
wxGetApp().getDemodMgr().saveInstance(demod, instance_i);
|
wxGetApp().getDemodMgr().saveInstance(demod, instance);
|
||||||
} //end for demodulators
|
} //end for demodulators
|
||||||
|
|
||||||
// Make sure the file name actually ends in .xml
|
// Make sure the file name actually ends in .xml
|
||||||
@ -2247,14 +2245,14 @@ bool AppFrame::loadSession(std::string fileName) {
|
|||||||
wxGetApp().setSoloMode(false);
|
wxGetApp().setSoloMode(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorInstance *loadedActiveDemod = nullptr;
|
DemodulatorInstancePtr loadedActiveDemod = nullptr;
|
||||||
DemodulatorInstance *newDemod = nullptr;
|
DemodulatorInstancePtr newDemod = nullptr;
|
||||||
|
|
||||||
if (l.rootNode()->hasAnother("demodulators")) {
|
if (l.rootNode()->hasAnother("demodulators")) {
|
||||||
|
|
||||||
DataNode *demodulators = l.rootNode()->getNext("demodulators");
|
DataNode *demodulators = l.rootNode()->getNext("demodulators");
|
||||||
|
|
||||||
std::vector<DemodulatorInstance *> demodsLoaded;
|
std::vector<DemodulatorInstancePtr> demodsLoaded;
|
||||||
|
|
||||||
while (demodulators->hasAnother("demodulator")) {
|
while (demodulators->hasAnother("demodulator")) {
|
||||||
DataNode *demod = demodulators->getNext("demodulator");
|
DataNode *demod = demodulators->getNext("demodulator");
|
||||||
@ -2275,7 +2273,7 @@ bool AppFrame::loadSession(std::string fileName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (demodsLoaded.size()) {
|
if (demodsLoaded.size()) {
|
||||||
wxGetApp().bindDemodulators(&demodsLoaded);
|
wxGetApp().notifyDemodulatorsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // if l.rootNode()->hasAnother("demodulators")
|
} // if l.rootNode()->hasAnother("demodulators")
|
||||||
@ -2404,14 +2402,14 @@ FrequencyDialog::FrequencyDialogTarget AppFrame::getFrequencyDialogTarget() {
|
|||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppFrame::gkNudgeLeft(DemodulatorInstance *demod, int snap) {
|
void AppFrame::gkNudgeLeft(DemodulatorInstancePtr demod, int snap) {
|
||||||
if (demod) {
|
if (demod) {
|
||||||
demod->setFrequency(demod->getFrequency()-snap);
|
demod->setFrequency(demod->getFrequency()-snap);
|
||||||
demod->updateLabel(demod->getFrequency());
|
demod->updateLabel(demod->getFrequency());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppFrame::gkNudgeRight(DemodulatorInstance *demod, int snap) {
|
void AppFrame::gkNudgeRight(DemodulatorInstancePtr demod, int snap) {
|
||||||
if (demod) {
|
if (demod) {
|
||||||
demod->setFrequency(demod->getFrequency()+snap);
|
demod->setFrequency(demod->getFrequency()+snap);
|
||||||
demod->updateLabel(demod->getFrequency());
|
demod->updateLabel(demod->getFrequency());
|
||||||
@ -2437,7 +2435,10 @@ int AppFrame::OnGlobalKeyDown(wxKeyEvent &event) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorInstance *demod = nullptr, *lastDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
DemodulatorInstancePtr demod = nullptr;
|
||||||
|
|
||||||
|
DemodulatorInstancePtr lastDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
||||||
|
|
||||||
int snap = wxGetApp().getFrequencySnap();
|
int snap = wxGetApp().getFrequencySnap();
|
||||||
|
|
||||||
if (event.ControlDown()) {
|
if (event.ControlDown()) {
|
||||||
@ -2562,8 +2563,8 @@ int AppFrame::OnGlobalKeyUp(wxKeyEvent &event) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator();
|
DemodulatorInstancePtr activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator();
|
||||||
DemodulatorInstance *lastDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
DemodulatorInstancePtr lastDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
||||||
|
|
||||||
#ifdef wxHAS_RAW_KEY_CODES
|
#ifdef wxHAS_RAW_KEY_CODES
|
||||||
switch (event.GetRawKeyCode()) {
|
switch (event.GetRawKeyCode()) {
|
||||||
|
@ -26,7 +26,8 @@
|
|||||||
#include "FrequencyDialog.h"
|
#include "FrequencyDialog.h"
|
||||||
#include "BookmarkView.h"
|
#include "BookmarkView.h"
|
||||||
#include "AboutDialog.h"
|
#include "AboutDialog.h"
|
||||||
|
#include "DemodulatorInstance.h"
|
||||||
|
#include "DemodulatorThread.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#define wxID_RT_AUDIO_DEVICE 1000
|
#define wxID_RT_AUDIO_DEVICE 1000
|
||||||
@ -107,8 +108,8 @@ public:
|
|||||||
void setMainWaterfallFFTSize(int fftSize);
|
void setMainWaterfallFFTSize(int fftSize);
|
||||||
void setScopeDeviceName(std::string deviceName);
|
void setScopeDeviceName(std::string deviceName);
|
||||||
|
|
||||||
void gkNudgeLeft(DemodulatorInstance *demod, int snap);
|
void gkNudgeLeft(DemodulatorInstancePtr demod, int snap);
|
||||||
void gkNudgeRight(DemodulatorInstance *demod, int snap);
|
void gkNudgeRight(DemodulatorInstancePtr demod, int snap);
|
||||||
|
|
||||||
int OnGlobalKeyDown(wxKeyEvent &event);
|
int OnGlobalKeyDown(wxKeyEvent &event);
|
||||||
int OnGlobalKeyUp(wxKeyEvent &event);
|
int OnGlobalKeyUp(wxKeyEvent &event);
|
||||||
@ -193,7 +194,7 @@ private:
|
|||||||
wxBoxSizer *demodTray;
|
wxBoxSizer *demodTray;
|
||||||
BookmarkView *bookmarkView;
|
BookmarkView *bookmarkView;
|
||||||
|
|
||||||
DemodulatorInstance *activeDemodulator;
|
DemodulatorInstancePtr activeDemodulator;
|
||||||
|
|
||||||
std::vector<RtAudio::DeviceInfo> devices;
|
std::vector<RtAudio::DeviceInfo> devices;
|
||||||
std::map<int,RtAudio::DeviceInfo> inputDevices;
|
std::map<int,RtAudio::DeviceInfo> inputDevices;
|
||||||
|
@ -205,7 +205,7 @@ bool BookmarkMgr::hasBackup(std::string bookmarkFn) {
|
|||||||
return backupFile.FileExists() && backupFile.IsFileReadable();
|
return backupFile.FileExists() && backupFile.IsFileReadable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BookmarkMgr::addBookmark(std::string group, DemodulatorInstance *demod) {
|
void BookmarkMgr::addBookmark(std::string group, DemodulatorInstancePtr demod) {
|
||||||
std::lock_guard < std::recursive_mutex > lock(busy_lock);
|
std::lock_guard < std::recursive_mutex > lock(busy_lock);
|
||||||
|
|
||||||
//Create a BookmarkEntry from demod data, saving its
|
//Create a BookmarkEntry from demod data, saving its
|
||||||
@ -392,7 +392,7 @@ void BookmarkMgr::updateBookmarks(std::string group) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BookmarkMgr::addRecent(DemodulatorInstance *demod) {
|
void BookmarkMgr::addRecent(DemodulatorInstancePtr demod) {
|
||||||
std::lock_guard < std::recursive_mutex > lock(busy_lock);
|
std::lock_guard < std::recursive_mutex > lock(busy_lock);
|
||||||
|
|
||||||
recents.push_back(demodToBookmarkEntry(demod));
|
recents.push_back(demodToBookmarkEntry(demod));
|
||||||
@ -482,7 +482,7 @@ void BookmarkMgr::clearRanges() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BookmarkEntryPtr BookmarkMgr::demodToBookmarkEntry(DemodulatorInstance *demod) {
|
BookmarkEntryPtr BookmarkMgr::demodToBookmarkEntry(DemodulatorInstancePtr demod) {
|
||||||
|
|
||||||
BookmarkEntryPtr be(new BookmarkEntry);
|
BookmarkEntryPtr be(new BookmarkEntry);
|
||||||
|
|
||||||
@ -536,7 +536,7 @@ std::wstring BookmarkMgr::getBookmarkEntryDisplayName(BookmarkEntryPtr bmEnt) {
|
|||||||
return dispName;
|
return dispName;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring BookmarkMgr::getActiveDisplayName(DemodulatorInstance *demod) {
|
std::wstring BookmarkMgr::getActiveDisplayName(DemodulatorInstancePtr demod) {
|
||||||
std::wstring activeName = demod->getDemodulatorUserLabel();
|
std::wstring activeName = demod->getDemodulatorUserLabel();
|
||||||
|
|
||||||
if (activeName == "") {
|
if (activeName == "") {
|
||||||
@ -547,7 +547,7 @@ std::wstring BookmarkMgr::getActiveDisplayName(DemodulatorInstance *demod) {
|
|||||||
return activeName;
|
return activeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BookmarkMgr::removeActive(DemodulatorInstance *demod) {
|
void BookmarkMgr::removeActive(DemodulatorInstancePtr demod) {
|
||||||
|
|
||||||
std::lock_guard < std::recursive_mutex > lock(busy_lock);
|
std::lock_guard < std::recursive_mutex > lock(busy_lock);
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ public:
|
|||||||
bool hasLastLoad(std::string bookmarkFn);
|
bool hasLastLoad(std::string bookmarkFn);
|
||||||
bool hasBackup(std::string bookmarkFn);
|
bool hasBackup(std::string bookmarkFn);
|
||||||
|
|
||||||
void addBookmark(std::string group, DemodulatorInstance *demod);
|
void addBookmark(std::string group, DemodulatorInstancePtr demod);
|
||||||
void addBookmark(std::string group, BookmarkEntryPtr be);
|
void addBookmark(std::string group, BookmarkEntryPtr be);
|
||||||
void removeBookmark(std::string group, BookmarkEntryPtr be);
|
void removeBookmark(std::string group, BookmarkEntryPtr be);
|
||||||
void removeBookmark(BookmarkEntryPtr be);
|
void removeBookmark(BookmarkEntryPtr be);
|
||||||
@ -105,13 +105,13 @@ public:
|
|||||||
void updateBookmarks();
|
void updateBookmarks();
|
||||||
void updateBookmarks(std::string group);
|
void updateBookmarks(std::string group);
|
||||||
|
|
||||||
void addRecent(DemodulatorInstance *demod);
|
void addRecent(DemodulatorInstancePtr demod);
|
||||||
void addRecent(BookmarkEntryPtr be);
|
void addRecent(BookmarkEntryPtr be);
|
||||||
void removeRecent(BookmarkEntryPtr be);
|
void removeRecent(BookmarkEntryPtr be);
|
||||||
const BookmarkList& getRecents();
|
const BookmarkList& getRecents();
|
||||||
void clearRecents();
|
void clearRecents();
|
||||||
|
|
||||||
void removeActive(DemodulatorInstance *demod);
|
void removeActive(DemodulatorInstancePtr demod);
|
||||||
|
|
||||||
void addRange(BookmarkRangeEntryPtr re);
|
void addRange(BookmarkRangeEntryPtr re);
|
||||||
void removeRange(BookmarkRangeEntryPtr re);
|
void removeRange(BookmarkRangeEntryPtr re);
|
||||||
@ -119,13 +119,13 @@ public:
|
|||||||
void clearRanges();
|
void clearRanges();
|
||||||
|
|
||||||
static std::wstring getBookmarkEntryDisplayName(BookmarkEntryPtr bmEnt);
|
static std::wstring getBookmarkEntryDisplayName(BookmarkEntryPtr bmEnt);
|
||||||
static std::wstring getActiveDisplayName(DemodulatorInstance *demod);
|
static std::wstring getActiveDisplayName(DemodulatorInstancePtr demod);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void trimRecents();
|
void trimRecents();
|
||||||
|
|
||||||
BookmarkEntryPtr demodToBookmarkEntry(DemodulatorInstance *demod);
|
BookmarkEntryPtr demodToBookmarkEntry(DemodulatorInstancePtr demod);
|
||||||
BookmarkEntryPtr nodeToBookmark(DataNode *node);
|
BookmarkEntryPtr nodeToBookmark(DataNode *node);
|
||||||
|
|
||||||
BookmarkMap bmData;
|
BookmarkMap bmData;
|
||||||
|
@ -421,9 +421,6 @@ int CubicSDR::OnExit() {
|
|||||||
std::cout << "Terminating All Demodulators.." << std::endl << std::flush;
|
std::cout << "Terminating All Demodulators.." << std::endl << std::flush;
|
||||||
demodMgr.terminateAll();
|
demodMgr.terminateAll();
|
||||||
|
|
||||||
//wait for effective death of all demodulators before continuing.
|
|
||||||
terminationSequenceOK = terminationSequenceOK && demodMgr.garbageCollect(true, 3000);
|
|
||||||
|
|
||||||
std::cout << "Terminating Visual Processor threads.." << std::endl << std::flush;
|
std::cout << "Terminating Visual Processor threads.." << std::endl << std::flush;
|
||||||
spectrumVisualThread->terminate();
|
spectrumVisualThread->terminate();
|
||||||
if (demodVisualThread) {
|
if (demodVisualThread) {
|
||||||
@ -831,30 +828,21 @@ SDRThread *CubicSDR::getSDRThread() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CubicSDR::bindDemodulator(DemodulatorInstance *demod) {
|
void CubicSDR::notifyDemodulatorsChanged() {
|
||||||
if (!demod) {
|
|
||||||
return;
|
sdrPostThread->notifyDemodulatorsChanged();
|
||||||
}
|
|
||||||
sdrPostThread->bindDemodulator(demod);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CubicSDR::bindDemodulators(std::vector<DemodulatorInstance *> *demods) {
|
|
||||||
if (!demods) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sdrPostThread->bindDemodulators(demods);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long long CubicSDR::getSampleRate() {
|
long long CubicSDR::getSampleRate() {
|
||||||
return sampleRate;
|
return sampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CubicSDR::removeDemodulator(DemodulatorInstance *demod) {
|
void CubicSDR::removeDemodulator(DemodulatorInstancePtr demod) {
|
||||||
if (!demod) {
|
if (!demod) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
demod->setActive(false);
|
demod->setActive(false);
|
||||||
sdrPostThread->removeDemodulator(demod);
|
sdrPostThread->notifyDemodulatorsChanged();
|
||||||
wxGetApp().getAppFrame()->notifyUpdateModemProperties();
|
wxGetApp().getAppFrame()->notifyUpdateModemProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -926,7 +914,7 @@ void CubicSDR::showFrequencyInput(FrequencyDialog::FrequencyDialogTarget targetM
|
|||||||
|
|
||||||
void CubicSDR::showLabelInput() {
|
void CubicSDR::showLabelInput() {
|
||||||
|
|
||||||
DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator();
|
DemodulatorInstancePtr activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator();
|
||||||
|
|
||||||
if (activeDemod != nullptr) {
|
if (activeDemod != nullptr) {
|
||||||
|
|
||||||
|
@ -121,9 +121,9 @@ public:
|
|||||||
SDRPostThread *getSDRPostThread();
|
SDRPostThread *getSDRPostThread();
|
||||||
SDRThread *getSDRThread();
|
SDRThread *getSDRThread();
|
||||||
|
|
||||||
void bindDemodulator(DemodulatorInstance *demod);
|
void notifyDemodulatorsChanged();
|
||||||
void bindDemodulators(std::vector<DemodulatorInstance *> *demods);
|
|
||||||
void removeDemodulator(DemodulatorInstance *demod);
|
void removeDemodulator(DemodulatorInstancePtr demod);
|
||||||
|
|
||||||
void setFrequencySnap(int snap);
|
void setFrequencySnap(int snap);
|
||||||
int getFrequencySnap();
|
int getFrequencySnap();
|
||||||
|
@ -13,7 +13,7 @@ EVT_SHOW(DemodLabelDialog::OnShow)
|
|||||||
wxEND_EVENT_TABLE()
|
wxEND_EVENT_TABLE()
|
||||||
|
|
||||||
DemodLabelDialog::DemodLabelDialog(wxWindow * parent, wxWindowID id, const wxString & title,
|
DemodLabelDialog::DemodLabelDialog(wxWindow * parent, wxWindowID id, const wxString & title,
|
||||||
DemodulatorInstance *demod, const wxPoint & position,
|
DemodulatorInstancePtr demod, const wxPoint & position,
|
||||||
const wxSize & size, long style) :
|
const wxSize & size, long style) :
|
||||||
wxDialog(parent, id, title, position, size, style) {
|
wxDialog(parent, id, title, position, size, style) {
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ class DemodLabelDialog : public wxDialog
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
DemodLabelDialog( wxWindow * parent, wxWindowID id, const wxString & title,
|
DemodLabelDialog( wxWindow * parent, wxWindowID id, const wxString & title,
|
||||||
DemodulatorInstance *demod = NULL,
|
DemodulatorInstancePtr demod = nullptr,
|
||||||
const wxPoint & pos = wxDefaultPosition,
|
const wxPoint & pos = wxDefaultPosition,
|
||||||
const wxSize & size = wxDefaultSize,
|
const wxSize & size = wxDefaultSize,
|
||||||
long style = wxDEFAULT_DIALOG_STYLE);
|
long style = wxDEFAULT_DIALOG_STYLE);
|
||||||
@ -24,7 +24,7 @@ public:
|
|||||||
wxTextCtrl * dialogText;
|
wxTextCtrl * dialogText;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DemodulatorInstance *activeDemod = nullptr;
|
DemodulatorInstancePtr activeDemod = nullptr;
|
||||||
void OnEnter ( wxCommandEvent &event );
|
void OnEnter ( wxCommandEvent &event );
|
||||||
void OnChar ( wxKeyEvent &event );
|
void OnChar ( wxKeyEvent &event );
|
||||||
void OnShow(wxShowEvent &event);
|
void OnShow(wxShowEvent &event);
|
||||||
|
@ -12,11 +12,13 @@ EVT_CHAR_HOOK(FrequencyDialog::OnChar)
|
|||||||
EVT_SHOW(FrequencyDialog::OnShow)
|
EVT_SHOW(FrequencyDialog::OnShow)
|
||||||
wxEND_EVENT_TABLE()
|
wxEND_EVENT_TABLE()
|
||||||
|
|
||||||
FrequencyDialog::FrequencyDialog(wxWindow * parent, wxWindowID id, const wxString & title, DemodulatorInstance *demod, const wxPoint & position,
|
FrequencyDialog::FrequencyDialog(wxWindow * parent, wxWindowID id, const wxString & title, DemodulatorInstancePtr demod, const wxPoint & position,
|
||||||
const wxSize & size, long style, FrequencyDialogTarget targetMode, wxString initString) :
|
const wxSize & size, long style, FrequencyDialogTarget targetMode, wxString initString) :
|
||||||
wxDialog(parent, id, title, position, size, style) {
|
wxDialog(parent, id, title, position, size, style) {
|
||||||
wxString freqStr;
|
wxString freqStr;
|
||||||
|
|
||||||
activeDemod = demod;
|
activeDemod = demod;
|
||||||
|
|
||||||
this->targetMode = targetMode;
|
this->targetMode = targetMode;
|
||||||
this->initialString = initString;
|
this->initialString = initString;
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ public:
|
|||||||
FDIALOG_TARGET_GAIN
|
FDIALOG_TARGET_GAIN
|
||||||
} FrequencyDialogTarget;
|
} FrequencyDialogTarget;
|
||||||
FrequencyDialog ( wxWindow * parent, wxWindowID id, const wxString & title,
|
FrequencyDialog ( wxWindow * parent, wxWindowID id, const wxString & title,
|
||||||
DemodulatorInstance *demod = NULL,
|
DemodulatorInstancePtr demod = nullptr,
|
||||||
const wxPoint & pos = wxDefaultPosition,
|
const wxPoint & pos = wxDefaultPosition,
|
||||||
const wxSize & size = wxDefaultSize,
|
const wxSize & size = wxDefaultSize,
|
||||||
long style = wxDEFAULT_DIALOG_STYLE,
|
long style = wxDEFAULT_DIALOG_STYLE,
|
||||||
@ -34,7 +34,7 @@ public:
|
|||||||
wxTextCtrl * dialogText;
|
wxTextCtrl * dialogText;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DemodulatorInstance *activeDemod;
|
DemodulatorInstancePtr activeDemod;
|
||||||
void OnEnter ( wxCommandEvent &event );
|
void OnEnter ( wxCommandEvent &event );
|
||||||
void OnChar ( wxKeyEvent &event );
|
void OnChar ( wxKeyEvent &event );
|
||||||
void OnShow(wxShowEvent &event);
|
void OnShow(wxShowEvent &event);
|
||||||
|
@ -101,7 +101,7 @@ void ModemProperties::initDefaultProperties() {
|
|||||||
defaultProps["._audio_output"] = addArgInfoProperty(m_propertyGrid, outputArg);
|
defaultProps["._audio_output"] = addArgInfoProperty(m_propertyGrid, outputArg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModemProperties::initProperties(ModemArgInfoList newArgs, DemodulatorInstance *demodInstance) {
|
void ModemProperties::initProperties(ModemArgInfoList newArgs, DemodulatorInstancePtr demodInstance) {
|
||||||
args = newArgs;
|
args = newArgs;
|
||||||
demodContext = demodInstance;
|
demodContext = demodInstance;
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ public:
|
|||||||
~ModemProperties();
|
~ModemProperties();
|
||||||
|
|
||||||
void initDefaultProperties();
|
void initDefaultProperties();
|
||||||
void initProperties(ModemArgInfoList newArgs, DemodulatorInstance *demodInstance);
|
void initProperties(ModemArgInfoList newArgs, DemodulatorInstancePtr demodInstance);
|
||||||
bool isMouseInView();
|
bool isMouseInView();
|
||||||
void setCollapsed(bool state);
|
void setCollapsed(bool state);
|
||||||
bool isCollapsed();
|
bool isCollapsed();
|
||||||
@ -46,7 +46,8 @@ private:
|
|||||||
wxBoxSizer* bSizer;
|
wxBoxSizer* bSizer;
|
||||||
wxPropertyGrid* m_propertyGrid;
|
wxPropertyGrid* m_propertyGrid;
|
||||||
ModemArgInfoList args;
|
ModemArgInfoList args;
|
||||||
DemodulatorInstance *demodContext;
|
DemodulatorInstancePtr demodContext;
|
||||||
|
|
||||||
std::map<std::string, wxPGProperty *> props;
|
std::map<std::string, wxPGProperty *> props;
|
||||||
bool mouseInView, collapsed;
|
bool mouseInView, collapsed;
|
||||||
|
|
||||||
|
@ -304,14 +304,12 @@ void AudioThread::setSampleRate(int sampleRate) {
|
|||||||
srcmix->setSampleRate(sampleRate);
|
srcmix->setSampleRate(sampleRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<DemodulatorInstance *>::iterator demod_i;
|
//make a local copy, snapshot of the list of demodulators
|
||||||
std::vector<DemodulatorInstance *> *demodulators;
|
std::vector<DemodulatorInstancePtr> demodulators = wxGetApp().getDemodMgr().getDemodulators();
|
||||||
|
|
||||||
demodulators = &wxGetApp().getDemodMgr().getDemodulators();
|
for (auto demod : demodulators) {
|
||||||
|
if (demod->getOutputDevice() == outputDevice.load()) {
|
||||||
for (demod_i = demodulators->begin(); demod_i != demodulators->end(); demod_i++) {
|
demod->setAudioSampleRate(sampleRate);
|
||||||
if ((*demod_i)->getOutputDevice() == outputDevice.load()) {
|
|
||||||
(*demod_i)->setAudioSampleRate(sampleRate);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,10 @@ public:
|
|||||||
|
|
||||||
typedef std::shared_ptr<AudioThreadInput> AudioThreadInputPtr;
|
typedef std::shared_ptr<AudioThreadInput> AudioThreadInputPtr;
|
||||||
|
|
||||||
|
typedef ThreadBlockingQueue<AudioThreadInputPtr> DemodulatorThreadOutputQueue;
|
||||||
|
|
||||||
|
typedef std::shared_ptr<DemodulatorThreadOutputQueue> DemodulatorThreadOutputQueuePtr;
|
||||||
|
|
||||||
class AudioThreadCommand {
|
class AudioThreadCommand {
|
||||||
public:
|
public:
|
||||||
enum AudioThreadCommandEnum {
|
enum AudioThreadCommandEnum {
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
|
|
||||||
class DemodulatorThread;
|
class DemodulatorThread;
|
||||||
|
|
||||||
|
|
||||||
class DemodulatorThreadControlCommand {
|
class DemodulatorThreadControlCommand {
|
||||||
public:
|
public:
|
||||||
enum DemodulatorThreadControlCommandEnum {
|
enum DemodulatorThreadControlCommandEnum {
|
||||||
|
@ -5,6 +5,10 @@
|
|||||||
#include "DemodulatorInstance.h"
|
#include "DemodulatorInstance.h"
|
||||||
#include "CubicSDR.h"
|
#include "CubicSDR.h"
|
||||||
|
|
||||||
|
#include "DemodulatorThread.h"
|
||||||
|
#include "DemodulatorPreThread.h"
|
||||||
|
|
||||||
|
|
||||||
#if USE_HAMLIB
|
#if USE_HAMLIB
|
||||||
#include "RigThread.h"
|
#include "RigThread.h"
|
||||||
#endif
|
#endif
|
||||||
@ -79,13 +83,37 @@ DemodulatorInstance::DemodulatorInstance() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorInstance::~DemodulatorInstance() {
|
DemodulatorInstance::~DemodulatorInstance() {
|
||||||
std::lock_guard < std::mutex > lockData(m_thread_control_mutex);
|
|
||||||
|
std::lock_guard < std::recursive_mutex > lockData(m_thread_control_mutex);
|
||||||
|
|
||||||
|
//now that DemodulatorInstance are managed through shared_ptr, we
|
||||||
|
//should enter here ONLY when it is no longer used by any piece of code, anywhere.
|
||||||
|
//so active wait on IsTerminated(), then die.
|
||||||
|
#define TERMINATION_SPIN_WAIT_MS (20)
|
||||||
|
#define MAX_WAIT_FOR_TERMINATION_MS (3000.0)
|
||||||
|
//this is a stupid busy plus sleep loop
|
||||||
|
int nbCyclesToWait = (MAX_WAIT_FOR_TERMINATION_MS / TERMINATION_SPIN_WAIT_MS) + 1;
|
||||||
|
int currentCycle = 0;
|
||||||
|
|
||||||
|
while (currentCycle < nbCyclesToWait) {
|
||||||
|
|
||||||
|
if (isTerminated()) {
|
||||||
|
std::cout << "Garbage collected demodulator instance '" << getLabel() << "'... " << std::endl << std::flush;
|
||||||
|
|
||||||
#if ENABLE_DIGITAL_LAB
|
#if ENABLE_DIGITAL_LAB
|
||||||
delete activeOutput;
|
delete activeOutput;
|
||||||
#endif
|
#endif
|
||||||
delete audioThread;
|
delete audioThread;
|
||||||
delete demodulatorThread;
|
delete demodulatorThread;
|
||||||
delete demodulatorPreThread;
|
delete demodulatorPreThread;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(TERMINATION_SPIN_WAIT_MS));
|
||||||
|
}
|
||||||
|
currentCycle++;
|
||||||
|
} //end while
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueuePtr tQueue) {
|
void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueuePtr tQueue) {
|
||||||
@ -94,7 +122,7 @@ void DemodulatorInstance::setVisualOutputQueue(DemodulatorThreadOutputQueuePtr t
|
|||||||
|
|
||||||
void DemodulatorInstance::run() {
|
void DemodulatorInstance::run() {
|
||||||
|
|
||||||
std::lock_guard < std::mutex > lockData(m_thread_control_mutex);
|
std::lock_guard < std::recursive_mutex > lockData(m_thread_control_mutex);
|
||||||
|
|
||||||
if (active) {
|
if (active) {
|
||||||
return;
|
return;
|
||||||
@ -163,7 +191,7 @@ void DemodulatorInstance::setLabel(std::string labelStr) {
|
|||||||
|
|
||||||
bool DemodulatorInstance::isTerminated() {
|
bool DemodulatorInstance::isTerminated() {
|
||||||
|
|
||||||
std::lock_guard < std::mutex > lockData(m_thread_control_mutex);
|
std::lock_guard < std::recursive_mutex > lockData(m_thread_control_mutex);
|
||||||
|
|
||||||
bool audioTerminated = audioThread->isTerminated();
|
bool audioTerminated = audioThread->isTerminated();
|
||||||
bool demodTerminated = demodulatorThread->isTerminated();
|
bool demodTerminated = demodulatorThread->isTerminated();
|
||||||
@ -224,7 +252,9 @@ void DemodulatorInstance::setActive(bool state) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
audioThread->setActive(state);
|
audioThread->setActive(state);
|
||||||
|
|
||||||
DemodulatorThread::releaseSquelchLock(this);
|
DemodulatorThread::releaseSquelchLock(this);
|
||||||
|
|
||||||
} else if (!active && state) {
|
} else if (!active && state) {
|
||||||
#if ENABLE_DIGITAL_LAB
|
#if ENABLE_DIGITAL_LAB
|
||||||
if (activeOutput && getModemType() == "digital") {
|
if (activeOutput && getModemType() == "digital") {
|
||||||
@ -404,7 +434,7 @@ void DemodulatorInstance::setFrequency(long long freq) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if USE_HAMLIB
|
#if USE_HAMLIB
|
||||||
if (wxGetApp().rigIsActive() && wxGetApp().getRigThread()->getFollowModem() && wxGetApp().getDemodMgr().getLastActiveDemodulator() == this) {
|
if (wxGetApp().rigIsActive() && wxGetApp().getRigThread()->getFollowModem() && wxGetApp().getDemodMgr().getLastActiveDemodulator().get() == this) {
|
||||||
wxGetApp().getRigThread()->setFrequency(freq,true);
|
wxGetApp().getRigThread()->setFrequency(freq,true);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,12 +6,11 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <memory>
|
||||||
#include "DemodulatorThread.h"
|
#include "DemodDefs.h"
|
||||||
#include "DemodulatorPreThread.h"
|
|
||||||
|
|
||||||
#include "ModemDigital.h"
|
#include "ModemDigital.h"
|
||||||
#include "ModemAnalog.h"
|
#include "ModemAnalog.h"
|
||||||
|
#include "AudioThread.h"
|
||||||
|
|
||||||
#if ENABLE_DIGITAL_LAB
|
#if ENABLE_DIGITAL_LAB
|
||||||
#include "DigitalConsole.h"
|
#include "DigitalConsole.h"
|
||||||
@ -30,6 +29,8 @@ private:
|
|||||||
std::atomic_int squelchBreak;
|
std::atomic_int squelchBreak;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DemodulatorThread;
|
||||||
|
class DemodulatorPreThread;
|
||||||
|
|
||||||
class DemodulatorInstance {
|
class DemodulatorInstance {
|
||||||
public:
|
public:
|
||||||
@ -139,7 +140,7 @@ private:
|
|||||||
DemodulatorThreadControlCommandQueuePtr threadQueueControl;
|
DemodulatorThreadControlCommandQueuePtr threadQueueControl;
|
||||||
|
|
||||||
//protects child thread creation and termination
|
//protects child thread creation and termination
|
||||||
std::mutex m_thread_control_mutex;
|
std::recursive_mutex m_thread_control_mutex;
|
||||||
|
|
||||||
std::atomic<std::string *> label; //
|
std::atomic<std::string *> label; //
|
||||||
// User editable buffer, 16 bit string.
|
// User editable buffer, 16 bit string.
|
||||||
@ -161,3 +162,5 @@ private:
|
|||||||
ModemDigitalOutput *activeOutput;
|
ModemDigitalOutput *activeOutput;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::shared_ptr<DemodulatorInstance> DemodulatorInstancePtr;
|
||||||
|
@ -17,13 +17,11 @@
|
|||||||
|
|
||||||
#include "DataTree.h"
|
#include "DataTree.h"
|
||||||
|
|
||||||
bool demodFreqCompare (DemodulatorInstance *i, DemodulatorInstance *j) { return (i->getFrequency()<j->getFrequency()); }
|
bool demodFreqCompare (DemodulatorInstancePtr i, DemodulatorInstancePtr j) { return (i->getFrequency() < j->getFrequency()); }
|
||||||
bool inactiveCompare (DemodulatorInstance *i, DemodulatorInstance *j) { return (i->isActive()<j->isActive()); }
|
bool inactiveCompare (DemodulatorInstancePtr i, DemodulatorInstancePtr j) { return (i->isActive() < j->isActive()); }
|
||||||
|
|
||||||
DemodulatorMgr::DemodulatorMgr() {
|
DemodulatorMgr::DemodulatorMgr() {
|
||||||
activeDemodulator = NULL;
|
|
||||||
lastActiveDemodulator = NULL;
|
|
||||||
activeVisualDemodulator = NULL;
|
|
||||||
lastBandwidth = DEFAULT_DEMOD_BW;
|
lastBandwidth = DEFAULT_DEMOD_BW;
|
||||||
lastDemodType = DEFAULT_DEMOD_TYPE;
|
lastDemodType = DEFAULT_DEMOD_TYPE;
|
||||||
lastSquelchEnabled = false;
|
lastSquelchEnabled = false;
|
||||||
@ -37,9 +35,11 @@ DemodulatorMgr::~DemodulatorMgr() {
|
|||||||
terminateAll();
|
terminateAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorInstance *DemodulatorMgr::newThread() {
|
DemodulatorInstancePtr DemodulatorMgr::newThread() {
|
||||||
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
||||||
DemodulatorInstance *newDemod = new DemodulatorInstance;
|
|
||||||
|
//create a new instance of DemodulatorInstance here.
|
||||||
|
DemodulatorInstancePtr newDemod = std::make_shared<DemodulatorInstance>();
|
||||||
|
|
||||||
std::stringstream label;
|
std::stringstream label;
|
||||||
label << demods.size();
|
label << demods.size();
|
||||||
@ -51,27 +51,34 @@ DemodulatorInstance *DemodulatorMgr::newThread() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorMgr::terminateAll() {
|
void DemodulatorMgr::terminateAll() {
|
||||||
|
|
||||||
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
||||||
|
|
||||||
while (demods.size()) {
|
while (demods.size()) {
|
||||||
|
|
||||||
DemodulatorInstance *d = demods.back();
|
DemodulatorInstancePtr d = demods.back();
|
||||||
demods.pop_back();
|
demods.pop_back();
|
||||||
wxGetApp().removeDemodulator(d);
|
wxGetApp().removeDemodulator(d);
|
||||||
deleteThread(d);
|
deleteThread(d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<DemodulatorInstance *> &DemodulatorMgr::getDemodulators() {
|
std::vector<DemodulatorInstancePtr> DemodulatorMgr::getDemodulators() {
|
||||||
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
||||||
return demods;
|
return demods;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<DemodulatorInstance *> DemodulatorMgr::getOrderedDemodulators(bool actives) {
|
std::vector<DemodulatorInstancePtr> DemodulatorMgr::getOrderedDemodulators(bool actives) {
|
||||||
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
||||||
std::vector<DemodulatorInstance *> demods_ordered = demods;
|
|
||||||
|
auto demods_ordered = demods;
|
||||||
|
|
||||||
if (actives) {
|
if (actives) {
|
||||||
|
|
||||||
std::sort(demods_ordered.begin(), demods_ordered.end(), inactiveCompare);
|
std::sort(demods_ordered.begin(), demods_ordered.end(), inactiveCompare);
|
||||||
std::vector<DemodulatorInstance *>::iterator i;
|
|
||||||
|
std::vector<DemodulatorInstancePtr>::iterator i;
|
||||||
|
|
||||||
for (i = demods_ordered.begin(); i != demods_ordered.end(); i++) {
|
for (i = demods_ordered.begin(); i != demods_ordered.end(); i++) {
|
||||||
if ((*i)->isActive()) {
|
if ((*i)->isActive()) {
|
||||||
break;
|
break;
|
||||||
@ -88,13 +95,14 @@ std::vector<DemodulatorInstance *> DemodulatorMgr::getOrderedDemodulators(bool a
|
|||||||
return demods_ordered;
|
return demods_ordered;
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorInstance *DemodulatorMgr::getPreviousDemodulator(DemodulatorInstance *demod, bool actives) {
|
DemodulatorInstancePtr DemodulatorMgr::getPreviousDemodulator(DemodulatorInstancePtr demod, bool actives) {
|
||||||
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
||||||
if (!getLastActiveDemodulator()) {
|
if (!getLastActiveDemodulator()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
std::vector<DemodulatorInstance *> demods_ordered = getOrderedDemodulators(actives);
|
auto demods_ordered = getOrderedDemodulators(actives);
|
||||||
std::vector<DemodulatorInstance *>::iterator p = std::find(demods_ordered.begin(), demods_ordered.end(), demod);
|
auto p = std::find(demods_ordered.begin(), demods_ordered.end(), demod);
|
||||||
|
|
||||||
if (p == demods_ordered.end()) {
|
if (p == demods_ordered.end()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -104,13 +112,14 @@ DemodulatorInstance *DemodulatorMgr::getPreviousDemodulator(DemodulatorInstance
|
|||||||
return *(--p);
|
return *(--p);
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorInstance *DemodulatorMgr::getNextDemodulator(DemodulatorInstance *demod, bool actives) {
|
DemodulatorInstancePtr DemodulatorMgr::getNextDemodulator(DemodulatorInstancePtr demod, bool actives) {
|
||||||
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
||||||
if (!getLastActiveDemodulator()) {
|
if (!getLastActiveDemodulator()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
std::vector<DemodulatorInstance *> demods_ordered = getOrderedDemodulators(actives);
|
auto demods_ordered = getOrderedDemodulators(actives);
|
||||||
std::vector<DemodulatorInstance *>::iterator p = std::find(demods_ordered.begin(), demods_ordered.end(), demod);
|
auto p = std::find(demods_ordered.begin(), demods_ordered.end(), demod);
|
||||||
|
|
||||||
if (actives) {
|
if (actives) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -123,26 +132,25 @@ DemodulatorInstance *DemodulatorMgr::getNextDemodulator(DemodulatorInstance *dem
|
|||||||
return *(++p);
|
return *(++p);
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorInstance *DemodulatorMgr::getLastDemodulator() {
|
DemodulatorInstancePtr DemodulatorMgr::getLastDemodulator() {
|
||||||
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
||||||
std::vector<DemodulatorInstance *> demods_ordered = getOrderedDemodulators();
|
|
||||||
return *(demods_ordered.end());
|
return getOrderedDemodulators().back();
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorInstance *DemodulatorMgr::getFirstDemodulator() {
|
DemodulatorInstancePtr DemodulatorMgr::getFirstDemodulator() {
|
||||||
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
||||||
std::vector<DemodulatorInstance *> demods_ordered = getOrderedDemodulators();
|
|
||||||
return *(demods_ordered.begin());
|
return getOrderedDemodulators().front();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorMgr::deleteThread(DemodulatorInstance *demod) {
|
void DemodulatorMgr::deleteThread(DemodulatorInstancePtr demod) {
|
||||||
|
|
||||||
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
||||||
|
|
||||||
wxGetApp().getBookmarkMgr().addRecent(demod);
|
wxGetApp().getBookmarkMgr().addRecent(demod);
|
||||||
|
|
||||||
std::vector<DemodulatorInstance *>::iterator i;
|
auto i = std::find(demods.begin(), demods.end(), demod);
|
||||||
|
|
||||||
i = std::find(demods.begin(), demods.end(), demod);
|
|
||||||
|
|
||||||
if (activeDemodulator == demod) {
|
if (activeDemodulator == demod) {
|
||||||
activeDemodulator = nullptr;
|
activeDemodulator = nullptr;
|
||||||
@ -161,19 +169,15 @@ void DemodulatorMgr::deleteThread(DemodulatorInstance *demod) {
|
|||||||
//Ask for termination
|
//Ask for termination
|
||||||
demod->setActive(false);
|
demod->setActive(false);
|
||||||
demod->terminate();
|
demod->terminate();
|
||||||
|
|
||||||
//Do not cleanup immediatly
|
|
||||||
std::lock_guard < std::mutex > lock_deleted(deleted_demods_busy);
|
|
||||||
demods_deleted.push_back(demod);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<DemodulatorInstance *> DemodulatorMgr::getDemodulatorsAt(long long freq, int bandwidth) {
|
std::vector<DemodulatorInstancePtr> DemodulatorMgr::getDemodulatorsAt(long long freq, int bandwidth) {
|
||||||
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
||||||
|
|
||||||
std::vector<DemodulatorInstance *> foundDemods;
|
std::vector<DemodulatorInstancePtr> foundDemods;
|
||||||
|
|
||||||
for (int i = 0, iMax = demods.size(); i < iMax; i++) {
|
for (int i = 0, iMax = demods.size(); i < iMax; i++) {
|
||||||
DemodulatorInstance *testDemod = demods[i];
|
DemodulatorInstancePtr testDemod = demods[i];
|
||||||
|
|
||||||
long long freqTest = testDemod->getFrequency();
|
long long freqTest = testDemod->getFrequency();
|
||||||
long long bandwidthTest = testDemod->getBandwidth();
|
long long bandwidthTest = testDemod->getBandwidth();
|
||||||
@ -192,7 +196,7 @@ std::vector<DemodulatorInstance *> DemodulatorMgr::getDemodulatorsAt(long long f
|
|||||||
bool DemodulatorMgr::anyDemodulatorsAt(long long freq, int bandwidth) {
|
bool DemodulatorMgr::anyDemodulatorsAt(long long freq, int bandwidth) {
|
||||||
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
||||||
for (int i = 0, iMax = demods.size(); i < iMax; i++) {
|
for (int i = 0, iMax = demods.size(); i < iMax; i++) {
|
||||||
DemodulatorInstance *testDemod = demods[i];
|
DemodulatorInstancePtr testDemod = demods[i];
|
||||||
|
|
||||||
long long freqTest = testDemod->getFrequency();
|
long long freqTest = testDemod->getFrequency();
|
||||||
long long bandwidthTest = testDemod->getBandwidth();
|
long long bandwidthTest = testDemod->getBandwidth();
|
||||||
@ -210,32 +214,34 @@ bool DemodulatorMgr::anyDemodulatorsAt(long long freq, int bandwidth) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DemodulatorMgr::setActiveDemodulator(DemodulatorInstance *demod, bool temporary) {
|
void DemodulatorMgr::setActiveDemodulator(DemodulatorInstancePtr demod, bool temporary) {
|
||||||
|
|
||||||
|
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
||||||
|
|
||||||
if (!temporary) {
|
if (!temporary) {
|
||||||
if (activeDemodulator.load() != nullptr) {
|
if (activeDemodulator != nullptr) {
|
||||||
lastActiveDemodulator = activeDemodulator.load();
|
lastActiveDemodulator = activeDemodulator;
|
||||||
updateLastState();
|
updateLastState();
|
||||||
} else {
|
} else {
|
||||||
lastActiveDemodulator = demod;
|
lastActiveDemodulator = demod;
|
||||||
}
|
}
|
||||||
updateLastState();
|
updateLastState();
|
||||||
#if USE_HAMLIB
|
#if USE_HAMLIB
|
||||||
if (wxGetApp().rigIsActive() && wxGetApp().getRigThread()->getFollowModem() && lastActiveDemodulator.load()) {
|
if (wxGetApp().rigIsActive() && wxGetApp().getRigThread()->getFollowModem() && lastActiveDemodulator) {
|
||||||
wxGetApp().getRigThread()->setFrequency(lastActiveDemodulator.load()->getFrequency(),true);
|
wxGetApp().getRigThread()->setFrequency(lastActiveDemodulator->getFrequency(),true);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
wxGetApp().getBookmarkMgr().updateActiveList();
|
wxGetApp().getBookmarkMgr().updateActiveList();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (activeVisualDemodulator.load()) {
|
if (activeVisualDemodulator) {
|
||||||
activeVisualDemodulator.load()->setVisualOutputQueue(nullptr);
|
activeVisualDemodulator->setVisualOutputQueue(nullptr);
|
||||||
}
|
}
|
||||||
if (demod) {
|
if (demod) {
|
||||||
demod->setVisualOutputQueue(wxGetApp().getAudioVisualQueue());
|
demod->setVisualOutputQueue(wxGetApp().getAudioVisualQueue());
|
||||||
activeVisualDemodulator = demod;
|
activeVisualDemodulator = demod;
|
||||||
} else {
|
} else {
|
||||||
DemodulatorInstance *last = getLastActiveDemodulator();
|
DemodulatorInstancePtr last = getLastActiveDemodulator();
|
||||||
if (last) {
|
if (last) {
|
||||||
last->setVisualOutputQueue(wxGetApp().getAudioVisualQueue());
|
last->setVisualOutputQueue(wxGetApp().getAudioVisualQueue());
|
||||||
}
|
}
|
||||||
@ -246,25 +252,41 @@ void DemodulatorMgr::setActiveDemodulator(DemodulatorInstance *demod, bool tempo
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorInstance *DemodulatorMgr::getActiveDemodulator() {
|
//Dangerous: this is only intended by some internal classes
|
||||||
if (activeDemodulator.load() && !activeDemodulator.load()->isActive()) {
|
void DemodulatorMgr::setActiveDemodulatorByRawPointer(DemodulatorInstance* demod, bool temporary) {
|
||||||
|
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
||||||
|
|
||||||
|
for (auto existing_demod : demods) {
|
||||||
|
|
||||||
|
if (existing_demod.get() == demod) {
|
||||||
|
|
||||||
|
setActiveDemodulator(existing_demod, temporary);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DemodulatorInstancePtr DemodulatorMgr::getActiveDemodulator() {
|
||||||
|
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
||||||
|
|
||||||
|
if (activeDemodulator && !activeDemodulator->isActive()) {
|
||||||
activeDemodulator = getLastActiveDemodulator();
|
activeDemodulator = getLastActiveDemodulator();
|
||||||
}
|
}
|
||||||
return activeDemodulator;
|
return activeDemodulator;
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorInstance *DemodulatorMgr::getLastActiveDemodulator() {
|
DemodulatorInstancePtr DemodulatorMgr::getLastActiveDemodulator() {
|
||||||
return lastActiveDemodulator;
|
return lastActiveDemodulator;
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorInstance *DemodulatorMgr::getLastDemodulatorWith(const std::string& type,
|
DemodulatorInstancePtr DemodulatorMgr::getLastDemodulatorWith(const std::string& type,
|
||||||
const std::wstring& userLabel,
|
const std::wstring& userLabel,
|
||||||
long long frequency,
|
long long frequency,
|
||||||
int bandwidth) {
|
int bandwidth) {
|
||||||
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
||||||
|
|
||||||
//backwards search:
|
//backwards search:
|
||||||
for (std::vector<DemodulatorInstance *>::reverse_iterator it = demods.rbegin(); it != demods.rend(); it++) {
|
for (auto it = demods.rbegin(); it != demods.rend(); it++) {
|
||||||
|
|
||||||
if ((*it)->getDemodulatorType() == type &&
|
if ((*it)->getDemodulatorType() == type &&
|
||||||
(*it)->getDemodulatorUserLabel() == userLabel &&
|
(*it)->getDemodulatorUserLabel() == userLabel &&
|
||||||
@ -278,86 +300,31 @@ DemodulatorInstance *DemodulatorMgr::getLastDemodulatorWith(const std::string& t
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DemodulatorMgr::garbageCollect(bool forcedGC, int maxWaitForTerminationMs) {
|
|
||||||
|
|
||||||
#define SPIN_WAIT_SLEEP_MS 5
|
|
||||||
|
|
||||||
//this is a stupid busy plus sleep loop
|
|
||||||
int nbCyclesToWait = 0;
|
|
||||||
|
|
||||||
if (maxWaitForTerminationMs <= 0) {
|
|
||||||
nbCyclesToWait = std::numeric_limits<int>::max();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
nbCyclesToWait = (maxWaitForTerminationMs / SPIN_WAIT_SLEEP_MS) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int currentWaitCycle = 0;
|
|
||||||
|
|
||||||
std::lock_guard < std::mutex > lock(deleted_demods_busy);
|
|
||||||
|
|
||||||
while (!demods_deleted.empty()) {
|
|
||||||
|
|
||||||
std::vector<DemodulatorInstance *>::iterator it = demods_deleted.begin();
|
|
||||||
//make 1 pass over
|
|
||||||
while (it != demods_deleted.end()) {
|
|
||||||
|
|
||||||
if ((*it)->isTerminated()) {
|
|
||||||
|
|
||||||
DemodulatorInstance *deleted = (*it);
|
|
||||||
|
|
||||||
std::cout << "Garbage collected demodulator instance '" << deleted->getLabel() << "'... " << std::endl << std::flush;
|
|
||||||
it = demods_deleted.erase(it);
|
|
||||||
delete deleted;
|
|
||||||
|
|
||||||
//only garbage collect 1 demod at a time.
|
|
||||||
if (!forcedGC) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
it++;
|
|
||||||
}
|
|
||||||
} //end while
|
|
||||||
//stupid busy-wait loop
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(SPIN_WAIT_SLEEP_MS));
|
|
||||||
|
|
||||||
currentWaitCycle++;
|
|
||||||
|
|
||||||
if (currentWaitCycle >= nbCyclesToWait) {
|
|
||||||
std::cout << "ERROR: DemodulatorMgr::garbageCollect() has not terminated in time ! (> " << (currentWaitCycle * SPIN_WAIT_SLEEP_MS) << " ms)" << std::endl << std::flush;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} //end while not empty
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemodulatorMgr::updateLastState() {
|
void DemodulatorMgr::updateLastState() {
|
||||||
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
||||||
|
|
||||||
if (std::find(demods.begin(), demods.end(), lastActiveDemodulator) == demods.end()) {
|
if (std::find(demods.begin(), demods.end(), lastActiveDemodulator) == demods.end()) {
|
||||||
if (activeDemodulator.load() && activeDemodulator.load()->isActive()) {
|
if (activeDemodulator && activeDemodulator->isActive()) {
|
||||||
lastActiveDemodulator = activeDemodulator.load();
|
lastActiveDemodulator = activeDemodulator;
|
||||||
} else if (activeDemodulator.load() && !activeDemodulator.load()->isActive()){
|
} else if (activeDemodulator && !activeDemodulator->isActive()){
|
||||||
activeDemodulator = nullptr;
|
activeDemodulator = nullptr;
|
||||||
lastActiveDemodulator = nullptr;
|
lastActiveDemodulator = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastActiveDemodulator.load() && !lastActiveDemodulator.load()->isActive()) {
|
if (lastActiveDemodulator && !lastActiveDemodulator->isActive()) {
|
||||||
lastActiveDemodulator = nullptr;
|
lastActiveDemodulator = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastActiveDemodulator.load()) {
|
if (lastActiveDemodulator) {
|
||||||
lastBandwidth = lastActiveDemodulator.load()->getBandwidth();
|
lastBandwidth = lastActiveDemodulator->getBandwidth();
|
||||||
lastDemodType = lastActiveDemodulator.load()->getDemodulatorType();
|
lastDemodType = lastActiveDemodulator->getDemodulatorType();
|
||||||
lastDemodLock = lastActiveDemodulator.load()->getDemodulatorLock()?true:false;
|
lastDemodLock = lastActiveDemodulator->getDemodulatorLock()?true:false;
|
||||||
lastSquelchEnabled = lastActiveDemodulator.load()->isSquelchEnabled();
|
lastSquelchEnabled = lastActiveDemodulator->isSquelchEnabled();
|
||||||
lastSquelch = lastActiveDemodulator.load()->getSquelchLevel();
|
lastSquelch = lastActiveDemodulator->getSquelchLevel();
|
||||||
lastGain = lastActiveDemodulator.load()->getGain();
|
lastGain = lastActiveDemodulator->getGain();
|
||||||
lastModemSettings[lastDemodType] = lastActiveDemodulator.load()->readModemSettings();
|
lastModemSettings[lastDemodType] = lastActiveDemodulator->readModemSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -436,7 +403,8 @@ void DemodulatorMgr::setOutputDevices(std::map<int,RtAudio::DeviceInfo> devs) {
|
|||||||
outputDevices = devs;
|
outputDevices = devs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorMgr::saveInstance(DataNode *node, DemodulatorInstance *inst) {
|
void DemodulatorMgr::saveInstance(DataNode *node, DemodulatorInstancePtr inst) {
|
||||||
|
|
||||||
*node->newChild("bandwidth") = inst->getBandwidth();
|
*node->newChild("bandwidth") = inst->getBandwidth();
|
||||||
*node->newChild("frequency") = inst->getFrequency();
|
*node->newChild("frequency") = inst->getFrequency();
|
||||||
*node->newChild("type") = inst->getDemodulatorType();
|
*node->newChild("type") = inst->getDemodulatorType();
|
||||||
@ -465,11 +433,11 @@ void DemodulatorMgr::saveInstance(DataNode *node, DemodulatorInstance *inst) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorInstance *DemodulatorMgr::loadInstance(DataNode *node) {
|
DemodulatorInstancePtr DemodulatorMgr::loadInstance(DataNode *node) {
|
||||||
|
|
||||||
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
std::lock_guard < std::recursive_mutex > lock(demods_busy);
|
||||||
|
|
||||||
DemodulatorInstance *newDemod = nullptr;
|
DemodulatorInstancePtr newDemod = nullptr;
|
||||||
|
|
||||||
node->rewindAll();
|
node->rewindAll();
|
||||||
|
|
||||||
|
@ -16,23 +16,32 @@ public:
|
|||||||
DemodulatorMgr();
|
DemodulatorMgr();
|
||||||
~DemodulatorMgr();
|
~DemodulatorMgr();
|
||||||
|
|
||||||
DemodulatorInstance *newThread();
|
DemodulatorInstancePtr newThread();
|
||||||
std::vector<DemodulatorInstance *> &getDemodulators();
|
|
||||||
std::vector<DemodulatorInstance *> getOrderedDemodulators(bool actives = true);
|
//return snapshot-copy of the list purposefully
|
||||||
std::vector<DemodulatorInstance *> getDemodulatorsAt(long long freq, int bandwidth);
|
std::vector<DemodulatorInstancePtr> getDemodulators();
|
||||||
DemodulatorInstance *getPreviousDemodulator(DemodulatorInstance *demod, bool actives = true);
|
|
||||||
DemodulatorInstance *getNextDemodulator(DemodulatorInstance *demod, bool actives = true);
|
std::vector<DemodulatorInstancePtr> getOrderedDemodulators(bool actives = true);
|
||||||
DemodulatorInstance *getLastDemodulator();
|
std::vector<DemodulatorInstancePtr> getDemodulatorsAt(long long freq, int bandwidth);
|
||||||
DemodulatorInstance *getFirstDemodulator();
|
|
||||||
|
DemodulatorInstancePtr getPreviousDemodulator(DemodulatorInstancePtr demod, bool actives = true);
|
||||||
|
DemodulatorInstancePtr getNextDemodulator(DemodulatorInstancePtr demod, bool actives = true);
|
||||||
|
DemodulatorInstancePtr getLastDemodulator();
|
||||||
|
DemodulatorInstancePtr getFirstDemodulator();
|
||||||
bool anyDemodulatorsAt(long long freq, int bandwidth);
|
bool anyDemodulatorsAt(long long freq, int bandwidth);
|
||||||
void deleteThread(DemodulatorInstance *);
|
void deleteThread(DemodulatorInstancePtr);
|
||||||
|
|
||||||
void terminateAll();
|
void terminateAll();
|
||||||
|
|
||||||
void setActiveDemodulator(DemodulatorInstance *demod, bool temporary = true);
|
void setActiveDemodulator(DemodulatorInstancePtr demod, bool temporary = true);
|
||||||
DemodulatorInstance *getActiveDemodulator();
|
|
||||||
DemodulatorInstance *getLastActiveDemodulator();
|
//Dangerous: this is only intended by some internal classes,
|
||||||
DemodulatorInstance *getLastDemodulatorWith(const std::string& type,
|
// and only set a pre-existing demod
|
||||||
|
void setActiveDemodulatorByRawPointer(DemodulatorInstance* demod, bool temporary = true);
|
||||||
|
|
||||||
|
DemodulatorInstancePtr getActiveDemodulator();
|
||||||
|
DemodulatorInstancePtr getLastActiveDemodulator();
|
||||||
|
DemodulatorInstancePtr getLastDemodulatorWith(const std::string& type,
|
||||||
const std::wstring& userLabel,
|
const std::wstring& userLabel,
|
||||||
long long frequency,
|
long long frequency,
|
||||||
int bandwidth);
|
int bandwidth);
|
||||||
@ -64,28 +73,17 @@ public:
|
|||||||
void updateLastState();
|
void updateLastState();
|
||||||
|
|
||||||
void setOutputDevices(std::map<int,RtAudio::DeviceInfo> devs);
|
void setOutputDevices(std::map<int,RtAudio::DeviceInfo> devs);
|
||||||
void saveInstance(DataNode *node, DemodulatorInstance *inst);
|
void saveInstance(DataNode *node, DemodulatorInstancePtr inst);
|
||||||
|
|
||||||
DemodulatorInstance *loadInstance(DataNode *node);
|
DemodulatorInstancePtr loadInstance(DataNode *node);
|
||||||
|
|
||||||
//to be called periodically to cleanup removed demodulators.
|
|
||||||
//if forcedGC = true, the methods waits until
|
|
||||||
//all deleted demodulators are effectively GCed.
|
|
||||||
//else: (default) the method test for effective termination
|
|
||||||
//and GC one demod per call.
|
|
||||||
// if forcedGC = true and maxWaitForTerminationMs > 0, do not
|
|
||||||
//block the method more than maxWaitForTerminationMs millisecs before returning.
|
|
||||||
//Returns: true if forcedGC = false, else true only if all deleted demodulators were GCs before maxWaitForTerminationMs.
|
|
||||||
bool garbageCollect(bool forcedGC = false, int maxWaitForTerminationMs = 0);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::vector<DemodulatorInstance *> demods;
|
std::vector<DemodulatorInstancePtr> demods;
|
||||||
std::vector<DemodulatorInstance *> demods_deleted;
|
|
||||||
|
|
||||||
std::atomic<DemodulatorInstance *> activeDemodulator;
|
DemodulatorInstancePtr activeDemodulator;
|
||||||
std::atomic<DemodulatorInstance *> lastActiveDemodulator;
|
DemodulatorInstancePtr lastActiveDemodulator;
|
||||||
std::atomic<DemodulatorInstance *> activeVisualDemodulator;
|
DemodulatorInstancePtr activeVisualDemodulator;
|
||||||
|
|
||||||
int lastBandwidth;
|
int lastBandwidth;
|
||||||
std::string lastDemodType;
|
std::string lastDemodType;
|
||||||
@ -99,9 +97,7 @@ private:
|
|||||||
//protects access to demods lists and such, need to be recursive
|
//protects access to demods lists and such, need to be recursive
|
||||||
//because of the usage of public re-entrant methods
|
//because of the usage of public re-entrant methods
|
||||||
std::recursive_mutex demods_busy;
|
std::recursive_mutex demods_busy;
|
||||||
|
|
||||||
std::mutex deleted_demods_busy;
|
|
||||||
|
|
||||||
std::map<std::string, ModemSettings> lastModemSettings;
|
std::map<std::string, ModemSettings> lastModemSettings;
|
||||||
std::map<int,RtAudio::DeviceInfo> outputDevices;
|
std::map<int,RtAudio::DeviceInfo> outputDevices;
|
||||||
};
|
};
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
//50 ms
|
//50 ms
|
||||||
#define HEARTBEAT_CHECK_PERIOD_MICROS (50 * 1000)
|
#define HEARTBEAT_CHECK_PERIOD_MICROS (50 * 1000)
|
||||||
|
|
||||||
DemodulatorPreThread::DemodulatorPreThread(DemodulatorInstance *parent) : IOThread(), iqResampler(NULL), iqResampleRatio(1), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), iqOutputQueue(NULL)
|
DemodulatorPreThread::DemodulatorPreThread(DemodulatorInstance* parent) : IOThread(), iqResampler(NULL), iqResampleRatio(1), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), iqOutputQueue(NULL)
|
||||||
{
|
{
|
||||||
initialized.store(false);
|
initialized.store(false);
|
||||||
this->parent = parent;
|
this->parent = parent;
|
||||||
|
@ -17,7 +17,7 @@ class DemodulatorInstance;
|
|||||||
class DemodulatorPreThread : public IOThread {
|
class DemodulatorPreThread : public IOThread {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DemodulatorPreThread(DemodulatorInstance *parent);
|
DemodulatorPreThread(DemodulatorInstance* parent);
|
||||||
virtual ~DemodulatorPreThread();
|
virtual ~DemodulatorPreThread();
|
||||||
|
|
||||||
virtual void run();
|
virtual void run();
|
||||||
@ -50,7 +50,9 @@ public:
|
|||||||
void writeModemSettings(ModemSettings settings);
|
void writeModemSettings(ModemSettings settings);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DemodulatorInstance *parent;
|
|
||||||
|
DemodulatorInstance* parent;
|
||||||
|
|
||||||
msresamp_crcf iqResampler;
|
msresamp_crcf iqResampler;
|
||||||
double iqResampleRatio;
|
double iqResampleRatio;
|
||||||
std::vector<liquid_float_complex> resampledData;
|
std::vector<liquid_float_complex> resampledData;
|
||||||
|
@ -19,10 +19,10 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::atomic<DemodulatorInstance *> DemodulatorThread::squelchLock(nullptr);
|
DemodulatorInstance* DemodulatorThread::squelchLock(nullptr);
|
||||||
std::mutex DemodulatorThread::squelchLockMutex;
|
std::mutex DemodulatorThread::squelchLockMutex;
|
||||||
|
|
||||||
DemodulatorThread::DemodulatorThread(DemodulatorInstance *parent)
|
DemodulatorThread::DemodulatorThread(DemodulatorInstance* parent)
|
||||||
: IOThread(), outputBuffers("DemodulatorThreadBuffers"), squelchLevel(-100),
|
: IOThread(), outputBuffers("DemodulatorThreadBuffers"), squelchLevel(-100),
|
||||||
signalLevel(-100), signalFloor(-30), signalCeil(30), squelchEnabled(false) {
|
signalLevel(-100), signalFloor(-30), signalCeil(30), squelchEnabled(false) {
|
||||||
|
|
||||||
@ -201,10 +201,10 @@ void DemodulatorThread::run() {
|
|||||||
if (!squelched && !squelchBreak) {
|
if (!squelched && !squelchBreak) {
|
||||||
if (wxGetApp().getSoloMode() && !wxGetApp().getAppFrame()->isUserDemodBusy()) {
|
if (wxGetApp().getSoloMode() && !wxGetApp().getAppFrame()->isUserDemodBusy()) {
|
||||||
std::lock_guard < std::mutex > lock(squelchLockMutex);
|
std::lock_guard < std::mutex > lock(squelchLockMutex);
|
||||||
if (squelchLock.load() == nullptr) {
|
if (squelchLock == nullptr) {
|
||||||
squelchLock.store(demodInstance);
|
squelchLock = demodInstance;
|
||||||
wxGetApp().getDemodMgr().setActiveDemodulator(nullptr);
|
wxGetApp().getDemodMgr().setActiveDemodulator(nullptr);
|
||||||
wxGetApp().getDemodMgr().setActiveDemodulator(demodInstance, false);
|
wxGetApp().getDemodMgr().setActiveDemodulatorByRawPointer(demodInstance, false);
|
||||||
squelchBreak = true;
|
squelchBreak = true;
|
||||||
demodInstance->getVisualCue()->triggerSquelchBreak(120);
|
demodInstance->getVisualCue()->triggerSquelchBreak(120);
|
||||||
}
|
}
|
||||||
@ -310,7 +310,7 @@ void DemodulatorThread::run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ati != nullptr) {
|
if (ati != nullptr) {
|
||||||
if (!muted.load() && (!wxGetApp().getSoloMode() || (demodInstance == wxGetApp().getDemodMgr().getLastActiveDemodulator()))) {
|
if (!muted.load() && (!wxGetApp().getSoloMode() || (demodInstance == wxGetApp().getDemodMgr().getLastActiveDemodulator().get()))) {
|
||||||
//non-blocking push needed for audio out
|
//non-blocking push needed for audio out
|
||||||
if (!audioOutputQueue->try_push(ati)) {
|
if (!audioOutputQueue->try_push(ati)) {
|
||||||
|
|
||||||
@ -385,9 +385,11 @@ bool DemodulatorThread::getSquelchBreak() {
|
|||||||
return squelchBreak;
|
return squelchBreak;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorThread::releaseSquelchLock(DemodulatorInstance *inst) {
|
void DemodulatorThread::releaseSquelchLock(DemodulatorInstance* inst) {
|
||||||
|
|
||||||
std::lock_guard < std::mutex > lock(squelchLockMutex);
|
std::lock_guard < std::mutex > lock(squelchLockMutex);
|
||||||
if (inst == nullptr || squelchLock.load() == inst) {
|
|
||||||
squelchLock.store(nullptr);
|
if (inst == nullptr || squelchLock == inst) {
|
||||||
|
squelchLock = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,10 +11,6 @@
|
|||||||
#include "AudioThread.h"
|
#include "AudioThread.h"
|
||||||
#include "Modem.h"
|
#include "Modem.h"
|
||||||
|
|
||||||
typedef ThreadBlockingQueue<AudioThreadInputPtr> DemodulatorThreadOutputQueue;
|
|
||||||
|
|
||||||
typedef std::shared_ptr<DemodulatorThreadOutputQueue> DemodulatorThreadOutputQueuePtr;
|
|
||||||
|
|
||||||
#define DEMOD_VIS_SIZE 2048
|
#define DEMOD_VIS_SIZE 2048
|
||||||
#define DEMOD_SIGNAL_MIN -30
|
#define DEMOD_SIGNAL_MIN -30
|
||||||
#define DEMOD_SIGNAL_MAX 30
|
#define DEMOD_SIGNAL_MAX 30
|
||||||
@ -24,7 +20,7 @@ class DemodulatorInstance;
|
|||||||
class DemodulatorThread : public IOThread {
|
class DemodulatorThread : public IOThread {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DemodulatorThread(DemodulatorInstance *parent);
|
DemodulatorThread(DemodulatorInstance* parent);
|
||||||
virtual ~DemodulatorThread();
|
virtual ~DemodulatorThread();
|
||||||
|
|
||||||
void onBindOutput(std::string name, ThreadQueueBasePtr threadQueue);
|
void onBindOutput(std::string name, ThreadQueueBasePtr threadQueue);
|
||||||
@ -43,13 +39,14 @@ public:
|
|||||||
|
|
||||||
bool getSquelchBreak();
|
bool getSquelchBreak();
|
||||||
|
|
||||||
static void releaseSquelchLock(DemodulatorInstance *inst);
|
|
||||||
|
static void releaseSquelchLock(DemodulatorInstance* inst);
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
double abMagnitude(float inphase, float quadrature);
|
double abMagnitude(float inphase, float quadrature);
|
||||||
double linearToDb(double linear);
|
double linearToDb(double linear);
|
||||||
|
|
||||||
DemodulatorInstance *demodInstance = nullptr;
|
DemodulatorInstance* demodInstance;
|
||||||
ReBuffer<AudioThreadInput> outputBuffers;
|
ReBuffer<AudioThreadInput> outputBuffers;
|
||||||
|
|
||||||
std::atomic_bool muted;
|
std::atomic_bool muted;
|
||||||
@ -58,7 +55,7 @@ protected:
|
|||||||
std::atomic<float> signalLevel, signalFloor, signalCeil;
|
std::atomic<float> signalLevel, signalFloor, signalCeil;
|
||||||
bool squelchEnabled, squelchBreak;
|
bool squelchEnabled, squelchBreak;
|
||||||
|
|
||||||
static std::atomic<DemodulatorInstance *> squelchLock;
|
static DemodulatorInstance* squelchLock;
|
||||||
static std::mutex squelchLockMutex;
|
static std::mutex squelchLockMutex;
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,9 +9,6 @@
|
|||||||
//50 ms
|
//50 ms
|
||||||
#define HEARTBEAT_CHECK_PERIOD_MICROS (50 * 1000)
|
#define HEARTBEAT_CHECK_PERIOD_MICROS (50 * 1000)
|
||||||
|
|
||||||
//1s
|
|
||||||
#define MAX_BLOCKING_DURATION_MICROS (1000 * 1000)
|
|
||||||
|
|
||||||
DemodulatorWorkerThread::DemodulatorWorkerThread() : IOThread(),
|
DemodulatorWorkerThread::DemodulatorWorkerThread() : IOThread(),
|
||||||
commandQueue(nullptr), resultQueue(nullptr), cModem(nullptr), cModemKit(nullptr) {
|
commandQueue(nullptr), resultQueue(nullptr), cModem(nullptr), cModemKit(nullptr) {
|
||||||
}
|
}
|
||||||
@ -111,7 +108,7 @@ void DemodulatorWorkerThread::run() {
|
|||||||
result.modemName = cModemName;
|
result.modemName = cModemName;
|
||||||
|
|
||||||
//VSO: blocking push
|
//VSO: blocking push
|
||||||
resultQueue->push(result, MAX_BLOCKING_DURATION_MICROS, "resultQueue");
|
resultQueue->push(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// std::cout << "Demodulator worker thread done." << std::endl;
|
// std::cout << "Demodulator worker thread done." << std::endl;
|
||||||
|
@ -348,10 +348,9 @@ wxTreeItemId BookmarkView::refreshBookmarks() {
|
|||||||
|
|
||||||
|
|
||||||
void BookmarkView::doUpdateActiveList() {
|
void BookmarkView::doUpdateActiveList() {
|
||||||
std::vector<DemodulatorInstance *> &demods = wxGetApp().getDemodMgr().getDemodulators();
|
|
||||||
|
auto demods = wxGetApp().getDemodMgr().getDemodulators();
|
||||||
// DemodulatorInstance *activeDemodulator = wxGetApp().getDemodMgr().getActiveDemodulator();
|
auto lastActiveDemodulator = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
||||||
DemodulatorInstance *lastActiveDemodulator = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
|
||||||
|
|
||||||
//capture the previously selected item info BY COPY (because the original will be destroyed together with the destroyed tree items) to restore it again after
|
//capture the previously selected item info BY COPY (because the original will be destroyed together with the destroyed tree items) to restore it again after
|
||||||
//having rebuilding the whole tree.
|
//having rebuilding the whole tree.
|
||||||
@ -693,7 +692,8 @@ wxButton *BookmarkView::addButton(wxWindow *parent, std::string labelVal, wxObje
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BookmarkView::doBookmarkActive(std::string group, DemodulatorInstance *demod) {
|
void BookmarkView::doBookmarkActive(std::string group, DemodulatorInstancePtr demod) {
|
||||||
|
|
||||||
wxGetApp().getBookmarkMgr().addBookmark(group, demod);
|
wxGetApp().getBookmarkMgr().addBookmark(group, demod);
|
||||||
wxGetApp().getBookmarkMgr().updateBookmarks();
|
wxGetApp().getBookmarkMgr().updateBookmarks();
|
||||||
}
|
}
|
||||||
@ -717,7 +717,7 @@ void BookmarkView::doMoveBookmark(BookmarkEntryPtr be, std::string group) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BookmarkView::doRemoveActive(DemodulatorInstance *demod) {
|
void BookmarkView::doRemoveActive(DemodulatorInstancePtr demod) {
|
||||||
|
|
||||||
wxGetApp().getBookmarkMgr().removeActive(demod);
|
wxGetApp().getBookmarkMgr().removeActive(demod);
|
||||||
wxGetApp().getBookmarkMgr().updateActiveList();
|
wxGetApp().getBookmarkMgr().updateActiveList();
|
||||||
@ -792,7 +792,7 @@ void BookmarkView::onBookmarkChoice( wxCommandEvent & /* event */ ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BookmarkView::activeSelection(DemodulatorInstance *dsel) {
|
void BookmarkView::activeSelection(DemodulatorInstancePtr dsel) {
|
||||||
|
|
||||||
m_frequencyVal->SetLabelText(frequencyToStr(dsel->getFrequency()));
|
m_frequencyVal->SetLabelText(frequencyToStr(dsel->getFrequency()));
|
||||||
m_bandwidthVal->SetLabelText(frequencyToStr(dsel->getBandwidth()));
|
m_bandwidthVal->SetLabelText(frequencyToStr(dsel->getBandwidth()));
|
||||||
@ -835,7 +835,7 @@ void BookmarkView::activateBookmark(BookmarkEntryPtr bmEnt) {
|
|||||||
//the already existing one:
|
//the already existing one:
|
||||||
// we search among the list of existing demodulators the one matching
|
// we search among the list of existing demodulators the one matching
|
||||||
//bmEnt and activate it. The search is made backwards, to select the most recently created one.
|
//bmEnt and activate it. The search is made backwards, to select the most recently created one.
|
||||||
DemodulatorInstance *matchingDemod = wxGetApp().getDemodMgr().getLastDemodulatorWith(
|
DemodulatorInstancePtr matchingDemod = wxGetApp().getDemodMgr().getLastDemodulatorWith(
|
||||||
bmEnt->type,
|
bmEnt->type,
|
||||||
bmEnt->label,
|
bmEnt->label,
|
||||||
bmEnt->frequency,
|
bmEnt->frequency,
|
||||||
@ -845,7 +845,7 @@ void BookmarkView::activateBookmark(BookmarkEntryPtr bmEnt) {
|
|||||||
|
|
||||||
matchingDemod = wxGetApp().getDemodMgr().loadInstance(bmEnt->node);
|
matchingDemod = wxGetApp().getDemodMgr().loadInstance(bmEnt->node);
|
||||||
matchingDemod->run();
|
matchingDemod->run();
|
||||||
wxGetApp().bindDemodulator(matchingDemod);
|
wxGetApp().notifyDemodulatorsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
matchingDemod->setActive(true);
|
matchingDemod->setActive(true);
|
||||||
|
@ -43,7 +43,7 @@ public:
|
|||||||
BookmarkEntryPtr bookmarkEnt;
|
BookmarkEntryPtr bookmarkEnt;
|
||||||
BookmarkRangeEntryPtr rangeEnt;
|
BookmarkRangeEntryPtr rangeEnt;
|
||||||
|
|
||||||
DemodulatorInstance* demod;
|
DemodulatorInstancePtr demod;
|
||||||
std::string groupName;
|
std::string groupName;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ public:
|
|||||||
static BookmarkRangeEntryPtr makeActiveRangeEntry();
|
static BookmarkRangeEntryPtr makeActiveRangeEntry();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void activeSelection(DemodulatorInstance *dsel);
|
void activeSelection(DemodulatorInstancePtr dsel);
|
||||||
void bookmarkSelection(BookmarkEntryPtr bmSel);
|
void bookmarkSelection(BookmarkEntryPtr bmSel);
|
||||||
void rangeSelection(BookmarkRangeEntryPtr re);
|
void rangeSelection(BookmarkRangeEntryPtr re);
|
||||||
|
|
||||||
@ -133,10 +133,10 @@ protected:
|
|||||||
wxButton *makeButton(wxWindow *parent, std::string labelVal, wxObjectEventFunction handler);
|
wxButton *makeButton(wxWindow *parent, std::string labelVal, wxObjectEventFunction handler);
|
||||||
wxButton *addButton(wxWindow *parent, std::string labelVal, wxObjectEventFunction handler);
|
wxButton *addButton(wxWindow *parent, std::string labelVal, wxObjectEventFunction handler);
|
||||||
|
|
||||||
void doBookmarkActive(std::string group, DemodulatorInstance *demod);
|
void doBookmarkActive(std::string group, DemodulatorInstancePtr demod);
|
||||||
void doBookmarkRecent(std::string group, BookmarkEntryPtr be);
|
void doBookmarkRecent(std::string group, BookmarkEntryPtr be);
|
||||||
void doMoveBookmark(BookmarkEntryPtr be, std::string group);
|
void doMoveBookmark(BookmarkEntryPtr be, std::string group);
|
||||||
void doRemoveActive(DemodulatorInstance *demod);
|
void doRemoveActive(DemodulatorInstancePtr demod);
|
||||||
void doRemoveRecent(BookmarkEntryPtr be);
|
void doRemoveRecent(BookmarkEntryPtr be);
|
||||||
void doClearRecents();
|
void doClearRecents();
|
||||||
|
|
||||||
@ -191,7 +191,7 @@ protected:
|
|||||||
// Focus
|
// Focus
|
||||||
BookmarkEntryPtr nextEnt;
|
BookmarkEntryPtr nextEnt;
|
||||||
BookmarkRangeEntryPtr nextRange;
|
BookmarkRangeEntryPtr nextRange;
|
||||||
DemodulatorInstance *nextDemod;
|
DemodulatorInstancePtr nextDemod;
|
||||||
std::string nextGroup;
|
std::string nextGroup;
|
||||||
|
|
||||||
// Search
|
// Search
|
||||||
|
@ -73,8 +73,8 @@ void RigThread::run() {
|
|||||||
while (!stopping) {
|
while (!stopping) {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(150));
|
std::this_thread::sleep_for(std::chrono::milliseconds(150));
|
||||||
|
|
||||||
DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator();
|
auto activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator();
|
||||||
DemodulatorInstance *lastDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
auto lastDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
||||||
|
|
||||||
if (freqChanged.load() && (controlMode.load() || setOneShot.load())) {
|
if (freqChanged.load() && (controlMode.load() || setOneShot.load())) {
|
||||||
status = rig_get_freq(rig, RIG_VFO_CURR, &freq);
|
status = rig_get_freq(rig, RIG_VFO_CURR, &freq);
|
||||||
|
@ -16,12 +16,12 @@
|
|||||||
#define MAX_BLOCKING_DURATION_MICROS (1000 * 1000)
|
#define MAX_BLOCKING_DURATION_MICROS (1000 * 1000)
|
||||||
|
|
||||||
SDRPostThread::SDRPostThread() : IOThread(), buffers("SDRPostThreadBuffers"), visualDataBuffers("SDRPostThreadVisualDataBuffers"), frequency(0) {
|
SDRPostThread::SDRPostThread() : IOThread(), buffers("SDRPostThreadBuffers"), visualDataBuffers("SDRPostThreadVisualDataBuffers"), frequency(0) {
|
||||||
iqDataInQueue = NULL;
|
iqDataInQueue = nullptr;
|
||||||
iqDataOutQueue = NULL;
|
iqDataOutQueue = nullptr;
|
||||||
iqVisualQueue = NULL;
|
iqVisualQueue = nullptr;
|
||||||
|
|
||||||
numChannels = 0;
|
numChannels = 0;
|
||||||
channelizer = NULL;
|
channelizer = nullptr;
|
||||||
|
|
||||||
sampleRate = 0;
|
sampleRate = 0;
|
||||||
nRunDemods = 0;
|
nRunDemods = 0;
|
||||||
@ -36,44 +36,12 @@ SDRPostThread::SDRPostThread() : IOThread(), buffers("SDRPostThreadBuffers"), vi
|
|||||||
SDRPostThread::~SDRPostThread() {
|
SDRPostThread::~SDRPostThread() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRPostThread::bindDemodulator(DemodulatorInstance *demod) {
|
void SDRPostThread::notifyDemodulatorsChanged() {
|
||||||
|
|
||||||
std::lock_guard < std::mutex > lock(busy_demod);
|
|
||||||
|
|
||||||
demodulators.push_back(demod);
|
|
||||||
doRefresh.store(true);
|
doRefresh.store(true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRPostThread::bindDemodulators(std::vector<DemodulatorInstance *> *demods) {
|
|
||||||
if (!demods) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::lock_guard < std::mutex > lock(busy_demod);
|
|
||||||
|
|
||||||
for (std::vector<DemodulatorInstance *>::iterator di = demods->begin(); di != demods->end(); di++) {
|
|
||||||
demodulators.push_back(*di);
|
|
||||||
doRefresh.store(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SDRPostThread::removeDemodulator(DemodulatorInstance *demod) {
|
|
||||||
if (!demod) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard < std::mutex > lock(busy_demod);
|
|
||||||
|
|
||||||
std::vector<DemodulatorInstance *>::iterator i = std::find(demodulators.begin(), demodulators.end(), demod);
|
|
||||||
|
|
||||||
if (i != demodulators.end()) {
|
|
||||||
demodulators.erase(i);
|
|
||||||
doRefresh.store(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SDRPostThread::initPFBChannelizer() {
|
void SDRPostThread::initPFBChannelizer() {
|
||||||
// std::cout << "Initializing post-process FIR polyphase filterbank channelizer with " << numChannels << " channels." << std::endl;
|
// std::cout << "Initializing post-process FIR polyphase filterbank channelizer with " << numChannels << " channels." << std::endl;
|
||||||
if (channelizer) {
|
if (channelizer) {
|
||||||
@ -91,15 +59,16 @@ void SDRPostThread::initPFBChannelizer() {
|
|||||||
|
|
||||||
void SDRPostThread::updateActiveDemodulators() {
|
void SDRPostThread::updateActiveDemodulators() {
|
||||||
// In range?
|
// In range?
|
||||||
std::vector<DemodulatorInstance *>::iterator demod_i;
|
|
||||||
|
|
||||||
nRunDemods = 0;
|
nRunDemods = 0;
|
||||||
|
|
||||||
long long centerFreq = wxGetApp().getFrequency();
|
long long centerFreq = wxGetApp().getFrequency();
|
||||||
|
|
||||||
for (demod_i = demodulators.begin(); demod_i != demodulators.end(); demod_i++) {
|
//retreive the current list of demodulators:
|
||||||
DemodulatorInstance *demod = *demod_i;
|
auto demodulators = wxGetApp().getDemodMgr().getDemodulators();
|
||||||
|
|
||||||
|
for (auto demod : demodulators) {
|
||||||
|
|
||||||
// not in range?
|
// not in range?
|
||||||
if (demod->isDeltaLock()) {
|
if (demod->isDeltaLock()) {
|
||||||
if (demod->getFrequency() != centerFreq + demod->getDeltaLockOfs()) {
|
if (demod->getFrequency() != centerFreq + demod->getDeltaLockOfs()) {
|
||||||
@ -123,7 +92,7 @@ void SDRPostThread::updateActiveDemodulators() {
|
|||||||
}
|
}
|
||||||
} else if (!demod->isActive()) { // in range, activate if not activated
|
} else if (!demod->isActive()) { // in range, activate if not activated
|
||||||
demod->setActive(true);
|
demod->setActive(true);
|
||||||
if (wxGetApp().getDemodMgr().getLastActiveDemodulator() == NULL) {
|
if (wxGetApp().getDemodMgr().getLastActiveDemodulator() == nullptr) {
|
||||||
|
|
||||||
wxGetApp().getDemodMgr().setActiveDemodulator(demod);
|
wxGetApp().getDemodMgr().setActiveDemodulator(demod);
|
||||||
}
|
}
|
||||||
@ -194,9 +163,8 @@ void SDRPostThread::run() {
|
|||||||
if (!iqDataInQueue->pop(data_in, HEARTBEAT_CHECK_PERIOD_MICROS)) {
|
if (!iqDataInQueue->pop(data_in, HEARTBEAT_CHECK_PERIOD_MICROS)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// std::lock_guard < std::mutex > lock(data_in->m_mutex);
|
|
||||||
|
bool doUpdate = false;
|
||||||
std::lock_guard < std::mutex > lock(busy_demod);
|
|
||||||
|
|
||||||
if (data_in && data_in->data.size()) {
|
if (data_in && data_in->data.size()) {
|
||||||
if(data_in->numChannels > 1) {
|
if(data_in->numChannels > 1) {
|
||||||
@ -205,17 +173,16 @@ void SDRPostThread::run() {
|
|||||||
runSingleCH(data_in.get());
|
runSingleCH(data_in.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool doUpdate = false;
|
|
||||||
for (size_t j = 0; j < nRunDemods; j++) {
|
for (size_t j = 0; j < nRunDemods; j++) {
|
||||||
DemodulatorInstance *demod = runDemods[j];
|
DemodulatorInstancePtr demod = runDemods[j];
|
||||||
if (abs(frequency - demod->getFrequency()) > (sampleRate / 2)) {
|
if (abs(frequency - demod->getFrequency()) > (sampleRate / 2)) {
|
||||||
doUpdate = true;
|
doUpdate = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Only update the list of demodulators here
|
//Only update the list of demodulators here
|
||||||
if (doUpdate) {
|
if (doUpdate || doRefresh) {
|
||||||
updateActiveDemodulators();
|
updateActiveDemodulators();
|
||||||
}
|
}
|
||||||
} //end while
|
} //end while
|
||||||
@ -264,9 +231,9 @@ void SDRPostThread::runSingleCH(SDRThreadIQData *data_in) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t refCount = nRunDemods;
|
size_t refCount = nRunDemods;
|
||||||
bool doIQDataOut = (iqDataOutQueue != NULL && !iqDataOutQueue->full());
|
bool doIQDataOut = (iqDataOutQueue != nullptr && !iqDataOutQueue->full());
|
||||||
bool doDemodVisOut = (nRunDemods && iqActiveDemodVisualQueue != NULL && !iqActiveDemodVisualQueue->full());
|
bool doDemodVisOut = (nRunDemods && iqActiveDemodVisualQueue != nullptr && !iqActiveDemodVisualQueue->full());
|
||||||
bool doVisOut = (iqVisualQueue != NULL && !iqVisualQueue->full());
|
bool doVisOut = (iqVisualQueue != nullptr && !iqVisualQueue->full());
|
||||||
|
|
||||||
if (doIQDataOut) {
|
if (doIQDataOut) {
|
||||||
refCount++;
|
refCount++;
|
||||||
@ -295,22 +262,26 @@ void SDRPostThread::runSingleCH(SDRThreadIQData *data_in) {
|
|||||||
|
|
||||||
if (doDemodVisOut) {
|
if (doDemodVisOut) {
|
||||||
//VSO: blocking push
|
//VSO: blocking push
|
||||||
iqActiveDemodVisualQueue->push(demodDataOut, MAX_BLOCKING_DURATION_MICROS, "runSingleCH() iqActiveDemodVisualQueue");
|
iqActiveDemodVisualQueue->push(demodDataOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doIQDataOut) {
|
if (doIQDataOut) {
|
||||||
//VSO: blocking push
|
//VSO: blocking push
|
||||||
iqDataOutQueue->push(demodDataOut, MAX_BLOCKING_DURATION_MICROS,"runSingleCH() iqDataOutQueue");
|
iqDataOutQueue->push(demodDataOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doVisOut) {
|
if (doVisOut) {
|
||||||
//VSO: blocking push
|
//VSO: blocking push
|
||||||
iqVisualQueue->push(demodDataOut, MAX_BLOCKING_DURATION_MICROS, "runSingleCH() iqVisualQueue");
|
iqVisualQueue->push(demodDataOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < nRunDemods; i++) {
|
for (size_t i = 0; i < nRunDemods; i++) {
|
||||||
//VSO: blocking push
|
//VSO: timed-push
|
||||||
runDemods[i]->getIQInputDataPipe()->push(demodDataOut, MAX_BLOCKING_DURATION_MICROS, "runSingleCH() runDemods[i]->getIQInputDataPipe()");
|
if (!runDemods[i]->getIQInputDataPipe()->push(demodDataOut, MAX_BLOCKING_DURATION_MICROS, "runSingleCH() runDemods[i]->getIQInputDataPipe()")) {
|
||||||
|
//some runDemods are no longer there, bail out from runSingleCH() entirely.
|
||||||
|
doRefresh = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -338,7 +309,7 @@ void SDRPostThread::runPFBCH(SDRThreadIQData *data_in) {
|
|||||||
|
|
||||||
bool doVis = false;
|
bool doVis = false;
|
||||||
|
|
||||||
if (iqVisualQueue != NULL && !iqVisualQueue->full()) {
|
if (iqVisualQueue != nullptr && !iqVisualQueue->full()) {
|
||||||
doVis = true;
|
doVis = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,11 +318,11 @@ void SDRPostThread::runPFBCH(SDRThreadIQData *data_in) {
|
|||||||
iqDataOut->data.assign(data_in->data.begin(), data_in->data.begin() + dataSize);
|
iqDataOut->data.assign(data_in->data.begin(), data_in->data.begin() + dataSize);
|
||||||
|
|
||||||
//VSO: blocking push
|
//VSO: blocking push
|
||||||
iqDataOutQueue->push(iqDataOut, MAX_BLOCKING_DURATION_MICROS, "runPFBCH() iqDataOutQueue");
|
iqDataOutQueue->push(iqDataOut);
|
||||||
|
|
||||||
if (doVis) {
|
if (doVis) {
|
||||||
//VSO: blocking push
|
//VSO: blocking push
|
||||||
iqVisualQueue->push(iqDataOut, MAX_BLOCKING_DURATION_MICROS, "runPFBCH() iqVisualQueue");
|
iqVisualQueue->push(iqDataOut);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,7 +337,7 @@ void SDRPostThread::runPFBCH(SDRThreadIQData *data_in) {
|
|||||||
doRefresh.store(false);
|
doRefresh.store(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
DemodulatorInstancePtr activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
||||||
int activeDemodChannel = -1;
|
int activeDemodChannel = -1;
|
||||||
|
|
||||||
// Find active demodulators
|
// Find active demodulators
|
||||||
@ -384,7 +355,7 @@ void SDRPostThread::runPFBCH(SDRThreadIQData *data_in) {
|
|||||||
|
|
||||||
// Find nearest channel for each demodulator
|
// Find nearest channel for each demodulator
|
||||||
for (size_t i = 0; i < nRunDemods; i++) {
|
for (size_t i = 0; i < nRunDemods; i++) {
|
||||||
DemodulatorInstance *demod = runDemods[i];
|
DemodulatorInstancePtr demod = runDemods[i];
|
||||||
demodChannel[i] = getChannelAt(demod->getFrequency());
|
demodChannel[i] = getChannelAt(demod->getFrequency());
|
||||||
if (demod == activeDemod) {
|
if (demod == activeDemod) {
|
||||||
activeDemodChannel = demodChannel[i];
|
activeDemodChannel = demodChannel[i];
|
||||||
@ -400,7 +371,7 @@ void SDRPostThread::runPFBCH(SDRThreadIQData *data_in) {
|
|||||||
|
|
||||||
// Run channels
|
// Run channels
|
||||||
for (int i = 0; i < numChannels+1; i++) {
|
for (int i = 0; i < numChannels+1; i++) {
|
||||||
int doDemodVis = ((activeDemodChannel == i) && (iqActiveDemodVisualQueue != NULL) && !iqActiveDemodVisualQueue->full())?1:0;
|
int doDemodVis = ((activeDemodChannel == i) && (iqActiveDemodVisualQueue != nullptr) && !iqActiveDemodVisualQueue->full())?1:0;
|
||||||
|
|
||||||
if (!doDemodVis && demodChannelActive[i] == 0) {
|
if (!doDemodVis && demodChannelActive[i] == 0) {
|
||||||
continue;
|
continue;
|
||||||
@ -447,16 +418,20 @@ void SDRPostThread::runPFBCH(SDRThreadIQData *data_in) {
|
|||||||
|
|
||||||
if (doDemodVis) {
|
if (doDemodVis) {
|
||||||
//VSO: blocking push
|
//VSO: blocking push
|
||||||
iqActiveDemodVisualQueue->push(demodDataOut, MAX_BLOCKING_DURATION_MICROS, "runPFBCH() iqActiveDemodVisualQueue");
|
iqActiveDemodVisualQueue->push(demodDataOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t j = 0; j < nRunDemods; j++) {
|
for (size_t j = 0; j < nRunDemods; j++) {
|
||||||
if (demodChannel[j] == i) {
|
if (demodChannel[j] == i) {
|
||||||
DemodulatorInstance *demod = runDemods[j];
|
|
||||||
//VSO: blocking push
|
//VSO: timed- push
|
||||||
demod->getIQInputDataPipe()->push(demodDataOut, MAX_BLOCKING_DURATION_MICROS, "runPFBCH() demod->getIQInputDataPipe()");
|
if (!runDemods[j]->getIQInputDataPipe()->push(demodDataOut, MAX_BLOCKING_DURATION_MICROS, "runPFBCH() runDemods[j]->getIQInputDataPipe()")) {
|
||||||
|
//Some runDemods are no longer there, bail out from runPFBCH() entirely.
|
||||||
|
doRefresh = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
} //end for
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,8 @@ public:
|
|||||||
SDRPostThread();
|
SDRPostThread();
|
||||||
~SDRPostThread();
|
~SDRPostThread();
|
||||||
|
|
||||||
void bindDemodulator(DemodulatorInstance *demod);
|
void notifyDemodulatorsChanged();
|
||||||
void bindDemodulators(std::vector<DemodulatorInstance *> *demods);
|
|
||||||
void removeDemodulator(DemodulatorInstance *demod);
|
|
||||||
|
|
||||||
virtual void run();
|
virtual void run();
|
||||||
virtual void terminate();
|
virtual void terminate();
|
||||||
|
|
||||||
@ -27,12 +25,6 @@ protected:
|
|||||||
DemodulatorThreadInputQueuePtr iqDataOutQueue;
|
DemodulatorThreadInputQueuePtr iqDataOutQueue;
|
||||||
DemodulatorThreadInputQueuePtr iqVisualQueue;
|
DemodulatorThreadInputQueuePtr iqVisualQueue;
|
||||||
DemodulatorThreadInputQueuePtr iqActiveDemodVisualQueue;
|
DemodulatorThreadInputQueuePtr iqActiveDemodVisualQueue;
|
||||||
|
|
||||||
//protects access to demodulators lists and such
|
|
||||||
std::mutex busy_demod;
|
|
||||||
std::vector<DemodulatorInstance *> demodulators;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -48,7 +40,7 @@ private:
|
|||||||
long long chanBw = 0;
|
long long chanBw = 0;
|
||||||
|
|
||||||
size_t nRunDemods;
|
size_t nRunDemods;
|
||||||
std::vector<DemodulatorInstance *> runDemods;
|
std::vector<DemodulatorInstancePtr> runDemods;
|
||||||
std::vector<int> demodChannel;
|
std::vector<int> demodChannel;
|
||||||
std::vector<int> demodChannelActive;
|
std::vector<int> demodChannelActive;
|
||||||
|
|
||||||
|
@ -13,10 +13,10 @@
|
|||||||
#define TARGET_DISPLAY_FPS 60
|
#define TARGET_DISPLAY_FPS 60
|
||||||
|
|
||||||
SDRThread::SDRThread() : IOThread(), buffers("SDRThreadBuffers") {
|
SDRThread::SDRThread() : IOThread(), buffers("SDRThreadBuffers") {
|
||||||
device = NULL;
|
device = nullptr;
|
||||||
|
|
||||||
deviceConfig.store(NULL);
|
deviceConfig.store(nullptr);
|
||||||
deviceInfo.store(NULL);
|
deviceInfo.store(nullptr);
|
||||||
|
|
||||||
sampleRate.store(DEFAULT_SAMPLE_RATE);
|
sampleRate.store(DEFAULT_SAMPLE_RATE);
|
||||||
frequency.store(0);
|
frequency.store(0);
|
||||||
|
@ -62,7 +62,7 @@ PrimaryGLContext::PrimaryGLContext(wxGLCanvas *canvas, wxGLContext *sharedContex
|
|||||||
//#endif
|
//#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrimaryGLContext::DrawDemodInfo(DemodulatorInstance *demod, RGBA4f color, long long center_freq, long long srate, bool centerline) {
|
void PrimaryGLContext::DrawDemodInfo(DemodulatorInstancePtr demod, RGBA4f color, long long center_freq, long long srate, bool centerline) {
|
||||||
if (!demod) {
|
if (!demod) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -287,7 +287,7 @@ void PrimaryGLContext::DrawFreqBwInfo(long long freq, int bw, RGBA4f color, long
|
|||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrimaryGLContext::DrawDemod(DemodulatorInstance *demod, RGBA4f color, long long center_freq, long long srate) {
|
void PrimaryGLContext::DrawDemod(DemodulatorInstancePtr demod, RGBA4f color, long long center_freq, long long srate) {
|
||||||
if (!demod) {
|
if (!demod) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -409,7 +409,8 @@ void PrimaryGLContext::drawSingleDemodLabel(const std::wstring& demodStr, float
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PrimaryGLContext::DrawFreqSelector(float uxPos, RGBA4f color, float w, long long /* center_freq */, long long srate) {
|
void PrimaryGLContext::DrawFreqSelector(float uxPos, RGBA4f color, float w, long long /* center_freq */, long long srate) {
|
||||||
DemodulatorInstance *demod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
|
||||||
|
DemodulatorInstancePtr demod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
||||||
|
|
||||||
long long bw = 0;
|
long long bw = 0;
|
||||||
|
|
||||||
|
@ -26,9 +26,9 @@ public:
|
|||||||
|
|
||||||
void DrawFreqSelector(float uxPos, RGBA4f color, float w = 0, long long center_freq = -1, long long srate = 0);
|
void DrawFreqSelector(float uxPos, RGBA4f color, float w = 0, long long center_freq = -1, long long srate = 0);
|
||||||
void DrawRangeSelector(float uxPos1, float uxPos2, RGBA4f color);
|
void DrawRangeSelector(float uxPos1, float uxPos2, RGBA4f color);
|
||||||
void DrawDemod(DemodulatorInstance *demod, RGBA4f color, long long center_freq = -1, long long srate = 0);
|
void DrawDemod(DemodulatorInstancePtr demod, RGBA4f color, long long center_freq = -1, long long srate = 0);
|
||||||
|
|
||||||
void DrawDemodInfo(DemodulatorInstance *demod, RGBA4f color, long long center_freq = -1, long long srate = 0, bool centerline = false);
|
void DrawDemodInfo(DemodulatorInstancePtr demod, RGBA4f color, long long center_freq = -1, long long srate = 0, bool centerline = false);
|
||||||
void DrawFreqBwInfo(long long freq, int bw, RGBA4f color, long long center_freq = - 1, long long srate = 0, bool stack = false, bool centerline = false);
|
void DrawFreqBwInfo(long long freq, int bw, RGBA4f color, long long center_freq = - 1, long long srate = 0, bool stack = false, bool centerline = false);
|
||||||
|
|
||||||
void setHoverAlpha(float hoverAlpha);
|
void setHoverAlpha(float hoverAlpha);
|
||||||
|
@ -90,9 +90,8 @@ void SpectrumCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
|||||||
|
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
|
|
||||||
std::vector<DemodulatorInstance *> &demods = wxGetApp().getDemodMgr().getDemodulators();
|
auto demods = wxGetApp().getDemodMgr().getDemodulators();
|
||||||
|
auto activeDemodulator = wxGetApp().getDemodMgr().getActiveDemodulator();
|
||||||
DemodulatorInstance *activeDemodulator = wxGetApp().getDemodMgr().getActiveDemodulator();
|
|
||||||
|
|
||||||
for (int i = 0, iMax = demods.size(); i < iMax; i++) {
|
for (int i = 0, iMax = demods.size(); i < iMax; i++) {
|
||||||
if (!demods[i]->isActive()) {
|
if (!demods[i]->isActive()) {
|
||||||
@ -112,7 +111,7 @@ void SpectrumCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
|||||||
freq = roundf((float)freq/(float)snap)*snap;
|
freq = roundf((float)freq/(float)snap)*snap;
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorInstance *lastActiveDemodulator = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
auto lastActiveDemodulator = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
||||||
|
|
||||||
bool isNew = (((waterfallCanvas->isShiftDown() || (lastActiveDemodulator && !lastActiveDemodulator->isActive())) && lastActiveDemodulator) || (!lastActiveDemodulator));
|
bool isNew = (((waterfallCanvas->isShiftDown() || (lastActiveDemodulator && !lastActiveDemodulator->isActive())) && lastActiveDemodulator) || (!lastActiveDemodulator));
|
||||||
|
|
||||||
|
@ -61,7 +61,8 @@ TuningCanvas::~TuningCanvas() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool TuningCanvas::changed() {
|
bool TuningCanvas::changed() {
|
||||||
DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
|
||||||
|
auto activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
||||||
|
|
||||||
long long current_freq = 0;
|
long long current_freq = 0;
|
||||||
if (activeDemod != NULL) {
|
if (activeDemod != NULL) {
|
||||||
@ -92,7 +93,7 @@ void TuningCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
|||||||
|
|
||||||
glContext->DrawBegin();
|
glContext->DrawBegin();
|
||||||
|
|
||||||
DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
auto activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
||||||
|
|
||||||
freq = 0;
|
freq = 0;
|
||||||
if (activeDemod != NULL) {
|
if (activeDemod != NULL) {
|
||||||
@ -170,7 +171,7 @@ void TuningCanvas::StepTuner(ActiveState state, int exponent, bool up) {
|
|||||||
amount *= 2;
|
amount *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
auto activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
||||||
if (state == TUNING_HOVER_FREQ && activeDemod) {
|
if (state == TUNING_HOVER_FREQ && activeDemod) {
|
||||||
long long freq = activeDemod->getFrequency();
|
long long freq = activeDemod->getFrequency();
|
||||||
long long diff = abs(wxGetApp().getFrequency() - freq);
|
long long diff = abs(wxGetApp().getFrequency() - freq);
|
||||||
@ -330,7 +331,7 @@ void TuningCanvas::OnMouseMoved(wxMouseEvent& event) {
|
|||||||
if (hoverState == TUNING_HOVER_BW || hoverState == TUNING_HOVER_FREQ) {
|
if (hoverState == TUNING_HOVER_BW || hoverState == TUNING_HOVER_FREQ) {
|
||||||
wxGetApp().getDemodMgr().setActiveDemodulator(wxGetApp().getDemodMgr().getLastActiveDemodulator());
|
wxGetApp().getDemodMgr().setActiveDemodulator(wxGetApp().getDemodMgr().getLastActiveDemodulator());
|
||||||
} else {
|
} else {
|
||||||
wxGetApp().getDemodMgr().setActiveDemodulator(NULL);
|
wxGetApp().getDemodMgr().setActiveDemodulator(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,7 +401,7 @@ void TuningCanvas::OnMouseLeftWindow(wxMouseEvent& event) {
|
|||||||
SetCursor(wxCURSOR_CROSS);
|
SetCursor(wxCURSOR_CROSS);
|
||||||
hoverIndex = 0;
|
hoverIndex = 0;
|
||||||
hoverState = TUNING_HOVER_NONE;
|
hoverState = TUNING_HOVER_NONE;
|
||||||
wxGetApp().getDemodMgr().setActiveDemodulator(NULL);
|
wxGetApp().getDemodMgr().setActiveDemodulator(nullptr);
|
||||||
|
|
||||||
if (currentPPM != lastPPM) {
|
if (currentPPM != lastPPM) {
|
||||||
wxGetApp().saveConfig();
|
wxGetApp().saveConfig();
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
|
|
||||||
#include <wx/numformatter.h>
|
#include <wx/numformatter.h>
|
||||||
|
|
||||||
|
#include "DemodulatorThread.h"
|
||||||
|
|
||||||
wxBEGIN_EVENT_TABLE(WaterfallCanvas, wxGLCanvas)
|
wxBEGIN_EVENT_TABLE(WaterfallCanvas, wxGLCanvas)
|
||||||
EVT_PAINT(WaterfallCanvas::OnPaint)
|
EVT_PAINT(WaterfallCanvas::OnPaint)
|
||||||
EVT_IDLE(WaterfallCanvas::OnIdle)
|
EVT_IDLE(WaterfallCanvas::OnIdle)
|
||||||
@ -263,10 +265,10 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
|||||||
waterfallPanel.calcTransform(CubicVR::mat4::identity());
|
waterfallPanel.calcTransform(CubicVR::mat4::identity());
|
||||||
waterfallPanel.draw();
|
waterfallPanel.draw();
|
||||||
|
|
||||||
std::vector<DemodulatorInstance *> &demods = wxGetApp().getDemodMgr().getDemodulators();
|
auto demods = wxGetApp().getDemodMgr().getDemodulators();
|
||||||
|
|
||||||
DemodulatorInstance *activeDemodulator = wxGetApp().getDemodMgr().getActiveDemodulator();
|
auto activeDemodulator = wxGetApp().getDemodMgr().getActiveDemodulator();
|
||||||
DemodulatorInstance *lastActiveDemodulator = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
auto lastActiveDemodulator = wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
||||||
|
|
||||||
bool isNew = shiftDown
|
bool isNew = shiftDown
|
||||||
|| (wxGetApp().getDemodMgr().getLastActiveDemodulator() && !wxGetApp().getDemodMgr().getLastActiveDemodulator()->isActive());
|
|| (wxGetApp().getDemodMgr().getLastActiveDemodulator() && !wxGetApp().getDemodMgr().getLastActiveDemodulator()->isActive());
|
||||||
@ -307,9 +309,9 @@ void WaterfallCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (lastActiveDemodulator) {
|
if (lastActiveDemodulator) {
|
||||||
glContext->DrawDemod(lastActiveDemodulator, ((isNew && activeDemodulator == NULL) || (activeDemodulator != NULL))?currentTheme->waterfallHighlight:currentTheme->waterfallDestroy, currentCenterFreq, currentBandwidth);
|
glContext->DrawDemod(lastActiveDemodulator, ((isNew && activeDemodulator == nullptr) || (activeDemodulator != nullptr))?currentTheme->waterfallHighlight:currentTheme->waterfallDestroy, currentCenterFreq, currentBandwidth);
|
||||||
}
|
}
|
||||||
if (activeDemodulator == NULL) {
|
if (activeDemodulator == nullptr) {
|
||||||
glContext->DrawFreqSelector(mouseTracker.getMouseX(), ((isNew && lastActiveDemodulator) || (!lastActiveDemodulator) )?currentTheme->waterfallNew:currentTheme->waterfallHover, 0, currentCenterFreq, currentBandwidth);
|
glContext->DrawFreqSelector(mouseTracker.getMouseX(), ((isNew && lastActiveDemodulator) || (!lastActiveDemodulator) )?currentTheme->waterfallNew:currentTheme->waterfallHover, 0, currentCenterFreq, currentBandwidth);
|
||||||
} else {
|
} else {
|
||||||
glContext->DrawDemod(activeDemodulator, currentTheme->waterfallHover, currentCenterFreq, currentBandwidth);
|
glContext->DrawDemod(activeDemodulator, currentTheme->waterfallHover, currentCenterFreq, currentBandwidth);
|
||||||
@ -390,7 +392,7 @@ void WaterfallCanvas::OnKeyUp(wxKeyEvent& event) {
|
|||||||
void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) {
|
void WaterfallCanvas::OnKeyDown(wxKeyEvent& event) {
|
||||||
InteractiveCanvas::OnKeyDown(event);
|
InteractiveCanvas::OnKeyDown(event);
|
||||||
|
|
||||||
DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator();
|
auto activeDemod = wxGetApp().getDemodMgr().getActiveDemodulator();
|
||||||
|
|
||||||
long long originalFreq = getCenterFrequency();
|
long long originalFreq = getCenterFrequency();
|
||||||
long long freq = originalFreq;
|
long long freq = originalFreq;
|
||||||
@ -490,9 +492,9 @@ void WaterfallCanvas::OnIdle(wxIdleEvent &event) {
|
|||||||
void WaterfallCanvas::updateHoverState() {
|
void WaterfallCanvas::updateHoverState() {
|
||||||
long long freqPos = getFrequencyAt(mouseTracker.getMouseX());
|
long long freqPos = getFrequencyAt(mouseTracker.getMouseX());
|
||||||
|
|
||||||
std::vector<DemodulatorInstance *> demodsHover = wxGetApp().getDemodMgr().getDemodulatorsAt(freqPos, 15000);
|
auto demodsHover = wxGetApp().getDemodMgr().getDemodulatorsAt(freqPos, 15000);
|
||||||
|
|
||||||
wxGetApp().getDemodMgr().setActiveDemodulator(NULL);
|
wxGetApp().getDemodMgr().setActiveDemodulator(nullptr);
|
||||||
|
|
||||||
if (altDown) {
|
if (altDown) {
|
||||||
nextDragState = WF_DRAG_RANGE;
|
nextDragState = WF_DRAG_RANGE;
|
||||||
@ -506,10 +508,10 @@ void WaterfallCanvas::updateHoverState() {
|
|||||||
} else if (demodsHover.size() && !shiftDown) {
|
} else if (demodsHover.size() && !shiftDown) {
|
||||||
long near_dist = getBandwidth();
|
long near_dist = getBandwidth();
|
||||||
|
|
||||||
DemodulatorInstance *activeDemodulator = NULL;
|
DemodulatorInstancePtr activeDemodulator = nullptr;
|
||||||
|
|
||||||
for (int i = 0, iMax = demodsHover.size(); i < iMax; i++) {
|
for (int i = 0, iMax = demodsHover.size(); i < iMax; i++) {
|
||||||
DemodulatorInstance *demod = demodsHover[i];
|
auto demod = demodsHover[i];
|
||||||
long long freqDiff = demod->getFrequency() - freqPos;
|
long long freqDiff = demod->getFrequency() - freqPos;
|
||||||
long halfBw = (demod->getBandwidth() / 2);
|
long halfBw = (demod->getBandwidth() / 2);
|
||||||
long long currentBw = getBandwidth();
|
long long currentBw = getBandwidth();
|
||||||
@ -537,7 +539,7 @@ void WaterfallCanvas::updateHoverState() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (activeDemodulator == NULL) {
|
if (activeDemodulator == nullptr) {
|
||||||
nextDragState = WF_DRAG_NONE;
|
nextDragState = WF_DRAG_NONE;
|
||||||
SetCursor(wxCURSOR_CROSS);
|
SetCursor(wxCURSOR_CROSS);
|
||||||
return;
|
return;
|
||||||
@ -588,10 +590,10 @@ void WaterfallCanvas::updateHoverState() {
|
|||||||
|
|
||||||
void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) {
|
void WaterfallCanvas::OnMouseMoved(wxMouseEvent& event) {
|
||||||
InteractiveCanvas::OnMouseMoved(event);
|
InteractiveCanvas::OnMouseMoved(event);
|
||||||
DemodulatorInstance *demod = wxGetApp().getDemodMgr().getActiveDemodulator();
|
auto demod = wxGetApp().getDemodMgr().getActiveDemodulator();
|
||||||
|
|
||||||
if (mouseTracker.mouseDown()) {
|
if (mouseTracker.mouseDown()) {
|
||||||
if (demod == NULL) {
|
if (demod == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (dragState == WF_DRAG_BANDWIDTH_LEFT || dragState == WF_DRAG_BANDWIDTH_RIGHT) {
|
if (dragState == WF_DRAG_BANDWIDTH_LEFT || dragState == WF_DRAG_BANDWIDTH_RIGHT) {
|
||||||
@ -650,7 +652,7 @@ void WaterfallCanvas::OnMouseDown(wxMouseEvent& event) {
|
|||||||
wxGetApp().getDemodMgr().updateLastState();
|
wxGetApp().getDemodMgr().updateLastState();
|
||||||
|
|
||||||
if (dragState && dragState != WF_DRAG_RANGE) {
|
if (dragState && dragState != WF_DRAG_RANGE) {
|
||||||
DemodulatorInstance *demod = wxGetApp().getDemodMgr().getActiveDemodulator();
|
auto demod = wxGetApp().getDemodMgr().getActiveDemodulator();
|
||||||
if (demod) {
|
if (demod) {
|
||||||
dragOfs = (long long) (mouseTracker.getMouseX() * (float) getBandwidth()) + getCenterFrequency() - (getBandwidth() / 2) - demod->getFrequency();
|
dragOfs = (long long) (mouseTracker.getMouseX() * (float) getBandwidth()) + getCenterFrequency() - (getBandwidth() / 2) - demod->getFrequency();
|
||||||
dragBW = demod->getBandwidth();
|
dragBW = demod->getBandwidth();
|
||||||
@ -670,14 +672,14 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
|
|||||||
InteractiveCanvas::OnMouseReleased(event);
|
InteractiveCanvas::OnMouseReleased(event);
|
||||||
wxGetApp().getDemodMgr().updateLastState();
|
wxGetApp().getDemodMgr().updateLastState();
|
||||||
|
|
||||||
bool isNew = shiftDown || (wxGetApp().getDemodMgr().getLastActiveDemodulator() == NULL)
|
bool isNew = shiftDown || (wxGetApp().getDemodMgr().getLastActiveDemodulator() == nullptr)
|
||||||
|| (wxGetApp().getDemodMgr().getLastActiveDemodulator() && !wxGetApp().getDemodMgr().getLastActiveDemodulator()->isActive());
|
|| (wxGetApp().getDemodMgr().getLastActiveDemodulator() && !wxGetApp().getDemodMgr().getLastActiveDemodulator()->isActive());
|
||||||
|
|
||||||
mouseTracker.setVertDragLock(false);
|
mouseTracker.setVertDragLock(false);
|
||||||
mouseTracker.setHorizDragLock(false);
|
mouseTracker.setHorizDragLock(false);
|
||||||
|
|
||||||
DemodulatorInstance *demod = isNew?NULL:wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
DemodulatorInstancePtr demod = isNew?nullptr:wxGetApp().getDemodMgr().getLastActiveDemodulator();
|
||||||
DemodulatorInstance *activeDemod = isNew?NULL:wxGetApp().getDemodMgr().getActiveDemodulator();
|
DemodulatorInstancePtr activeDemod = isNew?nullptr:wxGetApp().getDemodMgr().getActiveDemodulator();
|
||||||
|
|
||||||
DemodulatorMgr *mgr = &wxGetApp().getDemodMgr();
|
DemodulatorMgr *mgr = &wxGetApp().getDemodMgr();
|
||||||
|
|
||||||
@ -727,7 +729,7 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
|
|||||||
demod->writeModemSettings(mgr->getLastModemSettings(mgr->getLastDemodulatorType()));
|
demod->writeModemSettings(mgr->getLastModemSettings(mgr->getLastDemodulatorType()));
|
||||||
demod->run();
|
demod->run();
|
||||||
|
|
||||||
wxGetApp().bindDemodulator(demod);
|
wxGetApp().notifyDemodulatorsChanged();
|
||||||
DemodulatorThread::releaseSquelchLock(nullptr);
|
DemodulatorThread::releaseSquelchLock(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -827,10 +829,10 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
|
|||||||
|
|
||||||
demod->run();
|
demod->run();
|
||||||
|
|
||||||
wxGetApp().bindDemodulator(demod);
|
wxGetApp().notifyDemodulatorsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (demod == NULL) {
|
if (demod == nullptr) {
|
||||||
dragState = WF_DRAG_NONE;
|
dragState = WF_DRAG_NONE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -850,7 +852,7 @@ void WaterfallCanvas::OnMouseReleased(wxMouseEvent& event) {
|
|||||||
void WaterfallCanvas::OnMouseLeftWindow(wxMouseEvent& event) {
|
void WaterfallCanvas::OnMouseLeftWindow(wxMouseEvent& event) {
|
||||||
InteractiveCanvas::OnMouseLeftWindow(event);
|
InteractiveCanvas::OnMouseLeftWindow(event);
|
||||||
SetCursor(wxCURSOR_CROSS);
|
SetCursor(wxCURSOR_CROSS);
|
||||||
wxGetApp().getDemodMgr().setActiveDemodulator(NULL);
|
wxGetApp().getDemodMgr().setActiveDemodulator(nullptr);
|
||||||
mouseZoom = 1.0;
|
mouseZoom = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user