From 52d467cb95400a9fe0a1c35f2df5ce84207b504a Mon Sep 17 00:00:00 2001 From: sebaszm Date: Tue, 26 Nov 2024 14:44:46 +0100 Subject: [PATCH] Move BluetoothRemoteControl to C++ IDL --- definitions/Definitions.cpp | 7 - definitions/definitions.h | 1 - interfaces/IBluetoothRemoteControl.h | 157 +++++++++++++++ interfaces/IVoiceHandler.h | 66 ------- interfaces/Ids.h | 5 +- interfaces/Interfaces.vcxproj | 1 - interfaces/Interfaces.vcxproj.filters | 3 - jsonrpc/BluetoothRemoteControl.json | 275 -------------------------- 8 files changed, 160 insertions(+), 355 deletions(-) create mode 100644 interfaces/IBluetoothRemoteControl.h delete mode 100644 interfaces/IVoiceHandler.h delete mode 100644 jsonrpc/BluetoothRemoteControl.json diff --git a/definitions/Definitions.cpp b/definitions/Definitions.cpp index 8a7b9329..ef2d0143 100644 --- a/definitions/Definitions.cpp +++ b/definitions/Definitions.cpp @@ -82,7 +82,6 @@ #include #include #include -#include #include #include #include @@ -154,12 +153,6 @@ ENUM_CONVERSION_BEGIN(Exchange::IStream::state) { Exchange::IStream::state::Error, _TXT(_T("Error")) }, ENUM_CONVERSION_END(Exchange::IStream::state) -ENUM_CONVERSION_BEGIN(Exchange::IVoiceProducer::IProfile::codec) - { Exchange::IVoiceProducer::IProfile::codec::UNDEFINED, _TXT(_T("undefined")) }, - { Exchange::IVoiceProducer::IProfile::codec::PCM, _TXT(_T("pcm")) }, - { Exchange::IVoiceProducer::IProfile::codec::ADPCM, _TXT(_T("adpcm")) }, -ENUM_CONVERSION_END(Exchange::IVoiceProducer::IProfile::codec) - ENUM_CONVERSION_BEGIN(Exchange::IPower::PCState) { Exchange::IPower::On, _TXT(_T("on")) }, { Exchange::IPower::ActiveStandby, _TXT(_T("active")) }, diff --git a/definitions/definitions.h b/definitions/definitions.h index cf41f436..e974563a 100644 --- a/definitions/definitions.h +++ b/definitions/definitions.h @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include diff --git a/interfaces/IBluetoothRemoteControl.h b/interfaces/IBluetoothRemoteControl.h new file mode 100644 index 00000000..8204a983 --- /dev/null +++ b/interfaces/IBluetoothRemoteControl.h @@ -0,0 +1,157 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 Metrological + * + * 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. + */ + +#pragma once + +#include "Module.h" + +namespace Thunder { + +namespace Exchange { + + // @json 1.0.0 @text:legacy_lowercase + struct EXTERNAL IBluetoothRemoteControl : virtual public Core::IUnknown { + + enum { ID = ID_BLUETOOTHREMOTECONTROL }; + + struct unitmetadata { + string name /* @brief Name of the unit */; + Core::OptionalType model /* @brief Model name */; + Core::OptionalType serial /* @brief Serial number */; + Core::OptionalType firmware /* @brief Fimrware version */; + Core::OptionalType software /* @brief Software versione */; + Core::OptionalType manufacturer /* @brief Vendor/manufacturer name */; + }; + + enum codectype : uint8_t { + PCM /* @text:pcm */, + IMA_ADPCM /* @text:ima-adpcm */ + }; + + struct audioprofile { + // Samples are always little endian signed integers + codectype codec /* @brief Compression method (pcm: uncompressed) */; + uint8_t channels /* @brief Number of audio channels (e.g. 1) */; + uint8_t resolution /* @brief Sample resultion in bits (e.g. 16) */; + uint32_t sampleRate /* @brief Sample rate in hertz (e.g. 16000) */; + }; + + // @event + struct INotification : virtual public Core::IUnknown { + + enum { ID = ID_BLUETOOTHREMOTECONTROL_NOTIFICATION }; + + // @statuslistener + // @brief Signals battery level change + // @param level Battery level in percent (e.g. 75) + virtual void BatteryLevelChange(const uint8_t level) = 0; + }; + + // @event + struct IAudioTransmissionCallback : virtual public Core::IUnknown { + + enum { ID = ID_BLUETOOTHREMOTECONTROL_CALLBACK }; + + enum transmissionstate : uint8_t { + STOPPED, + STARTED + }; + + // @statuslistener + // @text audiotransmission + // @brief Signals beginning end of audio transmission + // @param state New state of the voice transmission + // @param profile Details of the audio format used in the voice transmission + virtual void StateChanged(const transmissionstate state) = 0; + + // @text audioframe + // @brief Provides audio frame data + // @description Format of the data can be retrieved with AudioProfile call + // @param seq Frame number in current transmission (e.g. 1) + // @param size Size of the raw data frame in bytes (e.g. 400) + // @param data Raw audio data + virtual void Data(const uint16_t seq, const uint16_t size, const uint8_t data[] /* @length:size @encode:base64 */) = 0; + }; + + virtual Core::hresult Register(INotification* const notification) = 0; + virtual Core::hresult Unregister(const INotification* const notification) = 0; + + // Note: Installing a callback and registering for a JSON-RPC notification is mutually exclusive. + virtual Core::hresult Callback(IAudioTransmissionCallback* const callback) = 0; + + // @brief Assigns a Bluetooth device + // @param address: Address of the Bluetooth device to assign + // @retval ERROR_UNKNOWN_KEY Device address value is invalid + // @retval ERROR_ALREADY_CONNECTED A RCU device is already assigned + virtual Core::hresult Assign(const string& address) = 0; + + // @brief Revokes a Bluetooth sink device from audio playback + // @retval ERROR_ALREADY_RELEASED No device is currently assigned as RCU + virtual Core::hresult Revoke() = 0; + + // @property + // @alt-deprecated:address + // @brief Bluetooth address + // @retval ERROR_ILLEGAL_STATE The RCU device currently is not assigned + virtual Core::hresult Device(string& address /* @out */) const = 0; + + // @property + // @brief Device metadata + // @alt-deprecated:info + // @retval ERROR_ILLEGAL_STATE The RCU device currently is not assigned + virtual Core::hresult Metadata(unitmetadata& info /* @out */) const = 0; + + // @property + // @brief Battery level + // @retval ERROR_UNAVAILABLE The device is not connected or does not support battery information + // @retval ERROR_ILLEGAL_STATE The RCU device currently is not assigned + virtual Core::hresult BatteryLevel(uint8_t& level /* @out */) const = 0; + + // @property + // @brief Toggle voice control + // @retval ERROR_NOT_SUPPORTED The device does not support voice input + // @retval ERROR_ILLEGAL_STATE The RCU device currently is not assigned + virtual Core::hresult VoiceControl(bool& value /* @out */) const = 0; + virtual Core::hresult VoiceControl(const bool value) = 0; + + // @property + // @brief Details of audio format + // @retval ERROR_ILLEGAL_STATE The RCU device currently is not assigned + // @retval ERROR_NOT_SUPPORTED The device does not support voice input + virtual Core::hresult AudioProfile(audioprofile& profile /* @out */) const = 0; + }; + + namespace JSONRPC { + + // @json 1.0.0 @text:legacy_lowercase + struct IBluetoothRemoteControlLegacy { + + virtual ~IBluetoothRemoteControlLegacy() = default; + + // @property @deprecated + // @brief Name of the RCU device + // @retval ERROR_ILLEGAL_STATE The RCU device is not assigned + virtual Core::hresult Name(string& name /* @out */) const = 0; + }; + + } + +} // namespace Exchange + +} diff --git a/interfaces/IVoiceHandler.h b/interfaces/IVoiceHandler.h deleted file mode 100644 index a5971c93..00000000 --- a/interfaces/IVoiceHandler.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2020 Metrological - * - * 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. - */ - -#pragma once -#include "Module.h" - -namespace Thunder { -namespace Exchange { - - struct EXTERNAL IVoiceHandler; - - /* - * Interface responsible for producing audio data - * The data that is produced must be signed big endian - */ - struct EXTERNAL IVoiceProducer : virtual public Core::IUnknown { - enum { ID = ID_VOICEPRODUCER }; - - struct EXTERNAL IProfile : virtual public Core::IUnknown { - enum { ID = ID_VOICEPRODUCER_PROFILE }; - - enum codec : uint8_t { - UNDEFINED = 0, - PCM, - ADPCM - }; - - virtual codec Codec() const = 0; - virtual uint8_t Channels() const = 0; - virtual uint32_t SampleRate() const = 0; - virtual uint8_t Resolution() const = 0; - }; - - virtual string Name() const = 0; - virtual uint32_t Callback(IVoiceHandler* callback) = 0; - virtual uint32_t Error() const = 0; - virtual string MetaData() const = 0; - virtual void Configure(const string& settings) = 0; - }; - - struct EXTERNAL IVoiceHandler : virtual public Core::IUnknown { - enum { ID = ID_VOICEHANDLER }; - - virtual void Start(const IVoiceProducer::IProfile* profile) = 0; - virtual void Stop() = 0; - virtual void Data(const uint32_t sequenceNo, const uint8_t data[] /* @in @length:length */, const uint16_t length) = 0; - }; - -} // Exchange -} // Thunder diff --git a/interfaces/Ids.h b/interfaces/Ids.h index f7080e58..f8876125 100644 --- a/interfaces/Ids.h +++ b/interfaces/Ids.h @@ -109,8 +109,9 @@ namespace Exchange { ID_GUIDE = RPC::IDS::ID_EXTERNAL_INTERFACE_OFFSET + 0x0F0, ID_GUIDE_NOTIFICATION = ID_GUIDE + 1, - ID_VOICEHANDLER = RPC::IDS::ID_EXTERNAL_INTERFACE_OFFSET + 0x100, - ID_VOICEPRODUCER = ID_VOICEHANDLER + 1, + ID_BLUETOOTHREMOTECONTROL = RPC::IDS::ID_EXTERNAL_INTERFACE_OFFSET + 0x100, + ID_BLUETOOTHREMOTECONTROL_CALLBACK = ID_BLUETOOTHREMOTECONTROL + 1, + ID_BLUETOOTHREMOTECONTROL_NOTIFICATION = ID_BLUETOOTHREMOTECONTROL + 2, ID_WEBDRIVER = RPC::IDS::ID_EXTERNAL_INTERFACE_OFFSET + 0x110, diff --git a/interfaces/Interfaces.vcxproj b/interfaces/Interfaces.vcxproj index ca5193c1..091caa14 100644 --- a/interfaces/Interfaces.vcxproj +++ b/interfaces/Interfaces.vcxproj @@ -153,7 +153,6 @@ - diff --git a/interfaces/Interfaces.vcxproj.filters b/interfaces/Interfaces.vcxproj.filters index 292688e2..177f5857 100644 --- a/interfaces/Interfaces.vcxproj.filters +++ b/interfaces/Interfaces.vcxproj.filters @@ -275,9 +275,6 @@ Interface Files - - Interface Files - Interface Files diff --git a/jsonrpc/BluetoothRemoteControl.json b/jsonrpc/BluetoothRemoteControl.json deleted file mode 100644 index f8ecea70..00000000 --- a/jsonrpc/BluetoothRemoteControl.json +++ /dev/null @@ -1,275 +0,0 @@ -{ - "$schema": "interface.schema.json", - "jsonrpc": "2.0", - "info": { - "version": "1.0.0", - "title": "Bluetooth Remote Control API", - "class": "BluetoothRemoteControl", - "format": "uncompliant-extended", - "description": "Bluetooth Remote Control JSON-RPC interface" - }, - "common": { - "$ref": "common.json" - }, - "definitions": { - "deviceaddress": { - "description": "Bluetooth address", - "type": "string", - "example": "81:6F:B0:91:9B:FE" - } - }, - "methods": { - "assign": { - "summary": "Assigns a bluetooth device as a remote control unit", - "params": { - "type": "object", - "properties": { - "address": { - "$ref": "#/definitions/deviceaddress" - } - } - }, - "result": { - "$ref": "#/common/results/void" - }, - "errors": [ - { - "description": "Bluetooth unavailable", - "$ref": "#/common/errors/unavailable" - }, - { - "description": "Device unknown", - "$ref": "#/common/errors/unknownkey" - }, - { - "description": "Failed to assign the device", - "$ref": "#/common/errors/general" - } - ] - }, - "revoke": { - "summary": "Revokes the current remote control assignment", - "result": { - "$ref": "#/common/results/void" - }, - "errors": [ - { - "description": "Remote not assigned", - "$ref": "#/common/errors/illegalstate" - } - ] - } - }, - "properties": { - "name": { - "readonly": true, - "summary": "Unit name", - "params": { - "type": "string", - "description": "Name of the remote control unit", - "example": "Acme Bluetooth RCU" - }, - "errors": [ - { - "$ref": "#/common/errors/illegalstate", - "description": "No remote has been assigned" - } - ] - }, - "address": { - "readonly": true, - "summary": "Bluetooth address of the unit", - "params": { - "$ref": "#/definitions/deviceaddress" - }, - "errors": [ - { - "$ref": "#/common/errors/illegalstate", - "description": "No remote has been assigned" - } - ] - }, - "info": { - "summary": "Unit auxiliary information", - "readonly": true, - "params": { - "type": "object", - "properties": { - "model": { - "type": "string", - "description": "Unit model name or number", - "example": "Acme 1500 Plus" - }, - "serial": { - "type": "string", - "description": "Unit serial number", - "example": "1234567890" - }, - "firmware": { - "type": "string", - "description": "Unit firmware revision", - "example": "1.0" - }, - "software": { - "type": "string", - "description": "Unit software revision", - "example": "1.0" - }, - "manufacturer": { - "type": "string", - "description": "Unit manufacturer name", - "example": "Acme Inc." - } - }, - "required": [ ] - }, - "errors": [ - { - "$ref": "#/common/errors/illegalstate", - "description": "No remote has been assigned" - }, - { - "$ref": "#/common/errors/general", - "description": "Failed to retrieve information" - } - ] - }, - "batterylevel": { - "summary": "Battery level", - "event": [ "batterylevel" ], - "readonly": true, - "params": { - "type": "number", - "size": 8, - "example": 50, - "description": "Remote control unit's battery level in percentage" - }, - "errors": [ - { - "$ref": "#/common/errors/illegalstate", - "description": "No remote has been assigned" - }, - { - "$ref": "#/common/errors/general", - "description": "Failed to retrieve battery level" - } - ] - }, - "voice": { - "summary": "Enable or Disable the flow of Voice data fragments from the remote", - "params": { - "type": "boolean", - "description": "Enable (true) or Disable (false) flow of voice data" - }, - "errors": [ - { - "$ref": "#/common/errors/general", - "description": "Failed to set the voice flow" - } - ] - }, - "audioprofile" : { - "summary": "Audio profile details", - "readonly": true, - "params": { - "type": "object", - "properties": { - "codec": { - "type": "string", - "enum" : [ "PCM", "ADPCM" ], - "example": "ADPCM", - "description": "Name of the audio codec (*pcm* for uncompressed audio)" - }, - "channels": { - "type": "number", - "size": 8, - "example": 1, - "description": "Number of audio channels (1: mono, 2: stereo, etc.)" - }, - "rate": { - "type": "number", - "size": 16, - "example": 16000, - "description": "Sample rate (in Hz)" - }, - "resolution": { - "type": "number", - "size": 8, - "example": 16, - "description": "Sample resolution (in bits per sample)" - } - }, - "required": [ - "codec", - "channels", - "rate", - "resolution" - ] - }, - "errors": [ - { - "$ref": "#/common/errors/illegalstate", - "description": "No remote has been assigned" - }, - { - "$ref": "#/common/errors/unknownkey", - "description": "The supplied audio profile is unknown" - } - ] - } - }, - "events": { - "audiotransmission": { - "summary": "Notifies about audio data transmission", - "description": "Register to this event to be notified about audio transmission status", - "params": { - "type": "object", - "properties": { - "profile": { - "type": "string", - "example": "pcm", - "description": "Type of audio profile, marking start of transmission; empty in case of end of transmission" - } - }, - "required": [] - } - }, - "audioframe": { - "summary": "Notifies about new audio data available", - "description": "Register to this event to be notified about audio data", - "params": { - "type": "object", - "properties": { - "seq": { - "type": "number", - "example": 1, - "description": "Sequence number of the audio frame within current audio transmission" - }, - "data": { - "type": "string", - "example": "yKMHiYh6qJiDspB6S7ihlKOAbivApYEQDCgY0aECCQhpkAqZogP1ECk9GbHGEAkwG8Ax8wArgaAtEMjGQIoYCKKgGCuzBSA/iuWkKEwamLKzOKoCeR2hwQQZKqgBKKqELoGQwQ==", - "description": "Base64 representation of the binary data of the audio frame; format of the data is specified by the audio profile denoted by the most recent *audiotransmission* notification" - } - }, - "required": [ - "data" - ] - } - }, - "batterylevelchange": { - "summary": "Notifies about battery level changes", - "description": "Register to this event to be notified about battery level drops", - "params": { - "type": "object", - "properties": { - "level": { - "type": "number", - "size": 8, - "example": 50, - "description": "Battery level (in percentage)" - } - } - } - } - } -}