From 061479780b11b2c88a88ef5fa8742ba02428407a Mon Sep 17 00:00:00 2001 From: Bartosz Cichocki Date: Thu, 22 Oct 2020 09:59:13 +0200 Subject: [PATCH] [EGD-4011] added BT audio device with A2DP playback (#870) Co-authored-by: SP2FET --- changelog.md | 1 + .../ApplicationSettings.cpp | 4 +- .../windows/BtScanWindow.cpp | 6 +- .../windows/BtScanWindow.hpp | 13 +++ module-audio/Audio/Audio.cpp | 10 +- module-audio/Audio/AudioCommon.hpp | 2 +- .../Audio/Operation/PlaybackOperation.cpp | 15 ++- module-audio/Audio/Profiles/Profile.cpp | 5 + .../Profiles/ProfilePlaybackBluetoothA2DP.hpp | 30 ++++++ .../interface/profiles/A2DP/A2DP.cpp | 29 ++++-- .../interface/profiles/A2DP/A2DP.hpp | 3 + .../interface/profiles/A2DP/A2DPImpl.hpp | 2 + .../Bluetooth/interface/profiles/Profile.hpp | 4 +- .../board/linux/audio/LinuxCellularAudio.cpp | 4 +- .../board/linux/audio/linux_audiocodec.cpp | 4 +- .../rt1051/bsp/audio/RT1051Audiocodec.cpp | 2 +- .../rt1051/bsp/audio/RT1051BluetoothAudio.cpp | 99 +++++++++++++++++++ .../rt1051/bsp/audio/RT1051BluetoothAudio.hpp | 42 ++++++++ .../rt1051/bsp/audio/RT1051CellularAudio.cpp | 2 +- module-bsp/bsp/audio/bsp_audio.cpp | 7 +- module-bsp/bsp/audio/bsp_audio.hpp | 3 +- module-bsp/targets/Target_Linux.cmake | 2 + module-bsp/targets/Target_RT1051.cmake | 1 + .../service-audio/ServiceAudio.cpp | 7 +- .../service-audio/messages/AudioMessage.hpp | 4 +- .../service-bluetooth/ServiceBluetooth.cpp | 15 ++- .../ServiceBluetoothCommon.hpp | 5 + .../service-evtmgr/EventManager.cpp | 2 +- 28 files changed, 284 insertions(+), 39 deletions(-) create mode 100644 module-audio/Audio/Profiles/ProfilePlaybackBluetoothA2DP.hpp create mode 100644 module-bsp/board/rt1051/bsp/audio/RT1051BluetoothAudio.cpp create mode 100644 module-bsp/board/rt1051/bsp/audio/RT1051BluetoothAudio.hpp diff --git a/changelog.md b/changelog.md index 18e5a6f1e4ba43ab03f7ff000a9a63960275601c..3b1649b714af3cbbaf2b537b3494307499648e10 100644 --- a/changelog.md +++ b/changelog.md @@ -8,6 +8,7 @@ * `[meditation]` Added basic meditation functionalities and settings * `[cellular]` Handling incoming calls and sms in sleep mode * `[audio]` Added Bluetooth related APIs to AudioServiceAPI +* `[audio][bluetooth]` Added Bluetooth A2DP playback * `[settings]` Added sql script for file indexer DB schema ### Fixed diff --git a/module-apps/application-settings/ApplicationSettings.cpp b/module-apps/application-settings/ApplicationSettings.cpp index 2433e05ee6a399dbc4d492d84cf39061a69f0d27..dbda34a23d732be7529948ae507f4bb30ef0eb43 100644 --- a/module-apps/application-settings/ApplicationSettings.cpp +++ b/module-apps/application-settings/ApplicationSettings.cpp @@ -53,9 +53,9 @@ namespace app if (auto btmsg = dynamic_cast(msgl); btmsg != nullptr) { auto devices = btmsg->devices; LOG_INFO("received BT Scan message!"); - + auto data = std::make_unique(devices); windowsFactory.build(this, gui::name::window::name_btscan); - setActiveWindow(gui::name::window::name_btscan); + switchWindow(gui::name::window::name_btscan, gui::ShowMode::GUI_SHOW_INIT, std::move(data)); render(gui::RefreshModes::GUI_REFRESH_FAST); } diff --git a/module-apps/application-settings/windows/BtScanWindow.cpp b/module-apps/application-settings/windows/BtScanWindow.cpp index a195f18d375b628d1ff699b7ed88e8fbdde7397b..2ce6fde2a621dd11d6df510f2fb1b1c60e4c69db 100644 --- a/module-apps/application-settings/windows/BtScanWindow.cpp +++ b/module-apps/application-settings/windows/BtScanWindow.cpp @@ -104,6 +104,10 @@ namespace gui } void BtScanWindow::onBeforeShow(ShowMode mode, SwitchData *data) - {} + { + auto newData = static_cast(data); + devices = newData->getDevices(); + rebuild(); + } } // namespace gui diff --git a/module-apps/application-settings/windows/BtScanWindow.hpp b/module-apps/application-settings/windows/BtScanWindow.hpp index be0c00af7ed6e598435f299b806e308ffcbfa75f..90eb5a330a0c2bdf1adb83085d9f2dc838925e3f 100644 --- a/module-apps/application-settings/windows/BtScanWindow.hpp +++ b/module-apps/application-settings/windows/BtScanWindow.hpp @@ -39,4 +39,17 @@ namespace gui void invalidate() noexcept; std::vector devices; }; + + class DeviceData : public SwitchData + { + std::vector devices; + + public: + DeviceData(std::vector devices) : SwitchData(), devices(std::move(devices)) + {} + auto getDevices() -> const std::vector & + { + return devices; + } + }; } // namespace gui diff --git a/module-audio/Audio/Audio.cpp b/module-audio/Audio/Audio.cpp index e79e02604acdffc90bd41a249dae9e2adfd9153c..8ac4f814ba7a5703c7a79a921f34a6c0d2b04770 100644 --- a/module-audio/Audio/Audio.cpp +++ b/module-audio/Audio/Audio.cpp @@ -46,11 +46,11 @@ namespace audio case EventType::HeadphonesUnplug: lineSinkAvailable = false; break; - case EventType::BTHeadsetOn: - lineSinkAvailable = true; + case EventType::BTA2DPOn: + btSinkAvailable = true; break; - case EventType::BTHeadsetOff: - lineSinkAvailable = false; + case EventType::BTA2DPOff: + btSinkAvailable = false; break; default: break; @@ -112,7 +112,7 @@ namespace audio currentOperation->SendEvent(std::make_unique(EventType::HeadphonesPlugin)); } if (btSinkAvailable && btData) { - currentOperation->SendEvent(std::make_unique(EventType::BTHeadsetOn)); + currentOperation->SendEvent(std::make_unique(EventType::BTA2DPOn)); currentOperation->SetBluetoothStreamData(btData); } } diff --git a/module-audio/Audio/AudioCommon.hpp b/module-audio/Audio/AudioCommon.hpp index ceab0d1023d579f65dc2f1ddb70e4b603c3bac5a..7e07c1192270ae5e0b6581a65ab69f93b41ed047 100644 --- a/module-audio/Audio/AudioCommon.hpp +++ b/module-audio/Audio/AudioCommon.hpp @@ -4,7 +4,7 @@ #pragma once #include -#include +#include #include "Profiles/Profile.hpp" diff --git a/module-audio/Audio/Operation/PlaybackOperation.cpp b/module-audio/Audio/Operation/PlaybackOperation.cpp index 166f0f06f00c7ee8c0d2d8eed2467cab716936ae..5a2257280a4ec7113eb7a904597f60a8081e0817 100644 --- a/module-audio/Audio/Operation/PlaybackOperation.cpp +++ b/module-audio/Audio/Operation/PlaybackOperation.cpp @@ -7,6 +7,8 @@ #include "Audio/Profiles/Profile.hpp" #include "Audio/Profiles/ProfilePlaybackLoudspeaker.hpp" #include "Audio/Profiles/ProfilePlaybackHeadphones.hpp" +#include "Audio/Profiles/ProfilePlaybackBluetoothA2DP.hpp" + #include "Audio/AudioCommon.hpp" #include @@ -56,6 +58,7 @@ namespace audio availableProfiles.push_back(Profile::Create(Profile::Type::PlaybackLoudspeaker, nullptr, loudspeakerVolume)); availableProfiles.push_back(Profile::Create(Profile::Type::PlaybackHeadphones, nullptr, headphonesVolume)); + availableProfiles.push_back(Profile::Create(Profile::Type::PlaybackBTA2DP, nullptr, loudspeakerVolume)); currentProfile = availableProfiles[0]; @@ -88,7 +91,7 @@ namespace audio state = State::Active; currentProfile->SetInOutFlags(tags->num_channel == 2 - ? static_cast(bsp::AudioDevice::Flags::OutPutStereo) + ? static_cast(bsp::AudioDevice::Flags::OutputStereo) : static_cast(bsp::AudioDevice::Flags::OutputMono)); currentProfile->SetSampleRate(tags->sample_rate); @@ -155,6 +158,10 @@ namespace audio // TODO: Switch to playback headphones/bt profile if present SwitchProfile(Profile::Type::PlaybackLoudspeaker); break; + case EventType::BTA2DPOn: + // TODO: Switch to playback headphones/bt profile if present + SwitchProfile(Profile::Type::PlaybackBTA2DP); + break; default: return RetCode::UnsupportedEvent; } @@ -201,7 +208,11 @@ namespace audio void PlaybackOperation::SetBluetoothStreamData(std::shared_ptr data) { - LOG_ERROR("UNIMPLEMENTED"); + if (auto device = dynamic_cast(audioDevice.get()); device != nullptr) { + device->sourceQueue = data->out; + device->metadata = data->metadata; + LOG_INFO("Queue and metadata set!"); + } } } // namespace audio diff --git a/module-audio/Audio/Profiles/Profile.cpp b/module-audio/Audio/Profiles/Profile.cpp index 3a5065786a3ed1803e430d7cc14b2ef837fac739..79e5afeeed16fcbc047cc946d2b42323218073c1 100644 --- a/module-audio/Audio/Profiles/Profile.cpp +++ b/module-audio/Audio/Profiles/Profile.cpp @@ -15,6 +15,8 @@ #include "ProfileRoutingHeadset.hpp" #include "ProfileRoutingSpeakerphone.hpp" +#include "ProfilePlaybackBluetoothA2DP.hpp" + #include namespace audio @@ -31,6 +33,9 @@ namespace audio case Type::PlaybackLoudspeaker: inst = std::make_unique(callback, vol); break; + case Type::PlaybackBTA2DP: + inst = std::make_unique(callback, vol); + break; case Type::RecordingBuiltInMic: inst = std::make_unique(callback, gain); break; diff --git a/module-audio/Audio/Profiles/ProfilePlaybackBluetoothA2DP.hpp b/module-audio/Audio/Profiles/ProfilePlaybackBluetoothA2DP.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8fe0a2407c155581e6cf69df42fac6b2e577780d --- /dev/null +++ b/module-audio/Audio/Profiles/ProfilePlaybackBluetoothA2DP.hpp @@ -0,0 +1,30 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include "Profile.hpp" +#include + +namespace audio +{ + + class ProfilePlaybackBluetoothA2DP : public Profile + { + public: + ProfilePlaybackBluetoothA2DP(std::function callback, Volume volume) + : Profile("Playback A2DP", + Type::PlaybackBTA2DP, + bsp::AudioDevice::Format{.sampleRate_Hz = 44100, + .bitWidth = 16, + .flags = 0, + .outputVolume = static_cast(volume), + .inputGain = 0, + .inputPath = bsp::AudioDevice::InputPath::None, + .outputPath = bsp::AudioDevice::OutputPath::BluetoothA2DP}, + bsp::AudioDevice::Type::Bluetooth, + callback) + {} + }; + +} // namespace audio diff --git a/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp b/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp index 4986cf7a639476dece6ccf3249a5e7acfbc72272..648bb8378f17dedfcaedca1cc815a1d01391057e 100644 --- a/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp +++ b/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp @@ -14,6 +14,9 @@ #include #include #include +#include +#include +#include extern "C" { #include "module-bluetooth/lib/btstack/src/btstack.h" @@ -72,11 +75,16 @@ namespace Bt { pimpl->setOwnerService(service); } + auto A2DP::getStreamData() -> std::shared_ptr + { + return pimpl->getStreamData(); + } sys::Service *A2DP::A2DPImpl::ownerService; QueueHandle_t A2DP::A2DPImpl::sourceQueue = nullptr; QueueHandle_t A2DP::A2DPImpl::sinkQueue = nullptr; bd_addr_t A2DP::A2DPImpl::deviceAddr; + DeviceMetadata_t A2DP::A2DPImpl::metadata; btstack_packet_callback_registration_t A2DP::A2DPImpl::hciEventCallbackRegistration; std::array A2DP::A2DPImpl::sdpSourceServiceBuffer; std::array A2DP::A2DPImpl::mediaSbcCodecCapabilities = { @@ -184,7 +192,6 @@ namespace Bt if (sourceQueue != nullptr) { if (xQueueReceive(sourceQueue, &audioData, 10) != pdPASS) { audioData.data.fill(0); - LOG_ERROR("Failed to receive!"); } } else { @@ -384,15 +391,12 @@ namespace Bt AVDTP::sbcConfig.maxBitpoolValue, AVDTP::sbcConfig.channelMode); - DeviceMetadata_t metadata{ + metadata = DeviceMetadata_t{ .sampleRate = static_cast(AVDTP::sbcConfig.samplingFrequency), .channels = static_cast(AVDTP::sbcConfig.numChannels), .samplesPerFrame = static_cast(btstack_sbc_encoder_num_audio_frames()), }; - auto msg = std::make_shared(std::move(metadata)); - sys::Bus::SendUnicast(std::move(msg), "ServiceBluetooth", ownerService); - break; } @@ -446,8 +450,9 @@ namespace Bt sourceQueue = xQueueCreate(5, sizeof(AudioData_t)); sinkQueue = nullptr; if (sourceQueue != nullptr) { - auto msg = std::make_shared(sourceQueue, sinkQueue); - sys::Bus::SendUnicast(std::move(msg), "ServiceBluetooth", ownerService); + auto event = std::make_shared(audio::EventType::BTA2DPOn); + auto msg = std::make_shared(std::move(event)); + sys::Bus::SendUnicast(std::move(msg), service::name::evt_manager, ownerService); } else { LOG_ERROR("failed to create queue!"); @@ -529,7 +534,11 @@ namespace Bt cid, AVRCP::mediaTracker.local_seid, local_seid); - + { + auto event = std::make_shared(audio::EventType::BTA2DPOff); + auto msg = std::make_shared(std::move(event)); + sys::Bus::SendUnicast(std::move(msg), service::name::evt_manager, ownerService); + } if (cid == AVRCP::mediaTracker.a2dp_cid) { AVRCP::mediaTracker.stream_opened = 0; LOG_INFO("A2DP Source: Stream released.\n"); @@ -576,5 +585,9 @@ namespace Bt { ownerService = service; } + auto A2DP::A2DPImpl::getStreamData() -> std::shared_ptr + { + return std::make_shared(sinkQueue, sourceQueue, metadata); + } } // namespace Bt diff --git a/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.hpp b/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.hpp index f49ec64628ca1370f45c95ce47e0971abf1917a5..f41b33f4e83606576973703befac73f4deb488d2 100644 --- a/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.hpp +++ b/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.hpp @@ -8,6 +8,7 @@ #include "Service/Service.hpp" #include "queue.h" #include +#include namespace Bt { class A2DP : public Profile @@ -24,6 +25,8 @@ namespace Bt auto init() -> Error override; void setDeviceAddress(uint8_t *addr) override; void setOwnerService(sys::Service *service); + auto getStreamData() -> std::shared_ptr override; + void start(); void stop(); diff --git a/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DPImpl.hpp b/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DPImpl.hpp index ab65e41163c7b2ea262cb21213eeb99438e87cb9..9d7997af45ec30fa1d79fae31184073c01b03d46 100644 --- a/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DPImpl.hpp +++ b/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DPImpl.hpp @@ -56,6 +56,7 @@ namespace Bt static sys::Service *ownerService; static QueueHandle_t sourceQueue; static QueueHandle_t sinkQueue; + static DeviceMetadata_t metadata; static void startTimer(MediaContext *context); static void stopTimer(MediaContext *context); @@ -71,5 +72,6 @@ namespace Bt void stop(); void setDeviceAddress(bd_addr_t addr); void setOwnerService(sys::Service *service); + auto getStreamData() -> std::shared_ptr; }; } // namespace Bt diff --git a/module-bluetooth/Bluetooth/interface/profiles/Profile.hpp b/module-bluetooth/Bluetooth/interface/profiles/Profile.hpp index 79619831c51d42c7ebacbfcfeee2861b5028c8ee..a1b1616b17500c6020366fd75ec740e52f21a08d 100644 --- a/module-bluetooth/Bluetooth/interface/profiles/Profile.hpp +++ b/module-bluetooth/Bluetooth/interface/profiles/Profile.hpp @@ -4,7 +4,8 @@ #pragma once #include "Error.hpp" - +#include +#include namespace Bt { class Profile @@ -13,6 +14,7 @@ namespace Bt virtual ~Profile() = default; virtual auto init() -> Error = 0; virtual void setDeviceAddress(uint8_t *addr) = 0; + virtual auto getStreamData() -> std::shared_ptr = 0; }; } // namespace Bt diff --git a/module-bsp/board/linux/audio/LinuxCellularAudio.cpp b/module-bsp/board/linux/audio/LinuxCellularAudio.cpp index e280767dcc6ca4bad6bc00bb9f2f55398d5ec429..3cca63be32060e30db67e626bd72aa953912c1dc 100755 --- a/module-bsp/board/linux/audio/LinuxCellularAudio.cpp +++ b/module-bsp/board/linux/audio/LinuxCellularAudio.cpp @@ -86,7 +86,7 @@ namespace bsp int32_t framesToFetch = framesPerBuffer; - if ((ptr->currentFormat.flags & static_cast(Flags::OutPutStereo))) { + if ((ptr->currentFormat.flags & static_cast(Flags::OutputStereo))) { framesToFetch = framesPerBuffer * 2; } @@ -162,7 +162,7 @@ namespace bsp outChan++; } - if (format.flags & static_cast(AudioDevice::Flags::OutPutStereo)) { + if (format.flags & static_cast(AudioDevice::Flags::OutputStereo)) { outChan = 2; } /* Open an audio I/O stream. */ diff --git a/module-bsp/board/linux/audio/linux_audiocodec.cpp b/module-bsp/board/linux/audio/linux_audiocodec.cpp index 57344639b1d0d65f1b530c27d186f1731d867124..ab09428bfa276c770d056e5c423bbeb77ed34bb0 100755 --- a/module-bsp/board/linux/audio/linux_audiocodec.cpp +++ b/module-bsp/board/linux/audio/linux_audiocodec.cpp @@ -84,7 +84,7 @@ namespace bsp int32_t framesToFetch = framesPerBuffer; - if ((ptr->currentFormat.flags & static_cast(Flags::OutPutStereo))) { + if ((ptr->currentFormat.flags & static_cast(Flags::OutputStereo))) { framesToFetch = framesPerBuffer * 2; } @@ -160,7 +160,7 @@ namespace bsp outChan++; } - if (format.flags & static_cast(AudioDevice::Flags::OutPutStereo)) { + if (format.flags & static_cast(AudioDevice::Flags::OutputStereo)) { outChan = 2; } /* Open an audio I/O stream. */ diff --git a/module-bsp/board/rt1051/bsp/audio/RT1051Audiocodec.cpp b/module-bsp/board/rt1051/bsp/audio/RT1051Audiocodec.cpp index a454c2b3df9cc2f8a779b0657db2824175cce799..843a9a18c6ae966b60e92709a15f4b7df8c0cb72 100644 --- a/module-bsp/board/rt1051/bsp/audio/RT1051Audiocodec.cpp +++ b/module-bsp/board/rt1051/bsp/audio/RT1051Audiocodec.cpp @@ -69,7 +69,7 @@ namespace bsp saiOutFormat.stereo = kSAI_MonoLeft; OutStart(); } - else if (format.flags & static_cast(AudioDevice::Flags::OutPutStereo)) { + else if (format.flags & static_cast(AudioDevice::Flags::OutputStereo)) { saiOutFormat.stereo = kSAI_Stereo; OutStart(); } diff --git a/module-bsp/board/rt1051/bsp/audio/RT1051BluetoothAudio.cpp b/module-bsp/board/rt1051/bsp/audio/RT1051BluetoothAudio.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0f6ee7ccdeab18c190cec8023e073927ec3a0245 --- /dev/null +++ b/module-bsp/board/rt1051/bsp/audio/RT1051BluetoothAudio.cpp @@ -0,0 +1,99 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "RT1051BluetoothAudio.hpp" + +namespace bsp +{ + RT1051BluetoothAudio::RT1051BluetoothAudio(AudioDevice::audioCallback_t callback) : AudioDevice(callback) + { + isInitialized = true; + LOG_INFO("Device created!"); + } + AudioDevice::RetCode RT1051BluetoothAudio::Start(const AudioDevice::Format &format) + { + LOG_INFO("Start"); + Init(); + if ((format.flags & static_cast(AudioDevice::Flags::OutputMono)) != 0u) { + OutStart(); + } + else if ((format.flags & static_cast(AudioDevice::Flags::OutputStereo)) != 0u) { + OutStart(); + } + return AudioDevice::RetCode::Success; + } + AudioDevice::RetCode RT1051BluetoothAudio::Stop() + { + return AudioDevice::RetCode::Success; + } + AudioDevice::RetCode RT1051BluetoothAudio::OutputVolumeCtrl(float vol) + { + return AudioDevice::RetCode::Success; + } + AudioDevice::RetCode RT1051BluetoothAudio::InputGainCtrl(float gain) + { + return AudioDevice::RetCode::Success; + } + AudioDevice::RetCode RT1051BluetoothAudio::OutputPathCtrl(AudioDevice::OutputPath outputPath) + { + return AudioDevice::RetCode::Success; + } + AudioDevice::RetCode RT1051BluetoothAudio::InputPathCtrl(AudioDevice::InputPath inputPath) + { + return AudioDevice::RetCode::Success; + } + bool RT1051BluetoothAudio::IsFormatSupported(const AudioDevice::Format &format) + { + return true; + } + + void outBluetoothAudioWorkerTask(void *pvp) + { + auto *inst = static_cast(pvp); + auto dataSize = inst->metadata.samplesPerFrame; + + while (true) { + auto framesFetched = inst->GetAudioCallback()(nullptr, inst->audioData.data.data(), dataSize); + if (framesFetched == 0) { + break; + } + else if (framesFetched < inst->audioData.data.size()) { + std::fill(inst->audioData.data.begin() + framesFetched, inst->audioData.data.end(), 0); + } + + if (inst->sourceQueue != nullptr) { + xQueueSend(inst->sourceQueue, inst->audioData.data.data(), 2); + } + else { + LOG_ERROR("Queue nullptr"); + vTaskDelay(2); + } + } + + inst->OutStop(); + inst->outWorkerThread = nullptr; + vTaskDelete(nullptr); + } + + void RT1051BluetoothAudio::OutStart() + { + if (xTaskCreate(outBluetoothAudioWorkerTask, + "outbluetoothaudio", + stackSize, + this, + tskIDLE_PRIORITY, + &outWorkerThread) != pdPASS) { + LOG_ERROR("Error during creating output bluetooth audio task"); + } + } + void RT1051BluetoothAudio::OutStop() + {} + + void RT1051BluetoothAudio::Init() + {} + + RT1051BluetoothAudio::~RT1051BluetoothAudio() + { + Stop(); + } +} // namespace bsp diff --git a/module-bsp/board/rt1051/bsp/audio/RT1051BluetoothAudio.hpp b/module-bsp/board/rt1051/bsp/audio/RT1051BluetoothAudio.hpp new file mode 100644 index 0000000000000000000000000000000000000000..33daaf4ea7c9293466a72102957369d162d619ad --- /dev/null +++ b/module-bsp/board/rt1051/bsp/audio/RT1051BluetoothAudio.hpp @@ -0,0 +1,42 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include "FreeRTOS.h" +#include "macros.h" +#include "task.h" +#include "bsp/audio/bsp_audio.hpp" +#include +#include + +namespace bsp +{ + class RT1051BluetoothAudio final : public AudioDevice + { + static constexpr uint16_t stackSize = 1024; + + public: + RT1051BluetoothAudio(AudioDevice::audioCallback_t callback); + ~RT1051BluetoothAudio() final; + + AudioDevice::RetCode Start(const Format &format) final; + AudioDevice::RetCode Stop() final; + AudioDevice::RetCode OutputVolumeCtrl(float vol) final; + AudioDevice::RetCode InputGainCtrl(float gain) final; + AudioDevice::RetCode OutputPathCtrl(OutputPath outputPath) final; + AudioDevice::RetCode InputPathCtrl(InputPath inputPath) final; + bool IsFormatSupported(const Format &format) final; + + TaskHandle_t outWorkerThread; + AudioData_t audioData; + QueueHandle_t sourceQueue; + DeviceMetadata_t metadata; + void OutStop(); + + private: + void Init(); + void OutStart(); + }; + +} // namespace bsp diff --git a/module-bsp/board/rt1051/bsp/audio/RT1051CellularAudio.cpp b/module-bsp/board/rt1051/bsp/audio/RT1051CellularAudio.cpp index 4d25269108d3617f36d0a4dc3c9879318efddd36..51e765cf582d3dace4857fdddc67e9350de073d1 100644 --- a/module-bsp/board/rt1051/bsp/audio/RT1051CellularAudio.cpp +++ b/module-bsp/board/rt1051/bsp/audio/RT1051CellularAudio.cpp @@ -66,7 +66,7 @@ namespace bsp saiOutFormat.stereo = kSAI_MonoLeft; OutStart(); } - else if (format.flags & static_cast(AudioDevice::Flags::OutPutStereo)) { + else if (format.flags & static_cast(AudioDevice::Flags::OutputStereo)) { saiOutFormat.stereo = kSAI_Stereo; OutStart(); } diff --git a/module-bsp/bsp/audio/bsp_audio.cpp b/module-bsp/bsp/audio/bsp_audio.cpp index 92082b814ab67faaef01a974346ad335940063ba..eeb3a566d8cdcaacb204257f389fffa44ac0921a 100644 --- a/module-bsp/bsp/audio/bsp_audio.cpp +++ b/module-bsp/bsp/audio/bsp_audio.cpp @@ -4,6 +4,8 @@ #include "board/rt1051/bsp/audio/RT1051Audiocodec.hpp" #include "board/rt1051/bsp/audio/RT1051CellularAudio.hpp" +#include "board/rt1051/bsp/audio/RT1051BluetoothAudio.hpp" + #elif defined(TARGET_Linux) #include "audio/linux_audiocodec.hpp" #include "audio/LinuxCellularAudio.hpp" @@ -22,7 +24,7 @@ namespace bsp{ case Type ::Audiocodec: { #if defined(TARGET_RT1051) - inst = std::make_unique(callback ); + inst = std::make_unique(callback); #elif defined(TARGET_Linux) inst = std::make_unique(callback ); #else @@ -36,6 +38,7 @@ namespace bsp{ case Type ::Bluetooth: { #if defined(TARGET_RT1051) + inst = std::make_unique(callback); #elif defined(TARGET_Linux) @@ -48,7 +51,7 @@ namespace bsp{ case Type::Cellular: { #if defined(TARGET_RT1051) - inst = std::make_unique(callback ); + inst = std::make_unique(callback); #elif defined(TARGET_Linux) inst = std::make_unique(callback ); #else diff --git a/module-bsp/bsp/audio/bsp_audio.hpp b/module-bsp/bsp/audio/bsp_audio.hpp index df1658b20c93d4dc5524c447f86f6139cf241a23..c411a1467a415857d9c63ac0e25f74d26ad3da18 100755 --- a/module-bsp/bsp/audio/bsp_audio.hpp +++ b/module-bsp/bsp/audio/bsp_audio.hpp @@ -32,12 +32,13 @@ namespace bsp { HeadphonesMono, Earspeaker, Loudspeaker, + BluetoothA2DP, None }; enum class Flags { OutputMono = 1 << 0, - OutPutStereo = 1 << 1, + OutputStereo = 1 << 1, InputLeft = 1 << 2, InputRight = 1 << 3, InputStereo = 1 << 4 diff --git a/module-bsp/targets/Target_Linux.cmake b/module-bsp/targets/Target_Linux.cmake index a0a8ca9e91bc3bc9bb8d3b3e9a9d07ab59585c74..4e2a0daaf5859dc96bd210bfd45482602b98d512 100644 --- a/module-bsp/targets/Target_Linux.cmake +++ b/module-bsp/targets/Target_Linux.cmake @@ -17,6 +17,8 @@ set(BOARD_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/board/linux/audio/linux_audiocodec.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/board/linux/audio/LinuxCellularAudio.cpp" + #needed because of PlaybackOperation::SetBluetoothStreamData + "${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/bsp/audio/RT1051BluetoothAudio.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/board/linux/bluetooth/Bluetooth.cpp" diff --git a/module-bsp/targets/Target_RT1051.cmake b/module-bsp/targets/Target_RT1051.cmake index 1721ff9d647c048e96b9e19ff859f7a1ba25fe9f..1d496f28f66b911804de9e3aab8c65efad177a93 100644 --- a/module-bsp/targets/Target_RT1051.cmake +++ b/module-bsp/targets/Target_RT1051.cmake @@ -85,6 +85,7 @@ set(BOARD_SOURCES ${BOARD_SOURCES} "${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/bsp/battery-charger/battery_charger.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/bsp/audio/RT1051Audiocodec.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/bsp/audio/RT1051CellularAudio.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/bsp/audio/RT1051BluetoothAudio.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/bsp/audio/CodecMAX98090.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/bsp/audio/qfilter.c" "${USB_CDC_SRC}" diff --git a/module-services/service-audio/ServiceAudio.cpp b/module-services/service-audio/ServiceAudio.cpp index 8bac91c58ca7e32d1c810cd56ad3c5ff00375f93..01b09d299e21fdd8b70ed6704b72a273f61083bf 100644 --- a/module-services/service-audio/ServiceAudio.cpp +++ b/module-services/service-audio/ServiceAudio.cpp @@ -323,7 +323,7 @@ std::unique_ptr ServiceAudio::HandleStart(const Operation: std::unique_ptr ServiceAudio::HandleSendEvent(std::shared_ptr evt) { - if (evt->getType() == EventType::BTHeadsetOn) { + if (evt->getType() == EventType::BTA2DPOn) { auto req = std::make_shared(); sys::Bus::SendUnicast(req, service::name::bluetooth, this); return std::make_unique(RetCode::Success); @@ -331,7 +331,7 @@ std::unique_ptr ServiceAudio::HandleSendEvent(std::shared_ for (auto &input : audioMux.GetAllInputs()) { input.audio->SendEvent(evt); - if (evt->getType() == EventType::BTHeadsetOff) { + if (evt->getType() == EventType::BTA2DPOff) { input.audio->SetBluetoothStreamData(nullptr); } } @@ -501,7 +501,8 @@ sys::Message_t ServiceAudio::DataReceivedHandler(sys::DataMessage *msgl, sys::Re auto *msg = static_cast(msgl); for (auto &input : audioMux.GetAllInputs()) { input.audio->SetBluetoothStreamData(msg->getData()); - input.audio->SendEvent(std::make_unique(EventType::BTHeadsetOn)); + input.audio->SendEvent(std::make_unique(EventType::BTA2DPOn)); + LOG_INFO("Queues received!"); } } else { diff --git a/module-services/service-audio/messages/AudioMessage.hpp b/module-services/service-audio/messages/AudioMessage.hpp index c9933f83c3409ec97b5c8fb8c6dd9cbece4c49fc..f770dc40613dc8705c7913feb9a4f98df627e828 100644 --- a/module-services/service-audio/messages/AudioMessage.hpp +++ b/module-services/service-audio/messages/AudioMessage.hpp @@ -7,8 +7,8 @@ #include #include "Service/Message.hpp" #include "MessageType.hpp" -#include "Audio/AudioCommon.hpp" -#include "Audio/decoder/decoder.hpp" +#include "module-audio/Audio/AudioCommon.hpp" +#include "module-audio/Audio/decoder/decoder.hpp" class AudioMessage : public sys::DataMessage { diff --git a/module-services/service-bluetooth/ServiceBluetooth.cpp b/module-services/service-bluetooth/ServiceBluetooth.cpp index 77c14156b42a9f091faad4445f047ab038e436ce..3c81762bb5f9f238c31d279bbc93f20812e9b25f 100644 --- a/module-services/service-bluetooth/ServiceBluetooth.cpp +++ b/module-services/service-bluetooth/ServiceBluetooth.cpp @@ -9,6 +9,7 @@ #include "messages/BluetoothMessage.hpp" #include #include +#include ServiceBluetooth::ServiceBluetooth() : sys::Service(service::name::bluetooth) { @@ -88,6 +89,16 @@ sys::Message_t ServiceBluetooth::DataReceivedHandler(sys::DataMessage *msg, sys: } break; } + case MessageType::BluetoothAddrResult: { + auto addrMsg = static_cast(msg); + worker->set_addr(addrMsg->addr); + } break; + case MessageType::BluetoothRequestStream: { + auto result = + std::make_shared(worker->currentProfile->getStreamData()); + sys::Bus::SendUnicast(std::move(result), "ServiceAudio", this); + LOG_INFO("Queues sent after a request!"); + } break; default: LOG_INFO("BT not handled!"); break; @@ -96,10 +107,6 @@ sys::Message_t ServiceBluetooth::DataReceivedHandler(sys::DataMessage *msg, sys: catch (std::exception &ex) { LOG_ERROR("Exception on BtService!: %s", ex.what()); } - if (dynamic_cast(msg) != nullptr) { - auto addrMsg = static_cast(msg); - worker->set_addr(addrMsg->addr); - } return std::make_shared(); } diff --git a/module-services/service-bluetooth/ServiceBluetoothCommon.hpp b/module-services/service-bluetooth/ServiceBluetoothCommon.hpp index 25ae2c7ab649a7833585c3dc55110feddba034e0..20a50dae4821faf73c2bd57541da49f74a827f56 100644 --- a/module-services/service-bluetooth/ServiceBluetoothCommon.hpp +++ b/module-services/service-bluetooth/ServiceBluetoothCommon.hpp @@ -5,10 +5,15 @@ #include #include +#include class BluetoothStreamData { public: QueueHandle_t in = nullptr; QueueHandle_t out = nullptr; + DeviceMetadata_t metadata; + BluetoothStreamData(QueueHandle_t in, QueueHandle_t out, DeviceMetadata_t metadata) + : in(in), out(out), metadata(metadata) + {} }; diff --git a/module-services/service-evtmgr/EventManager.cpp b/module-services/service-evtmgr/EventManager.cpp index 01a1aefef35de1a21bf2dc15a48c1257eb3e65c3..e50e2998b81c4d11d075629d9400367f46085b8c 100644 --- a/module-services/service-evtmgr/EventManager.cpp +++ b/module-services/service-evtmgr/EventManager.cpp @@ -160,7 +160,7 @@ sys::Message_t EventManager::DataReceivedHandler(sys::DataMessage *msgl, sys::Re handled = true; } - else if (auto msg = dynamic_cast(msgl); msg && msgl->sender == this->GetName()) { + else if (auto msg = dynamic_cast(msgl); msg /*&& msgl->sender == this->GetName()*/) { AudioServiceAPI::SendEvent(this, msg->getEvent()); handled = true; }