M .gitignore => .gitignore +3 -0
@@ 57,3 57,6 @@ update/
# build in docker files
.ccache/
.bash_history
+
+# often created by the visual studio code
+/null.d
M .vscode/settings.json => .vscode/settings.json +3 -1
@@ 6,6 6,7 @@
},
"testMate.cpp.test.executables": "build-linux-Debug/{googletest,catch2}-*",
"files.associations": {
+ "*.cc": "cpp",
"array": "cpp",
"atomic": "cpp",
"bit": "cpp",
@@ 80,6 81,7 @@
"pointers": "cpp",
"any": "cpp",
"charconv": "cpp",
- "scoped_allocator": "cpp"
+ "scoped_allocator": "cpp",
+ "*.inc": "cpp"
},
}=
\ No newline at end of file
A image/user/music/Ringtone-drum2-stereo.mp3 => image/user/music/Ringtone-drum2-stereo.mp3 +0 -0
A image/user/music/SMS-drum2-stereo.mp3 => image/user/music/SMS-drum2-stereo.mp3 +0 -0
M module-audio/Audio/AudioCommon.hpp => module-audio/Audio/AudioCommon.hpp +24 -1
@@ 11,8 11,9 @@
#include <Utils.hpp>
#include <PhoneModes/Common.hpp>
-#include <map>
#include <bitset>
+#include <map>
+#include <memory>
#include <utility>
namespace audio
@@ 314,5 315,27 @@ namespace AudioServiceMessage
const audio::PlaybackType playback;
};
+ class AudioDeviceCreated : public sys::Message
+ {
+ public:
+ explicit AudioDeviceCreated(std::shared_ptr<audio::AudioDevice> device, audio::AudioDevice::Type type)
+ : device(std::move(device)), type(type)
+ {}
+
+ auto getDevice() const noexcept -> std::shared_ptr<audio::AudioDevice>
+ {
+ return device;
+ }
+
+ auto getDeviceType() const noexcept -> audio::AudioDevice::Type
+ {
+ return type;
+ }
+
+ private:
+ std::shared_ptr<audio::AudioDevice> device;
+ audio::AudioDevice::Type type;
+ };
+
using Callback = std::function<std::optional<std::string>(const sys::Message *msg)>;
} // namespace AudioServiceMessage
M module-audio/Audio/AudioDeviceFactory.cpp => module-audio/Audio/AudioDeviceFactory.cpp +1 -1
@@ 13,7 13,7 @@ std::shared_ptr<AudioDevice> AudioDeviceFactory::CreateDevice(AudioDevice::Type
std::shared_ptr<AudioDevice> device = getDeviceFromType(deviceType);
if (_observer != nullptr && device) {
- _observer->onDeviceCreated(device);
+ _observer->onDeviceCreated(device, deviceType);
}
return device;
M module-audio/Audio/AudioDeviceFactory.hpp => module-audio/Audio/AudioDeviceFactory.hpp +2 -2
@@ 12,13 12,13 @@ namespace audio
class AudioDeviceFactory
{
+ public:
class Observer
{
public:
- virtual void onDeviceCreated(std::shared_ptr<AudioDevice> device) = 0;
+ virtual void onDeviceCreated(std::shared_ptr<AudioDevice> device, AudioDevice::Type deviceType) = 0;
};
- public:
explicit AudioDeviceFactory(Observer *observer = nullptr);
void setObserver(Observer *observer) noexcept;
M module-audio/Audio/Operation/Operation.cpp => module-audio/Audio/Operation/Operation.cpp +0 -3
@@ 7,7 7,6 @@
#include "Audio/AudioDevice.hpp"
#include "Audio/AudioDeviceFactory.hpp"
-#include "Audio/AudioPlatform.hpp"
#include "IdleOperation.hpp"
#include "PlaybackOperation.hpp"
@@ 96,8 95,6 @@ namespace audio
std::shared_ptr<AudioDevice> Operation::CreateDevice(AudioDevice::Type type)
{
- auto factory = AudioPlatform::GetDeviceFactory();
-
return factory->CreateDevice(type);
}
} // namespace audio
M module-audio/Audio/Operation/Operation.hpp => module-audio/Audio/Operation/Operation.hpp +13 -3
@@ 7,6 7,9 @@
#include <functional>
#include <Audio/AudioCommon.hpp>
+#include <Audio/AudioDeviceFactory.hpp>
+#include <Audio/AudioPlatform.hpp>
+#include <Audio/ServiceObserver.hpp>
#include <Audio/encoder/Encoder.hpp>
#include <Audio/Profiles/Profile.hpp>
@@ 17,9 20,13 @@ namespace audio
class Operation
{
public:
- Operation(AudioServiceMessage::Callback callback, const PlaybackType &playbackType = PlaybackType::None)
- : playbackType(playbackType), serviceCallback(callback)
- {}
+ explicit Operation(AudioServiceMessage::Callback callback,
+ const PlaybackType &playbackType = PlaybackType::None)
+ : playbackType(playbackType), serviceCallback(callback), observer(serviceCallback)
+ {
+ factory = AudioPlatform::GetDeviceFactory();
+ factory->setObserver(&observer);
+ }
enum class State
{
@@ 124,6 131,7 @@ namespace audio
std::shared_ptr<Profile> currentProfile;
std::shared_ptr<AudioDevice> audioDevice;
std::vector<SupportedProfile> supportedProfiles;
+ std::unique_ptr<AudioDeviceFactory> factory;
State state = State::Idle;
audio::Token operationToken;
@@ 132,6 140,8 @@ namespace audio
audio::PlaybackType playbackType = audio::PlaybackType::None;
AudioServiceMessage::Callback serviceCallback;
+ ServiceObserver observer;
+
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 +5 -7
@@ 32,12 32,6 @@ namespace audio
return std::string();
};
- auto defaultProfile = GetProfile(Profile::Type::PlaybackLoudspeaker);
- if (!defaultProfile) {
- throw AudioInitException("Error during initializing profile", RetCode::ProfileNotSet);
- }
- currentProfile = defaultProfile;
-
dec = Decoder::Create(file);
if (dec == nullptr) {
throw AudioInitException("Error during initializing decoder", RetCode::FileDoesntExist);
@@ 57,7 51,7 @@ namespace audio
}
// create stream
- StreamFactory streamFactory(playbackCapabilities);
+ StreamFactory streamFactory(playbackCapabilities, playbackBufferingSize);
dataStreamOut = streamFactory.makeStream(*dec.get(), *audioDevice.get());
// create audio connection
@@ 157,6 151,10 @@ namespace audio
return RetCode::UnsupportedProfile;
}
+ if (currentProfile && currentProfile->GetType() == newProfile->GetType()) {
+ return RetCode::Success;
+ }
+
/// profile change - (re)create output device; stop audio first by
/// killing audio connection
outputConnection.reset();
M module-audio/Audio/Operation/PlaybackOperation.hpp => module-audio/Audio/Operation/PlaybackOperation.hpp +4 -2
@@ 39,8 39,10 @@ namespace audio
Position GetPosition() final;
private:
- static constexpr auto minimumBlockSize = 256U;
- static constexpr auto maximumBlockSize = 2048U;
+ // these values are tightly connected to the Bluetooth A2DP update interval
+ static constexpr auto playbackBufferingSize = 8U;
+ static constexpr auto minimumBlockSize = 512U;
+ static constexpr auto maximumBlockSize = 512U;
static constexpr Endpoint::Capabilities playbackCapabilities{.minBlockSize = minimumBlockSize,
.maxBlockSize = maximumBlockSize};
A module-audio/Audio/ServiceObserver.cpp => module-audio/Audio/ServiceObserver.cpp +18 -0
@@ 0,0 1,18 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "ServiceObserver.hpp"
+#include "AudioCommon.hpp"
+#include "AudioDevice.hpp"
+
+using namespace audio;
+
+ServiceObserver::ServiceObserver(AudioServiceMessage::Callback serviceCallback)
+ : serviceCallback(std::move(serviceCallback))
+{}
+
+void ServiceObserver::onDeviceCreated(std::shared_ptr<AudioDevice> device, AudioDevice::Type deviceType)
+{
+ auto msg = AudioServiceMessage::AudioDeviceCreated(std::move(device), deviceType);
+ serviceCallback(&msg);
+}
A module-audio/Audio/ServiceObserver.hpp => module-audio/Audio/ServiceObserver.hpp +25 -0
@@ 0,0 1,25 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "AudioCommon.hpp"
+#include "AudioDevice.hpp"
+#include "AudioDeviceFactory.hpp"
+
+#include <memory>
+
+namespace audio
+{
+
+ class ServiceObserver : public AudioDeviceFactory::Observer
+ {
+ public:
+ explicit ServiceObserver(AudioServiceMessage::Callback serviceCallback);
+ virtual void onDeviceCreated(std::shared_ptr<AudioDevice> device, AudioDevice::Type deviceType) final;
+
+ private:
+ AudioServiceMessage::Callback serviceCallback;
+ };
+
+} // namespace audio
M module-audio/Audio/StreamFactory.cpp => module-audio/Audio/StreamFactory.cpp +3 -2
@@ 14,14 14,15 @@
using namespace audio;
-StreamFactory::StreamFactory(Endpoint::Capabilities factoryCaps) : caps(std::move(factoryCaps))
+StreamFactory::StreamFactory(Endpoint::Capabilities factoryCaps, unsigned int bufferingSize)
+ : caps(std::move(factoryCaps)), bufferingSize(bufferingSize)
{}
auto StreamFactory::makeStream(const Source &source, const Sink &sink) -> std::unique_ptr<Stream>
{
auto negotiatedCaps = negotiateCaps({source, sink});
- return std::make_unique<Stream>(getAllocator(negotiatedCaps.usesDMA), negotiatedCaps.maxBlockSize);
+ return std::make_unique<Stream>(getAllocator(negotiatedCaps.usesDMA), negotiatedCaps.maxBlockSize, bufferingSize);
}
auto StreamFactory::negotiateCaps(std::vector<std::reference_wrapper<const Endpoint>> v) -> Endpoint::Capabilities
M module-audio/Audio/StreamFactory.hpp => module-audio/Audio/StreamFactory.hpp +3 -1
@@ 14,7 14,8 @@ namespace audio
class StreamFactory
{
public:
- explicit StreamFactory(Endpoint::Capabilities factoryCaps);
+ explicit StreamFactory(Endpoint::Capabilities factoryCaps,
+ unsigned int bufferingSize = Stream::defaultBufferingSize);
auto makeStream(const Source &source, const Sink &sink) -> std::unique_ptr<Stream>;
private:
@@ 24,6 25,7 @@ namespace audio
Endpoint::Capabilities caps;
StandardStreamAllocator stdAlloc;
NonCacheableStreamAllocator nonCacheableAlloc;
+ unsigned int bufferingSize;
};
} // namespace audio
M module-audio/CMakeLists.txt => module-audio/CMakeLists.txt +10 -11
@@ 7,30 7,29 @@ project(module-audio VERSION 1.0
DESCRIPTION "Audio module library")
set(SOURCES
+ "${CMAKE_CURRENT_SOURCE_DIR}/Audio/Audio.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/Audio/AudioCommon.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/Audio/AudioDeviceFactory.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/Audio/AudioMux.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/decoder/Decoder.cpp"
- "${CMAKE_CURRENT_SOURCE_DIR}/Audio/decoder/DecoderWorker.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/decoder/decoderFLAC.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/decoder/decoderMP3.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/decoder/decoderWAV.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/Audio/decoder/DecoderWorker.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/decoder/xing_header.c"
-
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/encoder/Encoder.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/encoder/EncoderWAV.cpp"
-
- "${CMAKE_CURRENT_SOURCE_DIR}/Audio/Audio.cpp"
- "${CMAKE_CURRENT_SOURCE_DIR}/Audio/AudioDeviceFactory.cpp"
- "${CMAKE_CURRENT_SOURCE_DIR}/Audio/AudioMux.cpp"
- "${CMAKE_CURRENT_SOURCE_DIR}/Audio/AudioCommon.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/Endpoint.cpp"
- "${CMAKE_CURRENT_SOURCE_DIR}/Audio/Stream.cpp"
- "${CMAKE_CURRENT_SOURCE_DIR}/Audio/StreamFactory.cpp"
- "${CMAKE_CURRENT_SOURCE_DIR}/Audio/StreamQueuedEventsListener.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/Audio/Operation/IdleOperation.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/Operation/Operation.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/Operation/PlaybackOperation.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/Operation/RecorderOperation.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/Operation/RouterOperation.cpp"
- "${CMAKE_CURRENT_SOURCE_DIR}/Audio/Operation/IdleOperation.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Audio/Profiles/Profile.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/Audio/ServiceObserver.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/Audio/Stream.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/Audio/StreamFactory.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/Audio/StreamQueuedEventsListener.cpp"
)
# include target specific rules
M module-audio/board/rt1051/RT1051DeviceFactory.cpp => module-audio/board/rt1051/RT1051DeviceFactory.cpp +4 -4
@@ 4,6 4,7 @@
#include "RT1051DeviceFactory.hpp"
#include "board/rt1051/RT1051AudioCodec.hpp"
#include "board/rt1051/RT1051CellularAudio.hpp"
+#include "audio/BluetoothAudioDevice.hpp"
using audio::AudioDevice;
using audio::RT1051AudioCodec;
@@ 15,16 16,15 @@ std::shared_ptr<AudioDevice> RT1051DeviceFactory::getDeviceFromType(AudioDevice:
std::shared_ptr<AudioDevice> device;
switch (deviceType) {
case AudioDevice::Type::Audiocodec: {
- device = std::make_unique<RT1051AudioCodec>();
+ device = std::make_shared<RT1051AudioCodec>();
} break;
case AudioDevice::Type::Bluetooth: {
- LOG_FATAL("Bluetooth audio is not yet supported");
- device = nullptr;
+ device = std::make_shared<bluetooth::BluetoothAudioDevice>();
} break;
case AudioDevice::Type::Cellular: {
- device = std::make_unique<RT1051CellularAudio>();
+ device = std::make_shared<RT1051CellularAudio>();
} break;
default:
M module-bluetooth/Bluetooth/BluetoothWorker.cpp => module-bluetooth/Bluetooth/BluetoothWorker.cpp +10 -2
@@ 8,6 8,7 @@
#include "interface/BluetoothDriverImpl.hpp"
#include "interface/profiles/A2DP/A2DP.hpp"
#include "interface/profiles/HSP/HSP.hpp"
+#include "audio/BluetoothAudioDevice.hpp"
#include "BtKeysStorage.hpp"
#if DEBUG_BLUETOOTH_HCI_COMS == 1
@@ 27,8 28,8 @@ using namespace bsp;
namespace queues
{
- constexpr inline auto io = "qBtIO";
- constexpr inline auto cmd = "qBtCmds";
+ constexpr inline auto io = "qBtIO";
+ constexpr inline auto cmd = "qBtCmds";
constexpr inline auto btstack = "qBtStack";
constexpr inline auto queueLength = 10;
@@ 174,6 175,7 @@ auto BluetoothWorker::handleBtStackTrigger(QueueHandle_t queue) -> bool
return false;
}
if (notification) {
+ cpp_freertos::LockGuard lock(loopMutex);
runLoop->process();
return true;
}
@@ 276,3 278,9 @@ void BluetoothWorker::removeFromBoundDevices(uint8_t *addr)
LOG_INFO("Device %s removed from paired devices list", bd_addr_to_str(addr));
}
}
+
+void BluetoothWorker::setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> device)
+{
+ cpp_freertos::LockGuard lock(loopMutex);
+ profileManager->setAudioDevice(std::move(device));
+}
M module-bluetooth/Bluetooth/BluetoothWorker.hpp => module-bluetooth/Bluetooth/BluetoothWorker.hpp +21 -10
@@ 3,17 3,25 @@
#pragma once
-#include "Device.hpp"
-#include "Service/Worker.hpp"
+#include "audio/BluetoothAudioDevice.hpp"
+#include "glucode/BluetoothRunLoop.hpp"
#include "interface/profiles/Profile.hpp"
-#include <FreeRTOS.h>
+#include "service-bluetooth/SettingsHolder.hpp"
+#include "Service/Worker.hpp"
+
+#include "Device.hpp"
+#include "WorkerController.hpp"
+
#include <bsp/bluetooth/Bluetooth.hpp>
-#include <memory>
+
+#include <mutex.hpp>
+
+#include <FreeRTOS.h>
#include <task.h>
+
+#include <memory>
#include <vector>
-#include "service-bluetooth/SettingsHolder.hpp"
-#include "glucode/BluetoothRunLoop.hpp"
-#include "WorkerController.hpp"
+
struct HCI;
/// debug option for HCI (uart) commands debugging
@@ 63,7 71,7 @@ namespace bluetooth
{
};
};
-}; // namespace Bt
+}; // namespace bluetooth
class BluetoothWorker : private sys::Worker
{
@@ 76,8 84,9 @@ class BluetoothWorker : private sys::Worker
queueRunloopTrigger // btstack run_loop queue
};
- sys::Service *service = nullptr;
- bool isRunning = false;
+ sys::Service *service = nullptr;
+ bool isRunning = false;
+ cpp_freertos::MutexStandard loopMutex;
void registerQueues();
void onLinkKeyAdded(const std::string &deviceAddress);
@@ 102,6 111,8 @@ class BluetoothWorker : private sys::Worker
bool run() override;
auto deinit() -> bool override;
+ void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> device);
+
/// bluetooth stack id in use
unsigned long active_features;
std::shared_ptr<bluetooth::ProfileManager> profileManager;
A module-bluetooth/Bluetooth/audio/BluetoothAudioDevice.cpp => module-bluetooth/Bluetooth/audio/BluetoothAudioDevice.cpp +117 -0
@@ 0,0 1,117 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "BluetoothAudioDevice.hpp"
+
+#include <Audio/Stream.hpp>
+
+#include <cassert>
+
+using namespace bluetooth;
+
+BluetoothAudioDevice::BluetoothAudioDevice(MediaContext *mediaContext)
+ : AudioDevice(btCapabilities, btCapabilities), ctx(mediaContext)
+{
+ LOG_DEBUG("Bluetooth audio device created");
+}
+
+BluetoothAudioDevice::~BluetoothAudioDevice()
+{
+ LOG_DEBUG("Destroying bluetooth audio device");
+}
+
+void BluetoothAudioDevice::setMediaContext(MediaContext *mediaContext)
+{
+ ctx = mediaContext;
+}
+
+auto BluetoothAudioDevice::Start(const Format &format) -> audio::AudioDevice::RetCode
+{
+ return audio::AudioDevice::RetCode::Success;
+}
+
+auto BluetoothAudioDevice::Stop() -> audio::AudioDevice::RetCode
+{
+ return audio::AudioDevice::RetCode::Success;
+}
+
+auto BluetoothAudioDevice::OutputVolumeCtrl(float vol) -> audio::AudioDevice::RetCode
+{
+ return audio::AudioDevice::RetCode::Success;
+}
+
+auto BluetoothAudioDevice::InputGainCtrl(float gain) -> audio::AudioDevice::RetCode
+{
+ return audio::AudioDevice::RetCode::Success;
+}
+
+auto BluetoothAudioDevice::OutputPathCtrl(OutputPath outputPath) -> audio::AudioDevice::RetCode
+{
+ return audio::AudioDevice::RetCode::Success;
+}
+
+auto BluetoothAudioDevice::InputPathCtrl(InputPath inputPath) -> audio::AudioDevice::RetCode
+{
+ return audio::AudioDevice::RetCode::Success;
+}
+
+auto BluetoothAudioDevice::IsFormatSupported(const Format &format) -> bool
+{
+ return true;
+}
+
+void BluetoothAudioDevice::onDataSend()
+{
+ if (outputEnabled) {
+ fillSbcAudioBuffer(ctx);
+ }
+}
+
+void BluetoothAudioDevice::onDataReceive()
+{}
+
+void BluetoothAudioDevice::enableInput()
+{}
+
+void BluetoothAudioDevice::enableOutput()
+{
+ LOG_DEBUG("Enabling bluetooth audio output.");
+ outputEnabled = true;
+}
+
+void BluetoothAudioDevice::disableInput()
+{}
+
+void BluetoothAudioDevice::disableOutput()
+{
+ LOG_DEBUG("Disabling bluetooth audio output.");
+ outputEnabled = false;
+}
+
+auto BluetoothAudioDevice::fillSbcAudioBuffer(MediaContext *context) -> int
+{
+ // perform sbc encodin
+ int totalNumBytesRead = 0;
+ unsigned int numAudioSamplesPerSbcBuffer = btstack_sbc_encoder_num_audio_frames();
+
+ assert(context != nullptr);
+
+ while (context->samples_ready >= numAudioSamplesPerSbcBuffer &&
+ (context->max_media_payload_size - context->sbc_storage_count) >= btstack_sbc_encoder_sbc_buffer_length()) {
+ audio::Stream::Span dataSpan;
+
+ Sink::_stream->peek(dataSpan);
+ btstack_sbc_encoder_process_data(reinterpret_cast<int16_t *>(dataSpan.data));
+ Sink::_stream->consume();
+
+ uint16_t sbcFrameSize = btstack_sbc_encoder_sbc_buffer_length();
+ uint8_t *sbcFrame = btstack_sbc_encoder_sbc_buffer();
+
+ totalNumBytesRead += numAudioSamplesPerSbcBuffer;
+ memcpy(&context->sbc_storage[context->sbc_storage_count], sbcFrame, sbcFrameSize);
+ context->sbc_storage_count += sbcFrameSize;
+ context->samples_ready -= numAudioSamplesPerSbcBuffer;
+ }
+
+ return totalNumBytesRead;
+}
A module-bluetooth/Bluetooth/audio/BluetoothAudioDevice.hpp => module-bluetooth/Bluetooth/audio/BluetoothAudioDevice.hpp +47 -0
@@ 0,0 1,47 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <Audio/AudioDevice.hpp>
+#include <interface/profiles/A2DP/MediaContext.hpp>
+
+namespace bluetooth
+{
+
+ class BluetoothAudioDevice : public audio::AudioDevice
+ {
+ public:
+ BluetoothAudioDevice() = default;
+ explicit BluetoothAudioDevice(MediaContext *mediaContext);
+ virtual ~BluetoothAudioDevice();
+
+ void setMediaContext(MediaContext *MediaContext);
+
+ auto Start(const Format &format) -> audio::AudioDevice::RetCode override;
+ auto Stop() -> audio::AudioDevice::RetCode override;
+
+ auto OutputVolumeCtrl(float vol) -> audio::AudioDevice::RetCode override;
+ auto InputGainCtrl(float gain) -> audio::AudioDevice::RetCode override;
+ auto OutputPathCtrl(OutputPath outputPath) -> audio::AudioDevice::RetCode override;
+ auto InputPathCtrl(InputPath inputPath) -> audio::AudioDevice::RetCode override;
+ auto IsFormatSupported(const Format &format) -> bool override;
+
+ // Endpoint control methods
+ void onDataSend() override;
+ void onDataReceive() override;
+ void enableInput() override;
+ void enableOutput() override;
+ void disableInput() override;
+ void disableOutput() override;
+
+ private:
+ auto fillSbcAudioBuffer(MediaContext *context) -> int;
+
+ MediaContext *ctx = nullptr;
+ bool outputEnabled = false;
+
+ static constexpr Capabilities btCapabilities = {.usesDMA = false, .minBlockSize = 512U, .maxBlockSize = 512U};
+ };
+
+}; // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp +21 -49
@@ 20,6 20,8 @@
#include "service-bluetooth/messages/Connect.hpp"
#include "service-bluetooth/messages/Disconnect.hpp"
#include "service-bluetooth/Constants.hpp"
+#include <audio/BluetoothAudioDevice.hpp>
+
extern "C"
{
#include "module-bluetooth/lib/btstack/src/btstack.h"
@@ 73,11 75,6 @@ namespace bluetooth
pimpl->setOwnerService(service);
}
- auto A2DP::getStreamData() -> std::shared_ptr<BluetoothStreamData>
- {
- return pimpl->getStreamData();
- }
-
void A2DP::connect()
{
pimpl->connect();
@@ 98,6 95,11 @@ namespace bluetooth
pimpl->stop();
}
+ void A2DP::setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice)
+ {
+ pimpl->setAudioDevice(std::move(audioDevice));
+ }
+
const sys::Service *A2DP::A2DPImpl::ownerService;
QueueHandle_t A2DP::A2DPImpl::sourceQueue = nullptr;
QueueHandle_t A2DP::A2DPImpl::sinkQueue = nullptr;
@@ 110,6 112,7 @@ namespace bluetooth
0xFF, //(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS,
2,
53};
+ std::shared_ptr<BluetoothAudioDevice> A2DP::A2DPImpl::audioDevice;
bool A2DP::A2DPImpl::isConnected = false;
/* LISTING_START(MainConfiguration): Setup Audio Source and AVRCP Target services */
@@ 195,40 198,6 @@ namespace bluetooth
AVRCP::mediaTracker.sbc_ready_to_send = 0;
}
- auto A2DP::A2DPImpl::fillSbcAudioBuffer(MediaContext *context) -> int
- {
- // perform sbc encodin
- int totalNumBytesRead = 0;
- unsigned int numAudioSamplesPerSbcBuffer = btstack_sbc_encoder_num_audio_frames();
- while (context->samples_ready >= numAudioSamplesPerSbcBuffer &&
- (context->max_media_payload_size - context->sbc_storage_count) >=
- btstack_sbc_encoder_sbc_buffer_length()) {
-
- AudioData_t audioData;
-
- if (sourceQueue != nullptr) {
- if (xQueueReceive(sourceQueue, &audioData, 10) != pdPASS) {
- audioData.data.fill(0);
- }
- }
- else {
- audioData.data.fill(0);
- LOG_ERROR("queue is nullptr!");
- }
-
- btstack_sbc_encoder_process_data(audioData.data.data());
-
- uint16_t sbcFrameSize = btstack_sbc_encoder_sbc_buffer_length();
- uint8_t *sbcFrame = btstack_sbc_encoder_sbc_buffer();
-
- totalNumBytesRead += numAudioSamplesPerSbcBuffer;
- memcpy(&context->sbc_storage[context->sbc_storage_count], sbcFrame, sbcFrameSize);
- context->sbc_storage_count += sbcFrameSize;
- context->samples_ready -= numAudioSamplesPerSbcBuffer;
- }
- return totalNumBytesRead;
- }
-
void A2DP::A2DPImpl::audioTimeoutHandler(btstack_timer_source_t *timer)
{
auto *context = static_cast<MediaContext *>(btstack_run_loop_get_timer_context(timer));
@@ 255,7 224,9 @@ namespace bluetooth
return;
}
- fillSbcAudioBuffer(context);
+ if (audioDevice != nullptr) {
+ audioDevice->onDataSend();
+ }
if ((context->sbc_storage_count + btstack_sbc_encoder_sbc_buffer_length()) > context->max_media_payload_size) {
// schedule sending
@@ 347,7 318,7 @@ namespace bluetooth
bd_addr_to_str(address),
AVRCP::mediaTracker.a2dp_cid,
AVRCP::mediaTracker.local_seid);
- isConnected = true;
+ isConnected = true;
auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
busProxy.sendUnicast(std::make_shared<message::bluetooth::ConnectResult>(std::move(deviceAddress), true),
service::name::bluetooth);
@@ 608,15 579,10 @@ namespace bluetooth
ownerService = service;
}
- auto A2DP::A2DPImpl::getStreamData() -> std::shared_ptr<BluetoothStreamData>
- {
- return std::make_shared<BluetoothStreamData>(sinkQueue, sourceQueue, metadata);
- }
-
void A2DP::A2DPImpl::sendAudioEvent(audio::EventType event, audio::Event::DeviceState state)
{
- auto evt = std::make_shared<audio::Event>(event, state);
- auto msg = std::make_shared<AudioEventRequest>(std::move(evt));
+ auto evt = std::make_shared<audio::Event>(event, state);
+ auto msg = std::make_shared<AudioEventRequest>(std::move(evt));
auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
busProxy.sendUnicast(std::move(msg), service::name::evt_manager);
}
@@ 634,4 600,10 @@ namespace bluetooth
a2dp_source_pause_stream(AVRCP::mediaTracker.a2dp_cid, AVRCP::mediaTracker.local_seid);
}
-} // namespace Bt
+ void A2DP::A2DPImpl::setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> newAudioDevice)
+ {
+ newAudioDevice->setMediaContext(&AVRCP::mediaTracker);
+ A2DP::A2DPImpl::audioDevice = std::move(newAudioDevice);
+ }
+
+} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.hpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.hpp +5 -4
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 8,7 8,7 @@
#include "Service/Service.hpp"
#include "queue.h"
#include <memory>
-#include <service-bluetooth/ServiceBluetoothCommon.hpp>
+
namespace bluetooth
{
class A2DP : public Profile
@@ 25,15 25,16 @@ namespace bluetooth
auto init() -> Error::Code override;
void setDeviceAddress(uint8_t *addr) override;
void setOwnerService(const sys::Service *service) override;
- [[nodiscard]] auto getStreamData() -> std::shared_ptr<BluetoothStreamData> override;
void connect() override;
void disconnect() override;
void start() override;
void stop() override;
+ void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice) override;
+
private:
class A2DPImpl;
std::unique_ptr<A2DPImpl> pimpl;
};
-} // namespace Bt
+} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DPImpl.hpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DPImpl.hpp +10 -26
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 8,6 8,11 @@
#include <BtCommand.hpp>
#include <log/log.hpp>
#include <Audio/AudioCommon.hpp>
+#include <audio/BluetoothAudioDevice.hpp>
+
+#include "MediaContext.hpp"
+
+#include <memory>
extern "C"
{
@@ 17,29 22,6 @@ extern "C"
namespace bluetooth
{
- static constexpr int SBC_STORAGE_SIZE = 1030;
- struct MediaContext
- {
- uint16_t a2dp_cid;
- uint8_t local_seid;
- uint8_t remote_seid;
- uint8_t stream_opened;
- uint16_t avrcp_cid;
-
- uint32_t time_audio_data_sent_in_ms;
- uint32_t acc_num_missed_samples;
- uint32_t samples_ready;
- btstack_timer_source_t audio_timer;
- uint8_t streaming;
- int max_media_payload_size;
-
- uint8_t sbc_storage[SBC_STORAGE_SIZE];
- uint16_t sbc_storage_count;
- uint8_t sbc_ready_to_send;
-
- uint16_t volume;
- };
-
class AVRCP;
class A2DP::A2DPImpl
{
@@ 66,10 48,11 @@ namespace bluetooth
static void sourcePacketHandler(uint8_t packetType, uint16_t channel, uint8_t *packet, uint16_t size);
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, audio::Event::DeviceState state);
static bool isConnected;
+ static std::shared_ptr<BluetoothAudioDevice> audioDevice;
+
public:
auto init() -> Error::Code;
void connect();
@@ 79,5 62,6 @@ namespace bluetooth
void setDeviceAddress(bd_addr_t addr);
void setOwnerService(const sys::Service *service);
auto getStreamData() -> std::shared_ptr<BluetoothStreamData>;
+ void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice);
};
-} // namespace Bt
+} // namespace bluetooth
A module-bluetooth/Bluetooth/interface/profiles/A2DP/MediaContext.hpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/MediaContext.hpp +39 -0
@@ 0,0 1,39 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+extern "C"
+{
+#include <btstack.h>
+#include <btstack_defines.h>
+}
+
+#include <cstdint>
+
+namespace bluetooth
+{
+ static constexpr int SBC_STORAGE_SIZE = 1030;
+ struct MediaContext
+ {
+ uint16_t a2dp_cid;
+ uint8_t local_seid;
+ uint8_t remote_seid;
+ uint8_t stream_opened;
+ uint16_t avrcp_cid;
+
+ uint32_t time_audio_data_sent_in_ms;
+ uint32_t acc_num_missed_samples;
+ uint32_t samples_ready;
+ btstack_timer_source_t audio_timer;
+ uint8_t streaming;
+ int max_media_payload_size;
+
+ uint8_t sbc_storage[SBC_STORAGE_SIZE];
+ uint16_t sbc_storage_count;
+ uint8_t sbc_ready_to_send;
+
+ uint16_t volume;
+ };
+
+} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp => module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp +5 -10
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "HSPImpl.hpp"
@@ 51,11 51,6 @@ namespace bluetooth
pimpl->setOwnerService(service);
}
- auto HSP::getStreamData() -> std::shared_ptr<BluetoothStreamData>
- {
- return pimpl->getStreamData();
- }
-
void HSP::connect()
{
pimpl->connect();
@@ 89,8 84,8 @@ namespace bluetooth
void HSP::HSPImpl::sendAudioEvent(audio::EventType event, audio::Event::DeviceState state)
{
- auto evt = std::make_shared<audio::Event>(event, state);
- auto msg = std::make_shared<AudioEventRequest>(std::move(evt));
+ auto evt = std::make_shared<audio::Event>(event, state);
+ auto msg = std::make_shared<AudioEventRequest>(std::move(evt));
auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
busProxy.sendUnicast(std::move(msg), service::name::evt_manager);
}
@@ 165,7 160,7 @@ namespace bluetooth
case HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE:
LOG_DEBUG("Audio connection released.\n\n");
sendAudioEvent(audio::EventType::BlutoothHSPDeviceState, audio::Event::DeviceState::Disconnected);
- scoHandle = HCI_CON_HANDLE_INVALID;
+ scoHandle = HCI_CON_HANDLE_INVALID;
isConnected = false;
break;
case HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED:
@@ 259,4 254,4 @@ namespace bluetooth
hsp_ag_release_audio_connection();
}
-} // namespace Bt
+} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.hpp => module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.hpp +5 -3
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 25,7 25,6 @@ namespace bluetooth
auto init() -> Error::Code override;
void setDeviceAddress(uint8_t *addr) override;
- auto getStreamData() -> std::shared_ptr<BluetoothStreamData> override;
void setOwnerService(const sys::Service *service) override;
void connect() override;
@@ 33,6 32,9 @@ namespace bluetooth
void start() override;
void stop() override;
+ void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice) override
+ {}
+
private:
class HSPImpl;
std::unique_ptr<HSPImpl> pimpl;
@@ 40,4 42,4 @@ namespace bluetooth
btstack_run_loop *runLoopInstance{};
};
-} // namespace Bt
+} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/Profile.hpp => module-bluetooth/Bluetooth/interface/profiles/Profile.hpp +12 -9
@@ 4,23 4,26 @@
#pragma once
#include "Error.hpp"
+#include <audio/BluetoothAudioDevice.hpp>
#include <Service/Message.hpp>
#include <service-bluetooth/ServiceBluetoothCommon.hpp>
+
#include <memory>
+
namespace bluetooth
{
class Profile
{
public:
- virtual ~Profile() = default;
- virtual auto init() -> Error::Code = 0;
- virtual void setDeviceAddress(uint8_t *addr) = 0;
- virtual void setOwnerService(const sys::Service *service) = 0;
- virtual auto getStreamData() -> std::shared_ptr<BluetoothStreamData> = 0;
- virtual void connect() = 0;
- virtual void start() = 0;
- virtual void stop() = 0;
- virtual void disconnect() = 0;
+ virtual ~Profile() = default;
+ virtual auto init() -> Error::Code = 0;
+ virtual void setDeviceAddress(uint8_t *addr) = 0;
+ virtual void setOwnerService(const sys::Service *service) = 0;
+ virtual void connect() = 0;
+ virtual void start() = 0;
+ virtual void stop() = 0;
+ virtual void disconnect() = 0;
+ virtual void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice) = 0;
};
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/ProfileManager.cpp => module-bluetooth/Bluetooth/interface/profiles/ProfileManager.cpp +11 -0
@@ 82,15 82,26 @@ namespace bluetooth
start();
return Error::Success;
}
+
auto ProfileManager::start() -> Error::Code
{
currentProfilePtr->start();
return Error::Success;
}
+
auto ProfileManager::stop() -> Error::Code
{
currentProfilePtr->stop();
return Error::Success;
}
+ auto ProfileManager::setAudioDevice(std::shared_ptr<BluetoothAudioDevice> device) -> Error::Code
+ {
+ if (currentProfilePtr == nullptr) {
+ return Error::NotReady;
+ }
+
+ currentProfilePtr->setAudioDevice(std::move(device));
+ return Error::Success;
+ }
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/ProfileManager.hpp => module-bluetooth/Bluetooth/interface/profiles/ProfileManager.hpp +5 -0
@@ 8,6 8,9 @@
#include "Profile.hpp"
#include "interface/profiles/A2DP/A2DP.hpp"
#include "interface/profiles/HSP/HSP.hpp"
+#include "audio/BluetoothAudioDevice.hpp"
+
+#include <memory>
extern "C"
{
@@ 44,6 47,8 @@ namespace bluetooth
auto start() -> Error::Code;
auto stop() -> Error::Code;
+ auto setAudioDevice(std::shared_ptr<BluetoothAudioDevice> device) -> Error::Code;
+
private:
sys::Service *ownerService;
ProfileList profilesList;
M module-bluetooth/CMakeLists.txt => module-bluetooth/CMakeLists.txt +5 -1
@@ 1,8 1,12 @@
-project(module-bluetooth VERSION 1.0 DESCRIPTION "Bluetooth module library")
+# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+project(module-bluetooth VERSION 1.0 DESCRIPTION "Bluetooth module library")
set(CMAKE_CXX_STANDARD 17)
set(SOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/audio/BluetoothAudioDevice.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/BluetoothWorker.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/WorkerController.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/CommandHandler.cpp
M module-services/service-audio/ServiceAudio.cpp => module-services/service-audio/ServiceAudio.cpp +30 -7
@@ 6,6 6,7 @@
#include <Audio/Operation/IdleOperation.hpp>
#include <Audio/Operation/PlaybackOperation.hpp>
+#include <Bluetooth/audio/BluetoothAudioDevice.hpp>
#include <service-bluetooth/Constants.hpp>
#include <service-bluetooth/ServiceBluetoothCommon.hpp>
#include <service-bluetooth/BluetoothMessage.hpp>
@@ 217,6 218,13 @@ std::optional<std::string> ServiceAudio::AudioServicesCallback(const sys::Messag
}
return settings_it->second;
}
+ else if (const auto *deviceMsg = dynamic_cast<const AudioServiceMessage::AudioDeviceCreated *>(msg); deviceMsg) {
+ if (deviceMsg->getDeviceType() == AudioDevice::Type::Bluetooth) {
+ auto startBluetoothAudioMsg = std::make_shared<BluetoothAudioStartMessage>(
+ std::static_pointer_cast<bluetooth::BluetoothAudioDevice>(deviceMsg->getDevice()));
+ bus.sendUnicast(std::move(startBluetoothAudioMsg), service::name::bluetooth);
+ }
+ }
else {
LOG_DEBUG("Message received but not handled - no effect.");
}
@@ 377,6 385,13 @@ std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleStart(const Operation:
if (opType == Operation::Type::Playback) {
auto input = audioMux.GetPlaybackInput(playbackType);
+ // stop bluetooth stream if available
+ if (bluetoothConnected) {
+ LOG_DEBUG("Sending Bluetooth start stream request");
+ bus.sendUnicast(std::make_shared<BluetoothMessage>(BluetoothMessage::Request::Play),
+ service::name::bluetooth);
+ }
+
AudioStart(input);
return std::make_unique<AudioStartPlaybackResponse>(retCode, retToken);
}
@@ 395,17 410,20 @@ std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleStart(const Operation:
std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleSendEvent(std::shared_ptr<Event> evt)
{
- auto isBT =
- evt->getType() == EventType::BlutoothHSPDeviceState || evt->getType() == EventType::BlutoothA2DPDeviceState;
- if (isBT && evt->getDeviceState() == audio::Event::DeviceState::Connected) {
- auto req = std::make_shared<BluetoothRequestStreamMessage>();
- bus.sendUnicast(req, service::name::bluetooth);
- return std::make_unique<AudioEventResponse>(RetCode::Success);
+ // update bluetooth state
+ if (evt->getType() == EventType::BlutoothA2DPDeviceState) {
+ auto newState = evt->getDeviceState() == Event::DeviceState::Connected;
+ if (newState != bluetoothConnected) {
+ LOG_DEBUG("Bluetooth connection status changed: %s", newState ? "connected" : "disconnected");
+ bluetoothConnected = newState;
+ }
}
+ // update information about endpoints availability
for (auto &input : audioMux.GetAllInputs()) {
input.audio->SendEvent(evt);
}
+
return std::make_unique<AudioEventResponse>(RetCode::Success);
}
@@ 451,6 469,12 @@ std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleStop(const std::vector
}
}
+ // stop bluetooth stream if available
+ if (bluetoothConnected) {
+ LOG_DEBUG("Sending Bluetooth stop request");
+ bus.sendUnicast(std::make_shared<BluetoothMessage>(BluetoothMessage::Request::Stop), service::name::bluetooth);
+ }
+
// on failure return first false code
auto it =
std::find_if_not(retCodes.begin(), retCodes.end(), [](auto p) { return p.second == audio::RetCode::Success; });
@@ 560,7 584,6 @@ sys::MessagePointer ServiceAudio::DataReceivedHandler(sys::DataMessage *msgl, sy
{
sys::MessagePointer responseMsg;
bool isBusy = IsBusy();
-
auto &msgType = typeid(*msgl);
if (msgType == typeid(AudioNotificationMessage)) {
M module-services/service-audio/service-audio/ServiceAudio.hpp => module-services/service-audio/service-audio/ServiceAudio.hpp +1 -1
@@ 58,8 58,8 @@ class ServiceAudio : public sys::Service
audio::AudioMux::VibrationStatus vibrationMotorStatus = audio::AudioMux::VibrationStatus::Off;
std::unique_ptr<settings::Settings> settingsProvider;
std::map<std::string, std::string> settingsCache;
-
std::unique_ptr<sys::phone_modes::Observer> phoneModeObserver;
+ bool bluetoothConnected = false;
auto IsVibrationMotorOn()
{
M module-services/service-bluetooth/ServiceBluetooth.cpp => module-services/service-bluetooth/ServiceBluetooth.cpp +22 -63
@@ 69,69 69,20 @@ sys::ReturnCodes ServiceBluetooth::InitHandler()
LOG_ERROR("Disconnecting from timeout timer!");
});
- connect(message::bluetooth::RequestBondedDevices(), [&](sys::Message *msg) {
- auto request = static_cast<message::bluetooth::RequestBondedDevices *>(msg);
- return handle(request);
- });
-
- connect(message::bluetooth::RequestStatus(), [&](sys::Message *msg) {
- auto request = static_cast<message::bluetooth::RequestStatus *>(msg);
- return handle(request);
- });
-
- connect(typeid(message::bluetooth::SetStatus), [&](sys::Message *msg) {
- auto request = static_cast<message::bluetooth::SetStatus *>(msg);
- return handle(request);
- });
-
- connect(typeid(BluetoothPairMessage), [&](sys::Message *msg) {
- auto request = static_cast<BluetoothPairMessage *>(msg);
- return handle(request);
- });
- connect(typeid(message::bluetooth::Unpair), [&](sys::Message *msg) {
- auto request = static_cast<message::bluetooth::Unpair *>(msg);
- return handle(request);
- });
-
- connect(typeid(message::bluetooth::SetDeviceName), [&](sys::Message *msg) {
- auto request = static_cast<message::bluetooth::SetDeviceName *>(msg);
- return handle(request);
- });
-
- connect(typeid(sdesktop::developerMode::DeveloperModeRequest), [&](sys::Message *msg) {
- auto request = static_cast<sdesktop::developerMode::DeveloperModeRequest *>(msg);
- return handle(request);
- });
-
- connect(typeid(message::bluetooth::Connect), [&](sys::Message *msg) {
- auto request = static_cast<message::bluetooth::Connect *>(msg);
- return handle(request);
- });
-
- connect(typeid(message::bluetooth::Disconnect), [&](sys::Message *msg) {
- auto request = static_cast<message::bluetooth::Disconnect *>(msg);
- return handle(request);
- });
-
- connect(typeid(BluetoothMessage), [&](sys::Message *msg) {
- auto request = static_cast<BluetoothMessage *>(msg);
- return handle(request);
- });
-
- connect(typeid(BluetoothAddrMessage), [&](sys::Message *msg) {
- auto request = static_cast<BluetoothAddrMessage *>(msg);
- return handle(request);
- });
-
- connect(typeid(message::bluetooth::ConnectResult), [&](sys::Message *msg) {
- auto result = static_cast<message::bluetooth::ConnectResult *>(msg);
- return handle(result);
- });
-
- connect(typeid(message::bluetooth::DisconnectResult), [&](sys::Message *msg) {
- auto result = static_cast<message::bluetooth::DisconnectResult *>(msg);
- return handle(result);
- });
+ connectHandler<BluetoothAddrMessage>();
+ connectHandler<BluetoothAudioStartMessage>();
+ connectHandler<BluetoothMessage>();
+ connectHandler<BluetoothPairMessage>();
+ connectHandler<message::bluetooth::Connect>();
+ connectHandler<message::bluetooth::ConnectResult>();
+ connectHandler<message::bluetooth::Disconnect>();
+ connectHandler<message::bluetooth::DisconnectResult>();
+ connectHandler<message::bluetooth::RequestBondedDevices>();
+ connectHandler<message::bluetooth::RequestStatus>();
+ connectHandler<message::bluetooth::SetDeviceName>();
+ connectHandler<message::bluetooth::SetStatus>();
+ connectHandler<message::bluetooth::Unpair>();
+ connectHandler<sdesktop::developerMode::DeveloperModeRequest>();
settingsHolder->onStateChange = [this]() {
auto initialState = std::visit(bluetooth::IntVisitor(), settingsHolder->getValue(bluetooth::Settings::State));
@@ 157,6 108,7 @@ void ServiceBluetooth::ProcessCloseReason(sys::CloseReason closeReason)
sys::MessagePointer ServiceBluetooth::DataReceivedHandler([[maybe_unused]] sys::DataMessage *msg,
[[maybe_unused]] sys::ResponseMessage *resp)
{
+ LOG_ERROR("Unhandled message: %s", typeid(msg).name());
return std::make_shared<sys::ResponseMessage>();
}
@@ 170,6 122,12 @@ void ServiceBluetooth::sendWorkerCommand(bluetooth::Command command)
xQueueSend(workerQueue, &command, portMAX_DELAY);
}
+auto ServiceBluetooth::handle(BluetoothAudioStartMessage *msg) -> std::shared_ptr<sys::Message>
+{
+ worker->setAudioDevice(msg->getAudioDevice());
+ return std::make_shared<sys::ResponseMessage>();
+}
+
auto ServiceBluetooth::handle([[maybe_unused]] message::bluetooth::RequestBondedDevices *msg)
-> std::shared_ptr<sys::Message>
{
@@ 213,6 171,7 @@ auto ServiceBluetooth::handle(message::bluetooth::SetStatus *msg) -> std::shared
sendWorkerCommand(command);
return sys::MessageNone{};
}
+
auto ServiceBluetooth::handle(BluetoothPairMessage *msg) -> std::shared_ptr<sys::Message>
{
const auto addrString = msg->addr;
M module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp => module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp +7 -38
@@ 6,8 6,8 @@
#include "ServiceBluetoothCommon.hpp"
#include <Bluetooth/Device.hpp>
+#include <Bluetooth/audio/BluetoothAudioDevice.hpp>
#include <Service/Message.hpp>
-#include <Audio/Stream.hpp>
#include <MessageType.hpp>
#include <utility>
@@ 85,49 85,18 @@ class BluetoothPairMessage : public sys::DataMessage
~BluetoothPairMessage() override = default;
};
-class BluetoothAudioRegisterMessage : public sys::DataMessage
+class BluetoothAudioStartMessage : public sys::DataMessage
{
public:
- QueueHandle_t audioSourceQueue;
- QueueHandle_t audioSinkQueue;
- BluetoothAudioRegisterMessage(QueueHandle_t audioSourceQueue, QueueHandle_t audioSinkQueue)
- : sys::DataMessage(MessageType::BluetoothAudioRegister), audioSourceQueue(audioSourceQueue),
- audioSinkQueue(audioSinkQueue)
+ explicit BluetoothAudioStartMessage(std::shared_ptr<bluetooth::BluetoothAudioDevice> device)
+ : DataMessage(MessageType::BluetoothAudioStart), device(std::move(device))
{}
- ~BluetoothAudioRegisterMessage() override = default;
-};
-
-class BluetoothDeviceMetadataMessage : public sys::DataMessage
-{
- public:
- DeviceMetadata_t metadata;
- BluetoothDeviceMetadataMessage(DeviceMetadata_t metadata)
- : DataMessage(MessageType::BluetoothDeviceMetadata), metadata(std::move(metadata))
- {}
- ~BluetoothDeviceMetadataMessage() override = default;
-};
-
-class BluetoothRequestStreamMessage : public sys::DataMessage
-{
- public:
- BluetoothRequestStreamMessage() : DataMessage(MessageType::BluetoothRequestStream)
- {}
- ~BluetoothRequestStreamMessage() override = default;
-};
-
-class BluetoothRequestStreamResultMessage : public sys::DataMessage
-{
- public:
- BluetoothRequestStreamResultMessage(std::shared_ptr<BluetoothStreamData> data)
- : DataMessage(MessageType::BluetoothRequestStream), data(data)
- {}
- ~BluetoothRequestStreamResultMessage() override = default;
- std::shared_ptr<BluetoothStreamData> getData()
+ auto getAudioDevice() const -> std::shared_ptr<bluetooth::BluetoothAudioDevice>
{
- return data;
+ return device;
}
private:
- std::shared_ptr<BluetoothStreamData> data;
+ std::shared_ptr<bluetooth::BluetoothAudioDevice> device;
};
M module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp => module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp +6 -0
@@ 72,6 72,11 @@ class ServiceBluetooth : public sys::Service
void startTimeoutTimer();
void stopTimeoutTimer();
+ template <typename T> auto connectHandler() -> bool
+ {
+ return connect(typeid(T), [&](sys::Message *msg) { return handle(static_cast<T *>(msg)); });
+ }
+
[[nodiscard]] auto handle(message::bluetooth::RequestBondedDevices *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(message::bluetooth::RequestStatus *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(message::bluetooth::SetStatus *msg) -> std::shared_ptr<sys::Message>;
@@ 85,6 90,7 @@ class ServiceBluetooth : public sys::Service
[[nodiscard]] auto handle(BluetoothMessage *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(BluetoothAddrMessage *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(sdesktop::developerMode::DeveloperModeRequest *msg) -> std::shared_ptr<sys::Message>;
+ [[nodiscard]] auto handle(BluetoothAudioStartMessage *msg) -> std::shared_ptr<sys::Message>;
};
namespace sys
M source/MessageType.hpp => source/MessageType.hpp +1 -12
@@ 192,18 192,7 @@ enum class MessageType
BluetoothScanResult,
BluetoothAddrResult,
BluetoothPairResult,
- BluetoothAudioRegister,
- BluetoothDeviceMetadata,
- BluetoothRequestStream,
- BluetoothDeviceDisconnected,
-
- // bluetooth proxy
- BluetoothProxyStart,
- BluetoothProxyStop,
- BluetoothProxyOutputVolumeCtrl,
- BluetoothProxyInputGainCtrl,
- BluetoothProxyOutputPathCtrl,
- BluetoothProxyInputPathCtrl,
+ BluetoothAudioStart,
LwIP_request,
EVM_GPIO,