Merge pull request #260 from cjcliffe/soapysdr-manual-device

Manual/Remote SoapySDR device specification
This commit is contained in:
Charles J. Cliffe 2016-01-22 00:51:13 -05:00
commit 77297fa9c6
19 changed files with 1221 additions and 100 deletions

View File

@ -313,6 +313,8 @@ SET (cubicsdr_sources
src/ui/GLPanel.cpp
src/forms/SDRDevices/SDRDevices.cpp
src/forms/SDRDevices/SDRDevicesForm.cpp
src/forms/SDRDevices/SDRDeviceAdd.cpp
src/forms/SDRDevices/SDRDeviceAddForm.cpp
external/rtaudio/RtAudio.cpp
external/lodepng/lodepng.cpp
external/tinyxml/tinyxml.cpp
@ -413,6 +415,8 @@ SET (cubicsdr_headers
src/ui/UITestContext.h
src/forms/SDRDevices/SDRDevices.h
src/forms/SDRDevices/SDRDevicesForm.h
src/forms/SDRDevices/SDRDeviceAdd.h
src/forms/SDRDevices/SDRDeviceAddForm.h
external/rtaudio/RtAudio.h
external/lodepng/lodepng.h
external/tinyxml/tinyxml.h

View File

@ -303,6 +303,14 @@ float AppConfig::getSpectrumAvgSpeed() {
return spectrumAvgSpeed.load();
}
void AppConfig::setManualDevices(std::vector<SDRManualDef> manuals) {
manualDevices = manuals;
}
std::vector<SDRManualDef> AppConfig::getManualDevices() {
return manualDevices;
}
void AppConfig::setConfigName(std::string configName) {
this->configName = configName;
}
@ -354,6 +362,15 @@ bool AppConfig::save() {
device_config_i->second->save(device_node);
}
if (manualDevices.size()) {
DataNode *manual_node = cfg.rootNode()->newChild("manual_devices");
for (std::vector<SDRManualDef>::const_iterator i = manualDevices.begin(); i != manualDevices.end(); i++) {
DataNode *rig_node = manual_node->newChild("device");
*rig_node->newChild("factory") = i->factory;
*rig_node->newChild("params") = i->params;
}
}
#ifdef USE_HAMLIB
DataNode *rig_node = cfg.rootNode()->newChild("rig");
*rig_node->newChild("model") = rigModel.load();
@ -467,14 +484,29 @@ bool AppConfig::load() {
while (devices_node->hasAnother("device")) {
DataNode *device_node = devices_node->getNext("device");
if (device_node->hasAnother("id")) {
std::string deviceId;
device_node->getNext("id")->element()->get(deviceId);
std::string deviceId = device_node->getNext("id")->element()->toString();
getDevice(deviceId)->load(device_node);
}
}
}
if (cfg.rootNode()->hasAnother("manual_devices")) {
DataNode *manuals_node = cfg.rootNode()->getNext("manual_devices");
while (manuals_node->hasAnother("device")) {
DataNode *manual_node = manuals_node->getNext("device");
if (manual_node->hasAnother("factory") && manual_node->hasAnother("params")) {
SDRManualDef mdef;
mdef.factory = manual_node->getNext("factory")->element()->toString();
mdef.params = manual_node->getNext("params")->element()->toString();
manualDevices.push_back(mdef);
}
}
}
#ifdef USE_HAMLIB
if (cfg.rootNode()->hasAnother("rig")) {
DataNode *rig_node = cfg.rootNode()->getNext("rig");

View File

@ -8,6 +8,8 @@
#include <mutex>
#include "DataTree.h"
#include "CubicSDRDefs.h"
#include "SDRDeviceInfo.h"
typedef std::map<std::string, std::string> ConfigSettings;
@ -40,7 +42,7 @@ public:
void setRigIF(int rigType, long long freq);
long long getRigIF(int rigType);
void save(DataNode *node);
void load(DataNode *node);
@ -83,6 +85,9 @@ public:
void setSpectrumAvgSpeed(float avgSpeed);
float getSpectrumAvgSpeed();
void setManualDevices(std::vector<SDRManualDef> manuals);
std::vector<SDRManualDef> getManualDevices();
#if USE_HAMLIB
int getRigModel();
void setRigModel(int rigModel);
@ -110,6 +115,7 @@ private:
std::atomic_llong centerFreq;
std::atomic_int waterfallLinesPerSec;
std::atomic<float> spectrumAvgSpeed;
std::vector<SDRManualDef> manualDevices;
#if USE_HAMLIB
std::atomic_int rigModel, rigRate;
std::string rigPort;

View File

@ -680,22 +680,7 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
"Frequency Offset", wxGetApp().getOffset(), -2000000000, 2000000000, this);
if (ofs != -1) {
wxGetApp().setOffset(ofs);
wxGetApp().saveConfig();
}
} else if (event.GetId() == wxID_SET_DS_OFF) {
// wxGetApp().setDirectSampling(0);
// wxGetApp().saveConfig();
} else if (event.GetId() == wxID_SET_DS_I) {
// wxGetApp().setDirectSampling(1);
// wxGetApp().saveConfig();
} else if (event.GetId() == wxID_SET_DS_Q) {
// 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);
} else if (event.GetId() == wxID_AGC_CONTROL) {
if (wxGetApp().getDevice() == NULL) {
agcMenuItem->Check(true);
@ -722,7 +707,6 @@ void AppFrame::OnMenu(wxCommandEvent& event) {
long ofs = wxGetNumberFromUser("Frequency correction for device in PPM.\ni.e. -51 for -51 PPM\n\nNote: you can adjust PPM interactively\nby holding ALT over the frequency tuning bar.\n", "Parts per million (PPM)",
"Frequency Correction", wxGetApp().getPPM(), -1000, 1000, this);
wxGetApp().setPPM(ofs);
wxGetApp().saveConfig();
} else if (event.GetId() == wxID_SAVE) {
if (!currentSessionFile.empty()) {
saveSession(currentSessionFile);
@ -1007,6 +991,7 @@ void AppFrame::OnClose(wxCloseEvent& event) {
wxGetApp().getConfig()->setCenterFreq(wxGetApp().getFrequency());
wxGetApp().getConfig()->setSpectrumAvgSpeed(wxGetApp().getSpectrumProcessor()->getFFTAverageRate());
wxGetApp().getConfig()->setWaterfallLinesPerSec(waterfallDataThread->getLinesPerSecond());
wxGetApp().getConfig()->setManualDevices(SDREnumerator::getManuals());
#ifdef USE_HAMLIB
wxGetApp().getConfig()->setRigModel(rigModel);
wxGetApp().getConfig()->setRigRate(rigSerialRate);

View File

@ -25,10 +25,6 @@
#define wxID_SET_FREQ_OFFSET 2001
#define wxID_RESET 2002
#define wxID_SET_PPM 2003
#define wxID_SET_DS_OFF 2004
#define wxID_SET_DS_I 2005
#define wxID_SET_DS_Q 2006
#define wxID_SET_SWAP_IQ 2007
#define wxID_SDR_DEVICES 2008
#define wxID_AGC_CONTROL 2009

View File

@ -247,6 +247,8 @@ bool CubicSDR::OnInit() {
t_DemodVisual = new std::thread(&SpectrumVisualDataThread::threadMain, demodVisualThread);
sdrEnum = new SDREnumerator();
SDREnumerator::setManuals(config.getManualDevices());
appframe = new AppFrame();
t_SDREnum = new std::thread(&SDREnumerator::threadMain, sdrEnum);

View File

@ -0,0 +1,59 @@
#include "SDRDeviceAdd.h"
#include "SDREnumerator.h"
SDRDeviceAddDialog::SDRDeviceAddDialog( wxWindow* parent ): SDRDeviceAddForm( parent ) {
okPressed = false;
selectedModule = "";
moduleParam = "";
selectedModule = "SoapyRemote";
m_soapyModule->Append("SoapyRemote");
m_paramLabel->SetLabel("Remote Address (address[:port])");
std::vector<std::string> &factories = SDREnumerator::getFactories();
std::vector<std::string>::iterator factory_i;
for (factory_i = factories.begin(); factory_i != factories.end(); factory_i++) {
if (*factory_i != "remote" && *factory_i != "null") {
m_soapyModule->Append(*factory_i);
}
}
}
void SDRDeviceAddDialog::OnSoapyModuleChanged( wxCommandEvent& event ) {
wxString strSel = m_soapyModule->GetStringSelection();
selectedModule = strSel.ToStdString();
if (selectedModule == "SoapyRemote") {
m_paramLabel->SetLabelText("Remote Address (address[:port])");
} else {
m_paramLabel->SetLabel("SoapySDR Device Parameters, i.e. 'addr=192.168.1.105'");
}
}
void SDRDeviceAddDialog::OnCancelButton( wxCommandEvent& event ) {
okPressed = false;
Close(true);
}
void SDRDeviceAddDialog::OnOkButton( wxCommandEvent& event ) {
wxString strSel = m_soapyModule->GetStringSelection();
selectedModule = strSel.ToStdString();
moduleParam = m_paramText->GetValue().ToStdString();
okPressed = true;
Close(true);
}
bool SDRDeviceAddDialog::wasOkPressed() {
return okPressed;
}
std::string SDRDeviceAddDialog::getSelectedModule() {
return selectedModule;
}
std::string SDRDeviceAddDialog::getModuleParam() {
return moduleParam;
}

View File

@ -0,0 +1,681 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<wxFormBuilder_Project>
<FileVersion major="1" minor="13" />
<object class="Project" expanded="1">
<property name="class_decoration"></property>
<property name="code_generation">C++</property>
<property name="disconnect_events">1</property>
<property name="disconnect_mode">source_name</property>
<property name="disconnect_php_events">0</property>
<property name="disconnect_python_events">0</property>
<property name="embedded_files_path">res</property>
<property name="encoding">UTF-8</property>
<property name="event_generation">connect</property>
<property name="file">SDRDeviceAddForm</property>
<property name="first_id">1000</property>
<property name="help_provider">none</property>
<property name="internationalize">0</property>
<property name="name">SDRDeviceAddForm</property>
<property name="namespace"></property>
<property name="path">.</property>
<property name="precompiled_header"></property>
<property name="relative_path">1</property>
<property name="skip_lua_events">1</property>
<property name="skip_php_events">1</property>
<property name="skip_python_events">1</property>
<property name="ui_table">UI</property>
<property name="use_enum">0</property>
<property name="use_microsoft_bom">0</property>
<object class="Dialog" expanded="1">
<property name="aui_managed">0</property>
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
<property name="bg"></property>
<property name="center">wxBOTH</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="enabled">1</property>
<property name="event_handler">impl_virtual</property>
<property name="extra_style"></property>
<property name="fg"></property>
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size"></property>
<property name="name">SDRDeviceAddForm</property>
<property name="pos"></property>
<property name="size">395,241</property>
<property name="style">wxDEFAULT_DIALOG_STYLE</property>
<property name="subclass"></property>
<property name="title">Add SoapySDR Device</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnActivate"></event>
<event name="OnActivateApp"></event>
<event name="OnAuiFindManager"></event>
<event name="OnAuiPaneButton"></event>
<event name="OnAuiPaneClose"></event>
<event name="OnAuiPaneMaximize"></event>
<event name="OnAuiPaneRestore"></event>
<event name="OnAuiRender"></event>
<event name="OnChar"></event>
<event name="OnClose"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnHibernate"></event>
<event name="OnIconize"></event>
<event name="OnIdle"></event>
<event name="OnInitDialog"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bSizer6</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">10</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Manually add a SoapyRemote or SoapySDR device. &#x0A;&#x0A;Useful for a device that is not detected automatically.</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_staticText4</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
<event name="OnChar"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="spacer" expanded="1">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">10</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxChoice" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="choices"></property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_soapyModule</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="selection">0</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnChar"></event>
<event name="OnChoice">OnSoapyModuleChanged</event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="spacer" expanded="1">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">10</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">&lt;Parameter&gt;</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_paramLabel</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
<event name="OnChar"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">10</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxTextCtrl" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="maxlength"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_paramText</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxTE_DONTWRAP</property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnChar"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnText"></event>
<event name="OnTextEnter"></event>
<event name="OnTextMaxLen"></event>
<event name="OnTextURL"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="spacer" expanded="1">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bSizer7</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="spacer" expanded="1">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default">0</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Cancel</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_cancelButton</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnButtonClick">OnCancelButton</event>
<event name="OnChar"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default">0</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Ok</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_OkButton</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnButtonClick">OnOkButton</event>
<event name="OnChar"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="spacer" expanded="1">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
</object>
</object>
</object>
</wxFormBuilder_Project>

View File

@ -0,0 +1,21 @@
#pragma once
#include "SDRDeviceAddForm.h"
class SDRDeviceAddDialog : public SDRDeviceAddForm {
public:
SDRDeviceAddDialog( wxWindow* parent );
void OnSoapyModuleChanged( wxCommandEvent& event );
void OnCancelButton( wxCommandEvent& event );
void OnOkButton( wxCommandEvent& event );
bool wasOkPressed();
std::string getSelectedModule();
std::string getModuleParam();
private:
bool okPressed;
std::string selectedModule;
std::string moduleParam;
};

View File

@ -0,0 +1,81 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Aug 23 2015)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "SDRDeviceAddForm.h"
///////////////////////////////////////////////////////////////////////////
SDRDeviceAddForm::SDRDeviceAddForm( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
wxBoxSizer* bSizer6;
bSizer6 = new wxBoxSizer( wxVERTICAL );
m_staticText4 = new wxStaticText( this, wxID_ANY, wxT("Manually add a SoapyRemote or SoapySDR device. \n\nUseful for a device that is not detected automatically."), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText4->Wrap( -1 );
bSizer6->Add( m_staticText4, 0, wxALL, 10 );
bSizer6->Add( 0, 0, 1, wxEXPAND, 5 );
wxArrayString m_soapyModuleChoices;
m_soapyModule = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_soapyModuleChoices, 0 );
m_soapyModule->SetSelection( 0 );
bSizer6->Add( m_soapyModule, 0, wxALL, 10 );
bSizer6->Add( 0, 0, 1, wxEXPAND, 5 );
m_paramLabel = new wxStaticText( this, wxID_ANY, wxT("<Parameter>"), wxDefaultPosition, wxDefaultSize, 0 );
m_paramLabel->Wrap( -1 );
bSizer6->Add( m_paramLabel, 0, wxALL, 10 );
m_paramText = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_DONTWRAP );
bSizer6->Add( m_paramText, 0, wxALL|wxEXPAND, 10 );
bSizer6->Add( 0, 0, 1, wxEXPAND, 5 );
wxBoxSizer* bSizer7;
bSizer7 = new wxBoxSizer( wxHORIZONTAL );
bSizer7->Add( 0, 0, 1, wxEXPAND, 5 );
m_cancelButton = new wxButton( this, wxID_ANY, wxT("Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
bSizer7->Add( m_cancelButton, 0, wxALL, 5 );
m_OkButton = new wxButton( this, wxID_ANY, wxT("Ok"), wxDefaultPosition, wxDefaultSize, 0 );
bSizer7->Add( m_OkButton, 0, wxALL, 5 );
bSizer6->Add( bSizer7, 1, wxEXPAND, 5 );
bSizer6->Add( 0, 0, 1, wxEXPAND, 5 );
this->SetSizer( bSizer6 );
this->Layout();
this->Centre( wxBOTH );
// Connect Events
m_soapyModule->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( SDRDeviceAddForm::OnSoapyModuleChanged ), NULL, this );
m_cancelButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SDRDeviceAddForm::OnCancelButton ), NULL, this );
m_OkButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SDRDeviceAddForm::OnOkButton ), NULL, this );
}
SDRDeviceAddForm::~SDRDeviceAddForm()
{
// Disconnect Events
m_soapyModule->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( SDRDeviceAddForm::OnSoapyModuleChanged ), NULL, this );
m_cancelButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SDRDeviceAddForm::OnCancelButton ), NULL, this );
m_OkButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SDRDeviceAddForm::OnOkButton ), NULL, this );
}

View File

@ -0,0 +1,56 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Aug 23 2015)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#ifndef __SDRDEVICEADDFORM_H__
#define __SDRDEVICEADDFORM_H__
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/string.h>
#include <wx/stattext.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/choice.h>
#include <wx/textctrl.h>
#include <wx/button.h>
#include <wx/sizer.h>
#include <wx/dialog.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class SDRDeviceAddForm
///////////////////////////////////////////////////////////////////////////////
class SDRDeviceAddForm : public wxDialog
{
private:
protected:
wxStaticText* m_staticText4;
wxChoice* m_soapyModule;
wxStaticText* m_paramLabel;
wxTextCtrl* m_paramText;
wxButton* m_cancelButton;
wxButton* m_OkButton;
// Virtual event handlers, overide them in your derived class
virtual void OnSoapyModuleChanged( wxCommandEvent& event ) { event.Skip(); }
virtual void OnCancelButton( wxCommandEvent& event ) { event.Skip(); }
virtual void OnOkButton( wxCommandEvent& event ) { event.Skip(); }
public:
SDRDeviceAddForm( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Add SoapySDR Device"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 395,241 ), long style = wxDEFAULT_DIALOG_STYLE );
~SDRDeviceAddForm();
};
#endif //__SDRDEVICEADDFORM_H__

View File

@ -14,6 +14,8 @@ SDRDevicesDialog::SDRDevicesDialog( wxWindow* parent ): devFrame( parent ) {
m_deviceTimer.Start(250);
selId = nullptr;
editId = nullptr;
removeId = nullptr;
devAddDialog = nullptr;
}
void SDRDevicesDialog::OnClose( wxCloseEvent& event ) {
@ -95,7 +97,7 @@ wxPGProperty *SDRDevicesDialog::addArgInfoProperty(wxPropertyGrid *pg, SoapySDR:
void SDRDevicesDialog::OnSelectionChanged( wxTreeEvent& event ) {
SDRDeviceInfo *selDev = getSelectedDevice(devTree->GetSelection());
if (selDev) {
if (selDev && selDev->isAvailable()) {
dev = selDev;
selId = devTree->GetSelection();
DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice(dev->getName());
@ -109,7 +111,9 @@ void SDRDevicesDialog::OnSelectionChanged( wxTreeEvent& event ) {
devSettings.erase(devSettings.begin(),devSettings.end());
devSettings["name"] = m_propertyGrid->Append( new wxStringProperty("Name", wxPG_LABEL, devConfig->getDeviceName()) );
devSettings["offset"] = m_propertyGrid->Append( new wxIntProperty("Offset (Hz)", wxPG_LABEL, devConfig->getOffset()) );
props.erase(props.begin(), props.end());
if (args.size()) {
m_propertyGrid->Append(new wxPropertyCategory("Run-time Settings"));
@ -143,29 +147,81 @@ void SDRDevicesDialog::OnSelectionChanged( wxTreeEvent& event ) {
}
}
if (selDev->isManual()) {
m_addRemoteButton->SetLabel("Remove");
removeId = selId;
} else {
m_addRemoteButton->SetLabel("Add");
removeId = nullptr;
}
} else if (selDev && !selDev->isAvailable() && selDev->isManual()) {
m_propertyGrid->Clear();
devSettings.erase(devSettings.begin(),devSettings.end());
props.erase(props.begin(), props.end());
removeId = devTree->GetSelection();
dev = nullptr;
selId = nullptr;
editId = nullptr;
m_addRemoteButton->SetLabel("Remove");
} else if (!selDev) {
m_addRemoteButton->SetLabel("Add");
removeId = nullptr;
}
event.Skip();
}
void SDRDevicesDialog::OnAddRemote( wxMouseEvent& event ) {
if (!SDREnumerator::hasRemoteModule()) {
wxMessageDialog *info;
info = new wxMessageDialog(NULL, wxT("Install SoapyRemote module to add remote servers.\n\nhttps://github.com/pothosware/SoapyRemote"), wxT("SoapyRemote not found."), wxOK | wxICON_ERROR);
info->ShowModal();
if (removeId != nullptr) {
SDRDeviceInfo *selDev = getSelectedDevice(removeId);
if (selDev) {
SDREnumerator::removeManual(selDev->getDriver(),selDev->getManualParams());
m_propertyGrid->Clear();
devSettings.erase(devSettings.begin(),devSettings.end());
props.erase(props.begin(), props.end());
dev = nullptr;
selId = nullptr;
editId = nullptr;
devTree->Delete(removeId);
removeId = nullptr;
m_addRemoteButton->SetLabel("Add");
}
return;
}
wxString remoteAddr =
wxGetTextFromUser("Remote Address (address[:port])\n\ni.e. 'raspberrypi.local', '192.168.1.103:1234'\n","SoapySDR Remote Address", "", this);
devAddDialog = new SDRDeviceAddDialog(this);
devAddDialog->ShowModal();
if (devAddDialog->wasOkPressed()) {
std::string module = devAddDialog->getSelectedModule();
if (module == "SoapyRemote") {
if (!SDREnumerator::hasRemoteModule()) {
wxMessageDialog *info;
info = new wxMessageDialog(NULL, wxT("Install SoapyRemote module to add remote servers.\n\nhttps://github.com/pothosware/SoapyRemote"), wxT("SoapyRemote not found."), wxOK | wxICON_ERROR);
info->ShowModal();
return;
}
if (!remoteAddr.Trim().empty()) {
wxGetApp().addRemote(remoteAddr.Trim().ToStdString());
wxString remoteAddr = devAddDialog->getModuleParam();
if (!remoteAddr.Trim().empty()) {
wxGetApp().addRemote(remoteAddr.Trim().ToStdString());
}
devTree->Disable();
m_addRemoteButton->Disable();
m_useSelectedButton->Disable();
refresh = true;
} else {
std::string mod = devAddDialog->getSelectedModule();
std::string param = devAddDialog->getModuleParam();
SDREnumerator::addManual(mod, param);
doRefreshDevices();
}
}
devTree->Disable();
m_addRemoteButton->Disable();
m_useSelectedButton->Disable();
refresh = true;
}
SDRDeviceInfo *SDRDevicesDialog::getSelectedDevice(wxTreeItemId selId) {
@ -263,14 +319,26 @@ void SDRDevicesDialog::OnDeviceTimer( wxTimerEvent& event ) {
wxTreeItemId localBranch = devTree->AppendItem(devRoot, "Local");
wxTreeItemId dsBranch = devTree->AppendItem(devRoot, "Local Net");
wxTreeItemId remoteBranch = devTree->AppendItem(devRoot, "Remote");
wxTreeItemId manualBranch = devTree->AppendItem(devRoot, "Manual");
devs[""] = SDREnumerator::enumerate_devices("",true);
if (devs[""] != NULL) {
for (devs_i = devs[""]->begin(); devs_i != devs[""]->end(); devs_i++) {
DeviceConfig *devConfig = wxGetApp().getConfig()->getDevice((*devs_i)->getDeviceId());
if ((*devs_i)->isRemote()) {
DeviceConfig *devConfig = nullptr;
if ((*devs_i)->isManual()) {
std::string devName = "Unknown";
if ((*devs_i)->isAvailable()) {
devConfig = wxGetApp().getConfig()->getDevice((*devs_i)->getDeviceId());
devName = devConfig->getDeviceName();
} else {
devName = (*devs_i)->getDeviceId();
}
devItems[devTree->AppendItem(manualBranch, devName)] = (*devs_i);
} else if ((*devs_i)->isRemote()) {
devConfig = wxGetApp().getConfig()->getDevice((*devs_i)->getDeviceId());
devItems[devTree->AppendItem(dsBranch, devConfig->getDeviceName())] = (*devs_i);
} else {
devConfig = wxGetApp().getConfig()->getDevice((*devs_i)->getDeviceId());
devItems[devTree->AppendItem(localBranch, devConfig->getDeviceName())] = (*devs_i);
}
}
@ -308,20 +376,7 @@ void SDRDevicesDialog::OnDeviceTimer( wxTimerEvent& event ) {
}
void SDRDevicesDialog::OnRefreshDevices( wxMouseEvent& event ) {
wxGetApp().stopDevice();
devTree->DeleteAllItems();
devTree->Disable();
m_propertyGrid->Clear();
props.erase(props.begin(),props.end());
devSettings.erase(devSettings.begin(), devSettings.end());
m_refreshButton->Disable();
m_addRemoteButton->Disable();
m_useSelectedButton->Disable();
wxGetApp().reEnumerateDevices();
selId = nullptr;
editId = nullptr;
dev = nullptr;
refresh = true;
doRefreshDevices();
}
void SDRDevicesDialog::OnPropGridChanged( wxPropertyGridEvent& event ) {
@ -354,3 +409,23 @@ void SDRDevicesDialog::OnPropGridChanged( wxPropertyGridEvent& event ) {
void SDRDevicesDialog::OnPropGridFocus( wxFocusEvent& event ) {
editId = selId;
}
void SDRDevicesDialog::doRefreshDevices() {
wxGetApp().stopDevice();
devTree->DeleteAllItems();
devTree->Disable();
m_propertyGrid->Clear();
props.erase(props.begin(),props.end());
devSettings.erase(devSettings.begin(), devSettings.end());
m_refreshButton->Disable();
m_addRemoteButton->Disable();
m_useSelectedButton->Disable();
wxGetApp().reEnumerateDevices();
selId = nullptr;
editId = nullptr;
removeId = nullptr;
dev = nullptr;
refresh = true;
m_addRemoteButton->SetLabel("Add");
}

View File

@ -493,7 +493,7 @@
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<property name="proportion">1</property>
<object class="wxButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
@ -611,7 +611,7 @@
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Add Remote</property>
<property name="label">Add</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
@ -699,7 +699,7 @@
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Use Selected</property>
<property name="label">Start</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>

View File

@ -6,6 +6,7 @@
#include "SDRDevicesForm.h"
#include "SoapySDRThread.h"
#include "SDREnumerator.h"
#include "SDRDeviceAdd.h"
class SDRDevicesDialog: public devFrame {
public:
@ -23,6 +24,8 @@ public:
void OnPropGridFocus( wxFocusEvent& event );
private:
void doRefreshDevices();
SDRDeviceInfo *getSelectedDevice(wxTreeItemId selId);
wxPGProperty *addArgInfoProperty(wxPropertyGrid *pg, SoapySDR::ArgInfo arg);
@ -36,4 +39,6 @@ private:
std::map<std::string, wxPGProperty *> devSettings;
wxTreeItemId selId;
wxTreeItemId editId;
wxTreeItemId removeId;
SDRDeviceAddDialog *devAddDialog;
};

View File

@ -35,12 +35,12 @@ devFrame::devFrame( wxWindow* parent, wxWindowID id, const wxString& title, cons
bSizer5 = new wxBoxSizer( wxHORIZONTAL );
m_refreshButton = new wxButton( m_panel4, wxID_ANY, wxT("Refresh"), wxDefaultPosition, wxDefaultSize, 0 );
bSizer5->Add( m_refreshButton, 0, wxALL, 5 );
bSizer5->Add( m_refreshButton, 1, wxALL, 5 );
m_addRemoteButton = new wxButton( m_panel4, wxID_ANY, wxT("Add Remote"), wxDefaultPosition, wxDefaultSize, 0 );
m_addRemoteButton = new wxButton( m_panel4, wxID_ANY, wxT("Add"), wxDefaultPosition, wxDefaultSize, 0 );
bSizer5->Add( m_addRemoteButton, 1, wxALL, 5 );
m_useSelectedButton = new wxButton( m_panel4, wxID_ANY, wxT("Use Selected"), wxDefaultPosition, wxDefaultSize, 0 );
m_useSelectedButton = new wxButton( m_panel4, wxID_ANY, wxT("Start"), wxDefaultPosition, wxDefaultSize, 0 );
bSizer5->Add( m_useSelectedButton, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 );

View File

@ -160,7 +160,7 @@ std::vector<std::string> SDRDeviceChannel::getStreamArgNames() {
}
SDRDeviceInfo::SDRDeviceInfo() : name(""), serial(""), available(false), remote(false) {
SDRDeviceInfo::SDRDeviceInfo() : name(""), serial(""), available(false), remote(false), manual(false) {
}
@ -262,6 +262,22 @@ void SDRDeviceInfo::setRemote(bool remote) {
this->remote = remote;
}
bool SDRDeviceInfo::isManual() const {
return manual;
}
void SDRDeviceInfo::setManual(bool manual) {
this->manual = manual;
}
void SDRDeviceInfo::setManualParams(std::string manualParams) {
this->manual_params = manualParams;
}
std::string SDRDeviceInfo::getManualParams() {
return manual_params;
}
void SDRDeviceInfo::setDeviceArgs(SoapySDR::Kwargs deviceArgs) {
this->deviceArgs = deviceArgs;
}

View File

@ -5,32 +5,10 @@
#include <SoapySDR/Types.hpp>
/*
----------------------------------------------------
-- Device identification
----------------------------------------------------
driver=rtl
hardware=rtl
----------------------------------------------------
-- Peripheral summary
----------------------------------------------------
Channels: 1 Rx, 0 Tx
Timestamps: NO
----------------------------------------------------
-- RX Channel 0
----------------------------------------------------
Full-duplex: YES
Antennas: RX
Full gain range: [0, 49.6] dB
LNA gain range: [0, 49.6] dB
Full freq range: [24, 1766] MHz
RF freq range: [24, 1766] MHz
CORR freq range: MHz
Sample rates: [0.25, 2.56] MHz
Filter bandwidths: [] MHz
*/
typedef struct _SDRManualDef {
std::string factory;
std::string params;
} SDRManualDef;
class SDRDeviceRange {
public:
@ -139,7 +117,13 @@ public:
bool isRemote() const;
void setRemote(bool remote);
bool isManual() const;
void setManual(bool manual);
void setManualParams(std::string manualParams);
std::string getManualParams();
void addChannel(SDRDeviceChannel *chan);
std::vector<SDRDeviceChannel *> &getChannels();
SDRDeviceChannel * getRxChannel();
@ -159,8 +143,8 @@ public:
private:
int index;
std::string name, serial, product, manufacturer, tuner;
std::string driver, hardware;
bool timestamps, available, remote;
std::string driver, hardware, manual_params;
bool timestamps, available, remote, manual;
SoapySDR::Kwargs deviceArgs, streamArgs;
SoapySDR::ArgInfoList settingInfo;

View File

@ -11,6 +11,7 @@ std::vector<std::string> SDREnumerator::remotes;
std::map< std::string, std::vector<SDRDeviceInfo *> > SDREnumerator::devs;
bool SDREnumerator::soapy_initialized = false;
bool SDREnumerator::has_remote = false;
std::vector<SDRManualDef> SDREnumerator::manuals;
SDREnumerator::SDREnumerator() : IOThread() {
@ -20,6 +21,48 @@ SDREnumerator::~SDREnumerator() {
}
// Some utility from SoapySDR :)
static std::string trim(const std::string &s)
{
std::string out = s;
while (not out.empty() and std::isspace(out[0])) out = out.substr(1);
while (not out.empty() and std::isspace(out[out.size()-1])) out = out.substr(0, out.size()-1);
return out;
}
SoapySDR::Kwargs SDREnumerator::argsStrToKwargs(const std::string &args)
{
SoapySDR::Kwargs kwargs;
bool inKey = true;
std::string key, val;
for (size_t i = 0; i < args.size(); i++)
{
const char ch = args[i];
if (inKey)
{
if (ch == '=') inKey = false;
else if (ch == ',') inKey = true;
else key += ch;
}
else
{
if (ch == ',') inKey = true;
else val += ch;
}
if ((inKey and not val.empty()) or ((i+1) == args.size()))
{
key = trim(key);
val = trim(val);
if (not key.empty()) kwargs[key] = val;
key = "";
val = "";
}
}
return kwargs;
}
std::vector<SDRDeviceInfo *> *SDREnumerator::enumerate_devices(std::string remoteAddr, bool noInit) {
@ -77,14 +120,7 @@ std::vector<SDRDeviceInfo *> *SDREnumerator::enumerate_devices(std::string remot
#endif
}
// 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());
}
@ -113,6 +149,8 @@ std::vector<SDRDeviceInfo *> *SDREnumerator::enumerate_devices(std::string remot
soapy_initialized = true;
}
modules = SoapySDR::listModules();
std::vector<SoapySDR::Kwargs> results;
SoapySDR::Kwargs enumArgs;
bool isRemote = false;
@ -128,6 +166,37 @@ std::vector<SDRDeviceInfo *> *SDREnumerator::enumerate_devices(std::string remot
results = SoapySDR::Device::enumerate();
}
int manualsIdx = results.size();
std::vector<std::string> manualParams;
std::vector<bool> manualResult;
if (manuals.size()) {
for (std::vector<SDRManualDef>::const_iterator m_i = manuals.begin(); m_i != manuals.end(); m_i++) {
std::vector<SoapySDR::Kwargs> manual_result;
std::string strDevArgs = "driver="+m_i->factory+","+m_i->params;
manualParams.push_back(m_i->params);
wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Enumerating manual device '") + strDevArgs + "'..");
manual_result = SoapySDR::Device::enumerate(strDevArgs);
if (manual_result.size()) {
for (std::vector<SoapySDR::Kwargs>::const_iterator i = manual_result.begin(); i != manual_result.end(); i++) {
results.push_back(*i);
manualResult.push_back(true);
}
} else {
SoapySDR::Kwargs failedEnum;
failedEnum = argsStrToKwargs(strDevArgs);
failedEnum["label"] = "Not Found ("+m_i->factory+")";
results.push_back(failedEnum);
manualResult.push_back(false);
}
}
}
if (isRemote) {
wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Opening remote server ") + remoteAddr + "..");
}
@ -145,7 +214,6 @@ std::vector<SDRDeviceInfo *> *SDREnumerator::enumerate_devices(std::string remot
}
}
DeviceConfig *cfg = wxGetApp().getConfig()->getDevice(dev->getDeviceId());
if (deviceArgs.count("remote")) {
isRemote = true;
@ -154,9 +222,13 @@ std::vector<SDRDeviceInfo *> *SDREnumerator::enumerate_devices(std::string remot
}
dev->setRemote(isRemote);
dev->setManual(i>=manualsIdx);
if (i>=manualsIdx) {
dev->setManualParams(manualParams[i-manualsIdx]);
}
std::cout << "Make device " << i << std::endl;
try {
if (i<manualsIdx || manualResult[i-manualsIdx]) try {
SoapySDR::Device *device = SoapySDR::Device::make(deviceArgs);
SoapySDR::Kwargs info = device->getHardwareInfo();
for (SoapySDR::Kwargs::const_iterator it = info.begin(); it != info.end(); ++it) {
@ -173,7 +245,9 @@ std::vector<SDRDeviceInfo *> *SDREnumerator::enumerate_devices(std::string remot
}
SoapySDR::ArgInfoList settingsInfo = device->getSettingInfo();
DeviceConfig *cfg = wxGetApp().getConfig()->getDevice(dev->getDeviceId());
ConfigSettings devSettings = cfg->getSettings();
if (devSettings.size()) {
for (ConfigSettings::const_iterator set_i = devSettings.begin(); set_i != devSettings.end(); set_i++) {
@ -253,6 +327,8 @@ std::vector<SDRDeviceInfo *> *SDREnumerator::enumerate_devices(std::string remot
std::cerr << "Error making device: " << ex.what() << std::endl;
wxGetApp().sdrEnumThreadNotify(SDREnumerator::SDR_ENUM_MESSAGE, std::string("Error querying device #") + std::to_string(i));
dev->setAvailable(false);
} else {
dev->setAvailable(false);
}
std::cout << std::endl;
@ -323,6 +399,36 @@ std::vector<std::string> &SDREnumerator::getRemotes() {
return remotes;
}
void SDREnumerator::addManual(std::string factory, std::string params) {
SDRManualDef def;
def.factory = factory;
def.params = params;
manuals.push_back(def);
}
void SDREnumerator::removeManual(std::string factory, std::string params) {
for (std::vector<SDRManualDef>::const_iterator i = manuals.begin(); i != manuals.end(); i++) {
if (i->factory == factory && i->params == params) {
manuals.erase(i);
for (std::vector<SDRDeviceInfo *>::const_iterator subdevs_i = devs[""].begin(); subdevs_i != devs[""].end(); subdevs_i++) {
if ((*subdevs_i)->isManual() && (*subdevs_i)->getDriver() == factory && (*subdevs_i)->getManualParams() == params) {
devs[""].erase(subdevs_i);
break;
}
}
break;
}
}
}
std::vector<SDRManualDef> &SDREnumerator::getManuals() {
return SDREnumerator::manuals;
}
void SDREnumerator::setManuals(std::vector<SDRManualDef> manuals) {
SDREnumerator::manuals = manuals;
}
bool SDREnumerator::hasRemoteModule() {
return SDREnumerator::has_remote;
}
@ -333,3 +439,7 @@ void SDREnumerator::reset() {
modules.erase(modules.begin(), modules.end());
devs.erase(devs.begin(), devs.end());
}
std::vector<std::string> &SDREnumerator::getFactories() {
return SDREnumerator::factories;
}

View File

@ -25,11 +25,17 @@ public:
void run();
static SoapySDR::Kwargs argsStrToKwargs(const std::string &args);
static void addRemote(std::string remoteAddr);
static void removeRemote(std::string remoteAddr);
static std::vector<std::string> &getRemotes();
static bool hasRemoteModule();
static void addManual(std::string factory, std::string params);
static void removeManual(std::string factory, std::string params);
static std::vector<SDRManualDef> &getManuals();
static void setManuals(std::vector<SDRManualDef> manuals);
static void reset();
static std::vector<std::string> &getFactories();
protected:
static bool soapy_initialized, has_remote;
@ -37,4 +43,6 @@ protected:
static std::vector<std::string> modules;
static std::vector<std::string> remotes;
static std::map< std::string, std::vector<SDRDeviceInfo *> > devs;
static std::vector<SDRManualDef> manuals;
static std::mutex devs_busy;
};