M module-apps/application-music-player/AudioNotificationsHandler.cpp => module-apps/application-music-player/AudioNotificationsHandler.cpp +2 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "AudioNotificationsHandler.hpp"
@@ 10,7 10,7 @@ namespace app::music_player
AudioNotificationsHandler::AudioNotificationsHandler(
std::shared_ptr<app::music_player::SongsContract::Presenter> presenter)
- : presenter(presenter)
+ : presenter(std::move(presenter))
{}
sys::MessagePointer AudioNotificationsHandler::handleAudioStopNotification(
M module-apps/application-music-player/AudioNotificationsHandler.hpp => module-apps/application-music-player/AudioNotificationsHandler.hpp +2 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 8,6 8,7 @@
class AudioStopNotification;
class AudioPausedNotification;
class AudioResumedNotification;
+
namespace app::music_player
{
class AudioNotificationsHandler
M module-apps/application-music-player/widgets/SongItem.cpp => module-apps/application-music-player/widgets/SongItem.cpp +1 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "module-apps/application-music-player/widgets/SongItem.hpp"
@@ 7,7 7,6 @@
namespace gui
{
-
using namespace musicPlayerStyle;
SongItem::SongItem(const std::string &authorName,
M module-apps/application-music-player/windows/MusicPlayerMainWindow.cpp => module-apps/application-music-player/windows/MusicPlayerMainWindow.cpp +2 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "MusicPlayerMainWindow.hpp"
@@ 40,7 40,7 @@ namespace
}
return std::string(timeStringBuffer);
- };
+ }
} // namespace
namespace gui
M module-audio/Audio/Audio.cpp => module-audio/Audio/Audio.cpp +5 -3
@@ 9,9 9,9 @@
namespace audio
{
- Audio::Audio(AudioServiceMessage::Callback callback) : currentOperation(), serviceCallback(callback)
+ Audio::Audio(AudioServiceMessage::Callback callback) : currentOperation(), serviceCallback(std::move(callback))
{
- auto ret = Operation::Create(Operation::Type::Idle, "", audio::PlaybackType::None, callback);
+ auto ret = Operation::Create(Operation::Type::Idle, "", audio::PlaybackType::None, serviceCallback);
if (ret) {
currentOperation = std::move(ret);
}
@@ 85,7 85,9 @@ namespace audio
audio::RetCode Audio::Start()
{
- currentOperation->Stop();
+ if (currentState != State::Idle) {
+ currentOperation->Stop();
+ }
return Start(currentOperation->GetOperationType(),
currentOperation->GetToken(),
currentOperation->GetFilePath(),
M module-audio/Audio/Audio.hpp => module-audio/Audio/Audio.hpp +2 -3
@@ 31,8 31,7 @@ namespace audio
Routing,
};
- Audio(AudioServiceMessage::Callback callback);
-
+ explicit Audio(AudioServiceMessage::Callback callback);
virtual ~Audio() = default;
// Events
@@ 70,7 69,7 @@ namespace audio
const Operation &GetCurrentOperation() const
{
// currentOperation always exists - null pattern design
- return *(currentOperation.get());
+ return *currentOperation;
}
virtual audio::PlaybackType GetCurrentOperationPlaybackType() const
M module-audio/Audio/AudioDeviceFactory.hpp => module-audio/Audio/AudioDeviceFactory.hpp +1 -1
@@ 33,4 33,4 @@ namespace audio
private:
Observer *_observer = nullptr;
};
-}; // namespace audio
+} // namespace audio
M module-bluetooth/Bluetooth/audio/BluetoothAudioDevice.cpp => module-bluetooth/Bluetooth/audio/BluetoothAudioDevice.cpp +30 -4
@@ 12,6 12,7 @@
#include <Audio/VolumeScaler.hpp>
#include <Utils.hpp>
+#include <ticks.hpp>
#include <chrono>
#include <cassert>
@@ 311,11 312,36 @@ void CVSDAudioDevice::setAclHandle(hci_con_handle_t handle)
aclHandle = handle;
}
+audio::AudioDevice::RetCode A2DPAudioDevice::waitUntilStreamPaused() const
+{
+ /* Wait until A2DP stream is paused before proceeding. This is hacky way to prevent
+ * race condition when music player track automatically changes to the next one.
+ * a2dp_source functions are asynchronous, so in such case sometimes play request is
+ * sent before pause request has been fully processed, what results in A2DP stream
+ * not being restarted. */
+ constexpr auto timeoutMs = 200;
+ constexpr auto retryDelayMs = 10;
+
+ auto timeoutLoops = timeoutMs / retryDelayMs;
+ while ((AVRCP::playInfo.status == AVRCP_PLAYBACK_STATUS_PLAYING) && (timeoutLoops > 0)) {
+ vTaskDelay(cpp_freertos::Ticks::MsToTicks(retryDelayMs));
+ timeoutLoops--;
+ }
+
+ return (timeoutLoops == 0) ? audio::AudioDevice::RetCode::Failure : audio::AudioDevice::RetCode::Success;
+}
+
audio::AudioDevice::RetCode A2DPAudioDevice::Start()
{
- return (a2dp_source_start_stream(AVRCP::mediaTracker.a2dp_cid, AVRCP::mediaTracker.local_seid) == 0)
- ? audio::AudioDevice::RetCode::Success
- : audio::AudioDevice::RetCode::Failure;
+ const auto retCode = a2dp_source_start_stream(AVRCP::mediaTracker.a2dp_cid, AVRCP::mediaTracker.local_seid);
+ switch (retCode) {
+ case ERROR_CODE_SUCCESS:
+ return audio::AudioDevice::RetCode::Success;
+ case ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER:
+ return audio::AudioDevice::RetCode::Disconnected;
+ default:
+ return audio::AudioDevice::RetCode::Failure;
+ }
}
audio::AudioDevice::RetCode A2DPAudioDevice::Stop()
@@ 323,7 349,7 @@ audio::AudioDevice::RetCode A2DPAudioDevice::Stop()
const auto retCode = a2dp_source_pause_stream(AVRCP::mediaTracker.a2dp_cid, AVRCP::mediaTracker.local_seid);
switch (retCode) {
case ERROR_CODE_SUCCESS:
- return audio::AudioDevice::RetCode::Success;
+ return waitUntilStreamPaused();
case ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER:
return audio::AudioDevice::RetCode::Disconnected; // Device disconnected during playback, e.g. headphones
// discharged
M module-bluetooth/Bluetooth/audio/BluetoothAudioDevice.hpp => module-bluetooth/Bluetooth/audio/BluetoothAudioDevice.hpp +7 -4
@@ 34,8 34,8 @@ namespace bluetooth
void disableOutput() override;
protected:
- auto isInputEnabled() const -> bool;
- auto isOutputEnabled() const -> bool;
+ [[nodiscard]] auto isInputEnabled() const -> bool;
+ [[nodiscard]] auto isOutputEnabled() const -> bool;
auto fillSbcAudioBuffer() -> int;
auto scaleVolume(audio::Stream::Span &dataSpan) const -> void;
@@ 59,13 59,16 @@ namespace bluetooth
void onDataSend() override;
void onDataReceive() override;
auto getSupportedFormats() -> std::vector<audio::AudioFormat> override;
- auto getTraits() const -> Traits 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
@@ 82,7 85,7 @@ namespace bluetooth
void onDataSend(std::uint16_t scoHandle);
void onDataReceive() override;
auto getSupportedFormats() -> std::vector<audio::AudioFormat> override;
- auto getTraits() const -> Traits override;
+ [[nodiscard]] auto getTraits() const -> Traits override;
auto getSourceFormat() -> ::audio::AudioFormat override;
void enableInput() override;
void setAclHandle(hci_con_handle_t handle);
M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp +4 -13
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "A2DP.hpp"
@@ 32,7 32,7 @@ namespace bluetooth
A2DP::~A2DP()
{
pimpl->disconnect();
- pimpl->deInit();
+ pimpl->deinit();
}
A2DP::A2DP(A2DP &other) : pimpl(new A2DPImpl(*other.pimpl))
@@ 114,13 114,11 @@ namespace bluetooth
btstack_packet_callback_registration_t A2DP::A2DPImpl::hciEventCallbackRegistration;
- QueueHandle_t A2DP::A2DPImpl::sourceQueue = nullptr;
-
bool A2DP::A2DPImpl::isConnected = false;
auto A2DP::A2DPImpl::init() -> Result::Code
{
- // request role change on reconnecting headset to always use them in slave mode
+ // Request role change on reconnecting headset to always use them in slave mode
hci_set_master_slave_policy(0);
Profile::initL2cap();
@@ 169,7 167,6 @@ namespace bluetooth
std::memset(AVRCP::sdpControllerServiceBuffer, 0, sizeof(AVRCP::sdpControllerServiceBuffer));
const std::uint16_t controllerSupportedFeatures = AVRCP_FEATURE_MASK_CATEGORY_MONITOR_OR_AMPLIFIER;
-
avrcp_controller_create_sdp_record(AVRCP::sdpControllerServiceBuffer,
avrcpControllerSdpRecordHandle,
controllerSupportedFeatures,
@@ 446,12 443,6 @@ namespace bluetooth
AVRCP::mediaTracker.local_seid,
a2dp_subevent_stream_established_get_remote_seid(packet));
- sourceQueue = xQueueCreate(sourceQueueLength, sizeof(AudioData_t));
- if (sourceQueue == nullptr) {
- LOG_ERROR("Failed to create sourceQueue!");
- break;
- }
-
sendAudioEvent(audio::EventType::BluetoothA2DPDeviceState, audio::Event::DeviceState::Connected);
} break;
@@ 614,7 605,7 @@ namespace bluetooth
A2DP::A2DPImpl::audioDevice = std::move(newAudioDevice);
}
- void A2DP::A2DPImpl::deInit()
+ void A2DP::A2DPImpl::deinit()
{
sdp_unregister_service(a2dpSdpRecordHandle);
sdp_unregister_service(avrcpControllerSdpRecordHandle);
M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DPImpl.hpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DPImpl.hpp +3 -4
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 21,11 21,12 @@ extern "C"
namespace bluetooth
{
class AVRCP;
+
class A2DP::A2DPImpl
{
public:
auto init() -> Result::Code;
- void deInit();
+ void deinit();
void connect();
void disconnect();
void start();
@@ 65,8 66,6 @@ namespace bluetooth
static btstack_packet_callback_registration_t hciEventCallbackRegistration;
- static QueueHandle_t sourceQueue;
-
static bool isConnected;
};
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/Profile.hpp => module-bluetooth/Bluetooth/interface/profiles/Profile.hpp +2 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 79,6 79,6 @@ namespace bluetooth
[[nodiscard]] virtual auto setNetworkRegistrationStatus(bool registered) const noexcept -> Result::Code = 0;
/// Sets the roaming status in HFP profile
/// @return Error code that determines, whether operation was successful or not
- virtual auto setRoamingStatus(bool enabled) const noexcept -> Result::Code = 0;
+ [[nodiscard]] virtual auto setRoamingStatus(bool enabled) const noexcept -> Result::Code = 0;
};
} // namespace bluetooth
M module-bsp/board/rt1051/bluetooth/BlueKitchen.cpp => module-bsp/board/rt1051/bluetooth/BlueKitchen.cpp +5 -5
@@ 31,16 31,16 @@ BlueKitchen &BlueKitchen::getInstance()
return *instance;
}
-BTDevice::Error BlueKitchen::read(uint8_t *buf, size_t nbytes)
+BTDevice::Error BlueKitchen::read(std::uint8_t *buf, std::size_t size)
{
- logHciStack("BlueKitchen requested to read %d bytes", nbytes);
+ logHciStack("BlueKitchen requested to read %d bytes", size);
std::uint8_t val;
readBuffer = buf;
- readLength = nbytes;
+ readLength = size;
- if (BluetoothCommon::read(buf, nbytes) == BTDevice::Error::Success) {
+ if (BluetoothCommon::read(buf, size) == BTDevice::Error::Success) {
val = bluetooth::Message::EvtReceiving;
xQueueSend(qHandle, &val, portMAX_DELAY);
return BTDevice::Error::Success;
@@ 52,7 52,7 @@ BTDevice::Error BlueKitchen::read(uint8_t *buf, size_t nbytes)
}
}
-BTDevice::Error BlueKitchen::write(const uint8_t *buf, size_t size)
+BTDevice::Error BlueKitchen::write(const std::uint8_t *buf, std::size_t size)
{
logHciStack("BlueKitchen sends %d bytes", size);
M module-bsp/bsp/bluetooth/Bluetooth.hpp => module-bsp/bsp/bluetooth/Bluetooth.hpp +2 -2
@@ 119,8 119,8 @@ namespace bsp
virtual ~BlueKitchen();
static BlueKitchen &getInstance();
- virtual Error read(uint8_t *buf, size_t size) override;
- virtual Error write(const uint8_t *buf, size_t size) override;
+ virtual Error read(std::uint8_t *buf, std::size_t size) override;
+ virtual Error write(const std::uint8_t *buf, std::size_t size) override;
std::uint32_t readLength = 0;
std::uint8_t *readBuffer;
M module-services/service-audio/ServiceAudio.cpp => module-services/service-audio/ServiceAudio.cpp +2 -2
@@ 432,7 432,7 @@ std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleStart(const Operation:
auto input = audioMux.GetPlaybackInput(playbackType);
if (playbackType == audio::PlaybackType::CallRingtone && bluetoothVoiceProfileConnected && input) {
- // don't play ringtone on HFP connection on Pure, but do vibrate
+ // Don't play ringtone on HFP connection on Pure, but do vibrate
VibrationUpdate(playbackType, input);
return std::make_unique<AudioStartPlaybackResponse>(audio::RetCode::Success, retToken);
}
@@ 513,7 513,7 @@ std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleStop(const std::vector
// stop by token
if (const auto tokenInput = audioMux.GetInput(token); token.IsValid() && tokenInput) {
- retCodes.emplace_back(std::make_pair(token, StopInput(tokenInput.value())));
+ retCodes.emplace_back(token, StopInput(tokenInput.value()));
}
else if (token.IsValid()) {
return std::make_unique<AudioStopResponse>(RetCode::TokenNotFound, Token::MakeBadToken());
M pure_changelog.md => pure_changelog.md +1 -0
@@ 4,6 4,7 @@
### Fixed
* Fixed crash when deleting all contacts from MC with Phonebook app opened.
+* Fixed sound not being heard in Bluetooth device despite song being played in Music Player.
### Added