2017-05-14 22:58:56 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// 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/>. //
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <QDebug>
|
|
|
|
|
|
|
|
#include "util/simpleserializer.h"
|
|
|
|
#include "dsp/dspcommands.h"
|
|
|
|
#include "dsp/dspengine.h"
|
|
|
|
#include "dsp/filerecord.h"
|
|
|
|
|
|
|
|
#include "device/devicesinkapi.h"
|
|
|
|
|
|
|
|
#include "sdrdaemonsinkgui.h"
|
|
|
|
#include "sdrdaemonsinkoutput.h"
|
|
|
|
#include "sdrdaemonsinkthread.h"
|
|
|
|
|
2017-05-21 02:19:12 +00:00
|
|
|
MESSAGE_CLASS_DEFINITION(SDRdaemonSinkOutput::MsgConfigureSDRdaemonSink, Message)
|
|
|
|
MESSAGE_CLASS_DEFINITION(SDRdaemonSinkOutput::MsgConfigureSDRdaemonSinkName, Message)
|
|
|
|
MESSAGE_CLASS_DEFINITION(SDRdaemonSinkOutput::MsgConfigureSDRdaemonSinkWork, Message)
|
|
|
|
MESSAGE_CLASS_DEFINITION(SDRdaemonSinkOutput::MsgConfigureSDRdaemonSinkStreamTiming, Message)
|
|
|
|
MESSAGE_CLASS_DEFINITION(SDRdaemonSinkOutput::MsgReportSDRdaemonSinkGeneration, Message)
|
|
|
|
MESSAGE_CLASS_DEFINITION(SDRdaemonSinkOutput::MsgReportSDRdaemonSinkStreamTiming, Message)
|
|
|
|
|
|
|
|
SDRdaemonSinkOutput::SDRdaemonSinkOutput(DeviceSinkAPI *deviceAPI, const QTimer& masterTimer) :
|
2017-05-14 22:58:56 +00:00
|
|
|
m_deviceAPI(deviceAPI),
|
|
|
|
m_settings(),
|
|
|
|
m_fileSinkThread(0),
|
|
|
|
m_deviceDescription("FileSink"),
|
|
|
|
m_fileName("./test.sdriq"),
|
|
|
|
m_startingTimeStamp(0),
|
|
|
|
m_masterTimer(masterTimer)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-05-21 02:19:12 +00:00
|
|
|
SDRdaemonSinkOutput::~SDRdaemonSinkOutput()
|
2017-05-14 22:58:56 +00:00
|
|
|
{
|
|
|
|
stop();
|
|
|
|
}
|
|
|
|
|
2017-05-21 02:19:12 +00:00
|
|
|
void SDRdaemonSinkOutput::openFileStream()
|
2017-05-14 22:58:56 +00:00
|
|
|
{
|
|
|
|
if (m_ofstream.is_open()) {
|
|
|
|
m_ofstream.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
m_ofstream.open(m_fileName.toStdString().c_str(), std::ios::binary);
|
|
|
|
|
|
|
|
int actualSampleRate = m_settings.m_sampleRate * (1<<m_settings.m_log2Interp);
|
|
|
|
m_ofstream.write((const char *) &actualSampleRate, sizeof(int));
|
|
|
|
//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();
|
|
|
|
}
|
|
|
|
|
2017-05-21 02:19:12 +00:00
|
|
|
bool SDRdaemonSinkOutput::start()
|
2017-05-14 22:58:56 +00:00
|
|
|
{
|
|
|
|
QMutexLocker mutexLocker(&m_mutex);
|
|
|
|
qDebug() << "FileSinkOutput::start";
|
|
|
|
|
|
|
|
openFileStream();
|
|
|
|
|
|
|
|
if((m_fileSinkThread = new FileSinkThread(&m_ofstream, &m_sampleSourceFifo)) == 0)
|
|
|
|
{
|
|
|
|
qFatal("out of memory");
|
|
|
|
stop();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_fileSinkThread->setSamplerate(m_settings.m_sampleRate);
|
|
|
|
m_fileSinkThread->setLog2Interpolation(m_settings.m_log2Interp);
|
|
|
|
m_fileSinkThread->connectTimer(m_masterTimer);
|
|
|
|
m_fileSinkThread->startWork();
|
|
|
|
|
|
|
|
mutexLocker.unlock();
|
|
|
|
//applySettings(m_generalSettings, m_settings, true);
|
|
|
|
qDebug("FileSinkOutput::start: started");
|
|
|
|
|
2017-05-21 02:19:12 +00:00
|
|
|
MsgReportSDRdaemonSinkGeneration *report = MsgReportSDRdaemonSinkGeneration::create(true); // acquisition on
|
2017-05-14 22:58:56 +00:00
|
|
|
getOutputMessageQueueToGUI()->push(report);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-05-21 02:19:12 +00:00
|
|
|
void SDRdaemonSinkOutput::stop()
|
2017-05-14 22:58:56 +00:00
|
|
|
{
|
|
|
|
qDebug() << "FileSourceInput::stop";
|
|
|
|
QMutexLocker mutexLocker(&m_mutex);
|
|
|
|
|
|
|
|
if(m_fileSinkThread != 0)
|
|
|
|
{
|
|
|
|
m_fileSinkThread->stopWork();
|
|
|
|
delete m_fileSinkThread;
|
|
|
|
m_fileSinkThread = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_ofstream.is_open()) {
|
|
|
|
m_ofstream.close();
|
|
|
|
}
|
|
|
|
|
2017-05-21 02:19:12 +00:00
|
|
|
MsgReportSDRdaemonSinkGeneration *report = MsgReportSDRdaemonSinkGeneration::create(false); // acquisition off
|
2017-05-14 22:58:56 +00:00
|
|
|
getOutputMessageQueueToGUI()->push(report);
|
|
|
|
}
|
|
|
|
|
2017-05-21 02:19:12 +00:00
|
|
|
const QString& SDRdaemonSinkOutput::getDeviceDescription() const
|
2017-05-14 22:58:56 +00:00
|
|
|
{
|
|
|
|
return m_deviceDescription;
|
|
|
|
}
|
|
|
|
|
2017-05-21 02:19:12 +00:00
|
|
|
int SDRdaemonSinkOutput::getSampleRate() const
|
2017-05-14 22:58:56 +00:00
|
|
|
{
|
|
|
|
return m_settings.m_sampleRate;
|
|
|
|
}
|
|
|
|
|
2017-05-21 02:19:12 +00:00
|
|
|
quint64 SDRdaemonSinkOutput::getCenterFrequency() const
|
2017-05-14 22:58:56 +00:00
|
|
|
{
|
|
|
|
return m_settings.m_centerFrequency;
|
|
|
|
}
|
|
|
|
|
2017-05-21 02:19:12 +00:00
|
|
|
std::time_t SDRdaemonSinkOutput::getStartingTimeStamp() const
|
2017-05-14 22:58:56 +00:00
|
|
|
{
|
|
|
|
return m_startingTimeStamp;
|
|
|
|
}
|
|
|
|
|
2017-05-21 02:19:12 +00:00
|
|
|
bool SDRdaemonSinkOutput::handleMessage(const Message& message)
|
2017-05-14 22:58:56 +00:00
|
|
|
{
|
2017-05-21 02:19:12 +00:00
|
|
|
if (MsgConfigureSDRdaemonSinkName::match(message))
|
2017-05-14 22:58:56 +00:00
|
|
|
{
|
2017-05-21 02:19:12 +00:00
|
|
|
MsgConfigureSDRdaemonSinkName& conf = (MsgConfigureSDRdaemonSinkName&) message;
|
2017-05-14 22:58:56 +00:00
|
|
|
m_fileName = conf.getFileName();
|
|
|
|
openFileStream();
|
|
|
|
return true;
|
|
|
|
}
|
2017-05-21 02:19:12 +00:00
|
|
|
else if (MsgConfigureSDRdaemonSink::match(message))
|
2017-05-14 22:58:56 +00:00
|
|
|
{
|
|
|
|
qDebug() << "FileSinkOutput::handleMessage: MsgConfigureFileSink";
|
2017-05-21 02:19:12 +00:00
|
|
|
MsgConfigureSDRdaemonSink& conf = (MsgConfigureSDRdaemonSink&) message;
|
2017-05-14 22:58:56 +00:00
|
|
|
applySettings(conf.getSettings(), false);
|
|
|
|
return true;
|
|
|
|
}
|
2017-05-21 02:19:12 +00:00
|
|
|
else if (MsgConfigureSDRdaemonSinkWork::match(message))
|
2017-05-14 22:58:56 +00:00
|
|
|
{
|
2017-05-21 02:19:12 +00:00
|
|
|
MsgConfigureSDRdaemonSinkWork& conf = (MsgConfigureSDRdaemonSinkWork&) message;
|
2017-05-14 22:58:56 +00:00
|
|
|
bool working = conf.isWorking();
|
|
|
|
|
|
|
|
if (m_fileSinkThread != 0)
|
|
|
|
{
|
|
|
|
if (working)
|
|
|
|
{
|
|
|
|
m_fileSinkThread->startWork();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_fileSinkThread->stopWork();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2017-05-21 02:19:12 +00:00
|
|
|
else if (MsgConfigureSDRdaemonSinkStreamTiming::match(message))
|
2017-05-14 22:58:56 +00:00
|
|
|
{
|
2017-05-21 02:19:12 +00:00
|
|
|
MsgReportSDRdaemonSinkStreamTiming *report;
|
2017-05-14 22:58:56 +00:00
|
|
|
|
|
|
|
if (m_fileSinkThread != 0)
|
|
|
|
{
|
2017-05-21 02:19:12 +00:00
|
|
|
report = MsgReportSDRdaemonSinkStreamTiming::create(m_fileSinkThread->getSamplesCount());
|
2017-05-14 22:58:56 +00:00
|
|
|
getOutputMessageQueueToGUI()->push(report);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-21 02:19:12 +00:00
|
|
|
void SDRdaemonSinkOutput::applySettings(const FileSinkSettings& settings, bool force)
|
2017-05-14 22:58:56 +00:00
|
|
|
{
|
|
|
|
QMutexLocker mutexLocker(&m_mutex);
|
|
|
|
bool forwardChange = false;
|
|
|
|
|
|
|
|
if (force || (m_settings.m_centerFrequency != settings.m_centerFrequency))
|
|
|
|
{
|
|
|
|
m_settings.m_centerFrequency = settings.m_centerFrequency;
|
|
|
|
forwardChange = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (force || (m_settings.m_sampleRate != settings.m_sampleRate))
|
|
|
|
{
|
|
|
|
m_settings.m_sampleRate = settings.m_sampleRate;
|
|
|
|
|
|
|
|
if (m_fileSinkThread != 0)
|
|
|
|
{
|
|
|
|
m_fileSinkThread->setSamplerate(m_settings.m_sampleRate);
|
|
|
|
}
|
|
|
|
|
|
|
|
forwardChange = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (force || (m_settings.m_log2Interp != settings.m_log2Interp))
|
|
|
|
{
|
|
|
|
m_settings.m_log2Interp = settings.m_log2Interp;
|
|
|
|
|
|
|
|
if (m_fileSinkThread != 0)
|
|
|
|
{
|
|
|
|
m_fileSinkThread->setSamplerate(m_settings.m_sampleRate);
|
|
|
|
}
|
|
|
|
|
|
|
|
forwardChange = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (forwardChange)
|
|
|
|
{
|
|
|
|
qDebug("FileSinkOutput::applySettings: forward: m_centerFrequency: %llu m_sampleRate: %llu m_log2Interp: %d",
|
|
|
|
m_settings.m_centerFrequency,
|
|
|
|
m_settings.m_sampleRate,
|
|
|
|
m_settings.m_log2Interp);
|
|
|
|
DSPSignalNotification *notif = new DSPSignalNotification(m_settings.m_sampleRate, m_settings.m_centerFrequency);
|
|
|
|
m_deviceAPI->getDeviceInputMessageQueue()->push(notif);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|