summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorChristian Daniel <cd@maintech.de>2013-03-22 15:54:17 +0100
committerChristian Daniel <cd@maintech.de>2013-03-22 15:54:17 +0100
commit46a84022aa5c2aa11051115bc6414249f48b90c6 (patch)
treebdb782d2799e3a0a4fb4c7e8baaccf300bf93beb /plugins
parentec109f5613251d65641bb2d91b2c8246cc4da09a (diff)
add GNURadio input plugin
Diffstat (limited to 'plugins')
-rw-r--r--plugins/samplesource/gnuradio/CMakeLists.txt53
-rw-r--r--plugins/samplesource/gnuradio/gnuradiogui.cpp266
-rw-r--r--plugins/samplesource/gnuradio/gnuradiogui.h81
-rw-r--r--plugins/samplesource/gnuradio/gnuradiogui.ui369
-rw-r--r--plugins/samplesource/gnuradio/gnuradioinput.cpp234
-rw-r--r--plugins/samplesource/gnuradio/gnuradioinput.h184
-rw-r--r--plugins/samplesource/gnuradio/gnuradioplugin.cpp52
-rw-r--r--plugins/samplesource/gnuradio/gnuradioplugin.h26
-rw-r--r--plugins/samplesource/gnuradio/gnuradiothread.cpp145
-rw-r--r--plugins/samplesource/gnuradio/gnuradiothread.h64
10 files changed, 1474 insertions, 0 deletions
diff --git a/plugins/samplesource/gnuradio/CMakeLists.txt b/plugins/samplesource/gnuradio/CMakeLists.txt
new file mode 100644
index 0000000..e1205b4
--- /dev/null
+++ b/plugins/samplesource/gnuradio/CMakeLists.txt
@@ -0,0 +1,53 @@
+project(gnuradio)
+
+set(gnuradio_SOURCES
+ gnuradiogui.cpp
+ gnuradioinput.cpp
+ gnuradioplugin.cpp
+ gnuradiothread.cpp
+)
+
+set(gnuradio_HEADERS
+ gnuradiogui.h
+ gnuradioinput.h
+ gnuradioplugin.h
+ gnuradiothread.h
+)
+
+set(gnuradio_FORMS
+ gnuradiogui.ui
+)
+
+include_directories(
+ .
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/include
+ ${CMAKE_SOURCE_DIR}/include-gpl
+ ${Boost_INCLUDE_DIRS}
+ ${GRUEL_INCLUDE_DIRS}
+ ${GNURADIO_CORE_INCLUDE_DIRS}
+ ${GNURADIO_OSMOSDR_INCLUDE_DIRS}
+)
+
+include(${QT_USE_FILE})
+add_definitions(${QT_DEFINITIONS})
+add_definitions(-DQT_PLUGIN)
+add_definitions(-DQT_SHARED)
+
+qt4_wrap_cpp(gnuradio_HEADERS_MOC ${gnuradio_HEADERS})
+qt4_wrap_ui(gnuradio_FORMS_HEADERS ${gnuradio_FORMS})
+
+add_library(inputgnuradio SHARED
+ ${gnuradio_SOURCES}
+ ${gnuradio_HEADERS_MOC}
+ ${gnuradio_FORMS_HEADERS}
+)
+
+target_link_libraries(inputgnuradio
+ ${QT_LIBRARIES}
+ ${LIBUSB_LIBRARIES}
+ ${Boost_LIBRARIES}
+ ${GRUEL_LIBRARIES}
+ ${GNURADIO_CORE_LIBRARIES}
+ ${GNURADIO_OSMOSDR_LIBRARIES}
+)
diff --git a/plugins/samplesource/gnuradio/gnuradiogui.cpp b/plugins/samplesource/gnuradio/gnuradiogui.cpp
new file mode 100644
index 0000000..919708d
--- /dev/null
+++ b/plugins/samplesource/gnuradio/gnuradiogui.cpp
@@ -0,0 +1,266 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
+// written by Christian Daniel //
+// Copyright (C) 2013 by Dimitri Stolnikov <horiz0n@gmx.net> //
+// //
+// 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 <http://www.gnu.org/licenses/>. //
+///////////////////////////////////////////////////////////////////////////////////
+
+#include "gnuradiogui.h"
+#include "ui_gnuradiogui.h"
+
+#include <osmosdr_device.h>
+#include <boost/foreach.hpp>
+#include <iostream>
+#include <plugin/pluginapi.h>
+
+GNURadioGui::GNURadioGui(PluginAPI* pluginAPI, QWidget* parent) :
+ PluginGUI(parent),
+ ui(new Ui::GNURadioGui),
+ m_pluginAPI(pluginAPI),
+ m_settings(),
+ m_sampleSource(NULL)
+{
+ ui->setupUi(this);
+ ui->centerFrequency->setValueRange(7, 20000U, 2200000U);
+ connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
+ displaySettings();
+
+ m_sampleSource = new GNURadioInput(m_pluginAPI->getMainWindowMessageQueue());
+ m_pluginAPI->setSampleSource(m_sampleSource);
+}
+
+GNURadioGui::~GNURadioGui()
+{
+ delete ui;
+}
+
+void GNURadioGui::destroy()
+{
+ delete this;
+}
+
+void GNURadioGui::resetToDefaults()
+{
+ m_generalSettings.resetToDefaults();
+ m_settings.resetToDefaults();
+ displaySettings();
+ sendSettings();
+}
+
+QByteArray GNURadioGui::serializeGeneral() const
+{
+ return m_generalSettings.serialize();
+}
+
+bool GNURadioGui::deserializeGeneral(const QByteArray&data)
+{
+ if(m_generalSettings.deserialize(data)) {
+ displaySettings();
+ sendSettings();
+ return true;
+ } else {
+ resetToDefaults();
+ return false;
+ }
+}
+
+quint64 GNURadioGui::getCenterFrequency() const
+{
+ return m_generalSettings.m_centerFrequency;
+}
+
+QByteArray GNURadioGui::serialize() const
+{
+ return m_settings.serialize();
+}
+
+bool GNURadioGui::deserialize(const QByteArray& data)
+{
+ if(m_settings.deserialize(data)) {
+ displaySettings();
+ sendSettings();
+ return true;
+ } else {
+ resetToDefaults();
+ return false;
+ }
+}
+
+bool GNURadioGui::handleMessage(Message* message)
+{
+ if(message->id() == GNURadioInput::MsgReportGNURadio::ID()) {
+ GNURadioInput::MsgReportGNURadio* rep = (GNURadioInput::MsgReportGNURadio*)message;
+ m_rfGains = rep->getRfGains();
+ m_ifGains = rep->getIfGains();
+ m_sampRates = rep->getSampRates();
+ m_antennas = rep->getAntennas();
+ displaySettings();
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void GNURadioGui::displaySettings()
+{
+ int oldIndex = 0;
+
+ oldIndex = ui->gnuradioDevices->currentIndex();
+ ui->gnuradioDevices->clear();
+
+ BOOST_FOREACH(osmosdr::device_t dev, osmosdr::device::find())
+ {
+ QString label;
+
+ if ( dev.count( "label" ) ) {
+ label = QString(dev[ "label" ].c_str());
+ dev.erase("label");
+ }
+
+ QPair< QString, QString > pair(label, dev.to_string().c_str());
+ m_devs.append(pair);
+
+ ui->gnuradioDevices->addItem(label);
+ }
+
+ if ( ui->gnuradioDevices->count() && oldIndex >= 0 )
+ {
+ ui->gnuradioDevices->setCurrentIndex(oldIndex);
+ ui->deviceArguments->setText(m_devs[oldIndex].second);
+ }
+
+ ui->centerFrequency->setValue(m_generalSettings.m_centerFrequency / 1000);
+
+ if ( m_rfGains.size() ) {
+ oldIndex = ui->sldRfGain->value();
+ ui->sldRfGain->setMinimum(0);
+ ui->sldRfGain->setMaximum(m_rfGains.size() - 1);
+ ui->sldRfGain->setValue(oldIndex == 0 ? m_rfGains.size() / 2 : oldIndex);
+ ui->sldRfGain->setEnabled(true);
+ } else {
+ ui->sldRfGain->setEnabled(false);
+ }
+
+ if ( m_ifGains.size() ) {
+ oldIndex = ui->sldIfGain->value();
+ ui->sldIfGain->setMinimum(0);
+ ui->sldIfGain->setMaximum(m_ifGains.size() - 1);
+ ui->sldIfGain->setValue(oldIndex == 0 ? m_ifGains.size() / 2 : oldIndex);
+ ui->sldIfGain->setEnabled(true);
+ } else {
+ ui->sldIfGain->setEnabled(false);
+ }
+
+ oldIndex = ui->cboSampleRate->currentIndex();
+ ui->cboSampleRate->clear();
+
+ for ( int i = 0; i < m_sampRates.size(); i++ )
+ ui->cboSampleRate->addItem(QString("%1").arg( m_sampRates[i] ));
+
+ if ( ui->cboSampleRate->count() && oldIndex >= 0 )
+ ui->cboSampleRate->setCurrentIndex(oldIndex);
+
+ oldIndex = ui->cboAntennas->currentIndex();
+ ui->cboAntennas->clear();
+
+ if ( m_antennas.size() ) {
+ for ( int i = 0; i < m_antennas.size(); i++ )
+ ui->cboAntennas->addItem(QString("%1").arg( m_antennas[i] ));
+
+ if ( ui->cboAntennas->count() && oldIndex >= 0 )
+ ui->cboAntennas->setCurrentIndex(oldIndex);
+
+ ui->cboAntennas->setEnabled(true);
+ } else {
+ ui->cboAntennas->setEnabled(false);
+ }
+}
+
+void GNURadioGui::sendSettings()
+{
+ if(!m_updateTimer.isActive())
+ m_updateTimer.start(100);
+}
+
+void GNURadioGui::updateHardware()
+{
+ m_updateTimer.stop();
+ GNURadioInput::MsgConfigureGNURadio* msg = GNURadioInput::MsgConfigureGNURadio::create(m_generalSettings, m_settings);
+ msg->submit(m_pluginAPI->getDSPEngineMessageQueue());
+}
+
+void GNURadioGui::on_gnuradioDevices_currentIndexChanged(int index)
+{
+ if ( index < 0 || index >= m_devs.count() )
+ return;
+
+ ui->deviceArguments->setText(m_devs[index].second);
+}
+
+void GNURadioGui::on_centerFrequency_changed(quint64 value)
+{
+ m_generalSettings.m_centerFrequency = value * 1000;
+ sendSettings();
+}
+
+void GNURadioGui::on_sldFreqCorr_valueChanged(int value)
+{
+ ui->lblFreqCorrValue->setText(tr("%1").arg(value));
+ m_settings.m_freqCorr = value;
+ sendSettings();
+}
+
+void GNURadioGui::on_sldRfGain_valueChanged(int value)
+{
+ if ( value >= m_rfGains.size() )
+ return;
+
+ double gain = m_rfGains[value];
+ ui->lblRfGainValue->setText(tr("%1").arg(gain));
+ m_settings.m_rfGain = gain;
+ sendSettings();
+}
+
+void GNURadioGui::on_sldIfGain_valueChanged(int value)
+{
+ if ( value >= m_ifGains.size() )
+ return;
+
+ double gain = m_ifGains[value];
+ ui->lblIfGainValue->setText(tr("%1").arg(gain));
+ m_settings.m_ifGain = gain;
+ sendSettings();
+}
+
+void GNURadioGui::on_cboSampleRate_currentIndexChanged(int index)
+{
+ if ( index < 0 || index >= m_sampRates.size() )
+ return;
+
+ m_settings.m_sampleRate = m_sampRates[index];
+ sendSettings();
+}
+
+void GNURadioGui::on_deviceArguments_textChanged(const QString &arg1)
+{
+ m_settings.m_args = arg1;
+ sendSettings();
+}
+
+void GNURadioGui::on_cboAntennas_currentIndexChanged(const QString &arg1)
+{
+ m_settings.m_antenna = arg1;
+ std::cout << arg1.toStdString() << std::endl;
+ sendSettings();
+}
diff --git a/plugins/samplesource/gnuradio/gnuradiogui.h b/plugins/samplesource/gnuradio/gnuradiogui.h
new file mode 100644
index 0000000..e23d291
--- /dev/null
+++ b/plugins/samplesource/gnuradio/gnuradiogui.h
@@ -0,0 +1,81 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
+// written by Christian Daniel //
+// Copyright (C) 2013 by Dimitri Stolnikov <horiz0n@gmx.net> //
+// //
+// 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 <http://www.gnu.org/licenses/>. //
+///////////////////////////////////////////////////////////////////////////////////
+
+#ifndef INCLUDE_GNURADIOGUI_H
+#define INCLUDE_GNURADIOGUI_H
+
+#include <QTimer>
+#include <QPair>
+#include <QList>
+#include <QString>
+#include "plugin/plugingui.h"
+#include "gnuradioinput.h"
+
+namespace Ui {
+ class GNURadioGui;
+}
+
+class PluginAPI;
+
+class GNURadioGui : public PluginGUI {
+ Q_OBJECT
+
+public:
+ explicit GNURadioGui(PluginAPI* pluginAPI, QWidget* parent = NULL);
+ ~GNURadioGui();
+ void destroy();
+
+ void resetToDefaults();
+ QByteArray serializeGeneral() const;
+ bool deserializeGeneral(const QByteArray&data);
+ quint64 getCenterFrequency() const;
+ QByteArray serialize() const;
+ bool deserialize(const QByteArray& data);
+ bool handleMessage(Message* message);
+
+private:
+ Ui::GNURadioGui* ui;
+ PluginAPI* m_pluginAPI;
+ SampleSource* m_sampleSource;
+ QList< QPair<QString, QString> > m_devs;
+ std::vector<double> m_rfGains;
+ std::vector<double> m_ifGains;
+ std::vector<double> m_sampRates;
+ std::vector<QString> m_antennas;
+
+ SampleSource::GeneralSettings m_generalSettings;
+ GNURadioInput::Settings m_settings;
+ QTimer m_updateTimer;
+
+ void displaySettings();
+ void sendSettings();
+
+private slots:
+ void updateHardware();
+
+ void on_gnuradioDevices_currentIndexChanged(int index);
+ void on_centerFrequency_changed(quint64 value);
+ void on_sldFreqCorr_valueChanged(int value);
+ void on_sldRfGain_valueChanged(int value);
+ void on_sldIfGain_valueChanged(int value);
+ void on_cboSampleRate_currentIndexChanged(int index);
+ void on_deviceArguments_textChanged(const QString &arg1);
+ void on_cboAntennas_currentIndexChanged(const QString &arg1);
+};
+
+#endif // INCLUDE_GNURADIOGUI_H
diff --git a/plugins/samplesource/gnuradio/gnuradiogui.ui b/plugins/samplesource/gnuradio/gnuradiogui.ui
new file mode 100644
index 0000000..69ecdb7
--- /dev/null
+++ b/plugins/samplesource/gnuradio/gnuradiogui.ui
@@ -0,0 +1,369 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>GNURadioGui</class>
+ <widget class="QWidget" name="GNURadioGui">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>254</width>
+ <height>239</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>Gnuradio Source</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <property name="margin">
+ <number>2</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_5">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <property name="spacing">
+ <number>2</number>
+ </property>
+ <item>
+ <widget class="QComboBox" name="gnuradioDevices">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="editable">
+ <bool>false</bool>
+ </property>
+ <property name="sizeAdjustPolicy">
+ <enum>QComboBox::AdjustToMinimumContentsLength</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="deviceArguments">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Line" name="line_5">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="ValueDial" name="centerFrequency" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>32</width>
+ <height>16</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <family>Monospace</family>
+ <pointsize>20</pointsize>
+ </font>
+ </property>
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ <property name="toolTip">
+ <string>Tuner center frequency in kHz</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Freq. Corr.</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSlider" name="sldFreqCorr">
+ <property name="minimum">
+ <number>-100</number>
+ </property>
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ <property name="tracking">
+ <bool>true</bool>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="lblFreqCorrValue">
+ <property name="minimumSize">
+ <size>
+ <width>40</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Line" name="line_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="lblRfGainText">
+ <property name="text">
+ <string>RF Gain </string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSlider" name="sldRfGain">
+ <property name="toolTip">
+ <string/>
+ </property>
+ <property name="maximum">
+ <number>9</number>
+ </property>
+ <property name="pageStep">
+ <number>1</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="tickPosition">
+ <enum>QSlider::NoTicks</enum>
+ </property>
+ <property name="tickInterval">
+ <number>0</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="lblRfGainValue">
+ <property name="minimumSize">
+ <size>
+ <width>40</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Line" name="line_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="lblIfGain">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>IF Gain </string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSlider" name="sldIfGain">
+ <property name="toolTip">
+ <string/>
+ </property>
+ <property name="maximum">
+ <number>9</number>
+ </property>
+ <property name="pageStep">
+ <number>1</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="lblIfGainValue">
+ <property name="minimumSize">
+ <size>
+ <width>40</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Line" name="line_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_6">
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Sample Rate</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="cboSampleRate">
+ <property name="sizeAdjustPolicy">
+ <enum>QComboBox::AdjustToMinimumContentsLength</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Line" name="line_6">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_7">
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Antenna</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="cboAntennas"/>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>ValueDial</class>
+ <extends>QWidget</extends>
+ <header>gui/valuedial.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/plugins/samplesource/gnuradio/gnuradioinput.cpp b/plugins/samplesource/gnuradio/gnuradioinput.cpp
new file mode 100644
index 0000000..c9d8ec3
--- /dev/null
+++ b/plugins/samplesource/gnuradio/gnuradioinput.cpp
@@ -0,0 +1,234 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
+// written by Christian Daniel //
+// Copyright (C) 2013 by Dimitri Stolnikov <horiz0n@gmx.net> //
+// //
+// 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 <http://www.gnu.org/licenses/>. //
+///////////////////////////////////////////////////////////////////////////////////
+
+#include <string.h>
+#include <errno.h>
+#include <boost/foreach.hpp>
+#include "util/simpleserializer.h"
+#include "gnuradioinput.h"
+#include "gnuradiothread.h"
+#include "gnuradiogui.h"
+
+MessageRegistrator GNURadioInput::MsgConfigureGNURadio::ID("MsgConfigureGNURadio");
+MessageRegistrator GNURadioInput::MsgReportGNURadio::ID("MsgReportGNURadio");
+
+GNURadioInput::Settings::Settings() :
+ m_args(""),
+ m_sampleRate(2e6),
+ m_freqCorr(0),
+ m_rfGain(10),
+ m_ifGain(15),
+ m_antenna("")
+{
+}
+
+void GNURadioInput::Settings::resetToDefaults()
+{
+ m_args = "";
+ m_sampleRate = 2e6;
+ m_freqCorr = 0;
+ m_rfGain = 10;
+ m_ifGain = 15;
+ m_antenna = "";
+}
+
+QByteArray GNURadioInput::Settings::serialize() const
+{
+ SimpleSerializer s(1);
+ s.writeString(1, m_args);
+ s.writeDouble(2, m_sampleRate);
+ s.writeDouble(3, m_freqCorr);
+ s.writeDouble(4, m_rfGain);
+ s.writeDouble(5, m_ifGain);
+ s.writeString(6, m_antenna);
+ return s.final();
+}
+
+bool GNURadioInput::Settings::deserialize(const QByteArray& data)
+{
+ SimpleDeserializer d(data);
+
+ if(!d.isValid()) {
+ resetToDefaults();
+ return false;
+ }
+
+ if(d.getVersion() == 1) {
+ d.readString(1, &m_args, "");
+ d.readDouble(2, &m_sampleRate, 2e6);
+ d.readDouble(3, &m_freqCorr, 0);
+ d.readDouble(4, &m_rfGain, 10);
+ d.readDouble(5, &m_ifGain, 15);
+ d.readString(6, &m_antenna, "");
+ return true;
+ } else {
+ resetToDefaults();
+ return false;
+ }
+}
+
+GNURadioInput::GNURadioInput(MessageQueue* msgQueueToGUI) :
+ SampleSource(msgQueueToGUI),
+ m_settings(),
+ m_GnuradioThread(NULL),
+ m_deviceDescription()
+{
+}
+
+GNURadioInput::~GNURadioInput()
+{
+ stopInput();
+}
+
+bool GNURadioInput::startInput(int device)
+{
+ QMutexLocker mutexLocker(&m_mutex);
+
+ if(m_GnuradioThread != NULL)
+ stopInput();
+
+ if(!m_sampleFifo.setSize(524288)) {
+ qCritical("Could not allocate SampleFifo");
+ return false;
+ }
+
+ m_deviceDescription = m_settings.m_args;
+
+ // pass device arguments from the gui
+ m_GnuradioThread = new GnuradioThread(m_settings.m_args, &m_sampleFifo);
+ if(m_GnuradioThread == NULL) {
+ qFatal("out of memory");
+ goto failed;
+ }
+ m_GnuradioThread->startWork();
+
+ mutexLocker.unlock();
+ applySettings(m_generalSettings, m_settings, true);
+
+ if(m_GnuradioThread != NULL) {
+ osmosdr_source_c_sptr radio = m_GnuradioThread->radio();
+
+ m_sampRates = radio->get_sample_rates().values();
+ m_rfGains = radio->get_gain_range().values();
+ m_ifGains = radio->get_gain_range("IF").values();
+
+ m_antennas.clear();
+ BOOST_FOREACH( std::string antenna, radio->get_antennas() )
+ m_antennas.push_back( QString( antenna.c_str() ) );
+ }
+
+ qDebug("GnuradioInput: start");
+ MsgReportGNURadio::create(m_rfGains, m_ifGains, m_sampRates, m_antennas)->submit(m_guiMessageQueue);
+
+ return true;
+
+failed:
+ stopInput();
+ return false;
+}
+
+void GNURadioInput::stopInput()
+{
+ QMutexLocker mutexLocker(&m_mutex);
+
+ if(m_GnuradioThread != NULL) {
+ m_GnuradioThread->stopWork();
+ delete m_GnuradioThread;
+ m_GnuradioThread = NULL;
+ }
+
+ m_deviceDescription.clear();
+}
+
+const QString& GNURadioInput::getDeviceDescription() const
+{
+ return m_deviceDescription;
+}
+
+int GNURadioInput::getSampleRate() const
+{
+ return m_settings.m_sampleRate;
+}
+
+quint64 GNURadioInput::getCenterFrequency() const
+{
+ return m_generalSettings.m_centerFrequency;
+}
+
+bool GNURadioInput::handleMessage(Message* message)
+{
+ if(message->id() == MsgConfigureGNURadio::ID()) {
+ MsgConfigureGNURadio* conf = (MsgConfigureGNURadio*)message;
+ if(!applySettings(conf->getGeneralSettings(), conf->getSettings(), false))
+ qDebug("Gnuradio config error");
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool GNURadioInput::applySettings(const GeneralSettings& generalSettings, const Settings& settings, bool force)
+{
+ QMutexLocker mutexLocker(&m_mutex);
+
+ m_settings.m_args = settings.m_args;
+
+ if((m_settings.m_freqCorr != settings.m_freqCorr) || force) {
+ m_settings.m_freqCorr = settings.m_freqCorr;
+ if(m_GnuradioThread != NULL) {
+ m_GnuradioThread->radio()->set_freq_corr( m_settings.m_freqCorr );
+ }
+ }
+
+ if((m_generalSettings.m_centerFrequency != generalSettings.m_centerFrequency) || force) {
+ m_generalSettings.m_centerFrequency = generalSettings.m_centerFrequency;
+ if(m_GnuradioThread != NULL) {
+ m_GnuradioThread->radio()->set_center_freq( m_generalSettings.m_centerFrequency );
+ }
+ }
+
+ if((m_settings.m_rfGain != settings.m_rfGain) || force) {
+ m_settings.m_rfGain = settings.m_rfGain;
+ if(m_GnuradioThread != NULL) {
+ m_GnuradioThread->radio()->set_gain( m_settings.m_rfGain );
+ }
+ }
+
+ if((m_settings.m_ifGain != settings.m_ifGain) || force) {
+ m_settings.m_ifGain = settings.m_ifGain;
+ if(m_GnuradioThread != NULL) {
+ m_GnuradioThread->radio()->set_gain( m_settings.m_ifGain, "IF" );
+ }
+ }
+
+ if((m_settings.m_sampleRate != settings.m_sampleRate) || force) {
+ m_settings.m_sampleRate = settings.m_sampleRate;
+ if(m_GnuradioThread != NULL) {
+ m_GnuradioThread->radio()->set_sample_rate( m_settings.m_sampleRate );
+ }
+ }
+
+ if((m_settings.m_antenna != settings.m_antenna) || force) {
+ m_settings.m_antenna = settings.m_antenna;
+ if(m_GnuradioThread != NULL) {
+ m_GnuradioThread->radio()->set_antenna( m_settings.m_antenna.toStdString() );
+ }
+ }
+
+ return true;
+}
diff --git a/plugins/samplesource/gnuradio/gnuradioinput.h b/plugins/samplesource/gnuradio/gnuradioinput.h
new file mode 100644
index 0000000..6ff6513
--- /dev/null
+++ b/plugins/samplesource/gnuradio/gnuradioinput.h
@@ -0,0 +1,184 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
+// written by Christian Daniel //
+// Copyright (C) 2013 by Dimitri Stolnikov <horiz0n@gmx.net> //
+// //
+// 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 <http://www.gnu.org/licenses/>. //
+///////////////////////////////////////////////////////////////////////////////////
+
+#ifndef INCLUDE_GNURADIOINPUT_H
+#define INCLUDE_GNURADIOINPUT_H
+
+#include "dsp/samplesource/samplesource.h"
+#include <QString>
+
+class GnuradioThread;
+
+class GNURadioInput : public SampleSource {
+public:
+ struct Settings {
+ QString m_args;
+ double m_sampleRate;
+ double m_freqCorr;
+ double m_rfGain;
+ double m_ifGain;
+ QString m_antenna;
+
+ Settings();
+ void resetToDefaults();
+ QByteArray serialize() const;
+ bool deserialize(const QByteArray& data);
+ };
+
+ class MsgConfigureGNURadio : public Message {
+ public:
+ static MessageRegistrator ID;
+
+ const GeneralSettings& getGeneralSettings() const { return m_generalSettings; }
+ const Settings& getSettings() const { return m_settings; }
+
+ static MsgConfigureGNURadio* create(const GeneralSettings& generalSettings, const Settings& settings)
+ {
+ return new MsgConfigureGNURadio(generalSettings, settings);
+ }
+
+ protected:
+ GeneralSettings m_generalSettings;
+ Settings m_settings;
+
+ MsgConfigureGNURadio(const GeneralSettings& generalSettings, const Settings& settings) :
+ Message(ID()),
+ m_generalSettings(generalSettings),
+ m_settings(settings)
+ { }
+ };
+
+ class MsgReportGNURadio : public Message {
+ public:
+ static MessageRegistrator ID;
+
+ const std::vector<double>& getRfGains() const { return m_rfGains; }
+ const std::vector<double>& getIfGains() const { return m_ifGains; }
+ const std::vector<double>& getSampRates() const { return m_sampRates; }
+ const std::vector<QString>& getAntennas() const { return m_antennas; }
+
+ static MsgReportGNURadio* create(const std::vector<double>& rfGains,
+ const std::vector<double>& ifGains,
+ const std::vector<double>& sampRates,
+ const std::vector<QString>& antennas)
+ {
+ return new MsgReportGNURadio(rfGains, ifGains, sampRates, antennas);
+ }
+
+ protected:
+ std::vector<double> m_rfGains;
+ std::vector<double> m_ifGains;
+ std::vector<double> m_sampRates;
+ std::vector<QString> m_antennas;
+
+ MsgReportGNURadio(const std::vector<double>& rfGains,
+ const std::vector<double>& ifGains,
+ const std::vector<double>& sampRates,
+ const std::vector<QString>& antennas) :
+ Message(ID()),
+ m_rfGains(rfGains),
+ m_ifGains(ifGains),
+ m_sampRates(sampRates),
+ m_antennas(antennas)
+ { }
+ };
+
+ GNURadioInput(MessageQueue* msgQueueToGUI);
+ ~GNURadioInput();
+
+ bool startInput(int device);
+ void stopInput();
+
+ const QString& getDeviceDescription() const;
+ int getSampleRate() const;
+ quint64 getCenterFrequency() const;
+
+ bool handleMessage(Message* message);
+
+private:
+ QMutex m_mutex;
+ Settings m_settings;
+ GnuradioThread* m_GnuradioThread;
+ QString m_deviceDescription;
+ std::vector<double> m_rfGains;
+ std::vector<double> m_ifGains;
+ std::vector<double> m_sampRates;
+ std::vector<QString> m_antennas;
+
+ bool applySettings(const GeneralSettings& generalSettings, const Settings& settings, bool force);
+};
+#if 0
+class DSPCmdConfigureSourceGnuradio : public DSPCmdGUIToSource {
+public:
+ enum {
+ SourceType = 3
+ };
+
+ int sourceType() const;
+ const GnuradioInput::Settings& getSettings() const { return m_settings; }
+
+ static DSPCmdConfigureSourceGnuradio* create(const GnuradioInput::Settings& settings)
+ {
+ return new DSPCmdConfigureSourceGnuradio(settings);
+ }
+
+protected:
+ GnuradioInput::Settings m_settings;
+
+ DSPCmdConfigureSourceGnuradio(const GnuradioInput::Settings& settings) : m_settings(settings) { }
+};
+#endif
+#if 0
+class DSPCmdGUIInfoGnuradio : public DSPCmdSourceToGUI {
+public:
+ enum {
+ SourceType = 3
+ };
+
+ int sourceType() const;
+ const std::vector<double>& getRfGains() const { return m_rfGains; }
+ const std::vector<double>& getIfGains() const { return m_ifGains; }
+ const std::vector<double>& getSampRates() const { return m_sampRates; }
+ const std::vector<QString>& getAntennas() const { return m_antennas; }
+
+ static DSPCmdGUIInfoGnuradio* create(const std::vector<double>& rfGains,
+ const std::vector<double>& ifGains,
+ const std::vector<double>& sampRates,
+ const std::vector<QString>& antennas)
+ {
+ return new DSPCmdGUIInfoGnuradio(rfGains, ifGains, sampRates, antennas);
+ }
+
+protected:
+ std::vector<double> m_rfGains;
+ std::vector<double> m_ifGains;
+ std::vector<double> m_sampRates;
+ std::vector<QString> m_antennas;
+
+ DSPCmdGUIInfoGnuradio(const std::vector<double>& rfGains,
+ const std::vector<double>& ifGains,
+ const std::vector<double>& sampRates,
+ const std::vector<QString>& antennas) :
+ m_rfGains(rfGains),
+ m_ifGains(ifGains),
+ m_sampRates(sampRates),
+ m_antennas(antennas)
+ { }
+};
+#endif
+#endif // INCLUDE_GNURADIOINPUT_H
diff --git a/plugins/samplesource/gnuradio/gnuradioplugin.cpp b/plugins/samplesource/gnuradio/gnuradioplugin.cpp
new file mode 100644
index 0000000..bebbba8
--- /dev/null
+++ b/plugins/samplesource/gnuradio/gnuradioplugin.cpp
@@ -0,0 +1,52 @@
+#include <QtPlugin>
+#include <QAction>
+#include "plugin/pluginapi.h"
+#include "util/simpleserializer.h"
+#include "gnuradioplugin.h"
+#include "gnuradiogui.h"
+
+const PluginDescriptor GNURadioPlugin::m_pluginDescriptor = {
+ displayedName: QString("GR-OsmoSDR Input"),
+ version: QString("---"),
+ copyright: QString("(c) Dimitri Stolnikov <horiz0n@gmx.net>"),
+ website: QString("http://sdr.osmocom.org/trac/wiki/gr-osmosdr"),
+ licenseIsGPL: true,
+ sourceCodeURL: QString("http://cgit.osmocom.org/cgit/gr-osmosdr")
+};
+
+GNURadioPlugin::GNURadioPlugin(QObject* parent) :
+ QObject(parent)
+{
+}
+
+const PluginDescriptor& GNURadioPlugin::getPluginDescriptor() const
+{
+ return m_pluginDescriptor;
+}
+
+void GNURadioPlugin::initPlugin(PluginAPI* pluginAPI)
+{
+ m_pluginAPI = pluginAPI;
+
+ m_pluginAPI->registerSampleSource("org.osmocom.sdr.samplesource.gr-osmosdr", this);
+}
+
+PluginInterface::SampleSourceDevices GNURadioPlugin::enumSampleSources()
+{
+ SampleSourceDevices result;
+
+ result.append(SampleSourceDevice("GNURadio OsmoSDR Driver", "org.osmocom.sdr.samplesource.gr-osmosdr", QByteArray()));
+
+ return result;
+}
+
+PluginGUI* GNURadioPlugin::createSampleSource(const QString& sourceName, const QByteArray& address)
+{
+ if(sourceName == "org.osmocom.sdr.samplesource.gr-osmosdr") {
+ return new GNURadioGui(m_pluginAPI);
+ } else {
+ return NULL;
+ }
+}
+
+Q_EXPORT_PLUGIN2(gnuRadioPlugin, GNURadioPlugin);
diff --git a/plugins/samplesource/gnuradio/gnuradioplugin.h b/plugins/samplesource/gnuradio/gnuradioplugin.h
new file mode 100644
index 0000000..092469f
--- /dev/null
+++ b/plugins/samplesource/gnuradio/gnuradioplugin.h
@@ -0,0 +1,26 @@
+#ifndef INCLUDE_GNURADIOPLUGIN_H
+#define INCLUDE_GNURADIOPLUGIN_H
+
+#include <QObject>
+#include "plugin/plugininterface.h"
+
+class GNURadioPlugin : public QObject, PluginInterface {
+ Q_OBJECT
+ Q_INTERFACES(PluginInterface)
+
+public:
+ explicit GNURadioPlugin(QObject* parent = NULL);
+
+ const PluginDescriptor& getPluginDescriptor() const;
+ void initPlugin(PluginAPI* pluginAPI);
+
+ SampleSourceDevices enumSampleSources();
+ PluginGUI* createSampleSource(const QString& sourceName, const QByteArray& address);
+
+private:
+ static const PluginDescriptor m_pluginDescriptor;
+
+ PluginAPI* m_pluginAPI;
+};
+
+#endif // INCLUDE_GNURADIOPLUGIN_H
diff --git a/plugins/samplesource/gnuradio/gnuradiothread.cpp b/plugins/samplesource/gnuradio/gnuradiothread.cpp
new file mode 100644
index 0000000..c67de8c
--- /dev/null
+++ b/plugins/samplesource/gnuradio/gnuradiothread.cpp
@@ -0,0 +1,145 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
+// written by Christian Daniel //
+// Copyright (C) 2013 by Dimitri Stolnikov <horiz0n@gmx.net> //
+// //
+// 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 <http://www.gnu.org/licenses/>. //
+///////////////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <errno.h>
+#include "gnuradiothread.h"
+#include "dsp/samplefifo.h"
+
+#include <gr_sync_block.h>
+#include <gr_io_signature.h>
+
+////////////////////////////////////////////////////////////////////////////////
+class gr_adaptor;
+
+typedef boost::shared_ptr<gr_adaptor> gr_adaptor_sptr;
+
+gr_adaptor_sptr make_gr_adaptor (SampleFifo* sampleFifo);
+
+class gr_adaptor : public gr_sync_block
+{
+public:
+ gr_adaptor (SampleFifo* sampleFifo);
+ ~gr_adaptor ();
+
+ int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+private:
+ SampleFifo *m_sampleFifo;
+};
+
+gr_adaptor_sptr
+make_gr_adaptor (SampleFifo *sampleFifo)
+{
+ return gr_adaptor_sptr (new gr_adaptor (sampleFifo));
+}
+
+gr_adaptor::gr_adaptor (SampleFifo *sampleFifo)
+ : gr_sync_block ("gr_adaptor",
+ gr_make_io_signature (1, 1, sizeof (gr_complex)),
+ gr_make_io_signature (0, 0, 0)),
+ m_sampleFifo(sampleFifo)
+{
+}
+
+gr_adaptor::~gr_adaptor ()
+{
+}
+
+int
+gr_adaptor::work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const gr_complex *in = (const gr_complex *) input_items[0];
+ unsigned char *out = (unsigned char *) output_items[0];
+
+ std::vector<qint16> buffer(noutput_items * 2, 0);
+ std::vector<qint16>::iterator it = buffer.begin();
+
+ for (int i = 0; i < noutput_items; i++)
+ {
+ *it++ = in[i].real() * 32000;
+ *it++ = in[i].imag() * 32000;
+ }
+
+ // we must push at least 4 bytes into the fifo
+ m_sampleFifo->write((const quint8*)buffer.data(),
+ (it - buffer.begin()) * sizeof(qint16));
+
+ // Tell runtime system how many input items we consumed on
+ // each input stream.
+ consume_each(noutput_items);
+
+ // Tell runtime system how many output items we produced.
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+GnuradioThread::GnuradioThread(QString args, SampleFifo* sampleFifo, QObject* parent) :
+ QThread(parent),
+ m_running(false),
+ m_args(args),
+ m_sampleFifo(sampleFifo)
+{
+}
+
+GnuradioThread::~GnuradioThread()
+{
+ stopWork();
+}
+
+void GnuradioThread::startWork()
+{
+ m_startWaitMutex.lock();
+
+ start();
+ while(!m_running)
+ m_startWaiter.wait(&m_startWaitMutex, 100);
+
+ m_startWaitMutex.unlock();
+}
+
+void GnuradioThread::stopWork()
+{
+ m_running = false;
+
+ m_top->stop();
+
+ wait();
+}
+
+void GnuradioThread::run()
+{
+ m_top = gr_make_top_block( "flowgraph" );
+ m_src = osmosdr_make_source_c( m_args.toStdString() );
+
+ /* now since we've constructed our shared objects, we allow the calling
+ * thread to continue it's work and send some radio settings to us. */
+ m_running = true;
+ m_startWaiter.wakeAll();
+
+ gr_adaptor_sptr adaptor = make_gr_adaptor(m_sampleFifo);
+ m_top->connect(m_src, 0, adaptor, 0);
+
+ m_top->run();
+
+ m_running = false;
+}
diff --git a/plugins/samplesource/gnuradio/gnuradiothread.h b/plugins/samplesource/gnuradio/gnuradiothread.h
new file mode 100644
index 0000000..c098a47
--- /dev/null
+++ b/plugins/samplesource/gnuradio/gnuradiothread.h
@@ -0,0 +1,64 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
+// written by Christian Daniel //
+// Copyright (C) 2013 by Dimitri Stolnikov <horiz0n@gmx.net> //
+// //
+// 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 <http://www.gnu.org/licenses/>. //
+///////////////////////////////////////////////////////////////////////////////////
+
+#ifndef INCLUDE_GNURADIOTHREAD_H
+#define INCLUDE_GNURADIOTHREAD_H
+
+#include <QThread>
+#include <QMutex>
+#include <QWaitCondition>
+
+#include <gr_top_block.h>
+#include <osmosdr_source_c.h>
+
+class SampleFifo;
+
+class GnuradioThread : public QThread {
+ Q_OBJECT
+
+public:
+ GnuradioThread(QString args, SampleFifo* sampleFifo, QObject* parent = NULL);
+ ~GnuradioThread();
+
+ void startWork();
+ void stopWork();
+
+ osmosdr_source_c_sptr radio() { return m_src; }
+
+private:
+#pragma pack(push, 1)
+ struct Sample {
+ qint16 i;
+ qint16 q;
+ };
+#pragma pack(pop)
+
+ QMutex m_startWaitMutex;
+ QWaitCondition m_startWaiter;
+ bool m_running;
+
+ QString m_args;
+ SampleFifo* m_sampleFifo;
+
+ gr_top_block_sptr m_top;
+ osmosdr_source_c_sptr m_src;
+
+ void run();
+};
+
+#endif // INCLUDE_GNURADIOTHREAD_H