M image/assets/lang/Deutsch.json => image/assets/lang/Deutsch.json +1 -0
@@ 301,6 301,7 @@
"app_desktop_clear_all": "KPL.-LEER.",
"app_desktop_replay": "ANTWORTEN",
"app_popup_volume_text": "LAUTSTÄRKE",
+ "app_popup_bt_volume_text": "BLUETOOTH-LAUTSTÄRKE",
"app_popup_music_volume_text": "MUSIKLAUTSTÄRKE",
"app_popup_call_volume_text": "ANRUFLAUTSTÄRKE",
"app_popup_muted_text": "STUMM",
M image/assets/lang/English.json => image/assets/lang/English.json +2 -1
@@ 269,6 269,7 @@
"app_desktop_clear_all": "CLEAR ALL",
"app_desktop_replay": "REPLY",
"app_popup_volume_text": "VOLUME",
+ "app_popup_bt_volume_text": "BLUETOOTH VOLUME",
"app_popup_music_volume_text": "MUSIC VOLUME",
"app_popup_call_volume_text": "CALL VOLUME",
"app_popup_muted_text": "MUTED",
@@ 481,7 482,7 @@
"app_settings_option_connected": "CONNECTED",
"app_settings_option_connected_audio": "CONNECTED AUDIO",
"app_settings_option_connected_voice": "CONNECTED VOICE",
- "app_settings_option_connected_both": "CONNECTED VOICE,AUDIO",
+ "app_settings_option_connected_both": "CONNECTED VOICE, AUDIO",
"app_settings_option_connecting": "CONNECTING",
"app_settings_option_pairing": "PAIRING",
"app_settings_title_do_not_disturb": "Do not disturb",
M image/assets/lang/Espanol.json => image/assets/lang/Espanol.json +1 -0
@@ 301,6 301,7 @@
"app_desktop_clear_all": "BORRAR TODO",
"app_desktop_replay": "RESPONDER",
"app_popup_volume_text": "VOLUMEN",
+ "app_popup_bt_volume_text": "VOLUMEN DEL BLUETOOTH",
"app_popup_music_volume_text": "VOLUMEN DE MÚSICA",
"app_popup_call_volume_text": "VOLUMEN DE LLAMADAS",
"app_popup_muted_text": "SILENCIADO",
M image/assets/lang/Francais.json => image/assets/lang/Francais.json +1 -0
@@ 270,6 270,7 @@
"app_desktop_clear_all": "TOUT EFFACER",
"app_desktop_replay": "RÉPONDRE",
"app_popup_volume_text": "VOLUME",
+ "app_popup_bt_volume_text": "VOLUME DE LA BLUETOOTH",
"app_popup_music_volume_text": "VOLUME DE LA MUSIQUE",
"app_popup_call_volume_text": "VOLUME D'APPEL",
"app_popup_muted_text": "SILENCIEUX",
M image/assets/lang/Polski.json => image/assets/lang/Polski.json +1 -0
@@ 311,6 311,7 @@
"app_desktop_clear_all": "WYCZYŚĆ",
"app_desktop_replay": "ODPOWIEDZ",
"app_popup_volume_text": "GŁOŚNOŚĆ",
+ "app_popup_bt_volume_text": "GŁOŚNOŚĆ BLUETOOTH",
"app_popup_music_volume_text": "GŁOŚNOŚĆ MUZYKI",
"app_popup_call_volume_text": "GŁOŚNOŚĆ POŁĄCZEŃ",
"app_popup_muted_text": "WYCISZONE",
M => +5 -4
@@ 49,14 49,15 @@ namespace app
std::to_string(volumeParams->getVolume()).c_str());
auto volume = volumeParams->getVolume();
auto context = volumeParams->getAudioContext();
auto source = volumeParams->getRequestSource();
auto popupData = std::make_unique<gui::VolumePopupData>(volume, context, source);
const auto popupName = resolveWindowName(gui::popup::ID::Volume);
if (const auto currentWindowName = getCurrentWindow()->getName(); currentWindowName == popupName) {
updateCurrentWindow(std::make_unique<gui::VolumePopupData>(volume, context));
updateCurrentWindow(std::move(popupData));
}
else {
switchWindowPopup(popupName,
volumeParams->getDisposition(),
std::make_unique<gui::VolumePopupData>(volume, context));
switchWindowPopup(popupName, volumeParams->getDisposition(), std::move(popupData));
}
return true;
});
M => +36 -8
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <module-gui/gui/input/InputEvent.hpp>
@@ 55,21 55,40 @@ namespace gui
{
WindowWithTimer::onBeforeShow(mode, data);
const auto popupData = dynamic_cast<VolumePopupData *>(data);
if (popupData) {
if (popupData != nullptr) {
volume = popupData->getVolume();
audioContext = popupData->getAudioContext();
source = popupData->getVolumeChangeRequestSource();
if (volumeBar != nullptr) {
volumeBar->setValue(volume);
}
if (volumeText != nullptr) {
showProperText(audioContext, volume);
showProperText(audioContext, volume, source);
}
}
}
void VolumeWindow::showProperText(const audio::Context &audioContext, const audio::Volume volume) noexcept
void VolumeWindow::showProperText(const audio::Context &audioContext,
const audio::Volume volume,
const audio::VolumeChangeRequestSource source) noexcept
{
volumeText->setText(utils::translate(style::window::volume::base_title_key));
if (volume == 0) {
showMuted();
return;
}
switch (source) {
case audio::VolumeChangeRequestSource::A2DP:
showBTAudioDeviceVolume();
return;
case audio::VolumeChangeRequestSource::HFP:
case audio::VolumeChangeRequestSource::HSP:
showCalling();
return;
default:
break;
}
const auto [profileType, playbackType] = audioContext;
if (playbackType == audio::PlaybackType::Multimedia) {
showMultimediaPlayback();
@@ 81,12 100,21 @@ namespace gui
profileType == audio::Profile::Type::RoutingLoudspeaker) {
showCalling();
}
if (volume == 0) {
showMuted();
else {
showBaseTitle();
}
}
void VolumeWindow::showBaseTitle() noexcept
{
volumeText->setText(utils::translate(style::window::volume::base_title_key));
}
void VolumeWindow::showBTAudioDeviceVolume() noexcept
{
volumeText->setText(utils::translate(style::window::volume::bt_audio_title_key));
}
void VolumeWindow::showMultimediaPlayback() noexcept
{
volumeText->setText(utils::translate(style::window::volume::music_title_key));
M => +8 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 15,6 15,7 @@ namespace style::window::volume
{
constexpr inline auto title_height = 33;
constexpr inline auto base_title_key = "app_popup_volume_text";
constexpr inline auto bt_audio_title_key = "app_popup_bt_volume_text";
constexpr inline auto music_title_key = "app_popup_music_volume_text";
constexpr inline auto call_title_key = "app_popup_call_volume_text";
constexpr inline auto mute_title_key = "app_popup_muted_text";
@@ 39,8 40,13 @@ namespace gui
private:
audio::Volume volume = 0;
audio::Context audioContext;
audio::VolumeChangeRequestSource source;
void showProperText(const audio::Context &audioContext, const audio::Volume volume) noexcept;
void showProperText(const audio::Context &audioContext,
audio::Volume volume,
audio::VolumeChangeRequestSource source) noexcept;
void showBaseTitle() noexcept;
void showBTAudioDeviceVolume() noexcept;
void showMultimediaPlayback() noexcept;
void showCalling() noexcept;
void showMuted() noexcept;
M => +10 -2
@@ 11,8 11,10 @@ namespace gui
class VolumePopupData : public SwitchData
{
public:
explicit VolumePopupData(const audio::Volume volume, const audio::Context audioContext)
: SwitchData(), volume{volume}, audioContext{audioContext}
explicit VolumePopupData(const audio::Volume volume,
const audio::Context audioContext,
audio::VolumeChangeRequestSource source)
: SwitchData(), volume{volume}, audioContext{audioContext}, source{source}
{}
[[nodiscard]] auto getVolume() const noexcept -> audio::Volume
@@ 25,9 27,15 @@ namespace gui
return audioContext;
}
[[nodiscard]] auto getVolumeChangeRequestSource() const noexcept -> audio::VolumeChangeRequestSource
{
return source;
}
private:
const audio::Volume volume;
const audio::Context audioContext;
const audio::VolumeChangeRequestSource source;
};
class ModesPopupData : public SwitchData
M => +10 -2
@@ 146,8 146,10 @@ namespace gui
class VolumePopupRequestParams : public PopupRequestParams
{
public:
VolumePopupRequestParams(audio::Volume volume, const audio::Context audioContext)
: PopupRequestParams{gui::popup::ID::Volume}, volume{volume}, audioContext{audioContext}
VolumePopupRequestParams(audio::Volume volume,
const audio::Context audioContext,
audio::VolumeChangeRequestSource source)
: PopupRequestParams{gui::popup::ID::Volume}, volume{volume}, audioContext{audioContext}, source{source}
{}
[[nodiscard]] auto getVolume() const noexcept
@@ 160,9 162,15 @@ namespace gui
return audioContext;
}
[[nodiscard]] auto getRequestSource() const noexcept
{
return source;
}
private:
const audio::Volume volume;
const audio::Context audioContext;
const audio::VolumeChangeRequestSource source;
};
} // namespace gui
M module-audio/Audio/AudioCommon.hpp => module-audio/Audio/AudioCommon.hpp +8 -0
@@ 72,6 72,14 @@ namespace audio
Last = Bedtime,
};
+ enum class VolumeChangeRequestSource
+ {
+ A2DP,
+ HFP,
+ HSP,
+ Other
+ };
+
/// Used to describe audio operations
using Context = std::pair<Profile::Type, PlaybackType>;
M module-audio/Audio/VolumeScaler.cpp => module-audio/Audio/VolumeScaler.cpp +1 -6
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "VolumeScaler.hpp"
@@ 38,11 38,6 @@ namespace audio::volume::scaler
{
return btProfileToSystemVolume(avrcpVolume, static_cast<float>(avrcpMaxVolume));
}
-
- std::uint8_t toAvrcpVolume(float systemVolume) noexcept
- {
- return systemToBtProfileVolume(systemVolume, avrcpMaxVolume);
- }
} // namespace a2dp
namespace hsp
{
M module-audio/Audio/VolumeScaler.hpp => module-audio/Audio/VolumeScaler.hpp +1 -6
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 13,11 13,6 @@ namespace audio::volume::scaler
/// @param avrcpVolume - AVRCP volume level.
/// @return Volume level scaled to satisfy system's range [audio::minVolume, audio::maxVolume].
Volume toSystemVolume(std::uint8_t avrcpVolume) noexcept;
- /// @brief Takes volume level and converts it to according one for the AVRCP.
- /// @param systemVolume - system volume level.
- /// @return Volume level scaled to satisfy AVRCP's range [0, 127].
- std::uint8_t toAvrcpVolume(float systemVolume) noexcept;
-
} // namespace a2dp
namespace hsp
{
M module-audio/Audio/test/unittest_scaler.cpp => module-audio/Audio/test/unittest_scaler.cpp +0 -12
@@ 64,10 64,6 @@ SCENARIO("Scale volume levels between system and bluetooth")
{
WHEN("Volume is set to 10")
{
- THEN("AVRCP volume is 127")
- {
- REQUIRE(audio::volume::scaler::a2dp::toAvrcpVolume(10) == std::uint8_t{127});
- }
THEN("HSP speaker gain is 15")
{
REQUIRE(audio::volume::scaler::hsp::toHSPGain(10) == std::uint8_t{15});
@@ 75,10 71,6 @@ SCENARIO("Scale volume levels between system and bluetooth")
}
WHEN("System volume is set to 7")
{
- THEN("AVRCP volume is 89")
- {
- REQUIRE(audio::volume::scaler::a2dp::toAvrcpVolume(7) == std::uint8_t{89});
- }
THEN("HSP speaker gain is 7")
{
REQUIRE(audio::volume::scaler::hsp::toHSPGain(7) == std::uint8_t{11});
@@ 86,10 78,6 @@ SCENARIO("Scale volume levels between system and bluetooth")
}
WHEN("System volume is set to 1")
{
- THEN("AVRCP volume is 13")
- {
- REQUIRE(audio::volume::scaler::a2dp::toAvrcpVolume(1) == std::uint8_t{13});
- }
THEN("HSP speaker gain is 2")
{
REQUIRE(audio::volume::scaler::hsp::toHSPGain(1) == std::uint8_t{2});
M module-audio/board/rt1051/puretx/PureTxAudioDeviceFactory.cpp => module-audio/board/rt1051/puretx/PureTxAudioDeviceFactory.cpp +6 -4
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "PureTxAudioDeviceFactory.hpp"
@@ 16,21 16,23 @@ using audio::RT1051CellularAudio;
std::shared_ptr<AudioDevice> PureTxAudioDeviceFactory::getDevice(const audio::Profile &profile)
{
std::shared_ptr<AudioDevice> device;
+ const auto initialVolume = profile.GetOutputVolume();
+
switch (profile.GetAudioDeviceType()) {
case AudioDevice::Type::Audiocodec: {
device = std::make_shared<PureTxAudioCodec>(profile.GetAudioConfiguration());
} break;
case AudioDevice::Type::BluetoothA2DP: {
- device = std::make_shared<bluetooth::A2DPAudioDevice>();
+ device = std::make_shared<bluetooth::A2DPAudioDevice>(initialVolume);
} break;
case AudioDevice::Type::BluetoothHSP: {
- device = std::make_shared<bluetooth::CVSDAudioDevice>(bluetooth::AudioProfile::HSP);
+ device = std::make_shared<bluetooth::CVSDAudioDevice>(initialVolume, bluetooth::AudioProfile::HSP);
} break;
case AudioDevice::Type::BluetoothHFP: {
- device = std::make_shared<bluetooth::CVSDAudioDevice>(bluetooth::AudioProfile::HFP);
+ device = std::make_shared<bluetooth::CVSDAudioDevice>(initialVolume, bluetooth::AudioProfile::HFP);
} break;
case AudioDevice::Type::Cellular: {
M module-bluetooth/Bluetooth/audio/BluetoothAudioDevice.cpp => module-bluetooth/Bluetooth/audio/BluetoothAudioDevice.cpp +16 -9
@@ 23,7 23,9 @@ using bluetooth::CVSDAudioDevice;
using namespace std::chrono_literals;
BluetoothAudioDevice::BluetoothAudioDevice(AudioProfile audioProfile) : profile(audioProfile)
-{}
+{
+ LOG_DEBUG("Creating bluetooth device with %s profile", magic_enum::enum_name(audioProfile).data());
+}
BluetoothAudioDevice::~BluetoothAudioDevice()
{
@@ 52,13 54,6 @@ auto BluetoothAudioDevice::isOutputEnabled() const -> bool
auto A2DPAudioDevice::setOutputVolume(float vol) -> audio::AudioDevice::RetCode
{
- const auto volumeToSet = audio::volume::scaler::a2dp::toAvrcpVolume(vol);
- const auto status = avrcp_controller_set_absolute_volume(AVRCP::mediaTracker.avrcp_cid, volumeToSet);
- if (status != ERROR_CODE_SUCCESS) {
- LOG_ERROR("Can't set volume level. Status %x", status);
- return audio::AudioDevice::RetCode::Failure;
- }
-
outputVolume = vol;
return audio::AudioDevice::RetCode::Success;
}
@@ 234,7 229,19 @@ auto BluetoothAudioDevice::fillSbcAudioBuffer() -> int
audio::Stream::Span dataSpan;
Sink::_stream->peek(dataSpan);
- btstack_sbc_encoder_process_data(reinterpret_cast<int16_t *>(dataSpan.data));
+
+ constexpr size_t bytesPerSample =
+ sizeof(std::int16_t) / sizeof(std::uint8_t); // Samples are signed 16-bit, but stored in uint8_t array
+ const float outputVolumeNormalized =
+ outputVolume / static_cast<float>(audio::maxVolume); // Volume in <0;1> range
+
+ std::int16_t *firstSample = reinterpret_cast<std::int16_t *>(dataSpan.data);
+ std::int16_t *lastSample = firstSample + dataSpan.dataSize / bytesPerSample;
+
+ /* Scale each sample to reduce volume */
+ std::for_each(firstSample, lastSample, [&](std::int16_t &sample) { sample *= outputVolumeNormalized; });
+
+ btstack_sbc_encoder_process_data(firstSample);
Sink::_stream->consume();
uint16_t sbcFrameSize = btstack_sbc_encoder_sbc_buffer_length();
M module-bluetooth/Bluetooth/audio/BluetoothAudioDevice.hpp => module-bluetooth/Bluetooth/audio/BluetoothAudioDevice.hpp +7 -4
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 48,8 48,10 @@ namespace bluetooth
class A2DPAudioDevice : public BluetoothAudioDevice
{
public:
- explicit A2DPAudioDevice() : BluetoothAudioDevice(AudioProfile::A2DP)
- {}
+ explicit A2DPAudioDevice(const float volume) : BluetoothAudioDevice(AudioProfile::A2DP)
+ {
+ outputVolume = volume;
+ }
auto setOutputVolume(float vol) -> audio::AudioDevice::RetCode override;
void onDataSend() override;
@@ 65,8 67,9 @@ namespace bluetooth
class CVSDAudioDevice : public BluetoothAudioDevice
{
public:
- explicit CVSDAudioDevice(const AudioProfile &profile) : BluetoothAudioDevice(profile)
+ explicit CVSDAudioDevice(const float volume, const AudioProfile &profile) : BluetoothAudioDevice(profile)
{
+ outputVolume = volume;
btstack_cvsd_plc_init(&cvsdPlcState);
}
M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp +19 -15
@@ 12,7 12,6 @@
#include <Bluetooth/Device.hpp>
#include <Bluetooth/Error.hpp>
#include <log/log.hpp>
-#include <service-bluetooth/BluetoothMessage.hpp>
#include <Audio/AudioCommon.hpp>
#include <service-audio/AudioMessage.hpp>
#include <service-evtmgr/Constants.hpp>
@@ 108,8 107,8 @@ namespace bluetooth
QueueHandle_t A2DP::A2DPImpl::sinkQueue = nullptr;
DeviceMetadata_t A2DP::A2DPImpl::metadata;
btstack_packet_callback_registration_t A2DP::A2DPImpl::hciEventCallbackRegistration;
- std::array<uint8_t, 150> A2DP::A2DPImpl::sdpSourceServiceBuffer;
- std::array<uint8_t, 4> A2DP::A2DPImpl::mediaSbcCodecCapabilities = {
+ std::array<std::uint8_t, A2DP::A2DPImpl::SDP_BUFFER_LENGTH> A2DP::A2DPImpl::sdpSourceServiceBuffer;
+ std::array<std::uint8_t, A2DP::A2DPImpl::MEDIA_CAP_SIZE> A2DP::A2DPImpl::mediaSbcCodecCapabilities = {
(AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO,
0xFF, //(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS,
2,
@@ 160,7 159,7 @@ namespace bluetooth
// Create AVRCP target service record and register it with SDP.
AVRCP::sdpTargetServiceBuffer.fill(0);
- uint16_t supportedFeatures = AVRCP_FEATURE_MASK_CATEGORY_PLAYER_OR_RECORDER;
+ std::uint16_t supportedFeatures = AVRCP_FEATURE_MASK_CATEGORY_PLAYER_OR_RECORDER;
#ifdef AVRCP_BROWSING_ENABLED
supported_features |= AVRCP_FEATURE_MASK_BROWSING;
#endif
@@ 173,7 172,7 @@ namespace bluetooth
// setup AVRCP Controller
AVRCP::sdpControllerServiceBuffer.fill(0);
- uint16_t controllerSupportedFeatures = AVRCP_FEATURE_MASK_CATEGORY_PLAYER_OR_RECORDER;
+ uint16_t controllerSupportedFeatures = AVRCP_FEATURE_MASK_CATEGORY_MONITOR_OR_AMPLIFIER;
avrcp_controller_create_sdp_record(AVRCP::sdpControllerServiceBuffer.data(),
avrcpControllerSdpRecordHandle,
controllerSupportedFeatures,
@@ 197,7 196,7 @@ namespace bluetooth
{
int numBytesInFrame = btstack_sbc_encoder_sbc_buffer_length();
int bytesInStorage = AVRCP::mediaTracker.sbc_storage_count;
- uint8_t numFrames = bytesInStorage / numBytesInFrame;
+ std::uint8_t numFrames = bytesInStorage / numBytesInFrame;
a2dp_source_stream_send_media_payload(AVRCP::mediaTracker.a2dp_cid,
AVRCP::mediaTracker.local_seid,
AVRCP::mediaTracker.sbc_storage,
@@ 213,14 212,14 @@ namespace bluetooth
auto *context = static_cast<MediaContext *>(btstack_run_loop_get_timer_context(timer));
btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS);
btstack_run_loop_add_timer(&context->audio_timer);
- uint32_t now = btstack_run_loop_get_time_ms();
+ std::uint32_t now = btstack_run_loop_get_time_ms();
- uint32_t updatePeriodMs = AUDIO_TIMEOUT_MS;
+ std::uint32_t updatePeriodMs = AUDIO_TIMEOUT_MS;
if (context->time_audio_data_sent_in_ms > 0) {
updatePeriodMs = now - context->time_audio_data_sent_in_ms;
}
- uint32_t numSamples = (updatePeriodMs * AVDTP::sampleRate) / 1000;
+ std::uint32_t numSamples = (updatePeriodMs * AVDTP::sampleRate) / 1000;
context->acc_num_missed_samples += (updatePeriodMs * AVDTP::sampleRate) % 1000;
while (context->acc_num_missed_samples >= 1000) {
@@ 274,19 273,25 @@ namespace bluetooth
btstack_run_loop_remove_timer(&context->audio_timer);
}
- void A2DP::A2DPImpl::hciPacketHandler(uint8_t packetType, uint16_t channel, uint8_t *packet, uint16_t size)
+ void A2DP::A2DPImpl::hciPacketHandler(uint8_t packetType,
+ [[maybe_unused]] uint16_t channel,
+ [[maybe_unused]] uint8_t *packet,
+ [[maybe_unused]] uint16_t size)
{
if (packetType != HCI_EVENT_PACKET) {
return;
}
}
- void A2DP::A2DPImpl::sourcePacketHandler(uint8_t packetType, uint16_t channel, uint8_t *packet, uint16_t size)
+ void A2DP::A2DPImpl::sourcePacketHandler(uint8_t packetType,
+ [[maybe_unused]] uint16_t channel,
+ uint8_t *packet,
+ [[maybe_unused]] uint16_t size)
{
- uint8_t status;
- uint8_t local_seid;
+ std::uint8_t status;
+ std::uint8_t local_seid;
bd_addr_t address;
- uint16_t cid;
+ std::uint16_t cid;
if (packetType != HCI_EVENT_PACKET) {
return;
@@ 446,7 451,6 @@ namespace bluetooth
a2dp_subevent_stream_established_get_remote_seid(packet));
sourceQueue = xQueueCreate(5, sizeof(AudioData_t));
- sinkQueue = nullptr;
if (sourceQueue != nullptr) {
sendAudioEvent(audio::EventType::BlutoothA2DPDeviceState, audio::Event::DeviceState::Connected);
}
M module-bluetooth/Bluetooth/interface/profiles/A2DP/AVRCP.cpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/AVRCP.cpp +6 -17
@@ 46,11 46,12 @@ namespace bluetooth
avrcp_target_support_event(AVRCP::mediaTracker.avrcp_cid, AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED);
avrcp_target_support_event(AVRCP::mediaTracker.avrcp_cid,
AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED);
+
avrcp_controller_enable_notification(AVRCP::mediaTracker.avrcp_cid,
AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED);
avrcp_target_set_now_playing_info(
- AVRCP::mediaTracker.avrcp_cid, NULL, sizeof(AVRCP::tracks) / sizeof(avrcp_track_t));
+ AVRCP::mediaTracker.avrcp_cid, nullptr, sizeof(AVRCP::tracks) / sizeof(avrcp_track_t));
avrcp_target_set_unit_info(AVRCP::mediaTracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, AVRCP::companyId);
avrcp_target_set_subunit_info(AVRCP::mediaTracker.avrcp_cid,
AVRCP_SUBUNIT_TYPE_AUDIO,
@@ 85,12 86,6 @@ namespace bluetooth
const auto subevent_code = hci_event_avrcp_meta_get_subevent_code(packet);
switch (subevent_code) {
- case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED:
- AVRCP::mediaTracker.volume = avrcp_subevent_notification_volume_changed_get_absolute_volume(packet);
- LOG_INFO("AVRCP Target: Volume set to %u%% (%u)\n",
- AVRCP::targetVolumeToPercent(AVRCP::mediaTracker.volume),
- AVRCP::mediaTracker.volume);
- break;
case AVRCP_SUBEVENT_PLAY_STATUS_QUERY:
status = avrcp_target_play_status(AVRCP::mediaTracker.avrcp_cid,
AVRCP::playInfo.song_length_ms,
@@ 146,20 141,14 @@ namespace bluetooth
return;
}
- const std::uint8_t status = packet[5];
-
- // ignore INTERIM status
- if (status == AVRCP_CTYPE_RESPONSE_INTERIM) {
- return;
- }
-
const auto subevent_code = hci_event_avrcp_meta_get_subevent_code(packet);
switch (subevent_code) {
+ /* BT device requested volume change */
case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED: {
const auto volume = avrcp_subevent_notification_volume_changed_get_absolute_volume(packet);
auto &busProxy = AVRCP::ownerService->bus;
busProxy.sendUnicast(std::make_shared<message::bluetooth::A2DPVolume>(volume), service::name::bluetooth);
- LOG_INFO("AVRCP Controller: notification absolute volume changed %u%% (%u)\n",
+ LOG_INFO("AVRCP Controller: BT device volume changed to %u%% (%u)\n",
AVRCP::controllerVolumeToPercent(volume),
volume);
} break;
@@ 194,12 183,12 @@ namespace bluetooth
std::uint16_t AVRCP::targetVolumeToPercent(std::uint16_t volume)
{
- return volume * 127 / 100;
+ return volume * AVRCP::maxVolumeValue / 100;
}
std::uint16_t AVRCP::controllerVolumeToPercent(std::uint16_t volume)
{
- return volume * 100 / 127;
+ return volume * 100 / AVRCP::maxVolumeValue;
}
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/A2DP/AVRCP.hpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/AVRCP.hpp +1 -0
@@ 20,6 20,7 @@ namespace bluetooth
class AVRCP
{
private:
+ static constexpr std::uint16_t maxVolumeValue = 0x7F; // From Bluetooth AVRCP 1.6.2 spec, p. 83
static std::uint16_t targetVolumeToPercent(std::uint16_t volume);
static std::uint16_t controllerVolumeToPercent(std::uint16_t volume);
M module-services/service-audio/ServiceAudio.cpp => module-services/service-audio/ServiceAudio.cpp +12 -10
@@ 5,13 5,11 @@
#include <ServiceAudio.hpp>
#include <Audio/Operation/IdleOperation.hpp>
-#include <Audio/Operation/PlaybackOperation.hpp>
#include <Bluetooth/audio/BluetoothAudioDevice.hpp>
#include <module-audio/Audio/VolumeScaler.hpp>
#include <system/messages/SentinelRegistrationMessage.hpp>
#include <service-bluetooth/BluetoothMessage.hpp>
#include <service-bluetooth/Constants.hpp>
-#include <service-bluetooth/messages/AudioRouting.hpp>
#include <service-bluetooth/messages/AudioNotify.hpp>
#include <service-db/Settings.hpp>
#include <service-evtmgr/EventManagerServiceAPI.hpp>
@@ 20,7 18,6 @@
#include <algorithm>
#include <initializer_list>
#include <iterator>
-#include <type_traits>
#include <utility>
using namespace audio;
@@ 602,7 599,8 @@ auto ServiceAudio::HandleKeyPressed(const int step) -> sys::MessagePointer
// update volume of currently active sound
setSetting(Setting::Volume, std::to_string(newVolume));
}
- bus.sendMulticast(std::make_shared<VolumeChanged>(newVolume, context), sys::BusChannel::ServiceAudioNotifications);
+ bus.sendMulticast(std::make_shared<VolumeChanged>(newVolume, context, VolumeChangeRequestSource::Other),
+ sys::BusChannel::ServiceAudioNotifications);
return sys::msgHandled();
}
@@ 833,21 831,25 @@ void ServiceAudio::settingsChanged(const std::string &name, std::string value)
LOG_ERROR("ServiceAudio::settingsChanged received notification about not registered setting: %s", name.c_str());
}
-void ServiceAudio::onVolumeChanged(Volume volume)
+void ServiceAudio::onVolumeChanged(const Volume volume, const VolumeChangeRequestSource source)
{
const auto [profileType, playbackType] = getCurrentContext();
settingsProvider->setValue(dbPath(Setting::Volume, playbackType, profileType), std::to_string(volume));
settingsCache[dbPath(Setting::Volume, playbackType, profileType)] = std::to_string(volume);
- bus.sendMulticast(std::make_shared<VolumeChanged>(volume, std::make_pair(profileType, playbackType)),
+ bus.sendMulticast(std::make_shared<VolumeChanged>(volume, std::make_pair(profileType, playbackType), source),
sys::BusChannel::ServiceAudioNotifications);
}
auto ServiceAudio::handleA2DPVolumeChangedOnBluetoothDevice(sys::Message *msgl) -> sys::MessagePointer
{
- auto *a2dpMsg = dynamic_cast<A2DPDeviceVolumeChanged *>(msgl);
+ const auto a2dpMsg = dynamic_cast<A2DPDeviceVolumeChanged *>(msgl);
assert(a2dpMsg != nullptr);
+
+ const auto context = getCurrentContext();
const auto volume = volume::scaler::a2dp::toSystemVolume(a2dpMsg->getVolume());
- onVolumeChanged(volume);
+ bus.sendMulticast(std::make_shared<VolumeChanged>(volume, context, VolumeChangeRequestSource::A2DP),
+ sys::BusChannel::ServiceAudioNotifications);
+
return sys::msgHandled();
}
@@ 856,7 858,7 @@ auto ServiceAudio::handleHSPVolumeChangedOnBluetoothDevice(sys::Message *msgl) -
auto *hspMsg = dynamic_cast<HSPDeviceVolumeChanged *>(msgl);
assert(hspMsg != nullptr);
const auto volume = volume::scaler::hsp::toSystemVolume(hspMsg->getVolume());
- onVolumeChanged(volume);
+ onVolumeChanged(volume, VolumeChangeRequestSource::HSP);
return sys::msgHandled();
}
@@ 865,7 867,7 @@ auto ServiceAudio::handleHFPVolumeChangedOnBluetoothDevice(sys::Message *msgl) -
auto *hfpMsg = dynamic_cast<HFPDeviceVolumeChanged *>(msgl);
assert(hfpMsg != nullptr);
const auto volume = volume::scaler::hfp::toSystemVolume(hfpMsg->getVolume());
- onVolumeChanged(volume);
+ onVolumeChanged(volume, VolumeChangeRequestSource::HFP);
return sys::msgHandled();
}
auto ServiceAudio::handleA2DPAudioPause() -> sys::MessagePointer
M module-services/service-audio/include/service-audio/AudioMessage.hpp => module-services/service-audio/include/service-audio/AudioMessage.hpp +7 -4
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 260,19 260,22 @@ class AudioKeyPressedRequest : public AudioMessage
class VolumeChanged : public sys::DataMessage, public app::manager::actions::ConvertibleToAction
{
public:
- VolumeChanged(audio::Volume volume, audio::Context context)
- : sys::DataMessage{MessageType::MessageTypeUninitialized}, volume{volume}, context{context}
+ VolumeChanged(audio::Volume volume, audio::Context context, audio::VolumeChangeRequestSource source)
+ : sys::DataMessage{MessageType::MessageTypeUninitialized}, volume{volume}, context{context}, source{source}
{}
[[nodiscard]] auto toAction() const -> std::unique_ptr<app::manager::ActionRequest> override
{
return std::make_unique<app::manager::ActionRequest>(
- sender, app::manager::actions::ShowPopup, std::make_unique<gui::VolumePopupRequestParams>(volume, context));
+ sender,
+ app::manager::actions::ShowPopup,
+ std::make_unique<gui::VolumePopupRequestParams>(volume, context, source));
}
private:
const audio::Volume volume;
audio::Context context;
+ audio::VolumeChangeRequestSource source;
};
class BluetoothDeviceVolumeChanged : public AudioMessage
M module-services/service-audio/include/service-audio/ServiceAudio.hpp => module-services/service-audio/include/service-audio/ServiceAudio.hpp +2 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 123,7 123,7 @@ class ServiceAudio : public sys::Service
const audio::Context getCurrentContext();
void settingsChanged(const std::string &name, std::string value);
- void onVolumeChanged(audio::Volume volume);
+ void onVolumeChanged(audio::Volume volume, audio::VolumeChangeRequestSource source);
auto handleA2DPVolumeChangedOnBluetoothDevice(sys::Message *msgl) -> sys::MessagePointer;
auto handleHSPVolumeChangedOnBluetoothDevice(sys::Message *msgl) -> sys::MessagePointer;
auto handleHFPVolumeChangedOnBluetoothDevice(sys::Message *msgl) -> sys::MessagePointer;
M module-services/service-bluetooth/ServiceBluetooth.cpp => module-services/service-bluetooth/ServiceBluetooth.cpp +0 -10
@@ 86,7 86,6 @@ sys::ReturnCodes ServiceBluetooth::InitHandler()
LOG_INFO("Turning off Bluetooth due to inactivity timeout");
handleTurnOff();
});
- startTimeoutTimer();
connectHandler<BluetoothAddrMessage>();
connectHandler<BluetoothAudioStartMessage>();
@@ 403,7 402,6 @@ auto ServiceBluetooth::handle(message::bluetooth::ResponseAuthenticatePairCancel
auto ServiceBluetooth::handle(BluetoothMessage *msg) -> std::shared_ptr<sys::Message>
{
LOG_INFO("Bluetooth request!");
- resetTimeoutTimer();
switch (msg->req) {
case BluetoothMessage::Scan:
@@ 525,14 523,6 @@ void ServiceBluetooth::stopTimeoutTimer()
}
}
-void ServiceBluetooth::resetTimeoutTimer()
-{
- if (connectionTimeoutTimer.isValid() && connectionTimeoutTimer.isActive()) {
- connectionTimeoutTimer.stop();
- connectionTimeoutTimer.start();
- }
-}
-
void ServiceBluetooth::handleTurnOff()
{
sendWorkerCommand(std::make_unique<bluetooth::event::PowerOff>());
M module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp => module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp +0 -1
@@ 108,7 108,6 @@ class ServiceBluetooth : public sys::Service
void startTimeoutTimer();
void stopTimeoutTimer();
- void resetTimeoutTimer();
template <typename T> auto connectHandler() -> bool
{
M pure_changelog.md => pure_changelog.md +2 -0
@@ 4,9 4,11 @@
### Changed / Improved
* Changed USB logging
+* Separated system volume from Bluetooth device volume for A2DP
### Fixed
* Fixed improper duration of the rejected outgoing call shown in calls log
+* Fixed Bluetooth volume control issues
* Fixed turning on loudspeaker before outgoing call is answered
* Fixed PLAY label translation in German
* Fixed USB connection/disconnection detection