diff --git a/plugins/samplesink/filesink/CMakeLists.txt b/plugins/samplesink/filesink/CMakeLists.txt index f3562a0ac..90de6150e 100644 --- a/plugins/samplesink/filesink/CMakeLists.txt +++ b/plugins/samplesink/filesink/CMakeLists.txt @@ -4,6 +4,7 @@ set(filesink_SOURCES filesinkgui.cpp filesinkoutput.cpp filesinkplugin.cpp + filesinksettings.cpp filesinkthread.cpp ) @@ -11,6 +12,7 @@ set(filesink_HEADERS filesinkgui.h filesinkoutput.h filesinkplugin.h + filesinksettings.h filesinkthread.h ) diff --git a/plugins/samplesink/filesink/filesink.pro b/plugins/samplesink/filesink/filesink.pro index 4a26dd8e3..5239b40d1 100644 --- a/plugins/samplesink/filesink/filesink.pro +++ b/plugins/samplesink/filesink/filesink.pro @@ -19,11 +19,13 @@ CONFIG(Debug):build_subdir = debug SOURCES += filesinkgui.cpp\ filesinkoutput.cpp\ filesinkplugin.cpp\ + filesinksettings.cpp\ filesinkthread.cpp HEADERS += filesinkgui.h\ filesinkoutput.h\ filesinkplugin.h\ + filesinksettings.h\ filesinkthread.h FORMS += filesinkgui.ui diff --git a/plugins/samplesink/filesink/filesinkgui.cpp b/plugins/samplesink/filesink/filesinkgui.cpp index 6a0fa5966..c70851bdd 100644 --- a/plugins/samplesink/filesink/filesinkgui.cpp +++ b/plugins/samplesink/filesink/filesinkgui.cpp @@ -39,11 +39,9 @@ FileSinkGui::FileSinkGui(DeviceSinkAPI *deviceAPI, QWidget* parent) : ui(new Ui::FileSinkGui), m_deviceAPI(deviceAPI), m_settings(), - m_sampleSink(NULL), + m_deviceSampleSink(0), m_generation(false), - m_fileName("..."), - m_sampleRate(0), - m_centerFrequency(0), + m_fileName("./test.sdriq"), m_startingTimeStamp(0), m_samplesCount(0), m_tickCount(0), @@ -66,9 +64,9 @@ FileSinkGui::FileSinkGui(DeviceSinkAPI *deviceAPI, QWidget* parent) : displaySettings(); - m_sampleSink = new FileSinkOutput(m_deviceAPI->getMainWindow()->getMasterTimer()); - connect(m_sampleSink->getOutputMessageQueueToGUI(), SIGNAL(messageEnqueued()), this, SLOT(handleSinkMessages())); - m_deviceAPI->setSink(m_sampleSink); + m_deviceSampleSink = new FileSinkOutput(m_deviceAPI->getMainWindow()->getMasterTimer()); + connect(m_deviceSampleSink->getOutputMessageQueueToGUI(), SIGNAL(messageEnqueued()), this, SLOT(handleSinkMessages())); + m_deviceAPI->setSink(m_deviceSampleSink); connect(m_deviceAPI->getDeviceOutputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleDSPMessages()), Qt::QueuedConnection); } @@ -102,12 +100,12 @@ void FileSinkGui::resetToDefaults() qint64 FileSinkGui::getCenterFrequency() const { - return m_centerFrequency; + return m_settings.m_centerFrequency; } void FileSinkGui::setCenterFrequency(qint64 centerFrequency) { - m_centerFrequency = centerFrequency; + m_settings.m_centerFrequency = centerFrequency; displaySettings(); sendSettings(); } @@ -129,27 +127,6 @@ bool FileSinkGui::deserialize(const QByteArray& data) } } -void FileSinkGui::handleDSPMessages() -{ - Message* message; - - while ((message = m_deviceAPI->getDeviceOutputMessageQueue()->pop()) != 0) - { - qDebug("FileSinkGui::handleDSPMessages: message: %s", message->getIdentifier()); - - if (DSPSignalNotification::match(*message)) - { - DSPSignalNotification* notif = (DSPSignalNotification*) message; - m_deviceSampleRate = notif->getSampleRate(); - m_deviceCenterFrequency = notif->getCenterFrequency(); - qDebug("FileSinkGui::handleDSPMessages: SampleRate:%d, CenterFrequency:%llu", notif->getSampleRate(), notif->getCenterFrequency()); - updateSampleRateAndFrequency(); - - delete message; - } - } -} - bool FileSinkGui::handleMessage(const Message& message) { if (FileSinkOutput::MsgReportFileSinkGeneration::match(message)) @@ -158,14 +135,6 @@ bool FileSinkGui::handleMessage(const Message& message) updateWithGeneration(); return true; } - else if (FileSinkOutput::MsgReportFileSinkStreamData::match(message)) - { - m_sampleRate = ((FileSinkOutput::MsgReportFileSinkStreamData&)message).getSampleRate(); - m_centerFrequency = ((FileSinkOutput::MsgReportFileSinkStreamData&)message).getCenterFrequency(); - m_startingTimeStamp = ((FileSinkOutput::MsgReportFileSinkStreamData&)message).getStartingTimeStamp(); - updateWithStreamData(); - return true; - } else if (FileSinkOutput::MsgReportFileSinkStreamTiming::match(message)) { m_samplesCount = ((FileSinkOutput::MsgReportFileSinkStreamTiming&)message).getSamplesCount(); @@ -182,7 +151,7 @@ void FileSinkGui::handleSinkMessages() { Message* message; - while ((message = m_sampleSink->getOutputMessageQueueToGUI()->pop()) != 0) + while ((message = m_deviceSampleSink->getOutputMessageQueueToGUI()->pop()) != 0) { //qDebug("FileSourceGui::handleSourceMessages: message: %s", message->getIdentifier()); @@ -193,36 +162,17 @@ void FileSinkGui::handleSinkMessages() } } -void FileSinkGui::updateSampleRateAndFrequency() -{ - m_deviceAPI->getSpectrum()->setSampleRate(m_deviceSampleRate); - m_deviceAPI->getSpectrum()->setCenterFrequency(m_deviceCenterFrequency); - ui->deviceRateText->setText(tr("%1k").arg((float)m_deviceSampleRate / 1000)); -} - void FileSinkGui::displaySettings() { + ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000); + unsigned int sampleRateIndex = FileSinkSampleRates::getRateIndex(m_settings.m_sampleRate); + ui->samplerate->setCurrentIndex(sampleRateIndex); } void FileSinkGui::sendSettings() { -} - -void FileSinkGui::on_startStop_toggled(bool checked) -{ - if (checked) - { - if (m_deviceAPI->initGeneration()) - { - m_deviceAPI->startGeneration(); - DSPEngine::instance()->startAudio(); - } - } - else - { - m_deviceAPI->stopGeneration(); - DSPEngine::instance()->stopAudio(); - } + FileSinkOutput::MsgConfigureFileSink* message = FileSinkOutput::MsgConfigureFileSink::create(m_settings); + m_deviceSampleSink->getInputMessageQueue()->push(message); } void FileSinkGui::updateStatus() @@ -254,16 +204,40 @@ void FileSinkGui::updateStatus() } } -void FileSinkGui::on_play_toggled(bool checked) +void FileSinkGui::on_centerFrequency_changed(quint64 value) { - FileSinkOutput::MsgConfigureFileSinkWork* message = FileSinkOutput::MsgConfigureFileSinkWork::create(checked); - m_sampleSink->getInputMessageQueue()->push(message); + m_settings.m_centerFrequency = value * 1000; + sendSettings(); +} + +void FileSinkGui::on_sampleRate_currentIndexChanged(int index) +{ + int newrate = FileSinkSampleRates::getRate(index); + m_settings.m_sampleRate = newrate * 1000; + sendSettings(); +} + +void FileSinkGui::on_startStop_toggled(bool checked) +{ + if (checked) + { + if (m_deviceAPI->initGeneration()) + { + m_deviceAPI->startGeneration(); + DSPEngine::instance()->startAudio(); + } + } + else + { + m_deviceAPI->stopGeneration(); + DSPEngine::instance()->stopAudio(); + } } void FileSinkGui::on_showFileDialog_clicked(bool checked) { - QString fileName = QFileDialog::getOpenFileName(this, - tr("Save I/Q record file"), ".", tr("SDR I/Q Files (*.sdriq)")); + QString fileName = QFileDialog::getSaveFileName(this, + tr("Save I/Q record file"), ".", tr("SDR I/Q Files (*.sdriq)")); if (fileName != "") { @@ -277,7 +251,7 @@ void FileSinkGui::configureFileName() { qDebug() << "FileSinkGui::configureFileName: " << m_fileName.toStdString().c_str(); FileSinkOutput::MsgConfigureFileSinkName* message = FileSinkOutput::MsgConfigureFileSinkName::create(m_fileName); - m_sampleSink->getInputMessageQueue()->push(message); + m_deviceSampleSink->getInputMessageQueue()->push(message); } void FileSinkGui::updateWithGeneration() @@ -285,19 +259,14 @@ void FileSinkGui::updateWithGeneration() ui->showFileDialog->setEnabled(!m_generation); } -void FileSinkGui::updateWithStreamData() -{ - ui->centerFrequency->setValue(m_centerFrequency/1000); -} - void FileSinkGui::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; + if (m_settings.m_sampleRate > 0){ + t_msec = ((m_samplesCount * 1000) / m_settings.m_sampleRate) % 1000; + t_sec = m_samplesCount / m_settings.m_sampleRate; } QTime t(0, 0, 0, 0); @@ -311,7 +280,7 @@ void FileSinkGui::tick() { if ((++m_tickCount & 0xf) == 0) { FileSinkOutput::MsgConfigureFileSinkStreamTiming* message = FileSinkOutput::MsgConfigureFileSinkStreamTiming::create(); - m_sampleSink->getInputMessageQueue()->push(message); + m_deviceSampleSink->getInputMessageQueue()->push(message); } } diff --git a/plugins/samplesink/filesink/filesinkgui.h b/plugins/samplesink/filesink/filesinkgui.h index e020199a2..ff2dc0956 100644 --- a/plugins/samplesink/filesink/filesinkgui.h +++ b/plugins/samplesink/filesink/filesinkgui.h @@ -20,6 +20,7 @@ #include #include "filesinkoutput.h" +#include "filesinksettings.h" #include "plugin/plugingui.h" @@ -52,36 +53,30 @@ private: Ui::FileSinkGui* ui; DeviceSinkAPI* m_deviceAPI; - FileSinkOutput::Settings m_settings; + FileSinkSettings m_settings; + QString m_fileName; QTimer m_statusTimer; std::vector m_gains; - DeviceSampleSink* m_sampleSink; + DeviceSampleSink* m_deviceSampleSink; bool m_generation; - QString m_fileName; - int m_sampleRate; - quint64 m_centerFrequency; std::time_t m_startingTimeStamp; int m_samplesCount; std::size_t m_tickCount; - int m_deviceSampleRate; - quint64 m_deviceCenterFrequency; //!< Center frequency in device int m_lastEngineState; void displaySettings(); void displayTime(); void sendSettings(); - void updateSampleRateAndFrequency(); void configureFileName(); void updateWithGeneration(); - void updateWithStreamData(); void updateWithStreamTime(); private slots: - void handleDSPMessages(); void handleSinkMessages(); + void on_centerFrequency_changed(quint64 value); void on_startStop_toggled(bool checked); - void on_play_toggled(bool checked); void on_showFileDialog_clicked(bool checked); + void on_sampleRate_currentIndexChanged(int index); void updateStatus(); void tick(); }; diff --git a/plugins/samplesink/filesink/filesinkoutput.cpp b/plugins/samplesink/filesink/filesinkoutput.cpp index 34605e197..ef4434287 100644 --- a/plugins/samplesink/filesink/filesinkoutput.cpp +++ b/plugins/samplesink/filesink/filesinkoutput.cpp @@ -32,45 +32,8 @@ MESSAGE_CLASS_DEFINITION(FileSinkOutput::MsgConfigureFileSinkName, Message) MESSAGE_CLASS_DEFINITION(FileSinkOutput::MsgConfigureFileSinkWork, Message) MESSAGE_CLASS_DEFINITION(FileSinkOutput::MsgConfigureFileSinkStreamTiming, Message) MESSAGE_CLASS_DEFINITION(FileSinkOutput::MsgReportFileSinkGeneration, Message) -MESSAGE_CLASS_DEFINITION(FileSinkOutput::MsgReportFileSinkStreamData, Message) MESSAGE_CLASS_DEFINITION(FileSinkOutput::MsgReportFileSinkStreamTiming, Message) -FileSinkOutput::Settings::Settings() : - m_fileName("./test.sdriq") -{ -} - -void FileSinkOutput::Settings::resetToDefaults() -{ - m_fileName = "./test.sdriq"; -} - -QByteArray FileSinkOutput::Settings::serialize() const -{ - SimpleSerializer s(1); - s.writeString(1, m_fileName); - return s.final(); -} - -bool FileSinkOutput::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; - } -} - FileSinkOutput::FileSinkOutput(const QTimer& masterTimer) : m_settings(), m_fileSinkThread(0), @@ -97,19 +60,13 @@ void FileSinkOutput::openFileStream() } m_ofstream.open(m_fileName.toStdString().c_str(), std::ios::binary); - FileRecord::Header header; - header.sampleRate = m_sampleRate; - header.centerFrequency = m_centerFrequency; - header.startTimeStamp = m_startingTimeStamp; // TODO: set timestamp + m_ofstream.write((const char *) &m_settings.m_sampleRate, sizeof(int)); + m_ofstream.write((const char *) &m_settings.m_centerFrequency, sizeof(quint64)); + m_startingTimeStamp = time(0); + m_ofstream.write((const char *) &m_startingTimeStamp, sizeof(std::time_t)); qDebug() << "FileSinkOutput::openFileStream: " << m_fileName.toStdString().c_str(); - - MsgReportFileSinkStreamData *report = MsgReportFileSinkStreamData::create(m_sampleRate, - m_centerFrequency, - m_startingTimeStamp); // file stream data - - getOutputMessageQueueToGUI()->push(report); } bool FileSinkOutput::init(const Message& message) @@ -192,6 +149,12 @@ bool FileSinkOutput::handleMessage(const Message& message) openFileStream(); return true; } + else if (MsgConfigureFileSink::match(message)) + { + MsgConfigureFileSink& conf = (MsgConfigureFileSink&) message; + applySettings(conf.getSettings(), false); + return true; + } else if (MsgConfigureFileSinkWork::match(message)) { MsgConfigureFileSinkWork& conf = (MsgConfigureFileSinkWork&) message; @@ -202,10 +165,6 @@ bool FileSinkOutput::handleMessage(const Message& message) if (working) { m_fileSinkThread->startWork(); - /* - MsgReportFileSourceStreamTiming *report = - MsgReportFileSourceStreamTiming::create(m_fileSourceThread->getSamplesCount()); - getOutputMessageQueueToGUI()->push(report);*/ } else { @@ -232,3 +191,18 @@ bool FileSinkOutput::handleMessage(const Message& message) return false; } } + +void FileSinkOutput::applySettings(const FileSinkSettings& settings, bool force) +{ + QMutexLocker mutexLocker(&m_mutex); + + if (force || (m_settings.m_centerFrequency != settings.m_centerFrequency)) + { + m_settings.m_centerFrequency = settings.m_centerFrequency; + } + + if (force || (m_settings.m_sampleRate != settings.m_sampleRate)) + { + m_settings.m_sampleRate = settings.m_sampleRate; + } +} diff --git a/plugins/samplesink/filesink/filesinkoutput.h b/plugins/samplesink/filesink/filesinkoutput.h index af8f0ca7f..d3b5b5aa1 100644 --- a/plugins/samplesink/filesink/filesinkoutput.h +++ b/plugins/samplesink/filesink/filesinkoutput.h @@ -17,41 +17,34 @@ #ifndef INCLUDE_FILESINKOUTPUT_H #define INCLUDE_FILESINKOUTPUT_H -#include #include #include #include #include #include +#include "dsp/devicesamplesink.h" +#include "filesinksettings.h" + class FileSinkThread; class FileSinkOutput : public DeviceSampleSink { public: - struct Settings { - QString m_fileName; - - Settings(); - void resetToDefaults(); - QByteArray serialize() const; - bool deserialize(const QByteArray& data); - }; - class MsgConfigureFileSink : public Message { MESSAGE_CLASS_DECLARATION public: - const Settings& getSettings() const { return m_settings; } + const FileSinkSettings& getSettings() const { return m_settings; } - static MsgConfigureFileSink* create(const Settings& settings) + static MsgConfigureFileSink* create(const FileSinkSettings& settings) { return new MsgConfigureFileSink(settings); } private: - Settings m_settings; + FileSinkSettings m_settings; - MsgConfigureFileSink(const Settings& settings) : + MsgConfigureFileSink(const FileSinkSettings& settings) : Message(), m_settings(settings) { } @@ -134,36 +127,6 @@ public: { } }; - class MsgReportFileSinkStreamData : 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 MsgReportFileSinkStreamData* create(int sampleRate, - quint64 centerFrequency, - std::time_t startingTimeStamp) - { - return new MsgReportFileSinkStreamData(sampleRate, centerFrequency, startingTimeStamp); - } - - protected: - int m_sampleRate; - quint64 m_centerFrequency; - std::time_t m_startingTimeStamp; - - MsgReportFileSinkStreamData(int sampleRate, - quint64 centerFrequency, - std::time_t startingTimeStamp) : - Message(), - m_sampleRate(sampleRate), - m_centerFrequency(centerFrequency), - m_startingTimeStamp(startingTimeStamp) - { } - }; - class MsgReportFileSinkStreamTiming : public Message { MESSAGE_CLASS_DECLARATION @@ -200,7 +163,7 @@ public: private: QMutex m_mutex; - Settings m_settings; + FileSinkSettings m_settings; std::ofstream m_ofstream; FileSinkThread* m_fileSinkThread; QString m_deviceDescription; @@ -211,6 +174,7 @@ private: const QTimer& m_masterTimer; void openFileStream(); + void applySettings(const FileSinkSettings& settings, bool force = false); }; #endif // INCLUDE_FILESINKOUTPUT_H diff --git a/plugins/samplesink/filesink/filesinksettings.cpp b/plugins/samplesink/filesink/filesinksettings.cpp new file mode 100644 index 000000000..ad9aef1a3 --- /dev/null +++ b/plugins/samplesink/filesink/filesinksettings.cpp @@ -0,0 +1,61 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "util/simpleserializer.h" +#include "filesinksettings.h" + +FileSinkSettings::FileSinkSettings() +{ + resetToDefaults(); +} + +void FileSinkSettings::resetToDefaults() +{ + m_centerFrequency = 435000*1000; + m_sampleRate = 48000; +} + +QByteArray FileSinkSettings::serialize() const +{ + SimpleSerializer s(1); + + s.writeS32(1, m_sampleRate); + + return s.final(); +} + +bool FileSinkSettings::deserialize(const QByteArray& data) +{ + SimpleDeserializer d(data); + + if (!d.isValid()) + { + resetToDefaults(); + return false; + } + + if (d.getVersion() == 1) + { + int intval; + d.readS32(1, &m_sampleRate, 48000); + return true; + } + else + { + resetToDefaults(); + return false; + } +} diff --git a/plugins/samplesink/filesink/filesinksettings.h b/plugins/samplesink/filesink/filesinksettings.h new file mode 100644 index 000000000..87c0dba22 --- /dev/null +++ b/plugins/samplesink/filesink/filesinksettings.h @@ -0,0 +1,32 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef PLUGINS_SAMPLESINK_FILESINK_FILESINKSETTINGS_H_ +#define PLUGINS_SAMPLESINK_FILESINK_FILESINKSETTINGS_H_ + +#include + +struct FileSinkSettings { + quint64 m_centerFrequency; + qint32 m_sampleRate; + + FileSinkSettings(); + void resetToDefaults(); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); +}; + +#endif /* PLUGINS_SAMPLESINK_FILESINK_FILESINKSETTINGS_H_ */