M module-apps/application-call/ApplicationCall.cpp => module-apps/application-call/ApplicationCall.cpp +11 -8
@@ 6,6 6,7 @@
#include "CallWindow.hpp"
#include "EmergencyCallWindow.hpp"
#include "EnterNumberWindow.hpp"
+#include "presenter/CallPresenter.hpp"
#include <apps-common/messages/DialogMetadataMessage.hpp>
#include <apps-common/windows/Dialog.hpp>
@@ 19,6 20,7 @@
#include <service-cellular/CellularServiceAPI.hpp>
#include <time/time_conversion.hpp>
#include <WindowsPopupFilter.hpp>
+#include <service-audio/AudioServiceAPI.hpp>
#include <cassert>
#include <memory>
@@ 114,7 116,8 @@ namespace app
return actionHandled();
});
- callModel = std::make_shared<app::call::CallModel>(this);
+ callModel = std::make_shared<app::call::CallModel>(this);
+ callPresenter = std::make_unique<call::CallWindowContract::Presenter>(this->callModel);
}
bool ApplicationCall::conditionalReturnToPreviousView()
@@ 181,9 184,9 @@ namespace app
return sys::MessageNone{};
});
- connect(typeid(AudioEventRequest), [&](sys::Message *request) {
- auto message = static_cast<AudioEventRequest *>(request);
- return handleAudioMessageEvent(message);
+ connect(typeid(AudioRoutingNotification), [this](sys::Message *request) {
+ auto message = static_cast<AudioRoutingNotification *>(request);
+ return handleRoutingNotification(message);
});
createUserInterface();
@@ 197,8 200,7 @@ namespace app
return std::make_unique<gui::EnterNumberWindow>(app, static_cast<ApplicationCall *>(app));
});
windowsFactory.attach(app::window::name_call, [this](ApplicationCommon *app, const std::string &name) {
- return std::make_unique<gui::CallWindow>(
- app, std::make_unique<app::call::CallWindowContract::Presenter>(this->callModel));
+ return std::make_unique<gui::CallWindow>(app, *callPresenter);
});
windowsFactory.attach(app::window::name_emergencyCall, [](ApplicationCommon *app, const std::string &name) {
return std::make_unique<gui::EmergencyCallWindow>(app, static_cast<ApplicationCall *>(app));
@@ 281,10 283,11 @@ namespace app
}
}
- sys::MessagePointer ApplicationCall::handleAudioMessageEvent(AudioEventRequest *message)
+ sys::MessagePointer ApplicationCall::handleRoutingNotification(AudioRoutingNotification *message)
{
if (auto window = getCurrentWindow(); window->getName() == app::window::name_call) {
- static_cast<gui::CallWindow *>(window)->handleAudioEvent(*message->getEvent().get());
+ const auto currentRouting = message->profileType;
+ callPresenter->processCurrentRouting(currentRouting);
}
return sys::MessageNone{};
}
M module-apps/application-call/include/application-call/ApplicationCall.hpp => module-apps/application-call/include/application-call/ApplicationCall.hpp +4 -3
@@ 4,7 4,7 @@
#pragma once
#include <application-call/model/CallModel.hpp>
-
+#include <application-call/presenter/CallPresenter.hpp>
#include <Timers/TimerHandle.hpp>
#include <service-cellular/CellularMessage.hpp>
#include <service-evtmgr/Constants.hpp>
@@ 67,7 67,7 @@ namespace app
void handleCallEvent(const std::string &number, ExternalRequest isExternalRequest) override;
void handleAddContactEvent(const std::string &number) override;
- sys::MessagePointer handleAudioMessageEvent(AudioEventRequest *message);
+ sys::MessagePointer handleRoutingNotification(AudioRoutingNotification *message);
auto showNotification(std::function<bool()> action, const std::string &icon, const std::string &text) -> bool;
enum class NotificationType
@@ 78,7 78,8 @@ namespace app
auto showNotificationAndRestartCallFlow(NotificationType type, const std::string &text) -> bool;
private:
- std::shared_ptr<app::call::AbstractCallModel> callModel;
+ std::shared_ptr<call::AbstractCallModel> callModel;
+ std::unique_ptr<call::CallWindowContract::Presenter> callPresenter;
protected:
ExternalRequest externalRequest = ExternalRequest::False;
M module-apps/application-call/model/CallModel.cpp => module-apps/application-call/model/CallModel.cpp +1 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "CallModel.hpp"
M module-apps/application-call/presenter/CallPresenter.cpp => module-apps/application-call/presenter/CallPresenter.cpp +34 -8
@@ 8,6 8,9 @@ namespace app::call
{
CallWindowContract::Presenter::Presenter(std::shared_ptr<app::call::AbstractCallModel> callModel) : model(callModel)
+ {}
+
+ void CallWindowContract::Presenter::Presenter::attachCallbacks()
{
model->attachCallStateChangeCallback([this]() { this->handleCallStateChange(); });
model->attachDurationChangeCallback([this]() { this->handleCallDurationChange(); });
@@ 41,39 44,47 @@ namespace app::call
auto callState = model->getState();
switch (callState) {
- case app::call::CallState::Incoming:
+ case app::call::CallState::Incoming: {
view->updateDuration(utils::translate(callAppStyle::strings::iscalling));
view->setIncomingCallLayout(model->getCallerId().empty());
view->updateNumber(getCallerId());
break;
- case app::call::CallState::Outgoing:
+ }
+ case app::call::CallState::Outgoing: {
view->updateDuration(utils::translate(callAppStyle::strings::calling));
view->updateNumber(getCallerId());
view->setActiveCallLayout();
break;
- case app::call::CallState::Active:
+ }
+ case app::call::CallState::Active: {
view->updateDuration(utils::time::Duration(model->getTime()).str());
view->setActiveCallLayout();
break;
- case app::call::CallState::Rejected:
+ }
+ case app::call::CallState::Rejected: {
view->updateDuration(utils::translate(callAppStyle::strings::callrejected));
view->setCallEndedLayout();
break;
- case app::call::CallState::Ended:
+ }
+ case app::call::CallState::Ended: {
view->updateDuration(utils::translate(callAppStyle::strings::callended));
view->setCallEndedLayout();
break;
- case app::call::CallState::Missed:
+ }
+ case app::call::CallState::Missed: {
model->setState(CallState::None);
break;
- case app::call::CallState::Disconnecting:
+ }
+ case app::call::CallState::Disconnecting: {
view->updateDuration(utils::translate(callAppStyle::strings::endingcall));
view->setCallEndedLayout(false);
break;
- case app::call::CallState::None:
+ }
+ case app::call::CallState::None: {
view->clearNavBar();
break;
}
+ }
}
UTF8 CallWindowContract::Presenter::getCallerId()
@@ 179,4 190,19 @@ namespace app::call
{
model->setState(CallState::None);
}
+
+ void CallWindowContract::Presenter::processCurrentRouting(const audio::Profile::Type &routingType)
+ {
+ if (routingType == audio::Profile::Type::RoutingLoudspeaker) {
+ getView()->setSpeakerIconState(gui::SpeakerIconState::SPEAKERON);
+ }
+ else {
+ getView()->setSpeakerIconState(gui::SpeakerIconState::SPEAKER);
+ }
+ }
+ void CallWindowContract::Presenter::clearModel()
+ {
+ model->clear();
+ }
+
} // namespace app::call
M module-apps/application-call/presenter/CallPresenter.hpp => module-apps/application-call/presenter/CallPresenter.hpp +7 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 24,6 24,8 @@ namespace app::call
virtual void setActiveCallLayout() = 0;
virtual void setCallEndedLayout(bool delayedClose = true) = 0;
virtual void updateNumber(const UTF8 &text) = 0;
+ virtual gui::SpeakerIconState getSpeakerIconState() = 0;
+ virtual void setSpeakerIconState(const gui::SpeakerIconState &icon) = 0;
virtual ~View() noexcept = default;
};
@@ 53,6 55,10 @@ namespace app::call
void handleDelayedViewClose();
+ void processCurrentRouting(const audio::Profile::Type &routingType);
+ void attachCallbacks();
+ void clearModel();
+
private:
std::shared_ptr<app::call::AbstractCallModel> model;
UTF8 getCallerId();
M module-apps/application-call/test/mock/CallPresenterMocks.hpp => module-apps/application-call/test/mock/CallPresenterMocks.hpp +8 -3
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 31,7 31,7 @@ namespace app::call
{
layoutShowed = LayoutShowed::Active;
};
- ;
+
void setCallEndedLayout(bool delayedClose = true) override
{
layoutShowed = LayoutShowed::Ended;
@@ 41,6 41,12 @@ namespace app::call
{
number = text;
};
+ gui::SpeakerIconState getSpeakerIconState() override
+ {
+ return gui::SpeakerIconState::SPEAKER;
+ }
+ void setSpeakerIconState(const gui::SpeakerIconState &icon) override
+ {}
bool windowRefreshed = false;
@@ 85,7 91,6 @@ namespace app::call
{
return callerId;
};
-
void hangUpCall() override
{
hangupCallCalled = true;
M module-apps/application-call/windows/CallWindow.cpp => module-apps/application-call/windows/CallWindow.cpp +24 -42
@@ 26,13 26,17 @@ namespace gui
using namespace callAppStyle::callWindow;
using namespace app::call;
- CallWindow::CallWindow(app::ApplicationCommon *app,
- std::unique_ptr<app::call::CallWindowContract::Presenter> &&windowPresenter)
- : gui::AppWindow{app, app::window::name_call}, presenter{std::move(windowPresenter)}
+ CallWindow::CallWindow(app::ApplicationCommon *app, app::call::CallWindowContract::Presenter &presenter)
+ : gui::AppWindow{app, app::window::name_call}, presenter{presenter}
{
- presenter->attach(this);
+ presenter.attach(this);
+ presenter.attachCallbacks();
buildInterface();
}
+ CallWindow::~CallWindow() noexcept
+ {
+ presenter.clearModel();
+ }
void CallWindow::rebuild()
{
@@ 78,7 82,7 @@ namespace gui
microphoneIcon->setNext();
LOG_INFO("Microphone %s", static_cast<bool>(microphoneIcon->get()) ? "activated" : "deactivated");
- microphoneIcon->get() == MicrophoneIconState::MUTED ? presenter->muteCall() : presenter->unmuteCall();
+ microphoneIcon->get() == MicrophoneIconState::MUTED ? presenter.muteCall() : presenter.unmuteCall();
return true;
};
@@ 90,10 94,10 @@ namespace gui
switch (speakerIcon->get()) {
case SpeakerIconState::SPEAKER: {
- presenter->turnLoudspeakerOff();
+ presenter.turnLoudspeakerOff();
} break;
case SpeakerIconState::SPEAKERON: {
- presenter->turnLoudspeakerOn();
+ presenter.turnLoudspeakerOn();
} break;
// case SpeakerIconState::BLUETOOTH: {
// // TODO: need implementation
@@ 109,7 113,7 @@ namespace gui
sendSmsIcon->activatedCallback = [=](gui::Item &item) {
LOG_INFO("Send message template and reject the call");
constexpr auto preventAutoLock = true;
- auto msg = std::make_unique<SMSSendTemplateRequest>(presenter->getPhoneNumber().getView(), preventAutoLock);
+ auto msg = std::make_unique<SMSSendTemplateRequest>(presenter.getPhoneNumber().getView(), preventAutoLock);
msg->ignoreCurrentWindowOnStack = true;
return app::manager::Controller::sendAction(application,
app::manager::actions::ShowSmsTemplates,
@@ 150,11 154,11 @@ namespace gui
void CallWindow::onBeforeShow(ShowMode mode, SwitchData *data)
{
- presenter->buildLayout();
+ presenter.buildLayout();
if (auto switchData = dynamic_cast<SMSTemplateSent *>(data); switchData != nullptr) {
- presenter->hangUpCall();
- presenter->sendSms(switchData->getText());
+ presenter.hangUpCall();
+ presenter.sendSms(switchData->getText());
return;
}
}
@@ 171,19 175,19 @@ namespace gui
const auto code = translator.handle(inputEvent.getRawKey(), InputMode({InputMode::phone}).get());
switch (keyCode) {
case KeyCode::KEY_LF:
- handled = presenter->handleLeftButton();
+ handled = presenter.handleLeftButton();
break;
case KeyCode::KEY_RF:
- handled = presenter->handleRightButton();
+ handled = presenter.handleRightButton();
break;
case KeyCode::HEADSET_OK:
- handled = presenter->handleHeadsetOk();
+ handled = presenter.handleHeadsetOk();
break;
default:
break;
}
if (!handled && code != 0) {
- handled = presenter->handleDigitButton(code);
+ handled = presenter.handleDigitButton(code);
}
}
@@ 200,7 204,7 @@ namespace gui
{
timerCallback = [this](Item &, sys::Timer &timer) {
LOG_DEBUG("Delayed exit timer callback");
- presenter->handleDelayedViewClose();
+ presenter.handleDelayedViewClose();
application->popCurrentWindow();
app::manager::Controller::switchBack(application);
return true;
@@ 297,36 301,14 @@ namespace gui
numberLabel->setText(text);
}
- void CallWindow::handleAudioEvent(const audio::Event &event)
+ gui::SpeakerIconState CallWindow::getSpeakerIconState()
{
-
- switch (event.getType()) {
- case audio::EventType::BlutoothHFPDeviceState:
- case audio::EventType::BlutoothHSPDeviceState:
- case audio::EventType::JackState: {
- if (event.getDeviceState() == audio::Event::DeviceState::Connected) {
- devices_connected.insert(event.getType());
- changeSpeakerIconIfNeeded();
- }
- else {
- devices_connected.erase(event.getType());
- if (not devices_connected.empty()) {
- changeSpeakerIconIfNeeded();
- }
- }
- break;
- }
- default: {
- break;
- }
- }
+ return speakerIcon->get();
}
- void CallWindow::changeSpeakerIconIfNeeded()
+ void CallWindow::setSpeakerIconState(const gui::SpeakerIconState &icon)
{
- if (speakerIcon->get() == SpeakerIconState::SPEAKERON) {
- speakerIcon->setNext();
- }
+ speakerIcon->set(icon);
}
} /* namespace gui */
M module-apps/application-call/windows/CallWindow.hpp => module-apps/application-call/windows/CallWindow.hpp +5 -8
@@ 26,8 26,7 @@ namespace gui
{
return callDelayedStopTime;
}
-
- std::unique_ptr<app::call::CallWindowContract::Presenter> presenter;
+ app::call::CallWindowContract::Presenter &presenter;
protected:
// used to display both number and name of contact
@@ 44,11 43,9 @@ namespace gui
utils::PhoneNumber::View phoneNumber;
- std::set<audio::EventType> devices_connected{};
-
public:
- CallWindow(app::ApplicationCommon *app,
- std::unique_ptr<app::call::CallWindowContract::Presenter> &&windowPresenter);
+ CallWindow(app::ApplicationCommon *app, app::call::CallWindowContract::Presenter &presenter);
+ ~CallWindow() noexcept override;
bool onInput(const InputEvent &inputEvent) override;
void onBeforeShow(ShowMode mode, SwitchData *data) override;
@@ 69,8 66,8 @@ namespace gui
void setActiveCallLayout() override;
void setCallEndedLayout(bool delayedClose = true) override;
void updateNumber(const UTF8 &text) override;
- void handleAudioEvent(const audio::Event &event);
- void changeSpeakerIconIfNeeded();
+ gui::SpeakerIconState getSpeakerIconState() override;
+ void setSpeakerIconState(const gui::SpeakerIconState &icon) override;
};
} /* namespace gui */
M module-audio/Audio/Audio.hpp => module-audio/Audio/Audio.hpp +2 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 89,7 89,7 @@ namespace audio
if (audioSinkState.isConnected(EventType::JackState)) {
return Profile::Type::PlaybackHeadphones;
}
- if (audioSinkState.isConnected(EventType::BlutoothA2DPDeviceState)) {
+ if (audioSinkState.isConnected(EventType::BluetoothA2DPDeviceState)) {
return Profile::Type::PlaybackBluetoothA2DP;
}
return Profile::Type::PlaybackLoudspeaker;
M module-audio/Audio/AudioCommon.hpp => module-audio/Audio/AudioCommon.hpp +7 -7
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 103,11 103,11 @@ namespace audio
enum class EventType
{
// HW state change notifications
- JackState, //!< Jack input plugged / unplugged event
- MicrophoneState, //!< Microphone presence in headset (3-pole w/o microphone or 4-pole with microphone)
- BlutoothHSPDeviceState, //!< BT device connected / disconnected event (Headset Profile)
- BlutoothHFPDeviceState, //!< BT device connected / disconnected event (Headset Profile)
- BlutoothA2DPDeviceState, //!< BT device connected / disconnected event (Advanced Audio Distribution Profile)
+ JackState, //!< Jack input plugged / unplugged event
+ MicrophoneState, //!< Microphone presence in headset (3-pole w/o microphone or 4-pole with microphone)
+ BluetoothHSPDeviceState, //!< BT device connected / disconnected event (Headset Profile)
+ BluetoothHFPDeviceState, //!< BT device connected / disconnected event (Headset Profile)
+ BluetoothA2DPDeviceState, //!< BT device connected / disconnected event (Advanced Audio Distribution Profile)
// call control
CallMute,
@@ 116,7 116,7 @@ namespace audio
CallLoudspeakerOff,
};
- constexpr auto hwStateUpdateMaxEvent = magic_enum::enum_index(EventType::BlutoothA2DPDeviceState);
+ constexpr auto hwStateUpdateMaxEvent = magic_enum::enum_index(EventType::BluetoothA2DPDeviceState);
class Event
{
M module-audio/Audio/Operation/PlaybackOperation.cpp => module-audio/Audio/Operation/PlaybackOperation.cpp +2 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "PlaybackOperation.hpp"
@@ 164,7 164,7 @@ namespace audio
SetProfileAvailability({Profile::Type::PlaybackHeadphones}, isAvailable);
Operation::SwitchToPriorityProfile();
break;
- case EventType::BlutoothA2DPDeviceState:
+ case EventType::BluetoothA2DPDeviceState:
SetProfileAvailability({Profile::Type::PlaybackBluetoothA2DP}, isAvailable);
Operation::SwitchToPriorityProfile();
break;
M module-audio/Audio/Operation/RecorderOperation.cpp => module-audio/Audio/Operation/RecorderOperation.cpp +2 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "RecorderOperation.hpp"
@@ 132,7 132,7 @@ namespace audio
SetProfileAvailability({Profile::Type::RecordingHeadphones}, isAvailable);
SwitchToPriorityProfile();
break;
- case EventType::BlutoothHSPDeviceState:
+ case EventType::BluetoothHSPDeviceState:
SetProfileAvailability({Profile::Type::RecordingBluetoothHSP}, isAvailable);
SwitchToPriorityProfile();
break;
M module-audio/Audio/Operation/RouterOperation.cpp => module-audio/Audio/Operation/RouterOperation.cpp +2 -2
@@ 143,11 143,11 @@ namespace audio
setInputPathForHeadset(headsetHasMicrophone);
SwitchToPriorityProfile();
} break;
- case EventType::BlutoothHSPDeviceState:
+ case EventType::BluetoothHSPDeviceState:
SetProfileAvailability({Profile::Type::RoutingBluetoothHSP}, isAvailable);
SwitchToPriorityProfile();
break;
- case EventType::BlutoothHFPDeviceState:
+ case EventType::BluetoothHFPDeviceState:
SetProfileAvailability({Profile::Type::RoutingBluetoothHFP}, isAvailable);
SwitchToPriorityProfile();
break;
M module-audio/Audio/test/unittest_audio.cpp => module-audio/Audio/test/unittest_audio.cpp +6 -6
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <catch2/catch.hpp>
@@ 524,14 524,14 @@ SCENARIO("Profile playback priorities tests")
WHEN("All audio devices are connected")
{
audio.setConnected(EventType::JackState);
- audio.setConnected(EventType::BlutoothA2DPDeviceState);
+ audio.setConnected(EventType::BluetoothA2DPDeviceState);
THEN("Headphones are prioritized")
{
REQUIRE(audio.GetPriorityPlaybackProfile() == Profile::Type::PlaybackHeadphones);
}
AND_WHEN("Bluetooth is disconnected")
{
- audio.setDisconnected(EventType::BlutoothA2DPDeviceState);
+ audio.setDisconnected(EventType::BluetoothA2DPDeviceState);
THEN("Headphones are prioritized")
{
REQUIRE(audio.GetPriorityPlaybackProfile() == Profile::Type::PlaybackHeadphones);
@@ 548,7 548,7 @@ SCENARIO("Profile playback priorities tests")
}
WHEN("Only bluetooth device is connected")
{
- audio.setConnected(EventType::BlutoothA2DPDeviceState);
+ audio.setConnected(EventType::BluetoothA2DPDeviceState);
THEN("Bluetooth is prioritized")
{
REQUIRE(audio.GetPriorityPlaybackProfile() == Profile::Type::PlaybackBluetoothA2DP);
@@ 598,7 598,7 @@ SCENARIO("Router playback priorities tests")
WHEN("All audio devices are connected, loudspeaker is off")
{
routerOperation.SendEvent(
- std::make_shared<Event>(audio::EventType::BlutoothHSPDeviceState, Event::DeviceState::Connected));
+ std::make_shared<Event>(audio::EventType::BluetoothHSPDeviceState, Event::DeviceState::Connected));
routerOperation.SendEvent(
std::make_shared<Event>(audio::EventType::JackState, Event::DeviceState::Connected));
routerOperation.SendEvent(std::make_shared<Event>(audio::EventType::CallLoudspeakerOff));
@@ 641,7 641,7 @@ SCENARIO("Router playback priorities tests")
WHEN("Only bluetooth HSP is connected, loudspeaker is off")
{
routerOperation.SendEvent(
- std::make_shared<Event>(audio::EventType::BlutoothHSPDeviceState, Event::DeviceState::Connected));
+ std::make_shared<Event>(audio::EventType::BluetoothHSPDeviceState, Event::DeviceState::Connected));
routerOperation.SendEvent(std::make_shared<Event>(audio::EventType::CallLoudspeakerOff));
THEN("Bluetooth HSP is prioritized")
M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp +2 -2
@@ 452,7 452,7 @@ namespace bluetooth
sourceQueue = xQueueCreate(5, sizeof(AudioData_t));
if (sourceQueue != nullptr) {
- sendAudioEvent(audio::EventType::BlutoothA2DPDeviceState, audio::Event::DeviceState::Connected);
+ sendAudioEvent(audio::EventType::BluetoothA2DPDeviceState, audio::Event::DeviceState::Connected);
}
else {
LOG_ERROR("failed to create queue!");
@@ 528,7 528,7 @@ namespace bluetooth
cid,
AVRCP::mediaTracker.local_seid,
local_seid);
- sendAudioEvent(audio::EventType::BlutoothA2DPDeviceState, audio::Event::DeviceState::Disconnected);
+ sendAudioEvent(audio::EventType::BluetoothA2DPDeviceState, audio::Event::DeviceState::Disconnected);
if (cid == AVRCP::mediaTracker.a2dp_cid) {
AVRCP::mediaTracker.stream_opened = 0;
LOG_INFO("A2DP Source: Stream released");
M module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.cpp => module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.cpp +3 -3
@@ 248,13 248,13 @@ namespace bluetooth
status = hfp_subevent_service_level_connection_established_get_status(event);
if (status) {
LOG_DEBUG("Connection failed, status 0x%02x", status);
- sendAudioEvent(audio::EventType::BlutoothHFPDeviceState, audio::Event::DeviceState::Disconnected);
+ sendAudioEvent(audio::EventType::BluetoothHFPDeviceState, audio::Event::DeviceState::Disconnected);
break;
}
aclHandle = hfp_subevent_service_level_connection_established_get_acl_handle(event);
hfp_subevent_service_level_connection_established_get_bd_addr(event, device.address);
LOG_DEBUG("Service level connection established to %s", bd_addr_to_str(device.address));
- sendAudioEvent(audio::EventType::BlutoothHFPDeviceState, audio::Event::DeviceState::Connected);
+ sendAudioEvent(audio::EventType::BluetoothHFPDeviceState, audio::Event::DeviceState::Connected);
{
auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
device.deviceState = DeviceState::ConnectedVoice;
@@ 269,7 269,7 @@ namespace bluetooth
case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED:
LOG_DEBUG("Service level connection released");
aclHandle = HCI_CON_HANDLE_INVALID;
- sendAudioEvent(audio::EventType::BlutoothHFPDeviceState, audio::Event::DeviceState::Disconnected);
+ sendAudioEvent(audio::EventType::BluetoothHFPDeviceState, audio::Event::DeviceState::Disconnected);
{
auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
busProxy.sendUnicast(std::make_shared<message::bluetooth::DisconnectResult>(device),
M module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp => module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp +5 -5
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <log/log.hpp>
@@ 158,12 158,12 @@ 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);
+ sendAudioEvent(audio::EventType::BluetoothHSPDeviceState, audio::Event::DeviceState::Disconnected);
isConnected = false;
break;
}
LOG_DEBUG("RFCOMM connection established.\n");
- sendAudioEvent(audio::EventType::BlutoothHSPDeviceState, audio::Event::DeviceState::Connected);
+ sendAudioEvent(audio::EventType::BluetoothHSPDeviceState, audio::Event::DeviceState::Connected);
{
auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
device.deviceState = DeviceState::ConnectedVoice;
@@ 174,7 174,7 @@ namespace bluetooth
break;
case HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE: {
LOG_DEBUG("RFCOMM disconnected.\n");
- sendAudioEvent(audio::EventType::BlutoothHSPDeviceState, audio::Event::DeviceState::Disconnected);
+ sendAudioEvent(audio::EventType::BluetoothHSPDeviceState, audio::Event::DeviceState::Disconnected);
auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
busProxy.sendUnicast(std::make_shared<message::bluetooth::DisconnectResult>(device),
service::name::bluetooth);
@@ 200,7 200,7 @@ namespace bluetooth
LOG_DEBUG("Audio connection released.\n\n");
scoHandle = HCI_CON_HANDLE_INVALID;
callAnswered = false;
- sendAudioEvent(audio::EventType::BlutoothHSPDeviceState, audio::Event::DeviceState::Disconnected);
+ sendAudioEvent(audio::EventType::BluetoothHSPDeviceState, audio::Event::DeviceState::Disconnected);
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/AudioServiceAPI.cpp => module-services/service-audio/AudioServiceAPI.cpp +5 -6
@@ 90,18 90,16 @@ namespace AudioServiceAPI
return serv->bus.sendUnicast(msg, service::name::audio);
}
- void SendEvent(sys::Service *serv, std::shared_ptr<audio::Event> evt)
+ bool SendEvent(sys::Service *serv, std::shared_ptr<audio::Event> evt)
{
auto msg = std::make_shared<AudioEventRequest>(std::move(evt));
- serv->bus.sendMulticast(msg, sys::BusChannel::ServiceAudioNotifications);
- // return true;
+ return serv->bus.sendUnicast(msg, service::name::audio);
}
- void SendEvent(sys::Service *serv, audio::EventType eType, audio::Event::DeviceState state)
+ bool SendEvent(sys::Service *serv, audio::EventType eType, audio::Event::DeviceState state)
{
auto msg = std::make_shared<AudioEventRequest>(eType, state);
- serv->bus.sendMulticast(msg, sys::BusChannel::ServiceAudioNotifications);
- // return true;
+ return serv->bus.sendUnicast(msg, service::name::audio);
}
std::string GetSetting(sys::Service *serv, audio::Setting setting, audio::PlaybackType playbackType)
@@ 251,4 249,5 @@ namespace AudioServiceAPI
{
return serv->bus.sendUnicast(std::make_shared<HFPDeviceVolumeChanged>(volume), service::name::audio);
}
+
} // namespace AudioServiceAPI
M module-services/service-audio/ServiceAudio.cpp => module-services/service-audio/ServiceAudio.cpp +22 -10
@@ 126,11 126,6 @@ ServiceAudio::ServiceAudio()
[this](sys::Message *msg) -> sys::MessagePointer { return handleMultimediaAudioPause(); });
connect(typeid(message::bluetooth::AudioStart),
[this](sys::Message *msg) -> sys::MessagePointer { return handleMultimediaAudioStart(); });
- connect(typeid(AudioEventRequest), [this](sys::Message *msg) -> sys::MessagePointer {
- auto message = static_cast<AudioEventRequest *>(msg);
- HandleSendEvent(message->getEvent());
- return sys::msgHandled();
- });
}
ServiceAudio::~ServiceAudio()
@@ 454,13 449,13 @@ std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleStart(const Operation:
return std::make_unique<AudioStartRoutingResponse>(RetCode::OperationNotSet, Token::MakeBadToken());
}
-sys::MessagePointer ServiceAudio::HandleSendEvent(std::shared_ptr<Event> evt)
+std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleSendEvent(std::shared_ptr<Event> evt)
{
const auto eventType = evt->getType();
const auto deviceConnected = evt->getDeviceState() == audio::Event::DeviceState::Connected;
switch (eventType) {
- case EventType::BlutoothA2DPDeviceState: {
+ case EventType::BluetoothA2DPDeviceState: {
LOG_DEBUG("Bluetooth A2DP connection status changed: %s", deviceConnected ? "connected" : "disconnected");
if (!deviceConnected) {
@@ 474,8 469,8 @@ sys::MessagePointer ServiceAudio::HandleSendEvent(std::shared_ptr<Event> evt)
HandleStop(playbacksToBeStopped, audio::Token());
} break;
- case EventType::BlutoothHSPDeviceState:
- case EventType::BlutoothHFPDeviceState: {
+ case EventType::BluetoothHSPDeviceState:
+ case EventType::BluetoothHFPDeviceState: {
if (deviceConnected != bluetoothVoiceProfileConnected) {
LOG_DEBUG("Bluetooth voice connection status changed: %s", deviceConnected ? "connected" : "disconnected");
bluetoothVoiceProfileConnected = deviceConnected;
@@ 497,7 492,9 @@ sys::MessagePointer ServiceAudio::HandleSendEvent(std::shared_ptr<Event> evt)
input.audio->SendEvent(evt);
}
- return sys::msgHandled();
+ notifyAboutNewRoutingIfRouterAvailable();
+
+ return std::make_unique<AudioEventResponse>(RetCode::Success);
}
std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleStop(const std::vector<audio::PlaybackType> &stopTypes,
@@ 675,6 672,10 @@ sys::MessagePointer ServiceAudio::DataReceivedHandler(sys::DataMessage *msgl, sy
auto *msg = static_cast<AudioResumeRequest *>(msgl);
responseMsg = HandleResume(msg->token);
}
+ else if (msgType == typeid(AudioEventRequest)) {
+ auto *msg = static_cast<AudioEventRequest *>(msgl);
+ responseMsg = HandleSendEvent(msg->getEvent());
+ }
else if (msgType == typeid(AudioKeyPressedRequest)) {
auto *msg = static_cast<AudioKeyPressedRequest *>(msgl);
responseMsg = HandleKeyPressed(msg->step);
@@ 896,3 897,14 @@ auto ServiceAudio::handleMultimediaAudioStart() -> sys::MessagePointer
}
return sys::msgHandled();
}
+
+void ServiceAudio::notifyAboutNewRoutingIfRouterAvailable()
+{
+ for (auto &input : audioMux.GetAllInputs()) {
+ if (input.audio->GetCurrentOperation().GetOperationType() == audio::Operation::Type::Router) {
+ bus.sendMulticast(
+ std::make_shared<AudioRoutingNotification>(input.audio->GetCurrentOperation().GetProfile()->GetType()),
+ sys::BusChannel::ServiceAudioNotifications);
+ }
+ }
+}
M module-services/service-audio/include/service-audio/AudioMessage.hpp => module-services/service-audio/include/service-audio/AudioMessage.hpp +9 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 168,6 168,14 @@ class AudioStartRoutingResponse : public AudioResponseMessage
const audio::Token token;
};
+class AudioRoutingNotification : public AudioMessage
+{
+ public:
+ AudioRoutingNotification(const audio::Profile::Type &profileType) : profileType(profileType)
+ {}
+ const audio::Profile::Type profileType;
+};
+
class AudioStartRecorderRequest : public AudioMessage
{
public:
M module-services/service-audio/include/service-audio/AudioServiceAPI.hpp => module-services/service-audio/include/service-audio/AudioServiceAPI.hpp +8 -4
@@ 104,18 104,22 @@ namespace AudioServiceAPI
*/
bool Resume(sys::Service *serv, const audio::Token &token);
/**
- * @brief Sends audio event as multicast
+ * @brief Sends audio event.
* @param serv Requesting service.
* @param evt Event to be sent.
+ * @return True if request has been sent successfully, false otherwise
+ * Response will come as message AudioSendEventResponse
*/
- void SendEvent(sys::Service *serv, std::shared_ptr<audio::Event> evt);
+ bool SendEvent(sys::Service *serv, std::shared_ptr<audio::Event> evt);
/**
- * @brief Sends audio event as multicast
+ * @brief Sends audio event.
* @param serv Requesting service.
* @param evt Event to be sent.
* @param state Optional parameter to request.
+ * @return True if request has been sent successfully, false otherwise
+ * Response will come as message AudioSendEventResponse
*/
- void SendEvent(sys::Service *serv,
+ bool SendEvent(sys::Service *serv,
audio::EventType evt,
audio::Event::DeviceState state = audio::Event::DeviceState::Connected);
M module-services/service-audio/include/service-audio/ServiceAudio.hpp => module-services/service-audio/include/service-audio/ServiceAudio.hpp +3 -1
@@ 78,7 78,7 @@ class ServiceAudio : public sys::Service
};
auto StopInput(audio::AudioMux::Input *input, StopReason stopReason = StopReason::Other) -> audio::RetCode;
- auto HandleSendEvent(std::shared_ptr<audio::Event> evt) -> sys::MessagePointer;
+ auto HandleSendEvent(std::shared_ptr<audio::Event> evt) -> std::unique_ptr<AudioResponseMessage>;
auto HandlePause(const audio::Token &token) -> std::unique_ptr<AudioResponseMessage>;
auto HandlePause(std::optional<audio::AudioMux::Input *> input) -> std::unique_ptr<AudioResponseMessage>;
auto HandleResume(const audio::Token &token) -> std::unique_ptr<AudioResponseMessage>;
@@ 127,6 127,8 @@ class ServiceAudio : public sys::Service
auto handleHFPVolumeChangedOnBluetoothDevice(sys::Message *msgl) -> sys::MessagePointer;
auto handleMultimediaAudioPause() -> sys::MessagePointer;
auto handleMultimediaAudioStart() -> sys::MessagePointer;
+
+ void notifyAboutNewRoutingIfRouterAvailable();
};
namespace sys
M module-services/service-evtmgr/AppSettingsNotify.cpp => module-services/service-evtmgr/AppSettingsNotify.cpp +4 -4
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "Service/BusProxy.hpp"
@@ 9,17 9,17 @@ namespace evm::api
void notifySettingsBluetoothAudio(sys::BusProxy &bus, std::shared_ptr<audio::Event> event)
{
switch (event->getType()) {
- case audio::EventType::BlutoothA2DPDeviceState: {
+ case audio::EventType::BluetoothA2DPDeviceState: {
auto message = std::make_shared<message::bluetooth::ProfileStatus>(
bluetooth::AudioProfile::A2DP, (event->getDeviceState() == audio::Event::DeviceState::Connected));
bus.sendUnicast(message, app::name_settings);
} break;
- case audio::EventType::BlutoothHSPDeviceState: {
+ case audio::EventType::BluetoothHSPDeviceState: {
auto message = std::make_shared<message::bluetooth::ProfileStatus>(
bluetooth::AudioProfile::HSP, (event->getDeviceState() == audio::Event::DeviceState::Connected));
bus.sendUnicast(message, app::name_settings);
} break;
- case audio::EventType::BlutoothHFPDeviceState: {
+ case audio::EventType::BluetoothHFPDeviceState: {
auto message = std::make_shared<message::bluetooth::ProfileStatus>(
bluetooth::AudioProfile::HFP, (event->getDeviceState() == audio::Event::DeviceState::Connected));
bus.sendUnicast(message, app::name_settings);
M pure_changelog.md => pure_changelog.md +1 -1
@@ 72,7 72,7 @@
* Fixed (removed) redundant leading zero from time representation unless exactly midnight
* Fixed inability to type characters other than digits in USSD replies
* Fixed screen ghosting after emoji selection
-* Fixed incorrect loudspeaker icon in call window when headset was connected during a call
+* Fixed incorrect loudspeaker icon in call window when headset was connected or disconnected during a call
* Fixed invalid screen displayed after missed call
* Fixed minor issues in the Calculator Application
* Fixed displaying usual SMS template call rejection window when no templates were defined