~aleteoryx/muditaos

061479780b11b2c88a88ef5fa8742ba02428407a — Bartosz Cichocki 5 years ago 19f5673
[EGD-4011] added BT audio device with A2DP playback (#870)

Co-authored-by: SP2FET <bartosz.cichocki@mudita.com>
28 files changed, 284 insertions(+), 39 deletions(-)

M changelog.md
M module-apps/application-settings/ApplicationSettings.cpp
M module-apps/application-settings/windows/BtScanWindow.cpp
M module-apps/application-settings/windows/BtScanWindow.hpp
M module-audio/Audio/Audio.cpp
M module-audio/Audio/AudioCommon.hpp
M module-audio/Audio/Operation/PlaybackOperation.cpp
M module-audio/Audio/Profiles/Profile.cpp
A module-audio/Audio/Profiles/ProfilePlaybackBluetoothA2DP.hpp
M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp
M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.hpp
M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DPImpl.hpp
M module-bluetooth/Bluetooth/interface/profiles/Profile.hpp
M module-bsp/board/linux/audio/LinuxCellularAudio.cpp
M module-bsp/board/linux/audio/linux_audiocodec.cpp
M module-bsp/board/rt1051/bsp/audio/RT1051Audiocodec.cpp
A module-bsp/board/rt1051/bsp/audio/RT1051BluetoothAudio.cpp
A module-bsp/board/rt1051/bsp/audio/RT1051BluetoothAudio.hpp
M module-bsp/board/rt1051/bsp/audio/RT1051CellularAudio.cpp
M module-bsp/bsp/audio/bsp_audio.cpp
M module-bsp/bsp/audio/bsp_audio.hpp
M module-bsp/targets/Target_Linux.cmake
M module-bsp/targets/Target_RT1051.cmake
M module-services/service-audio/ServiceAudio.cpp
M module-services/service-audio/messages/AudioMessage.hpp
M module-services/service-bluetooth/ServiceBluetooth.cpp
M module-services/service-bluetooth/ServiceBluetoothCommon.hpp
M module-services/service-evtmgr/EventManager.cpp
M changelog.md => changelog.md +1 -0
@@ 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

M module-apps/application-settings/ApplicationSettings.cpp => module-apps/application-settings/ApplicationSettings.cpp +2 -2
@@ 53,9 53,9 @@ namespace app
        if (auto btmsg = dynamic_cast<BluetoothScanResultMessage *>(msgl); btmsg != nullptr) {
            auto devices = btmsg->devices;
            LOG_INFO("received BT Scan message!");

            auto data = std::make_unique<gui::DeviceData>(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);
        }

M module-apps/application-settings/windows/BtScanWindow.cpp => module-apps/application-settings/windows/BtScanWindow.cpp +5 -1
@@ 104,6 104,10 @@ namespace gui
    }

    void BtScanWindow::onBeforeShow(ShowMode mode, SwitchData *data)
    {}
    {
        auto newData = static_cast<DeviceData *>(data);
        devices      = newData->getDevices();
        rebuild();
    }

} // namespace gui

M module-apps/application-settings/windows/BtScanWindow.hpp => module-apps/application-settings/windows/BtScanWindow.hpp +13 -0
@@ 39,4 39,17 @@ namespace gui
        void invalidate() noexcept;
        std::vector<Devicei> devices;
    };

    class DeviceData : public SwitchData
    {
        std::vector<Devicei> devices;

      public:
        DeviceData(std::vector<Devicei> devices) : SwitchData(), devices(std::move(devices))
        {}
        auto getDevices() -> const std::vector<Devicei> &
        {
            return devices;
        }
    };
} // namespace gui

M module-audio/Audio/Audio.cpp => module-audio/Audio/Audio.cpp +5 -5
@@ 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<Event>(EventType::HeadphonesPlugin));
            }
            if (btSinkAvailable && btData) {
                currentOperation->SendEvent(std::make_unique<Event>(EventType::BTHeadsetOn));
                currentOperation->SendEvent(std::make_unique<Event>(EventType::BTA2DPOn));
                currentOperation->SetBluetoothStreamData(btData);
            }
        }

M module-audio/Audio/AudioCommon.hpp => module-audio/Audio/AudioCommon.hpp +1 -1
@@ 4,7 4,7 @@
#pragma once

#include <map>
#include <bsp_audio.hpp>
#include <bsp/audio/bsp_audio.hpp>

#include "Profiles/Profile.hpp"


M module-audio/Audio/Operation/PlaybackOperation.cpp => module-audio/Audio/Operation/PlaybackOperation.cpp +13 -2
@@ 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 <bsp/audio/bsp_audio.hpp>


@@ 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<uint32_t>(bsp::AudioDevice::Flags::OutPutStereo)
                                          ? static_cast<uint32_t>(bsp::AudioDevice::Flags::OutputStereo)
                                          : static_cast<uint32_t>(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<BluetoothStreamData> data)
    {
        LOG_ERROR("UNIMPLEMENTED");
        if (auto device = dynamic_cast<bsp::RT1051BluetoothAudio *>(audioDevice.get()); device != nullptr) {
            device->sourceQueue = data->out;
            device->metadata    = data->metadata;
            LOG_INFO("Queue and metadata set!");
        }
    }

} // namespace audio

M module-audio/Audio/Profiles/Profile.cpp => module-audio/Audio/Profiles/Profile.cpp +5 -0
@@ 15,6 15,8 @@
#include "ProfileRoutingHeadset.hpp"
#include "ProfileRoutingSpeakerphone.hpp"

#include "ProfilePlaybackBluetoothA2DP.hpp"

#include <Utils.hpp>

namespace audio


@@ 31,6 33,9 @@ namespace audio
        case Type::PlaybackLoudspeaker:
            inst = std::make_unique<ProfilePlaybackLoudspeaker>(callback, vol);
            break;
        case Type::PlaybackBTA2DP:
            inst = std::make_unique<ProfilePlaybackBluetoothA2DP>(callback, vol);
            break;
        case Type::RecordingBuiltInMic:
            inst = std::make_unique<ProfileRecordingOnBoardMic>(callback, gain);
            break;

A module-audio/Audio/Profiles/ProfilePlaybackBluetoothA2DP.hpp => module-audio/Audio/Profiles/ProfilePlaybackBluetoothA2DP.hpp +30 -0
@@ 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 <module-bsp/board/rt1051/bsp/audio/RT1051BluetoothAudio.hpp>

namespace audio
{

    class ProfilePlaybackBluetoothA2DP : public Profile
    {
      public:
        ProfilePlaybackBluetoothA2DP(std::function<int32_t()> callback, Volume volume)
            : Profile("Playback A2DP",
                      Type::PlaybackBTA2DP,
                      bsp::AudioDevice::Format{.sampleRate_Hz = 44100,
                                               .bitWidth      = 16,
                                               .flags         = 0,
                                               .outputVolume  = static_cast<float>(volume),
                                               .inputGain     = 0,
                                               .inputPath     = bsp::AudioDevice::InputPath::None,
                                               .outputPath    = bsp::AudioDevice::OutputPath::BluetoothA2DP},
                      bsp::AudioDevice::Type::Bluetooth,
                      callback)
        {}
    };

} // namespace audio

M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp +21 -8
@@ 14,6 14,9 @@
#include <log/log.hpp>
#include <module-sys/Service/Bus.hpp>
#include <service-bluetooth/messages/BluetoothMessage.hpp>
#include <module-audio/Audio/AudioCommon.hpp>
#include <module-services/service-audio/messages/AudioMessage.hpp>
#include <module-services/service-evtmgr/Constants.hpp>
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<BluetoothStreamData>
    {
        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<uint8_t, 150> A2DP::A2DPImpl::sdpSourceServiceBuffer;
    std::array<uint8_t, 4> 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<unsigned int>(AVDTP::sbcConfig.samplingFrequency),
                .channels        = static_cast<unsigned short>(AVDTP::sbcConfig.numChannels),
                .samplesPerFrame = static_cast<unsigned int>(btstack_sbc_encoder_num_audio_frames()),
            };

            auto msg = std::make_shared<BluetoothDeviceMetadataMessage>(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<BluetoothAudioRegisterMessage>(sourceQueue, sinkQueue);
                sys::Bus::SendUnicast(std::move(msg), "ServiceBluetooth", ownerService);
                auto event = std::make_shared<audio::Event>(audio::EventType::BTA2DPOn);
                auto msg   = std::make_shared<AudioEventRequest>(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::Event>(audio::EventType::BTA2DPOff);
                auto msg   = std::make_shared<AudioEventRequest>(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<BluetoothStreamData>
    {
        return std::make_shared<BluetoothStreamData>(sinkQueue, sourceQueue, metadata);
    }

} // namespace Bt

M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.hpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.hpp +3 -0
@@ 8,6 8,7 @@
#include "Service/Service.hpp"
#include "queue.h"
#include <memory>
#include <module-services/service-bluetooth/ServiceBluetoothCommon.hpp>
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<BluetoothStreamData> override;

        void start();
        void stop();


M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DPImpl.hpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DPImpl.hpp +2 -0
@@ 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<BluetoothStreamData>;
    };
} // namespace Bt

M module-bluetooth/Bluetooth/interface/profiles/Profile.hpp => module-bluetooth/Bluetooth/interface/profiles/Profile.hpp +3 -1
@@ 4,7 4,8 @@
#pragma once

#include "Error.hpp"

#include <module-services/service-bluetooth/ServiceBluetoothCommon.hpp>
#include <memory>
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<BluetoothStreamData> = 0;
    };

} // namespace Bt

M module-bsp/board/linux/audio/LinuxCellularAudio.cpp => module-bsp/board/linux/audio/LinuxCellularAudio.cpp +2 -2
@@ 86,7 86,7 @@ namespace bsp

        int32_t framesToFetch = framesPerBuffer;

        if ((ptr->currentFormat.flags & static_cast<uint32_t>(Flags::OutPutStereo))) {
        if ((ptr->currentFormat.flags & static_cast<uint32_t>(Flags::OutputStereo))) {
            framesToFetch = framesPerBuffer * 2;
        }



@@ 162,7 162,7 @@ namespace bsp
            outChan++;
        }

        if (format.flags & static_cast<uint32_t>(AudioDevice::Flags::OutPutStereo)) {
        if (format.flags & static_cast<uint32_t>(AudioDevice::Flags::OutputStereo)) {
            outChan = 2;
        }
        /* Open an audio I/O stream. */

M module-bsp/board/linux/audio/linux_audiocodec.cpp => module-bsp/board/linux/audio/linux_audiocodec.cpp +2 -2
@@ 84,7 84,7 @@ namespace bsp

        int32_t framesToFetch = framesPerBuffer;

        if ((ptr->currentFormat.flags & static_cast<uint32_t>(Flags::OutPutStereo))) {
        if ((ptr->currentFormat.flags & static_cast<uint32_t>(Flags::OutputStereo))) {
            framesToFetch = framesPerBuffer * 2;
        }



@@ 160,7 160,7 @@ namespace bsp
            outChan++;
        }

        if (format.flags & static_cast<uint32_t>(AudioDevice::Flags::OutPutStereo)) {
        if (format.flags & static_cast<uint32_t>(AudioDevice::Flags::OutputStereo)) {
            outChan = 2;
        }
        /* Open an audio I/O stream. */

M module-bsp/board/rt1051/bsp/audio/RT1051Audiocodec.cpp => module-bsp/board/rt1051/bsp/audio/RT1051Audiocodec.cpp +1 -1
@@ 69,7 69,7 @@ namespace bsp
            saiOutFormat.stereo = kSAI_MonoLeft;
            OutStart();
        }
        else if (format.flags & static_cast<uint32_t>(AudioDevice::Flags::OutPutStereo)) {
        else if (format.flags & static_cast<uint32_t>(AudioDevice::Flags::OutputStereo)) {
            saiOutFormat.stereo = kSAI_Stereo;
            OutStart();
        }

A module-bsp/board/rt1051/bsp/audio/RT1051BluetoothAudio.cpp => module-bsp/board/rt1051/bsp/audio/RT1051BluetoothAudio.cpp +99 -0
@@ 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<uint32_t>(AudioDevice::Flags::OutputMono)) != 0u) {
            OutStart();
        }
        else if ((format.flags & static_cast<uint32_t>(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<RT1051BluetoothAudio *>(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

A module-bsp/board/rt1051/bsp/audio/RT1051BluetoothAudio.hpp => module-bsp/board/rt1051/bsp/audio/RT1051BluetoothAudio.hpp +42 -0
@@ 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 <module-bluetooth/Bluetooth/Device.hpp>
#include <mutex.hpp>

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

M module-bsp/board/rt1051/bsp/audio/RT1051CellularAudio.cpp => module-bsp/board/rt1051/bsp/audio/RT1051CellularAudio.cpp +1 -1
@@ 66,7 66,7 @@ namespace bsp
            saiOutFormat.stereo = kSAI_MonoLeft;
            OutStart();
        }
        else if (format.flags & static_cast<uint32_t>(AudioDevice::Flags::OutPutStereo)) {
        else if (format.flags & static_cast<uint32_t>(AudioDevice::Flags::OutputStereo)) {
            saiOutFormat.stereo = kSAI_Stereo;
            OutStart();
        }

M module-bsp/bsp/audio/bsp_audio.cpp => module-bsp/bsp/audio/bsp_audio.cpp +5 -2
@@ 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<bsp::RT1051Audiocodec>(callback );
                inst = std::make_unique<bsp::RT1051Audiocodec>(callback);
#elif defined(TARGET_Linux)
                inst = std::make_unique<bsp::LinuxAudiocodec>(callback );
#else


@@ 36,6 38,7 @@ namespace bsp{
            case Type ::Bluetooth:
            {
#if defined(TARGET_RT1051)
                inst = std::make_unique<bsp::RT1051BluetoothAudio>(callback);

#elif defined(TARGET_Linux)



@@ 48,7 51,7 @@ namespace bsp{
            case Type::Cellular:
            {
#if defined(TARGET_RT1051)
                inst = std::make_unique<bsp::RT1051CellularAudio>(callback );
                inst = std::make_unique<bsp::RT1051CellularAudio>(callback);
#elif defined(TARGET_Linux)
                inst = std::make_unique<bsp::LinuxCellularAudio>(callback );
#else

M module-bsp/bsp/audio/bsp_audio.hpp => module-bsp/bsp/audio/bsp_audio.hpp +2 -1
@@ 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

M module-bsp/targets/Target_Linux.cmake => module-bsp/targets/Target_Linux.cmake +2 -0
@@ 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"


M module-bsp/targets/Target_RT1051.cmake => module-bsp/targets/Target_RT1051.cmake +1 -0
@@ 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}"

M module-services/service-audio/ServiceAudio.cpp => module-services/service-audio/ServiceAudio.cpp +4 -3
@@ 323,7 323,7 @@ std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleStart(const Operation:

std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleSendEvent(std::shared_ptr<Event> evt)
{
    if (evt->getType() == EventType::BTHeadsetOn) {
    if (evt->getType() == EventType::BTA2DPOn) {
        auto req = std::make_shared<BluetoothRequestStreamMessage>();
        sys::Bus::SendUnicast(req, service::name::bluetooth, this);
        return std::make_unique<AudioEventResponse>(RetCode::Success);


@@ 331,7 331,7 @@ std::unique_ptr<AudioResponseMessage> 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<BluetoothRequestStreamResultMessage *>(msgl);
        for (auto &input : audioMux.GetAllInputs()) {
            input.audio->SetBluetoothStreamData(msg->getData());
            input.audio->SendEvent(std::make_unique<Event>(EventType::BTHeadsetOn));
            input.audio->SendEvent(std::make_unique<Event>(EventType::BTA2DPOn));
            LOG_INFO("Queues received!");
        }
    }
    else {

M module-services/service-audio/messages/AudioMessage.hpp => module-services/service-audio/messages/AudioMessage.hpp +2 -2
@@ 7,8 7,8 @@
#include <variant>
#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
{

M module-services/service-bluetooth/ServiceBluetooth.cpp => module-services/service-bluetooth/ServiceBluetooth.cpp +11 -4
@@ 9,6 9,7 @@
#include "messages/BluetoothMessage.hpp"
#include <log/log.hpp>
#include <service-lwip/ServiceLwIP.hpp>
#include <module-sys/Service/Bus.hpp>

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<BluetoothAddrMessage *>(msg);
            worker->set_addr(addrMsg->addr);
        } break;
        case MessageType::BluetoothRequestStream: {
            auto result =
                std::make_shared<BluetoothRequestStreamResultMessage>(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<BluetoothAddrMessage *>(msg) != nullptr) {
        auto addrMsg = static_cast<BluetoothAddrMessage *>(msg);
        worker->set_addr(addrMsg->addr);
    }

    return std::make_shared<sys::ResponseMessage>();
}

M module-services/service-bluetooth/ServiceBluetoothCommon.hpp => module-services/service-bluetooth/ServiceBluetoothCommon.hpp +5 -0
@@ 5,10 5,15 @@

#include <FreeRTOS.h>
#include <queue.h>
#include <module-bluetooth/Bluetooth/Device.hpp>

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)
    {}
};

M module-services/service-evtmgr/EventManager.cpp => module-services/service-evtmgr/EventManager.cpp +1 -1
@@ 160,7 160,7 @@ sys::Message_t EventManager::DataReceivedHandler(sys::DataMessage *msgl, sys::Re

        handled = true;
    }
    else if (auto msg = dynamic_cast<AudioEventRequest *>(msgl); msg && msgl->sender == this->GetName()) {
    else if (auto msg = dynamic_cast<AudioEventRequest *>(msgl); msg /*&& msgl->sender == this->GetName()*/) {
        AudioServiceAPI::SendEvent(this, msg->getEvent());
        handled = true;
    }