Files
MuditaOS/module-bluetooth/Bluetooth/audio/BluetoothAudioDevice.hpp
Lefucjusz 2e04d268c4 [MOS-1068] Fix A2DP stream not restarting after song changes
Workaround for the issue that A2DP stream
would sometimes not restart when music
player changes song to the next one.
2024-05-29 17:33:30 +02:00

117 lines
3.9 KiB
C++

// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
#include <Audio/Endpoint.hpp>
#include <Audio/AudioDevice.hpp>
#include <Audio/AudioFormat.hpp>
#include <Audio/Stream.hpp>
#include <interface/profiles/A2DP/MediaContext.hpp>
#include <interface/profiles/AudioProfile.hpp>
extern "C"
{
#include "classic/btstack_cvsd_plc.h"
}
namespace bluetooth
{
class BluetoothAudioDevice : public audio::AudioDevice
{
public:
explicit BluetoothAudioDevice(AudioProfile audioProfile);
virtual ~BluetoothAudioDevice();
virtual auto getProfileType() const -> AudioProfile;
auto setInputGain(float gain) -> audio::AudioDevice::RetCode override;
// Endpoint control methods
void enableInput() override;
void enableOutput() override;
void disableInput() override;
void disableOutput() override;
protected:
[[nodiscard]] auto isInputEnabled() const -> bool;
[[nodiscard]] auto isOutputEnabled() const -> bool;
auto fillSbcAudioBuffer() -> int;
auto scaleVolume(audio::Stream::Span &dataSpan) const -> void;
float outputVolume;
private:
bool outputEnabled = false;
bool inputEnabled = false;
AudioProfile profile = AudioProfile::None;
};
class A2DPAudioDevice : public BluetoothAudioDevice
{
public:
explicit A2DPAudioDevice(const float volume) : BluetoothAudioDevice(AudioProfile::A2DP)
{
outputVolume = volume;
}
auto setOutputVolume(float vol) -> audio::AudioDevice::RetCode override;
void onDataSend() override;
void onDataReceive() override;
auto getSupportedFormats() -> std::vector<audio::AudioFormat> override;
[[nodiscard]] auto getTraits() const -> Traits override;
auto getSourceFormat() -> ::audio::AudioFormat override;
audio::AudioDevice::RetCode Start() override;
audio::AudioDevice::RetCode Stop() override;
audio::AudioDevice::RetCode Resume() override;
audio::AudioDevice::RetCode Pause() override;
private:
[[nodiscard]] audio::AudioDevice::RetCode waitUntilStreamPaused() const;
};
class CVSDAudioDevice : public BluetoothAudioDevice
{
public:
explicit CVSDAudioDevice(const float volume, const AudioProfile &profile) : BluetoothAudioDevice(profile)
{
outputVolume = volume;
btstack_cvsd_plc_init(&cvsdPlcState);
}
auto setOutputVolume(float vol) -> audio::AudioDevice::RetCode override;
void onDataSend() override;
void onDataSend(std::uint16_t scoHandle);
void onDataReceive() override;
auto getSupportedFormats() -> std::vector<audio::AudioFormat> override;
[[nodiscard]] auto getTraits() const -> Traits override;
auto getSourceFormat() -> ::audio::AudioFormat override;
void enableInput() override;
void setAclHandle(hci_con_handle_t handle);
void receiveCVSD(audio::AbstractStream::Span receivedData);
private:
static constexpr std::size_t scratchBufferSize = 128;
static constexpr auto packetHandleOffset = 0;
static constexpr auto packetStatusOffset = 1;
static constexpr auto packetLengthOffset = 2;
static constexpr auto packetDataOffset = 3;
static constexpr auto supportedBitWidth = 16U;
static constexpr auto supportedChannels = 1;
static constexpr auto allGoodMask = 0x30;
auto decodeCVSD(audio::AbstractStream::Span dataToDecode) -> audio::AbstractStream::Span;
std::unique_ptr<std::uint8_t[]> rxLeftovers;
std::unique_ptr<std::int16_t[]> decoderBuffer;
std::size_t leftoversSize = 0;
btstack_cvsd_plc_state_t cvsdPlcState;
hci_con_handle_t aclHandle;
};
} // namespace bluetooth