M module-apps/application-call/ApplicationCall.cpp => module-apps/application-call/ApplicationCall.cpp +26 -88
@@ 2,6 2,7 @@
#include "DialogMetadata.hpp"
#include "DialogMetadataMessage.hpp"
+#include "application-call/data/CallWindowData.hpp"
#include "data/CallSwitchData.hpp"
#include "windows/CallMainWindow.hpp"
#include "windows/CallWindow.hpp"
@@ 14,6 15,7 @@
#include <UiCommonActions.hpp>
#include <Dialog.hpp>
#include <log/log.hpp>
+#include <memory>
#include <service-cellular/ServiceCellular.hpp>
#include <service-cellular/api/CellularServiceAPI.hpp>
#include <service-audio/api/AudioServiceAPI.hpp>
@@ 29,103 31,39 @@ namespace app
ApplicationCall::ApplicationCall(std::string name, std::string parent, bool startBackground)
: Application(name, parent, startBackground, app::call_stack_size)
{
- timerCall = std::make_unique<sys::Timer>("Call", this, 1000);
- timerCall->connect([this](sys::Timer &) { timerCallCallback(); });
}
// number of seconds after end call to switch back to previous application
const inline utils::time::Duration delayToSwitchToPreviousApp = 3;
- void ApplicationCall::timerCallCallback()
+ void switchWindowOrApp(Application *app, std::unique_ptr<gui::SwitchData> &&data)
{
- callDuration = utils::time::Timestamp() - callStartTime;
-
- if (getCurrentWindow() == windowsStack.get(window::name_call)) {
- auto callWindow = dynamic_cast<gui::CallWindow *>(getCurrentWindow());
-
- if (callWindow != nullptr && callWindow->getState() == gui::CallWindow::State::CALL_IN_PROGRESS) {
- callWindow->updateDuration(callDuration);
- refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
- }
+ if (app->getState() == Application::State::ACTIVE_FORGROUND) {
+ app->switchWindow(window::name_call, std::move(data));
+ }
+ else {
+ sapm::ApplicationManager::messageSwitchApplication(app, name_call, window::name_call, std::move(data));
}
}
void ApplicationCall::CallAbortHandler()
{
- auto callWindow = dynamic_cast<gui::CallWindow *>(windowsStack.get(window::name_call));
- assert(callWindow != nullptr);
-
- LOG_INFO("---------------------------------CallAborted");
- AudioServiceAPI::StopAll(this);
-
- callWindow->setState(gui::CallWindow::State::CALL_ENDED);
- if (getState() == State::ACTIVE_FORGROUND && getCurrentWindow() != callWindow) {
- switchWindow(window::name_call);
- return;
- }
- else if (getState() == State::ACTIVE_BACKGROUND) {
- // it means we have switched to different application during call and the call was aborted
- // hence we need to switch back to call application
- sapm::ApplicationManager::messageSwitchPreviousApplication(this);
- }
-
- refreshWindow(gui::RefreshModes::GUI_REFRESH_DEEP);
+ switchWindowOrApp(this, std::make_unique<app::CallAbortData>());
}
void ApplicationCall::CallActiveHandler()
{
- auto callWindow = dynamic_cast<gui::CallWindow *>(windowsStack.get(window::name_call));
- assert(callWindow != nullptr);
-
- AudioServiceAPI::RoutingStart(this);
- runCallTimer();
-
- LOG_INFO("---------------------------------CallActive");
- callWindow->setState(gui::CallWindow::State::CALL_IN_PROGRESS);
- refreshWindow(gui::RefreshModes::GUI_REFRESH_DEEP);
+ switchWindowOrApp(this, std::make_unique<app::CallActiveData>());
}
void ApplicationCall::IncomingCallHandler(const CellularCallMessage *const msg)
{
- auto callWindow = dynamic_cast<gui::CallWindow *>(windowsStack.get(window::name_call));
- assert(callWindow != nullptr);
-
- LOG_INFO("---------------------------------IncomingCall");
- if (callWindow->getState() == gui::CallWindow::State::INCOMING_CALL) {
- LOG_INFO("ignoring call incoming");
- }
- else {
- AudioServiceAPI::PlaybackStart(this, audio::PlaybackType::CallRingtone, ringtone_path);
- runCallTimer();
- std::unique_ptr<gui::SwitchData> data = std::make_unique<app::IncomingCallData>(msg->number);
- // send to itself message to switch (run) call application
- callWindow->setState(gui::CallWindow::State::INCOMING_CALL);
- if (getState() == State::ACTIVE_FORGROUND) {
- LOG_INFO("++++++++++++WINDOW SWITCH");
- switchWindow(window::name_call, std::move(data));
- }
- else {
- LOG_INFO("++++++++++++APP SWITCH");
-
- sapm::ApplicationManager::messageSwitchApplication(this, name_call, window::name_call, std::move(data));
- }
- }
+ switchWindowOrApp(this, std::make_unique<app::IncomingCallData>(msg->number));
}
void ApplicationCall::RingingHandler(const CellularCallMessage *const msg)
{
- auto callWindow = dynamic_cast<gui::CallWindow *>(windowsStack.get(window::name_call));
- assert(callWindow != nullptr);
-
- LOG_INFO("---------------------------------Ringing");
- AudioServiceAPI::RoutingStart(this);
- runCallTimer();
-
- std::unique_ptr<gui::SwitchData> data = std::make_unique<app::ExecuteCallData>(msg->number);
- callWindow->setState(gui::CallWindow::State::OUTGOING_CALL);
- if (getState() == State::ACTIVE_FORGROUND) {
- switchWindow(window::name_call, std::move(data));
- }
+ switchWindowOrApp(this, std::make_unique<app::ExecuteCallData>(msg->number));
}
// Invoked upon receiving data message
@@ 238,20 176,6 @@ namespace app
return true;
}
- void ApplicationCall::runCallTimer()
- {
- callStartTime = utils::time::Timestamp();
- callDuration = 0;
- timerCall->reload();
- }
-
- void ApplicationCall::stopCallTimer()
- {
- callStartTime = 0;
- callDuration = 0;
- timerCall->stop();
- }
-
void ApplicationCall::destroyUserInterface()
{}
@@ 285,4 209,18 @@ namespace app
}
}
+ void ApplicationCall::stopAudio()
+ {
+ AudioServiceAPI::StopAll(this);
+ }
+
+ void ApplicationCall::startRinging()
+ {
+ AudioServiceAPI::PlaybackStart(this, audio::PlaybackType::CallRingtone, ringtone_path);
+ }
+
+ void ApplicationCall::startRouting()
+ {
+ AudioServiceAPI::RoutingStart(this);
+ }
} // namespace app
M module-apps/application-call/ApplicationCall.hpp => module-apps/application-call/ApplicationCall.hpp +4 -8
@@ 32,11 32,7 @@ namespace app
void RingingHandler(const CellularCallMessage *const msg);
protected:
- std::unique_ptr<sys::Timer> timerCall;
- utils::time::Timestamp callStartTime = 0;
- utils::time::Duration callDuration;
sys::ms callDelayedStopTime = 3000;
- void timerCallCallback();
public:
ApplicationCall(std::string name = name_call, std::string parent = "", bool startBackgound = false);
@@ 53,10 49,6 @@ namespace app
void destroyUserInterface() override;
void setDisplayedNumber(std::string num);
const std::string &getDisplayedNumber();
- // starts timer that upon triggering, if no user action was performed, will hide application to background and
- // move to previous application
- void runCallTimer();
- void stopCallTimer();
void handleCallEvent(const std::string &number);
void handleAddContactEvent(const std::string &number);
@@ 67,5 59,9 @@ namespace app
{
return callDelayedStopTime;
}
+
+ void stopAudio();
+ void startRinging();
+ void startRouting();
};
} /* namespace app */
M module-apps/application-call/CMakeLists.txt => module-apps/application-call/CMakeLists.txt +0 -1
@@ 23,7 23,6 @@ target_sources( ${PROJECT_NAME}
"${CMAKE_CURRENT_LIST_DIR}/windows/CallWindow.cpp"
PUBLIC
"${CMAKE_CURRENT_LIST_DIR}/ApplicationCall.hpp"
- "${CMAKE_CURRENT_LIST_DIR}/windows/CallMainWindow.hpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/EnterNumberWindow.hpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/EmergencyCallWindow.hpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/CallWindow.hpp"
M module-apps/application-call/data/CallSwitchData.hpp => module-apps/application-call/data/CallSwitchData.hpp +11 -0
@@ 69,4 69,15 @@ namespace app
};
+ class CallAbortData : public gui::SwitchData
+ {
+ public:
+ CallAbortData() = default;
+ };
+
+ class CallActiveData : public gui::SwitchData
+ {
+ public:
+ CallActiveData() = default;
+ };
} /* namespace app */
A module-apps/application-call/data/CallWindowData.hpp => module-apps/application-call/data/CallWindowData.hpp +20 -0
@@ 0,0 1,20 @@
+#pragma once
+
+#include "CallWindowState.hpp"
+#include <SwitchData.hpp>
+
+namespace gui
+{
+ class CallWindowData : public SwitchData
+ {
+ call::State state;
+
+ public:
+ CallWindowData(call::State state) : state(state)
+ {}
+ [[nodiscard]] const auto &getState() const noexcept
+ {
+ return state;
+ }
+ };
+} // namespace gui
A module-apps/application-call/data/CallWindowState.hpp => module-apps/application-call/data/CallWindowState.hpp +30 -0
@@ 0,0 1,30 @@
+#pragma once
+
+namespace gui::call
+{
+ enum class State
+ {
+ IDLE,
+ INCOMING_CALL,
+ OUTGOING_CALL,
+ CALL_IN_PROGRESS,
+ CALL_ENDED
+ };
+}
+
+inline const char *c_str(gui::call::State state)
+{
+ switch (state) {
+ case gui::call::State::IDLE:
+ return "IDLE";
+ case gui::call::State::INCOMING_CALL:
+ return "INCOMING_CALL";
+ case gui::call::State::OUTGOING_CALL:
+ return "OUTGOING_CALL";
+ case gui::call::State::CALL_IN_PROGRESS:
+ return "CALL_IN_PROGRESS";
+ case gui::call::State::CALL_ENDED:
+ return "CALL_ENDED";
+ }
+ return "";
+}
M module-apps/application-call/windows/CallWindow.cpp => module-apps/application-call/windows/CallWindow.cpp +73 -16
@@ 1,16 1,10 @@
-/*
- * @file CallWindow.cpp
- * @author Robert Borzecki (robert.borzecki@mudita.com)
- * @date 12 lip 2019
- * @brief
- * @copyright Copyright (C) 2019 mudita.com
- * @details
- */
#include "CallWindow.hpp"
+#include <application-call/data/CallWindowData.hpp>
#include "GuiTimer.hpp"
#include "InputEvent.hpp"
#include "application-call/widgets/Icons.hpp"
+#include "log/log.hpp"
#include "service-appmgr/ApplicationManager.hpp"
#include "application-call/ApplicationCall.hpp"
@@ 25,6 19,7 @@
#include "Label.hpp"
#include "Margins.hpp"
#include "application-call/data/CallAppStyle.hpp"
+#include "time/time_conversion.hpp"
#include <UiCommonActions.hpp>
#include <application-messages/data/SMSdata.hpp>
@@ 36,11 31,13 @@
#include <iomanip>
#include <cassert>
+#include <magic_enum.hpp>
namespace gui
{
using namespace callAppStyle;
using namespace callAppStyle::callWindow;
+ using namespace call;
CallWindow::CallWindow(app::Application *app, std::string windowName) : AppWindow(app, windowName)
{
@@ 159,11 156,12 @@ namespace gui
void CallWindow::setState(State state)
{
+ LOG_INFO("==> Call state change: %s -> %s", c_str(this->state), c_str(state));
this->state = state;
setVisibleState();
}
- const CallWindow::State &CallWindow::getState()
+ const State &CallWindow::getState()
{
return state;
}
@@ 173,6 171,8 @@ namespace gui
// show state of the window
switch (state) {
case State::INCOMING_CALL: {
+ runCallTimer();
+
bottomBar->setActive(gui::BottomBar::Side::CENTER, true);
bottomBar->setText(gui::BottomBar::Side::LEFT, utils::localize.get(strings::answer), true);
bottomBar->setText(gui::BottomBar::Side::RIGHT, utils::localize.get(strings::reject), true);
@@ 184,6 184,8 @@ namespace gui
setFocusItem(sendSmsIcon);
} break;
case State::CALL_ENDED: {
+ stopCallTimer();
+
bottomBar->setActive(gui::BottomBar::Side::LEFT, false);
bottomBar->setActive(gui::BottomBar::Side::CENTER, false);
bottomBar->setActive(gui::BottomBar::Side::RIGHT, false);
@@ 220,6 222,8 @@ namespace gui
setFocusItem(microphoneIcon);
} break;
case State::IDLE:
+ stopCallTimer();
+ [[fallthrough]];
default:
bottomBar->setActive(gui::BottomBar::Side::LEFT, false);
bottomBar->setActive(gui::BottomBar::Side::CENTER, false);
@@ 236,7 240,7 @@ namespace gui
void CallWindow::setCallNumber(std::string)
{}
- void CallWindow::updateDuration(const utils::time::Duration &duration)
+ void CallWindow::updateDuration(const utils::time::Duration duration)
{
if (durationLabel != nullptr) {
durationLabel->setText(duration.str());
@@ 273,7 277,6 @@ namespace gui
}
}
else {
- LOG_ERROR("Unrecognized SwitchData");
return false;
}
@@ 299,7 302,37 @@ namespace gui
}
void CallWindow::onBeforeShow(ShowMode mode, SwitchData *data)
- {}
+ {
+ auto app = static_cast<app::ApplicationCall *>(application);
+
+ if (dynamic_cast<app::IncomingCallData *>(data) != nullptr) {
+ if (getState() == call::State::INCOMING_CALL) {
+ LOG_INFO("ignoring call incoming");
+ }
+ app->startRinging();
+ setState(call::State::INCOMING_CALL);
+ return;
+ }
+
+ if (dynamic_cast<app::CallAbortData *>(data) != nullptr) {
+ app->stopAudio();
+ setState(State::CALL_ENDED);
+ return;
+ }
+
+ if (dynamic_cast<app::CallActiveData *>(data) != nullptr) {
+ app->startRouting();
+ runCallTimer();
+ return;
+ }
+
+ if (dynamic_cast<app::ExecuteCallData *>(data) != nullptr) {
+ AudioServiceAPI::RoutingStart(application);
+ runCallTimer();
+ setState(State::OUTGOING_CALL);
+ return;
+ }
+ }
bool CallWindow::handleLeftButton()
{
@@ 378,16 411,40 @@ namespace gui
{
auto app = dynamic_cast<app::ApplicationCall *>(application);
assert(app != nullptr);
+
auto timer = std::make_unique<app::GuiTimer>(app);
timer->setInterval(app->getDelayedStopTime());
- timerCallback = [app, this](Item &, Timer &timer) {
- app->stopCallTimer();
+
+ timerCallback = [this](Item &, Timer &timer) {
setState(State::IDLE);
detachTimer(timer);
- sapm::ApplicationManager::messageSwitchPreviousApplication(app);
+ sapm::ApplicationManager::messageSwitchPreviousApplication(application);
+ return true;
+ };
+ application->connect(std::move(timer), this);
+ }
+
+ void CallWindow::runCallTimer()
+ {
+ static const sys::ms one_second = 1000;
+ callStart = utils::time::Timestamp();
+ stop_timer = false;
+ auto timer = std::make_unique<app::GuiTimer>("CallTime", application, one_second, Timer::Continous);
+ timerCallback = [&](Item &, Timer &timer) {
+ if (stop_timer) {
+ timer.stop();
+ detachTimer(timer);
+ }
+ updateDuration(utils::time::Duration(utils::time::Timestamp(), callStart));
+ application->refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
return true;
};
- app->connect(std::move(timer), this);
+ timer->start();
+ application->connect(std::move(timer), this);
}
+ void CallWindow::stopCallTimer()
+ {
+ stop_timer = true;
+ }
} /* namespace gui */
M module-apps/application-call/windows/CallWindow.hpp => module-apps/application-call/windows/CallWindow.hpp +10 -14
@@ 7,22 7,16 @@
#include <gui/input/Translator.hpp>
#include <Rect.hpp>
#include <Image.hpp>
+#include <application-call/data/CallWindowState.hpp>
+
namespace gui
{
class CallWindow : public AppWindow
{
- public:
- enum class State
- {
- IDLE,
- INCOMING_CALL,
- OUTGOING_CALL,
- CALL_IN_PROGRESS,
- CALL_ENDED
- };
-
private:
gui::KeyInputMappedTranslation translator;
+ utils::time::Timestamp callStart;
+ bool stop_timer = false;
protected:
// used to display both nnumber and name of contact
@@ 36,7 30,7 @@ namespace gui
gui::Image *imageCircleTop = nullptr;
gui::Image *imageCircleBottom = nullptr;
- State state = State::IDLE;
+ call::State state = call::State::IDLE;
utils::PhoneNumber::View phoneNumber;
/**
* Manipulates widgets to handle currently set state of the window.
@@ 44,6 38,7 @@ namespace gui
void setVisibleState();
bool handleLeftButton();
bool handleRightButton();
+ void setState(call::State state);
public:
CallWindow(app::Application *app, std::string windowName = app::window::name_call);
@@ 52,9 47,8 @@ namespace gui
/**
* Used by application to update window's state
*/
- void setState(State state);
- const State &getState();
- void updateDuration(const utils::time::Duration &duration);
+ const call::State &getState();
+ void updateDuration(const utils::time::Duration duration);
void setCallNumber(std::string);
bool onInput(const InputEvent &inputEvent) override;
@@ 66,6 60,8 @@ namespace gui
void destroyInterface() override;
bool handleDigit(const uint32_t digit);
void connectTimerOnExit();
+ void runCallTimer();
+ void stopCallTimer();
};
} /* namespace gui */