diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 77d8fce..d17a02e 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -24,6 +24,7 @@ #include "ColorTheme.h" #include "DemodulatorMgr.h" #include "ImagePanel.h" +#include "ActionDialog.h" #include #include @@ -53,6 +54,22 @@ wxEND_EVENT_TABLE() #endif + +class ActionDialogBookmarkReset : public ActionDialog { +public: + ActionDialogBookmarkReset() : ActionDialog(wxGetApp().getAppFrame(), wxID_ANY, wxT("Reset Bookmarks?")) { + m_questionText->SetLabelText(wxT("Resetting bookmarks will erase all current bookmarks; are you sure?")); + } + + void doClickOK() { + wxGetApp().getBookmarkMgr().resetBookmarks(); + wxGetApp().getBookmarkMgr().updateBookmarks(); + wxGetApp().getBookmarkMgr().updateActiveList(); + } +}; + + + /* split a string by 'seperator' into a vector of string */ std::vector str_explode(const std::string &seperator, const std::string &in_str); @@ -711,18 +728,28 @@ wxMenu *AppFrame::makeFileMenu() { menu->Append(wxID_SDR_START_STOP, "Stop / Start Device"); menu->AppendSeparator(); - menu->Append(wxID_OPEN, "&Open Session"); - menu->Append(wxID_SAVE, "&Save Session"); - menu->Append(wxID_SAVEAS, "Save Session &As.."); - menu->AppendSeparator(); - menu->Append(wxID_RESET, "&Reset Session"); - menu->AppendSeparator(); - menu->Append(wxID_OPEN_BOOKMARKS, "Open Bookmarks"); - menu->Append(wxID_SAVE_BOOKMARKS, "Save Bookmarks"); - menu->Append(wxID_SAVEAS_BOOKMARKS, "Save Bookmarks As.."); - menu->AppendSeparator(); - menu->Append(wxID_RESET_BOOKMARKS, "Reset Bookmarks"); + wxMenu *sessionMenu = new wxMenu; + + sessionMenu->Append(wxID_OPEN, "&Open Session"); + sessionMenu->Append(wxID_SAVE, "&Save Session"); + sessionMenu->Append(wxID_SAVEAS, "Save Session &As.."); + sessionMenu->AppendSeparator(); + sessionMenu->Append(wxID_RESET, "&Reset Session"); + menu->AppendSubMenu(sessionMenu, "Session"); + + menu->AppendSeparator(); + + wxMenu *bookmarkMenu = new wxMenu; + + bookmarkMenu->Append(wxID_OPEN_BOOKMARKS, "Open Bookmarks"); + bookmarkMenu->Append(wxID_SAVE_BOOKMARKS, "Save Bookmarks"); + bookmarkMenu->Append(wxID_SAVEAS_BOOKMARKS, "Save Bookmarks As.."); + bookmarkMenu->AppendSeparator(); + bookmarkMenu->Append(wxID_RESET_BOOKMARKS, "Reset Bookmarks"); + + menu->AppendSubMenu(bookmarkMenu, "Bookmarks"); + #ifndef __APPLE__ menu->AppendSeparator(); menu->Append(wxID_CLOSE); @@ -1570,10 +1597,8 @@ bool AppFrame::actionOnMenuLoadSave(wxCommandEvent& event) { } else if (event.GetId() == wxID_RESET_BOOKMARKS) { - wxGetApp().getBookmarkMgr().resetBookmarks(); - wxGetApp().getBookmarkMgr().updateBookmarks(); - wxGetApp().getBookmarkMgr().updateActiveList(); - + ActionDialog::showDialog(new ActionDialogBookmarkReset()); + return true; } diff --git a/src/AppFrame.h b/src/AppFrame.h index 081db1c..03344ae 100644 --- a/src/AppFrame.h +++ b/src/AppFrame.h @@ -221,6 +221,7 @@ private: std::vector devices; std::map inputDevices; std::map outputDevices; + std::map outputDeviceMenuItems; std::map sampleRateMenuItems; std::map antennaMenuItems; diff --git a/src/audio/AudioThread.h b/src/audio/AudioThread.h index dfb2e5e..7585faa 100644 --- a/src/audio/AudioThread.h +++ b/src/audio/AudioThread.h @@ -21,15 +21,32 @@ public: int channels; float peak; int type; - bool is_squelch_active = false; + bool is_squelch_active; std::vector data; AudioThreadInput() : - frequency(0), inputRate(0), sampleRate(0), channels(0), peak(0), type(0) { + frequency(0), inputRate(0), sampleRate(0), channels(0), peak(0), type(0), is_squelch_active(false) { } + + AudioThreadInput(AudioThreadInput *copyFrom) { + copy(copyFrom); + } + + void copy(AudioThreadInput *copyFrom) { + frequency = copyFrom->frequency; + inputRate = copyFrom->inputRate; + sampleRate = copyFrom->sampleRate; + channels = copyFrom->channels; + peak = copyFrom->peak; + type = copyFrom->type; + is_squelch_active = copyFrom->is_squelch_active; + data.assign(copyFrom->data.begin(), copyFrom->data.end()); + } + + virtual ~AudioThreadInput() { } diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index d7014d6..39e9014 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -187,7 +187,7 @@ void DemodulatorInstance::terminate() { demodulatorPreThread->terminate(); if (audioSinkThread != nullptr) { - audioSinkThread->terminate(); + stopRecording(); } //that will actually unblock the currently blocked push(). diff --git a/src/demod/DemodulatorThread.cpp b/src/demod/DemodulatorThread.cpp index 82cb198..d828d26 100644 --- a/src/demod/DemodulatorThread.cpp +++ b/src/demod/DemodulatorThread.cpp @@ -225,13 +225,6 @@ void DemodulatorThread::run() { } } - // Capture audioSinkOutputQueue state in a local variable - DemodulatorThreadOutputQueuePtr localAudioSinkOutputQueue = nullptr; - { - std::lock_guard < std::mutex > lock(m_mutexAudioVisOutputQueue); - localAudioSinkOutputQueue = audioSinkOutputQueue; - } - //compute audio peak: if (audioOutputQueue != nullptr && ati) { @@ -250,21 +243,6 @@ void DemodulatorThread::run() { ati->is_squelch_active = squelched; } - //Push to audio sink, if any: - if (ati && localAudioSinkOutputQueue != nullptr) { - - if (!localAudioSinkOutputQueue->try_push(ati)) { - std::cout << "DemodulatorThread::run() cannot push ati into audioSinkOutputQueue, is full !" << std::endl; - std::this_thread::yield(); - } - } - - //now we can nullify ati if squelched, to skip the next processing entirely. - if (ati && squelched) { - - ati = nullptr; - } - //At that point, capture the current state of audioVisOutputQueue in a local //variable, and works with it with now on until the next while-turn. DemodulatorThreadOutputQueuePtr localAudioVisOutputQueue = nullptr; @@ -273,7 +251,7 @@ void DemodulatorThread::run() { localAudioVisOutputQueue = audioVisOutputQueue; } - if ((ati || modemDigital) && localAudioVisOutputQueue != nullptr && localAudioVisOutputQueue->empty()) { + if (!squelched && (ati || modemDigital) && localAudioVisOutputQueue != nullptr && localAudioVisOutputQueue->empty()) { AudioThreadInputPtr ati_vis = std::make_shared(); @@ -343,7 +321,7 @@ void DemodulatorThread::run() { } } - if (ati != nullptr) { + if (!squelched && ati != nullptr) { if (!muted.load() && (!wxGetApp().getSoloMode() || (demodInstance == wxGetApp().getDemodMgr().getLastActiveDemodulator().get()))) { //non-blocking push needed for audio out if (!audioOutputQueue->try_push(ati)) { @@ -354,6 +332,23 @@ void DemodulatorThread::run() { } } + + // Capture audioSinkOutputQueue state in a local variable + DemodulatorThreadOutputQueuePtr localAudioSinkOutputQueue = nullptr; + { + std::lock_guard < std::mutex > lock(m_mutexAudioVisOutputQueue); + localAudioSinkOutputQueue = audioSinkOutputQueue; + } + + //Push to audio sink, if any: + if (ati && localAudioSinkOutputQueue != nullptr) { + + if (!localAudioSinkOutputQueue->try_push(ati)) { + std::cout << "DemodulatorThread::run() cannot push ati into audioSinkOutputQueue, is full !" << std::endl; + std::this_thread::yield(); + } + } + DemodulatorThreadControlCommand command; //empty command queue, execute commands