From f9029e8572fd9a9c18930e7e9ea92367e914f729 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 3 Aug 2015 01:04:20 +0200 Subject: [PATCH] Implemented a minimalist file source plugin (recording reader) compilable but untested --- Readme.md | 1 + plugins/samplesource/CMakeLists.txt | 1 + .../samplesource/filesource/CMakeLists.txt | 50 ++++ .../samplesource/filesource/filesourcegui.cpp | 136 +++++++++ .../samplesource/filesource/filesourcegui.h | 69 +++++ .../samplesource/filesource/filesourcegui.ui | 269 ++++++++++++++++++ .../filesource/filesourceinput.cpp | 196 +++++++++++++ .../samplesource/filesource/filesourceinput.h | 108 +++++++ .../filesource/filesourceplugin.cpp | 77 +++++ .../filesource/filesourceplugin.h | 43 +++ .../filesource/filesourcethread.cpp | 137 +++++++++ .../filesource/filesourcethread.h | 66 +++++ 12 files changed, 1153 insertions(+) create mode 100644 plugins/samplesource/filesource/CMakeLists.txt create mode 100644 plugins/samplesource/filesource/filesourcegui.cpp create mode 100644 plugins/samplesource/filesource/filesourcegui.h create mode 100644 plugins/samplesource/filesource/filesourcegui.ui create mode 100644 plugins/samplesource/filesource/filesourceinput.cpp create mode 100644 plugins/samplesource/filesource/filesourceinput.h create mode 100644 plugins/samplesource/filesource/filesourceplugin.cpp create mode 100644 plugins/samplesource/filesource/filesourceplugin.h create mode 100644 plugins/samplesource/filesource/filesourcethread.cpp create mode 100644 plugins/samplesource/filesource/filesourcethread.h diff --git a/Readme.md b/Readme.md index 108db09ad..c35ade14d 100644 --- a/Readme.md +++ b/Readme.md @@ -128,6 +128,7 @@ Done since the fork - Trigger line display for all trigger modes - Coarse and fine trigger level sliders - Minimalist recording + - Minimalist file source (recording reader) compilable but untested ===== To Do diff --git a/plugins/samplesource/CMakeLists.txt b/plugins/samplesource/CMakeLists.txt index 6c9de667d..145ca65f1 100644 --- a/plugins/samplesource/CMakeLists.txt +++ b/plugins/samplesource/CMakeLists.txt @@ -31,3 +31,4 @@ if(LIBUSB_FOUND AND LIBBLADERF_FOUND) add_subdirectory(bladerf) endif(LIBUSB_FOUND AND LIBBLADERF_FOUND) +add_subdirectory(filesource) diff --git a/plugins/samplesource/filesource/CMakeLists.txt b/plugins/samplesource/filesource/CMakeLists.txt new file mode 100644 index 000000000..5f3ab75a7 --- /dev/null +++ b/plugins/samplesource/filesource/CMakeLists.txt @@ -0,0 +1,50 @@ +project(filesource) + +set(filesource_SOURCES + filesourcegui.cpp + filesourceinput.cpp + filesourceplugin.cpp + filesourcethread.cpp +) + +set(filesource_HEADERS + filesourcegui.h + filesourceinput.h + filesourceplugin.h + filesourcethread.h +) + +set(filesource_FORMS + filesourcegui.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(filesource_HEADERS_MOC ${filesource_HEADERS}) +qt5_wrap_ui(filesource_FORMS_HEADERS ${filesource_FORMS}) + +add_library(inputfilesource SHARED + ${filesource_SOURCES} + ${filesource_HEADERS_MOC} + ${filesource_FORMS_HEADERS} +) + +target_link_libraries(inputfilesource + ${QT_LIBRARIES} + ${LIBBLADERF_LIBRARIES} + ${LIBUSB_LIBRARIES} + sdrbase +) + +qt5_use_modules(inputfilesource Core Widgets OpenGL Multimedia) diff --git a/plugins/samplesource/filesource/filesourcegui.cpp b/plugins/samplesource/filesource/filesourcegui.cpp new file mode 100644 index 000000000..ca22e6b0d --- /dev/null +++ b/plugins/samplesource/filesource/filesourcegui.cpp @@ -0,0 +1,136 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#include "ui_filesourcegui.h" +#include "plugin/pluginapi.h" +#include "gui/colormapper.h" +#include "mainwindow.h" + +#include "filesourcegui.h" + +FileSourceGui::FileSourceGui(PluginAPI* pluginAPI, QWidget* parent) : + QWidget(parent), + ui(new Ui::FileSourceGui), + m_pluginAPI(pluginAPI), + m_settings(), + m_sampleSource(NULL) +{ + ui->setupUi(this); + ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::ReverseGold)); + ui->centerFrequency->setValueRange(7, 0, pow(10,7)); + connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware())); + displaySettings(); + + m_sampleSource = new FileSourceInput(m_pluginAPI->getMainWindowMessageQueue(), m_pluginAPI->getMainWindow()->getMasterTimer()); + m_pluginAPI->setSampleSource(m_sampleSource); +} + +FileSourceGui::~FileSourceGui() +{ + delete ui; +} + +void FileSourceGui::destroy() +{ + delete this; +} + +void FileSourceGui::setName(const QString& name) +{ + setObjectName(name); +} + +QString FileSourceGui::getName() const +{ + return objectName(); +} + +void FileSourceGui::resetToDefaults() +{ + m_generalSettings.resetToDefaults(); + m_settings.resetToDefaults(); + displaySettings(); + sendSettings(); +} + +QByteArray FileSourceGui::serializeGeneral() const +{ + return m_generalSettings.serialize(); +} + +bool FileSourceGui::deserializeGeneral(const QByteArray&data) +{ + if(m_generalSettings.deserialize(data)) { + displaySettings(); + sendSettings(); + return true; + } else { + resetToDefaults(); + return false; + } +} + +qint64 FileSourceGui::getCenterFrequency() const +{ + return m_generalSettings.m_centerFrequency; +} + +QByteArray FileSourceGui::serialize() const +{ + return m_settings.serialize(); +} + +bool FileSourceGui::deserialize(const QByteArray& data) +{ + if(m_settings.deserialize(data)) { + displaySettings(); + sendSettings(); + return true; + } else { + resetToDefaults(); + return false; + } +} + +bool FileSourceGui::handleMessage(Message* message) +{ + if(FileSourceInput::MsgReportFileSource::match(message)) { + displaySettings(); + message->completed(); + return true; + } else { + return false; + } +} + +void FileSourceGui::displaySettings() +{ +} + +void FileSourceGui::sendSettings() +{ + if(!m_updateTimer.isActive()) + m_updateTimer.start(100); +} + +void FileSourceGui::updateHardware() +{ + FileSourceInput::MsgConfigureFileSource* message = FileSourceInput::MsgConfigureFileSource::create(m_generalSettings, m_settings); + message->submit(m_pluginAPI->getDSPEngineMessageQueue()); + m_updateTimer.stop(); +} diff --git a/plugins/samplesource/filesource/filesourcegui.h b/plugins/samplesource/filesource/filesourcegui.h new file mode 100644 index 000000000..630b67b68 --- /dev/null +++ b/plugins/samplesource/filesource/filesourcegui.h @@ -0,0 +1,69 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_FILESOURCEGUI_H +#define INCLUDE_FILESOURCEGUI_H + +#include +#include "plugin/plugingui.h" + +#include "filesourceinput.h" + +class PluginAPI; + +namespace Ui { + class FileSourceGui; +} + +class FileSourceGui : public QWidget, public PluginGUI { + Q_OBJECT + +public: + explicit FileSourceGui(PluginAPI* pluginAPI, QWidget* parent = NULL); + ~FileSourceGui(); + void destroy(); + + void setName(const QString& name); + QString getName() const; + + void resetToDefaults(); + QByteArray serializeGeneral() const; + bool deserializeGeneral(const QByteArray&data); + qint64 getCenterFrequency() const; + QByteArray serialize() const; + bool deserialize(const QByteArray& data); + bool handleMessage(Message* message); + +private: + Ui::FileSourceGui* ui; + + PluginAPI* m_pluginAPI; + SampleSource::GeneralSettings m_generalSettings; + FileSourceInput::Settings m_settings; + QTimer m_updateTimer; + std::vector m_gains; + SampleSource* m_sampleSource; + + void displaySettings(); + void sendSettings(); + void updateHardware(); + +private slots: + void on_playLoop_toggled(bool checked); + void on_play_toggled(bool checked); +}; + +#endif // INCLUDE_FILESOURCEGUI_H diff --git a/plugins/samplesource/filesource/filesourcegui.ui b/plugins/samplesource/filesource/filesourcegui.ui new file mode 100644 index 000000000..e3b1c512e --- /dev/null +++ b/plugins/samplesource/filesource/filesourcegui.ui @@ -0,0 +1,269 @@ + + + FileSourceGui + + + + 0 + 0 + 198 + 88 + + + + + 0 + 0 + + + + BladeRF + + + + 3 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + false + + + + 0 + 0 + + + + + 32 + 16 + + + + + Monospace + 20 + + + + SizeVerCursor + + + Qt::StrongFocus + + + Tuner center frequency in kHz + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + + Qt::Horizontal + + + + + + + + + + 8 + + + + Rate + + + 0k + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + + + + + false + + + + 8 + + + + 20150101 00:00:00.000 + + + + + + + + + Qt::Horizontal + + + + + + + + + + + + + :/playloop.png:/playloop.png + + + + 16 + 16 + + + + true + + + + + + + + + + + :/play.png:/play.png + + + + 16 + 16 + + + + true + + + false + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + + + + + false + + + + 8 + + + + 00:00:00.000 + + + + + + + + + + ValueDial + QWidget +
gui/valuedial.h
+ 1 +
+ + ButtonSwitch + QToolButton +
gui/buttonswitch.h
+
+
+ + +
diff --git a/plugins/samplesource/filesource/filesourceinput.cpp b/plugins/samplesource/filesource/filesourceinput.cpp new file mode 100644 index 000000000..674eefe66 --- /dev/null +++ b/plugins/samplesource/filesource/filesourceinput.cpp @@ -0,0 +1,196 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#include "util/simpleserializer.h" +#include "dsp/filesink.h" + +#include "filesourcegui.h" +#include "filesourceinput.h" +#include "filesourcethread.h" + +MESSAGE_CLASS_DEFINITION(FileSourceInput::MsgConfigureFileSource, Message) +MESSAGE_CLASS_DEFINITION(FileSourceInput::MsgReportFileSource, Message) + +FileSourceInput::Settings::Settings() : + m_fileName("./test.sdriq") +{ +} + +void FileSourceInput::Settings::resetToDefaults() +{ + m_fileName = "./test.sdriq"; +} + +QByteArray FileSourceInput::Settings::serialize() const +{ + SimpleSerializer s(1); + s.writeString(1, m_fileName); + return s.final(); +} + +bool FileSourceInput::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; + } +} + +FileSourceInput::FileSourceInput(MessageQueue* msgQueueToGUI, const QTimer& masterTimer) : + SampleSource(msgQueueToGUI), + m_settings(), + m_fileSourceThread(NULL), + m_deviceDescription(), + m_sampleRate(0), + m_centerFrequency(0), + m_startingTimeStamp(0), + m_masterTimer(masterTimer) +{ +} + +FileSourceInput::~FileSourceInput() +{ + stopInput(); +} + +void FileSourceInput::openFileStream() +{ + m_ifstream.open(m_settings.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; +} + +bool FileSourceInput::startInput(int device) +{ + QMutexLocker mutexLocker(&m_mutex); + + openFileStream(); + + if((m_fileSourceThread = new FileSourceThread(&m_ifstream, &m_sampleFifo)) == NULL) { + qFatal("out of memory"); + goto failed; + } + + m_fileSourceThread->setSamplerate(m_sampleRate); + m_fileSourceThread->connectTimer(m_masterTimer); + m_fileSourceThread->startWork(); + + mutexLocker.unlock(); + applySettings(m_generalSettings, m_settings, true); + + qDebug("bladerfInput: start"); + //MsgReportBladerf::create(m_gains)->submit(m_guiMessageQueue); Pass anything here + + return true; + +failed: + stopInput(); + return false; +} + +void FileSourceInput::stopInput() +{ + QMutexLocker mutexLocker(&m_mutex); + + if(m_fileSourceThread != NULL) { + m_fileSourceThread->stopWork(); + delete m_fileSourceThread; + m_fileSourceThread = NULL; + } + + m_deviceDescription.clear(); +} + +const QString& FileSourceInput::getDeviceDescription() const +{ + return m_deviceDescription; +} + +int FileSourceInput::getSampleRate() const +{ + return m_sampleRate; +} + +quint64 FileSourceInput::getCenterFrequency() const +{ + return m_centerFrequency; +} + +std::time_t FileSourceInput::getStartingTimeStamp() const +{ + return m_startingTimeStamp; +} + +bool FileSourceInput::handleMessage(Message* message) +{ + if(MsgConfigureFileSource::match(message)) { + MsgConfigureFileSource* conf = (MsgConfigureFileSource*)message; + if(!applySettings(conf->getGeneralSettings(), conf->getSettings(), false)) + qDebug("File Source config error"); + message->completed(); + return true; + } else { + return false; + } +} + +bool FileSourceInput::applySettings(const GeneralSettings& generalSettings, const Settings& settings, bool force) +{ + QMutexLocker mutexLocker(&m_mutex); + + if((m_settings.m_fileName != settings.m_fileName) || force) { + m_settings.m_fileName = settings.m_fileName; + + if (m_fileSourceThread != 0) { + m_fileSourceThread->stopWork(); + } + + if (m_ifstream.is_open()) { + m_ifstream.close(); + } + + openFileStream(); + + if (m_fileSourceThread != 0) { + m_fileSourceThread->setSamplerate(m_sampleRate); + } + + std::cerr << "FileSourceInput: center freq: " << m_generalSettings.m_centerFrequency << " Hz" + << " file name: " << settings.m_fileName.toStdString() << std::endl; + } + + return true; +} diff --git a/plugins/samplesource/filesource/filesourceinput.h b/plugins/samplesource/filesource/filesourceinput.h new file mode 100644 index 000000000..2f16f462a --- /dev/null +++ b/plugins/samplesource/filesource/filesourceinput.h @@ -0,0 +1,108 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_FILESOURCEINPUT_H +#define INCLUDE_FILESOURCEINPUT_H + +#include "dsp/samplesource/samplesource.h" +#include +#include +#include +#include +#include + +class FileSourceThread; + +class FileSourceInput : public SampleSource { +public: + struct Settings { + QString m_fileName; + + Settings(); + void resetToDefaults(); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); + }; + + class MsgConfigureFileSource : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const GeneralSettings& getGeneralSettings() const { return m_generalSettings; } + const Settings& getSettings() const { return m_settings; } + + static MsgConfigureFileSource* create(const GeneralSettings& generalSettings, const Settings& settings) + { + return new MsgConfigureFileSource(generalSettings, settings); + } + + private: + GeneralSettings m_generalSettings; + Settings m_settings; + + MsgConfigureFileSource(const GeneralSettings& generalSettings, const Settings& settings) : + Message(), + m_generalSettings(generalSettings), + m_settings(settings) + { } + }; + + class MsgReportFileSource : public Message { + MESSAGE_CLASS_DECLARATION + + public: + + static MsgReportFileSource* create() + { + return new MsgReportFileSource(); + } + + protected: + + MsgReportFileSource() : + Message() + { } + }; + + FileSourceInput(MessageQueue* msgQueueToGUI, const QTimer& masterTimer); + ~FileSourceInput(); + + bool startInput(int device); + void stopInput(); + + const QString& getDeviceDescription() const; + int getSampleRate() const; + quint64 getCenterFrequency() const; + std::time_t getStartingTimeStamp() const; + + bool handleMessage(Message* message); + +private: + QMutex m_mutex; + Settings m_settings; + std::ifstream m_ifstream; + FileSourceThread* m_fileSourceThread; + QString m_deviceDescription; + int m_sampleRate; + quint64 m_centerFrequency; + std::time_t m_startingTimeStamp; + const QTimer& m_masterTimer; + + bool applySettings(const GeneralSettings& generalSettings, const Settings& settings, bool force); + void openFileStream(); +}; + +#endif // INCLUDE_FILESOURCEINPUT_H diff --git a/plugins/samplesource/filesource/filesourceplugin.cpp b/plugins/samplesource/filesource/filesourceplugin.cpp new file mode 100644 index 000000000..1e95f018a --- /dev/null +++ b/plugins/samplesource/filesource/filesourceplugin.cpp @@ -0,0 +1,77 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "plugin/pluginapi.h" +#include "util/simpleserializer.h" + +#include "filesourcegui.h" +#include "filesourceplugin.h" + +const PluginDescriptor FileSourcePlugin::m_pluginDescriptor = { + QString("File source input"), + QString("1.0"), + QString("(c) Edouard Griffiths, F4EXB"), + QString("https://github.com/f4exb/rtl-sdrangelove/tree/f4exb"), + true, + QString("https://github.com/f4exb/rtl-sdrangelove/tree/f4exb") +}; + +FileSourcePlugin::FileSourcePlugin(QObject* parent) : + QObject(parent) +{ +} + +const PluginDescriptor& FileSourcePlugin::getPluginDescriptor() const +{ + return m_pluginDescriptor; +} + +void FileSourcePlugin::initPlugin(PluginAPI* pluginAPI) +{ + m_pluginAPI = pluginAPI; + m_pluginAPI->registerSampleSource("org.osmocom.sdr.samplesource.filesource", this); +} + +PluginInterface::SampleSourceDevices FileSourcePlugin::enumSampleSources() +{ + SampleSourceDevices result; + int count = 1; + + for(int i = 0; i < count; i++) + { + QString displayedName(QString("FileSource #%1 choose file").arg(i)); + SimpleSerializer s(1); + s.writeS32(1, i); + s.writeString(2, ""); + result.append(SampleSourceDevice(displayedName, "org.osmocom.sdr.samplesource.filesource", s.final())); + } + + return result; +} + +PluginGUI* FileSourcePlugin::createSampleSource(const QString& sourceName, const QByteArray& address) +{ + if(sourceName == "org.osmocom.sdr.samplesource.filesource") { + FileSourceGui* gui = new FileSourceGui(m_pluginAPI); + m_pluginAPI->setInputGUI(gui); + return gui; + } else { + return NULL; + } +} diff --git a/plugins/samplesource/filesource/filesourceplugin.h b/plugins/samplesource/filesource/filesourceplugin.h new file mode 100644 index 000000000..a08be1cf1 --- /dev/null +++ b/plugins/samplesource/filesource/filesourceplugin.h @@ -0,0 +1,43 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_FILESOURCEPLUGIN_H +#define INCLUDE_FILESOURCEPLUGIN_H + +#include +#include "plugin/plugininterface.h" + +class FileSourcePlugin : public QObject, PluginInterface { + Q_OBJECT + Q_INTERFACES(PluginInterface) + Q_PLUGIN_METADATA(IID "org.osmocom.sdr.samplesource.filesource") + +public: + explicit FileSourcePlugin(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_FILESOURCEPLUGIN_H diff --git a/plugins/samplesource/filesource/filesourcethread.cpp b/plugins/samplesource/filesource/filesourcethread.cpp new file mode 100644 index 000000000..82d7f192c --- /dev/null +++ b/plugins/samplesource/filesource/filesourcethread.cpp @@ -0,0 +1,137 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "dsp/samplefifo.h" + +#include "filesourcethread.h" + +const int FileSourceThread::m_rateDivider = 1000/FILESOURCE_THROTTLE_MS; + +FileSourceThread::FileSourceThread(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_samplerate(0) +{ +} + +FileSourceThread::~FileSourceThread() +{ + if (m_running) { + stopWork(); + } + + if (m_buf != 0) { + free(m_buf); + } +} + +void FileSourceThread::startWork() +{ + m_startWaitMutex.lock(); + start(); + while(!m_running) + m_startWaiter.wait(&m_startWaitMutex, 100); + m_startWaitMutex.unlock(); +} + +void FileSourceThread::stopWork() +{ + m_running = false; + wait(); +} + +void FileSourceThread::setSamplerate(int samplerate) +{ + if (samplerate != m_samplerate) + { + if (m_running) { + stopWork(); + } + + m_bufsize = (m_samplerate / m_rateDivider)*4; + + if (m_buf == 0) { + m_buf = (quint8*) malloc(m_bufsize); + } else { + m_buf = (quint8*) realloc((void*) m_buf, m_bufsize); + } + } + + m_samplerate = samplerate; + m_chunksize = (m_samplerate / m_rateDivider)*4; +} + +void FileSourceThread::run() +{ + int res; + + m_running = true; + m_startWaiter.wakeAll(); + + while(m_running) + { + sleep(1); + } + + m_running = false; +} + +void FileSourceThread::connectTimer(const QTimer& timer) +{ + std::cerr << "FileSourceThread::connectTimer" << std::endl; + connect(&timer, SIGNAL(timeout()), this, SLOT(tick())); +} + +void FileSourceThread::tick() +{ + if (m_running) + { + // read samples directly feeding the SampleFifo (no callback) + m_ifstream->read(reinterpret_cast(m_buf), m_chunksize); + m_sampleFifo->write(m_buf, m_chunksize); + } +} + + +/* +void FileSourceThread::decimate1(SampleVector::iterator* it, const qint16* buf, qint32 len) +{ + qint16 xreal, yimag; + + for (int pos = 0; pos < len; pos += 2) { + xreal = buf[pos+0]; + yimag = buf[pos+1]; + Sample s( xreal * 16, yimag * 16 ); // shift by 4 bit positions (signed) + **it = s; + (*it)++; + } +} + +// Decimate according to specified log2 (ex: log2=4 => decim=16) +void FileSourceThread::callback(const qint16* buf, qint32 len) +{ + SampleVector::iterator it = m_convertBuffer.begin(); + decimate1(&it, buf, len); + m_sampleFifo->write(m_convertBuffer.begin(), it); +} +*/ diff --git a/plugins/samplesource/filesource/filesourcethread.h b/plugins/samplesource/filesource/filesourcethread.h new file mode 100644 index 000000000..791dddc28 --- /dev/null +++ b/plugins/samplesource/filesource/filesourcethread.h @@ -0,0 +1,66 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_FILESOURCETHREAD_H +#define INCLUDE_FILESOURCETHREAD_H + +#include +#include +#include +#include +#include +#include +#include +#include "dsp/samplefifo.h" +#include "dsp/inthalfbandfilter.h" + +#define FILESOURCE_THROTTLE_MS 50 + +class FileSourceThread : public QThread { + Q_OBJECT + +public: + FileSourceThread(std::ifstream *samplesStream, SampleFifo* sampleFifo, QObject* parent = NULL); + ~FileSourceThread(); + + void startWork(); + void stopWork(); + void setSamplerate(int samplerate); + + 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; + + int m_samplerate; + static const int m_rateDivider; + + void run(); + //void decimate1(SampleVector::iterator* it, const qint16* buf, qint32 len); + //void callback(const qint16* buf, qint32 len); +private slots: + void tick(); +}; + +#endif // INCLUDE_FILESOURCETHREAD_H