diff options
-rw-r--r-- | radio/RadioClient.cpp | 142 | ||||
-rw-r--r-- | radio/RadioClient.h (renamed from radio/radio.h) | 61 | ||||
-rw-r--r-- | radio/RadioGrpcClient.cpp | 213 | ||||
-rw-r--r-- | radio/RadioGrpcClient.h | 67 | ||||
-rw-r--r-- | radio/meson.build | 43 | ||||
-rw-r--r-- | radio/protos/radio.proto | 205 | ||||
-rw-r--r-- | radio/radio.cpp | 294 |
7 files changed, 695 insertions, 330 deletions
diff --git a/radio/RadioClient.cpp b/radio/RadioClient.cpp new file mode 100644 index 0000000..a142d22 --- /dev/null +++ b/radio/RadioClient.cpp @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2018-2020,2022 Konsulko Group + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <QDebug> +#include "RadioClient.h" +#include "RadioGrpcClient.h" + +RadioClient::RadioClient(QQmlContext *context, QObject * parent) : + QObject(parent), + m_band(1), + m_frequency(0), + m_minFrequency(0), + m_maxFrequency(0), + m_playing(false), + m_scanning(false) +{ + m_radio = new RadioGrpcClient(this); + + if (m_radio) { + m_radio->GetBandParameters(m_band, m_minFrequency, m_maxFrequency, m_frequencyStep); + emit minFrequencyChanged(m_minFrequency); + emit maxFrequencyChanged(m_maxFrequency); + emit frequencyStepChanged(m_frequencyStep); + + // Handle start up + if (!m_frequency) { + m_frequency = m_minFrequency; + emit frequencyChanged(m_frequency); + } + } +} + +RadioClient::~RadioClient() +{ + delete m_radio; +} + +void RadioClient::setBand(int band) +{ + if (m_radio) + m_radio->SetBand(band); +} + +void RadioClient::setFrequency(int frequency) +{ + if (!m_radio) + return; + + m_radio->SetFrequency(frequency); + + // To improve UI responsiveness, signal the change here immediately + // This fixes visual glitchiness in the slider caused by the frequency + // update event taking long enough that the QML engine gets a chance + // to update the slider with the current value before the event with + // the new value comes. + m_frequency = frequency; + emit frequencyChanged(m_frequency); +} + +// control related methods + +void RadioClient::start() +{ + if (m_radio) + m_radio->Start(); +} + +void RadioClient::stop() +{ + if (m_radio) + m_radio->Stop(); +} + +void RadioClient::scanForward() +{ + if (!m_radio || m_scanning) + return; + + m_radio->ScanForward(); + + m_scanning = true; + emit scanningChanged(m_scanning); +} + +void RadioClient::scanBackward() +{ + if (!m_radio || m_scanning) + return; + + m_radio->ScanBackward(); + + m_scanning = true; + emit scanningChanged(m_scanning); +} + +void RadioClient::scanStop() +{ + if (m_radio) + m_radio->ScanStop(); + + m_scanning = false; + emit scanningChanged(m_scanning); +} + +void RadioClient::updateBand(int band) +{ + m_band = band; + emit bandChanged(m_band); +} + +void RadioClient::updateFrequency(int frequency) +{ + m_frequency = frequency; + emit frequencyChanged(m_frequency); +} + +void RadioClient::updatePlaying(bool status) +{ + m_playing = status; + emit playingChanged(m_playing); +} + +void RadioClient::updateScanning(int station_found) +{ + if (station_found && m_scanning) { + m_scanning = false; + emit scanningChanged(m_scanning); + } +} diff --git a/radio/radio.h b/radio/RadioClient.h index cfd314c..5920442 100644 --- a/radio/radio.h +++ b/radio/RadioClient.h @@ -14,28 +14,30 @@ * limitations under the License. */ -#ifndef RADIO_H -#define RADIO_H +#ifndef RADIO_CLIENT_H +#define RADIO_CLIENT_H #include <QObject> #include <QtQml/QQmlContext> -class Radio : public QObject +class RadioGrpcClient; + +class RadioClient : public QObject { - Q_OBJECT - Q_PROPERTY(unsigned int band READ band WRITE setBand NOTIFY bandChanged) - Q_PROPERTY(unsigned int amBand READ amBand CONSTANT) - Q_PROPERTY(unsigned int fmBand READ fmBand CONSTANT) - Q_PROPERTY(unsigned int frequency READ frequency WRITE setFrequency NOTIFY frequencyChanged) - Q_PROPERTY(bool playing READ playing NOTIFY playingChanged) - Q_PROPERTY(bool scanning READ scanning NOTIFY scanningChanged) - Q_PROPERTY(unsigned int minFrequency READ minFrequency NOTIFY minFrequencyChanged) - Q_PROPERTY(unsigned int maxFrequency READ maxFrequency NOTIFY maxFrequencyChanged) - Q_PROPERTY(unsigned int frequencyStep READ frequencyStep NOTIFY frequencyStepChanged) - - public: - explicit Radio(QQmlContext *context, QObject * parent = Q_NULLPTR); - virtual ~Radio(); + Q_OBJECT + Q_PROPERTY(unsigned int band READ band WRITE setBand NOTIFY bandChanged) + Q_PROPERTY(unsigned int amBand READ amBand CONSTANT) + Q_PROPERTY(unsigned int fmBand READ fmBand CONSTANT) + Q_PROPERTY(unsigned int frequency READ frequency WRITE setFrequency NOTIFY frequencyChanged) + Q_PROPERTY(bool playing READ playing NOTIFY playingChanged) + Q_PROPERTY(bool scanning READ scanning NOTIFY scanningChanged) + Q_PROPERTY(unsigned int minFrequency READ minFrequency NOTIFY minFrequencyChanged) + Q_PROPERTY(unsigned int maxFrequency READ maxFrequency NOTIFY maxFrequencyChanged) + Q_PROPERTY(unsigned int frequencyStep READ frequencyStep NOTIFY frequencyStepChanged) + +public: + explicit RadioClient(QQmlContext *context, QObject * parent = Q_NULLPTR); + virtual ~RadioClient(); unsigned int band() const { return m_band; } void setBand(int band); @@ -61,7 +63,13 @@ class Radio : public QObject Q_INVOKABLE void scanBackward(); Q_INVOKABLE void scanStop(); - signals: +public slots: + void updateBand(int band); + void updateFrequency(int frequency); + void updatePlaying(bool status); + void updateScanning(int station_found); + +signals: void bandChanged(int band); void frequencyChanged(int frequency); void playingChanged(bool status); @@ -70,9 +78,11 @@ class Radio : public QObject void maxFrequencyChanged(int maxFrequency); void frequencyStepChanged(int frequencyStep); - private: +private: QQmlContext *m_context; + RadioGrpcClient *m_radio; + unsigned int m_band; unsigned int m_frequency; unsigned int m_minFrequency; @@ -80,19 +90,6 @@ class Radio : public QObject unsigned int m_frequencyStep; bool m_playing; bool m_scanning; - - void updateFrequencyBandParameters(); -#if 0 - void onConnected(); - void onDisconnected(); - void onMessageReceived(std::shared_ptr<Message> msg); - - const QStringList events { - "frequency", - "station_found", - "status", - }; -#endif }; #endif // RADIO_H diff --git a/radio/RadioGrpcClient.cpp b/radio/RadioGrpcClient.cpp new file mode 100644 index 0000000..3795d1d --- /dev/null +++ b/radio/RadioGrpcClient.cpp @@ -0,0 +1,213 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright (C) 2023 Konsulko Group + */ + +#include <QDebug> +#include "RadioGrpcClient.h" +#include "RadioClient.h" + +using grpc::Channel; +using grpc::ClientContext; +using grpc::ClientReader; +using grpc::Status; + +using automotivegradelinux::Radio; +using automotivegradelinux::SetBandRequest; +using automotivegradelinux::SetBandResponse; +using automotivegradelinux::SetFrequencyRequest; +using automotivegradelinux::SetFrequencyResponse; +using automotivegradelinux::StartRequest; +using automotivegradelinux::StartResponse; +using automotivegradelinux::StopRequest; +using automotivegradelinux::StopResponse; +using automotivegradelinux::ScanStartRequest; +using automotivegradelinux::ScanStartResponse; +using automotivegradelinux::ScanStopRequest; +using automotivegradelinux::ScanStopResponse; +using automotivegradelinux::GetBandParametersRequest; +using automotivegradelinux::GetBandParametersResponse; +using automotivegradelinux::StatusRequest; +using automotivegradelinux::StatusResponse; +using automotivegradelinux::BandStatus; +using automotivegradelinux::FrequencyStatus; +using automotivegradelinux::PlayStatus; +using automotivegradelinux::ScanStatus; + +// Enum values used +using automotivegradelinux::BAND_AM; +using automotivegradelinux::BAND_FM; +using automotivegradelinux::SCAN_DIRECTION_FORWARD; +using automotivegradelinux::SCAN_DIRECTION_BACKWARD; + +void RadioStatusEventReader::GetStatusEvents() +{ + ClientContext context; + StatusRequest request; + StatusResponse response; + + std::unique_ptr<ClientReader<StatusResponse> > reader(stub_->GetStatusEvents(&context, request)); + while (reader->Read(&response)) { + if (response.has_band()) { + BandStatus band_status = response.band(); + unsigned int band; + if (band_status.band() == BAND_AM) + band = 0; + else if (band_status.band() == BAND_FM) + band = 1; + else + continue; + emit bandUpdate(band); + } else if (response.has_frequency()) { + FrequencyStatus frequency_status = response.frequency(); + emit frequencyUpdate(frequency_status.frequency()); + } else if (response.has_play()) { + PlayStatus play_status = response.play(); + emit playingUpdate(play_status.playing()); + } else if (response.has_scan()) { + ScanStatus scan_status = response.scan(); + emit scanningUpdate(scan_status.station_found()); + } + } + Status status = reader->Finish(); + if (!status.ok()) { + qWarning() << "GetStatusEvents RPC failed"; + } + + emit finished(); +} + + +RadioGrpcClient::RadioGrpcClient(QObject *parent) : QObject(parent) +{ + stub_ = Radio::NewStub(grpc::CreateChannel("localhost:50053", grpc::InsecureChannelCredentials())); + + // Create thread to read status events + RadioStatusEventReader *reader = new RadioStatusEventReader(stub_); + reader->moveToThread(&m_event_thread); + connect(&m_event_thread, &QThread::started, reader, &RadioStatusEventReader::GetStatusEvents); + connect(reader, &RadioStatusEventReader::finished, &m_event_thread, &QThread::quit); + // FIXME: Normally the thread finishing would be connected per the below + // to trigger cleaning up the object. That seems to trigger a crash + // for not entirely obvious reasons. It seems unrelated to the signal + // connection to AppLauncherClient, as not connecting does not prevent + // the crash; further investigation is required. + //connect(reader, &RadioStatusEventReader::finished, reader, &RadioStatusEventReader::deleteLater); + //connect(&m_event_thread, &QThread::finished, &m_event_thread, &QThread::deleteLater); + + // To avoid having intermediary slot+signal's in this class, try + // casting parent to Radio and connect directly to its slot. + // Callers should set parent to ensure this works as required. + if (parent) { + RadioClient *radio = qobject_cast<RadioClient*>(parent); + if (radio) { + connect(reader, + &RadioStatusEventReader::bandUpdate, + radio, + &RadioClient::updateBand); + connect(reader, + &RadioStatusEventReader::frequencyUpdate, + radio, + &RadioClient::updateFrequency); + connect(reader, + &RadioStatusEventReader::playingUpdate, + radio, + &RadioClient::updatePlaying); + connect(reader, + &RadioStatusEventReader::scanningUpdate, + radio, + &RadioClient::updateScanning); + } + } + + // Start status event handling + m_event_thread.start(); +} + +void RadioGrpcClient::SetBand(unsigned int band) +{ + SetBandRequest request; + + ClientContext context; + SetBandResponse response; + if (band) + request.set_band(BAND_FM); + else + request.set_band(BAND_AM); + Status status = stub_->SetBand(&context, request, &response); +} + +void RadioGrpcClient::SetFrequency(unsigned int frequency) +{ + SetFrequencyRequest request; + + ClientContext context; + SetFrequencyResponse response; + request.set_frequency(frequency); + Status status = stub_->SetFrequency(&context, request, &response); +} + +void RadioGrpcClient::Start() +{ + StartRequest request; + + ClientContext context; + StartResponse response; + Status status = stub_->Start(&context, request, &response); +} + +void RadioGrpcClient::Stop() +{ + StopRequest request; + + ClientContext context; + StopResponse response; + Status status = stub_->Stop(&context, request, &response); +} + +void RadioGrpcClient::ScanForward() +{ + ScanStartRequest request; + + ClientContext context; + ScanStartResponse response; + request.set_direction(SCAN_DIRECTION_FORWARD); + Status status = stub_->ScanStart(&context, request, &response); +} + +void RadioGrpcClient::ScanBackward() +{ + ScanStartRequest request; + + ClientContext context; + ScanStartResponse response; + request.set_direction(SCAN_DIRECTION_BACKWARD); + Status status = stub_->ScanStart(&context, request, &response); +} + +void RadioGrpcClient::ScanStop() +{ + ScanStopRequest request; + + ClientContext context; + ScanStopResponse response; + Status status = stub_->ScanStop(&context, request, &response); +} + +void RadioGrpcClient::GetBandParameters(unsigned int band, unsigned int &min, unsigned int &max, unsigned int &step) +{ + GetBandParametersRequest request; + + ClientContext context; + GetBandParametersResponse response; + if (band) + request.set_band(BAND_FM); + else + request.set_band(BAND_AM); + Status status = stub_->GetBandParameters(&context, request, &response); + if (status.ok()) { + min = response.min(); + max = response.max(); + step = response.step(); + } +} diff --git a/radio/RadioGrpcClient.h b/radio/RadioGrpcClient.h new file mode 100644 index 0000000..603253a --- /dev/null +++ b/radio/RadioGrpcClient.h @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright (C) 2023 Konsulko Group + */ + +#ifndef RADIO_GRPC_CLIENT_H +#define RADIO_GRPC_CLIENT_H + +#include <QObject> +#include <QList> +#include <QMap> +#include <QThread> +#include <grpcpp/grpcpp.h> + +#include "radio.grpc.pb.h" + +using grpc::Channel; + +class RadioStatusEventReader : public QObject +{ + Q_OBJECT +public: + RadioStatusEventReader(std::shared_ptr<automotivegradelinux::Radio::Stub> &stub, + QObject *parent = Q_NULLPTR) : QObject(parent), stub_(stub) {} + +public slots: + void GetStatusEvents(); + +signals: + void bandUpdate(int band); + void frequencyUpdate(int frequency); + void playingUpdate(bool status); + void scanningUpdate(bool scanning); + + void finished(); + +private: + std::shared_ptr<automotivegradelinux::Radio::Stub> stub_; +}; + +class RadioGrpcClient : public QObject +{ + Q_OBJECT + +public: + RadioGrpcClient(QObject *parent = Q_NULLPTR); + + void SetBand(unsigned int band); + void SetFrequency(unsigned int frequency); + void Start(); + void Stop(); + void ScanForward(); + void ScanBackward(); + void ScanStop(); + void GetBandParameters(unsigned int band, + unsigned int &min, + unsigned int &max, + unsigned int &step); + +private: + std::shared_ptr<automotivegradelinux::Radio::Stub> stub_; + + QThread m_event_thread; + +}; + +#endif // RADIO_GRPC_CLIENT_H diff --git a/radio/meson.build b/radio/meson.build index c8218a3..7ae1bac 100644 --- a/radio/meson.build +++ b/radio/meson.build @@ -1,17 +1,52 @@ +cpp = meson.get_compiler('cpp') +grpcpp_reflection_dep = cpp.find_library('grpc++_reflection') + qt5_dep = dependency('qt5', modules: ['Qml']) +radio_dep = [ + qt5_dep, + dependency('protobuf'), + dependency('grpc'), + dependency('grpc++'), + grpcpp_reflection_dep, +] + +protoc = find_program('protoc') +grpc_cpp = find_program('grpc_cpp_plugin') + +protoc_gen = generator(protoc, \ + output : ['@BASENAME@.pb.cc', '@BASENAME@.pb.h'], + arguments : ['--proto_path=@CURRENT_SOURCE_DIR@/protos', + '--cpp_out=@BUILD_DIR@', + '@INPUT@']) +generated_protoc_sources = protoc_gen.process('protos/radio.proto') -moc_files = qt5.compile_moc(headers: 'radio.h', +grpc_gen = generator(protoc, \ + output : ['@BASENAME@.grpc.pb.cc', '@BASENAME@.grpc.pb.h'], + arguments : ['--proto_path=@CURRENT_SOURCE_DIR@/protos', + '--grpc_out=@BUILD_DIR@', + '--plugin=protoc-gen-grpc=' + grpc_cpp.path(), + '@INPUT@']) +generated_grpc_sources = grpc_gen.process('protos/radio.proto') + +moc_files = qt5.compile_moc(headers: ['RadioClient.h', 'RadioGrpcClient.h'], dependencies: qt5_dep) -src = ['radio.cpp', moc_files] +src = [ + 'RadioClient.cpp', + 'RadioGrpcClient.cpp', + generated_protoc_sources, + generated_grpc_sources, + moc_files +] + lib = shared_library('qtappfw-radio', sources: src, version: '1.0.0', soversion: '0', - dependencies: qt5_dep, + dependencies: radio_dep, install: true) -install_headers('radio.h') +install_headers('RadioClient.h') pkg_mod = import('pkgconfig') pkg_mod.generate(libraries : lib, diff --git a/radio/protos/radio.proto b/radio/protos/radio.proto new file mode 100644 index 0000000..60afc45 --- /dev/null +++ b/radio/protos/radio.proto @@ -0,0 +1,205 @@ +syntax = "proto3"; + +package automotivegradelinux; + +service Radio { + rpc GetFrequency(GetFrequencyRequest) returns (GetFrequencyResponse) {} + rpc SetFrequency(SetFrequencyRequest) returns (SetFrequencyResponse) {} + + rpc GetBand(GetBandRequest) returns (GetBandResponse) {} + rpc SetBand(SetBandRequest) returns (SetBandResponse) {} + + rpc GetBandSupported(GetBandSupportedRequest) returns (GetBandSupportedResponse) {} + rpc GetBandParameters(GetBandParametersRequest) returns (GetBandParametersResponse) {} + + rpc GetStereoMode(GetStereoModeRequest) returns (GetStereoModeResponse) {} + rpc SetStereoMode(SetStereoModeRequest) returns (SetStereoModeResponse) {} + + rpc Start(StartRequest) returns (StartResponse) {} + rpc Stop(StopRequest) returns (StopResponse) {} + + rpc ScanStart(ScanStartRequest) returns (ScanStartResponse) {} + rpc ScanStop(ScanStopRequest) returns (ScanStopResponse) {} + + rpc GetRDS(GetRDSRequest) returns (GetRDSResponse) {} + + rpc GetQuality(GetQualityRequest) returns (GetQualityResponse) {} + + rpc SetAlternativeFrequency(SetAlternativeFrequencyRequest) returns (SetAlternativeFrequencyResponse) {} + + rpc GetStatusEvents(StatusRequest) returns (stream StatusResponse) {} +} + +message GetFrequencyRequest { +} + +message GetFrequencyResponse { + uint32 frequency = 1; +} + +message SetFrequencyRequest { + uint32 frequency = 1; +} + +message SetFrequencyResponse { + uint32 frequency = 1; +} + +message GetBandRequest { +} + +enum Band { + BAND_UNSPECIFIED = 0; + BAND_AM = 1; + BAND_FM = 2; + BAND_DBS = 3; +} + +message GetBandResponse { + Band band = 1; +} + +message SetBandRequest { + Band band = 1; +} + +message SetBandResponse { + Band band = 1; +} + +message GetBandSupportedRequest { + Band band = 1; +} + +message GetBandSupportedResponse { + bool supported = 1; +} + +message GetBandParametersRequest { + Band band = 1; +} + +message GetBandParametersResponse { + uint32 min = 1; + uint32 max = 2; + uint32 step = 3; +} + +enum StereoMode { + STEREO_MODE_UNSPECIFIED = 0; + STEREO_MODE_MONO = 1; + STEREO_MODE_STEREO = 2; +} + +message GetStereoModeRequest { +} + +message GetStereoModeResponse { + StereoMode mode = 1; +} + +message SetStereoModeRequest { + StereoMode mode = 1; +} + +message SetStereoModeResponse { + StereoMode mode = 1; +} + +message StartRequest { +} + +message StartResponse { +} + +message StopRequest { +} + +message StopResponse { +} + +enum ScanDirection { + SCAN_DIRECTION_UNSPECIFIED = 0; + SCAN_DIRECTION_FORWARD = 1; + SCAN_DIRECTION_BACKWARD = 2; +} + +message ScanStartRequest { + ScanDirection direction = 1; +} + +message ScanStartResponse { +} + +message ScanStopRequest { +} + +message ScanStopResponse { +} + +message GetRDSRequest { +} + +// NOTE: This is a placeholder and will be revised! +message GetRDSResponse { + string name = 1; + string radio_text = 2; + string alternatives = 3; + string minute = 4; + string hour = 5; + string day = 6; + string month = 7; + string year = 8; + string pi = 9; + string pty = 10; + string ta = 11; + string tp = 12; + string ms = 13; +} + +message GetQualityRequest { +} + +message GetQualityResponse { +} + +message SetAlternativeFrequencyRequest { + uint32 frequency = 1; +} + +message SetAlternativeFrequencyResponse { + uint32 frequency = 1; +} + +message StatusRequest { +} + +message BandStatus { + Band band = 1; +} + +message FrequencyStatus { + uint32 frequency = 1; +} + +message PlayStatus { + bool playing = 1; +} + +message ScanStatus { + bool station_found = 1; +} + +message StereoStatus { + StereoMode mode = 1; +} + +message StatusResponse { + oneof status { + BandStatus band = 1; + FrequencyStatus frequency = 2; + PlayStatus play = 3; + StereoStatus stereo = 4; + ScanStatus scan = 5; + } +} diff --git a/radio/radio.cpp b/radio/radio.cpp deleted file mode 100644 index efe8e78..0000000 --- a/radio/radio.cpp +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright (C) 2018-2020,2022 Konsulko Group - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <QDebug> -#include "radio.h" - - -Radio::Radio(QQmlContext *context, QObject * parent) : - QObject(parent), - m_band(1), - m_frequency(0), - m_minFrequency(0), - m_maxFrequency(0), - m_playing(false), - m_scanning(false) -{ -#if 0 - m_mloop = MessageEngineFactory::getInstance().getMessageEngine(url); - m_context = context; - - QObject::connect(m_mloop.get(), &MessageEngine::connected, this, &Radio::onConnected); - QObject::connect(m_mloop.get(), &MessageEngine::disconnected, this, &Radio::onDisconnected); - QObject::connect(m_mloop.get(), &MessageEngine::messageReceived, this, &Radio::onMessageReceived); -#endif -} - -Radio::~Radio() -{ -} - -void Radio::setBand(int band) -{ -#if 0 - std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); - if (!msg) - return; - - CallMessage* rmsg = static_cast<CallMessage*>(msg.get()); - QJsonObject parameter; - - parameter.insert("band", band ? "FM": "AM"); - rmsg->createRequest("radio", "band", parameter); - m_mloop->sendMessage(std::move(msg)); -#endif -} - -void Radio::setFrequency(int frequency) -{ -#if 0 - std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); - if (!msg) - return; - - CallMessage* rmsg = static_cast<CallMessage*>(msg.get()); - QJsonObject parameter; - - if (m_scanning) - scanStop(); - - if (frequency == m_frequency) - return; - - parameter.insert("value", QString::number(frequency)); - rmsg->createRequest("radio", "frequency", parameter); - m_mloop->sendMessage(std::move(msg)); - - // To improve UI responsiveness, signal the change here immediately - // This fixes visual glitchiness in the slider caused by the frequency - // update event taking long enough that the QML engine gets a chance - // to update the slider with the current value before the event with - // the new value comes. - m_frequency = frequency; - emit frequencyChanged(m_frequency); -#endif -} - -// control related methods - -void Radio::start() -{ -#if 0 - std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); - if (!msg) - return; - - CallMessage* rmsg = static_cast<CallMessage*>(msg.get()); - QJsonObject parameter; - - rmsg->createRequest("radio", "start", parameter); - m_mloop->sendMessage(std::move(msg)); -#endif -} - -void Radio::stop() -{ -#if 0 - std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); - if (!msg) - return; - - CallMessage* rmsg = static_cast<CallMessage*>(msg.get()); - QJsonObject parameter; - rmsg->createRequest("radio", "stop", parameter); - m_mloop->sendMessage(std::move(msg)); -#endif -} - -void Radio::scanForward() -{ - if (m_scanning) - return; - -#if 0 - std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); - CallMessage* rmsg = static_cast<CallMessage*>(msg.get()); - QJsonObject parameter; - parameter.insert("direction", "forward"); - rmsg->createRequest("radio", "scan_start", parameter); - m_mloop->sendMessage(std::move(msg)); - - m_scanning = true; - emit scanningChanged(m_scanning); -#endif -} - -void Radio::scanBackward() -{ - if (m_scanning) - return; - -#if 0 - std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); - if (!msg) - return; - - CallMessage* rmsg = static_cast<CallMessage*>(msg.get()); - QJsonObject parameter; - parameter.insert("direction", "backward"); - rmsg->createRequest("radio", "scan_start", parameter); - m_mloop->sendMessage(std::move(msg)); - - m_scanning = true; - emit scanningChanged(m_scanning); -#endif -} - -void Radio::scanStop() -{ -#if 0 - std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); - if (!msg) - return; - - CallMessage* rmsg = static_cast<CallMessage*>(msg.get()); - QJsonObject parameter; - rmsg->createRequest("radio", "scan_stop", parameter); - m_mloop->sendMessage(std::move(msg)); - - m_scanning = false; - emit scanningChanged(m_scanning); -#endif -} - -void Radio::updateFrequencyBandParameters() -{ -#if 0 - std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); - if (!msg) - return; - - CallMessage* rmsg = static_cast<CallMessage*>(msg.get()); - QJsonObject parameter; - parameter.insert("band", m_band ? "FM" : "AM"); - rmsg->createRequest("radio", "frequency_range", parameter); - m_mloop->sendMessage(std::move(msg)); - - std::unique_ptr<Message> msg2 = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); - if (!msg2) - return; - - rmsg = static_cast<CallMessage*>(msg2.get()); - rmsg->createRequest("radio", "frequency_step", parameter); - m_mloop->sendMessage(std::move(msg2)); -#endif -} - -#if 0 -void Radio::onConnected() -{ - QStringListIterator eventIterator(events); - - while (eventIterator.hasNext()) { - std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); - if (!msg) - return; - - CallMessage* rmsg = static_cast<CallMessage*>(msg.get()); - QJsonObject parameter; - parameter.insert("value", eventIterator.next()); - rmsg->createRequest("radio", "subscribe", parameter); - m_mloop->sendMessage(std::move(msg)); - } - - // Trigger initial update of frequency band parameters (min/max/step) - updateFrequencyBandParameters(); -} - -void Radio::onDisconnected() -{ - QStringListIterator eventIterator(events); - - while (eventIterator.hasNext()) { - std::unique_ptr<Message> msg = MessageFactory::getInstance().createOutboundMessage(MessageId::Call); - if (!msg) - return; - - CallMessage* rmsg = static_cast<CallMessage*>(msg.get()); - QJsonObject parameter; - parameter.insert("value", eventIterator.next()); - rmsg->createRequest("radio", "unsubscribe", parameter); - m_mloop->sendMessage(std::move(msg)); - } -} - -void Radio::onMessageReceived(std::shared_ptr<Message> msg) -{ - if (!msg) - return; - - if (msg->isEvent()) { - std::shared_ptr<EventMessage> emsg = std::static_pointer_cast<EventMessage>(msg); - QString ename = emsg->eventName(); - QString eapi = emsg->eventApi(); - QJsonObject data = emsg->eventData(); - if (ename == "frequency") { - unsigned int frequency = data.value("value").toInt(); - m_frequency = frequency; - if (!m_scanning && (m_frequency != frequency)) { - emit frequencyChanged(m_frequency); - } - } else if (ename == "station_found") { - m_scanning = false; - emit scanningChanged(m_scanning); - - m_frequency = data.value("value").toInt(); - emit frequencyChanged(m_frequency); - } else if (ename == "status") { - if (data.value("value") == QString("playing")) { - m_playing = true; - emit playingChanged(m_playing); - } else if (data.value("value") == QString("stopped")) { - m_playing = false; - emit playingChanged(m_playing); - } - } - } else if (msg->isReply()) { - std::shared_ptr<ResponseMessage> rmsg = std::static_pointer_cast<ResponseMessage>(msg); - QString api = rmsg->requestApi(); - if (api != "radio") - return; - - QString verb = rmsg->requestVerb(); - QJsonObject data = rmsg->replyData(); - if (verb == "frequency_range") { - m_minFrequency = data.value("min").toInt(); - emit minFrequencyChanged(m_minFrequency); - m_maxFrequency = data.value("max").toInt(); - emit maxFrequencyChanged(m_maxFrequency); - - // Handle start up - if (!m_frequency) { - m_frequency = m_minFrequency; - emit frequencyChanged(m_frequency); - } - } else if (verb == "frequency_step") { - m_frequencyStep = data.value("step").toInt(); - emit frequencyStepChanged(m_frequencyStep); - } - } -} -#endif |