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
+
+ 1
+
+
+ ButtonSwitch
+ QToolButton
+
+
+
+
+
+
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