diff options
author | Tasuku Suzuki <tasuku.suzuki@qt.io> | 2016-07-19 22:49:40 +0900 |
---|---|---|
committer | Tasuku Suzuki <tasuku.suzuki@qt.io> | 2016-07-19 22:49:40 +0900 |
commit | ddfe5552b3297236effc42f0c73e8b69654c976c (patch) | |
tree | 58290a7ed8035a468393c1dd63357d8f1d300133 /rtlfmradiotunercontrol.cpp | |
parent | 02670272224eb2ce73a5470441131861aa3cfb91 (diff) |
initial commit for ALS2016
Change-Id: If170e059c9be053117e31afd5ae4b7cfa810aa1b
Diffstat (limited to 'rtlfmradiotunercontrol.cpp')
-rw-r--r-- | rtlfmradiotunercontrol.cpp | 345 |
1 files changed, 345 insertions, 0 deletions
diff --git a/rtlfmradiotunercontrol.cpp b/rtlfmradiotunercontrol.cpp new file mode 100644 index 0000000..83096b6 --- /dev/null +++ b/rtlfmradiotunercontrol.cpp @@ -0,0 +1,345 @@ +/* Copyright (C) 2016, The Qt Company Ltd. All Rights Reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "rtlfmradiotunercontrol.h" + +#include <QtCore/QDebug> +#include <QtCore/QTimer> +#include <QtCore/QProcess> + +class RtlFmRadioTunerControl::Private +{ +public: + Private(RtlFmRadioTunerControl *parent); + ~Private(); + +private: + RtlFmRadioTunerControl *q; + +public: + QRadioTuner::State state; + QRadioTuner::Band band; + int frequency; + QRadioTuner::StereoMode stereoMode; + int signalStrength; + int volume; + bool muted; + bool searching; + QRadioTuner::Error error; + QString errorString; + QTimer timer; + bool searchOne; + int step; + + QProcess rtlFm; + QProcess aplay; + +private: + QMap<int, QString> amFrequenciesTokyo = { + { 594000, QString::fromUtf8("NHK Tokyo #1") } + , { 693000, QString::fromUtf8("NHK Tokyo #2") } + , { 810000, QString::fromUtf8("Eagle 810 (AFN TOKYO)") } + , { 954000, QString::fromUtf8("TBS Radio Tokyo") } + , { 1134000, QString::fromUtf8("Nippon Cultural Broadcasting") } + , { 1242000, QString::fromUtf8("Nippon Broadcasting") } + }; + + QMap<int, QString> fmFrequenciesTokyo = { + { 76100, QString::fromUtf8("Inter FM") } + , { 77100, QString::fromUtf8("The Open University of Japan") } + , { 80000, QString::fromUtf8("TOKYO FM") } + , { 81300, QString::fromUtf8("J-WAVE") } + , { 82500, QString::fromUtf8("NHK FM Tokyo") } + }; +}; + +RtlFmRadioTunerControl::Private::Private(RtlFmRadioTunerControl *parent) + : q(parent) + , state(QRadioTuner::StoppedState) + , band(QRadioTuner::FM) + , frequency(76100) + , stereoMode(QRadioTuner::Auto) + , signalStrength(100) + , volume(50) + , muted(false) + , searching(false) + , error(QRadioTuner::NoError) + , searchOne(true) + , step(0) +{ + connect(q, &RtlFmRadioTunerControl::stationFound, [this](int frequency, const QString &name) { + qDebug() << frequency << name; + if (rtlFm.state() != QProcess::NotRunning) + q->start(); + }); + connect(q, &RtlFmRadioTunerControl::frequencyChanged, [this](int frequency) { + QMap<int, QString> knownBands; + switch (band) { + case QRadioTuner::AM: + knownBands = amFrequenciesTokyo; + break; + case QRadioTuner::FM: + knownBands = fmFrequenciesTokyo; + break; + default: + qFatal("%s:%d %d not supported", Q_FUNC_INFO, __LINE__, band); + break; + } + if (knownBands.contains(frequency)) { + emit q->stationFound(frequency, knownBands.value(frequency)); + if (timer.isActive() && searchOne) + timer.stop(); + } + }); + connect(&timer, &QTimer::timeout, [this]() { + q->setFrequency(frequency + step); + }); + + connect(&rtlFm, &QProcess::readyReadStandardOutput, [this]() { + aplay.write(rtlFm.readAllStandardOutput()); + }); + connect(&rtlFm, &QProcess::readyReadStandardError, [this]() { + qDebug() << rtlFm.readAllStandardError(); + }); +} + +RtlFmRadioTunerControl::Private::~Private() +{ + aplay.kill(); + aplay.waitForFinished(); + rtlFm.kill(); + rtlFm.waitForFinished(); +} + +RtlFmRadioTunerControl::RtlFmRadioTunerControl(QObject *parent) + : QRadioTunerControl(parent) + , d(new Private(this)) +{ +} + +RtlFmRadioTunerControl::~RtlFmRadioTunerControl() +{ + delete d; +} + +QRadioTuner::State RtlFmRadioTunerControl::state() const +{ + return d->state; +} + +QRadioTuner::Band RtlFmRadioTunerControl::band() const +{ + return d->band; +} + +void RtlFmRadioTunerControl::setBand(QRadioTuner::Band band) +{ + if (d->band == band) return; + d->band = band; + emit bandChanged(band); +} + +bool RtlFmRadioTunerControl::isBandSupported(QRadioTuner::Band band) const +{ + switch (band) { + case QRadioTuner::AM: + case QRadioTuner::FM: + return true; + default: + break; + } + return false; +} + +int RtlFmRadioTunerControl::frequency() const +{ + return d->frequency; +} + +int RtlFmRadioTunerControl::frequencyStep(QRadioTuner::Band band) const +{ + int ret = 0; + switch (band) { + case QRadioTuner::AM: + ret = 1000; // 1kHz + break; + case QRadioTuner::FM: + ret = 100; // 100Hz + break; + default: + break; + } + return ret; +} + +QPair<int,int> RtlFmRadioTunerControl::frequencyRange(QRadioTuner::Band band) const +{ + QPair<int,int> ret; + switch (band) { + case QRadioTuner::AM: + ret = qMakePair<int,int>(594000, 1242000); + break; + case QRadioTuner::FM: + ret = qMakePair<int,int>(76100, 82500); + break; + default: + break; + } + return ret; +} + +void RtlFmRadioTunerControl::setFrequency(int frequency) +{ + QPair<int,int> range = frequencyRange(d->band); + frequency = qBound(range.first, frequency, range.second); + if (d->frequency == frequency) { + if (d->timer.isActive()) + d->timer.stop(); + return; + } + d->frequency = frequency; + emit frequencyChanged(frequency); +} + +bool RtlFmRadioTunerControl::isStereo() const +{ + bool ret = false; + switch (d->stereoMode) { + case QRadioTuner::ForceStereo: + case QRadioTuner::Auto: + ret = true; + break; + default: + break; + } + return ret; +} + +QRadioTuner::StereoMode RtlFmRadioTunerControl::stereoMode() const +{ + return d->stereoMode; +} + +void RtlFmRadioTunerControl::setStereoMode(QRadioTuner::StereoMode stereoMode) +{ + if (d->stereoMode == stereoMode) return; + bool prevStereo = isStereo(); + d->stereoMode = stereoMode; + bool currentStereo = isStereo(); + if (prevStereo != currentStereo) + emit stereoStatusChanged(currentStereo); +} + +int RtlFmRadioTunerControl::signalStrength() const +{ + return d->signalStrength; +} + +int RtlFmRadioTunerControl::volume() const +{ + return d->volume; +} + +void RtlFmRadioTunerControl::setVolume(int volume) +{ + volume = qBound(0, volume, 100); + if (d->volume == volume) return; + d->volume = volume; + emit volumeChanged(volume); +} + +bool RtlFmRadioTunerControl::isMuted() const +{ + return d->muted; +} + +void RtlFmRadioTunerControl::setMuted(bool muted) +{ + if (d->muted == muted) return; + d->muted = muted; + emit mutedChanged(muted); +} + +bool RtlFmRadioTunerControl::isSearching() const +{ + return d->searching; +} + +void RtlFmRadioTunerControl::searchForward() +{ + d->searchOne = true; + d->step = frequencyStep(d->band); + d->timer.start(100); + setSearching(true); +} + +void RtlFmRadioTunerControl::searchBackward() +{ + d->searchOne = true; + d->step = -frequencyStep(d->band); + d->timer.start(250); + setSearching(true); +} + +void RtlFmRadioTunerControl::searchAllStations(QRadioTuner::SearchMode searchMode) +{ + Q_UNUSED(searchMode) + d->searchOne = false; + d->frequency = frequencyRange(d->band).first; + d->step = frequencyStep(d->band); + d->timer.start(250); + setSearching(true); +} + +void RtlFmRadioTunerControl::cancelSearch() +{ + d->timer.stop(); + setSearching(false); +} + +void RtlFmRadioTunerControl::setSearching(bool searching) +{ + if (d->searching == searching) return; + d->searching = searching; + emit searchingChanged(searching); +} + +void RtlFmRadioTunerControl::start() +{ + stop(); + d->aplay.start(QStringLiteral("aplay"), QStringList() << QStringLiteral("-r") << QStringLiteral("48000") << QStringLiteral("-f") << QStringLiteral("S16_LE")); + d->aplay.waitForStarted(); +// d->rtlFm.start(QStringLiteral("sudo"), QStringList() << QStringLiteral("rtl_fm -f %1 -M wbfm -s 200000 -r 48000").arg(d->frequency * 1000).split(" ")); + d->rtlFm.start(QStringLiteral("rtl_fm"), QStringList() << QStringLiteral("-f %1 -M wbfm -s 200000 -r 48000").arg(d->frequency * 1000).split(" ")); + d->rtlFm.waitForStarted(); + d->state = QRadioTuner::ActiveState; +} + +void RtlFmRadioTunerControl::stop() +{ + d->aplay.kill(); + d->aplay.waitForFinished(); + d->rtlFm.kill(); + d->rtlFm.waitForFinished(); + d->state = QRadioTuner::StoppedState; +} + +QRadioTuner::Error RtlFmRadioTunerControl::error() const +{ + return d->error; +} + +QString RtlFmRadioTunerControl::errorString() const +{ + return d->errorString; +} + +void RtlFmRadioTunerControl::setError(QRadioTuner::Error error, const QString &errorString) +{ + d->error = error; + d->errorString = errorString; + emit QRadioTunerControl::error(error); +} |