diff options
author | Scott Murray <scott.murray@konsulko.com> | 2023-01-03 00:58:28 -0500 |
---|---|---|
committer | Scott Murray <scott.murray@konsulko.com> | 2023-01-10 16:09:53 -0500 |
commit | 22ad8cbaad00d89361cbd92023dd20a807bcf5cb (patch) | |
tree | 5c1a8242166270e188e4a0e87ecc4aced2f9b7de | |
parent | ce49ef384541220a110eda598b8980b11eb19160 (diff) |
Rework radio support for new gRPC API
Update the stubbed out radio support library to use the new gRPC API.
The "Radio" Qt wrapper object has been renamed to "RadioClient" to
avoid conflicting with the generated gRPC API code. This somewhat
aligns with the naming that has been used with the AppLauncher
support.
Bug-AGL: SPEC-4665
Signed-off-by: Scott Murray <scott.murray@konsulko.com>
Change-Id: I642f9b9b62d6981cf5231ecea4caddba713f493a
-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 |