From 7c1b1032c92c6a90ed78d8f19a43fd07fe183bac Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 28 Nov 2016 02:17:08 +0100 Subject: [PATCH] AM Modulator: added file input (basic) --- Readme.md | 2 +- debian/changelog | 6 + plugins/channeltx/modam/ammod.cpp | 116 ++++++++++- plugins/channeltx/modam/ammod.h | 156 ++++++++++++++- plugins/channeltx/modam/ammodgui.cpp | 159 ++++++++++++++- plugins/channeltx/modam/ammodgui.h | 23 +++ plugins/channeltx/modam/ammodgui.ui | 219 ++++++++++++++++++++- plugins/channeltx/modam/ammodplugin.cpp | 2 +- plugins/samplesource/rtlsdr/CMakeLists.txt | 2 +- sdrbase/gui/aboutdialog.ui | 2 +- sdrbase/mainwindow.cpp | 2 +- sdrbase/resources/microphone.png | Bin 0 -> 1078 bytes sdrbase/resources/res.qrc | 1 + 13 files changed, 667 insertions(+), 23 deletions(-) create mode 100644 sdrbase/resources/microphone.png diff --git a/Readme.md b/Readme.md index 4aade1527..d28b4a30a 100644 --- a/Readme.md +++ b/Readme.md @@ -37,7 +37,7 @@ Transmission or signal generation support for eligible devices (BladeRF and Hack - Phase 1: version 2.2.0: generation to file (File Sink) with AM modulator with simple sine modulation. Fixed sample rate of 48 kS/s (no effective interpolation) - Phase 2: version 2.2.x: full baseband interpolation chain: in AM modulator and Up Channelizer. - 2.3.0: SDRplay came into play ... - - Phase 3a: version 2.3.x: Improve AM modulator with audio file input + - Phase 3a: version 2.3.1: Improve AM modulator with audio file input - Phase 3b: version 2.3.x: Improve AM modulator with audio input (Mic) support - Phase 4a: version 2.4.0: FM modulator - Phase 4b: version 2.4.x: WFM modulator diff --git a/debian/changelog b/debian/changelog index 67ab04bff..b49491686 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +sdrangel (2.3.1-1) unstable; urgency=medium + + * AM Modulator: support file input + + -- Edouard Griffiths, F4EXB Sun, 27 Nov 2016 23:14:18 +0100 + sdrangel (2.3.0-1) unstable; urgency=medium * SDRplay support: new input source plugin diff --git a/plugins/channeltx/modam/ammod.cpp b/plugins/channeltx/modam/ammod.cpp index 88d102735..66148a255 100644 --- a/plugins/channeltx/modam/ammod.cpp +++ b/plugins/channeltx/modam/ammod.cpp @@ -26,6 +26,13 @@ #include "dsp/pidcontroller.h" MESSAGE_CLASS_DEFINITION(AMMod::MsgConfigureAMMod, Message) +MESSAGE_CLASS_DEFINITION(AMMod::MsgConfigureFileSourceName, Message) +MESSAGE_CLASS_DEFINITION(AMMod::MsgConfigureFileSourceSeek, Message) +MESSAGE_CLASS_DEFINITION(AMMod::MsgConfigureAFInput, Message) +MESSAGE_CLASS_DEFINITION(AMMod::MsgConfigureFileSourceStreamTiming, Message) +MESSAGE_CLASS_DEFINITION(AMMod::MsgReportFileSourceStreamData, Message) +MESSAGE_CLASS_DEFINITION(AMMod::MsgReportFileSourceStreamTiming, Message) + AMMod::AMMod() : m_settingsMutex(QMutex::Recursive) @@ -49,6 +56,8 @@ AMMod::AMMod() : m_magsq = 0.0; m_toneNco.setFreq(1000.0, m_config.m_audioSampleRate); + + m_afInput = AMModInputNone; } AMMod::~AMMod() @@ -64,18 +73,19 @@ void AMMod::configure(MessageQueue* messageQueue, Real rfBandwidth, Real afBandw void AMMod::pull(Sample& sample) { Complex ci; + Real t; m_settingsMutex.lock(); if (m_interpolatorDistance > 1.0f) // decimate { - Real t = m_toneNco.next(); + pullAF(t); m_modSample.real(((t+1.0f) * m_running.m_modFactor * 16384.0f)); // modulate and scale zero frequency carrier m_modSample.imag(0.0f); while (!m_interpolator.decimate(&m_interpolatorDistanceRemain, m_modSample, &ci)) { - Real t = m_toneNco.next(); + pullAF(t); m_modSample.real(((t+1.0f) * m_running.m_modFactor * 16384.0f)); // modulate and scale zero frequency carrier m_modSample.imag(0.0f); } @@ -84,7 +94,7 @@ void AMMod::pull(Sample& sample) { if (m_interpolator.interpolate(&m_interpolatorDistanceRemain, m_modSample, &ci)) { - Real t = m_toneNco.next(); + pullAF(t); m_modSample.real(((t+1.0f) * m_running.m_modFactor * 16384.0f)); // modulate and scale zero frequency carrier m_modSample.imag(0.0f); } @@ -105,6 +115,41 @@ void AMMod::pull(Sample& sample) sample.m_imag = (FixReal) ci.imag(); } +void AMMod::pullAF(Real& sample) +{ + switch (m_afInput) + { + case AMModInputTone: + sample = m_toneNco.next(); + break; + case AMModInputFile: + // sox f4exb_call.wav --encoding float --endian little f4exb_call.raw + // ffplay -f f32le -ar 48k -ac 1 f4exb_call.raw + if (m_ifstream.is_open()) + { + if (m_ifstream.eof()) // TODO: handle loop playback situation + { + m_ifstream.clear(); + m_ifstream.seekg(0, std::ios::beg); + } + + m_ifstream.read(reinterpret_cast(&sample), sizeof(Real)); + } + else + { + sample = 0.0f; + } + break; + case AMModInputAudio: + sample = 0.0f; // TODO + break; + case AMModInputNone: + default: + sample = 0.0f; + break; + } +} + void AMMod::start() { qDebug() << "AMMod::start: m_outputSampleRate: " << m_config.m_outputSampleRate @@ -155,6 +200,37 @@ bool AMMod::handleMessage(const Message& cmd) return true; } + else if (MsgConfigureFileSourceName::match(cmd)) + { + MsgConfigureFileSourceName& conf = (MsgConfigureFileSourceName&) cmd; + m_fileName = conf.getFileName(); + openFileStream(); + return true; + } + else if (MsgConfigureFileSourceSeek::match(cmd)) + { + MsgConfigureFileSourceSeek& conf = (MsgConfigureFileSourceSeek&) cmd; + int seekPercentage = conf.getPercentage(); + seekFileStream(seekPercentage); + + return true; + } + else if (MsgConfigureAFInput::match(cmd)) + { + MsgConfigureAFInput& conf = (MsgConfigureAFInput&) cmd; + m_afInput = conf.getAFInput(); + + return true; + } + else if (MsgConfigureFileSourceStreamTiming::match(cmd)) + { + std::size_t samplesCount = m_ifstream.tellg() / sizeof(Real); + MsgReportFileSourceStreamTiming *report; + report = MsgReportFileSourceStreamTiming::create(samplesCount); + getOutputMessageQueue()->push(report); + + return true; + } else { return false; @@ -200,3 +276,37 @@ void AMMod::apply() m_running.m_audioMute = m_config.m_audioMute; } +void AMMod::openFileStream() +{ + if (m_ifstream.is_open()) { + m_ifstream.close(); + } + + m_ifstream.open(m_fileName.toStdString().c_str(), std::ios::binary | std::ios::ate); + quint64 fileSize = m_ifstream.tellg(); + m_ifstream.seekg(0,std::ios_base::beg); + + m_sampleRate = 48000; // fixed rate + m_recordLength = fileSize / (sizeof(Real) * m_sampleRate); + + qDebug() << "AMMod::openFileStream: " << m_fileName.toStdString().c_str() + << " fileSize: " << fileSize << "bytes" + << " length: " << m_recordLength << " seconds"; + + MsgReportFileSourceStreamData *report; + report = MsgReportFileSourceStreamData::create(m_sampleRate, m_recordLength); + getOutputMessageQueue()->push(report); +} + +void AMMod::seekFileStream(int seekPercentage) +{ + QMutexLocker mutexLocker(&m_settingsMutex); + + if (m_ifstream.is_open()) + { + int seekPoint = ((m_recordLength * seekPercentage) / 100) * m_sampleRate; + seekPoint *= sizeof(Real); + m_ifstream.clear(); + m_ifstream.seekg(seekPoint, std::ios::beg); + } +} diff --git a/plugins/channeltx/modam/ammod.h b/plugins/channeltx/modam/ammod.h index e5625035a..1a261a0b6 100644 --- a/plugins/channeltx/modam/ammod.h +++ b/plugins/channeltx/modam/ammod.h @@ -19,6 +19,9 @@ #include #include +#include +#include + #include "dsp/basebandsamplesource.h" #include "dsp/nco.h" #include "dsp/interpolator.h" @@ -32,6 +35,142 @@ class AMMod : public BasebandSampleSource { Q_OBJECT public: + typedef enum + { + AMModInputNone, + AMModInputTone, + AMModInputFile, + AMModInputAudio + } AMModInputAF; + + class MsgConfigureFileSourceName : public Message + { + MESSAGE_CLASS_DECLARATION + + public: + const QString& getFileName() const { return m_fileName; } + + static MsgConfigureFileSourceName* create(const QString& fileName) + { + return new MsgConfigureFileSourceName(fileName); + } + + private: + QString m_fileName; + + MsgConfigureFileSourceName(const QString& fileName) : + Message(), + m_fileName(fileName) + { } + }; + + class MsgConfigureFileSourceSeek : public Message + { + MESSAGE_CLASS_DECLARATION + + public: + int getPercentage() const { return m_seekPercentage; } + + static MsgConfigureFileSourceSeek* create(int seekPercentage) + { + return new MsgConfigureFileSourceSeek(seekPercentage); + } + + protected: + int m_seekPercentage; //!< percentage of seek position from the beginning 0..100 + + MsgConfigureFileSourceSeek(int seekPercentage) : + Message(), + m_seekPercentage(seekPercentage) + { } + }; + + class MsgConfigureFileSourceStreamTiming : public Message { + MESSAGE_CLASS_DECLARATION + + public: + + static MsgConfigureFileSourceStreamTiming* create() + { + return new MsgConfigureFileSourceStreamTiming(); + } + + private: + + MsgConfigureFileSourceStreamTiming() : + Message() + { } + }; + + class MsgConfigureAFInput : public Message + { + MESSAGE_CLASS_DECLARATION + + public: + AMModInputAF getAFInput() const { return m_afInput; } + + static MsgConfigureAFInput* create(AMModInputAF afInput) + { + return new MsgConfigureAFInput(afInput); + } + + private: + AMModInputAF m_afInput; + + MsgConfigureAFInput(AMModInputAF afInput) : + Message(), + m_afInput(afInput) + { } + }; + + class MsgReportFileSourceStreamTiming : public Message + { + MESSAGE_CLASS_DECLARATION + + public: + std::size_t getSamplesCount() const { return m_samplesCount; } + + static MsgReportFileSourceStreamTiming* create(std::size_t samplesCount) + { + return new MsgReportFileSourceStreamTiming(samplesCount); + } + + protected: + std::size_t m_samplesCount; + + MsgReportFileSourceStreamTiming(std::size_t samplesCount) : + Message(), + m_samplesCount(samplesCount) + { } + }; + + class MsgReportFileSourceStreamData : public Message { + MESSAGE_CLASS_DECLARATION + + public: + int getSampleRate() const { return m_sampleRate; } + quint32 getRecordLength() const { return m_recordLength; } + + static MsgReportFileSourceStreamData* create(int sampleRate, + quint32 recordLength) + { + return new MsgReportFileSourceStreamData(sampleRate, recordLength); + } + + protected: + int m_sampleRate; + quint32 m_recordLength; + + MsgReportFileSourceStreamData(int sampleRate, + quint32 recordLength) : + Message(), + m_sampleRate(sampleRate), + m_recordLength(recordLength) + { } + }; + + //================================================================= + AMMod(); ~AMMod(); @@ -45,7 +184,8 @@ public: Real getMagSq() const { return m_magsq; } private: - class MsgConfigureAMMod : public Message { + class MsgConfigureAMMod : public Message + { MESSAGE_CLASS_DECLARATION public: @@ -74,6 +214,8 @@ private: { } }; + //================================================================= + struct AudioSample { qint16 l; qint16 r; @@ -105,6 +247,8 @@ private: { } }; + //================================================================= + Config m_config; Config m_running; @@ -128,7 +272,17 @@ private: SampleVector m_sampleBuffer; QMutex m_settingsMutex; + std::ifstream m_ifstream; + QString m_fileName; + quint32 m_recordLength; //!< record length in seconds computed from file size + int m_sampleRate; + + AMModInputAF m_afInput; + void apply(); + void pullAF(Real& sample); + void openFileStream(); + void seekFileStream(int seekPercentage); }; diff --git a/plugins/channeltx/modam/ammodgui.cpp b/plugins/channeltx/modam/ammodgui.cpp index 34d9ec584..582fa5f5b 100644 --- a/plugins/channeltx/modam/ammodgui.cpp +++ b/plugins/channeltx/modam/ammodgui.cpp @@ -16,6 +16,9 @@ #include #include +#include +#include +#include #include "ammodgui.h" @@ -31,8 +34,6 @@ #include "dsp/dspengine.h" #include "mainwindow.h" -#include "ammod.h" - const QString AMModGUI::m_channelID = "sdrangel.channeltx.modam"; const int AMModGUI::m_rfBW[] = { @@ -141,7 +142,24 @@ bool AMModGUI::deserialize(const QByteArray& data) bool AMModGUI::handleMessage(const Message& message) { - return false; + if (AMMod::MsgReportFileSourceStreamData::match(message)) + { + m_recordSampleRate = ((AMMod::MsgReportFileSourceStreamData&)message).getSampleRate(); + m_recordLength = ((AMMod::MsgReportFileSourceStreamData&)message).getRecordLength(); + m_samplesCount = 0; + updateWithStreamData(); + return true; + } + else if (AMMod::MsgReportFileSourceStreamTiming::match(message)) + { + m_samplesCount = ((AMMod::MsgReportFileSourceStreamTiming&)message).getSamplesCount(); + updateWithStreamTime(); + return true; + } + else + { + return false; + } } void AMModGUI::viewChanged() @@ -149,6 +167,19 @@ void AMModGUI::viewChanged() applySettings(); } +void AMModGUI::handleSourceMessages() +{ + Message* message; + + while ((message = m_amMod->getOutputMessageQueue()->pop()) != 0) + { + if (handleMessage(*message)) + { + delete message; + } + } +} + void AMModGUI::on_deltaMinus_toggled(bool minus) { int deltaFrequency = m_channelMarker.getCenterFrequency(); @@ -193,6 +224,74 @@ void AMModGUI::on_audioMute_toggled(bool checked) applySettings(); } +void AMModGUI::on_playLoop_toggled(bool checked) +{ + // TODO: do something about it! +} + +void AMModGUI::on_play_toggled(bool checked) +{ + ui->tone->setEnabled(!checked); // release other source inputs + ui->mic->setEnabled(!checked); + m_modAFInput = checked ? AMMod::AMModInputFile : AMMod::AMModInputNone; + AMMod::MsgConfigureAFInput* message = AMMod::MsgConfigureAFInput::create(m_modAFInput); + m_amMod->getInputMessageQueue()->push(message); + ui->navTimeSlider->setEnabled(!checked); + m_enableNavTime = !checked; +} + +void AMModGUI::on_tone_toggled(bool checked) +{ + ui->play->setEnabled(!checked); // release other source inputs + ui->mic->setEnabled(!checked); + m_modAFInput = checked ? AMMod::AMModInputTone : AMMod::AMModInputNone; + AMMod::MsgConfigureAFInput* message = AMMod::MsgConfigureAFInput::create(m_modAFInput); + m_amMod->getInputMessageQueue()->push(message); +} + +void AMModGUI::on_mic_toggled(bool checked) +{ + ui->play->setEnabled(!checked); // release other source inputs + ui->tone->setEnabled(!checked); // release other source inputs + m_modAFInput = checked ? AMMod::AMModInputAudio : AMMod::AMModInputNone; + AMMod::MsgConfigureAFInput* message = AMMod::MsgConfigureAFInput::create(m_modAFInput); + m_amMod->getInputMessageQueue()->push(message); +} + +void AMModGUI::on_navTimeSlider_valueChanged(int value) +{ + if (m_enableNavTime && ((value >= 0) && (value <= 100))) + { + int t_sec = (m_recordLength * value) / 100; + QTime t(0, 0, 0, 0); + t = t.addSecs(t_sec); + + AMMod::MsgConfigureFileSourceSeek* message = AMMod::MsgConfigureFileSourceSeek::create(value); + m_amMod->getInputMessageQueue()->push(message); + } +} + +void AMModGUI::on_showFileDialog_clicked(bool checked) +{ + QString fileName = QFileDialog::getOpenFileName(this, + tr("Open raw audio file"), ".", tr("Raw audio Files (*.raw)")); + + if (fileName != "") + { + m_fileName = fileName; + ui->recordFileText->setText(m_fileName); + ui->play->setEnabled(true); + configureFileName(); + } +} + +void AMModGUI::configureFileName() +{ + qDebug() << "FileSourceGui::configureFileName: " << m_fileName.toStdString().c_str(); + AMMod::MsgConfigureFileSourceName* message = AMMod::MsgConfigureFileSourceName::create(m_fileName); + m_amMod->getInputMessageQueue()->push(message); +} + void AMModGUI::onWidgetRolled(QWidget* widget, bool rollDown) { } @@ -214,7 +313,13 @@ AMModGUI::AMModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pare m_channelMarker(this), m_basicSettingsShown(false), m_doApplySettings(true), - m_channelPowerDbAvg(20,0) + m_channelPowerDbAvg(20,0), + m_recordLength(0), + m_recordSampleRate(48000), + m_samplesCount(0), + m_tickCount(0), + m_enableNavTime(false), + m_modAFInput(AMMod::AMModInputNone) { ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose, true); @@ -243,7 +348,14 @@ AMModGUI::AMModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pare m_deviceAPI->addChannelMarker(&m_channelMarker); m_deviceAPI->addRollupWidget(this); + ui->play->setEnabled(false); + ui->play->setChecked(false); + ui->tone->setChecked(false); + ui->mic->setChecked(false); + applySettings(); + + connect(m_amMod->getOutputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages())); } AMModGUI::~AMModGUI() @@ -302,5 +414,44 @@ void AMModGUI::tick() Real powDb = CalcDb::dbPower(m_amMod->getMagSq()); m_channelPowerDbAvg.feed(powDb); ui->channelPower->setText(QString::number(m_channelPowerDbAvg.average(), 'f', 1)); + + if (((++m_tickCount & 0xf) == 0) && (m_modAFInput == AMMod::AMModInputFile)) + { + AMMod::MsgConfigureFileSourceStreamTiming* message = AMMod::MsgConfigureFileSourceStreamTiming::create(); + m_amMod->getInputMessageQueue()->push(message); + } } +void AMModGUI::updateWithStreamData() +{ + QTime recordLength(0, 0, 0, 0); + recordLength = recordLength.addSecs(m_recordLength); + QString s_time = recordLength.toString("hh:mm:ss"); + ui->recordLengthText->setText(s_time); + updateWithStreamTime(); +} + +void AMModGUI::updateWithStreamTime() +{ + int t_sec = 0; + int t_msec = 0; + + if (m_recordSampleRate > 0) + { + t_msec = ((m_samplesCount * 1000) / m_recordSampleRate) % 1000; + t_sec = m_samplesCount / m_recordSampleRate; + } + + QTime t(0, 0, 0, 0); + t = t.addSecs(t_sec); + t = t.addMSecs(t_msec); + QString s_timems = t.toString("hh:mm:ss.zzz"); + QString s_time = t.toString("hh:mm:ss"); + ui->relTimeText->setText(s_timems); + + if (!m_enableNavTime) + { + float posRatio = (float) t_sec / (float) m_recordLength; + ui->navTimeSlider->setValue((int) (posRatio * 100.0)); + } +} diff --git a/plugins/channeltx/modam/ammodgui.h b/plugins/channeltx/modam/ammodgui.h index 699f1cc25..fdbee0449 100644 --- a/plugins/channeltx/modam/ammodgui.h +++ b/plugins/channeltx/modam/ammodgui.h @@ -21,6 +21,7 @@ #include "plugin/plugingui.h" #include "dsp/channelmarker.h" #include "dsp/movingaverage.h" +#include "ammod.h" class PluginAPI; class DeviceSinkAPI; @@ -55,14 +56,26 @@ public: private slots: void viewChanged(); + void handleSourceMessages(); + void on_deltaFrequency_changed(quint64 value); void on_deltaMinus_toggled(bool minus); void on_rfBW_valueChanged(int value); void on_afBW_valueChanged(int value); void on_modPercent_valueChanged(int value); void on_audioMute_toggled(bool checked); + void on_tone_toggled(bool checked); + void on_mic_toggled(bool checked); + void on_play_toggled(bool checked); + + void on_playLoop_toggled(bool checked); + void on_navTimeSlider_valueChanged(int value); + void on_showFileDialog_clicked(bool checked); + void onWidgetRolled(QWidget* widget, bool rollDown); void onMenuDoubleClicked(); + + void configureFileName(); void tick(); private: @@ -78,6 +91,14 @@ private: AMMod* m_amMod; MovingAverage m_channelPowerDbAvg; + QString m_fileName; + quint32 m_recordLength; + int m_recordSampleRate; + int m_samplesCount; + std::size_t m_tickCount; + bool m_enableNavTime; + AMMod::AMModInputAF m_modAFInput; + static const int m_rfBW[]; explicit AMModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* parent = NULL); @@ -85,6 +106,8 @@ private: void blockApplySettings(bool block); void applySettings(); + void updateWithStreamData(); + void updateWithStreamTime(); void leaveEvent(QEvent*); void enterEvent(QEvent*); diff --git a/plugins/channeltx/modam/ammodgui.ui b/plugins/channeltx/modam/ammodgui.ui index 2f1bda29f..d55bb5fb5 100644 --- a/plugins/channeltx/modam/ammodgui.ui +++ b/plugins/channeltx/modam/ammodgui.ui @@ -6,8 +6,8 @@ 0 0 - 257 - 143 + 261 + 180 @@ -27,8 +27,8 @@ 10 10 - 235 - 121 + 241 + 161 @@ -302,22 +302,221 @@ + + + + + + Tone modulation (1 kHz) + + + ... + + + + :/carrier.png:/carrier.png + + + + + + + Audio input + + + ... + + + + :/microphone.png:/microphone.png + + + true + + + + + + + + 24 + 24 + + + + + 24 + 24 + + + + Open record file (48 kHz 32 bit float LE mono) + + + + + + + :/preset-load.png:/preset-load.png + + + + + + + ... + + + + + + + + + + + Play record file in a loop + + + ... + + + + :/playloop.png:/playloop.png + + + + + + + Record file play/pause + + + ... + + + + :/play.png + :/pause.png + :/play.png + :/play.png:/play.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + + + + + false + + + + 90 + 0 + + + + Record time from start + + + 00:00:00.000 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Vertical + + + + + + + false + + + + 60 + 0 + + + + Total record time + + + 00:00:00 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + Record file time navigator + + + 100 + + + 1 + + + Qt::Horizontal + + + + + - - RollupWidget - QWidget -
gui/rollupwidget.h
- 1 -
ValueDial QWidget
gui/valuedial.h
1
+ + ButtonSwitch + QToolButton +
gui/buttonswitch.h
+
+ + RollupWidget + QWidget +
gui/rollupwidget.h
+ 1 +
diff --git a/plugins/channeltx/modam/ammodplugin.cpp b/plugins/channeltx/modam/ammodplugin.cpp index 37c74d132..90b6b410c 100644 --- a/plugins/channeltx/modam/ammodplugin.cpp +++ b/plugins/channeltx/modam/ammodplugin.cpp @@ -23,7 +23,7 @@ const PluginDescriptor AMModPlugin::m_pluginDescriptor = { QString("AM Modulator"), - QString("2.2.1"), + QString("2.3.1"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, diff --git a/plugins/samplesource/rtlsdr/CMakeLists.txt b/plugins/samplesource/rtlsdr/CMakeLists.txt index 22c833d0d..7e127242d 100644 --- a/plugins/samplesource/rtlsdr/CMakeLists.txt +++ b/plugins/samplesource/rtlsdr/CMakeLists.txt @@ -31,7 +31,7 @@ else (BUILD_DEBIAN) include_directories( . ${CMAKE_CURRENT_BINARY_DIR} - ${LIBRTLSDRSRC}/include + ${LIBRTLSDR_INCLUDE_DIR} ) endif (BUILD_DEBIAN) diff --git a/sdrbase/gui/aboutdialog.ui b/sdrbase/gui/aboutdialog.ui index 259b9fe88..df87ec799 100644 --- a/sdrbase/gui/aboutdialog.ui +++ b/sdrbase/gui/aboutdialog.ui @@ -84,7 +84,7 @@ - <html><head/><body><p>Version 2.3.0 - Copyright (C) 2015-2016 Edouard Griffiths, F4EXB. </p><p>Code at <a href="https://github.com/f4exb/sdrangel"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/f4exb/sdrangel</span></a> This is a complete redesign from RTL-SDRangelove at <a href="https://github.com/hexameron/rtl-sdrangelove"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/hexameron/rtl-sdrangelove</span></a></p><p>Many thanks to the original developers:</p><p>The osmocom developer team - especially horizon, Hoernchen &amp; tnt.</p><p>Christian Daniel from maintech GmbH.</p><p>John Greb (hexameron) for the contributions in RTL-SDRangelove</p><p>The following rules apply to the SDRangel main application and libsdrbase:<br/>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; either version 2 of the License, or (at your option) any later version. 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. You should have received a copy of the GNU General Public License along with this program. If not, see <a href="http://www.gnu.org/licenses/"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/</span></a>.</p><p>For the license of installed plugins, look into the plugin list.</p></body></html> + <html><head/><body><p>Version 2.3.1 - Copyright (C) 2015-2016 Edouard Griffiths, F4EXB. </p><p>Code at <a href="https://github.com/f4exb/sdrangel"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/f4exb/sdrangel</span></a> This is a complete redesign from RTL-SDRangelove at <a href="https://github.com/hexameron/rtl-sdrangelove"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/hexameron/rtl-sdrangelove</span></a></p><p>Many thanks to the original developers:</p><p>The osmocom developer team - especially horizon, Hoernchen &amp; tnt.</p><p>Christian Daniel from maintech GmbH.</p><p>John Greb (hexameron) for the contributions in RTL-SDRangelove</p><p>The following rules apply to the SDRangel main application and libsdrbase:<br/>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; either version 2 of the License, or (at your option) any later version. 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. You should have received a copy of the GNU General Public License along with this program. If not, see <a href="http://www.gnu.org/licenses/"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/</span></a>.</p><p>For the license of installed plugins, look into the plugin list.</p></body></html> true diff --git a/sdrbase/mainwindow.cpp b/sdrbase/mainwindow.cpp index ffda2f864..a0295e137 100644 --- a/sdrbase/mainwindow.cpp +++ b/sdrbase/mainwindow.cpp @@ -450,7 +450,7 @@ void MainWindow::savePresetSettings(Preset* preset, int tabIndex) void MainWindow::createStatusBar() { QString qtVersionStr = QString("Qt %1 ").arg(QT_VERSION_STR); - m_showSystemWidget = new QLabel("SDRangel v2.3.0 " + qtVersionStr + QSysInfo::prettyProductName(), this); + m_showSystemWidget = new QLabel("SDRangel v2.3.1 " + qtVersionStr + QSysInfo::prettyProductName(), this); statusBar()->addPermanentWidget(m_showSystemWidget); m_dateTimeWidget = new QLabel(tr("Date"), this); diff --git a/sdrbase/resources/microphone.png b/sdrbase/resources/microphone.png new file mode 100644 index 0000000000000000000000000000000000000000..28f6eaeed2e11cf2d829bcc73faae8008e490845 GIT binary patch literal 1078 zcmV-61j+k}P)WzNS)eq{O>)oqeCW+gZf=76;BwEo z_xpa|Ip3e(Ih0PH66h8NK&?rsRN^~#Y}~%R8n!G;tgim-%*@QnOeRgP>-Mu{@*I%& zu=nGE!tn4gu3h_<8;!;rx~^vcSj@b6aB%QtEEfCa+_{&GN~MAz+ja+9o5BMb9E>8H zU2>WEa{x2G-*v}vUNlW}`OKMTb!JA8Xl>rQB%57w9jBHK00)49a5(%`p^zWk+1U;< zCjhLWw-5k?LIdaf=tNJRe0torH#i6!ZK0uF3e0TvTLcjzz6iAE5?ViS4}tnP(0u0P zcc%MtKmeGCu)Td4S7t5(7zCjF0Lcs-xLm1pLwLFmDA`#rskPB@&MU0GiF_+eGx#*|X1Ix_H%90Q?2u9{|O@ zy}f4~$0>$Fp^pJ5+qU0ri^zX~L3AC9#b|OeBQ9Kc>kA@!jhUAljryni`_&DAH6l&K zVzG>27;^v;j#GQVG$Tt>QyJZHoQ|`hCta6HCCtx%XiQJPJTHWJ&r9fiuK-K{7Jy2% zy8p_F6JtLmlaE14_y5!N$jAt;T>0A7b$#yMy`7|#@)K{D31(iCQqB@lJQ|JtkW40n zz{!821u7VZftxq;5&$cuvPATp<2X~MX%(aK@F+M(~N2Ae)qw8F5h0Epglg#X}Cz_^B0~jz(bEWl7DRp&j?gQhY z=o$blD*~ltomqVkP&|N90f3ZJzcm`oKyUzx(&k7Ohg2|U&Q1@=$w*?q>~1^@s607*qoM6N<$f=ZF{X8-^I literal 0 HcmV?d00001 diff --git a/sdrbase/resources/res.qrc b/sdrbase/resources/res.qrc index c59b33f70..ceb6f6791 100644 --- a/sdrbase/resources/res.qrc +++ b/sdrbase/resources/res.qrc @@ -1,5 +1,6 @@ + microphone.png checkmark.png questionmark.png res.qrc