From e04ec9ef37b4580579f4e65dccd4ea5fb3a7e532 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Mon, 2 Nov 2015 19:02:45 -0500 Subject: [PATCH 1/7] Remove built-in RTLSDR settings to prepare for replacements, Device form propgrid test --- CMakeLists.txt | 16 + src/AppConfig.cpp | 46 -- src/AppConfig.h | 9 +- src/AppFrame.cpp | 39 +- src/AppFrame.h | 2 +- src/CubicSDR.cpp | 27 +- src/CubicSDR.h | 7 - src/forms/SDRDevices/SDRDevices.cpp | 24 + src/forms/SDRDevices/SDRDevices.fbp | 569 ++++++++---------------- src/forms/SDRDevices/SDRDevicesForm.cpp | 37 +- src/forms/SDRDevices/SDRDevicesForm.h | 15 +- src/sdr/SDREnumerator.cpp | 37 +- src/sdr/SoapySDRThread.cpp | 47 -- src/sdr/SoapySDRThread.h | 14 +- 14 files changed, 278 insertions(+), 611 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c8a33991..282b8907 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -425,6 +425,10 @@ IF (APPLE AND BUNDLE_APP) PROJECT(CubicSDR) SET(MACOSX_BUNDLE_BUNDLE_NAME CubicSDR) + set(BUNDLE_SOAPY_MODS OFF CACHE BOOL "Bundle local SoapySDR modules") + + + ADD_DEFINITIONS( -std=c++0x -pthread @@ -491,6 +495,18 @@ IF (APPLE AND BUNDLE_APP) VERIFY_APP(\"${APPS}\") " COMPONENT Runtime) + # IF (BUNDLE_SOAPY_MODS) + # install( DIRECTORY "${SOAPY_SDR_ROOT}/lib/modules" + # DESTINATION ${APPS}/modules + # COMPONENT Runtime + # FILES_MATCHING + # PATTERN "*.dylib" + # PATTERN "*_debug.dylib" EXCLUDE + # ) + # ENDIF(BUNDLE_SOAPY_MODS) + + + INSTALL(TARGETS CubicSDR BUNDLE DESTINATION . COMPONENT Runtime ) diff --git a/src/AppConfig.cpp b/src/AppConfig.cpp index f1a716d4..4d2a360f 100644 --- a/src/AppConfig.cpp +++ b/src/AppConfig.cpp @@ -2,9 +2,7 @@ #include "CubicSDR.h" DeviceConfig::DeviceConfig() : deviceId("") { - iqSwap.store(0); ppm.store(0); - directSampling.store(false); offset.store(0); } @@ -20,14 +18,6 @@ int DeviceConfig::getPPM() { return ppm.load(); } -void DeviceConfig::setDirectSampling(int mode) { - directSampling.store(mode); -} - -int DeviceConfig::getDirectSampling() { - return directSampling.load(); -} - void DeviceConfig::setOffset(long long offset) { this->offset.store(offset); } @@ -36,14 +26,6 @@ long long DeviceConfig::getOffset() { return offset.load(); } -void DeviceConfig::setIQSwap(bool iqSwap) { - this->iqSwap.store(iqSwap); -} - -bool DeviceConfig::getIQSwap() { - return iqSwap.load(); -} - void DeviceConfig::setDeviceId(std::string deviceId) { busy_lock.lock(); this->deviceId = deviceId; @@ -64,8 +46,6 @@ void DeviceConfig::save(DataNode *node) { busy_lock.lock(); *node->newChild("id") = deviceId; *node->newChild("ppm") = (int)ppm; - *node->newChild("iq_swap") = iqSwap; - *node->newChild("direct_sampling") = directSampling; *node->newChild("offset") = offset; busy_lock.unlock(); } @@ -79,32 +59,6 @@ void DeviceConfig::load(DataNode *node) { setPPM(ppmValue); std::cout << "Loaded PPM for device '" << deviceId << "' at " << ppmValue << "ppm" << std::endl; } - if (node->hasAnother("iq_swap")) { - DataNode *iq_swap_node = node->getNext("iq_swap"); - int iqSwapValue = 0; - iq_swap_node->element()->get(iqSwapValue); - setIQSwap(iqSwapValue?true:false); - std::cout << "Loaded I/Q Swap for device '" << deviceId << "' as " << (iqSwapValue?"swapped":"not swapped") << std::endl; - } - if (node->hasAnother("direct_sampling")) { - DataNode *direct_sampling_node = node->getNext("direct_sampling"); - int directSamplingValue = 0; - direct_sampling_node->element()->get(directSamplingValue); - setDirectSampling(directSamplingValue); - std::cout << "Loaded Direct Sampling Mode for device '" << deviceId << "': "; - switch (directSamplingValue) { - case 0: - std::cout << "off" << std::endl; - break; - case 1: - std::cout << "I-ADC" << std::endl; - break; - case 2: - std::cout << "Q-ADC" << std::endl; - break; - - } - } if (node->hasAnother("offset")) { DataNode *offset_node = node->getNext("offset"); long long offsetValue = 0; diff --git a/src/AppConfig.h b/src/AppConfig.h index 60de0c7b..a7daebb8 100644 --- a/src/AppConfig.h +++ b/src/AppConfig.h @@ -17,15 +17,9 @@ class DeviceConfig { void setPPM(int ppm); int getPPM(); - void setDirectSampling(int mode); - int getDirectSampling(); - void setOffset(long long offset); long long getOffset(); - void setIQSwap(bool iqSwap); - bool getIQSwap(); - void setDeviceId(std::string deviceId); std::string getDeviceId(); @@ -36,8 +30,7 @@ class DeviceConfig { std::string deviceId; std::mutex busy_lock; - std::atomic_int ppm, directSampling; - std::atomic_bool iqSwap; + std::atomic_int ppm; std::atomic_llong offset; }; diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index ad5f82a2..80aebb0c 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -258,16 +258,7 @@ AppFrame::AppFrame() : menu->Append(wxID_SET_FREQ_OFFSET, "Frequency Offset"); menu->Append(wxID_SET_PPM, "Device PPM"); - iqSwapMenuItem = menu->AppendCheckItem(wxID_SET_SWAP_IQ, "Swap I/Q"); - wxMenu *dsMenu = new wxMenu; - - directSamplingMenuItems[0] = dsMenu->AppendRadioItem(wxID_SET_DS_OFF, "Off"); - directSamplingMenuItems[1] = dsMenu->AppendRadioItem(wxID_SET_DS_I, "I-ADC"); - directSamplingMenuItems[2] = dsMenu->AppendRadioItem(wxID_SET_DS_Q, "Q-ADC"); - - menu->AppendSubMenu(dsMenu, "Direct Sampling"); - agcMenuItem = menu->AppendCheckItem(wxID_AGC_CONTROL, "Automatic Gain"); agcMenuItem->Check(wxGetApp().getAGCMode()); @@ -434,16 +425,6 @@ void AppFrame::initDeviceParams(SDRDeviceInfo *devInfo) { DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(deviceId); - int dsMode = devConfig->getDirectSampling(); - - if (dsMode > 0 && dsMode <= 2) { - directSamplingMenuItems[devConfig->getDirectSampling()]->Check(); - } - - if (devConfig->getIQSwap()) { - iqSwapMenuItem->Check(); - } - // Build sample rate menu from device info sampleRates = devInfo->getRxChannel()->getSampleRates(); @@ -503,19 +484,19 @@ void AppFrame::OnMenu(wxCommandEvent& event) { wxGetApp().saveConfig(); } } else if (event.GetId() == wxID_SET_DS_OFF) { - wxGetApp().setDirectSampling(0); - wxGetApp().saveConfig(); +// wxGetApp().setDirectSampling(0); +// wxGetApp().saveConfig(); } else if (event.GetId() == wxID_SET_DS_I) { - wxGetApp().setDirectSampling(1); - wxGetApp().saveConfig(); +// wxGetApp().setDirectSampling(1); +// wxGetApp().saveConfig(); } else if (event.GetId() == wxID_SET_DS_Q) { - wxGetApp().setDirectSampling(2); - wxGetApp().saveConfig(); +// wxGetApp().setDirectSampling(2); +// wxGetApp().saveConfig(); } else if (event.GetId() == wxID_SET_SWAP_IQ) { - bool swap_state = !wxGetApp().getSwapIQ(); - wxGetApp().setSwapIQ(swap_state); - wxGetApp().saveConfig(); - iqSwapMenuItem->Check(swap_state); +// bool swap_state = !wxGetApp().getSwapIQ(); +// wxGetApp().setSwapIQ(swap_state); +// wxGetApp().saveConfig(); +// iqSwapMenuItem->Check(swap_state); } else if (event.GetId() == wxID_AGC_CONTROL) { if (wxGetApp().getDevice() == NULL) { agcMenuItem->Check(); diff --git a/src/AppFrame.h b/src/AppFrame.h index 28e55893..164cde94 100644 --- a/src/AppFrame.h +++ b/src/AppFrame.h @@ -100,7 +100,7 @@ class AppFrame: public wxFrame { std::map sampleRateMenuItems; std::map audioSampleRateMenuItems; std::map directSamplingMenuItems; - wxMenuItem *iqSwapMenuItem; +// wxMenuItem *iqSwapMenuItem; wxMenu *sampleRateMenu; wxMenuItem *agcMenuItem; std::vector sampleRates; diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index b7d471e2..c93f45e2 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -112,7 +112,7 @@ long long strToFrequency(std::string freqStr) { } -CubicSDR::CubicSDR() : appframe(NULL), m_glContext(NULL), frequency(0), offset(0), ppm(0), snap(1), sampleRate(DEFAULT_SAMPLE_RATE), directSamplingMode(0), +CubicSDR::CubicSDR() : appframe(NULL), m_glContext(NULL), frequency(0), offset(0), ppm(0), snap(1), sampleRate(DEFAULT_SAMPLE_RATE), sdrThread(NULL), sdrPostThread(NULL), spectrumVisualThread(NULL), demodVisualThread(NULL), pipeSDRIQData(NULL), pipeIQVisualData(NULL), pipeAudioVisualData(NULL), t_SDR(NULL), t_PostSDR(NULL) { sampleRateInitialized.store(false); agcMode.store(true); @@ -141,7 +141,6 @@ bool CubicSDR::OnInit() { frequency = wxGetApp().getConfig()->getCenterFreq(); offset = 0; ppm = 0; - directSamplingMode = 0; devicesReady.store(false); deviceSelectorOpen.store(false); @@ -351,28 +350,6 @@ void CubicSDR::setOffset(long long ofs) { config.getDevice(dev->getDeviceId())->setOffset(ofs); } -void CubicSDR::setDirectSampling(int mode) { - directSamplingMode = mode; - sdrThread->setDirectSampling(mode); - - SDRDeviceInfo *dev = getDevice(); - config.getDevice(dev->getDeviceId())->setDirectSampling(mode); -} - -int CubicSDR::getDirectSampling() { - return directSamplingMode; -} - -void CubicSDR::setSwapIQ(bool swapIQ) { - sdrThread->setIQSwap(swapIQ); - SDRDeviceInfo *dev = getDevice(); - config.getDevice(dev->getDeviceId())->setIQSwap(swapIQ); -} - -bool CubicSDR::getSwapIQ() { - return sdrThread->getIQSwap(); -} - long long CubicSDR::getFrequency() { return frequency; } @@ -441,8 +418,6 @@ void CubicSDR::setDevice(SDRDeviceInfo *dev) { setSampleRate(sampleRate); setPPM(devConfig->getPPM()); - setDirectSampling(devConfig->getDirectSampling()); - setSwapIQ(devConfig->getIQSwap()); setOffset(devConfig->getOffset()); t_SDR = new std::thread(&SDRThread::threadMain, sdrThread); diff --git a/src/CubicSDR.h b/src/CubicSDR.h index bbacf87b..598b7672 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -58,12 +58,6 @@ class CubicSDR: public wxApp { void setOffset(long long ofs); long long getOffset(); - void setDirectSampling(int mode); - int getDirectSampling(); - - void setSwapIQ(bool swapIQ); - bool getSwapIQ(); - void setSampleRate(long long rate_in); long long getSampleRate(); @@ -126,7 +120,6 @@ class CubicSDR: public wxApp { long long offset; int ppm, snap; long long sampleRate; - int directSamplingMode; std::atomic_bool agcMode; SDRThread *sdrThread; diff --git a/src/forms/SDRDevices/SDRDevices.cpp b/src/forms/SDRDevices/SDRDevices.cpp index 7eed3fec..25501c61 100644 --- a/src/forms/SDRDevices/SDRDevices.cpp +++ b/src/forms/SDRDevices/SDRDevices.cpp @@ -10,6 +10,30 @@ SDRDevicesDialog::SDRDevicesDialog( wxWindow* parent ): devFrame( parent ) { m_addRemoteButton->Disable(); m_useSelectedButton->Disable(); m_deviceTimer.Start(250); + + + // Add int property + m_propertyGrid->Append( new wxIntProperty("IntProperty", wxPG_LABEL, 12345678) ); + // Add float property (value type is actually double) + m_propertyGrid->Append( new wxFloatProperty("FloatProperty", wxPG_LABEL, 12345.678) ); + // Add a bool property + m_propertyGrid->Append( new wxBoolProperty("BoolProperty", wxPG_LABEL, false) ); + // A string property that can be edited in a separate editor dialog. + m_propertyGrid->Append( new wxLongStringProperty("LongStringProperty", + wxPG_LABEL, + "This is much longer string than the " + "first one. Edit it by clicking the button.")); + // String editor with dir selector button. + m_propertyGrid->Append( new wxDirProperty("DirProperty", wxPG_LABEL, ::wxGetUserHome()) ); + // wxArrayStringProperty embeds a wxArrayString. + m_propertyGrid->Append( new wxArrayStringProperty("Label of ArrayStringProperty", + "NameOfArrayStringProp")); + // A file selector property. + m_propertyGrid->Append( new wxFileProperty("FileProperty", wxPG_LABEL, wxEmptyString) ); + // Extra: set wild card for file property (format same as in wxFileDialog). + m_propertyGrid->SetPropertyAttribute( "FileProperty", + wxPG_FILE_WILDCARD, + "All files (*.*)|*.*" ); } void SDRDevicesDialog::OnClose( wxCloseEvent& event ) { diff --git a/src/forms/SDRDevices/SDRDevices.fbp b/src/forms/SDRDevices/SDRDevices.fbp index 362fade1..1bd7999e 100644 --- a/src/forms/SDRDevices/SDRDevices.fbp +++ b/src/forms/SDRDevices/SDRDevices.fbp @@ -44,7 +44,7 @@ devFrame - 392,467 + 700,467 wxDEFAULT_FRAME_STYLE CubicSDR :: SDR Devices @@ -490,11 +490,11 @@ bSizer5 wxHORIZONTAL none - + 5 wxALL 1 - + 1 1 1 @@ -578,11 +578,11 @@ - + 5 wxALL|wxALIGN_CENTER_VERTICAL 1 - + 1 1 1 @@ -674,9 +674,9 @@ 5 - wxEXPAND + wxEXPAND | wxALL 1 - + 1 1 1 @@ -687,7 +687,6 @@ - 1 0 @@ -700,10 +699,10 @@ Left 1 - 0 + 1 0 - 1 + 0 wxID_ANY 0 @@ -712,7 +711,7 @@ 0 1 - devTabs + m_panel61 1 @@ -722,13 +721,12 @@ Resizable 1 - 0 - + wxTAB_TRAVERSAL @@ -745,8 +743,6 @@ - - @@ -754,385 +750,178 @@ - - - Device - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 0 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - - 1 - devInfoPanel - 1 - - - protected - 1 - - Resizable - 1 - - - 0 - - - - wxTAB_TRAVERSAL - - - - - - - - - - - - - - - - - - - - - - - - + + + bSizer7 + wxVERTICAL + none + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Stream Options + + 0 + + + 0 - devInfoSizer - wxVERTICAL - none - - 5 - wxEXPAND - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - - 1 - m_DevInfoList - 1 - - - protected - 1 - - Resizable - 1 - - wxLC_ICON - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + 1 + m_staticText1 + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + - - - - Parameters - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - - 1 - devParamsPanel - 1 - - - protected - 1 - - Resizable - 1 - - - 0 - - - - wxTAB_TRAVERSAL - - - - - - - - - - - - - - - - - - - - - - - - + + 5 + wxALL|wxEXPAND + 1 + + 1 + 1 + 1 + 1 + + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + + 1 + + 0 + 0 + wxID_ANY + 1 + + 0 + + + 0 - devParamsSizer - wxVERTICAL - none - - 5 - wxEXPAND - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - - 1 - m_ParamInfoList - 1 - - - protected - 1 - - Resizable - 1 - - wxLC_ICON - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + 1 + m_propertyGrid + 1 + + + protected + 1 + + Resizable + 1 + + wxPG_DEFAULT_STYLE + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/forms/SDRDevices/SDRDevicesForm.cpp b/src/forms/SDRDevices/SDRDevicesForm.cpp index 3e1a8138..ba012c93 100644 --- a/src/forms/SDRDevices/SDRDevicesForm.cpp +++ b/src/forms/SDRDevices/SDRDevicesForm.cpp @@ -52,35 +52,22 @@ devFrame::devFrame( wxWindow* parent, wxWindowID id, const wxString& title, cons bSizer6->Fit( m_panel6 ); bSizer4->Add( m_panel6, 1, wxEXPAND | wxALL, 5 ); - devTabs = new wxNotebook( m_panel3, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - devTabs->Hide(); + m_panel61 = new wxPanel( m_panel3, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer7; + bSizer7 = new wxBoxSizer( wxVERTICAL ); - devInfoPanel = new wxPanel( devTabs, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* devInfoSizer; - devInfoSizer = new wxBoxSizer( wxVERTICAL ); + m_staticText1 = new wxStaticText( m_panel61, wxID_ANY, wxT("Stream Options"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText1->Wrap( -1 ); + bSizer7->Add( m_staticText1, 0, wxALL, 5 ); - m_DevInfoList = new wxListCtrl( devInfoPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_ICON ); - devInfoSizer->Add( m_DevInfoList, 1, wxEXPAND, 5 ); + m_propertyGrid = new wxPropertyGrid(m_panel61, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxPG_DEFAULT_STYLE); + bSizer7->Add( m_propertyGrid, 1, wxALL|wxEXPAND, 5 ); - devInfoPanel->SetSizer( devInfoSizer ); - devInfoPanel->Layout(); - devInfoSizer->Fit( devInfoPanel ); - devTabs->AddPage( devInfoPanel, wxT("Device"), false ); - devParamsPanel = new wxPanel( devTabs, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* devParamsSizer; - devParamsSizer = new wxBoxSizer( wxVERTICAL ); - - m_ParamInfoList = new wxListCtrl( devParamsPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_ICON ); - devParamsSizer->Add( m_ParamInfoList, 1, wxEXPAND, 5 ); - - - devParamsPanel->SetSizer( devParamsSizer ); - devParamsPanel->Layout(); - devParamsSizer->Fit( devParamsPanel ); - devTabs->AddPage( devParamsPanel, wxT("Parameters"), false ); - - bSizer4->Add( devTabs, 1, wxEXPAND, 5 ); + m_panel61->SetSizer( bSizer7 ); + m_panel61->Layout(); + bSizer7->Fit( m_panel61 ); + bSizer4->Add( m_panel61, 1, wxEXPAND | wxALL, 5 ); m_panel3->SetSizer( bSizer4 ); diff --git a/src/forms/SDRDevices/SDRDevicesForm.h b/src/forms/SDRDevices/SDRDevicesForm.h index 2857d5c3..efaa3e11 100644 --- a/src/forms/SDRDevices/SDRDevicesForm.h +++ b/src/forms/SDRDevices/SDRDevicesForm.h @@ -20,11 +20,12 @@ #include #include #include -#include +#include #include #include #include -#include +#include +#include #include #include @@ -46,11 +47,9 @@ class devFrame : public wxFrame wxPanel* m_panel4; wxButton* m_addRemoteButton; wxButton* m_useSelectedButton; - wxNotebook* devTabs; - wxPanel* devInfoPanel; - wxListCtrl* m_DevInfoList; - wxPanel* devParamsPanel; - wxListCtrl* m_ParamInfoList; + wxPanel* m_panel61; + wxStaticText* m_staticText1; + wxPropertyGrid* m_propertyGrid; wxTimer m_deviceTimer; // Virtual event handlers, overide them in your derived class @@ -65,7 +64,7 @@ class devFrame : public wxFrame public: - devFrame( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("CubicSDR :: SDR Devices"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 392,467 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL ); + devFrame( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("CubicSDR :: SDR Devices"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 700,467 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL ); ~devFrame(); diff --git a/src/sdr/SDREnumerator.cpp b/src/sdr/SDREnumerator.cpp index 1ea78528..30746d21 100644 --- a/src/sdr/SDREnumerator.cpp +++ b/src/sdr/SDREnumerator.cpp @@ -108,19 +108,6 @@ std::vector *SDREnumerator::enumerate_devices(std::string remot SDRDeviceInfo *dev = new SDRDeviceInfo(); SoapySDR::Kwargs deviceArgs = results[i]; - SoapySDR::Kwargs streamArgs; - - if (isRemote) { - wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Querying remote " + remoteAddr + " device #" + std::to_string(i)); -// deviceArgs["remote"] = remoteAddr; - if (deviceArgs.count("rtl") != 0) { - streamArgs["remote:mtu"] = "8192"; - streamArgs["remote:format"] = "CS8"; - streamArgs["remote:window"] = "16384000"; - } - } else { - wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Found local device #") + std::to_string(i)); - } for (SoapySDR::Kwargs::const_iterator it = deviceArgs.begin(); it != deviceArgs.end(); ++it) { std::cout << " " << it->first << " = " << it->second << std::endl; @@ -132,7 +119,6 @@ std::vector *SDREnumerator::enumerate_devices(std::string remot } dev->setDeviceArgs(deviceArgs); - dev->setStreamArgs(streamArgs); std::cout << "Make device " << i << std::endl; try { @@ -188,6 +174,29 @@ std::vector *SDREnumerator::enumerate_devices(std::string remot dev->addChannel(chan); } + + SoapySDR::Kwargs streamArgs; + + if (isRemote) { + wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Querying remote " + remoteAddr + " device #" + std::to_string(i)); + +// if (deviceArgs.count("rtl") != 0) { +// streamArgs["remote:mtu"] = "8192"; +// streamArgs["remote:window"] = "16384000"; +// } + double fullScale = 0; + std::string nativeFormat = device->getNativeStreamFormat(SOAPY_SDR_RX, dev->getRxChannel()->getChannel(), fullScale); + + if (nativeFormat.length()) { + streamArgs["remote:format"] = nativeFormat; + } + } else { + wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Found local device #") + std::to_string(i)); + } + + dev->setStreamArgs(streamArgs); + + dev->setSettingsInfo(device->getSettingInfo()); SoapySDR::Device::unmake(device); diff --git a/src/sdr/SoapySDRThread.cpp b/src/sdr/SoapySDRThread.cpp index a8b50848..729df437 100644 --- a/src/sdr/SoapySDRThread.cpp +++ b/src/sdr/SoapySDRThread.cpp @@ -15,7 +15,6 @@ SDRThread::SDRThread() : IOThread() { frequency.store(0); offset.store(0); ppm.store(0); - direct_sampling_mode.store(0); numElems.store(0); @@ -23,16 +22,11 @@ SDRThread::SDRThread() : IOThread() { freq_changed.store(false); offset_changed.store(false); ppm_changed .store(false); - direct_sampling_changed.store(false); device_changed.store(false); - iq_swap.store(false); - iq_swap_changed.store(false); hasPPM.store(false); hasHardwareDC.store(false); numChannels.store(8); - hasDirectSampling.store(false); - hasIQSwap.store(false); agc_mode.store(true); agc_mode_changed.store(false); @@ -51,12 +45,6 @@ void SDRThread::init() { ppm.store(devConfig->getPPM()); ppm_changed.store(true); - direct_sampling_mode.store(devConfig->getDirectSampling()); - direct_sampling_changed.store(true); - - iq_swap.store(devConfig->getIQSwap()); - iq_swap_changed.store(true); - std::string driverName = devInfo->getDriver(); offset = devConfig->getOffset(); @@ -85,14 +73,6 @@ void SDRThread::init() { } else { hasHardwareDC.store(false); } - - std::vector settingNames = devInfo->getSettingNames(); - if (std::find(settingNames.begin(), settingNames.end(), "direct_samp") != settingNames.end()) { - hasDirectSampling.store(true); - } - if (std::find(settingNames.begin(), settingNames.end(), "iq_swap") != settingNames.end()) { - hasIQSwap.store(true); - } device->setGainMode(SOAPY_SDR_RX,0,agc_mode.load()); @@ -184,14 +164,6 @@ void SDRThread::readLoop() { device->setFrequency(SOAPY_SDR_RX,0,"RF",frequency.load() - offset.load()); freq_changed.store(false); } - if (hasDirectSampling.load() && direct_sampling_changed.load()) { - device->writeSetting("direct_samp", std::to_string(direct_sampling_mode)); - direct_sampling_changed.store(false); - } - if (hasIQSwap.load() && iq_swap_changed.load()) { - device->writeSetting("iq_swap", iq_swap.load()?"true":"false"); - iq_swap_changed.store(false); - } if (agc_mode_changed.load()) { SDRDeviceInfo *devInfo = deviceInfo.load(); @@ -346,25 +318,6 @@ int SDRThread::getPPM() { return ppm.load(); } -void SDRThread::setDirectSampling(int dsMode) { - direct_sampling_mode.store(dsMode); - direct_sampling_changed.store(true); - std::cout << "Set direct sampling mode: " << this->direct_sampling_mode.load() << std::endl; -} - -int SDRThread::getDirectSampling() { - return direct_sampling_mode.load(); -} - -void SDRThread::setIQSwap(bool iqSwap) { - iq_swap.store(iqSwap); - iq_swap_changed.store(true); -} - -bool SDRThread::getIQSwap() { - return iq_swap.load(); -} - void SDRThread::setAGCMode(bool mode) { agc_mode.store(mode); agc_mode_changed.store(true); diff --git a/src/sdr/SoapySDRThread.h b/src/sdr/SoapySDRThread.h index 1a199de6..8cee44a1 100644 --- a/src/sdr/SoapySDRThread.h +++ b/src/sdr/SoapySDRThread.h @@ -69,12 +69,6 @@ class SDRThread : public IOThread { void setPPM(int ppm); int getPPM(); - void setDirectSampling(int dsMode); - int getDirectSampling(); - - void setIQSwap(bool iqSwap); - bool getIQSwap(); - void setAGCMode(bool mode); bool getAGCMode(); @@ -94,10 +88,10 @@ class SDRThread : public IOThread { std::atomic sampleRate; std::atomic_llong frequency, offset; - std::atomic_int ppm, direct_sampling_mode, numElems, numChannels; - std::atomic_bool hasPPM, hasHardwareDC, hasDirectSampling, hasIQSwap; - std::atomic_bool iq_swap, agc_mode, rate_changed, freq_changed, offset_changed, - ppm_changed, direct_sampling_changed, device_changed, iq_swap_changed, agc_mode_changed, gain_value_changed; + std::atomic_int ppm, numElems, numChannels; + std::atomic_bool hasPPM, hasHardwareDC; + std::atomic_bool agc_mode, rate_changed, freq_changed, offset_changed, + ppm_changed, device_changed, agc_mode_changed, gain_value_changed; std::mutex gain_busy; std::map gainValues; From bcc5f8560f5b2234abea4a38fdd2b16845010fef Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Tue, 3 Nov 2015 00:53:39 -0500 Subject: [PATCH 2/7] Device dialog /w editable SoapySDR config -- not actually applied yet :) --- src/AppFrame.cpp | 22 +--- src/CubicSDR.cpp | 1 + src/forms/SDRDevices/SDRDevices.cpp | 129 +++++++++++++++++++----- src/forms/SDRDevices/SDRDevices.fbp | 2 +- src/forms/SDRDevices/SDRDevices.h | 3 + src/forms/SDRDevices/SDRDevicesForm.cpp | 2 +- 6 files changed, 110 insertions(+), 49 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 58bbe138..9e86fba0 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -196,6 +196,7 @@ AppFrame::AppFrame() : waterfallDataThread->setInputQueue("IQDataInput", wxGetApp().getWaterfallVisualQueue()); waterfallDataThread->setOutputQueue("FFTDataOutput", waterfallCanvas->getVisualDataQueue()); + waterfallDataThread->getProcessor()->setHideDC(true); t_FFTData = new std::thread(&FFTVisualDataThread::threadMain, waterfallDataThread); @@ -636,24 +637,7 @@ void AppFrame::OnMenu(wxCommandEvent& event) { } break; } - -// std::vector *devs = wxGetApp().getDevices(); -// if (event.GetId() >= wxID_DEVICE_ID && event.GetId() <= wxID_DEVICE_ID + devs->size()) { -// int devId = event.GetId() - wxID_DEVICE_ID; -// wxGetApp().setDevice(devId); -// -// SDRDeviceInfo *dev = (*wxGetApp().getDevices())[devId]; -// DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(dev->getDeviceId()); -// -// int dsMode = devConfig->getDirectSampling(); -// -// if (dsMode >= 0 && dsMode <= 2) { -// directSamplingMenuItems[devConfig->getDirectSampling()]->Check(); -// } -// -// iqSwapMenuItem->Check(devConfig->getIQSwap()); -// } - + if (event.GetId() >= wxID_BANDWIDTH_BASE && event.GetId() < wxID_BANDWIDTH_BASE+sampleRates.size()) { wxGetApp().setSampleRate(sampleRates[event.GetId()-wxID_BANDWIDTH_BASE]); } @@ -864,7 +848,6 @@ void AppFrame::OnIdle(wxIdleEvent& event) { // wxGetApp().getSpectrumDistributor()->run(); SpectrumVisualProcessor *proc = wxGetApp().getSpectrumProcessor(); - proc->setHideDC(true); if (spectrumAvgMeter->inputChanged()) { float val = spectrumAvgMeter->getInputValue(); @@ -891,7 +874,6 @@ void AppFrame::OnIdle(wxIdleEvent& event) { dproc->setCenterFrequency(demodWaterfallCanvas->getCenterFrequency()); SpectrumVisualProcessor *wproc = waterfallDataThread->getProcessor(); - wproc->setHideDC(true); if (waterfallSpeedMeter->inputChanged()) { float val = waterfallSpeedMeter->getInputValue(); diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index c93f45e2..986d2137 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -159,6 +159,7 @@ bool CubicSDR::OnInit() { getDemodSpectrumProcessor()->setInput(pipeDemodIQVisualData); getSpectrumProcessor()->setInput(pipeIQVisualData); + getSpectrumProcessor()->setHideDC(true); pipeAudioVisualData = new DemodulatorThreadOutputQueue(); pipeAudioVisualData->set_max_num_items(1); diff --git a/src/forms/SDRDevices/SDRDevices.cpp b/src/forms/SDRDevices/SDRDevices.cpp index 25501c61..a1582012 100644 --- a/src/forms/SDRDevices/SDRDevices.cpp +++ b/src/forms/SDRDevices/SDRDevices.cpp @@ -11,30 +11,7 @@ SDRDevicesDialog::SDRDevicesDialog( wxWindow* parent ): devFrame( parent ) { m_useSelectedButton->Disable(); m_deviceTimer.Start(250); - - // Add int property - m_propertyGrid->Append( new wxIntProperty("IntProperty", wxPG_LABEL, 12345678) ); - // Add float property (value type is actually double) - m_propertyGrid->Append( new wxFloatProperty("FloatProperty", wxPG_LABEL, 12345.678) ); - // Add a bool property - m_propertyGrid->Append( new wxBoolProperty("BoolProperty", wxPG_LABEL, false) ); - // A string property that can be edited in a separate editor dialog. - m_propertyGrid->Append( new wxLongStringProperty("LongStringProperty", - wxPG_LABEL, - "This is much longer string than the " - "first one. Edit it by clicking the button.")); - // String editor with dir selector button. - m_propertyGrid->Append( new wxDirProperty("DirProperty", wxPG_LABEL, ::wxGetUserHome()) ); - // wxArrayStringProperty embeds a wxArrayString. - m_propertyGrid->Append( new wxArrayStringProperty("Label of ArrayStringProperty", - "NameOfArrayStringProp")); - // A file selector property. - m_propertyGrid->Append( new wxFileProperty("FileProperty", wxPG_LABEL, wxEmptyString) ); - // Extra: set wild card for file property (format same as in wxFileDialog). - m_propertyGrid->SetPropertyAttribute( "FileProperty", - wxPG_FILE_WILDCARD, - "All files (*.*)|*.*" ); -} + } void SDRDevicesDialog::OnClose( wxCloseEvent& event ) { wxGetApp().setDeviceSelectorClosed(); @@ -45,7 +22,98 @@ void SDRDevicesDialog::OnDeleteItem( wxTreeEvent& event ) { event.Skip(); } +wxPGProperty *SDRDevicesDialog::addArgInfoProperty(wxPropertyGrid *pg, SoapySDR::ArgInfo arg) { + + wxPGProperty *prop = NULL; + + int intVal; + double floatVal; + std::vector::iterator stringIter; + + switch (arg.type) { + case SoapySDR::ArgInfo::INT: + try { + intVal = std::stoi(arg.value); + } catch (std::invalid_argument e) { + intVal = 0; + } + prop = pg->Append( new wxIntProperty(arg.name, wxPG_LABEL, intVal) ); + if (arg.range.minimum() != arg.range.maximum()) { + pg->SetPropertyAttribute( prop, wxPG_ATTR_MIN, arg.range.minimum()); + pg->SetPropertyAttribute( prop, wxPG_ATTR_MAX, arg.range.maximum()); + } + break; + case SoapySDR::ArgInfo::FLOAT: + try { + floatVal = std::stod(arg.value); + } catch (std::invalid_argument e) { + floatVal = 0; + } + prop = pg->Append( new wxFloatProperty(arg.name, wxPG_LABEL, floatVal) ); + if (arg.range.minimum() != arg.range.maximum()) { + pg->SetPropertyAttribute( prop, wxPG_ATTR_MIN, arg.range.minimum()); + pg->SetPropertyAttribute( prop, wxPG_ATTR_MAX, arg.range.maximum()); + } + break; + case SoapySDR::ArgInfo::BOOL: + prop = pg->Append( new wxBoolProperty(arg.name, wxPG_LABEL, (arg.value=="true")) ); + break; + case SoapySDR::ArgInfo::STRING: + if (arg.options.size()) { + intVal = 0; + prop = pg->Append( new wxEnumProperty(arg.name, wxPG_LABEL) ); + for (stringIter = arg.options.begin(); stringIter != arg.options.end(); stringIter++) { + prop->AddChoice((*stringIter)); + if ((*stringIter)==arg.value) { + prop->SetChoiceSelection(intVal); + } + intVal++; + } + } else { + prop = pg->Append( new wxStringProperty(arg.name, wxPG_LABEL, arg.value) ); + } + break; + } + + if (prop != NULL) { + prop->SetHelpString(arg.key + ": " + arg.description); + } + + return prop; +} + void SDRDevicesDialog::OnSelectionChanged( wxTreeEvent& event ) { + wxTreeItemId selId = devTree->GetSelection(); + + dev = getSelectedDevice(selId); + + if (dev) { + m_propertyGrid->Clear(); + m_propertyGrid->Append(new wxPropertyCategory("Run-time Settings")); + + SoapySDR::ArgInfoList::const_iterator args_i; + + SoapySDR::ArgInfoList args = dev->getSettingsArgInfo(); + + for (args_i = args.begin(); args_i != args.end(); args_i++) { + SoapySDR::ArgInfo arg = (*args_i); + addArgInfoProperty(m_propertyGrid, arg); + } + + if (dev->getRxChannel()) { + args = dev->getRxChannel()->getStreamArgsInfo(); + + if (args.size()) { + m_propertyGrid->Append(new wxPropertyCategory("Stream Settings")); + + for (args_i = args.begin(); args_i != args.end(); args_i++) { + SoapySDR::ArgInfo arg = (*args_i); + addArgInfoProperty(m_propertyGrid, arg); + } + } + } + + } event.Skip(); } @@ -70,12 +138,19 @@ void SDRDevicesDialog::OnAddRemote( wxMouseEvent& event ) { } +SDRDeviceInfo *SDRDevicesDialog::getSelectedDevice(wxTreeItemId selId) { + devItems_i = devItems.find(selId); + if (devItems_i != devItems.end()) { + return devItems[selId]; + } + return NULL; +} + void SDRDevicesDialog::OnUseSelected( wxMouseEvent& event ) { wxTreeItemId selId = devTree->GetSelection(); - devItems_i = devItems.find(selId); - if (devItems_i != devItems.end()) { - dev = devItems[selId]; + dev = getSelectedDevice(selId); + if (dev != NULL) { wxGetApp().setDevice(dev); Close(); } diff --git a/src/forms/SDRDevices/SDRDevices.fbp b/src/forms/SDRDevices/SDRDevices.fbp index 1bd7999e..9d67c3f2 100644 --- a/src/forms/SDRDevices/SDRDevices.fbp +++ b/src/forms/SDRDevices/SDRDevices.fbp @@ -787,7 +787,7 @@ 0 0 wxID_ANY - Stream Options + SoapySDR Device Options 0 diff --git a/src/forms/SDRDevices/SDRDevices.h b/src/forms/SDRDevices/SDRDevices.h index ccd8a774..faa6fac3 100644 --- a/src/forms/SDRDevices/SDRDevices.h +++ b/src/forms/SDRDevices/SDRDevices.h @@ -21,6 +21,9 @@ class SDRDevicesDialog: public devFrame { void OnDeviceTimer( wxTimerEvent& event ); private: + SDRDeviceInfo *getSelectedDevice(wxTreeItemId selId); + wxPGProperty *addArgInfoProperty(wxPropertyGrid *pg, SoapySDR::ArgInfo arg); + bool refresh; std::map* > devs; std::vector::iterator devs_i; diff --git a/src/forms/SDRDevices/SDRDevicesForm.cpp b/src/forms/SDRDevices/SDRDevicesForm.cpp index ba012c93..8863060d 100644 --- a/src/forms/SDRDevices/SDRDevicesForm.cpp +++ b/src/forms/SDRDevices/SDRDevicesForm.cpp @@ -56,7 +56,7 @@ devFrame::devFrame( wxWindow* parent, wxWindowID id, const wxString& title, cons wxBoxSizer* bSizer7; bSizer7 = new wxBoxSizer( wxVERTICAL ); - m_staticText1 = new wxStaticText( m_panel61, wxID_ANY, wxT("Stream Options"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText1 = new wxStaticText( m_panel61, wxID_ANY, wxT("SoapySDR Device Options"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText1->Wrap( -1 ); bSizer7->Add( m_staticText1, 0, wxALL, 5 ); From c7ecc5f1f6869194ea34de8e1d66f2ce825dbff3 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Tue, 3 Nov 2015 19:58:42 -0500 Subject: [PATCH 3/7] Settings now added to settings menu, not yet functional.. - Also possible re-ordering fix for scope visual crash I have occasionally --- src/AppFrame.cpp | 69 ++++++++++++++++++++++++---- src/AppFrame.h | 3 ++ src/forms/SDRDevices/SDRDevices.cpp | 9 +++- src/process/ScopeVisualProcessor.cpp | 22 +++++---- 4 files changed, 82 insertions(+), 21 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 9e86fba0..071d5545 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -255,15 +255,9 @@ AppFrame::AppFrame() : menuBar->Append(menu, wxT("&File")); - menu = new wxMenu; - - menu->Append(wxID_SET_FREQ_OFFSET, "Frequency Offset"); - menu->Append(wxID_SET_PPM, "Device PPM"); - - agcMenuItem = menu->AppendCheckItem(wxID_AGC_CONTROL, "Automatic Gain"); - agcMenuItem->Check(wxGetApp().getAGCMode()); - - menuBar->Append(menu, wxT("&Settings")); + settingsMenu = new wxMenu; + + menuBar->Append(settingsMenu, wxT("&Settings")); menu = new wxMenu; @@ -434,7 +428,62 @@ void AppFrame::updateDeviceParams() { return; } - // Build sample rate menu from device info + + // Build settings menu + wxMenu *newSettingsMenu = new wxMenu; + newSettingsMenu->Append(wxID_SET_FREQ_OFFSET, "Frequency Offset"); + if (devInfo->getRxChannel()->hasCORR()) { + newSettingsMenu->Append(wxID_SET_PPM, "Device PPM"); + } + + agcMenuItem = newSettingsMenu->AppendCheckItem(wxID_AGC_CONTROL, "Automatic Gain"); + agcMenuItem->Check(wxGetApp().getAGCMode()); + + SoapySDR::ArgInfoList args = devInfo->getSettingsArgInfo(); + SoapySDR::ArgInfoList::const_iterator args_i; + + int i = 0; + for (args_i = args.begin(); args_i != args.end(); args_i++) { + SoapySDR::ArgInfo arg = (*args_i); + if (arg.type == SoapySDR::ArgInfo::BOOL) { + wxMenuItem *item = newSettingsMenu->AppendCheckItem(wxID_SETTINGS_BASE+i, arg.name, arg.description); + item->Check(arg.value=="true"); + i++; + } else if (arg.type == SoapySDR::ArgInfo::INT) { + wxMenuItem *item = newSettingsMenu->Append(wxID_SETTINGS_BASE+i, arg.name, arg.description); + i++; + } else if (arg.type == SoapySDR::ArgInfo::FLOAT) { + wxMenuItem *item = newSettingsMenu->Append(wxID_SETTINGS_BASE+i, arg.name, arg.description); + i++; + } else if (arg.type == SoapySDR::ArgInfo::STRING) { + if (arg.options.size()) { + wxMenu *subMenu = new wxMenu; + int j = 0; + for (std::vector::iterator str_i = arg.options.begin(); str_i != arg.options.end(); str_i++) { + std::string optName = (*str_i); + std::string displayName = optName; + if (arg.optionNames.size()) { + displayName = arg.optionNames[j]; + } + wxMenuItem *item = subMenu->AppendRadioItem(wxID_SETTINGS_BASE+i, displayName); + if (arg.value == (*str_i)) { + item->Check(); + } + i++; + j++; + } + newSettingsMenu->AppendSubMenu(subMenu, arg.name, arg.description); + } else { + wxMenuItem *item = newSettingsMenu->Append(wxID_SETTINGS_BASE+i, arg.name, arg.description); + i++; + } + } + } + + menuBar->Replace(1, newSettingsMenu, wxT("&Settings")); + settingsMenu = newSettingsMenu; + + // Build sample rate menu sampleRates = devInfo->getRxChannel()->getSampleRates(); sampleRateMenuItems.erase(sampleRateMenuItems.begin(),sampleRateMenuItems.end()); diff --git a/src/AppFrame.h b/src/AppFrame.h index 596735b7..5f17df44 100644 --- a/src/AppFrame.h +++ b/src/AppFrame.h @@ -45,6 +45,8 @@ #define wxID_BANDWIDTH_BASE 2150 #define wxID_BANDWIDTH_MANUAL 2200 +#define wxID_SETTINGS_BASE 2300 + #define wxID_DEVICE_ID 3500 #define wxID_AUDIO_BANDWIDTH_BASE 9000 @@ -104,6 +106,7 @@ class AppFrame: public wxFrame { wxMenuBar *menuBar; wxMenu *sampleRateMenu; wxMenuItem *agcMenuItem; + wxMenu *settingsMenu; std::vector sampleRates; std::string currentSessionFile; diff --git a/src/forms/SDRDevices/SDRDevices.cpp b/src/forms/SDRDevices/SDRDevices.cpp index a1582012..9595ff69 100644 --- a/src/forms/SDRDevices/SDRDevices.cpp +++ b/src/forms/SDRDevices/SDRDevices.cpp @@ -63,10 +63,17 @@ wxPGProperty *SDRDevicesDialog::addArgInfoProperty(wxPropertyGrid *pg, SoapySDR: intVal = 0; prop = pg->Append( new wxEnumProperty(arg.name, wxPG_LABEL) ); for (stringIter = arg.options.begin(); stringIter != arg.options.end(); stringIter++) { - prop->AddChoice((*stringIter)); + std::string optName = (*stringIter); + std::string displayName = optName; + if (arg.optionNames.size()) { + displayName = arg.optionNames[intVal]; + } + + prop->AddChoice(displayName); if ((*stringIter)==arg.value) { prop->SetChoiceSelection(intVal); } + intVal++; } } else { diff --git a/src/process/ScopeVisualProcessor.cpp b/src/process/ScopeVisualProcessor.cpp index baaf566a..dad6a033 100644 --- a/src/process/ScopeVisualProcessor.cpp +++ b/src/process/ScopeVisualProcessor.cpp @@ -81,7 +81,7 @@ void ScopeVisualProcessor::process() { renderData->channels = audioInputData->channels; renderData->inputRate = audioInputData->inputRate; renderData->sampleRate = audioInputData->sampleRate; - + if (renderData->waveform_points.size() != iMax * 2) { renderData->waveform_points.resize(iMax * 2); } @@ -112,7 +112,6 @@ void ScopeVisualProcessor::process() { } renderData->spectrum = false; - distribute(renderData); } @@ -137,7 +136,14 @@ void ScopeVisualProcessor::process() { } } } + + renderData = outputBuffers.getBuffer(); + renderData->channels = audioInputData->channels; + renderData->inputRate = audioInputData->inputRate; + renderData->sampleRate = audioInputData->sampleRate; + + audioInputData->decRefCount(); fftwf_execute(fftw_plan); @@ -175,12 +181,10 @@ void ScopeVisualProcessor::process() { int outSize = fftSize/2; - if (audioInputData->sampleRate != audioInputData->inputRate) { - outSize = (int)floor((float)outSize * ((float)audioInputData->sampleRate/(float)audioInputData->inputRate)); + if (renderData->sampleRate != renderData->inputRate) { + outSize = (int)floor((float)outSize * ((float)renderData->sampleRate/(float)renderData->inputRate)); } - renderData = outputBuffers.getBuffer(); - if (renderData->waveform_points.size() != outSize*2) { renderData->waveform_points.resize(outSize*2); } @@ -194,12 +198,10 @@ void ScopeVisualProcessor::process() { renderData->fft_floor = fft_floor_maa; renderData->fft_ceil = fft_ceil_maa; renderData->fft_size = fftSize/2; - renderData->inputRate = audioInputData->inputRate; - renderData->sampleRate = audioInputData->sampleRate; renderData->spectrum = true; distribute(renderData); + } else { + audioInputData->decRefCount(); } - - audioInputData->decRefCount(); } } From 97cf6c4b23a4a4a06ddd7f4c57c099b08453d829 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Tue, 3 Nov 2015 21:06:22 -0500 Subject: [PATCH 4/7] SDRThread read/write setting support --- src/CubicSDR.cpp | 10 ++- src/CubicSDR.h | 3 +- src/sdr/SoapySDRThread.cpp | 163 ++++++++++++++++++++++++++----------- src/sdr/SoapySDRThread.h | 14 +++- 4 files changed, 135 insertions(+), 55 deletions(-) diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index 986d2137..db8e0fb2 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -296,6 +296,9 @@ void CubicSDR::removeRemote(std::string remoteAddr) { void CubicSDR::sdrThreadNotify(SDRThread::SDRThreadState state, std::string message) { notify_busy.lock(); + if (state == SDRThread::SDR_THREAD_INITIALIZED) { + appframe->initDeviceParams(getDevice()); + } if (state == SDRThread::SDR_THREAD_MESSAGE) { notifyMessage = message; } @@ -422,8 +425,6 @@ void CubicSDR::setDevice(SDRDeviceInfo *dev) { setOffset(devConfig->getOffset()); t_SDR = new std::thread(&SDRThread::threadMain, sdrThread); - - appframe->initDeviceParams(dev); } } @@ -463,6 +464,11 @@ SDRPostThread *CubicSDR::getSDRPostThread() { return sdrPostThread; } +SDRThread *CubicSDR::getSDRThread() { + return sdrThread; +} + + void CubicSDR::bindDemodulator(DemodulatorInstance *demod) { if (!demod) { return; diff --git a/src/CubicSDR.h b/src/CubicSDR.h index 598b7672..1946660f 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -76,7 +76,8 @@ class CubicSDR: public wxApp { DemodulatorMgr &getDemodMgr(); SDRPostThread *getSDRPostThread(); - + SDRThread *getSDRThread(); + void bindDemodulator(DemodulatorInstance *demod); void removeDemodulator(DemodulatorInstance *demod); diff --git a/src/sdr/SoapySDRThread.cpp b/src/sdr/SoapySDRThread.cpp index 729df437..75020741 100644 --- a/src/sdr/SoapySDRThread.cpp +++ b/src/sdr/SoapySDRThread.cpp @@ -31,6 +31,7 @@ SDRThread::SDRThread() : IOThread() { agc_mode.store(true); agc_mode_changed.store(false); gain_value_changed.store(false); + setting_value_changed.store(false); } SDRThread::~SDRThread() { @@ -81,6 +82,30 @@ void SDRThread::init() { inpBuffer.data.resize(numElems.load()); buffs[0] = malloc(numElems * 2 * sizeof(float)); + + SoapySDR::ArgInfoList settingsInfo = device->getSettingInfo(); + SoapySDR::ArgInfoList::const_iterator settings_i; + + if (!setting_value_changed.load()) { + settings.erase(settings.begin(), settings.end()); + settingChanged.erase(settingChanged.begin(), settingChanged.end()); + } + + setting_busy.lock(); + for (settings_i = settingsInfo.begin(); settings_i != settingsInfo.end(); settings_i++) { + SoapySDR::ArgInfo setting = (*settings_i); + if ((settingChanged.find(setting.key) != settingChanged.end()) && (settings.find(setting.key) != settings.end())) { + device->writeSetting(setting.key, settings[setting.key]); + settingChanged[setting.key] = false; + } else { + settings[setting.key] = device->readSetting(setting.key); + settingChanged[setting.key] = false; + } + } + setting_value_changed.store(false); + setting_busy.unlock(); + + wxGetApp().sdrThreadNotify(SDRThread::SDR_THREAD_INITIALIZED, std::string("Device Initialized.")); } void SDRThread::deinit() { @@ -139,57 +164,10 @@ void SDRThread::readLoop() { updateGains(); while (!terminated.load()) { - if (offset_changed.load()) { - if (!freq_changed.load()) { - frequency.store(frequency.load()); - freq_changed.store(true); - } - offset_changed.store(false); - } - if (rate_changed.load()) { - device->setSampleRate(SOAPY_SDR_RX,0,sampleRate.load()); - sampleRate.store(device->getSampleRate(SOAPY_SDR_RX,0)); - numChannels.store(getOptimalChannelCount(sampleRate.load())); - numElems.store(getOptimalElementCount(sampleRate.load(), 60)); - inpBuffer.data.resize(numElems.load()); - free(buffs[0]); - buffs[0] = malloc(numElems.load() * 2 * sizeof(float)); - rate_changed.store(false); - } - if (ppm_changed.load() && hasPPM.load()) { - device->setFrequency(SOAPY_SDR_RX,0,"CORR",ppm.load()); - ppm_changed.store(false); - } - if (freq_changed.load()) { - device->setFrequency(SOAPY_SDR_RX,0,"RF",frequency.load() - offset.load()); - freq_changed.store(false); - } - if (agc_mode_changed.load()) { - SDRDeviceInfo *devInfo = deviceInfo.load(); - - device->setGainMode(SOAPY_SDR_RX,devInfo->getRxChannel()->getChannel(),agc_mode.load()); - agc_mode_changed.store(false); - if (!agc_mode.load()) { - updateGains(); - } - } - if (gain_value_changed.load() && !agc_mode.load()) { - SDRDeviceInfo *devInfo = deviceInfo.load(); - - gain_busy.lock(); - for (std::map::iterator gci = gainChanged.begin(); gci != gainChanged.end(); gci++) { - if (gci->second) { - device->setGain(SOAPY_SDR_RX, devInfo->getRxChannel()->getChannel(), gci->first, gainValues[gci->first]); - gainChanged[gci->first] = false; - } - } - gain_busy.unlock(); - - gain_value_changed.store(false); - } - + updateSettings(); readStream(iqDataOutQueue); } + buffers.purge(); } @@ -208,6 +186,76 @@ void SDRThread::updateGains() { gain_value_changed.store(false); } +void SDRThread::updateSettings() { + if (offset_changed.load()) { + if (!freq_changed.load()) { + frequency.store(frequency.load()); + freq_changed.store(true); + } + offset_changed.store(false); + } + + if (rate_changed.load()) { + device->setSampleRate(SOAPY_SDR_RX,0,sampleRate.load()); + sampleRate.store(device->getSampleRate(SOAPY_SDR_RX,0)); + numChannels.store(getOptimalChannelCount(sampleRate.load())); + numElems.store(getOptimalElementCount(sampleRate.load(), 60)); + inpBuffer.data.resize(numElems.load()); + free(buffs[0]); + buffs[0] = malloc(numElems.load() * 2 * sizeof(float)); + rate_changed.store(false); + } + + if (ppm_changed.load() && hasPPM.load()) { + device->setFrequency(SOAPY_SDR_RX,0,"CORR",ppm.load()); + ppm_changed.store(false); + } + + if (freq_changed.load()) { + device->setFrequency(SOAPY_SDR_RX,0,"RF",frequency.load() - offset.load()); + freq_changed.store(false); + } + + if (agc_mode_changed.load()) { + SDRDeviceInfo *devInfo = deviceInfo.load(); + + device->setGainMode(SOAPY_SDR_RX,devInfo->getRxChannel()->getChannel(),agc_mode.load()); + agc_mode_changed.store(false); + if (!agc_mode.load()) { + updateGains(); + } + } + + if (gain_value_changed.load() && !agc_mode.load()) { + SDRDeviceInfo *devInfo = deviceInfo.load(); + + gain_busy.lock(); + for (std::map::iterator gci = gainChanged.begin(); gci != gainChanged.end(); gci++) { + if (gci->second) { + device->setGain(SOAPY_SDR_RX, devInfo->getRxChannel()->getChannel(), gci->first, gainValues[gci->first]); + gainChanged[gci->first] = false; + } + } + gain_busy.unlock(); + + gain_value_changed.store(false); + } + + + if (setting_value_changed.load()) { + setting_busy.lock(); + + for (std::map::iterator sci = settingChanged.begin(); sci != settingChanged.end(); sci++) { + if (sci->second) { + device->writeSetting(sci->first, settings[sci->first]); + settingChanged[sci->first] = false; + } + } + + setting_value_changed.store(false); + setting_busy.unlock(); + } +} void SDRThread::run() { //#ifdef __APPLE__ @@ -341,3 +389,20 @@ float SDRThread::getGain(std::string name) { gain_busy.unlock(); return val; } + +void SDRThread::writeSetting(std::string name, std::string value) { + setting_busy.lock(); + settings[name] = value; + settingChanged[name] = true; + setting_value_changed.store(true); + setting_busy.unlock(); +} + +std::string SDRThread::readSetting(std::string name) { + std::string val; + setting_busy.lock(); + val = device->readSetting(name); + setting_busy.unlock(); + return val; +} + diff --git a/src/sdr/SoapySDRThread.h b/src/sdr/SoapySDRThread.h index 8cee44a1..566422ae 100644 --- a/src/sdr/SoapySDRThread.h +++ b/src/sdr/SoapySDRThread.h @@ -48,7 +48,7 @@ class SDRThread : public IOThread { public: SDRThread(); ~SDRThread(); - enum SDRThreadState { SDR_THREAD_MESSAGE, SDR_THREAD_TERMINATED, SDR_THREAD_FAILED }; + enum SDRThreadState { SDR_THREAD_MESSAGE, SDR_THREAD_INITIALIZED, SDR_THREAD_TERMINATED, SDR_THREAD_FAILED }; void run(); @@ -75,9 +75,13 @@ class SDRThread : public IOThread { void setGain(std::string name, float value); float getGain(std::string name); + void writeSetting(std::string name, std::string value); + std::string readSetting(std::string name); + protected: void updateGains(); - + void updateSettings(); + SoapySDR::Stream *stream; SoapySDR::Device *device; void *buffs[1]; @@ -85,13 +89,17 @@ class SDRThread : public IOThread { SDRThreadIQData inpBuffer; std::atomic deviceConfig; std::atomic deviceInfo; + + std::mutex setting_busy; + std::map settings; + std::map settingChanged; std::atomic sampleRate; std::atomic_llong frequency, offset; std::atomic_int ppm, numElems, numChannels; std::atomic_bool hasPPM, hasHardwareDC; std::atomic_bool agc_mode, rate_changed, freq_changed, offset_changed, - ppm_changed, device_changed, agc_mode_changed, gain_value_changed; + ppm_changed, device_changed, agc_mode_changed, gain_value_changed, setting_value_changed; std::mutex gain_busy; std::map gainValues; From efbdb2d69f3fb05b809d14226fc4b726d0919357 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Tue, 3 Nov 2015 23:44:35 -0500 Subject: [PATCH 5/7] Settings menu now functional. --- src/AppFrame.cpp | 65 ++++++++++++++++++++++++++++++++++++++++++------ src/AppFrame.h | 3 ++- 2 files changed, 59 insertions(+), 9 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index 071d5545..4f313cf1 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -439,21 +439,22 @@ void AppFrame::updateDeviceParams() { agcMenuItem = newSettingsMenu->AppendCheckItem(wxID_AGC_CONTROL, "Automatic Gain"); agcMenuItem->Check(wxGetApp().getAGCMode()); - SoapySDR::ArgInfoList args = devInfo->getSettingsArgInfo(); SoapySDR::ArgInfoList::const_iterator args_i; int i = 0; - for (args_i = args.begin(); args_i != args.end(); args_i++) { + settingArgs = devInfo->getSettingsArgInfo(); + for (args_i = settingArgs.begin(); args_i != settingArgs.end(); args_i++) { SoapySDR::ArgInfo arg = (*args_i); + std::string currentVal = wxGetApp().getSDRThread()->readSetting(arg.key); if (arg.type == SoapySDR::ArgInfo::BOOL) { wxMenuItem *item = newSettingsMenu->AppendCheckItem(wxID_SETTINGS_BASE+i, arg.name, arg.description); - item->Check(arg.value=="true"); + item->Check(currentVal=="true"); i++; } else if (arg.type == SoapySDR::ArgInfo::INT) { - wxMenuItem *item = newSettingsMenu->Append(wxID_SETTINGS_BASE+i, arg.name, arg.description); + newSettingsMenu->Append(wxID_SETTINGS_BASE+i, arg.name, arg.description); i++; } else if (arg.type == SoapySDR::ArgInfo::FLOAT) { - wxMenuItem *item = newSettingsMenu->Append(wxID_SETTINGS_BASE+i, arg.name, arg.description); + newSettingsMenu->Append(wxID_SETTINGS_BASE+i, arg.name, arg.description); i++; } else if (arg.type == SoapySDR::ArgInfo::STRING) { if (arg.options.size()) { @@ -466,19 +467,20 @@ void AppFrame::updateDeviceParams() { displayName = arg.optionNames[j]; } wxMenuItem *item = subMenu->AppendRadioItem(wxID_SETTINGS_BASE+i, displayName); - if (arg.value == (*str_i)) { + if (currentVal == (*str_i)) { item->Check(); } - i++; j++; + i++; } newSettingsMenu->AppendSubMenu(subMenu, arg.name, arg.description); } else { - wxMenuItem *item = newSettingsMenu->Append(wxID_SETTINGS_BASE+i, arg.name, arg.description); + newSettingsMenu->Append(wxID_SETTINGS_BASE+i, arg.name, arg.description); i++; } } } + settingsIdMax = wxID_SETTINGS_BASE+i; menuBar->Replace(1, newSettingsMenu, wxT("&Settings")); settingsMenu = newSettingsMenu; @@ -645,6 +647,53 @@ void AppFrame::OnMenu(wxCommandEvent& event) { ThemeMgr::mgr.setTheme(COLOR_THEME_RADAR); } + if (event.GetId() >= wxID_SETTINGS_BASE && event.GetId() < settingsIdMax) { + int setIdx = event.GetId()-wxID_SETTINGS_BASE; + int menuIdx = 0; + for (std::vector::iterator arg_i = settingArgs.begin(); arg_i != settingArgs.end(); arg_i++) { + SoapySDR::ArgInfo &arg = (*arg_i); + + if (arg.type == SoapySDR::ArgInfo::STRING && arg.options.size() && setIdx >= menuIdx && setIdx < menuIdx+arg.options.size()) { + int optIdx = setIdx-menuIdx; + wxGetApp().getSDRThread()->writeSetting(arg.key, arg.options[optIdx]); + break; + } else if (arg.type == SoapySDR::ArgInfo::STRING && arg.options.size()) { + menuIdx += arg.options.size(); + } else if (menuIdx == setIdx) { + if (arg.type == SoapySDR::ArgInfo::BOOL) { + wxGetApp().getSDRThread()->writeSetting(arg.key, (wxGetApp().getSDRThread()->readSetting(arg.key)=="true")?"false":"true"); + break; + } else if (arg.type == SoapySDR::ArgInfo::STRING) { + menuIdx++; + } else if (arg.type == SoapySDR::ArgInfo::INT) { + int currentVal; + try { + currentVal = std::stoi(wxGetApp().getSDRThread()->readSetting(arg.key)); + } catch (std::invalid_argument e) { + currentVal = 0; + } + int intVal = wxGetNumberFromUser(arg.description, arg.units, arg.name, currentVal, arg.range.minimum(), arg.range.maximum(), this); + if (intVal != -1) { + wxGetApp().getSDRThread()->writeSetting(arg.key, std::to_string(intVal)); + } + break; + } else if (arg.type == SoapySDR::ArgInfo::FLOAT) { + wxString floatVal = wxGetTextFromUser(arg.description, arg.name, wxGetApp().getSDRThread()->readSetting(arg.key)); + try { + wxGetApp().getSDRThread()->writeSetting(arg.key, floatVal.ToStdString()); + } catch (std::invalid_argument e) { + // ... + } + break; + } else { + menuIdx++; + } + } else { + menuIdx++; + } + } + } + if (event.GetId() >= wxID_THEME_DEFAULT && event.GetId() <= wxID_THEME_RADAR) { demodTuner->Refresh(); demodModeSelector->Refresh(); diff --git a/src/AppFrame.h b/src/AppFrame.h index 5f17df44..d174d57b 100644 --- a/src/AppFrame.h +++ b/src/AppFrame.h @@ -52,7 +52,6 @@ #define wxID_AUDIO_BANDWIDTH_BASE 9000 #define wxID_AUDIO_DEVICE_MULTIPLIER 50 - // Define a new frame type class AppFrame: public wxFrame { public: @@ -107,6 +106,8 @@ class AppFrame: public wxFrame { wxMenu *sampleRateMenu; wxMenuItem *agcMenuItem; wxMenu *settingsMenu; + SoapySDR::ArgInfoList settingArgs; + int settingsIdMax; std::vector sampleRates; std::string currentSessionFile; From 5346bdd50dba882a025e64f1949cc9706879e79e Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Wed, 4 Nov 2015 02:04:52 -0500 Subject: [PATCH 6/7] SDR Device dialog property settings now functional --- src/CubicSDR.cpp | 12 +++++++ src/CubicSDR.h | 6 ++++ src/forms/SDRDevices/SDRDevices.cpp | 53 +++++++++++++++++++++++++++-- src/forms/SDRDevices/SDRDevices.h | 1 + src/sdr/SoapySDRThread.cpp | 17 ++++++++- src/sdr/SoapySDRThread.h | 5 +++ 6 files changed, 90 insertions(+), 4 deletions(-) diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index db8e0fb2..49460b20 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -373,6 +373,10 @@ void CubicSDR::setDevice(SDRDeviceInfo *dev) { } } + for (SoapySDR::Kwargs::const_iterator i = settingArgs.begin(); i != settingArgs.end(); i++) { + sdrThread->writeSetting(i->first, i->second); + } + sdrThread->setStreamArgs(streamArgs); sdrThread->setDevice(dev); DeviceConfig *devConfig = config.getDevice(dev->getDeviceId()); @@ -599,3 +603,11 @@ float CubicSDR::getGain(std::string name) { return sdrThread->getGain(name); } +void CubicSDR::setStreamArgs(SoapySDR::Kwargs streamArgs_in) { + streamArgs = streamArgs_in; +} + +void CubicSDR::setDeviceArgs(SoapySDR::Kwargs settingArgs_in) { + settingArgs = settingArgs_in; +} + diff --git a/src/CubicSDR.h b/src/CubicSDR.h index 1946660f..4fed242d 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -109,6 +109,9 @@ class CubicSDR: public wxApp { void setGain(std::string name, float gain_in); float getGain(std::string name); + void setStreamArgs(SoapySDR::Kwargs streamArgs_in); + void setDeviceArgs(SoapySDR::Kwargs settingArgs_in); + private: AppFrame *appframe; AppConfig config; @@ -140,6 +143,9 @@ class CubicSDR: public wxApp { SDRDevicesDialog *deviceSelectorDialog; + SoapySDR::Kwargs streamArgs; + SoapySDR::Kwargs settingArgs; + std::thread *t_SDR, *t_SDREnum, *t_PostSDR, *t_SpectrumVisual, *t_DemodVisual; std::atomic_bool devicesReady; std::atomic_bool deviceSelectorOpen; diff --git a/src/forms/SDRDevices/SDRDevices.cpp b/src/forms/SDRDevices/SDRDevices.cpp index 9595ff69..3839c99c 100644 --- a/src/forms/SDRDevices/SDRDevices.cpp +++ b/src/forms/SDRDevices/SDRDevices.cpp @@ -93,7 +93,7 @@ void SDRDevicesDialog::OnSelectionChanged( wxTreeEvent& event ) { wxTreeItemId selId = devTree->GetSelection(); dev = getSelectedDevice(selId); - + props.erase(props.begin(), props.end()); if (dev) { m_propertyGrid->Clear(); m_propertyGrid->Append(new wxPropertyCategory("Run-time Settings")); @@ -104,7 +104,7 @@ void SDRDevicesDialog::OnSelectionChanged( wxTreeEvent& event ) { for (args_i = args.begin(); args_i != args.end(); args_i++) { SoapySDR::ArgInfo arg = (*args_i); - addArgInfoProperty(m_propertyGrid, arg); + props.push_back(addArgInfoProperty(m_propertyGrid, arg)); } if (dev->getRxChannel()) { @@ -115,7 +115,7 @@ void SDRDevicesDialog::OnSelectionChanged( wxTreeEvent& event ) { for (args_i = args.begin(); args_i != args.end(); args_i++) { SoapySDR::ArgInfo arg = (*args_i); - addArgInfoProperty(m_propertyGrid, arg); + props.push_back(addArgInfoProperty(m_propertyGrid, arg)); } } } @@ -158,6 +158,53 @@ void SDRDevicesDialog::OnUseSelected( wxMouseEvent& event ) { dev = getSelectedDevice(selId); if (dev != NULL) { + + int i = 0; + SoapySDR::ArgInfoList::const_iterator args_i; + SoapySDR::ArgInfoList args = dev->getSettingsArgInfo(); + + SoapySDR::Kwargs settingArgs; + SoapySDR::Kwargs streamArgs; + + for (args_i = args.begin(); args_i != args.end(); args_i++) { + SoapySDR::ArgInfo arg = (*args_i); + wxPGProperty *prop = props[i]; + + if (arg.type == SoapySDR::ArgInfo::STRING && arg.options.size()) { + settingArgs[arg.key] = arg.options[prop->GetChoiceSelection()]; + } else if (arg.type == SoapySDR::ArgInfo::BOOL) { + settingArgs[arg.key] = (prop->GetValueAsString()=="True")?"true":"false"; + } else { + settingArgs[arg.key] = prop->GetValueAsString(); + } + + i++; + } + + if (dev->getRxChannel()) { + args = dev->getRxChannel()->getStreamArgsInfo(); + + if (args.size()) { + for (args_i = args.begin(); args_i != args.end(); args_i++) { + SoapySDR::ArgInfo arg = (*args_i); + wxPGProperty *prop = props[i]; + + if (arg.type == SoapySDR::ArgInfo::STRING && arg.options.size()) { + streamArgs[arg.key] = arg.options[prop->GetChoiceSelection()]; + } else if (arg.type == SoapySDR::ArgInfo::BOOL) { + streamArgs[arg.key] = (prop->GetValueAsString()=="True")?"true":"false"; + } else { + streamArgs[arg.key] = prop->GetValueAsString(); + } + + i++; + } + } + } + + + wxGetApp().setDeviceArgs(settingArgs); + wxGetApp().setStreamArgs(streamArgs); wxGetApp().setDevice(dev); Close(); } diff --git a/src/forms/SDRDevices/SDRDevices.h b/src/forms/SDRDevices/SDRDevices.h index faa6fac3..74441ae0 100644 --- a/src/forms/SDRDevices/SDRDevices.h +++ b/src/forms/SDRDevices/SDRDevices.h @@ -30,4 +30,5 @@ class SDRDevicesDialog: public devFrame { std::map devItems; std::map::iterator devItems_i; SDRDeviceInfo *dev = NULL; + std::vector props; }; \ No newline at end of file diff --git a/src/sdr/SoapySDRThread.cpp b/src/sdr/SoapySDRThread.cpp index 75020741..8b80dc30 100644 --- a/src/sdr/SoapySDRThread.cpp +++ b/src/sdr/SoapySDRThread.cpp @@ -38,6 +38,18 @@ SDRThread::~SDRThread() { } +SoapySDR::Kwargs SDRThread::combineArgs(SoapySDR::Kwargs a, SoapySDR::Kwargs b) { + SoapySDR::Kwargs c; + SoapySDR::Kwargs::iterator i; + for (i = a.begin(); i != a.end(); i++) { + c[i->first] = i->second; + } + for (i = b.begin(); i != b.end(); i++) { + c[i->first] = i->second; + } + return c; +} + void SDRThread::init() { SDRDeviceInfo *devInfo = deviceInfo.load(); deviceConfig.store(wxGetApp().getConfig()->getDevice(devInfo->getDeviceId())); @@ -54,7 +66,7 @@ void SDRThread::init() { wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Initializing device.")); device = SoapySDR::Device::make(args); - stream = device->setupStream(SOAPY_SDR_RX,"CF32", std::vector(), devInfo->getStreamArgs()); + stream = device->setupStream(SOAPY_SDR_RX,"CF32", std::vector(), combineArgs(devInfo->getStreamArgs(),streamArgs)); wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Activating stream.")); device->setSampleRate(SOAPY_SDR_RX,0,sampleRate.load()); @@ -406,3 +418,6 @@ std::string SDRThread::readSetting(std::string name) { return val; } +void SDRThread::setStreamArgs(SoapySDR::Kwargs streamArgs_in) { + streamArgs = streamArgs_in; +} diff --git a/src/sdr/SoapySDRThread.h b/src/sdr/SoapySDRThread.h index 566422ae..4c21103d 100644 --- a/src/sdr/SoapySDRThread.h +++ b/src/sdr/SoapySDRThread.h @@ -78,9 +78,12 @@ class SDRThread : public IOThread { void writeSetting(std::string name, std::string value); std::string readSetting(std::string name); + void setStreamArgs(SoapySDR::Kwargs streamArgs); + protected: void updateGains(); void updateSettings(); + SoapySDR::Kwargs combineArgs(SoapySDR::Kwargs a, SoapySDR::Kwargs b); SoapySDR::Stream *stream; SoapySDR::Device *device; @@ -104,4 +107,6 @@ class SDRThread : public IOThread { std::mutex gain_busy; std::map gainValues; std::map gainChanged; + + SoapySDR::Kwargs streamArgs; }; From f39a96022a6cefd2644fc40c4351d89aef68d3d5 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Sun, 8 Nov 2015 16:45:06 -0500 Subject: [PATCH 7/7] Add OSX SoapySDR module bundling support. --- CMakeLists.txt | 59 ++++++++++++++++++++++++++++----------- src/CubicSDR.cpp | 13 +++++++++ src/CubicSDR.h | 14 +++++++++- src/sdr/SDREnumerator.cpp | 51 ++++++++++++++++++++------------- 4 files changed, 100 insertions(+), 37 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 282b8907..d8dd22ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required (VERSION 2.8) SET(CUBICSDR_VERSION_MAJOR "0") SET(CUBICSDR_VERSION_MINOR "1") -SET(CUBICSDR_VERSION_PATCH "15") +SET(CUBICSDR_VERSION_PATCH "16") SET(CUBICSDR_VERSION_REL "alpha") SET(CUBICSDR_VERSION "${CUBICSDR_VERSION_MAJOR}.${CUBICSDR_VERSION_MINOR}.${CUBICSDR_VERSION_PATCH}-${CUBICSDR_VERSION_REL}") @@ -427,7 +427,11 @@ IF (APPLE AND BUNDLE_APP) set(BUNDLE_SOAPY_MODS OFF CACHE BOOL "Bundle local SoapySDR modules") - + IF (BUNDLE_SOAPY_MODS) + ADD_DEFINITIONS( + -DBUNDLE_SOAPY_MODS=1 + ) + ENDIF() ADD_DEFINITIONS( -std=c++0x @@ -470,7 +474,7 @@ IF (APPLE AND BUNDLE_APP) ${PROJECT_SOURCE_DIR}/icon/CubicSDR.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources - ) + ) target_link_libraries(CubicSDR ${LIQUID_LIB} ${FFTW_LIB} ${wxWidgets_LIBRARIES} ${OPENGL_LIBRARIES} ${OTHER_LIBRARIES}) SET_TARGET_PROPERTIES(CubicSDR PROPERTIES MACOSX_BUNDLE TRUE) @@ -482,30 +486,51 @@ IF (APPLE AND BUNDLE_APP) # MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}" MACOSX_BUNDLE_GUI_IDENTIFIER "com.cubicproductions.cubicsdr" MACOSX_BUNDLE_ICON_FILE CubicSDR.icns - ) + ) SET(APPS "${CMAKE_BINARY_DIR}/${EX_PLATFORM_NAME}/CubicSDR.app") # SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE) # SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) + + IF (BUNDLE_SOAPY_MODS) + + message(STATUS "SOAPY_ROOT: ${SOAPY_SDR_ROOT}") + file(GLOB SOAPY_MODS ${SOAPY_SDR_ROOT}/lib/SoapySDR/modules/*.so) + + FOREACH(SOAPY_MOD_FILE ${SOAPY_MODS}) + INSTALL( FILES "${SOAPY_MOD_FILE}" + DESTINATION "${APPS}/Contents/MacOS/modules" + COMPONENT Runtime + ) + ENDFOREACH() + + ENDIF(BUNDLE_SOAPY_MODS) INSTALL(CODE " - SET(BU_COPY_FULL_FRAMEWORK_CONTENTS ON) + SET(BU_COPY_FULL_FRAMEWORK_CONTENTS ON) include(BundleUtilities) fixup_bundle(\"${APPS}\" \"\" \"/usr/local/lib\") - VERIFY_APP(\"${APPS}\") " COMPONENT Runtime) - # IF (BUNDLE_SOAPY_MODS) - # install( DIRECTORY "${SOAPY_SDR_ROOT}/lib/modules" - # DESTINATION ${APPS}/modules - # COMPONENT Runtime - # FILES_MATCHING - # PATTERN "*.dylib" - # PATTERN "*_debug.dylib" EXCLUDE - # ) - # ENDIF(BUNDLE_SOAPY_MODS) - - + IF (BUNDLE_SOAPY_MODS) + FOREACH(SOAPY_MOD_FILE ${SOAPY_MODS}) + GET_FILENAME_COMPONENT(SOAPY_MOD_NAME ${SOAPY_MOD_FILE} NAME) + + IF(${SOAPY_MOD_NAME} STREQUAL "libsdrPlaySupport.so") # prevent inclusion of libmirsdrapi-rsp.so + message(STATUS "Excluding libsdrPlaySupport.so") + CONTINUE() + ELSE() + message(STATUS "Bundling ${SOAPY_MOD_NAME} from ${SOAPY_MOD_FILE}") + ENDIF() + INSTALL(CODE " + fixup_bundle(\"${APPS}\" \"${APPS}/Contents/MacOS/modules/${SOAPY_MOD_NAME}\" \"/usr/local/lib\") + " COMPONENT Runtime) + ENDFOREACH() + ENDIF(BUNDLE_SOAPY_MODS) + + INSTALL(CODE " + VERIFY_APP(\"${APPS}\") + " COMPONENT Runtime) INSTALL(TARGETS CubicSDR BUNDLE DESTINATION . COMPONENT Runtime diff --git a/src/CubicSDR.cpp b/src/CubicSDR.cpp index 49460b20..b6220479 100644 --- a/src/CubicSDR.cpp +++ b/src/CubicSDR.cpp @@ -270,6 +270,16 @@ bool CubicSDR::OnCmdLineParsed(wxCmdLineParser& parser) { config.load(); +#ifdef BUNDLE_SOAPY_MODS + if (parser.Found("l")) { + useLocalMod.store(true); + } else { + useLocalMod.store(false); + } +#else + useLocalMod.store(false); +#endif + return true; } @@ -611,3 +621,6 @@ void CubicSDR::setDeviceArgs(SoapySDR::Kwargs settingArgs_in) { settingArgs = settingArgs_in; } +bool CubicSDR::getUseLocalMod() { + return useLocalMod.load(); +} \ No newline at end of file diff --git a/src/CubicSDR.h b/src/CubicSDR.h index 4fed242d..1150008b 100644 --- a/src/CubicSDR.h +++ b/src/CubicSDR.h @@ -111,7 +111,8 @@ class CubicSDR: public wxApp { void setStreamArgs(SoapySDR::Kwargs streamArgs_in); void setDeviceArgs(SoapySDR::Kwargs settingArgs_in); - + + bool getUseLocalMod(); private: AppFrame *appframe; AppConfig config; @@ -150,15 +151,26 @@ class CubicSDR: public wxApp { std::atomic_bool devicesReady; std::atomic_bool deviceSelectorOpen; std::atomic_bool sampleRateInitialized; + std::atomic_bool useLocalMod; std::string notifyMessage; std::mutex notify_busy; }; +#ifdef BUNDLE_SOAPY_MODS +static const wxCmdLineEntryDesc commandLineInfo [] = +{ + { wxCMD_LINE_SWITCH, "h", "help", "Command line parameter help", wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP }, + { wxCMD_LINE_OPTION, "c", "config", "Specify a named configuration to use, i.e. '-c ham'" }, + { wxCMD_LINE_SWITCH, "l", "localmod", "Check local SoapySDR modules instead of bundled first." }, + { wxCMD_LINE_NONE } +}; +#else static const wxCmdLineEntryDesc commandLineInfo [] = { { wxCMD_LINE_SWITCH, "h", "help", "Command line parameter help", wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP }, { wxCMD_LINE_OPTION, "c", "config", "Specify a named configuration to use, i.e. '-c ham'" }, { wxCMD_LINE_NONE } }; +#endif DECLARE_APP(CubicSDR) diff --git a/src/sdr/SDREnumerator.cpp b/src/sdr/SDREnumerator.cpp index 30746d21..501d0e7a 100644 --- a/src/sdr/SDREnumerator.cpp +++ b/src/sdr/SDREnumerator.cpp @@ -36,31 +36,44 @@ std::vector *SDREnumerator::enumerate_devices(std::string remot std::cout << "\tAPI Version: v" << SoapySDR::getAPIVersion() << std::endl; std::cout << "\tABI Version: v" << SoapySDR::getABIVersion() << std::endl; std::cout << "\tInstall root: " << SoapySDR::getRootPath() << std::endl; - - modules = SoapySDR::listModules(); - for (size_t i = 0; i < modules.size(); i++) { - std::cout << "\tModule found: " << modules[i] << std::endl; - } - if (modules.empty()) { - std::cout << "No modules found!" << std::endl; - } - std::cout << "\tLoading modules... " << std::flush; + std::cout << "\tLoading modules... " << std::endl; #ifdef BUNDLE_SOAPY_MODS - wxFileName exePath = wxFileName(wxStandardPaths::Get().GetExecutablePath()); - std::vector localMods = SoapySDR::listModules(exePath.GetPath().ToStdString() + "/modules/"); - for (std::vector::iterator mods_i = localMods.begin(); mods_i != localMods.end(); mods_i++) { - wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Initializing bundled SoapySDR module " + (*mods_i) + ".."); - SoapySDR::loadModule(*mods_i); - } - wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Loading SoapySDR modules.."); + bool localModPref = wxGetApp().getUseLocalMod(); + if (localModPref) { + wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Loading SoapySDR modules.."); + std::cout << "Checking local system SoapySDR modules.." << std::flush; + SoapySDR::loadModules(); + } - SoapySDR::loadModules(); + wxFileName exePath = wxFileName(wxStandardPaths::Get().GetExecutablePath()); + std::vector localMods = SoapySDR::listModules(exePath.GetPath().ToStdString() + "/modules/"); + for (std::vector::iterator mods_i = localMods.begin(); mods_i != localMods.end(); mods_i++) { + wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Initializing bundled SoapySDR module " + (*mods_i) + ".."); + std::cout << "Loading bundled SoapySDR module " << (*mods_i) << ".." << std::endl; + SoapySDR::loadModule(*mods_i); + } + + if (!localModPref) { + wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Loading SoapySDR modules.."); + std::cout << "Checking system SoapySDR modules.." << std::flush; + SoapySDR::loadModules(); + } #else + wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "Loading SoapySDR modules.."); SoapySDR::loadModules(); #endif - std::cout << "done" << std::endl; - + wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, "done."); + std::cout << "done." << std::endl; + +// modules = SoapySDR::listModules(); +// for (size_t i = 0; i < modules.size(); i++) { +// std::cout << "\tModule found: " << modules[i] << std::endl; +// } +// if (modules.empty()) { +// std::cout << "No modules found!" << std::endl; +// } + if (SDREnumerator::factories.size()) { SDREnumerator::factories.erase(SDREnumerator::factories.begin(), SDREnumerator::factories.end()); }