M module-audio/Audio/Audio.cpp => module-audio/Audio/Audio.cpp +13 -2
@@ 90,7 90,7 @@ namespace audio
break;
}
currentOperation = std::move(ret);
- UpdateProfiles();
+ UpdateProfiles(playbackType);
}
catch (const AudioInitException &audioException) {
// If creating operation failed fallback to IdleOperation which is guaranteed to work
@@ 159,13 159,24 @@ namespace audio
return SetOutputVolume(0);
}
- void Audio::UpdateProfiles()
+ void Audio::SendUpdateEventsToCurrentOperation()
{
auto updateEvents = audioSinkState.getUpdateEvents();
for (auto &event : updateEvents) {
currentOperation->SendEvent(event);
}
+ }
+
+ void Audio::UpdateProfiles()
+ {
+ SendUpdateEventsToCurrentOperation();
currentOperation->SwitchToPriorityProfile();
}
+ void Audio::UpdateProfiles(audio::PlaybackType playbackType)
+ {
+ SendUpdateEventsToCurrentOperation();
+ currentOperation->SwitchToPriorityProfile(playbackType);
+ }
+
} // namespace audio
M module-audio/Audio/Audio.hpp => module-audio/Audio/Audio.hpp +11 -0
@@ 112,7 112,18 @@ namespace audio
virtual audio::RetCode Mute();
private:
+ void SendUpdateEventsToCurrentOperation();
+ /**
+ * @brief Sends update to the current operation and switches to priority profile.
+ */
void UpdateProfiles();
+ /**
+ * @brief Sends update to the current operation and switches to priority profile.
+ *
+ * @param playbackType if it's callringtone and bluetooth a2dp is used then
+ * ignore priorities and change profile to the earpeaker. Not needed otherwise.
+ */
+ void UpdateProfiles(audio::PlaybackType playbackType);
Muted muted = Muted::False;
AudioSinkState audioSinkState;
M module-audio/Audio/Operation/Operation.cpp => module-audio/Audio/Operation/Operation.cpp +5 -0
@@ 65,6 65,11 @@ namespace audio
return audio::RetCode::ProfileNotSet;
}
+ audio::RetCode Operation::SwitchToPriorityProfile([[maybe_unused]] audio::PlaybackType playbackType)
+ {
+ return SwitchToPriorityProfile();
+ }
+
void Operation::SetProfileAvailability(std::vector<Profile::Type> profiles, bool available)
{
for (auto &p : supportedProfiles) {
M module-audio/Audio/Operation/Operation.hpp => module-audio/Audio/Operation/Operation.hpp +11 -2
@@ 114,8 114,17 @@ namespace audio
{
return filePath;
}
-
- audio::RetCode SwitchToPriorityProfile();
+ /**
+ * @brief Switches operation to priority profile.
+ */
+ virtual audio::RetCode SwitchToPriorityProfile();
+ /**
+ * @brief Switches operation to priority profile.
+ *
+ * @param playbackType if it's callringtone and bluetooth a2dp is used then
+ * ignore priorities and change profile to the earpeaker. Not needed otherwise.
+ */
+ virtual audio::RetCode SwitchToPriorityProfile(audio::PlaybackType playbackType);
protected:
struct SupportedProfile
M module-audio/Audio/Operation/PlaybackOperation.cpp => module-audio/Audio/Operation/PlaybackOperation.cpp +19 -3
@@ 40,7 40,7 @@ namespace audio
auto format = dec->getSourceFormat();
LOG_DEBUG("Source format: %s", format.toString().c_str());
- auto retCode = SwitchToPriorityProfile();
+ auto retCode = SwitchToPriorityProfile(playbackType);
if (retCode != RetCode::Success) {
throw AudioInitException("Failed to switch audio profile", retCode);
}
@@ 133,17 133,32 @@ namespace audio
return dec->getCurrentPosition();
}
+ audio::RetCode PlaybackOperation::SwitchToPriorityProfile(audio::PlaybackType playbackType)
+ {
+ for (const auto &p : supportedProfiles) {
+ const auto profileType = p.profile->GetType();
+ if (profileType == audio::Profile::Type::PlaybackBluetoothA2DP &&
+ playbackType == audio::PlaybackType::CallRingtone) {
+ continue;
+ }
+ if (p.isAvailable) {
+ return SwitchProfile(profileType);
+ }
+ }
+ return audio::RetCode::ProfileNotSet;
+ }
+
audio::RetCode PlaybackOperation::SendEvent(std::shared_ptr<Event> evt)
{
auto isAvailable = evt->getDeviceState() == Event::DeviceState::Connected ? true : false;
switch (evt->getType()) {
case EventType::JackState:
SetProfileAvailability({Profile::Type::PlaybackHeadphones}, isAvailable);
- SwitchToPriorityProfile();
+ Operation::SwitchToPriorityProfile();
break;
case EventType::BlutoothA2DPDeviceState:
SetProfileAvailability({Profile::Type::PlaybackBluetoothA2DP}, isAvailable);
- SwitchToPriorityProfile();
+ Operation::SwitchToPriorityProfile();
break;
default:
return RetCode::UnsupportedEvent;
@@ 156,6 171,7 @@ namespace audio
{
auto newProfile = GetProfile(type);
if (newProfile == nullptr) {
+ LOG_ERROR("Unsupported profile");
return RetCode::UnsupportedProfile;
}
M module-audio/Audio/Operation/PlaybackOperation.hpp => module-audio/Audio/Operation/PlaybackOperation.hpp +1 -0
@@ 40,6 40,7 @@ namespace audio
audio::RetCode SetInputGain(float gain) final;
Position GetPosition() final;
+ audio::RetCode SwitchToPriorityProfile(audio::PlaybackType playbackType) final;
private:
static constexpr auto playbackTimeConstraint = 10ms;
M module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp => module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp +4 -2
@@ 179,6 179,8 @@ namespace bluetooth
if (hsp_subevent_rfcomm_connection_complete_get_status(event) != 0u) {
LOG_DEBUG("RFCOMM connection establishement failed with status %u\n",
hsp_subevent_rfcomm_connection_complete_get_status(event));
+ sendAudioEvent(audio::EventType::BlutoothHSPDeviceState, audio::Event::DeviceState::Disconnected);
+ isConnected = false;
break;
}
LOG_DEBUG("RFCOMM connection established.\n");
@@ 200,6 202,8 @@ namespace bluetooth
if (hsp_subevent_audio_connection_complete_get_status(event) != 0u) {
LOG_DEBUG("Audio connection establishment failed with status %u\n",
hsp_subevent_audio_connection_complete_get_status(event));
+ sendAudioEvent(audio::EventType::BlutoothHSPDeviceState, audio::Event::DeviceState::Disconnected);
+ isConnected = false;
}
else {
scoHandle = hsp_subevent_audio_connection_complete_get_handle(event);
@@ 210,9 214,7 @@ namespace bluetooth
break;
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;
- isConnected = false;
break;
case HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED:
LOG_DEBUG("Received microphone gain change %d\n", hsp_subevent_microphone_gain_changed_get_gain(event));
M module-services/service-audio/ServiceAudio.cpp => module-services/service-audio/ServiceAudio.cpp +9 -16
@@ 341,17 341,14 @@ std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleStart(const Operation:
if (opType == Operation::Type::Playback) {
auto input = audioMux.GetPlaybackInput(playbackType);
- // stop bluetooth stream if available
- if (bluetoothA2DPConnected || bluetoothHSPConnected) {
- if (playbackType == audio::PlaybackType::CallRingtone) {
- HandleSendEvent(std::make_shared<audio::Event>(EventType::BlutoothHSPDeviceState));
-
- LOG_DEBUG("Sending Bluetooth start ringing");
- bus.sendUnicast(std::make_shared<message::bluetooth::Ring>(message::bluetooth::Ring::State::Enable),
- service::name::bluetooth);
- return std::make_unique<AudioStartPlaybackResponse>(audio::RetCode::Success, retToken);
- }
- else {
+ if (playbackType == audio::PlaybackType::CallRingtone && bluetoothHSPConnected) {
+ LOG_DEBUG("Sending Bluetooth start ringing");
+ bus.sendUnicast(std::make_shared<message::bluetooth::Ring>(message::bluetooth::Ring::State::Enable),
+ service::name::bluetooth);
+ return std::make_unique<AudioStartPlaybackResponse>(audio::RetCode::Success, retToken);
+ }
+ else if (bluetoothA2DPConnected) {
+ if (playbackType != audio::PlaybackType::CallRingtone) {
LOG_DEBUG("Sending Bluetooth start stream request");
bus.sendUnicast(std::make_shared<BluetoothMessage>(BluetoothMessage::Request::Play),
service::name::bluetooth);
@@ 368,9 365,6 @@ std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleStart(const Operation:
}
else if (opType == Operation::Type::Router) {
auto input = audioMux.GetRoutingInput(true);
- if (bluetoothA2DPConnected) {
- HandleSendEvent(std::make_shared<audio::Event>(EventType::BlutoothHSPDeviceState));
- }
if (bluetoothHSPConnected) {
LOG_DEBUG("Sending Bluetooth start routing");
bus.sendUnicast(std::make_shared<message::bluetooth::StartAudioRouting>(), service::name::bluetooth);
@@ 396,8 390,7 @@ std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleSendEvent(std::shared_
audio::Token());
}
}
-
- if (evt->getType() == EventType::BlutoothHSPDeviceState) {
+ else if (evt->getType() == EventType::BlutoothHSPDeviceState) {
auto newState = evt->getDeviceState() == Event::DeviceState::Connected;
if (newState != bluetoothHSPConnected) {
LOG_DEBUG("Bluetooth connection status changed: %s", newState ? "connected" : "disconnected");