// SPDX-License-Identifier: Apache-2.0 /* * Copyright (C) 2023 Konsulko Group */ #include #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 > 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(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(); } }