~aleteoryx/muditaos

383073f8f71297f8f9d28638aaeb53d228621021 — Adam Dobrowolski 5 years ago a1b7d94
EGD-4098 Call rework
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 */