~aleteoryx/muditaos

b7e1a04a125e28761d71d12124a1474cd8b2b4f1 — Hubert Chrzaniuk 5 years ago 4d4882d
[EGD-4301] Bluetooth Audio profile support (#984)

 - implemented audio sink/source switching
 - reorganized / renamed sound events
 - moved SetBluetoothStreamData and AudioDevice instance to base Operation class
 - added audio profiles RecordingBluetoothHSP, RoutingBluetoothHSP
 - removed unused audio Profiles
 - removed redundant OutputPath and InputPath classes from CodecParamsMAX98090
37 files changed, 456 insertions(+), 314 deletions(-)

M changelog.md
M module-apps/application-call/windows/CallWindow.cpp
M module-audio/Audio/Audio.cpp
M module-audio/Audio/Audio.hpp
M module-audio/Audio/AudioCommon.hpp
M module-audio/Audio/Operation/IdleOperation.cpp
M module-audio/Audio/Operation/Operation.cpp
M module-audio/Audio/Operation/Operation.hpp
M module-audio/Audio/Operation/PlaybackOperation.cpp
M module-audio/Audio/Operation/PlaybackOperation.hpp
M module-audio/Audio/Operation/RecorderOperation.cpp
M module-audio/Audio/Operation/RecorderOperation.hpp
M module-audio/Audio/Operation/RouterOperation.cpp
M module-audio/Audio/Operation/RouterOperation.hpp
M module-audio/Audio/Profiles/Profile.cpp
M module-audio/Audio/Profiles/Profile.hpp
M module-audio/Audio/Profiles/ProfilePlaybackBluetoothA2DP.hpp
A module-audio/Audio/Profiles/ProfileRecordingBluetoothHSP.hpp
R module-audio/Audio/Profiles/{ProfileRecordingHeadset => ProfileRecordingHeadphones}.hpp
A module-audio/Audio/Profiles/ProfileRoutingBluetoothHSP.hpp
R module-audio/Audio/Profiles/{ProfileRoutingHeadset => ProfileRoutingHeadphones}.hpp
R module-audio/Audio/Profiles/{ProfileRoutingSpeakerphone => ProfileRoutingLoudspeaker}.hpp
M module-audio/Audio/test/unittest_audio.cpp
M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp
M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DPImpl.hpp
M module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp
M module-bluetooth/Bluetooth/interface/profiles/HSP/HSPImpl.hpp
M module-bluetooth/Bluetooth/interface/profiles/HSP/SCO.cpp
M module-bsp/board/rt1051/bsp/audio/CodecMAX98090.cpp
M module-bsp/board/rt1051/bsp/audio/CodecMAX98090.hpp
M module-bsp/board/rt1051/bsp/audio/RT1051Audiocodec.cpp
M module-bsp/bsp/audio/bsp_audio.hpp
M module-services/service-audio/AudioServiceAPI.cpp
M module-services/service-audio/ServiceAudio.cpp
M module-services/service-audio/service-audio/AudioMessage.hpp
M module-services/service-audio/service-audio/AudioServiceAPI.hpp
M module-services/service-evtmgr/WorkerEvent.cpp
M changelog.md => changelog.md +1 -0
@@ 7,6 7,7 @@
* `[calendar]` Added a new field for date of the event when the user adds/edits event.
* `[file indexer db]` Added messages for File Indexer db.
* `[settings]` Added Torch window (front-end only).
* `[audio]` Added support for Bluetooth audio profiles

## Changed


M module-apps/application-call/windows/CallWindow.cpp => module-apps/application-call/windows/CallWindow.cpp +2 -2
@@ 97,10 97,10 @@ namespace gui

            switch (speakerIcon->get()) {
            case SpeakerIconState::SPEAKER: {
                AudioServiceAPI::SendEvent(this->application, audio::EventType::CallSpeakerphoneOff);
                AudioServiceAPI::SendEvent(this->application, audio::EventType::CallLoudspeakerOff);
            } break;
            case SpeakerIconState::SPEAKERON: {
                AudioServiceAPI::SendEvent(this->application, audio::EventType::CallSpeakerphoneOn);
                AudioServiceAPI::SendEvent(this->application, audio::EventType::CallLoudspeakerOn);
            } break;
            // case SpeakerIconState::BLUETOOTH: {
            //     // TODO: need implementation

M module-audio/Audio/Audio.cpp => module-audio/Audio/Audio.cpp +18 -27
@@ 16,9 16,9 @@ namespace audio

        auto ret = Operation::Create(Operation::Type::Idle, "", audio::PlaybackType::None, dbCallback);
        if (ret) {
            currentOperation = std::move(ret.value());
            currentOperation = std::move(ret);
        }
        lineSinkAvailable = bsp::headset::IsInserted();
        audioSinkState.setConnected(EventType::JackState, bsp::headset::IsInserted());
    }

    Position Audio::GetPosition()


@@ 39,23 39,8 @@ namespace audio

    audio::RetCode Audio::SendEvent(std::shared_ptr<Event> evt)
    {
        switch (evt->getType()) {
        case EventType::HeadphonesPlugin:
            lineSinkAvailable = true;
            break;
        case EventType::HeadphonesUnplug:
            lineSinkAvailable = false;
            break;
        case EventType::BTA2DPOn:
            btSinkAvailable = true;
            break;
        case EventType::BTA2DPOff:
            btSinkAvailable = false;
            break;
        default:
            break;
        }

        audioSinkState.UpdateState(evt);
        UpdateProfiles();
        return currentOperation->SendEvent(std::move(evt));
    }



@@ 106,20 91,17 @@ namespace audio
            case Operation::Type::Idle:
                break;
            }
            currentOperation = std::move(ret.value());
            currentOperation = std::move(ret);
            UpdateProfiles();

            if (lineSinkAvailable) {
                currentOperation->SendEvent(std::make_unique<Event>(EventType::HeadphonesPlugin));
            }
            if (btSinkAvailable && btData) {
                currentOperation->SendEvent(std::make_unique<Event>(EventType::BTA2DPOn));
            if (btData) {
                currentOperation->SetBluetoothStreamData(btData);
            }
        }
        else {
            // If creating operation failed fallback to IdleOperation which is guaranteed to work
            LOG_ERROR("Failed to create operation type %s", Operation::c_str(op));
            currentOperation = Operation::Create(Operation::Type::Idle).value_or(nullptr);
            currentOperation = Operation::Create(Operation::Type::Idle);
            currentState     = State ::Idle;
            return RetCode::OperationCreateFailed;
        }


@@ 150,7 132,7 @@ namespace audio
        auto ret = Operation::Create(Operation::Type::Idle);
        if (ret) {
            currentState     = State::Idle;
            currentOperation = std::move(ret.value());
            currentOperation = std::move(ret);
            return RetCode::Success;
        }
        else {


@@ 185,4 167,13 @@ namespace audio
        btData = data;
    }

    void Audio::UpdateProfiles()
    {
        auto updateEvents = audioSinkState.getUpdateEvents();
        for (auto &event : updateEvents) {
            currentOperation->SendEvent(event);
        }
        currentOperation->SwitchToPriorityProfile();
    }

} // namespace audio

M module-audio/Audio/Audio.hpp => module-audio/Audio/Audio.hpp +12 -9
@@ 6,6 6,7 @@
#include <memory>
#include <optional>
#include <functional>
#include <bitset>

#include <service-bluetooth/ServiceBluetoothCommon.hpp>



@@ 76,14 77,15 @@ namespace audio
            return GetCurrentOperation().GetState();
        }

        [[nodiscard]] inline bool IsLineSinkAvailable() const
        audio::Profile::Type GetPriorityPlaybackProfile() const
        {
            return lineSinkAvailable;
        }

        [[nodiscard]] inline bool IsBtSinkAvailable() const
        {
            return lineSinkAvailable;
            if (audioSinkState.isConnected(EventType::BlutoothA2DPDeviceState)) {
                return Profile::Type::PlaybackBluetoothA2DP;
            }
            if (audioSinkState.isConnected(EventType::JackState)) {
                return Profile::Type::PlaybackHeadphones;
            }
            return Profile::Type::PlaybackLoudspeaker;
        }

        // Operations


@@ 105,8 107,9 @@ namespace audio
        virtual void SetBluetoothStreamData(std::shared_ptr<BluetoothStreamData> data);

      private:
        bool lineSinkAvailable = false;
        bool btSinkAvailable   = false;
        void UpdateProfiles();
        AudioSinkState audioSinkState;

        std::shared_ptr<BluetoothStreamData> btData;

        State currentState = State::Idle;

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

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

#include "Profiles/Profile.hpp"



@@ 68,32 70,86 @@ namespace audio

    enum class EventType
    {
        HeadphonesPlugin,
        HeadphonesUnplug,
        BTHeadsetOn,
        BTHeadsetOff,
        BTA2DPOn,
        BTA2DPOff,
        // HW state change notifications
        JackState,               //!< jack input plugged / unplugged event
        BlutoothHSPDeviceState,  //!< BT device connected / disconnected event (Headset Profile)
        BlutoothA2DPDeviceState, //!< BT device connected / disconnected event (Advanced Audio Distribution Profile)

        // call control
        CallMute,
        CallUnmute,
        CallSpeakerphoneOn,
        CallSpeakerphoneOff,
        CallLoudspeakerOn,
        CallLoudspeakerOff,
    };

    constexpr auto hwStateUpdateMaxEvent = magic_enum::enum_index(EventType::BlutoothA2DPDeviceState);

    class Event
    {
      public:
        explicit Event(EventType eType) : eventType(eType)
        enum class DeviceState
        {
            Connected,
            Disconnected
        };

        explicit Event(EventType eType, DeviceState deviceState = DeviceState::Connected)
            : eventType(eType), deviceState(deviceState)
        {}

        virtual ~Event() = default;

        EventType getType() const
        EventType getType() const noexcept
        {
            return eventType;
        }

        DeviceState getDeviceState() const noexcept
        {
            return deviceState;
        }

      private:
        const EventType eventType;
        const DeviceState deviceState;
    };

    class AudioSinkState
    {
      public:
        void UpdateState(std::shared_ptr<Event> stateChangeEvent)
        {
            auto hwUpdateEventIdx = magic_enum::enum_integer(stateChangeEvent->getType());
            if (hwUpdateEventIdx <= hwStateUpdateMaxEvent) {
                audioSinkState.set(hwUpdateEventIdx,
                                   stateChangeEvent->getDeviceState() == Event::DeviceState::Connected ? true : false);
            }
        }

        std::vector<std::shared_ptr<Event>> getUpdateEvents() const
        {
            std::vector<std::shared_ptr<Event>> updateEvents;
            for (size_t i = 0; i < hwStateUpdateMaxEvent; i++) {
                auto isConnected =
                    audioSinkState.test(i) ? Event::DeviceState::Connected : Event::DeviceState::Disconnected;
                auto updateEvt = magic_enum::enum_cast<EventType>(i);
                updateEvents.emplace_back(std::make_unique<Event>(updateEvt.value(), isConnected));
            }
            return updateEvents;
        }

        bool isConnected(EventType deviceUpdateEvent) const
        {
            return audioSinkState.test(magic_enum::enum_integer(deviceUpdateEvent));
        }

        void setConnected(EventType deviceUpdateEvent, bool isConnected)
        {
            audioSinkState.set(magic_enum::enum_integer(deviceUpdateEvent), isConnected);
        }

      private:
        std::bitset<magic_enum::enum_count<EventType>()> audioSinkState;
    };

    enum class RetCode

M module-audio/Audio/Operation/IdleOperation.cpp => module-audio/Audio/Operation/IdleOperation.cpp +2 -2
@@ 10,8 10,8 @@ namespace audio

    IdleOperation::IdleOperation([[maybe_unused]] const char *file) : Operation{true}
    {
        availableProfiles.push_back(Profile::Create(Profile::Type::Idle, nullptr));
        currentProfile = availableProfiles[0];
        supportedProfiles.emplace_back(Profile::Create(Profile::Type::Idle, nullptr), true);
        currentProfile = supportedProfiles[0].profile;
    }

    audio::RetCode IdleOperation::SetOutputVolume(float vol)

M module-audio/Audio/Operation/Operation.cpp => module-audio/Audio/Operation/Operation.cpp +40 -8
@@ 10,12 10,14 @@
#include "RecorderOperation.hpp"
#include "RouterOperation.hpp"

#include "bsp/audio/bsp_audio.hpp"
#include "Audio/decoder/decoder.hpp"

#include <bsp/audio/bsp_audio.hpp>
#include <module-bsp/board/rt1051/bsp/audio/RT1051BluetoothAudio.hpp>

namespace audio
{
    std::optional<std::unique_ptr<Operation>> Operation::Create(
    std::unique_ptr<Operation> Operation::Create(
        Operation::Type t,
        const char *fileName,
        const audio::PlaybackType &playbackType,


@@ 48,16 50,46 @@ namespace audio
        }
    }

    std::optional<std::shared_ptr<Profile>> Operation::GetProfile(const Profile::Type type)
    std::shared_ptr<Profile> Operation::GetProfile(const Profile::Type type)
    {
        auto ret = std::find_if(
            availableProfiles.begin(), availableProfiles.end(), [type](const auto &w) { return w->GetType() == type; });
        if (ret == availableProfiles.end()) {
            return std::nullopt;
        auto ret = std::find_if(supportedProfiles.begin(), supportedProfiles.end(), [type](const auto &w) {
            return w.isAvailable == true && w.profile->GetType() == type;
        });
        if (ret == supportedProfiles.end()) {
            return nullptr;
        }
        else {
            return *ret;
            return ret->profile;
        }
    }

    void Operation::SetBluetoothStreamData(std::shared_ptr<BluetoothStreamData> data)
    {
        if (auto device = dynamic_cast<bsp::RT1051BluetoothAudio *>(audioDevice.get()); device != nullptr) {
            GetProfile()->SetSampleRate(data->metadata.sampleRate);
            device->sourceQueue = data->out;
            device->metadata    = data->metadata;
            LOG_INFO("Queue and metadata set!");
        }
    }

    audio::RetCode Operation::SwitchToPriorityProfile()
    {
        for (auto &p : supportedProfiles) {
            if (p.isAvailable == true) {
                return SwitchProfile(p.profile->GetType());
            }
        }
        return audio::RetCode::Failed;
    }

    void Operation::SetProfileAvailability(std::vector<Profile::Type> profiles, bool available)
    {
        for (auto &p : supportedProfiles) {
            if (auto shouldSet = (std::find(profiles.begin(), profiles.end(), p.profile->GetType()) != profiles.end());
                shouldSet) {
                p.isAvailable = available;
            }
        }
    }
} // namespace audio

M module-audio/Audio/Operation/Operation.hpp => module-audio/Audio/Operation/Operation.hpp +23 -5
@@ 55,7 55,7 @@ namespace audio

        virtual ~Operation() = default;

        static std::optional<std::unique_ptr<Operation>> Create(
        static std::unique_ptr<Operation> Create(
            Type t,
            const char *fileName                  = "",
            const audio::PlaybackType &operations = audio::PlaybackType::None,


@@ 70,7 70,7 @@ namespace audio
        virtual audio::RetCode SetInputGain(float gain) = 0;

        virtual Position GetPosition() = 0;
        virtual void SetBluetoothStreamData(std::shared_ptr<BluetoothStreamData> data) = 0;
        virtual void SetBluetoothStreamData(std::shared_ptr<BluetoothStreamData> data);

        Volume GetOutputVolume() const
        {


@@ 87,7 87,7 @@ namespace audio
            return state;
        }

        const std::shared_ptr<const Profile> GetProfile() const
        const std::shared_ptr<Profile> GetProfile() const
        {
            return currentProfile;
        }


@@ 112,12 112,30 @@ namespace audio
            return filePath;
        }

        audio::RetCode SwitchToPriorityProfile();

      protected:
        struct SupportedProfile
        {
            SupportedProfile(std::shared_ptr<Profile> profile, bool isAvailable)
                : profile(std::move(profile)), isAvailable(isAvailable)
            {}

            std::shared_ptr<Profile> profile;
            bool isAvailable;
        };

        std::shared_ptr<Profile> currentProfile;
        std::vector<std::shared_ptr<Profile>> availableProfiles;
        std::unique_ptr<bsp::AudioDevice> audioDevice;

        std::vector<SupportedProfile> supportedProfiles;
        void SetProfileAvailability(std::vector<Profile::Type> profiles, bool available);

        State state = State::Idle;
        audio::AsyncCallback eventCallback;

        AudioSinkState audioSinkState;

        audio::Token operationToken;
        Type opType = Type::Idle;
        std::string filePath;


@@ 127,7 145,7 @@ namespace audio

        virtual audio::RetCode SwitchProfile(const Profile::Type type) = 0;

        std::optional<std::shared_ptr<Profile>> GetProfile(const Profile::Type type);
        std::shared_ptr<Profile> GetProfile(const Profile::Type type);

        std::function<int32_t(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer)>
            audioCallback = nullptr;

M module-audio/Audio/Operation/PlaybackOperation.cpp => module-audio/Audio/Operation/PlaybackOperation.cpp +29 -34
@@ 5,16 5,11 @@

#include "Audio/decoder/decoder.hpp"
#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>
#include <log/log.hpp>
#include <FreeRTOS.h>
#include <task.h>

namespace audio
{


@@ 56,20 51,28 @@ namespace audio
            audio::dbPath(audio::Setting::Volume, playbackType, audio::Profile::Type::PlaybackHeadphones);
        const auto headphonesVolume = dbCallback(dbHeadphonesVolumePath, defaultHeadphonesVolume);

        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];
        // order in vector defines priority
        supportedProfiles.emplace_back(
            Profile::Create(Profile::Type::PlaybackBluetoothA2DP, nullptr, loudspeakerVolume), false);
        supportedProfiles.emplace_back(Profile::Create(Profile::Type::PlaybackHeadphones, nullptr, headphonesVolume),
                                       false);
        supportedProfiles.emplace_back(Profile::Create(Profile::Type::PlaybackLoudspeaker, nullptr, loudspeakerVolume),
                                       true);

        auto defaultProfile = GetProfile(Profile::Type::PlaybackLoudspeaker);
        if (!defaultProfile) {
            LOG_ERROR("Error during initializing profile");
            return;
        }
        currentProfile = defaultProfile;

        dec = decoder::Create(file);
        if (dec == nullptr) {
            LOG_ERROR("Error during initializing decoder");
            return;
        }
        audioDevice = bsp::AudioDevice::Create(currentProfile->GetAudioDeviceType(), audioCallback).value_or(nullptr);
        if (audioDevice == nullptr) {
            LOG_ERROR("Error creating AudioDevice");

        if (SwitchToPriorityProfile() != audio::RetCode::Success) {
            return;
        }



@@ 149,40 152,41 @@ namespace audio

    audio::RetCode PlaybackOperation::SendEvent(std::shared_ptr<Event> evt)
    {

        auto isAvailable = evt->getDeviceState() == Event::DeviceState::Connected ? true : false;
        switch (evt->getType()) {
        case EventType::HeadphonesPlugin:
            SwitchProfile(Profile::Type::PlaybackHeadphones);
            break;
        case EventType::HeadphonesUnplug:
            // TODO: Switch to playback headphones/bt profile if present
            SwitchProfile(Profile::Type::PlaybackLoudspeaker);
        case EventType::JackState:
            SetProfileAvailability({Profile::Type::PlaybackHeadphones}, isAvailable);
            SwitchToPriorityProfile();
            break;
        case EventType::BTA2DPOn:
            // TODO: Switch to playback headphones/bt profile if present
            SwitchProfile(Profile::Type::PlaybackBTA2DP);
        case EventType::BlutoothA2DPDeviceState:
            SetProfileAvailability({Profile::Type::PlaybackBluetoothA2DP}, isAvailable);
            SwitchToPriorityProfile();
            break;
        default:
            return RetCode::UnsupportedEvent;
        }

        return RetCode::Success;
    }

    audio::RetCode PlaybackOperation::SwitchProfile(const Profile::Type type)
    {

        uint32_t currentSampleRate = currentProfile->GetSampleRate();
        uint32_t currentInOutFlags = currentProfile->GetInOutFlags();

        auto ret = GetProfile(type);
        if (ret) {
            currentProfile = ret.value();
            currentProfile = ret;
        }
        else {
            return RetCode::UnsupportedProfile;
        }

        audioDevice = bsp::AudioDevice::Create(currentProfile->GetAudioDeviceType(), audioCallback).value_or(nullptr);
        if (audioDevice == nullptr) {
            LOG_ERROR("Error creating AudioDevice");
            return RetCode::Failed;
        }

        currentProfile->SetSampleRate(currentSampleRate);
        currentProfile->SetInOutFlags(currentInOutFlags);


@@ 206,13 210,4 @@ namespace audio
        Stop();
    }

    void PlaybackOperation::SetBluetoothStreamData(std::shared_ptr<BluetoothStreamData> data)
    {
        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/Operation/PlaybackOperation.hpp => module-audio/Audio/Operation/PlaybackOperation.hpp +0 -2
@@ 38,11 38,9 @@ namespace audio
        audio::RetCode SetInputGain(float gain) final;

        Position GetPosition() final;
        void SetBluetoothStreamData(std::shared_ptr<BluetoothStreamData> data) final;

      private:
        std::unique_ptr<decoder> dec;
        std::unique_ptr<bsp::AudioDevice> audioDevice;
        std::unique_ptr<Tags> tags;
    };


M module-audio/Audio/Operation/RecorderOperation.cpp => module-audio/Audio/Operation/RecorderOperation.cpp +29 -29
@@ 5,7 5,7 @@
#include "Audio/encoder/Encoder.hpp"
#include "bsp/audio/bsp_audio.hpp"
#include "Audio/Profiles/Profile.hpp"
#include "Audio/Profiles/ProfileRecordingHeadset.hpp"
#include "Audio/Profiles/ProfileRecordingHeadphones.hpp"
#include "Audio/Profiles/ProfileRecordingOnBoardMic.hpp"
#include "Audio/AudioCommon.hpp"



@@ 50,14 50,23 @@ namespace audio
        const auto recordingOnBoardMicGain = dbCallback(dbRecordingOnBoardMicGainPath, defaultRecordingOnBoardMicGain);

        const auto dbRecordingHeadsetGainPath =
            audio::dbPath(audio::Setting::Gain, audio::PlaybackType::None, audio::Profile::Type::RecordingHeadset);
            audio::dbPath(audio::Setting::Gain, audio::PlaybackType::None, audio::Profile::Type::RecordingHeadphones);
        const auto recordingHeadsetGain = dbCallback(dbRecordingHeadsetGainPath, defaultRecordingHeadsetGain);

        availableProfiles.push_back(
            Profile::Create(Profile::Type::RecordingBuiltInMic, nullptr, 0, recordingOnBoardMicGain));
        availableProfiles.push_back(Profile::Create(Profile::Type::RecordingHeadset, nullptr, 0, recordingHeadsetGain));

        currentProfile = availableProfiles[0];
        // order in vector defines priority
        supportedProfiles.emplace_back(
            Profile::Create(Profile::Type::RecordingBluetoothHSP, nullptr, 0, recordingHeadsetGain), false);
        supportedProfiles.emplace_back(
            Profile::Create(Profile::Type::RecordingHeadphones, nullptr, 0, recordingHeadsetGain), false);
        supportedProfiles.emplace_back(
            Profile::Create(Profile::Type::RecordingBuiltInMic, nullptr, 0, recordingOnBoardMicGain), true);

        auto defaultProfile = GetProfile(Profile::Type::PlaybackLoudspeaker);
        if (!defaultProfile) {
            LOG_ERROR("Error during initializing profile");
            return;
        }
        currentProfile = defaultProfile;

        uint32_t channels = 0;
        if ((currentProfile->GetInOutFlags() & static_cast<uint32_t>(AudioDevice::Flags::InputLeft)) ||


@@ 69,15 78,12 @@ namespace audio
        }

        enc = Encoder::Create(file, Encoder::Format{.chanNr = channels, .sampleRate = currentProfile->GetSampleRate()});

        if (enc == nullptr) {
            LOG_ERROR("Error during initializing encoder");
            return;
        }

        audioDevice = AudioDevice::Create(currentProfile->GetAudioDeviceType(), audioCallback).value_or(nullptr);
        if (audioDevice == nullptr) {
            LOG_ERROR("Error creating AudioDevice");
        if (SwitchToPriorityProfile() != audio::RetCode::Success) {
            return;
        }



@@ 139,20 145,15 @@ namespace audio

    audio::RetCode RecorderOperation::SendEvent(std::shared_ptr<Event> evt)
    {
        auto isAvailable = evt->getDeviceState() == Event::DeviceState::Connected ? true : false;
        switch (evt->getType()) {
        case EventType::HeadphonesPlugin:
            SwitchProfile(Profile::Type::RecordingHeadset);
            break;
        case EventType::HeadphonesUnplug:
            // TODO: Switch to recording bt profile if present
            SwitchProfile(Profile::Type::RecordingBuiltInMic);
        case EventType::JackState:
            SetProfileAvailability({Profile::Type::RecordingHeadphones}, isAvailable);
            SwitchToPriorityProfile();
            break;
        case EventType::BTHeadsetOn:
            SwitchProfile(Profile::Type::RecordingBTHeadset);
            break;
        case EventType::BTHeadsetOff:
            // TODO: Switch to recording headphones profile if present
            SwitchProfile(Profile::Type::RecordingBuiltInMic);
        case EventType::BlutoothHSPDeviceState:
            SetProfileAvailability({Profile::Type::RecordingBluetoothHSP}, isAvailable);
            SwitchToPriorityProfile();
            break;
        default:
            return RetCode::UnsupportedEvent;


@@ 166,13 167,17 @@ namespace audio

        auto ret = GetProfile(type);
        if (ret) {
            currentProfile = ret.value();
            currentProfile = ret;
        }
        else {
            return RetCode::UnsupportedProfile;
        }

        audioDevice = AudioDevice::Create(currentProfile->GetAudioDeviceType(), audioCallback).value_or(nullptr);
        if (audioDevice == nullptr) {
            LOG_ERROR("Error creating AudioDevice");
            return RetCode::Failed;
        }

        switch (state) {
        case State::Idle:


@@ 206,9 211,4 @@ namespace audio
    {
        return enc->getCurrentPosition();
    }

    void RecorderOperation::SetBluetoothStreamData(std::shared_ptr<BluetoothStreamData> data)
    {
        LOG_ERROR("UNIMPLEMENTED");
    }
} // namespace audio

M module-audio/Audio/Operation/RecorderOperation.hpp => module-audio/Audio/Operation/RecorderOperation.hpp +0 -2
@@ 26,7 26,6 @@ namespace audio
        audio::RetCode SetInputGain(float gain) final;

        Position GetPosition() final;
        void SetBluetoothStreamData(std::shared_ptr<BluetoothStreamData> data) final;

        uint32_t GetSize()
        {


@@ 35,7 34,6 @@ namespace audio

      private:
        std::unique_ptr<Encoder> enc;
        std::unique_ptr<bsp::AudioDevice> audioDevice;
    };

} // namespace audio

M module-audio/Audio/Operation/RouterOperation.cpp => module-audio/Audio/Operation/RouterOperation.cpp +60 -48
@@ 104,8 104,8 @@ namespace audio
        constexpr audio::Volume defaultRoutingEarspeakerVolume   = 10;
        constexpr audio::Gain defaultRoutingSpeakerphoneGain     = 20;
        constexpr audio::Volume defaultRoutingSpeakerphoneVolume = 10;
        constexpr audio::Gain defaultRoutingHeadsetGain          = 50;
        constexpr audio::Volume defaultRoutingHeadsetVolume      = 10;
        constexpr audio::Gain defaultRoutingHeadphonesGain       = 50;
        constexpr audio::Volume defaultRoutingHeadphonesVolume   = 10;

        const auto dbRoutingEarspeakerGainPath =
            audio::dbPath(audio::Setting::Gain, audio::PlaybackType::None, audio::Profile::Type::RoutingEarspeaker);


@@ 113,40 113,44 @@ namespace audio
        const auto dbRoutingEarspeakerVolumePath =
            audio::dbPath(audio::Setting::Volume, audio::PlaybackType::None, audio::Profile::Type::RoutingEarspeaker);
        const auto routingEarspeakerVolume = dbCallback(dbRoutingEarspeakerVolumePath, defaultRoutingEarspeakerVolume);
        const auto dbRoutingSpeakerphoneGainPath =
            audio::dbPath(audio::Setting::Gain, audio::PlaybackType::None, audio::Profile::Type::RoutingSpeakerphone);
        const auto routingSpeakerphoneGain = dbCallback(dbRoutingSpeakerphoneGainPath, defaultRoutingSpeakerphoneGain);
        const auto dbRoutingSpeakerphoneVolumePath =
            audio::dbPath(audio::Setting::Volume, audio::PlaybackType::None, audio::Profile::Type::RoutingSpeakerphone);
        const auto routingSpeakerphoneVolume =
            dbCallback(dbRoutingSpeakerphoneVolumePath, defaultRoutingSpeakerphoneVolume);
        const auto dbRoutingLoudspeakerGainPath =
            audio::dbPath(audio::Setting::Gain, audio::PlaybackType::None, audio::Profile::Type::RoutingLoudspeaker);
        const auto routingLoudspeakerGain = dbCallback(dbRoutingLoudspeakerGainPath, defaultRoutingSpeakerphoneGain);
        const auto dbRoutingLoudspeakerVolumePath =
            audio::dbPath(audio::Setting::Volume, audio::PlaybackType::None, audio::Profile::Type::RoutingLoudspeaker);
        const auto routingLoudspeakerVolume =
            dbCallback(dbRoutingLoudspeakerVolumePath, defaultRoutingSpeakerphoneVolume);
        const auto dbRoutingHeadsetGainPath =
            audio::dbPath(audio::Setting::Gain, audio::PlaybackType::None, audio::Profile::Type::RoutingHeadset);
        const auto routingHeadsetGain = dbCallback(dbRoutingHeadsetGainPath, defaultRoutingHeadsetGain);
        const auto dbRoutingHeadsetVolumePath =
            audio::dbPath(audio::Setting::Volume, audio::PlaybackType::None, audio::Profile::Type::RoutingHeadset);
        const auto routingHeadsetVolume = dbCallback(dbRoutingHeadsetVolumePath, defaultRoutingHeadsetVolume);

        availableProfiles.push_back(
            Profile::Create(Profile::Type::RoutingEarspeaker, nullptr, routingEarspeakerVolume, routingEarspeakerGain));
        availableProfiles.push_back(Profile::Create(
            Profile::Type::RoutingSpeakerphone, nullptr, routingSpeakerphoneVolume, routingSpeakerphoneGain));
        availableProfiles.push_back(
            Profile::Create(Profile::Type::RoutingHeadset, nullptr, routingHeadsetVolume, routingHeadsetGain));

        currentProfile = availableProfiles[0];

        audioDevice =
            bsp::AudioDevice::Create(currentProfile->GetAudioDeviceType(), audioDeviceCallback).value_or(nullptr);
        if (audioDevice == nullptr) {
            LOG_ERROR("Error creating AudioDevice");
            audio::dbPath(audio::Setting::Gain, audio::PlaybackType::None, audio::Profile::Type::RoutingHeadphones);
        const auto routingHeadphonesGain = dbCallback(dbRoutingHeadsetGainPath, defaultRoutingHeadphonesGain);
        const auto dbRoutingHeadphonesVolumePath =
            audio::dbPath(audio::Setting::Volume, audio::PlaybackType::None, audio::Profile::Type::RoutingHeadphones);
        const auto routingHeadphonesVolume = dbCallback(dbRoutingHeadphonesVolumePath, defaultRoutingHeadphonesVolume);

        // order in vector defines priority
        supportedProfiles.emplace_back(
            Profile::Create(
                Profile::Type::RoutingBluetoothHSP, nullptr, routingHeadphonesVolume, routingHeadphonesGain),
            false);
        supportedProfiles.emplace_back(
            Profile::Create(Profile::Type::RoutingHeadphones, nullptr, routingHeadphonesVolume, routingHeadphonesGain),
            false);
        supportedProfiles.emplace_back(
            Profile::Create(Profile::Type::RoutingEarspeaker, nullptr, routingEarspeakerVolume, routingEarspeakerGain),
            true);
        supportedProfiles.emplace_back(
            Profile::Create(
                Profile::Type::RoutingLoudspeaker, nullptr, routingLoudspeakerVolume, routingLoudspeakerGain),
            true);

        auto defaultProfile = GetProfile(Profile::Type::PlaybackLoudspeaker);
        if (!defaultProfile) {
            LOG_ERROR("Error during initializing profile");
            return;
        }
        currentProfile = defaultProfile;

        audioDeviceCellular =
            bsp::AudioDevice::Create(bsp::AudioDevice::Type::Cellular, audioDeviceCellularCallback).value_or(nullptr);
        if (audioDeviceCellular == nullptr) {
            LOG_ERROR("Error creating AudioDeviceCellular");
        if (SwitchToPriorityProfile() != audio::RetCode::Success) {
            return;
        }



@@ 234,12 238,22 @@ namespace audio

    audio::RetCode RouterOperation::SendEvent(std::shared_ptr<Event> evt)
    {
        auto isAvailable = evt->getDeviceState() == Event::DeviceState::Connected ? true : false;

        switch (evt->getType()) {
        case EventType::HeadphonesPlugin:
            SwitchProfile(Profile::Type::RoutingHeadset);
        case EventType::JackState:
            SetProfileAvailability({Profile::Type::RoutingHeadphones}, isAvailable);
            SwitchToPriorityProfile();
            break;
        case EventType::BlutoothHSPDeviceState:
            SetProfileAvailability({Profile::Type::RoutingBluetoothHSP}, isAvailable);
            SwitchToPriorityProfile();
            break;
        case EventType::HeadphonesUnplug:
            SwitchProfile(Profile::Type::RoutingEarspeaker);
        case EventType::CallLoudspeakerOn:
            SwitchProfile(Profile::Type::RoutingLoudspeaker);
            break;
        case EventType::CallLoudspeakerOff:
            SwitchToPriorityProfile();
            break;
        case EventType::CallMute:
            Mute(true);


@@ 247,12 261,6 @@ namespace audio
        case EventType::CallUnmute:
            Mute(false);
            break;
        case EventType::CallSpeakerphoneOn:
            SwitchProfile(Profile::Type::RoutingSpeakerphone);
            break;
        case EventType::CallSpeakerphoneOff:
            SwitchProfile(Profile::Type::RoutingEarspeaker);
            break;
        default:
            return RetCode::UnsupportedEvent;
        }


@@ 264,7 272,7 @@ namespace audio
    {
        auto ret = GetProfile(type);
        if (ret) {
            currentProfile = ret.value();
            currentProfile = ret;
        }
        else {
            return RetCode::UnsupportedProfile;


@@ 272,8 280,17 @@ namespace audio

        audioDevice =
            bsp::AudioDevice::Create(currentProfile->GetAudioDeviceType(), audioDeviceCallback).value_or(nullptr);
        if (audioDevice == nullptr) {
            LOG_ERROR("Error creating AudioDevice");
            return RetCode::Failed;
        }

        audioDeviceCellular =
            bsp::AudioDevice::Create(bsp::AudioDevice::Type::Cellular, audioDeviceCellularCallback).value_or(nullptr);
        if (audioDeviceCellular == nullptr) {
            LOG_ERROR("Error creating AudioDeviceCellular");
            return RetCode::Failed;
        }

        switch (state) {
        case State::Idle:


@@ 300,9 317,4 @@ namespace audio
        return 0.0;
    }

    void RouterOperation::SetBluetoothStreamData(std::shared_ptr<BluetoothStreamData> data)
    {
        LOG_ERROR("UNIMPLEMENTED");
    }

} // namespace audio

M module-audio/Audio/Operation/RouterOperation.hpp => module-audio/Audio/Operation/RouterOperation.hpp +0 -2
@@ 42,7 42,6 @@ namespace audio
        audio::RetCode SetInputGain(float gain) final;

        Position GetPosition() final;
        void SetBluetoothStreamData(std::shared_ptr<BluetoothStreamData> data) final;

      private:
        bool Mute(bool enable);


@@ 51,7 50,6 @@ namespace audio

        std::unique_ptr<Encoder> enc;

        std::unique_ptr<bsp::AudioDevice> audioDevice;
        std::unique_ptr<bsp::AudioDevice> audioDeviceCellular;

        AudioCallback audioDeviceCallback         = nullptr;

M module-audio/Audio/Profiles/Profile.cpp => module-audio/Audio/Profiles/Profile.cpp +18 -12
@@ 6,14 6,16 @@
#include "ProfileIdle.hpp"

#include "ProfileRecordingOnBoardMic.hpp"
#include "ProfileRecordingHeadset.hpp"
#include "ProfileRecordingHeadphones.hpp"
#include "ProfileRecordingBluetoothHSP.hpp"

#include "ProfilePlaybackHeadphones.hpp"
#include "ProfilePlaybackLoudspeaker.hpp"

#include "ProfileRoutingEarspeaker.hpp"
#include "ProfileRoutingHeadset.hpp"
#include "ProfileRoutingSpeakerphone.hpp"
#include "ProfileRoutingHeadphones.hpp"
#include "ProfileRoutingLoudspeaker.hpp"
#include "ProfileRoutingBluetoothHSP.hpp"

#include "ProfilePlaybackBluetoothA2DP.hpp"



@@ 33,29 35,33 @@ namespace audio
        case Type::PlaybackLoudspeaker:
            inst = std::make_unique<ProfilePlaybackLoudspeaker>(callback, vol);
            break;
        case Type::PlaybackBTA2DP:
        case Type::PlaybackBluetoothA2DP:
            inst = std::make_unique<ProfilePlaybackBluetoothA2DP>(callback, vol);
            break;
        case Type::RecordingBuiltInMic:
            inst = std::make_unique<ProfileRecordingOnBoardMic>(callback, gain);
            break;
        case Type::RecordingHeadset:
            inst = std::make_unique<ProfileRecordingHeadset>(callback, gain);
        case Type::RecordingHeadphones:
            inst = std::make_unique<ProfileRecordingHeadphones>(callback, gain);
            break;
        case Type::RoutingHeadset:
            inst = std::make_unique<ProfileRoutingHeadset>(callback, vol, gain);
        case Type::RecordingBluetoothHSP:
            inst = std::make_unique<ProfileRecordingBluetoothHSP>(callback, gain);
            break;
        case Type::RoutingSpeakerphone:
            inst = std::make_unique<ProfileRoutingSpeakerphone>(callback, vol, gain);
        case Type::RoutingHeadphones:
            inst = std::make_unique<ProfileRoutingHeadphones>(callback, vol, gain);
            break;
        case Type::RoutingLoudspeaker:
            inst = std::make_unique<ProfileRoutingLoudspeaker>(callback, vol, gain);
            break;
        case Type::RoutingEarspeaker:
            inst = std::make_unique<ProfileRoutingEarspeaker>(callback, vol, gain);
            break;
        case Type::RoutingBluetoothHSP:
            inst = std::make_unique<ProfileRoutingBluetoothHSP>(callback, vol, gain);
            break;
        case Type::Idle:
            inst = std::make_unique<ProfileIdle>();
            break;
        default:
            break;
        }

        return inst;

M module-audio/Audio/Profiles/Profile.hpp => module-audio/Audio/Profiles/Profile.hpp +5 -11
@@ 23,26 23,20 @@ namespace audio
        enum class Type
        {
            // Profiles used only during call
            RoutingSpeakerphone,
            RoutingHeadset,
            RoutingBTHeadset,
            RoutingLoudspeaker,
            RoutingHeadphones,
            RoutingEarspeaker,
            RoutingBluetoothHSP,

            // Recording profiles
            RecordingBuiltInMic,
            RecordingHeadset,
            RecordingBTHeadset,
            RecordingHeadphones,
            RecordingBluetoothHSP,

            // Profiles used by music player
            PlaybackLoudspeaker,
            PlaybackHeadphones,
            PlaybackBTA2DP,

            // Profiles used by system sounds
            SystemSoundLoudspeaker,
            SystemSoundHeadphones,
            SystemSoundBTA2DP,
            PlaybackBluetoothA2DP,

            Idle,


M module-audio/Audio/Profiles/ProfilePlaybackBluetoothA2DP.hpp => module-audio/Audio/Profiles/ProfilePlaybackBluetoothA2DP.hpp +2 -2
@@ 13,8 13,8 @@ namespace audio
    {
      public:
        ProfilePlaybackBluetoothA2DP(std::function<int32_t()> callback, Volume volume)
            : Profile("Playback A2DP",
                      Type::PlaybackBTA2DP,
            : Profile("Playback Bluetooth A2DP",
                      Type::PlaybackBluetoothA2DP,
                      bsp::AudioDevice::Format{.sampleRate_Hz = 44100,
                                               .bitWidth      = 16,
                                               .flags         = 0,

A module-audio/Audio/Profiles/ProfileRecordingBluetoothHSP.hpp => module-audio/Audio/Profiles/ProfileRecordingBluetoothHSP.hpp +31 -0
@@ 0,0 1,31 @@
// 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"

namespace audio
{

    class ProfileRecordingBluetoothHSP : public Profile
    {
      public:
        ProfileRecordingBluetoothHSP(std::function<int32_t()> callback, Gain gain)
            : Profile(
                  "Recording Bluetooth HSP",
                  Type::RecordingHeadphones,
                  bsp::AudioDevice::Format{.sampleRate_Hz = 8000,
                                           .bitWidth      = 16,
                                           .flags         = static_cast<uint32_t>(
                                               bsp::AudioDevice::Flags::InputLeft), // microphone use left audio channel
                                           .outputVolume = 0,
                                           .inputGain    = static_cast<float>(gain),
                                           .inputPath    = bsp::AudioDevice::InputPath::BluetoothHSP,
                                           .outputPath   = bsp::AudioDevice::OutputPath::None},
                  bsp::AudioDevice::Type::Bluetooth,
                  callback)
        {}
    };

} // namespace audio

R module-audio/Audio/Profiles/ProfileRecordingHeadset.hpp => module-audio/Audio/Profiles/ProfileRecordingHeadphones.hpp +3 -4
@@ 8,13 8,13 @@
namespace audio
{

    class ProfileRecordingHeadset : public Profile
    class ProfileRecordingHeadphones : public Profile
    {
      public:
        ProfileRecordingHeadset(std::function<int32_t()> callback, Gain gain)
        ProfileRecordingHeadphones(std::function<int32_t()> callback, Gain gain)
            : Profile(
                  "Recording Headset",
                  Type::RecordingHeadset,
                  Type::RecordingHeadphones,
                  bsp::AudioDevice::Format{.sampleRate_Hz = 44100,
                                           .bitWidth      = 16,
                                           .flags         = static_cast<uint32_t>(


@@ 29,4 29,3 @@ namespace audio
    };

} // namespace audio


A module-audio/Audio/Profiles/ProfileRoutingBluetoothHSP.hpp => module-audio/Audio/Profiles/ProfileRoutingBluetoothHSP.hpp +31 -0
@@ 0,0 1,31 @@
// 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"

namespace audio
{
    class ProfileRoutingBluetoothHSP : public Profile
    {
      public:
        ProfileRoutingBluetoothHSP(std::function<int32_t()> callback, Volume volume, Gain gain)
            : Profile("Routing Bluetooth HSP",
                      Type::RoutingBluetoothHSP,
                      bsp::AudioDevice::Format{
                          .sampleRate_Hz = 8000,
                          .bitWidth      = 16,
                          .flags         = static_cast<uint32_t>(
                                       bsp::AudioDevice::Flags::InputLeft) | // microphone use left audio channel
                                   static_cast<uint32_t>(bsp::AudioDevice::Flags::OutputMono),
                          .outputVolume = static_cast<float>(volume),
                          .inputGain    = static_cast<float>(gain),
                          .inputPath    = bsp::AudioDevice::InputPath::BluetoothHSP,
                          .outputPath   = bsp::AudioDevice::OutputPath::BluetoothHSP},
                      bsp::AudioDevice::Type::Bluetooth,
                      callback)
        {}
    };

} // namespace audio

R module-audio/Audio/Profiles/ProfileRoutingHeadset.hpp => module-audio/Audio/Profiles/ProfileRoutingHeadphones.hpp +3 -4
@@ 8,12 8,12 @@
namespace audio
{

    class ProfileRoutingHeadset : public Profile
    class ProfileRoutingHeadphones : public Profile
    {
      public:
        ProfileRoutingHeadset(std::function<int32_t()> callback, Volume volume, Gain gain)
        ProfileRoutingHeadphones(std::function<int32_t()> callback, Volume volume, Gain gain)
            : Profile("Routing Headset",
                      Type::RoutingHeadset,
                      Type::RoutingHeadphones,
                      bsp::AudioDevice::Format{
                          .sampleRate_Hz = 16000,
                          .bitWidth      = 16,


@@ 30,4 30,3 @@ namespace audio
    };

} // namespace audio


R module-audio/Audio/Profiles/ProfileRoutingSpeakerphone.hpp => module-audio/Audio/Profiles/ProfileRoutingLoudspeaker.hpp +3 -3
@@ 8,12 8,12 @@
namespace audio
{

    class ProfileRoutingSpeakerphone : public Profile
    class ProfileRoutingLoudspeaker : public Profile
    {
      public:
        ProfileRoutingSpeakerphone(std::function<int32_t()> callback, Volume volume, Gain gain)
        ProfileRoutingLoudspeaker(std::function<int32_t()> callback, Volume volume, Gain gain)
            : Profile("Routing Speakerphone",
                      Type::RoutingSpeakerphone,
                      Type::RoutingLoudspeaker,
                      bsp::AudioDevice::Format{
                          .sampleRate_Hz = 16000,
                          .bitWidth      = 16,

M module-audio/Audio/test/unittest_audio.cpp => module-audio/Audio/test/unittest_audio.cpp +2 -2
@@ 58,9 58,9 @@ TEST_CASE("Audio settings string creation")
    SECTION("Create volume string for routing speakerphone")
    {
        const auto str =
            audio::dbPath(audio::Setting::Volume, audio::PlaybackType::None, audio::Profile::Type::RoutingSpeakerphone);
            audio::dbPath(audio::Setting::Volume, audio::PlaybackType::None, audio::Profile::Type::RoutingLoudspeaker);
        REQUIRE_FALSE(str.empty());
        REQUIRE(str == "audio/RoutingSpeakerphone/Volume");
        REQUIRE(str == "audio/RoutingLoudspeaker/Volume");
    }

    SECTION("Create gain string for recording built-in microphone")

M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp +4 -4
@@ 455,7 455,7 @@ namespace Bt
            sourceQueue = xQueueCreate(5, sizeof(AudioData_t));
            sinkQueue   = nullptr;
            if (sourceQueue != nullptr) {
                sendAudioEvent(audio::EventType::BTA2DPOn);
                sendAudioEvent(audio::EventType::BlutoothA2DPDeviceState, audio::Event::DeviceState::Connected);
            }
            else {
                LOG_ERROR("failed to create queue!");


@@ 537,7 537,7 @@ namespace Bt
                cid,
                AVRCP::mediaTracker.local_seid,
                local_seid);
            sendAudioEvent(audio::EventType::BTA2DPOff);
            sendAudioEvent(audio::EventType::BlutoothA2DPDeviceState, audio::Event::DeviceState::Disconnected);
            if (cid == AVRCP::mediaTracker.a2dp_cid) {
                AVRCP::mediaTracker.stream_opened = 0;
                LOG_INFO("A2DP Source: Stream released.\n");


@@ 591,9 591,9 @@ namespace Bt
        return std::make_shared<BluetoothStreamData>(sinkQueue, sourceQueue, metadata);
    }

    void A2DP::A2DPImpl::sendAudioEvent(audio::EventType event)
    void A2DP::A2DPImpl::sendAudioEvent(audio::EventType event, audio::Event::DeviceState state)
    {
        auto evt = std::make_shared<audio::Event>(event);
        auto evt = std::make_shared<audio::Event>(event, state);
        auto msg = std::make_shared<AudioEventRequest>(std::move(evt));
        sys::Bus::SendUnicast(std::move(msg), service::name::evt_manager, const_cast<sys::Service *>(ownerService));
    }

M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DPImpl.hpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DPImpl.hpp +1 -1
@@ 67,7 67,7 @@ namespace Bt
        static void hciPacketHandler(uint8_t packetType, uint16_t channel, uint8_t *packet, uint16_t size);
        static void sendMediaPacket();
        static auto fillSbcAudioBuffer(MediaContext *context) -> int;
        static void sendAudioEvent(audio::EventType event);
        static void sendAudioEvent(audio::EventType event, audio::Event::DeviceState state);

      public:
        auto init() -> Error::Code;

M module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp => module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp +4 -4
@@ 75,9 75,9 @@ namespace Bt
    const sys::Service *HSP::HSPImpl::ownerService;
    std::string HSP::HSPImpl::agServiceName = "PurePhone HSP";

    void HSP::HSPImpl::sendAudioEvent(audio::EventType event)
    void HSP::HSPImpl::sendAudioEvent(audio::EventType event, audio::Event::DeviceState state)
    {
        auto evt = std::make_shared<audio::Event>(event);
        auto evt = std::make_shared<audio::Event>(event, state);
        auto msg = std::make_shared<AudioEventRequest>(std::move(evt));
        sys::Bus::SendUnicast(std::move(msg), service::name::evt_manager, const_cast<sys::Service *>(ownerService));
    }


@@ 135,7 135,7 @@ namespace Bt
            }
            else {
                LOG_DEBUG("RFCOMM disconnected.\n");
                sendAudioEvent(audio::EventType::BTHeadsetOff);
                sendAudioEvent(audio::EventType::BlutoothHSPDeviceState, audio::Event::DeviceState::Disconnected);
            }
            break;
        case HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE:


@@ 152,7 152,7 @@ namespace Bt
            break;
        case HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE:
            LOG_DEBUG("Audio connection released.\n\n");
            sendAudioEvent(audio::EventType::BTHeadsetOff);
            sendAudioEvent(audio::EventType::BlutoothHSPDeviceState, audio::Event::DeviceState::Disconnected);
            scoHandle = HCI_CON_HANDLE_INVALID;
            break;
        case HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED:

M module-bluetooth/Bluetooth/interface/profiles/HSP/HSPImpl.hpp => module-bluetooth/Bluetooth/interface/profiles/HSP/HSPImpl.hpp +1 -1
@@ 24,7 24,7 @@ namespace Bt
        auto getStreamData() -> std::shared_ptr<BluetoothStreamData>;

      private:
        static void sendAudioEvent(audio::EventType event);
        static void sendAudioEvent(audio::EventType event, audio::Event::DeviceState state);
        static void processHCIEvent(uint8_t *event);
        static void processHSPEvent(uint8_t *event);
        static std::array<uint8_t, serviceBufferLength> serviceBuffer;

M module-bluetooth/Bluetooth/interface/profiles/HSP/SCO.cpp => module-bluetooth/Bluetooth/interface/profiles/HSP/SCO.cpp +4 -4
@@ 50,7 50,7 @@ namespace Bt
        static void initCvsd();
        static void receiveCvsd(uint8_t *packet, uint16_t size);
        static void writeToHostEndian(int16_t *buffer, uint8_t *packet, int length);
        static void sendEvent(audio::EventType event);
        static void sendEvent(audio::EventType event, audio::Event::DeviceState state);
        static void flipEndianess(uint16_t *data, size_t length);
    };



@@ 102,9 102,9 @@ QueueHandle_t SCO::SCOImpl::sourceQueue;
const sys::Service *SCO::SCOImpl::ownerService = nullptr;
DeviceMetadata_t SCO::SCOImpl::metadata;

void SCO::SCOImpl::sendEvent(audio::EventType event)
void SCO::SCOImpl::sendEvent(audio::EventType event, audio::Event::DeviceState state)
{
    auto evt = std::make_shared<audio::Event>(event);
    auto evt = std::make_shared<audio::Event>(event, state);
    auto msg = std::make_shared<AudioEventRequest>(std::move(evt));
    sys::Bus::SendUnicast(std::move(msg), service::name::evt_manager, const_cast<sys::Service *>(ownerService));
}


@@ 121,7 121,7 @@ auto SCO::SCOImpl::audioInitialize(int sampleRate) -> Error
    metadata.samplesPerFrame = audioSamplesPerPacket;

    if (sourceQueue != nullptr && sinkQueue != nullptr) {
        sendEvent(audio::EventType::BTHeadsetOn);
        sendEvent(audio::EventType::BlutoothHSPDeviceState, audio::Event::DeviceState::Connected);
    }
    else {
        LOG_ERROR("failed to create queue!");

M module-bsp/board/rt1051/bsp/audio/CodecMAX98090.cpp => module-bsp/board/rt1051/bsp/audio/CodecMAX98090.cpp +18 -18
@@ 79,7 79,7 @@ CodecRetCode CodecMAX98090::Start(const CodecParams &param)
    i2c->Write(i2cAddr, (uint8_t *)&q_dai_setup, 1);

    // OUT configuration
    if (params.outputPath != CodecParamsMAX98090::OutputPath::None) {
    if (params.outputPath != bsp::AudioDevice::OutputPath::None) {
        // Set output route
        max98090_reg_playback_quick_setup_t q_playback_setup = {0};



@@ 88,7 88,7 @@ CodecRetCode CodecMAX98090::Start(const CodecParams &param)

        switch (params.outputPath) {

        case CodecParamsMAX98090::OutputPath::HeadphonesMono: {
        case bsp::AudioDevice::OutputPath::HeadphonesMono: {

            // Mix left DAC channel to left&right HP output
            max98090_reg_lhp_mixer_t lmixconf = {0};


@@ 113,7 113,7 @@ CodecRetCode CodecMAX98090::Start(const CodecParams &param)

        } break;

        case CodecParamsMAX98090::OutputPath::Headphones: {
        case bsp::AudioDevice::OutputPath::Headphones: {
            // Set DAC headphones output to high performance mode, increasing power consumption but providing the
            // highest quality
            dacperf.dachp           = 1;


@@ 127,7 127,7 @@ CodecRetCode CodecMAX98090::Start(const CodecParams &param)

        } break;

        case CodecParamsMAX98090::OutputPath::Earspeaker: {
        case bsp::AudioDevice::OutputPath::Earspeaker: {
            q_playback_setup.dig2ear = 1;
            i2cAddr.subAddress       = MAX98090_REG_PLAYBACK_QUICK_SETUP;
            i2c->Write(i2cAddr, (uint8_t *)&q_playback_setup, 1);


@@ 170,7 170,7 @@ CodecRetCode CodecMAX98090::Start(const CodecParams &param)

        } break;

        case CodecParamsMAX98090::OutputPath::Loudspeaker: {
        case bsp::AudioDevice::OutputPath::Loudspeaker: {
            q_playback_setup.dig2spk = 1;

            uint8_t mask       = 0x08; // Set 3th bit (dmono on)


@@ 226,10 226,10 @@ CodecRetCode CodecMAX98090::Start(const CodecParams &param)
    }

    // IN configuration
    if (params.inputPath != CodecParamsMAX98090::InputPath::None) {
    if (params.inputPath != bsp::AudioDevice::InputPath::None) {
        // Set input path
        switch (params.inputPath) {
        case CodecParamsMAX98090::InputPath::Headphones: {
        case bsp::AudioDevice::InputPath::Headphones: {
            /* 			max98090_reg_analog_to_record_quick_t q_analog_setup = {0};

                        q_analog_setup.in34mic2 = 1;


@@ 253,7 253,7 @@ CodecRetCode CodecMAX98090::Start(const CodecParams &param)

        } break;

        case CodecParamsMAX98090::InputPath::Microphone: {
        case bsp::AudioDevice::InputPath::Microphone: {
            max98090_reg_input_to_record_quick_t q_input_setup   = {0};
            max98090_reg_analog_to_record_quick_t q_analog_setup = {0};
            max98090_reg_digmic_enable_t digena                  = {0};


@@ 384,8 384,8 @@ CodecRetCode CodecMAX98090::SetOutputVolume(const float vol)
    }

    switch (currentParams.outputPath) {
    case CodecParamsMAX98090::OutputPath::Headphones:
    case CodecParamsMAX98090::OutputPath::HeadphonesMono: {
    case bsp::AudioDevice::OutputPath::Headphones:
    case bsp::AudioDevice::OutputPath::HeadphonesMono: {
        // Scale input volume(range 0 - 100) to MAX98090 range(decibels hardcoded as specific hex values)
        constexpr float scale_factor     = .31f * 10.f;
        uint8_t volume                   = static_cast<float>(vol * scale_factor);


@@ 404,7 404,7 @@ CodecRetCode CodecMAX98090::SetOutputVolume(const float vol)

    } break;

    case CodecParamsMAX98090::OutputPath::Earspeaker: {
    case bsp::AudioDevice::OutputPath::Earspeaker: {
        // Scale input volume(range 0 - 100) to MAX98090 range(decibels hardcoded as specific hex values)
        constexpr float scale_factor     = .31f * 10.f;
        uint8_t volume                   = static_cast<float>(vol * scale_factor);


@@ 417,7 417,7 @@ CodecRetCode CodecMAX98090::SetOutputVolume(const float vol)
        i2c->Write(i2cAddr, (uint8_t *)&vol, 1);
    } break;

    case CodecParamsMAX98090::OutputPath::Loudspeaker: {
    case bsp::AudioDevice::OutputPath::Loudspeaker: {
        // Scale input volume(range 0 - 100) to MAX98090 range(decibels hardcoded as specific hex values)
        constexpr float scale_factor = .39f * 10.f;
        uint8_t volume               = static_cast<float>(vol * scale_factor) + 0x18;


@@ 533,7 533,7 @@ CodecRetCode CodecMAX98090::Reset()
    return CodecRetCode::Success;
}

CodecRetCode CodecMAX98090::SetOutputPath(const CodecParamsMAX98090::OutputPath path)
CodecRetCode CodecMAX98090::SetOutputPath(const bsp::AudioDevice::OutputPath path)
{
    Reset();
    currentParams.outputPath = path;


@@ 542,7 542,7 @@ CodecRetCode CodecMAX98090::SetOutputPath(const CodecParamsMAX98090::OutputPath 
    return CodecRetCode::Success;
}

CodecRetCode CodecMAX98090::SetInputPath(const CodecParamsMAX98090::InputPath path)
CodecRetCode CodecMAX98090::SetInputPath(const bsp::AudioDevice::InputPath path)
{
    Reset();
    currentParams.inputPath = path;


@@ 558,17 558,17 @@ CodecRetCode CodecMAX98090::SetMute(const bool enable)
    uint8_t regl, regr = 0;

    switch (currentParams.outputPath) {
    case CodecParamsMAX98090::OutputPath::Headphones: {
    case bsp::AudioDevice::OutputPath::Headphones: {
        regl = MAX98090_REG_LHP_VOL_CTRL;
        regr = MAX98090_REG_RHP_VOL_CTRL;
    } break;

    case CodecParamsMAX98090::OutputPath::Earspeaker: {
    case bsp::AudioDevice::OutputPath::Earspeaker: {
        regl = MAX98090_REG_RECV_VOL_CTRL;
        regr = 0;
    } break;

    case CodecParamsMAX98090::OutputPath::Loudspeaker: {
    case bsp::AudioDevice::OutputPath::Loudspeaker: {
        regl = MAX98090_REG_LSPK_VOL_CTRL;
        regr = MAX98090_REG_RSPK_VOL_CTRL;
    } break;


@@ 595,4 595,4 @@ std::optional<uint32_t> CodecMAX98090::Probe()
    i2cAddr.subAddress = MAX98090_REG_REVID;
    i2c->Write(i2cAddr, (uint8_t *)&id, 1);
    return id;
}
\ No newline at end of file
}

M module-bsp/board/rt1051/bsp/audio/CodecMAX98090.hpp => module-bsp/board/rt1051/bsp/audio/CodecMAX98090.hpp +5 -20
@@ 6,6 6,7 @@

#include "Codec.hpp"
#include "drivers/i2c/DriverI2C.hpp"
#include "bsp/audio/bsp_audio.hpp"

class CodecParamsMAX98090 : public CodecParams
{


@@ 33,22 34,6 @@ class CodecParamsMAX98090 : public CodecParams
        Invalid
    };

    enum class OutputPath
    {
        Headphones,
        HeadphonesMono,
        Earspeaker,
        Loudspeaker,
        None
    };

    enum class InputPath
    {
        Headphones,
        Microphone,
        None
    };

    enum class MonoStereo
    {
        Mono,


@@ 101,8 86,8 @@ class CodecParamsMAX98090 : public CodecParams
    bool muteEnable       = false;
    bool resetEnable      = false;
    bool micBiasEnable    = false;
    InputPath inputPath   = InputPath ::None;
    OutputPath outputPath = OutputPath ::None;
    bsp::AudioDevice::InputPath inputPath   = bsp::AudioDevice::InputPath::None;
    bsp::AudioDevice::OutputPath outputPath = bsp::AudioDevice::OutputPath::None;
    SampleRate sampleRate = SampleRate ::Rate44K1Hz;
};



@@ 132,8 117,8 @@ class CodecMAX98090 : public Codec
    CodecRetCode SetOutputVolume(const float vol);
    CodecRetCode SetInputGain(const float gain);
    CodecRetCode SetMute(const bool enable);
    CodecRetCode SetInputPath(const CodecParamsMAX98090::InputPath path);
    CodecRetCode SetOutputPath(const CodecParamsMAX98090::OutputPath path);
    CodecRetCode SetInputPath(const bsp::AudioDevice::InputPath path);
    CodecRetCode SetOutputPath(const bsp::AudioDevice::OutputPath path);
    CodecRetCode MicBias(const bool enable);
    CodecRetCode WriteFilterCoeff(const float coeff, const uint8_t basereg);
    CodecRetCode Reset();

M module-bsp/board/rt1051/bsp/audio/RT1051Audiocodec.cpp => module-bsp/board/rt1051/bsp/audio/RT1051Audiocodec.cpp +4 -5
@@ 79,8 79,8 @@ namespace bsp
            LOG_ERROR("Unsupported sample rate");
        }

        codecParams.inputPath  = static_cast<CodecParamsMAX98090::InputPath>(format.inputPath);
        codecParams.outputPath = static_cast<CodecParamsMAX98090::OutputPath>(format.outputPath);
        codecParams.inputPath  = format.inputPath;
        codecParams.outputPath = format.outputPath;
        codecParams.outVolume  = format.outputVolume;
        codecParams.inGain     = format.inputGain;
        codec.Start(codecParams);


@@ 146,7 146,7 @@ namespace bsp
    {
        currentFormat.inputPath = inputPath;
        CodecParamsMAX98090 params;
        params.inputPath = static_cast<CodecParamsMAX98090::InputPath>(inputPath);
        params.inputPath = inputPath;
        params.opCmd     = CodecParamsMAX98090::Cmd::SetInput;
        codec.Ioctrl(params);
        return AudioDevice::RetCode::Success;


@@ 156,7 156,7 @@ namespace bsp
    {
        currentFormat.outputPath = outputPath;
        CodecParamsMAX98090 params;
        params.outputPath = static_cast<CodecParamsMAX98090::OutputPath>(outputPath);
        params.outputPath = outputPath;
        params.opCmd      = CodecParamsMAX98090::Cmd::SetOutput;
        codec.Ioctrl(params);
        return AudioDevice::RetCode::Success;


@@ 170,7 170,6 @@ namespace bsp
        }
        return true;
    }

    // INTERNALS

    void RT1051Audiocodec::Init()

M module-bsp/bsp/audio/bsp_audio.hpp => module-bsp/bsp/audio/bsp_audio.hpp +2 -0
@@ 24,6 24,7 @@ namespace bsp {
        enum class InputPath{
            Headphones,
            Microphone,
            BluetoothHSP,
            None
        };



@@ 33,6 34,7 @@ namespace bsp {
            Earspeaker,
            Loudspeaker,
            BluetoothA2DP,
            BluetoothHSP,
            None
        };


M module-services/service-audio/AudioServiceAPI.cpp => module-services/service-audio/AudioServiceAPI.cpp +2 -2
@@ 97,9 97,9 @@ namespace AudioServiceAPI
        return sys::Bus::SendUnicast(msg, ServiceAudio::serviceName, serv);
    }

    bool SendEvent(sys::Service *serv, audio::EventType eType)
    bool SendEvent(sys::Service *serv, audio::EventType eType, audio::Event::DeviceState state)
    {
        auto msg = std::make_shared<AudioEventRequest>(eType);
        auto msg = std::make_shared<AudioEventRequest>(eType, state);
        return sys::Bus::SendUnicast(msg, ServiceAudio::serviceName, serv);
    }


M module-services/service-audio/ServiceAudio.cpp => module-services/service-audio/ServiceAudio.cpp +21 -32
@@ 44,39 44,40 @@ sys::ReturnCodes ServiceAudio::InitHandler()

        // PLAYBACK
        {dbPath(Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackHeadphones), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackBTA2DP), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackBluetoothA2DP), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackLoudspeaker), defaultVolumeHigh},

        {dbPath(Setting::Volume, PlaybackType::Notifications, Profile::Type::PlaybackHeadphones), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::Notifications, Profile::Type::PlaybackBTA2DP), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::Notifications, Profile::Type::PlaybackBluetoothA2DP), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::Notifications, Profile::Type::PlaybackLoudspeaker), defaultVolumeHigh},

        {dbPath(Setting::Volume, PlaybackType::KeypadSound, Profile::Type::PlaybackHeadphones), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::KeypadSound, Profile::Type::PlaybackBTA2DP), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::KeypadSound, Profile::Type::PlaybackBluetoothA2DP), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::KeypadSound, Profile::Type::PlaybackLoudspeaker), defaultVolumeHigh},

        {dbPath(Setting::Volume, PlaybackType::CallRingtone, Profile::Type::PlaybackHeadphones), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::CallRingtone, Profile::Type::PlaybackBTA2DP), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::CallRingtone, Profile::Type::PlaybackBluetoothA2DP), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::CallRingtone, Profile::Type::PlaybackLoudspeaker), defaultVolumeHigh},

        {dbPath(Setting::Volume, PlaybackType::TextMessageRingtone, Profile::Type::PlaybackHeadphones),
         defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::TextMessageRingtone, Profile::Type::PlaybackBTA2DP), defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::TextMessageRingtone, Profile::Type::PlaybackBluetoothA2DP),
         defaultVolumeLow},
        {dbPath(Setting::Volume, PlaybackType::TextMessageRingtone, Profile::Type::PlaybackLoudspeaker),
         defaultVolumeHigh},

        // ROUTING
        {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RoutingBTHeadset), "20"},
        {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RoutingBluetoothHSP), "20"},
        {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RoutingEarspeaker), "20"},
        {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RoutingHeadphones), "20"},
        {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RoutingSpeakerphone), "20"},
        {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RoutingHeadset), "50"},
        {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RoutingLoudspeaker), "20"},
        {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RoutingHeadphones), "50"},

        {dbPath(Setting::Volume, PlaybackType::None, Profile::Type::RoutingBTHeadset), defaultVolumeHigh},
        {dbPath(Setting::Volume, PlaybackType::None, Profile::Type::RoutingBluetoothHSP), defaultVolumeHigh},
        {dbPath(Setting::Volume, PlaybackType::None, Profile::Type::RoutingEarspeaker), defaultVolumeHigh},
        {dbPath(Setting::Volume, PlaybackType::None, Profile::Type::RoutingHeadphones), defaultVolumeHigh},
        {dbPath(Setting::Volume, PlaybackType::None, Profile::Type::RoutingSpeakerphone), defaultVolumeHigh},
        {dbPath(Setting::Volume, PlaybackType::None, Profile::Type::RoutingHeadset), defaultVolumeHigh},
        {dbPath(Setting::Volume, PlaybackType::None, Profile::Type::RoutingLoudspeaker), defaultVolumeHigh},
        {dbPath(Setting::Volume, PlaybackType::None, Profile::Type::RoutingHeadphones), defaultVolumeHigh},

        // MISC
        {dbPath(Setting::EnableVibration, PlaybackType::Multimedia, Profile::Type::Idle), defaultFalse},


@@ 323,7 324,9 @@ std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleStart(const Operation:

std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleSendEvent(std::shared_ptr<Event> evt)
{
    if (evt->getType() == EventType::BTA2DPOn) {
    auto isBT =
        evt->getType() == EventType::BlutoothHSPDeviceState || evt->getType() == EventType::BlutoothA2DPDeviceState;
    if (isBT && evt->getDeviceState() == audio::Event::DeviceState::Connected) {
        auto req = std::make_shared<BluetoothRequestStreamMessage>();
        sys::Bus::SendUnicast(req, service::name::bluetooth, this);
        return std::make_unique<AudioEventResponse>(RetCode::Success);


@@ 331,7 334,7 @@ std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleSendEvent(std::shared_

    for (auto &input : audioMux.GetAllInputs()) {
        input.audio->SendEvent(evt);
        if (evt->getType() == EventType::BTA2DPOff) {
        if (isBT && evt->getDeviceState() == audio::Event::DeviceState::Connected) {
            input.audio->SetBluetoothStreamData(nullptr);
        }
    }


@@ 512,7 515,8 @@ sys::MessagePointer ServiceAudio::DataReceivedHandler(sys::DataMessage *msgl, sy
        auto *msg = static_cast<BluetoothRequestStreamResultMessage *>(msgl);
        for (auto &input : audioMux.GetAllInputs()) {
            input.audio->SetBluetoothStreamData(msg->getData());
            input.audio->SendEvent(std::make_unique<Event>(EventType::BTA2DPOn));
            input.audio->SendEvent(
                std::make_unique<Event>(EventType::BlutoothA2DPDeviceState, audio::Event::DeviceState::Connected));
            LOG_INFO("Queues received!");
        }
    }


@@ 565,13 569,7 @@ std::string ServiceAudio::getSetting(const Setting &setting,
            targetPlayback = currentPlaybackType;
        }
        else if (auto input = audioMux.GetIdleInput(); input && (setting == Setting::Volume)) {
            targetProfile = Profile::Type::PlaybackLoudspeaker;
            if ((*input)->audio->IsLineSinkAvailable()) {
                targetProfile = Profile::Type::PlaybackHeadphones;
            }
            if ((*input)->audio->IsBtSinkAvailable()) {
                targetProfile = Profile::Type::PlaybackBTA2DP;
            }
            targetProfile = (*input)->audio->GetPriorityPlaybackProfile();

            targetPlayback = PlaybackType::CallRingtone;
        }


@@ 607,14 605,7 @@ void ServiceAudio::setSetting(const Setting &setting,
            updatedPlayback              = (*activeInput)->audio->GetCurrentOperationPlaybackType();
        }
        else if (auto input = audioMux.GetIdleInput(); input && (setting == audio::Setting::Volume)) {
            updatedProfile = Profile::Type::PlaybackLoudspeaker;
            if ((*input)->audio->IsLineSinkAvailable()) {
                updatedProfile = Profile::Type::PlaybackHeadphones;
            }
            if ((*input)->audio->IsBtSinkAvailable()) {
                updatedProfile = Profile::Type::PlaybackBTA2DP;
            }

            updatedProfile  = (*input)->audio->GetPriorityPlaybackProfile();
            updatedPlayback = PlaybackType::CallRingtone;
            valueToSet      = std::clamp(utils::getValue<audio::Volume>(value), minVolume, maxVolume);
        }


@@ 657,9 648,7 @@ const std::pair<audio::Profile::Type, audio::PlaybackType> ServiceAudio::getCurr
    if (!activeInput.has_value()) {
        const auto idleInput = audioMux.GetIdleInput();
        if (idleInput.has_value()) {
            return {(*idleInput)->audio->IsLineSinkAvailable() ? Profile::Type::PlaybackHeadphones
                                                               : Profile::Type::PlaybackLoudspeaker,
                    audio::PlaybackType::CallRingtone};
            return {(*idleInput)->audio->GetPriorityPlaybackProfile(), audio::PlaybackType::CallRingtone};
        }
    }
    auto &audio                  = (*activeInput)->audio;

M module-services/service-audio/service-audio/AudioMessage.hpp => module-services/service-audio/service-audio/AudioMessage.hpp +2 -1
@@ 232,7 232,8 @@ class AudioEventRequest : public AudioMessage
    explicit AudioEventRequest(std::shared_ptr<audio::Event> evt) : evt(std::move(evt))
    {}

    explicit AudioEventRequest(audio::EventType eType) : evt(std::make_shared<audio::Event>(eType))
    explicit AudioEventRequest(audio::EventType eType, audio::Event::DeviceState state)
        : evt(std::make_shared<audio::Event>(eType, state))
    {}

    std::shared_ptr<audio::Event> getEvent()

M module-services/service-audio/service-audio/AudioServiceAPI.hpp => module-services/service-audio/service-audio/AudioServiceAPI.hpp +5 -2
@@ 115,10 115,13 @@ namespace AudioServiceAPI
     * @brief Sends audio event
     * @param serv Requesting service.
     * @param evt Event to be sent.
     *  @return True is request has been sent successfully, false otherwise
     * @param state Optional parameter to request.
     * @return True is request has been sent successfully, false otherwise
     *   Response will come as message AudioSendEventResponse
     */
    bool SendEvent(sys::Service *serv, audio::EventType evt);
    bool SendEvent(sys::Service *serv,
                   audio::EventType evt,
                   audio::Event::DeviceState state = audio::Event::DeviceState::Connected);
    /**
     * @brief Attempts to parse audio file for metatags.
     *

M module-services/service-evtmgr/WorkerEvent.cpp => module-services/service-evtmgr/WorkerEvent.cpp +3 -2
@@ 82,8 82,9 @@ bool WorkerEvent::handleMessage(uint32_t queueID)

        if (bsp::headset::Handler(notification) == true) {
            bool state = bsp::headset::IsInserted();
            auto message = std::make_shared<AudioEventRequest>(state ? audio::EventType::HeadphonesPlugin
                                                                     : audio::EventType::HeadphonesUnplug);
            auto message = std::make_shared<AudioEventRequest>(audio::EventType::JackState,
                                                               state ? audio::Event::DeviceState::Connected
                                                                     : audio::Event::DeviceState::Disconnected);
            sys::Bus::SendUnicast(message, service::name::evt_manager, this->service);
        }
    }