mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-29 20:10:22 -04:00 
			
		
		
		
	Copied filesource plugin folder to new sdrdaemon
This commit is contained in:
		
							parent
							
								
									24607ee6f1
								
							
						
					
					
						commit
						e4f97e1a1b
					
				| @ -43,3 +43,4 @@ if(LIBUSB_FOUND AND LIBHACKRF_FOUND) | ||||
| endif(LIBUSB_FOUND AND LIBHACKRF_FOUND) | ||||
| 
 | ||||
| add_subdirectory(filesource) | ||||
| add_subdirectory(sdrdaemon) | ||||
|  | ||||
							
								
								
									
										49
									
								
								plugins/samplesource/sdrdaemon/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								plugins/samplesource/sdrdaemon/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | ||||
| project(sdrdaemon) | ||||
| 
 | ||||
| set(sdrdaemon_SOURCES | ||||
| 	sdrdaemongui.cpp | ||||
| 	sdrdaemoninput.cpp | ||||
| 	sdrdaemonplugin.cpp | ||||
| 	sdrdaemonthread.cpp | ||||
| ) | ||||
| 
 | ||||
| set(sdrdaemon_HEADERS | ||||
| 	sdrdaemongui.h | ||||
| 	sdrdaemoninput.h | ||||
| 	sdrdaemonplugin.h | ||||
| 	sdrdaemonthread.h | ||||
| ) | ||||
| 
 | ||||
| set(sdrdaemon_FORMS | ||||
| 	sdrdaemongui.ui | ||||
| ) | ||||
| 
 | ||||
| include_directories( | ||||
| 	. | ||||
| 	${CMAKE_CURRENT_BINARY_DIR} | ||||
| 	${CMAKE_SOURCE_DIR}/include | ||||
| 	${CMAKE_SOURCE_DIR}/include-gpl | ||||
| 	${LIBRTLSDR_INCLUDE_DIR} | ||||
| ) | ||||
| 
 | ||||
| #include(${QT_USE_FILE}) | ||||
| add_definitions(${QT_DEFINITIONS}) | ||||
| add_definitions(-DQT_PLUGIN) | ||||
| add_definitions(-DQT_SHARED) | ||||
| 
 | ||||
| #qt4_wrap_cpp(sdrdaemon_HEADERS_MOC ${sdrdaemon_HEADERS}) | ||||
| qt5_wrap_ui(sdrdaemon_FORMS_HEADERS ${sdrdaemon_FORMS}) | ||||
| 
 | ||||
| add_library(inputsdrdaemon SHARED | ||||
| 	${sdrdaemon_SOURCES} | ||||
| 	${sdrdaemon_HEADERS_MOC} | ||||
| 	${sdrdaemon_FORMS_HEADERS} | ||||
| ) | ||||
| 
 | ||||
| target_link_libraries(inputsdrdaemon | ||||
| 	${QT_LIBRARIES} | ||||
| 	${LIBUSB_LIBRARIES} | ||||
| 	sdrbase | ||||
| ) | ||||
| 
 | ||||
| qt5_use_modules(inputsdrdaemon Core Widgets OpenGL Multimedia) | ||||
							
								
								
									
										241
									
								
								plugins/samplesource/sdrdaemon/sdrdaemongui.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										241
									
								
								plugins/samplesource/sdrdaemon/sdrdaemongui.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,241 @@ | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Copyright (C) 2015 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 <http://www.gnu.org/licenses/>.          //
 | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| #include <QDebug> | ||||
| 
 | ||||
| #include <QTime> | ||||
| #include <QDateTime> | ||||
| #include <QString> | ||||
| #include <QFileDialog> | ||||
| #include "ui_sdrdaemongui.h" | ||||
| #include "plugin/pluginapi.h" | ||||
| #include "gui/colormapper.h" | ||||
| #include "dsp/dspengine.h" | ||||
| #include "mainwindow.h" | ||||
| 
 | ||||
| #include "sdrdaemongui.h" | ||||
| 
 | ||||
| SDRdaemonGui::SDRdaemonGui(PluginAPI* pluginAPI, QWidget* parent) : | ||||
| 	QWidget(parent), | ||||
| 	ui(new Ui::SDRdaemonGui), | ||||
| 	m_pluginAPI(pluginAPI), | ||||
| 	m_settings(), | ||||
| 	m_sampleSource(NULL), | ||||
| 	m_acquisition(false), | ||||
| 	m_fileName("..."), | ||||
| 	m_sampleRate(0), | ||||
| 	m_centerFrequency(0), | ||||
| 	m_startingTimeStamp(0), | ||||
| 	m_samplesCount(0), | ||||
| 	m_tickCount(0) | ||||
| { | ||||
| 	ui->setupUi(this); | ||||
| 	ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::ReverseGold)); | ||||
| 	ui->centerFrequency->setValueRange(7, 0, pow(10,7)); | ||||
| 	ui->fileNameText->setText(m_fileName); | ||||
| 	connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware())); | ||||
| 	connect(&(m_pluginAPI->getMainWindow()->getMasterTimer()), SIGNAL(timeout()), this, SLOT(tick())); | ||||
| 	displaySettings(); | ||||
| 
 | ||||
| 	m_sampleSource = new SDRdaemonInput(m_pluginAPI->getMainWindow()->getMasterTimer()); | ||||
| 	connect(m_sampleSource->getOutputMessageQueueToGUI(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages())); | ||||
| 	DSPEngine::instance()->setSource(m_sampleSource); | ||||
| } | ||||
| 
 | ||||
| SDRdaemonGui::~SDRdaemonGui() | ||||
| { | ||||
| 	delete ui; | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonGui::destroy() | ||||
| { | ||||
| 	delete this; | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonGui::setName(const QString& name) | ||||
| { | ||||
| 	setObjectName(name); | ||||
| } | ||||
| 
 | ||||
| QString SDRdaemonGui::getName() const | ||||
| { | ||||
| 	return objectName(); | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonGui::resetToDefaults() | ||||
| { | ||||
| 	m_settings.resetToDefaults(); | ||||
| 	displaySettings(); | ||||
| 	sendSettings(); | ||||
| } | ||||
| 
 | ||||
| qint64 SDRdaemonGui::getCenterFrequency() const | ||||
| { | ||||
| 	return m_centerFrequency; | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonGui::setCenterFrequency(qint64 centerFrequency) | ||||
| { | ||||
| 	m_centerFrequency = centerFrequency; | ||||
| 	displaySettings(); | ||||
| 	sendSettings(); | ||||
| } | ||||
| 
 | ||||
| QByteArray SDRdaemonGui::serialize() const | ||||
| { | ||||
| 	return m_settings.serialize(); | ||||
| } | ||||
| 
 | ||||
| bool SDRdaemonGui::deserialize(const QByteArray& data) | ||||
| { | ||||
| 	if(m_settings.deserialize(data)) { | ||||
| 		displaySettings(); | ||||
| 		sendSettings(); | ||||
| 		return true; | ||||
| 	} else { | ||||
| 		resetToDefaults(); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| bool SDRdaemonGui::handleMessage(const Message& message) | ||||
| { | ||||
| 	if (SDRdaemonInput::MsgReportSDRdaemonAcquisition::match(message)) | ||||
| 	{ | ||||
| 		m_acquisition = ((SDRdaemonInput::MsgReportSDRdaemonAcquisition&)message).getAcquisition(); | ||||
| 		updateWithAcquisition(); | ||||
| 		return true; | ||||
| 	} | ||||
| 	else if (SDRdaemonInput::MsgReportSDRdaemonStreamData::match(message)) | ||||
| 	{ | ||||
| 		m_sampleRate = ((SDRdaemonInput::MsgReportSDRdaemonStreamData&)message).getSampleRate(); | ||||
| 		m_centerFrequency = ((SDRdaemonInput::MsgReportSDRdaemonStreamData&)message).getCenterFrequency(); | ||||
| 		m_startingTimeStamp = ((SDRdaemonInput::MsgReportSDRdaemonStreamData&)message).getStartingTimeStamp(); | ||||
| 		updateWithStreamData(); | ||||
| 		return true; | ||||
| 	} | ||||
| 	else if (SDRdaemonInput::MsgReportSDRdaemonStreamTiming::match(message)) | ||||
| 	{ | ||||
| 		m_samplesCount = ((SDRdaemonInput::MsgReportSDRdaemonStreamTiming&)message).getSamplesCount(); | ||||
| 		updateWithStreamTime(); | ||||
| 		return true; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonGui::handleSourceMessages() | ||||
| { | ||||
| 	Message* message; | ||||
| 
 | ||||
| 	while ((message = m_sampleSource->getOutputMessageQueueToGUI()->pop()) != 0) | ||||
| 	{ | ||||
| 		qDebug("SDRdaemonGui::handleSourceMessages: message: %s", message->getIdentifier()); | ||||
| 
 | ||||
| 		if (handleMessage(*message)) | ||||
| 		{ | ||||
| 			delete message; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonGui::displaySettings() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonGui::sendSettings() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonGui::updateHardware() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonGui::on_play_toggled(bool checked) | ||||
| { | ||||
| 	SDRdaemonInput::MsgConfigureSDRdaemonWork* message = SDRdaemonInput::MsgConfigureSDRdaemonWork::create(checked); | ||||
| 	m_sampleSource->getInputMessageQueue()->push(message); | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonGui::on_showFileDialog_clicked(bool checked) | ||||
| { | ||||
| 	QString fileName = QFileDialog::getOpenFileName(this, | ||||
| 	    tr("Open I/Q record file"), ".", tr("SDR I/Q Files (*.sdriq)")); | ||||
| 
 | ||||
| 	if (fileName != "") | ||||
| 	{ | ||||
| 		m_fileName = fileName; | ||||
| 		ui->fileNameText->setText(m_fileName); | ||||
| 		configureFileName(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonGui::configureFileName() | ||||
| { | ||||
| 	qDebug() << "SDRdaemonGui::configureFileName: " << m_fileName.toStdString().c_str(); | ||||
| 	SDRdaemonInput::MsgConfigureSDRdaemonName* message = SDRdaemonInput::MsgConfigureSDRdaemonName::create(m_fileName); | ||||
| 	m_sampleSource->getInputMessageQueue()->push(message); | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonGui::updateWithAcquisition() | ||||
| { | ||||
| 	ui->play->setEnabled(m_acquisition); | ||||
| 	ui->play->setChecked(m_acquisition); | ||||
| 	ui->showFileDialog->setEnabled(!m_acquisition); | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonGui::updateWithStreamData() | ||||
| { | ||||
| 	ui->centerFrequency->setValue(m_centerFrequency/1000); | ||||
| 	QString s = QString::number(m_sampleRate/1000.0, 'f', 0); | ||||
| 	ui->sampleRateText->setText(tr("%1k").arg(s)); | ||||
| 	ui->play->setEnabled(m_acquisition); | ||||
| 	updateWithStreamTime(); // TODO: remove when time data is implemented
 | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonGui::updateWithStreamTime() | ||||
| { | ||||
| 	int t_sec = 0; | ||||
| 	int t_msec = 0; | ||||
| 
 | ||||
| 	if (m_sampleRate > 0){ | ||||
| 		t_msec = ((m_samplesCount * 1000) / m_sampleRate) % 1000; | ||||
| 		t_sec = m_samplesCount / m_sampleRate; | ||||
| 	} | ||||
| 
 | ||||
| 	QTime t(0, 0, 0, 0); | ||||
| 	t = t.addSecs(t_sec); | ||||
| 	t = t.addMSecs(t_msec); | ||||
| 	QString s_time = t.toString("hh:mm:ss.zzz"); | ||||
| 	ui->relTimeText->setText(s_time); | ||||
| 
 | ||||
| 	quint64 startingTimeStampMsec = m_startingTimeStamp * 1000; | ||||
| 	QDateTime dt = QDateTime::fromMSecsSinceEpoch(startingTimeStampMsec); | ||||
| 	dt = dt.addSecs(t_sec); | ||||
| 	dt = dt.addMSecs(t_msec); | ||||
| 	QString s_date = dt.toString("yyyyMMdd hh.mm.ss.zzz"); | ||||
| 	ui->absTimeText->setText(s_date); | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonGui::tick() | ||||
| { | ||||
| 	if ((++m_tickCount & 0xf) == 0) { | ||||
| 		SDRdaemonInput::MsgConfigureSDRdaemonStreamTiming* message = SDRdaemonInput::MsgConfigureSDRdaemonStreamTiming::create(); | ||||
| 		m_sampleSource->getInputMessageQueue()->push(message); | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										82
									
								
								plugins/samplesource/sdrdaemon/sdrdaemongui.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								plugins/samplesource/sdrdaemon/sdrdaemongui.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,82 @@ | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.          //
 | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| #ifndef INCLUDE_SDRDAEMONGUI_H | ||||
| #define INCLUDE_SDRDAEMONGUI_H | ||||
| 
 | ||||
| #include <QTimer> | ||||
| #include "plugin/plugingui.h" | ||||
| 
 | ||||
| #include "sdrdaemoninput.h" | ||||
| 
 | ||||
| class PluginAPI; | ||||
| 
 | ||||
| namespace Ui { | ||||
| 	class SDRdaemonGui; | ||||
| } | ||||
| 
 | ||||
| class SDRdaemonGui : public QWidget, public PluginGUI { | ||||
| 	Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
| 	explicit SDRdaemonGui(PluginAPI* pluginAPI, QWidget* parent = NULL); | ||||
| 	virtual ~SDRdaemonGui(); | ||||
| 	void destroy(); | ||||
| 
 | ||||
| 	void setName(const QString& name); | ||||
| 	QString getName() const; | ||||
| 
 | ||||
| 	void resetToDefaults(); | ||||
| 	virtual qint64 getCenterFrequency() const; | ||||
| 	virtual void setCenterFrequency(qint64 centerFrequency); | ||||
| 	QByteArray serialize() const; | ||||
| 	bool deserialize(const QByteArray& data); | ||||
| 	virtual bool handleMessage(const Message& message); | ||||
| 
 | ||||
| private: | ||||
| 	Ui::SDRdaemonGui* ui; | ||||
| 
 | ||||
| 	PluginAPI* m_pluginAPI; | ||||
| 	SDRdaemonInput::Settings m_settings; | ||||
| 	QTimer m_updateTimer; | ||||
| 	std::vector<int> m_gains; | ||||
| 	SampleSource* m_sampleSource; | ||||
|     bool m_acquisition; | ||||
|     QString m_fileName; | ||||
| 	int m_sampleRate; | ||||
| 	quint64 m_centerFrequency; | ||||
| 	std::time_t m_startingTimeStamp; | ||||
| 	int m_samplesCount; | ||||
| 	std::size_t m_tickCount; | ||||
| 
 | ||||
| 	void displaySettings(); | ||||
| 	void displayTime(); | ||||
| 	void sendSettings(); | ||||
| 	void updateHardware(); | ||||
| 	void configureFileName(); | ||||
| 	void updateWithAcquisition(); | ||||
| 	void updateWithStreamData(); | ||||
| 	void updateWithStreamTime(); | ||||
| 
 | ||||
| private slots: | ||||
| 	void handleSourceMessages(); | ||||
| 	void on_playLoop_toggled(bool checked); | ||||
| 	void on_play_toggled(bool checked); | ||||
| 	void on_showFileDialog_clicked(bool checked); | ||||
| 	void tick(); | ||||
| }; | ||||
| 
 | ||||
| #endif // INCLUDE_SDRDAEMONGUI_H
 | ||||
							
								
								
									
										346
									
								
								plugins/samplesource/sdrdaemon/sdrdaemongui.ui
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										346
									
								
								plugins/samplesource/sdrdaemon/sdrdaemongui.ui
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,346 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <ui version="4.0"> | ||||
|  <class>SDRdaemonGui</class> | ||||
|  <widget class="QWidget" name="SDRdaemonGui"> | ||||
|   <property name="geometry"> | ||||
|    <rect> | ||||
|     <x>0</x> | ||||
|     <y>0</y> | ||||
|     <width>198</width> | ||||
|     <height>133</height> | ||||
|    </rect> | ||||
|   </property> | ||||
|   <property name="sizePolicy"> | ||||
|    <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> | ||||
|     <horstretch>0</horstretch> | ||||
|     <verstretch>0</verstretch> | ||||
|    </sizepolicy> | ||||
|   </property> | ||||
|   <property name="font"> | ||||
|    <font> | ||||
|     <family>Sans Serif</family> | ||||
|     <pointsize>9</pointsize> | ||||
|    </font> | ||||
|   </property> | ||||
|   <property name="windowTitle"> | ||||
|    <string>BladeRF</string> | ||||
|   </property> | ||||
|   <layout class="QVBoxLayout" name="verticalLayout"> | ||||
|    <property name="spacing"> | ||||
|     <number>3</number> | ||||
|    </property> | ||||
|    <property name="leftMargin"> | ||||
|     <number>2</number> | ||||
|    </property> | ||||
|    <property name="topMargin"> | ||||
|     <number>2</number> | ||||
|    </property> | ||||
|    <property name="rightMargin"> | ||||
|     <number>2</number> | ||||
|    </property> | ||||
|    <property name="bottomMargin"> | ||||
|     <number>2</number> | ||||
|    </property> | ||||
|    <item> | ||||
|     <layout class="QHBoxLayout" name="horizontalLayout_freq"> | ||||
|      <item> | ||||
|       <spacer name="freqLeftSpacer"> | ||||
|        <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="enabled"> | ||||
|         <bool>false</bool> | ||||
|        </property> | ||||
|        <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="cursor"> | ||||
|         <cursorShape>SizeVerCursor</cursorShape> | ||||
|        </property> | ||||
|        <property name="focusPolicy"> | ||||
|         <enum>Qt::StrongFocus</enum> | ||||
|        </property> | ||||
|        <property name="toolTip"> | ||||
|         <string>Record center frequency in kHz</string> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <widget class="QLabel" name="freqUnits"> | ||||
|        <property name="text"> | ||||
|         <string> kHz</string> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <spacer name="freqRightlSpacer"> | ||||
|        <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_freq"> | ||||
|      <property name="orientation"> | ||||
|       <enum>Qt::Horizontal</enum> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item> | ||||
|     <layout class="QHBoxLayout" name="fileSelectionLayout"> | ||||
|      <item> | ||||
|       <widget class="QPushButton" name="showFileDialog"> | ||||
|        <property name="minimumSize"> | ||||
|         <size> | ||||
|          <width>24</width> | ||||
|          <height>24</height> | ||||
|         </size> | ||||
|        </property> | ||||
|        <property name="maximumSize"> | ||||
|         <size> | ||||
|          <width>24</width> | ||||
|          <height>24</height> | ||||
|         </size> | ||||
|        </property> | ||||
|        <property name="toolTip"> | ||||
|         <string>Open file</string> | ||||
|        </property> | ||||
|        <property name="text"> | ||||
|         <string/> | ||||
|        </property> | ||||
|        <property name="icon"> | ||||
|         <iconset resource="../../../sdrbase/resources/res.qrc"> | ||||
|          <normaloff>:/preset-load.png</normaloff>:/preset-load.png</iconset> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <widget class="QLabel" name="fileNameText"> | ||||
|        <property name="enabled"> | ||||
|         <bool>false</bool> | ||||
|        </property> | ||||
|        <property name="toolTip"> | ||||
|         <string>File currently opened</string> | ||||
|        </property> | ||||
|        <property name="text"> | ||||
|         <string>...</string> | ||||
|        </property> | ||||
|        <property name="alignment"> | ||||
|         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|     </layout> | ||||
|    </item> | ||||
|    <item> | ||||
|     <widget class="Line" name="line_file"> | ||||
|      <property name="orientation"> | ||||
|       <enum>Qt::Horizontal</enum> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item> | ||||
|     <layout class="QHBoxLayout" name="rateTimeLayout"> | ||||
|      <item> | ||||
|       <widget class="QLabel" name="sampleRateText"> | ||||
|        <property name="font"> | ||||
|         <font> | ||||
|          <pointsize>8</pointsize> | ||||
|         </font> | ||||
|        </property> | ||||
|        <property name="toolTip"> | ||||
|         <string>Record sample rate</string> | ||||
|        </property> | ||||
|        <property name="text"> | ||||
|         <string>0k</string> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <spacer name="horizontalSpacer"> | ||||
|        <property name="orientation"> | ||||
|         <enum>Qt::Horizontal</enum> | ||||
|        </property> | ||||
|        <property name="sizeHint" stdset="0"> | ||||
|         <size> | ||||
|          <width>40</width> | ||||
|          <height>20</height> | ||||
|         </size> | ||||
|        </property> | ||||
|       </spacer> | ||||
|      </item> | ||||
|      <item> | ||||
|       <widget class="Line" name="absTimeLine"> | ||||
|        <property name="orientation"> | ||||
|         <enum>Qt::Vertical</enum> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <widget class="QLabel" name="absTimeText"> | ||||
|        <property name="enabled"> | ||||
|         <bool>false</bool> | ||||
|        </property> | ||||
|        <property name="toolTip"> | ||||
|         <string>Record absolute time</string> | ||||
|        </property> | ||||
|        <property name="text"> | ||||
|         <string>20150101 00:00:00.000</string> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|     </layout> | ||||
|    </item> | ||||
|    <item> | ||||
|     <widget class="Line" name="line_rate"> | ||||
|      <property name="orientation"> | ||||
|       <enum>Qt::Horizontal</enum> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item> | ||||
|     <layout class="QHBoxLayout" name="playControllLayout"> | ||||
|      <item> | ||||
|       <widget class="ButtonSwitch" name="playLoop"> | ||||
|        <property name="toolTip"> | ||||
|         <string>Play in a loop</string> | ||||
|        </property> | ||||
|        <property name="text"> | ||||
|         <string/> | ||||
|        </property> | ||||
|        <property name="icon"> | ||||
|         <iconset resource="../../../sdrbase/resources/res.qrc"> | ||||
|          <normaloff>:/playloop.png</normaloff>:/playloop.png</iconset> | ||||
|        </property> | ||||
|        <property name="iconSize"> | ||||
|         <size> | ||||
|          <width>16</width> | ||||
|          <height>16</height> | ||||
|         </size> | ||||
|        </property> | ||||
|        <property name="checkable"> | ||||
|         <bool>true</bool> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <widget class="ButtonSwitch" name="play"> | ||||
|        <property name="toolTip"> | ||||
|         <string>Stopped / Play / Pause</string> | ||||
|        </property> | ||||
|        <property name="text"> | ||||
|         <string/> | ||||
|        </property> | ||||
|        <property name="icon"> | ||||
|         <iconset resource="../../../sdrbase/resources/res.qrc"> | ||||
|          <normaloff>:/play.png</normaloff> | ||||
|          <normalon>:/pause.png</normalon> | ||||
|          <disabledoff>:/stop.png</disabledoff> | ||||
|          <disabledon>:/stop.png</disabledon> | ||||
|          <activeoff>:/play.png</activeoff> | ||||
|          <activeon>:/pause.png</activeon> | ||||
|          <selectedoff>:/play.png</selectedoff> | ||||
|          <selectedon>:/pause.png</selectedon>:/play.png</iconset> | ||||
|        </property> | ||||
|        <property name="iconSize"> | ||||
|         <size> | ||||
|          <width>16</width> | ||||
|          <height>16</height> | ||||
|         </size> | ||||
|        </property> | ||||
|        <property name="checkable"> | ||||
|         <bool>true</bool> | ||||
|        </property> | ||||
|        <property name="checked"> | ||||
|         <bool>false</bool> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <spacer name="horizontalSpacer_2"> | ||||
|        <property name="orientation"> | ||||
|         <enum>Qt::Horizontal</enum> | ||||
|        </property> | ||||
|        <property name="sizeHint" stdset="0"> | ||||
|         <size> | ||||
|          <width>40</width> | ||||
|          <height>20</height> | ||||
|         </size> | ||||
|        </property> | ||||
|       </spacer> | ||||
|      </item> | ||||
|      <item> | ||||
|       <widget class="Line" name="relTimeLine"> | ||||
|        <property name="orientation"> | ||||
|         <enum>Qt::Vertical</enum> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <widget class="QLabel" name="relTimeText"> | ||||
|        <property name="enabled"> | ||||
|         <bool>false</bool> | ||||
|        </property> | ||||
|        <property name="toolTip"> | ||||
|         <string>Record time from start</string> | ||||
|        </property> | ||||
|        <property name="text"> | ||||
|         <string>00:00:00.000</string> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|     </layout> | ||||
|    </item> | ||||
|   </layout> | ||||
|  </widget> | ||||
|  <customwidgets> | ||||
|   <customwidget> | ||||
|    <class>ValueDial</class> | ||||
|    <extends>QWidget</extends> | ||||
|    <header>gui/valuedial.h</header> | ||||
|    <container>1</container> | ||||
|   </customwidget> | ||||
|   <customwidget> | ||||
|    <class>ButtonSwitch</class> | ||||
|    <extends>QToolButton</extends> | ||||
|    <header>gui/buttonswitch.h</header> | ||||
|   </customwidget> | ||||
|  </customwidgets> | ||||
|  <resources> | ||||
|   <include location="../../../sdrbase/resources/res.qrc"/> | ||||
|  </resources> | ||||
|  <connections/> | ||||
| </ui> | ||||
							
								
								
									
										290
									
								
								plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										290
									
								
								plugins/samplesource/sdrdaemon/sdrdaemoninput.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,290 @@ | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Copyright (C) 2015 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 <http://www.gnu.org/licenses/>.          //
 | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| #include <string.h> | ||||
| #include <errno.h> | ||||
| #include <QDebug> | ||||
| 
 | ||||
| #include "util/simpleserializer.h" | ||||
| #include "dsp/dspcommands.h" | ||||
| #include "dsp/dspengine.h" | ||||
| #include "dsp/filesink.h" | ||||
| 
 | ||||
| #include "sdrdaemongui.h" | ||||
| #include "sdrdaemoninput.h" | ||||
| #include "sdrdaemonthread.h" | ||||
| 
 | ||||
| MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemon, Message) | ||||
| MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonName, Message) | ||||
| MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonWork, Message) | ||||
| MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgConfigureSDRdaemonStreamTiming, Message) | ||||
| MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgReportSDRdaemonAcquisition, Message) | ||||
| MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgReportSDRdaemonStreamData, Message) | ||||
| MESSAGE_CLASS_DEFINITION(SDRdaemonInput::MsgReportSDRdaemonStreamTiming, Message) | ||||
| 
 | ||||
| SDRdaemonInput::Settings::Settings() : | ||||
| 	m_fileName("./test.sdriq") | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonInput::Settings::resetToDefaults() | ||||
| { | ||||
| 	m_fileName = "./test.sdriq"; | ||||
| } | ||||
| 
 | ||||
| QByteArray SDRdaemonInput::Settings::serialize() const | ||||
| { | ||||
| 	SimpleSerializer s(1); | ||||
| 	s.writeString(1, m_fileName); | ||||
| 	return s.final(); | ||||
| } | ||||
| 
 | ||||
| bool SDRdaemonInput::Settings::deserialize(const QByteArray& data) | ||||
| { | ||||
| 	SimpleDeserializer d(data); | ||||
| 
 | ||||
| 	if(!d.isValid()) { | ||||
| 		resetToDefaults(); | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	if(d.getVersion() == 1) { | ||||
| 		int intval; | ||||
| 		d.readString(1, &m_fileName, "./test.sdriq"); | ||||
| 		return true; | ||||
| 	} else { | ||||
| 		resetToDefaults(); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| SDRdaemonInput::SDRdaemonInput(const QTimer& masterTimer) : | ||||
| 	m_settings(), | ||||
| 	m_SDRdaemonThread(NULL), | ||||
| 	m_deviceDescription(), | ||||
| 	m_fileName("..."), | ||||
| 	m_sampleRate(0), | ||||
| 	m_centerFrequency(0), | ||||
| 	m_startingTimeStamp(0), | ||||
| 	m_masterTimer(masterTimer) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| SDRdaemonInput::~SDRdaemonInput() | ||||
| { | ||||
| 	stop(); | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonInput::openFileStream() | ||||
| { | ||||
| 	qDebug() << "SDRdaemonInput::openFileStream: " << m_fileName.toStdString().c_str(); | ||||
| 
 | ||||
| 	//stopInput();
 | ||||
| 
 | ||||
| 	if (m_ifstream.is_open()) { | ||||
| 		m_ifstream.close(); | ||||
| 	} | ||||
| 
 | ||||
| 	m_ifstream.open(m_fileName.toStdString().c_str(), std::ios::binary); | ||||
| 	FileSink::Header header; | ||||
| 	FileSink::readHeader(m_ifstream, header); | ||||
| 
 | ||||
| 	m_sampleRate = header.sampleRate; | ||||
| 	m_centerFrequency = header.centerFrequency; | ||||
| 	m_startingTimeStamp = header.startTimeStamp; | ||||
| 
 | ||||
| 	MsgReportSDRdaemonStreamData *report = MsgReportSDRdaemonStreamData::create(m_sampleRate, m_centerFrequency, m_startingTimeStamp); // file stream data
 | ||||
| 	getOutputMessageQueueToGUI()->push(report); | ||||
| } | ||||
| 
 | ||||
| bool SDRdaemonInput::init(const Message& message) | ||||
| { | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| bool SDRdaemonInput::start(int device) | ||||
| { | ||||
| 	QMutexLocker mutexLocker(&m_mutex); | ||||
| 	qDebug() << "SDRdaemonInput::startInput"; | ||||
| 
 | ||||
| 	if (m_ifstream.tellg() != 0) { | ||||
| 		m_ifstream.clear(); | ||||
| 		m_ifstream.seekg(0, std::ios::beg); | ||||
| 	} | ||||
| 
 | ||||
| 	if(!m_sampleFifo.setSize(96000 * 4)) { | ||||
| 		qCritical("Could not allocate SampleFifo"); | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	//openFileStream();
 | ||||
| 
 | ||||
| 	if((m_SDRdaemonThread = new SDRdaemonThread(&m_ifstream, &m_sampleFifo)) == NULL) { | ||||
| 		qFatal("out of memory"); | ||||
| 		stop(); | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	m_SDRdaemonThread->setSamplerate(m_sampleRate); | ||||
| 	m_SDRdaemonThread->connectTimer(m_masterTimer); | ||||
| 	m_SDRdaemonThread->startWork(); | ||||
| 	m_deviceDescription = "SDRdaemon"; | ||||
| 
 | ||||
| 	mutexLocker.unlock(); | ||||
| 	//applySettings(m_generalSettings, m_settings, true);
 | ||||
| 	qDebug("SDRdaemonInput::startInput: started"); | ||||
| 
 | ||||
| 	MsgReportSDRdaemonAcquisition *report = MsgReportSDRdaemonAcquisition::create(true); // acquisition on
 | ||||
| 	getOutputMessageQueueToGUI()->push(report); | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonInput::stop() | ||||
| { | ||||
| 	qDebug() << "SDRdaemonInput::stop"; | ||||
| 	QMutexLocker mutexLocker(&m_mutex); | ||||
| 
 | ||||
| 	if(m_SDRdaemonThread != 0) | ||||
| 	{ | ||||
| 		m_SDRdaemonThread->stopWork(); | ||||
| 		delete m_SDRdaemonThread; | ||||
| 		m_SDRdaemonThread = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	m_deviceDescription.clear(); | ||||
| 
 | ||||
| 	MsgReportSDRdaemonAcquisition *report = MsgReportSDRdaemonAcquisition::create(false); // acquisition off
 | ||||
| 	getOutputMessageQueueToGUI()->push(report); | ||||
| } | ||||
| 
 | ||||
| const QString& SDRdaemonInput::getDeviceDescription() const | ||||
| { | ||||
| 	return m_deviceDescription; | ||||
| } | ||||
| 
 | ||||
| int SDRdaemonInput::getSampleRate() const | ||||
| { | ||||
| 	return m_sampleRate; | ||||
| } | ||||
| 
 | ||||
| quint64 SDRdaemonInput::getCenterFrequency() const | ||||
| { | ||||
| 	return m_centerFrequency; | ||||
| } | ||||
| 
 | ||||
| std::time_t SDRdaemonInput::getStartingTimeStamp() const | ||||
| { | ||||
| 	return m_startingTimeStamp; | ||||
| } | ||||
| 
 | ||||
| bool SDRdaemonInput::handleMessage(const Message& message) | ||||
| { | ||||
| 	if (MsgConfigureSDRdaemonName::match(message)) | ||||
| 	{ | ||||
| 		MsgConfigureSDRdaemonName& conf = (MsgConfigureSDRdaemonName&) message; | ||||
| 		m_fileName = conf.getFileName(); | ||||
| 		openFileStream(); | ||||
| 		return true; | ||||
| 	} | ||||
| 	else if (MsgConfigureSDRdaemonWork::match(message)) | ||||
| 	{ | ||||
| 		MsgConfigureSDRdaemonWork& conf = (MsgConfigureSDRdaemonWork&) message; | ||||
| 		bool working = conf.isWorking(); | ||||
| 
 | ||||
| 		if (m_SDRdaemonThread != 0) | ||||
| 		{ | ||||
| 			if (working) | ||||
| 			{ | ||||
| 				m_SDRdaemonThread->startWork(); | ||||
| 				MsgReportSDRdaemonStreamTiming *report = | ||||
| 						MsgReportSDRdaemonStreamTiming::create(m_SDRdaemonThread->getSamplesCount()); | ||||
| 				getOutputMessageQueueToGUI()->push(report); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				m_SDRdaemonThread->stopWork(); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		return true; | ||||
| 	} | ||||
| 	else if (MsgConfigureSDRdaemonStreamTiming::match(message)) | ||||
| 	{ | ||||
| 		MsgReportSDRdaemonStreamTiming *report; | ||||
| 
 | ||||
| 		if (m_SDRdaemonThread != 0) | ||||
| 		{ | ||||
| 			report = MsgReportSDRdaemonStreamTiming::create(m_SDRdaemonThread->getSamplesCount()); | ||||
| 			getOutputMessageQueueToGUI()->push(report); | ||||
| 		} | ||||
| 
 | ||||
| 		return true; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| bool SDRdaemonInput::applySettings(const Settings& settings, bool force) | ||||
| { | ||||
| 	QMutexLocker mutexLocker(&m_mutex); | ||||
| 	bool wasRunning = false; | ||||
| 
 | ||||
| 	if((m_settings.m_fileName != settings.m_fileName) || force) | ||||
| 	{ | ||||
| 		m_settings.m_fileName = settings.m_fileName; | ||||
| 
 | ||||
| 		if (m_SDRdaemonThread != 0) | ||||
| 		{ | ||||
| 			wasRunning = m_SDRdaemonThread->isRunning(); | ||||
| 
 | ||||
| 			if (wasRunning) | ||||
| 			{ | ||||
| 				m_SDRdaemonThread->stopWork(); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if (m_ifstream.is_open()) | ||||
| 		{ | ||||
| 			m_ifstream.close(); | ||||
| 		} | ||||
| 
 | ||||
| 		openFileStream(); | ||||
| 
 | ||||
| 		if (m_SDRdaemonThread != 0) | ||||
| 		{ | ||||
| 			m_SDRdaemonThread->setSamplerate(m_sampleRate); | ||||
| 
 | ||||
| 			if (wasRunning) | ||||
| 			{ | ||||
| 				m_SDRdaemonThread->startWork(); | ||||
| 			} | ||||
| 		} | ||||
|          | ||||
| 		DSPSignalNotification *notif = new DSPSignalNotification(m_sampleRate, m_centerFrequency); | ||||
| 		DSPEngine::instance()->getInputMessageQueue()->push(notif); | ||||
| 
 | ||||
| 		qDebug() << "SDRdaemonInput::applySettings:" | ||||
| 				<< " file name: " << settings.m_fileName.toStdString().c_str() | ||||
| 				<< " center freq: " << m_centerFrequency << " Hz" | ||||
| 				<< " sample rate: " << m_sampleRate | ||||
| 				<< " Unix timestamp: " << m_startingTimeStamp; | ||||
| 	} | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
							
								
								
									
										213
									
								
								plugins/samplesource/sdrdaemon/sdrdaemoninput.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								plugins/samplesource/sdrdaemon/sdrdaemoninput.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,213 @@ | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.          //
 | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| #ifndef INCLUDE_SDRDAEMONINPUT_H | ||||
| #define INCLUDE_SDRDAEMONINPUT_H | ||||
| 
 | ||||
| #include "dsp/samplesource.h" | ||||
| #include <QString> | ||||
| #include <QTimer> | ||||
| #include <ctime> | ||||
| #include <iostream> | ||||
| #include <fstream> | ||||
| 
 | ||||
| class SDRdaemonThread; | ||||
| 
 | ||||
| class SDRdaemonInput : public SampleSource { | ||||
| public: | ||||
| 	struct Settings { | ||||
| 		QString m_fileName; | ||||
| 
 | ||||
| 		Settings(); | ||||
| 		void resetToDefaults(); | ||||
| 		QByteArray serialize() const; | ||||
| 		bool deserialize(const QByteArray& data); | ||||
| 	}; | ||||
| 
 | ||||
| 	class MsgConfigureSDRdaemon : public Message { | ||||
| 		MESSAGE_CLASS_DECLARATION | ||||
| 
 | ||||
| 	public: | ||||
| 		const Settings& getSettings() const { return m_settings; } | ||||
| 
 | ||||
| 		static MsgConfigureSDRdaemon* create(const Settings& settings) | ||||
| 		{ | ||||
| 			return new MsgConfigureSDRdaemon(settings); | ||||
| 		} | ||||
| 
 | ||||
| 	private: | ||||
| 		Settings m_settings; | ||||
| 
 | ||||
| 		MsgConfigureSDRdaemon(const Settings& settings) : | ||||
| 			Message(), | ||||
| 			m_settings(settings) | ||||
| 		{ } | ||||
| 	}; | ||||
| 
 | ||||
| 	class MsgConfigureSDRdaemonName : public Message { | ||||
| 		MESSAGE_CLASS_DECLARATION | ||||
| 
 | ||||
| 	public: | ||||
| 		const QString& getFileName() const { return m_fileName; } | ||||
| 
 | ||||
| 		static MsgConfigureSDRdaemonName* create(const QString& fileName) | ||||
| 		{ | ||||
| 			return new MsgConfigureSDRdaemonName(fileName); | ||||
| 		} | ||||
| 
 | ||||
| 	private: | ||||
| 		QString m_fileName; | ||||
| 
 | ||||
| 		MsgConfigureSDRdaemonName(const QString& fileName) : | ||||
| 			Message(), | ||||
| 			m_fileName(fileName) | ||||
| 		{ } | ||||
| 	}; | ||||
| 
 | ||||
| 	class MsgConfigureSDRdaemonWork : public Message { | ||||
| 		MESSAGE_CLASS_DECLARATION | ||||
| 
 | ||||
| 	public: | ||||
| 		bool isWorking() const { return m_working; } | ||||
| 
 | ||||
| 		static MsgConfigureSDRdaemonWork* create(bool working) | ||||
| 		{ | ||||
| 			return new MsgConfigureSDRdaemonWork(working); | ||||
| 		} | ||||
| 
 | ||||
| 	private: | ||||
| 		bool m_working; | ||||
| 
 | ||||
| 		MsgConfigureSDRdaemonWork(bool working) : | ||||
| 			Message(), | ||||
| 			m_working(working) | ||||
| 		{ } | ||||
| 	}; | ||||
| 
 | ||||
| 	class MsgConfigureSDRdaemonStreamTiming : public Message { | ||||
| 		MESSAGE_CLASS_DECLARATION | ||||
| 
 | ||||
| 	public: | ||||
| 
 | ||||
| 		static MsgConfigureSDRdaemonStreamTiming* create() | ||||
| 		{ | ||||
| 			return new MsgConfigureSDRdaemonStreamTiming(); | ||||
| 		} | ||||
| 
 | ||||
| 	private: | ||||
| 
 | ||||
| 		MsgConfigureSDRdaemonStreamTiming() : | ||||
| 			Message() | ||||
| 		{ } | ||||
| 	}; | ||||
| 
 | ||||
| 	class MsgReportSDRdaemonAcquisition : public Message { | ||||
| 		MESSAGE_CLASS_DECLARATION | ||||
| 
 | ||||
| 	public: | ||||
| 		bool getAcquisition() const { return m_acquisition; } | ||||
| 
 | ||||
| 		static MsgReportSDRdaemonAcquisition* create(bool acquisition) | ||||
| 		{ | ||||
| 			return new MsgReportSDRdaemonAcquisition(acquisition); | ||||
| 		} | ||||
| 
 | ||||
| 	protected: | ||||
| 		bool m_acquisition; | ||||
| 
 | ||||
| 		MsgReportSDRdaemonAcquisition(bool acquisition) : | ||||
| 			Message(), | ||||
| 			m_acquisition(acquisition) | ||||
| 		{ } | ||||
| 	}; | ||||
| 
 | ||||
| 	class MsgReportSDRdaemonStreamData : public Message { | ||||
| 		MESSAGE_CLASS_DECLARATION | ||||
| 
 | ||||
| 	public: | ||||
| 		int getSampleRate() const { return m_sampleRate; } | ||||
| 		quint64 getCenterFrequency() const { return m_centerFrequency; } | ||||
| 		std::time_t getStartingTimeStamp() const { return m_startingTimeStamp; } | ||||
| 
 | ||||
| 		static MsgReportSDRdaemonStreamData* create(int sampleRate, quint64 centerFrequency, std::time_t startingTimeStamp) | ||||
| 		{ | ||||
| 			return new MsgReportSDRdaemonStreamData(sampleRate, centerFrequency, startingTimeStamp); | ||||
| 		} | ||||
| 
 | ||||
| 	protected: | ||||
| 		int m_sampleRate; | ||||
| 		quint64 m_centerFrequency; | ||||
| 		std::time_t m_startingTimeStamp; | ||||
| 
 | ||||
| 		MsgReportSDRdaemonStreamData(int sampleRate, quint64 centerFrequency, std::time_t startingTimeStamp) : | ||||
| 			Message(), | ||||
| 			m_sampleRate(sampleRate), | ||||
| 			m_centerFrequency(centerFrequency), | ||||
| 			m_startingTimeStamp(startingTimeStamp) | ||||
| 		{ } | ||||
| 	}; | ||||
| 
 | ||||
| 	class MsgReportSDRdaemonStreamTiming : public Message { | ||||
| 		MESSAGE_CLASS_DECLARATION | ||||
| 
 | ||||
| 	public: | ||||
| 		std::size_t getSamplesCount() const { return m_samplesCount; } | ||||
| 
 | ||||
| 		static MsgReportSDRdaemonStreamTiming* create(std::size_t samplesCount) | ||||
| 		{ | ||||
| 			return new MsgReportSDRdaemonStreamTiming(samplesCount); | ||||
| 		} | ||||
| 
 | ||||
| 	protected: | ||||
| 		std::size_t m_samplesCount; | ||||
| 
 | ||||
| 		MsgReportSDRdaemonStreamTiming(std::size_t samplesCount) : | ||||
| 			Message(), | ||||
| 			m_samplesCount(samplesCount) | ||||
| 		{ } | ||||
| 	}; | ||||
| 
 | ||||
| 	SDRdaemonInput(const QTimer& masterTimer); | ||||
| 	virtual ~SDRdaemonInput(); | ||||
| 
 | ||||
| 	virtual bool init(const Message& message); | ||||
| 	virtual bool start(int device); | ||||
| 	virtual void stop(); | ||||
| 
 | ||||
| 	virtual const QString& getDeviceDescription() const; | ||||
| 	virtual int getSampleRate() const; | ||||
| 	virtual quint64 getCenterFrequency() const; | ||||
| 	std::time_t getStartingTimeStamp() const; | ||||
| 
 | ||||
| 	virtual bool handleMessage(const Message& message); | ||||
| 
 | ||||
| private: | ||||
| 	QMutex m_mutex; | ||||
| 	Settings m_settings; | ||||
| 	std::ifstream m_ifstream; | ||||
| 	SDRdaemonThread* m_SDRdaemonThread; | ||||
| 	QString m_deviceDescription; | ||||
| 	QString m_fileName; | ||||
| 	int m_sampleRate; | ||||
| 	quint64 m_centerFrequency; | ||||
| 	std::time_t m_startingTimeStamp; | ||||
| 	const QTimer& m_masterTimer; | ||||
| 
 | ||||
| 	bool applySettings(const Settings& settings, bool force); | ||||
| 	void openFileStream(); | ||||
| }; | ||||
| 
 | ||||
| #endif // INCLUDE_SDRDAEMONINPUT_H
 | ||||
							
								
								
									
										82
									
								
								plugins/samplesource/sdrdaemon/sdrdaemonplugin.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								plugins/samplesource/sdrdaemon/sdrdaemonplugin.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,82 @@ | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Copyright (C) 2015 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 <http://www.gnu.org/licenses/>.          //
 | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| #include <QtPlugin> | ||||
| #include <QAction> | ||||
| #include "plugin/pluginapi.h" | ||||
| #include "util/simpleserializer.h" | ||||
| 
 | ||||
| #include "sdrdaemongui.h" | ||||
| #include "sdrdaemonplugin.h" | ||||
| 
 | ||||
| const PluginDescriptor SDRdaemonPlugin::m_pluginDescriptor = { | ||||
| 	QString("File source input"), | ||||
| 	QString("---"), | ||||
| 	QString("(c) Edouard Griffiths, F4EXB"), | ||||
| 	QString("https://github.com/f4exb/sdrangel"), | ||||
| 	true, | ||||
| 	QString("https://github.com/f4exb/sdrangel") | ||||
| }; | ||||
| 
 | ||||
| const QString SDRdaemonPlugin::m_deviceTypeID = SDRDAEMON_DEVICE_TYPE_ID; | ||||
| 
 | ||||
| SDRdaemonPlugin::SDRdaemonPlugin(QObject* parent) : | ||||
| 	QObject(parent) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| const PluginDescriptor& SDRdaemonPlugin::getPluginDescriptor() const | ||||
| { | ||||
| 	return m_pluginDescriptor; | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonPlugin::initPlugin(PluginAPI* pluginAPI) | ||||
| { | ||||
| 	m_pluginAPI = pluginAPI; | ||||
| 	m_pluginAPI->registerSampleSource(m_deviceTypeID, this); | ||||
| } | ||||
| 
 | ||||
| PluginInterface::SampleSourceDevices SDRdaemonPlugin::enumSampleSources() | ||||
| { | ||||
| 	SampleSourceDevices result; | ||||
| 	int count = 1; | ||||
| 
 | ||||
| 	for(int i = 0; i < count; i++) | ||||
| 	{ | ||||
| 		QString displayedName(QString("SDRdaemon[%1]").arg(i)); | ||||
| 
 | ||||
| 		result.append(SampleSourceDevice(displayedName, | ||||
| 				m_deviceTypeID, | ||||
| 				QString::null, | ||||
| 				i)); | ||||
| 	} | ||||
| 
 | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| PluginGUI* SDRdaemonPlugin::createSampleSourcePluginGUI(const QString& sourceId) | ||||
| { | ||||
| 	if(sourceId == m_deviceTypeID) | ||||
| 	{ | ||||
| 		SDRdaemonGui* gui = new SDRdaemonGui(m_pluginAPI); | ||||
| 		m_pluginAPI->setInputGUI(gui); | ||||
| 		return gui; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		return NULL; | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										47
									
								
								plugins/samplesource/sdrdaemon/sdrdaemonplugin.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								plugins/samplesource/sdrdaemon/sdrdaemonplugin.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.          //
 | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| #ifndef INCLUDE_SDRDAEMONPLUGIN_H | ||||
| #define INCLUDE_SDRDAEMONPLUGIN_H | ||||
| 
 | ||||
| #include <QObject> | ||||
| #include "plugin/plugininterface.h" | ||||
| 
 | ||||
| #define SDRDAEMON_DEVICE_TYPE_ID "sdrangel.samplesource.sdrdaemon" | ||||
| 
 | ||||
| class SDRdaemonPlugin : public QObject, public PluginInterface { | ||||
| 	Q_OBJECT | ||||
| 	Q_INTERFACES(PluginInterface) | ||||
| 	Q_PLUGIN_METADATA(IID SDRDAEMON_DEVICE_TYPE_ID) | ||||
| 
 | ||||
| public: | ||||
| 	explicit SDRdaemonPlugin(QObject* parent = NULL); | ||||
| 
 | ||||
| 	const PluginDescriptor& getPluginDescriptor() const; | ||||
| 	void initPlugin(PluginAPI* pluginAPI); | ||||
| 
 | ||||
| 	virtual SampleSourceDevices enumSampleSources(); | ||||
| 	virtual PluginGUI* createSampleSourcePluginGUI(const QString& sourceId); | ||||
| 
 | ||||
| 	static const QString m_deviceTypeID; | ||||
| 
 | ||||
| private: | ||||
| 	static const PluginDescriptor m_pluginDescriptor; | ||||
| 
 | ||||
| 	PluginAPI* m_pluginAPI; | ||||
| }; | ||||
| 
 | ||||
| #endif // INCLUDE_SDRDAEMONPLUGIN_H
 | ||||
							
								
								
									
										153
									
								
								plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								plugins/samplesource/sdrdaemon/sdrdaemonthread.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,153 @@ | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Copyright (C) 2015 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 <http://www.gnu.org/licenses/>.          //
 | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <errno.h> | ||||
| #include <assert.h> | ||||
| #include "dsp/samplefifo.h" | ||||
| #include <QDebug> | ||||
| 
 | ||||
| #include "sdrdaemonthread.h" | ||||
| 
 | ||||
| const int SDRdaemonThread::m_rateDivider = 1000/SDRDAEMON_THROTTLE_MS; | ||||
| 
 | ||||
| SDRdaemonThread::SDRdaemonThread(std::ifstream *samplesStream, SampleFifo* sampleFifo, QObject* parent) : | ||||
| 	QThread(parent), | ||||
| 	m_running(false), | ||||
| 	m_ifstream(samplesStream), | ||||
| 	m_buf(0), | ||||
| 	m_bufsize(0), | ||||
| 	m_chunksize(0), | ||||
| 	m_sampleFifo(sampleFifo), | ||||
| 	m_samplesCount(0), | ||||
| 	m_samplerate(0) | ||||
| { | ||||
|     assert(m_ifstream != 0); | ||||
| } | ||||
| 
 | ||||
| SDRdaemonThread::~SDRdaemonThread() | ||||
| { | ||||
| 	if (m_running) { | ||||
| 		stopWork(); | ||||
| 	} | ||||
| 
 | ||||
| 	if (m_buf != 0) { | ||||
| 		free(m_buf); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonThread::startWork() | ||||
| { | ||||
| 	qDebug() << "SDRdaemonThread::startWork: "; | ||||
|      | ||||
|     if (m_ifstream->is_open()) | ||||
|     { | ||||
|         qDebug() << "  - file stream open, starting..."; | ||||
|         m_startWaitMutex.lock(); | ||||
|         start(); | ||||
|         while(!m_running) | ||||
|             m_startWaiter.wait(&m_startWaitMutex, 100); | ||||
|         m_startWaitMutex.unlock(); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         qDebug() << "  - file stream closed, not starting."; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonThread::stopWork() | ||||
| { | ||||
| 	qDebug() << "SDRdaemonThread::stopWork"; | ||||
| 	m_running = false; | ||||
| 	wait(); | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonThread::setSamplerate(int samplerate) | ||||
| { | ||||
| 	qDebug() << "SDRdaemonThread::setSamplerate:" | ||||
| 			<< " new:" << samplerate | ||||
| 			<< " old:" << m_samplerate; | ||||
| 
 | ||||
| 	if (samplerate != m_samplerate) | ||||
| 	{ | ||||
| 		if (m_running) { | ||||
| 			stopWork(); | ||||
| 		} | ||||
| 
 | ||||
| 		m_samplerate = samplerate; | ||||
| 		m_chunksize = (m_samplerate / m_rateDivider)*4; // TODO: implement FF and slow motion here. 4 corresponds to live. 2 is half speed, 8 is doulbe speed
 | ||||
| 		m_bufsize = m_chunksize; | ||||
| 
 | ||||
| 		if (m_buf == 0)	{ | ||||
| 			qDebug() << "  - Allocate buffer"; | ||||
| 			m_buf = (quint8*) malloc(m_bufsize); | ||||
| 		} else { | ||||
| 			qDebug() << "  - Re-allocate buffer"; | ||||
| 			m_buf = (quint8*) realloc((void*) m_buf, m_bufsize); | ||||
| 		} | ||||
| 
 | ||||
| 		qDebug() << "  - size: " << m_bufsize | ||||
| 				<< " #samples: " << (m_bufsize/4); | ||||
| 	} | ||||
| 
 | ||||
| 	//m_samplerate = samplerate;
 | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonThread::run() | ||||
| { | ||||
| 	int res; | ||||
| 
 | ||||
| 	m_running = true; | ||||
| 	m_startWaiter.wakeAll(); | ||||
| 
 | ||||
| 	while(m_running) // actual work is in the tick() function
 | ||||
| 	{ | ||||
| 		sleep(1); | ||||
| 	} | ||||
| 
 | ||||
| 	m_running = false; | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonThread::connectTimer(const QTimer& timer) | ||||
| { | ||||
| 	qDebug() << "SDRdaemonThread::connectTimer"; | ||||
| 	connect(&timer, SIGNAL(timeout()), this, SLOT(tick())); | ||||
| } | ||||
| 
 | ||||
| void SDRdaemonThread::tick() | ||||
| { | ||||
| 	if (m_running) | ||||
| 	{ | ||||
| 		// read samples directly feeding the SampleFifo (no callback)
 | ||||
| 		m_ifstream->read(reinterpret_cast<char*>(m_buf), m_chunksize); | ||||
|          | ||||
|         if (m_ifstream->eof()) | ||||
|         { | ||||
|             m_sampleFifo->write(m_buf, m_ifstream->gcount()); | ||||
|             // TODO: handle loop playback situation
 | ||||
|     		m_ifstream->clear(); | ||||
|     		m_ifstream->seekg(0, std::ios::beg); | ||||
|     		m_samplesCount = 0; | ||||
|             //stopWork();
 | ||||
|             //m_ifstream->close();
 | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             m_sampleFifo->write(m_buf, m_chunksize); | ||||
|     		m_samplesCount += m_chunksize / 4; | ||||
|         } | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										67
									
								
								plugins/samplesource/sdrdaemon/sdrdaemonthread.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								plugins/samplesource/sdrdaemon/sdrdaemonthread.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,67 @@ | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.          //
 | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| #ifndef INCLUDE_SDRDAEMONTHREAD_H | ||||
| #define INCLUDE_SDRDAEMONTHREAD_H | ||||
| 
 | ||||
| #include <QThread> | ||||
| #include <QMutex> | ||||
| #include <QWaitCondition> | ||||
| #include <QTimer> | ||||
| #include <iostream> | ||||
| #include <fstream> | ||||
| #include <cstdlib> | ||||
| #include "dsp/samplefifo.h" | ||||
| #include "dsp/inthalfbandfilter.h" | ||||
| 
 | ||||
| #define SDRDAEMON_THROTTLE_MS 50 | ||||
| 
 | ||||
| class SDRdaemonThread : public QThread { | ||||
| 	Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
| 	SDRdaemonThread(std::ifstream *samplesStream, SampleFifo* sampleFifo, QObject* parent = NULL); | ||||
| 	~SDRdaemonThread(); | ||||
| 
 | ||||
| 	void startWork(); | ||||
| 	void stopWork(); | ||||
| 	void setSamplerate(int samplerate); | ||||
| 	bool isRunning() const { return m_running; } | ||||
| 	std::size_t getSamplesCount() const { return m_samplesCount; } | ||||
| 
 | ||||
| 	void connectTimer(const QTimer& timer); | ||||
| 
 | ||||
| private: | ||||
| 	QMutex m_startWaitMutex; | ||||
| 	QWaitCondition m_startWaiter; | ||||
| 	bool m_running; | ||||
| 
 | ||||
| 	std::ifstream* m_ifstream; | ||||
| 	quint8  *m_buf; | ||||
| 	std::size_t m_bufsize; | ||||
| 	std::size_t m_chunksize; | ||||
| 	SampleFifo* m_sampleFifo; | ||||
| 	std::size_t m_samplesCount; | ||||
| 
 | ||||
| 	int m_samplerate; | ||||
| 	static const int m_rateDivider; | ||||
| 
 | ||||
| 	void run(); | ||||
| private slots: | ||||
| 	void tick(); | ||||
| }; | ||||
| 
 | ||||
| #endif // INCLUDE_SDRDAEMONTHREAD_H
 | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user