From c82d8387082141d5fea5bba16288f54abcb4e729 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 29 Oct 2018 16:39:25 +0100 Subject: [PATCH] SoapySDR support: build infrastructure and input plugin enumeration --- app/main.cpp | 2 +- appbench/main.cpp | 2 +- appsrv/main.cpp | 2 +- cmake/Modules/FindSoapySDR.cmake | 34 +++++ debian/changelog | 6 + devices/CMakeLists.txt | 6 + devices/readme.md | 4 + devices/soapysdr/CMakeLists.txt | 46 ++++++ devices/soapysdr/devicesoapysdrscan.cpp | 128 +++++++++++++++++ devices/soapysdr/devicesoapysdrscan.h | 51 +++++++ plugins/samplesource/CMakeLists.txt | 8 ++ .../bladerf2input/bladerf2inputgui.h | 6 +- .../samplesource/soapysdrinput/CMakeLists.txt | 78 +++++++++++ .../soapysdrinput/soapysdrinput.cpp | 80 +++++++++++ .../soapysdrinput/soapysdrinput.h | 56 ++++++++ .../soapysdrinput/soapysdrinputgui.cpp | 86 ++++++++++++ .../soapysdrinput/soapysdrinputgui.h | 70 ++++++++++ .../soapysdrinput/soapysdrinputplugin.cpp | 132 ++++++++++++++++++ .../soapysdrinput/soapysdrinputplugin.h | 56 ++++++++ 19 files changed, 847 insertions(+), 6 deletions(-) create mode 100644 cmake/Modules/FindSoapySDR.cmake create mode 100644 devices/soapysdr/CMakeLists.txt create mode 100644 devices/soapysdr/devicesoapysdrscan.cpp create mode 100644 devices/soapysdr/devicesoapysdrscan.h create mode 100644 plugins/samplesource/soapysdrinput/CMakeLists.txt create mode 100644 plugins/samplesource/soapysdrinput/soapysdrinput.cpp create mode 100644 plugins/samplesource/soapysdrinput/soapysdrinput.h create mode 100644 plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp create mode 100644 plugins/samplesource/soapysdrinput/soapysdrinputgui.h create mode 100644 plugins/samplesource/soapysdrinput/soapysdrinputplugin.cpp create mode 100644 plugins/samplesource/soapysdrinput/soapysdrinputplugin.h diff --git a/app/main.cpp b/app/main.cpp index 8470d5f6e..8d1f8de47 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -35,7 +35,7 @@ static int runQtApplication(int argc, char* argv[], qtwebapp::LoggerWithFile *lo */ QCoreApplication::setOrganizationName("f4exb"); QCoreApplication::setApplicationName("SDRangel"); - QCoreApplication::setApplicationVersion("4.2.4"); + QCoreApplication::setApplicationVersion("4.3.0"); #if QT_VERSION >= 0x050600 QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // DPI support QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); //HiDPI pixmaps diff --git a/appbench/main.cpp b/appbench/main.cpp index 055fdb98c..1bb7f1f5f 100644 --- a/appbench/main.cpp +++ b/appbench/main.cpp @@ -57,7 +57,7 @@ static int runQtApplication(int argc, char* argv[], qtwebapp::LoggerWithFile *lo QCoreApplication::setOrganizationName("f4exb"); QCoreApplication::setApplicationName("SDRangelBench"); - QCoreApplication::setApplicationVersion("4.2.4"); + QCoreApplication::setApplicationVersion("4.3.0"); int catchSignals[] = {SIGQUIT, SIGINT, SIGTERM, SIGHUP}; std::vector vsig(catchSignals, catchSignals + sizeof(catchSignals) / sizeof(int)); diff --git a/appsrv/main.cpp b/appsrv/main.cpp index 0c7f89079..e11724111 100644 --- a/appsrv/main.cpp +++ b/appsrv/main.cpp @@ -56,7 +56,7 @@ static int runQtApplication(int argc, char* argv[], qtwebapp::LoggerWithFile *lo QCoreApplication::setOrganizationName("f4exb"); QCoreApplication::setApplicationName("SDRangelSrv"); - QCoreApplication::setApplicationVersion("4.2.4"); + QCoreApplication::setApplicationVersion("4.3.0"); int catchSignals[] = {SIGQUIT, SIGINT, SIGTERM, SIGHUP}; std::vector vsig(catchSignals, catchSignals + sizeof(catchSignals) / sizeof(int)); diff --git a/cmake/Modules/FindSoapySDR.cmake b/cmake/Modules/FindSoapySDR.cmake new file mode 100644 index 000000000..cf8e274c9 --- /dev/null +++ b/cmake/Modules/FindSoapySDR.cmake @@ -0,0 +1,34 @@ +# Find Soapy SDR + +if (NOT SOAPYSDR_INCLUDE_DIR) + FIND_PATH (SOAPYSDR_INCLUDE_DIR + NAMES SoapySDR/Version.h + PATHS + /usr/include + /usr/local/include + ) +endif() + +if (NOT SOAPYSDR_LIBRARY) + FIND_LIBRARY (SOAPYSDR_LIBRARY + NAMES SoapySDR + HINTS ${CMAKE_INSTALL_PREFIX}/lib + ${CMAKE_INSTALL_PREFIX}/lib64 + PATHS /usr/local/lib + /usr/local/lib64 + /usr/lib + /usr/lib64 + ) +endif() + +if (SOAPYSDR_INCLUDE_DIR AND SOAPYSDR_LIBRARY) + SET(SOAPYSDR_FOUND TRUE) +endif() + +if (SOAPYSDR_FOUND) + MESSAGE (STATUS "Found SoapySDR: ${SOAPYSDR_INCLUDE_DIR}, ${SOAPYSDR_LIBRARY}") +else() + MESSAGE (STATUS "Could not find SoapySDR") +endif() + +mark_as_advanced(SOAPYSDR_INCLUDE_DIR SOAPYSDR_LIBRARY) diff --git a/debian/changelog b/debian/changelog index b84f7bfb6..b3dec420b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +sdrangel (4.3.0-1) unstable; urgency=medium + + * SoapySDR support + + -- Edouard Griffiths, F4EXB Sun, 04 Nov 2018 21:14:18 +0200 + sdrangel (4.2.4-1) unstable; urgency=medium * LimeSDR: use LimeSuite 18.10.0 for builds diff --git a/devices/CMakeLists.txt b/devices/CMakeLists.txt index 5437b4595..9626e5db9 100644 --- a/devices/CMakeLists.txt +++ b/devices/CMakeLists.txt @@ -9,6 +9,7 @@ if (BUILD_DEBIAN) add_subdirectory(limesdr) add_subdirectory(perseus) add_subdirectory(plutosdr) + add_subdirectory(soapysdr) else(BUILD_DEBIAN) find_package(LibBLADERF) if(LIBUSB_FOUND AND LIBBLADERF_FOUND) @@ -35,4 +36,9 @@ else(BUILD_DEBIAN) if(LIBUSB_FOUND AND LIBPERSEUS_FOUND) add_subdirectory(perseus) endif() + + find_package(SoapySDR) + if(LIBUSB_FOUND AND SOAPYSDR_FOUND) + add_subdirectory(soapysdr) + endif() endif (BUILD_DEBIAN) diff --git a/devices/readme.md b/devices/readme.md index f6b28ca62..21e334eff 100644 --- a/devices/readme.md +++ b/devices/readme.md @@ -21,3 +21,7 @@ This folder contains classes and methods that can be used by different plugins t - PlutoSDR: one Rx and one Tx full duplex. Plugins are - plutosdrinput - plutosdroutput + + - SoapySDR: Soapy SDR virtual device + - soapysdrinput + - soapysdroutput \ No newline at end of file diff --git a/devices/soapysdr/CMakeLists.txt b/devices/soapysdr/CMakeLists.txt new file mode 100644 index 000000000..57f627bd9 --- /dev/null +++ b/devices/soapysdr/CMakeLists.txt @@ -0,0 +1,46 @@ +project(soapysdrdevice) + +set (CMAKE_CXX_STANDARD 11) + +set(soapysdrdevice_SOURCES + devicesoapysdrscan.cpp +) + +set(soapysdrdevice_HEADERS + devicesoapysdrscan.h +) + +if (BUILD_DEBIAN) +include_directories( + . + ${CMAKE_CURRENT_BINARY_DIR} + ${SOAPYSDRSRC} +) +else (BUILD_DEBIAN) +include_directories( + . + ${CMAKE_CURRENT_BINARY_DIR} + ${SOAPYSDR_INCLUDE_DIR} +) +endif (BUILD_DEBIAN) + +#add_definitions(${QT_DEFINITIONS}) +#add_definitions(-DQT_SHARED) + +add_library(soapysdrdevice SHARED + ${soapysdrdevice_SOURCES} +) + +if (BUILD_DEBIAN) +target_link_libraries(soapysdrdevice + soapysdr + sdrbase +) +else (BUILD_DEBIAN) +target_link_libraries(soapysdrdevice + ${SOAPYSDR_LIBRARY} + sdrbase +) +endif (BUILD_DEBIAN) + +install(TARGETS soapysdrdevice DESTINATION lib) diff --git a/devices/soapysdr/devicesoapysdrscan.cpp b/devices/soapysdr/devicesoapysdrscan.cpp new file mode 100644 index 000000000..2be76ab72 --- /dev/null +++ b/devices/soapysdr/devicesoapysdrscan.cpp @@ -0,0 +1,128 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#include +#include + +#include "devicesoapysdrscan.h" + +void DeviceSoapySDRScan::scan() +{ + qDebug("DeviceSoapySDRScan::scan: Lib Version: v%s", SoapySDR::getLibVersion().c_str()); + qDebug("DeviceSoapySDRScan::scan: API Version: v%s", SoapySDR::getAPIVersion().c_str()); + qDebug("DeviceSoapySDRScan::scan: ABI Version: v%s", SoapySDR::getABIVersion().c_str()); + qDebug("DeviceSoapySDRScan::scan: Install root: %s", SoapySDR::getRootPath().c_str()); + + const std::vector& modules = SoapySDR::listModules(); + + for (const auto &it : modules) + { + const auto &errMsg = SoapySDR::loadModule(it); + + if (not errMsg.empty()) { + qWarning("DeviceSoapySDRScan::scan: cannot load module %s: %s", it.c_str(), errMsg.c_str()); + } else { + qDebug("DeviceSoapySDRScan::scan: loaded module: %s", it.c_str()); + } + } + + SoapySDR::FindFunctions findFunctions = SoapySDR::Registry::listFindFunctions(); + SoapySDR::Kwargs kwargs; + m_deviceEnums.clear(); + + for (const auto &it : findFunctions) // for each driver + { + qDebug("DeviceSoapySDRScan::scan: driver: %s", it.first.c_str()); + kwargs["driver"] = it.first; + + SoapySDR::KwargsList kwargsList = SoapySDR::Device::enumerate(kwargs); + SoapySDR::KwargsList::const_iterator kit = kwargsList.begin(); + + for (int deviceSeq = 0; kit != kwargsList.end(); ++kit, deviceSeq++) // for each device + { + m_deviceEnums.push_back(SoapySDRDeviceEnum()); + m_deviceEnums.back().m_driverName = QString(it.first.c_str()); + + // collect identification information + for (SoapySDR::Kwargs::const_iterator kargIt = kit->begin(); kargIt != kit->end(); ++kargIt) + { + if (kargIt->first == "label") + { + m_deviceEnums.back().m_label = QString(kargIt->second.c_str()); + qDebug("DeviceSoapySDRScan::scan: %s #%u %s", + m_deviceEnums.back().m_driverName.toStdString().c_str(), + deviceSeq, + kargIt->second.c_str()); + } + else if ((m_deviceEnums.back().m_idKey.size() == 0) && (kargIt->first == "serial")) + { + m_deviceEnums.back().m_idKey = QString(kargIt->first.c_str()); + m_deviceEnums.back().m_idValue = QString(kargIt->second.c_str()); + } + else if ((m_deviceEnums.back().m_idKey.size() == 0) && (kargIt->first == "device_id")) + { + m_deviceEnums.back().m_idKey = QString(kargIt->first.c_str()); + m_deviceEnums.back().m_idValue = QString(kargIt->second.c_str()); + } + else if ((m_deviceEnums.back().m_idKey.size() == 0) && (kargIt->first == "addr")) + { + m_deviceEnums.back().m_idKey = QString(kargIt->first.c_str()); + m_deviceEnums.back().m_idValue = QString(kargIt->second.c_str()); + } + } + + // access the device to get the number of Rx and Tx channels and at the same time probe + // whether it is available for Soapy + + try + { + SoapySDR::Device *device; + SoapySDR::Kwargs kwargs; + kwargs["driver"] = m_deviceEnums.back().m_driverName.toStdString(); + + if (m_deviceEnums.back().m_idKey.size() > 0) { + kwargs[m_deviceEnums.back().m_idKey.toStdString()] = m_deviceEnums.back().m_idValue.toStdString(); + } + + device = SoapySDR::Device::make(kwargs); + m_deviceEnums.back().m_nbRx = device->getNumChannels(SOAPY_SDR_RX); + m_deviceEnums.back().m_nbTx = device->getNumChannels(SOAPY_SDR_TX); + qDebug("DeviceSoapySDRScan::scan: %s #%u driver=%s hardware=%s #Rx=%u #Tx=%u", + m_deviceEnums.back().m_driverName.toStdString().c_str(), + deviceSeq, + device->getDriverKey().c_str(), + device->getHardwareKey().c_str(), + m_deviceEnums.back().m_nbRx, + m_deviceEnums.back().m_nbTx); + + SoapySDR::Device::unmake(device); + } + catch (const std::exception &ex) + { + qWarning("DeviceSoapySDRScan::scan: %s #%u cannot be opened: %s", + m_deviceEnums.back().m_driverName.toStdString().c_str(), + deviceSeq, + ex.what()); + m_deviceEnums.pop_back(); + } + } // for each device + } +} diff --git a/devices/soapysdr/devicesoapysdrscan.h b/devices/soapysdr/devicesoapysdrscan.h new file mode 100644 index 000000000..bfc7f80dc --- /dev/null +++ b/devices/soapysdr/devicesoapysdrscan.h @@ -0,0 +1,51 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef DEVICES_SOAPYSDR_DEVICESOAPYSDRSCAN_H_ +#define DEVICES_SOAPYSDR_DEVICESOAPYSDRSCAN_H_ + +#include + +#include + +#include "export.h" + +class DEVICES_API DeviceSoapySDRScan +{ +public: + struct SoapySDRDeviceEnum + { + QString m_driverName; + QString m_label; //!< the label key for display should always be present + QString m_idKey; //!< key to uniquely identify device + QString m_idValue; //!< value for the above key + uint32_t m_nbRx; + uint32_t m_nbTx; + + SoapySDRDeviceEnum() : m_nbRx(0), m_nbTx(0) + {} + }; + + void scan(); + uint32_t getNbDevices() const { return m_deviceEnums.size(); } + const std::vector& getDevicesEnumeration() const { return m_deviceEnums; } + +private: + std::vector m_deviceEnums; +}; + + +#endif /* DEVICES_SOAPYSDR_DEVICESOAPYSDRSCAN_H_ */ diff --git a/plugins/samplesource/CMakeLists.txt b/plugins/samplesource/CMakeLists.txt index c3c54d52a..93fc805c7 100644 --- a/plugins/samplesource/CMakeLists.txt +++ b/plugins/samplesource/CMakeLists.txt @@ -77,6 +77,14 @@ else(LIBUSB_FOUND AND LIBMIRISDR_FOUND) message(STATUS "LibMiriSDR NOT found") endif(LIBUSB_FOUND AND LIBMIRISDR_FOUND) +find_package(SoapySDR) +if(LIBUSB_FOUND AND SOAPYSDR_FOUND) + add_subdirectory(soapysdrinput) + message(STATUS "SoapySDR found") +else() + message(STATUS "SoapySDR not found") +endif() + if (BUILD_DEBIAN) add_subdirectory(airspy) add_subdirectory(airspyhf) diff --git a/plugins/samplesource/bladerf2input/bladerf2inputgui.h b/plugins/samplesource/bladerf2input/bladerf2inputgui.h index 33ff82bd7..665670f3d 100644 --- a/plugins/samplesource/bladerf2input/bladerf2inputgui.h +++ b/plugins/samplesource/bladerf2input/bladerf2inputgui.h @@ -42,11 +42,11 @@ public: void setName(const QString& name); QString getName() const; - void resetToDefaults(); + virtual void resetToDefaults(); virtual qint64 getCenterFrequency() const; virtual void setCenterFrequency(qint64 centerFrequency); - QByteArray serialize() const; - bool deserialize(const QByteArray& data); + virtual QByteArray serialize() const; + virtual bool deserialize(const QByteArray& data); virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } virtual bool handleMessage(const Message& message); diff --git a/plugins/samplesource/soapysdrinput/CMakeLists.txt b/plugins/samplesource/soapysdrinput/CMakeLists.txt new file mode 100644 index 000000000..9e461fb3c --- /dev/null +++ b/plugins/samplesource/soapysdrinput/CMakeLists.txt @@ -0,0 +1,78 @@ +project(soapysdrinput) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +set(soapysdrinput_SOURCES + soapysdrinputgui.cpp + soapysdrinput.cpp + soapysdrinputplugin.cpp +# soapysdrinputsettings.cpp +# soapysdrinputthread.cpp +) + +set(soapysdrinput_HEADERS + soapysdrinputgui.h + soapysdrinput.h + soapysdrinputplugin.h +# soapysdrinputsettings.h +# soapysdrinputthread.h +) + +set(soapysdrinput_FORMS +# soapysdrinputgui.ui +) + +if (BUILD_DEBIAN) +include_directories( + . + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client + ${CMAKE_SOURCE_DIR}/devices + ${SOAPYSDRSRC}/include + ${SOAPYSDRSRC}/src +) +else (BUILD_DEBIAN) +include_directories( + . + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client + ${CMAKE_SOURCE_DIR}/devices + ${SOAPYSDR_INCLUDE_DIR} +) +endif (BUILD_DEBIAN) + +add_definitions(${QT_DEFINITIONS}) +add_definitions(-DQT_PLUGIN) +add_definitions(-DQT_SHARED) + +qt5_wrap_ui(soapysdrinput_FORMS_HEADERS ${soapysdrinput_FORMS}) + +add_library(inputsoapysdr SHARED + ${soapysdrinput_SOURCES} + ${soapysdrinput_HEADERS_MOC} + ${soapysdrinput_FORMS_HEADERS} +) + +if (BUILD_DEBIAN) +target_link_libraries(inputsoapysdr + ${QT_LIBRARIES} + bladerf + sdrbase + sdrgui + swagger + soapysdrdevice +) +else (BUILD_DEBIAN) +target_link_libraries(inputsoapysdr + ${QT_LIBRARIES} + ${SOAPYSDR_LIBRARY} + sdrbase + sdrgui + swagger + soapysdrdevice +) +endif (BUILD_DEBIAN) + +target_link_libraries(inputsoapysdr Qt5::Core Qt5::Widgets) + +install(TARGETS inputsoapysdr DESTINATION lib/plugins/samplesource) diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.cpp b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp new file mode 100644 index 000000000..70597a8bb --- /dev/null +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.cpp @@ -0,0 +1,80 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "util/simpleserializer.h" + +#include "soapysdrinput.h" + +SoapySDRInput::SoapySDRInput(DeviceSourceAPI *deviceAPI) +{ +} + +SoapySDRInput::~SoapySDRInput() +{ +} + +void SoapySDRInput::destroy() +{ + delete this; +} + +void SoapySDRInput::init() +{ +} + +bool SoapySDRInput::start() +{ + return false; +} + +void SoapySDRInput::stop() +{ +} + +QByteArray SoapySDRInput::serialize() const +{ + SimpleSerializer s(1); + return s.final(); +} + +bool SoapySDRInput::deserialize(const QByteArray& data) +{ + return false; +} + +const QString& SoapySDRInput::getDeviceDescription() const +{ + return m_deviceDescription; +} + +int SoapySDRInput::getSampleRate() const +{ + return 0; +} + +quint64 SoapySDRInput::getCenterFrequency() const +{ + return 0; +} + +void SoapySDRInput::setCenterFrequency(qint64 centerFrequency) +{ +} + +bool SoapySDRInput::handleMessage(const Message& message) +{ + return false; +} diff --git a/plugins/samplesource/soapysdrinput/soapysdrinput.h b/plugins/samplesource/soapysdrinput/soapysdrinput.h new file mode 100644 index 000000000..0beeb42d3 --- /dev/null +++ b/plugins/samplesource/soapysdrinput/soapysdrinput.h @@ -0,0 +1,56 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef PLUGINS_SAMPLESOURCE_SOAPYSDRINPUT_SOAPYSDRINPUT_H_ +#define PLUGINS_SAMPLESOURCE_SOAPYSDRINPUT_SOAPYSDRINPUT_H_ + +#include +#include +#include + +#include "dsp/devicesamplesource.h" + +class DeviceSourceAPI; + +class SoapySDRInput : public DeviceSampleSource +{ +public: + SoapySDRInput(DeviceSourceAPI *deviceAPI); + virtual ~SoapySDRInput(); + virtual void destroy(); + + virtual void init(); + virtual bool start(); + virtual void stop(); + + virtual QByteArray serialize() const; + virtual bool deserialize(const QByteArray& data); + + virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; } + virtual const QString& getDeviceDescription() const; + virtual int getSampleRate() const; + virtual quint64 getCenterFrequency() const; + virtual void setCenterFrequency(qint64 centerFrequency); + + virtual bool handleMessage(const Message& message); + +private: + QString m_deviceDescription; +}; + + + +#endif /* PLUGINS_SAMPLESOURCE_SOAPYSDRINPUT_SOAPYSDRINPUT_H_ */ diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp b/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp new file mode 100644 index 000000000..fe29fb4d0 --- /dev/null +++ b/plugins/samplesource/soapysdrinput/soapysdrinputgui.cpp @@ -0,0 +1,86 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "dsp/dspengine.h" +#include "dsp/dspcommands.h" +#include "device/devicesourceapi.h" +#include "device/deviceuiset.h" +#include "util/simpleserializer.h" + +#include "soapysdrinputgui.h" + +SoapySDRInputGui::SoapySDRInputGui(DeviceUISet *deviceUISet, QWidget* parent) : + QWidget(parent), + ui(0), + m_deviceUISet(deviceUISet), + m_forceSettings(true), + m_doApplySettings(true), + m_sampleSource(0), + m_sampleRate(0), + m_lastEngineState(DSPDeviceSourceEngine::StNotStarted) +{ +} + +SoapySDRInputGui::~SoapySDRInputGui() +{ +} + +void SoapySDRInputGui::destroy() +{ + delete this; +} + +void SoapySDRInputGui::setName(const QString& name) +{ + setObjectName(name); +} + +QString SoapySDRInputGui::getName() const +{ + return objectName(); +} + +void SoapySDRInputGui::resetToDefaults() +{ +} + +qint64 SoapySDRInputGui::getCenterFrequency() const +{ + return 0; +} + +void SoapySDRInputGui::setCenterFrequency(qint64 centerFrequency __attribute__((unused))) +{ +} + +QByteArray SoapySDRInputGui::serialize() const +{ + SimpleSerializer s(1); + return s.final(); +} + +bool SoapySDRInputGui::deserialize(const QByteArray& data __attribute__((unused))) +{ + return false; +} + + +bool SoapySDRInputGui::handleMessage(const Message& message __attribute__((unused))) +{ + return false; +} + + diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputgui.h b/plugins/samplesource/soapysdrinput/soapysdrinputgui.h new file mode 100644 index 000000000..970b72d7a --- /dev/null +++ b/plugins/samplesource/soapysdrinput/soapysdrinputgui.h @@ -0,0 +1,70 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef PLUGINS_SAMPLESOURCE_SOAPYSDRINPUT_SOAPYSDRINPUTGUI_H_ +#define PLUGINS_SAMPLESOURCE_SOAPYSDRINPUT_SOAPYSDRINPUTGUI_H_ + +#include +#include + +#include "plugin/plugininstancegui.h" +#include "util/messagequeue.h" + +#include "soapysdrinput.h" + +class DeviceUISet; + +namespace Ui { + class SoapySDRInputGui; +} + +class SoapySDRInputGui : public QWidget, public PluginInstanceGUI { + Q_OBJECT + +public: + explicit SoapySDRInputGui(DeviceUISet *deviceUISet, QWidget* parent = 0); + virtual ~SoapySDRInputGui(); + virtual void destroy(); + + void setName(const QString& name); + QString getName() const; + + virtual void resetToDefaults(); + virtual qint64 getCenterFrequency() const; + virtual void setCenterFrequency(qint64 centerFrequency); + virtual QByteArray serialize() const; + virtual bool deserialize(const QByteArray& data); + virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } + virtual bool handleMessage(const Message& message); + +private: + Ui::SoapySDRInputGui* ui; + + DeviceUISet* m_deviceUISet; + bool m_forceSettings; + bool m_doApplySettings; + QTimer m_updateTimer; + QTimer m_statusTimer; + SoapySDRInput* m_sampleSource; + int m_sampleRate; + quint64 m_deviceCenterFrequency; //!< Center frequency in device + int m_lastEngineState; + MessageQueue m_inputMessageQueue; +}; + + + +#endif /* PLUGINS_SAMPLESOURCE_SOAPYSDRINPUT_SOAPYSDRINPUTGUI_H_ */ diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputplugin.cpp b/plugins/samplesource/soapysdrinput/soapysdrinputplugin.cpp new file mode 100644 index 000000000..690457e02 --- /dev/null +++ b/plugins/samplesource/soapysdrinput/soapysdrinputplugin.cpp @@ -0,0 +1,132 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include "plugin/pluginapi.h" +#include "util/simpleserializer.h" +#include "device/devicesourceapi.h" +#include "soapysdr/devicesoapysdrscan.h" + +#include "soapysdrinputplugin.h" + +#ifdef SERVER_MODE +#include "soapysdrinput.h" +#else +#include "soapysdrinputgui.h" +#endif + +const PluginDescriptor SoapySDRInputPlugin::m_pluginDescriptor = { + QString("SoapySDR Input"), + QString("4.3.0"), + QString("(c) Edouard Griffiths, F4EXB"), + QString("https://github.com/f4exb/sdrangel"), + true, + QString("https://github.com/f4exb/sdrangel") +}; + +const QString SoapySDRInputPlugin::m_hardwareID = "SoapySDR"; +const QString SoapySDRInputPlugin::m_deviceTypeID = SOAPYSDRINPUT_DEVICE_TYPE_ID; + +SoapySDRInputPlugin::SoapySDRInputPlugin(QObject* parent) : + QObject(parent) +{ +} + +const PluginDescriptor& SoapySDRInputPlugin::getPluginDescriptor() const +{ + return m_pluginDescriptor; +} + +void SoapySDRInputPlugin::initPlugin(PluginAPI* pluginAPI) +{ + pluginAPI->registerSampleSource(m_deviceTypeID, this); +} + +PluginInterface::SamplingDevices SoapySDRInputPlugin::enumSampleSources() +{ + SamplingDevices result; + DeviceSoapySDRScan scanner; + scanner.scan(); + const std::vector& devicesEnumeration = scanner.getDevicesEnumeration(); + qDebug("SoapySDRInputPlugin::enumSampleSources: found %lu devices", devicesEnumeration.size()); + std::vector::const_iterator it = devicesEnumeration.begin(); + + for (int idev = 0; it != devicesEnumeration.end(); ++it, idev++) + { + unsigned int nbRxChannels = it->m_nbRx; + + for (unsigned int ichan = 0; ichan < nbRxChannels; ichan++) + { + QString displayedName(QString("SoapySDR[%1:%2] %3").arg(idev).arg(ichan).arg(it->m_label)); + result.append(SamplingDevice(displayedName, + m_hardwareID, + m_deviceTypeID, + it->m_idValue, + idev, + PluginInterface::SamplingDevice::PhysicalDevice, + true, + nbRxChannels, + ichan)); + } + } + + return result; +} + +#ifdef SERVER_MODE +PluginInstanceGUI* SoapySDRInputPlugin::createSampleSourcePluginInstanceGUI( + const QString& sourceId __attribute__((unused)), + QWidget **widget __attribute__((unused)), + DeviceUISet *deviceUISet __attribute__((unused))) +{ + return 0; +} +#else +PluginInstanceGUI* SoapySDRInputPlugin::createSampleSourcePluginInstanceGUI( + const QString& sourceId, + QWidget **widget, + DeviceUISet *deviceUISet) +{ + if(sourceId == m_deviceTypeID) + { + SoapySDRInputGui* gui = new SoapySDRInputGui(deviceUISet); + *widget = gui; + return gui; + } + else + { + return 0; + } +} +#endif + +DeviceSampleSource *SoapySDRInputPlugin::createSampleSourcePluginInstanceInput(const QString& sourceId, DeviceSourceAPI *deviceAPI) +{ + if (sourceId == m_deviceTypeID) + { + SoapySDRInput *input = new SoapySDRInput(deviceAPI); + return input; + } + else + { + return 0; + } +} + + + + + diff --git a/plugins/samplesource/soapysdrinput/soapysdrinputplugin.h b/plugins/samplesource/soapysdrinput/soapysdrinputplugin.h new file mode 100644 index 000000000..c53acf12a --- /dev/null +++ b/plugins/samplesource/soapysdrinput/soapysdrinputplugin.h @@ -0,0 +1,56 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef PLUGINS_SAMPLESOURCE_SOAPYSDRINPUT_SOAPYSDRINPUTPLUGIN_H_ +#define PLUGINS_SAMPLESOURCE_SOAPYSDRINPUT_SOAPYSDRINPUTPLUGIN_H_ + +#include +#include "plugin/plugininterface.h" + +class PluginAPI; +class DeviceSourceAPI; +class DeviceUISet; + +#define SOAPYSDRINPUT_DEVICE_TYPE_ID "sdrangel.samplesource.soapysdrinput" + +class SoapySDRInputPlugin : public QObject, public PluginInterface { + Q_OBJECT + Q_INTERFACES(PluginInterface) + Q_PLUGIN_METADATA(IID SOAPYSDRINPUT_DEVICE_TYPE_ID) + +public: + explicit SoapySDRInputPlugin(QObject* parent = 0); + + const PluginDescriptor& getPluginDescriptor() const; + void initPlugin(PluginAPI* pluginAPI); + + virtual SamplingDevices enumSampleSources(); + virtual PluginInstanceGUI* createSampleSourcePluginInstanceGUI( + const QString& sourceId, + QWidget **widget, + DeviceUISet *deviceUISet); + virtual DeviceSampleSource* createSampleSourcePluginInstanceInput(const QString& sourceId, DeviceSourceAPI *deviceAPI); + + static const QString m_hardwareID; + static const QString m_deviceTypeID; + +private: + static const PluginDescriptor m_pluginDescriptor; +}; + + + +#endif /* PLUGINS_SAMPLESOURCE_SOAPYSDRINPUT_SOAPYSDRINPUTPLUGIN_H_ */