From 9ea5d704c07d7f7eb06fc0c4e60c5b1ce23faa7e Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Thu, 28 Jul 2016 19:33:59 -0400 Subject: [PATCH 1/2] Unify font+theme into Display menu --- src/AppFrame.cpp | 50 ++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index f336473..b05bebd 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -378,21 +378,11 @@ AppFrame::AppFrame() : } menuBar->Append(menu, wxT("Audio &Output")); - - menu = new wxMenu; - - int themeId = wxGetApp().getConfig()->getTheme(); - menu->AppendRadioItem(wxID_THEME_DEFAULT, "Default")->Check(themeId==COLOR_THEME_DEFAULT); - menu->AppendRadioItem(wxID_THEME_RADAR, "RADAR")->Check(themeId==COLOR_THEME_RADAR); - menu->AppendRadioItem(wxID_THEME_BW, "Black & White")->Check(themeId==COLOR_THEME_BW); - menu->AppendRadioItem(wxID_THEME_SHARP, "Sharp")->Check(themeId==COLOR_THEME_SHARP); - menu->AppendRadioItem(wxID_THEME_RAD, "Rad")->Check(themeId==COLOR_THEME_RAD); - menu->AppendRadioItem(wxID_THEME_TOUCH, "Touch")->Check(themeId==COLOR_THEME_TOUCH); - menu->AppendRadioItem(wxID_THEME_HD, "HD")->Check(themeId==COLOR_THEME_HD); - - menuBar->Append(menu, wxT("&Color Scheme")); + sampleRateMenu = new wxMenu; + menuBar->Append(sampleRateMenu, wxT("Sample &Rate")); + // Audio Sample Rates menu = new wxMenu; #define NUM_RATES_DEFAULT 4 @@ -441,23 +431,37 @@ AppFrame::AppFrame() : } } - sampleRateMenu = new wxMenu; - - menuBar->Append(sampleRateMenu, wxT("Sample &Rate")); - menuBar->Append(menu, wxT("Audio &Sample Rate")); - //Add Display menu displayMenu = new wxMenu; + + wxMenu *fontMenu = new wxMenu; - menuBar->Append(displayMenu, wxT("&Display")); int fontScale = wxGetApp().getConfig()->getFontScale(); - displayMenu->AppendRadioItem(wxID_DISPLAY_BASE, "Text Size: Normal")->Check(GLFont::GLFONT_SCALE_NORMAL == fontScale); - displayMenu->AppendRadioItem(wxID_DISPLAY_BASE + 1, "Text Size: 1.5x")->Check(GLFont::GLFONT_SCALE_MEDIUM == fontScale); - displayMenu->AppendRadioItem(wxID_DISPLAY_BASE + 2, "Text Size: 2.0x")->Check(GLFont::GLFONT_SCALE_LARGE == fontScale); + fontMenu->AppendRadioItem(wxID_DISPLAY_BASE, "Normal")->Check(GLFont::GLFONT_SCALE_NORMAL == fontScale); + fontMenu->AppendRadioItem(wxID_DISPLAY_BASE + 1, "1.5x")->Check(GLFont::GLFONT_SCALE_MEDIUM == fontScale); + fontMenu->AppendRadioItem(wxID_DISPLAY_BASE + 2, "2.0x")->Check(GLFont::GLFONT_SCALE_LARGE == fontScale); + displayMenu->AppendSubMenu(fontMenu, "&Text Size"); + + wxMenu *themeMenu = new wxMenu; + + int themeId = wxGetApp().getConfig()->getTheme(); + + themeMenu->AppendRadioItem(wxID_THEME_DEFAULT, "Default")->Check(themeId==COLOR_THEME_DEFAULT); + themeMenu->AppendRadioItem(wxID_THEME_RADAR, "RADAR")->Check(themeId==COLOR_THEME_RADAR); + themeMenu->AppendRadioItem(wxID_THEME_BW, "Black & White")->Check(themeId==COLOR_THEME_BW); + themeMenu->AppendRadioItem(wxID_THEME_SHARP, "Sharp")->Check(themeId==COLOR_THEME_SHARP); + themeMenu->AppendRadioItem(wxID_THEME_RAD, "Rad")->Check(themeId==COLOR_THEME_RAD); + themeMenu->AppendRadioItem(wxID_THEME_TOUCH, "Touch")->Check(themeId==COLOR_THEME_TOUCH); + themeMenu->AppendRadioItem(wxID_THEME_HD, "HD")->Check(themeId==COLOR_THEME_HD); + + displayMenu->AppendSubMenu(themeMenu, wxT("&Color Scheme")); + + menuBar->Append(displayMenu, wxT("&Display")); + GLFont::setScale((GLFont::GLFontScale)fontScale); #ifdef USE_HAMLIB @@ -721,7 +725,7 @@ void AppFrame::updateDeviceParams() { sampleRateMenuItems[wxID_BANDWIDTH_MANUAL]->Check(true); } - menuBar->Replace(4, newSampleRateMenu, wxT("Sample &Rate")); + menuBar->Replace(3, newSampleRateMenu, wxT("Sample &Rate")); sampleRateMenu = newSampleRateMenu; if (!wxGetApp().getAGCMode()) { From c36ca29111a19f08238156d343a49004679cb275 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Thu, 28 Jul 2016 22:50:02 -0400 Subject: [PATCH 2/2] Move audio out choice to modem props, save modem props collapse state, shift rig menu over --- src/AppConfig.cpp | 17 ++++++- src/AppConfig.h | 5 ++- src/AppFrame.cpp | 84 +++++++++++++++++++++-------------- src/AppFrame.h | 1 + src/ModemProperties.cpp | 98 +++++++++++++++++++++++++++++++++++++---- src/ModemProperties.h | 14 +++++- 6 files changed, 175 insertions(+), 44 deletions(-) diff --git a/src/AppConfig.cpp b/src/AppConfig.cpp index 1fb7d99..39d2f4d 100644 --- a/src/AppConfig.cpp +++ b/src/AppConfig.cpp @@ -289,6 +289,7 @@ AppConfig::AppConfig() : configName("") { centerFreq.store(100000000); waterfallLinesPerSec.store(DEFAULT_WATERFALL_LPS); spectrumAvgSpeed.store(0.65f); + modemPropsCollapsed.store(false); #ifdef USE_HAMLIB rigEnabled.store(false); rigModel.store(1); @@ -342,6 +343,14 @@ bool AppConfig::getWindowMaximized() { return winMax.load(); } +void AppConfig::setModemPropsCollapsed(bool collapse) { + modemPropsCollapsed.store(collapse); +} + +bool AppConfig::getModemPropsCollapsed() { + return modemPropsCollapsed.load(); +} + void AppConfig::setShowTips(bool show) { showTips.store(show); } @@ -468,6 +477,7 @@ bool AppConfig::save() { *window_node->newChild("center_freq") = centerFreq.load(); *window_node->newChild("waterfall_lps") = waterfallLinesPerSec.load(); *window_node->newChild("spectrum_avg") = spectrumAvgSpeed.load(); + *window_node->newChild("modemprops_collapsed") = modemPropsCollapsed.load();; } DataNode *devices_node = cfg.rootNode()->newChild("devices"); @@ -547,7 +557,7 @@ bool AppConfig::load() { if (cfg.rootNode()->hasAnother("window")) { int x,y,w,h; - int max,tips,lpm; + int max,tips,lpm,mpc; DataNode *win_node = cfg.rootNode()->getNext("window"); @@ -613,6 +623,11 @@ bool AppConfig::load() { win_node->getNext("spectrum_avg")->element()->get(avgVal); spectrumAvgSpeed.store(avgVal); } + + if (win_node->hasAnother("modemprops_collapsed")) { + win_node->getNext("modemprops_collapsed")->element()->get(mpc); + modemPropsCollapsed.store(mpc?true:false); + } } if (cfg.rootNode()->hasAnother("devices")) { diff --git a/src/AppConfig.h b/src/AppConfig.h index fdc4a24..96570aa 100644 --- a/src/AppConfig.h +++ b/src/AppConfig.h @@ -85,6 +85,9 @@ public: void setWindowMaximized(bool max); bool getWindowMaximized(); + void setModemPropsCollapsed(bool collapse); + bool getModemPropsCollapsed(); + void setShowTips(bool show); bool getShowTips(); @@ -148,7 +151,7 @@ private: std::string configName; std::map deviceConfig; std::atomic_int winX,winY,winW,winH; - std::atomic_bool winMax, showTips, lowPerfMode; + std::atomic_bool winMax, showTips, lowPerfMode, modemPropsCollapsed; std::atomic_int themeId; std::atomic_int fontScale; std::atomic_llong snap; diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index b05bebd..7538e54 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -42,6 +42,8 @@ wxEND_EVENT_TABLE() #include "RigThread.h" #endif +#define APPFRAME_MODEMPROPS_SIZE 240 + AppFrame::AppFrame() : wxFrame(NULL, wxID_ANY, CUBICSDR_TITLE), activeDemodulator(NULL) { @@ -110,8 +112,8 @@ AppFrame::AppFrame() : modemPropertiesUpdated.store(false); modemProps = new ModemProperties(demodPanel, wxID_ANY); - modemProps->SetMinSize(wxSize(200,-1)); - modemProps->SetMaxSize(wxSize(200,-1)); + modemProps->SetMinSize(wxSize(APPFRAME_MODEMPROPS_SIZE,-1)); + modemProps->SetMaxSize(wxSize(APPFRAME_MODEMPROPS_SIZE,-1)); modemProps->Hide(); demodTray->Add(modemProps, 15, wxEXPAND | wxALL, 0); @@ -367,17 +369,17 @@ AppFrame::AppFrame() : } i++; } - - for (mdevices_i = outputDevices.begin(); mdevices_i != outputDevices.end(); mdevices_i++) { - wxMenuItem *itm = menu->AppendRadioItem(wxID_RT_AUDIO_DEVICE + mdevices_i->first, mdevices_i->second.name, wxT("Description?")); - itm->SetId(wxID_RT_AUDIO_DEVICE + mdevices_i->first); - if (mdevices_i->second.isDefaultOutput) { - itm->Check(true); - } - outputDeviceMenuItems[mdevices_i->first] = itm; - } - - menuBar->Append(menu, wxT("Audio &Output")); +// +// for (mdevices_i = outputDevices.begin(); mdevices_i != outputDevices.end(); mdevices_i++) { +// wxMenuItem *itm = menu->AppendRadioItem(wxID_RT_AUDIO_DEVICE + mdevices_i->first, mdevices_i->second.name, wxT("Description?")); +// itm->SetId(wxID_RT_AUDIO_DEVICE + mdevices_i->first); +// if (mdevices_i->second.isDefaultOutput) { +// itm->Check(true); +// } +// outputDeviceMenuItems[mdevices_i->first] = itm; +// } +// +// menuBar->Append(menu, wxT("Audio &Output")); sampleRateMenu = new wxMenu; menuBar->Append(sampleRateMenu, wxT("Sample &Rate")); @@ -460,8 +462,6 @@ AppFrame::AppFrame() : displayMenu->AppendSubMenu(themeMenu, wxT("&Color Scheme")); - menuBar->Append(displayMenu, wxT("&Display")); - GLFont::setScale((GLFont::GLFontScale)fontScale); #ifdef USE_HAMLIB @@ -543,7 +543,9 @@ AppFrame::AppFrame() : menuBar->Append(rigMenu, wxT("&Rig Control")); #endif - + + menuBar->Append(displayMenu, wxT("&Display")); + SetMenuBar(menuBar); CreateStatusBar(); @@ -578,6 +580,12 @@ AppFrame::AppFrame() : ThemeMgr::mgr.setTheme(wxGetApp().getConfig()->getTheme()); + int mpc =wxGetApp().getConfig()->getModemPropsCollapsed(); + + if (mpc) { + modemProps->setCollapsed(true); + } + Show(); #ifdef _WIN32 @@ -725,7 +733,7 @@ void AppFrame::updateDeviceParams() { sampleRateMenuItems[wxID_BANDWIDTH_MANUAL]->Check(true); } - menuBar->Replace(3, newSampleRateMenu, wxT("Sample &Rate")); + menuBar->Replace(2, newSampleRateMenu, wxT("Sample &Rate")); sampleRateMenu = newSampleRateMenu; if (!wxGetApp().getAGCMode()) { @@ -796,19 +804,23 @@ void AppFrame::disableRig() { void AppFrame::OnMenu(wxCommandEvent& event) { - if (event.GetId() >= wxID_RT_AUDIO_DEVICE && event.GetId() < wxID_RT_AUDIO_DEVICE + (int)devices.size()) { - if (activeDemodulator) { - activeDemodulator->setOutputDevice(event.GetId() - wxID_RT_AUDIO_DEVICE); - activeDemodulator = NULL; - } - } +// if (event.GetId() >= wxID_RT_AUDIO_DEVICE && event.GetId() < wxID_RT_AUDIO_DEVICE + (int)devices.size()) { +// if (activeDemodulator) { +// activeDemodulator->setOutputDevice(event.GetId() - wxID_RT_AUDIO_DEVICE); +// activeDemodulator = NULL; +// } +// return; +// } + #ifdef __APPLE__ - else if (event.GetId() == wxApp::s_macAboutMenuItemId) { + if (event.GetId() == wxApp::s_macAboutMenuItemId) { wxMessageDialog *aboutDlg = new wxMessageDialog(NULL, wxT("CubicSDR v" CUBICSDR_VERSION "\nby Charles J. Cliffe (@ccliffe)\nwww.cubicsdr.com"), wxT("CubicSDR v" CUBICSDR_VERSION), wxOK); aboutDlg->ShowModal(); + return; } #endif - else if (event.GetId() == wxID_SDR_START_STOP) { + + if (event.GetId() == wxID_SDR_START_STOP) { if (!wxGetApp().getSDRThread()->isTerminated()) { wxGetApp().stopDevice(true, 2000); } else { @@ -1204,6 +1216,7 @@ void AppFrame::OnClose(wxCloseEvent& event) { wxGetApp().getConfig()->setSpectrumAvgSpeed(wxGetApp().getSpectrumProcessor()->getFFTAverageRate()); wxGetApp().getConfig()->setWaterfallLinesPerSec(waterfallDataThread->getLinesPerSecond()); wxGetApp().getConfig()->setManualDevices(SDREnumerator::getManuals()); + wxGetApp().getConfig()->setModemPropsCollapsed(modemProps->isCollapsed()); #ifdef USE_HAMLIB wxGetApp().getConfig()->setRigEnabled(rigEnableMenuItem->IsChecked()); wxGetApp().getConfig()->setRigModel(rigModel); @@ -1263,7 +1276,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) { wxGetApp().getDemodMgr().setLastGain(demod->getGain()); int outputDevice = demod->getOutputDevice(); scopeCanvas->setDeviceName(outputDevices[outputDevice].name); - outputDeviceMenuItems[outputDevice]->Check(true); +// outputDeviceMenuItems[outputDevice]->Check(true); std::string dType = demod->getDemodulatorType(); demodModeSelector->setSelection(dType); #ifdef ENABLE_DIGITAL_LAB @@ -1504,7 +1517,7 @@ void AppFrame::OnIdle(wxIdleEvent& event) { //reset notification flag modemPropertiesUpdated.store(false); - modemProps->initProperties(demod->getModemArgs()); + modemProps->initProperties(demod->getModemArgs(), demod); demodTray->Layout(); modemProps->fitColumns(); @@ -1517,17 +1530,20 @@ void AppFrame::OnIdle(wxIdleEvent& event) { } demod->showOutput(); } -#endif +#endif + } else if (!demod) { + modemProps->Hide(); + demodTray->Layout(); } - if (modemProps->isCollapsed() && modemProps->GetMinWidth() > 22) { + if (modemProps->IsShown() && modemProps->isCollapsed() && modemProps->GetMinWidth() > 22) { modemProps->SetMinSize(wxSize(22,-1)); modemProps->SetMaxSize(wxSize(22,-1)); demodTray->Layout(); modemProps->fitColumns(); - } else if (!modemProps->isCollapsed() && modemProps->GetMinWidth() < 200) { - modemProps->SetMinSize(wxSize(200,-1)); - modemProps->SetMaxSize(wxSize(200,-1)); + } else if (modemProps->IsShown() && !modemProps->isCollapsed() && modemProps->GetMinWidth() < 200) { + modemProps->SetMinSize(wxSize(APPFRAME_MODEMPROPS_SIZE,-1)); + modemProps->SetMaxSize(wxSize(APPFRAME_MODEMPROPS_SIZE,-1)); demodTray->Layout(); modemProps->fitColumns(); } @@ -1893,6 +1909,10 @@ void AppFrame::setMainWaterfallFFTSize(int fftSize) { waterfallCanvas->setFFTSize(fftSize); } +void AppFrame::setScopeDeviceName(std::string deviceName) { + scopeCanvas->setDeviceName(deviceName); +} + void AppFrame::refreshGainUI() { gainCanvas->updateGainUI(); diff --git a/src/AppFrame.h b/src/AppFrame.h index 991b37a..aedc53c 100644 --- a/src/AppFrame.h +++ b/src/AppFrame.h @@ -85,6 +85,7 @@ public: void notifyUpdateModemProperties(); void setMainWaterfallFFTSize(int fftSize); + void setScopeDeviceName(std::string deviceName); void gkNudgeLeft(DemodulatorInstance *demod, int snap); void gkNudgeRight(DemodulatorInstance *demod, int snap); diff --git a/src/ModemProperties.cpp b/src/ModemProperties.cpp index 981f479..cd490e9 100644 --- a/src/ModemProperties.cpp +++ b/src/ModemProperties.cpp @@ -66,20 +66,72 @@ ModemProperties::~ModemProperties() { } -void ModemProperties::initProperties(ModemArgInfoList newArgs) { - args = newArgs; +void ModemProperties::initDefaultProperties() { + + if (!audioOutputDevices.size()) { + std::vector outputOpts; + std::vector outputOptNames; + + AudioThread::enumerateDevices(audioDevices); + + int i = 0; + + for (auto aDev : audioDevices) { + if (aDev.inputChannels) { + audioInputDevices[i] = aDev; + } + if (aDev.outputChannels) { + audioOutputDevices[i] = aDev; + } + i++; + } + + int defaultDevice = 0; + int dc = 0; + + for (auto mdevices_i : audioOutputDevices) { + outputOpts.push_back(std::to_string(mdevices_i.first)); + outputOptNames.push_back(mdevices_i.second.name); + + if (mdevices_i.second.isDefaultOutput) { + defaultDevice = dc; + } + dc++; + } + + outputArg.key ="._audio_output"; + outputArg.name = "Audio Out"; + outputArg.description = "Set the current modem's audio output device."; + outputArg.type = ModemArgInfo::STRING; + outputArg.options = outputOpts; + outputArg.optionNames = outputOptNames; + } + + int currentOutput = demodContext->getOutputDevice(); + + outputArg.value = std::to_string(currentOutput); + + defaultProps["._audio_output"] = addArgInfoProperty(m_propertyGrid, outputArg); +} + +void ModemProperties::initProperties(ModemArgInfoList newArgs, DemodulatorInstance *demodInstance) { + args = newArgs; + demodContext = demodInstance; + bSizer->Layout(); m_propertyGrid->Clear(); - if (newArgs.size() == 0) { + if (!demodInstance) { Hide(); return; } else { Show(); } - m_propertyGrid->Append(new wxPropertyCategory("Modem Settings")); + m_propertyGrid->Append(new wxPropertyCategory(demodInstance->getDemodulatorType() + " Settings")); + + initDefaultProperties(); ModemArgInfoList::const_iterator args_i; @@ -161,7 +213,7 @@ wxPGProperty *ModemProperties::addArgInfoProperty(wxPropertyGrid *pg, ModemArgIn } if (prop != NULL) { - prop->SetHelpString(arg.key + ": " + arg.description); + prop->SetHelpString(arg.name + ": " + arg.description); } return prop; @@ -191,18 +243,35 @@ std::string ModemProperties::readProperty(std::string key) { } void ModemProperties::OnChange(wxPropertyGridEvent &event) { - DemodulatorInstance *inst = wxGetApp().getDemodMgr().getLastActiveDemodulator(); - - if (!inst) { + if (!demodContext || !demodContext->isActive()) { return; } std::map::const_iterator prop_i; + + if (event.m_property == defaultProps["._audio_output"]) { + int sel = event.m_property->GetChoiceSelection(); + + outputArg.value = outputArg.options[sel]; + + if (demodContext) { + try { + demodContext->setOutputDevice(std::stoi(outputArg.value)); + } catch (exception e) { + // .. this should never happen ;) + } + + wxGetApp().getAppFrame()->setScopeDeviceName(outputArg.optionNames[sel]); + } + + return; + } + for (prop_i = props.begin(); prop_i != props.end(); prop_i++) { if (prop_i->second == event.m_property) { std::string key = prop_i->first; std::string value = readProperty(prop_i->first); - inst->writeModemSetting(key, value); + demodContext->writeModemSetting(key, value); return; } } @@ -228,6 +297,17 @@ bool ModemProperties::isMouseInView() { return mouseInView || (m_propertyGrid && m_propertyGrid->IsEditorFocused()); } +void ModemProperties::setCollapsed(bool state) { + collapsed = state; + if (m_propertyGrid) { + if (state) { + m_propertyGrid->CollapseAll(); + } else { + m_propertyGrid->ExpandAll(); + } + } +} + bool ModemProperties::isCollapsed() { return collapsed; } diff --git a/src/ModemProperties.h b/src/ModemProperties.h index 2f1efc9..bfebcde 100644 --- a/src/ModemProperties.h +++ b/src/ModemProperties.h @@ -5,6 +5,7 @@ #include #include +#include "DemodulatorInstance.h" #include "Modem.h" class ModemProperties : public wxPanel { @@ -19,8 +20,10 @@ public: ); ~ModemProperties(); - void initProperties(ModemArgInfoList newArgs); + void initDefaultProperties(); + void initProperties(ModemArgInfoList newArgs, DemodulatorInstance *demodInstance); bool isMouseInView(); + void setCollapsed(bool state); bool isCollapsed(); void fitColumns(); @@ -40,6 +43,15 @@ private: wxBoxSizer* bSizer; wxPropertyGrid* m_propertyGrid; ModemArgInfoList args; + DemodulatorInstance *demodContext; std::map props; bool mouseInView, collapsed; + + ModemArgInfoList defaultArgs; + ModemArgInfo outputArg; + std::map defaultProps; + + std::vector audioDevices; + std::map audioInputDevices; + std::map audioOutputDevices; }; \ No newline at end of file