mirror of
https://github.com/mudita/MuditaOS.git
synced 2026-05-19 14:15:02 -04:00
Workaround for the issue that A2DP stream would sometimes not restart when music player changes song to the next one.
117 lines
3.9 KiB
C++
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
|