/* * @file CallWindow.cpp * @author Robert Borzecki (robert.borzecki@mudita.com) * @date 12 lip 2019 * @brief * @copyright Copyright (C) 2019 mudita.com * @details */ #include #include #include #include #include "service-appmgr/ApplicationManager.hpp" #include "../ApplicationCall.hpp" #include "../data/CallSwitchData.hpp" #include "i18/i18.hpp" #include "service-cellular/api/CellularServiceAPI.hpp" #include "service-audio/api/AudioServiceAPI.hpp" #include "Label.hpp" #include "Margins.hpp" #include "CallWindow.hpp" namespace gui { CallWindow::CallWindow( app::Application* app, std::string windowName ) : AppWindow(app, windowName){ setSize( 480, 600 ); buildInterface(); } void CallWindow::rebuild() { destroyInterface(); buildInterface(); } void CallWindow::buildInterface() { AppWindow::buildInterface(); topBar->setActive(gui::TopBar::Elements::BATTERY, true ); topBar->setActive(gui::TopBar::Elements::SIGNAL, true ); topBar->setActive(gui::TopBar::Elements::TIME, true ); bottomBar->setActive( BottomBar::Side::CENTER, true ); bottomBar->setActive( BottomBar::Side::RIGHT, true ); bottomBar->setText( BottomBar::Side::CENTER, utils::localize.get("common_select")); bottomBar->setText( BottomBar::Side::RIGHT, utils::localize.get("common_back")); bottomBar->setText( gui::BottomBar::Side::CENTER, "Message" ); //create circles to hold images inside for( uint32_t i=0; i<2; ++i ) { rects[i] = new gui::Rect( this, 0,0, 80, 80 ); rects[i]->setFilled( false ); rects[i]->setRadius(40); rects[i]->setPenFocusWidth(3); rects[i]->setPenWidth(1); } rects[static_cast(FocusRects::Speaker)]->setPosition( 150, 400 ); rects[static_cast(FocusRects::Micrphone)]->setPosition( 250, 400 ); imageSpeaker[static_cast(AudioState::ON)] = new gui::Image( rects[static_cast(FocusRects::Speaker)], 20, 20, 0,0, "speaker_on" ); imageSpeaker[static_cast(AudioState::OFF)] = new gui::Image( rects[static_cast(FocusRects::Speaker)], 20, 20, 0,0, "speaker_off" ); imageSpeaker[static_cast(AudioState::ON)]->setVisible(false); imageSpeaker[static_cast(AudioState::OFF)]->setVisible(false); // imageMessage = new gui::Image( this, 200, 60-177, 0,0, "call_message" ); imageMicrophone[static_cast(AudioState::ON)] = new gui::Image( rects[static_cast(FocusRects::Micrphone)], 20, 20, 0,0, "microphone_on" ); imageMicrophone[static_cast(AudioState::OFF)] = new gui::Image( rects[static_cast(FocusRects::Micrphone)], 20, 20, 0,0, "microphone_off" ); imageMicrophone[static_cast(AudioState::ON)]->setVisible(false); imageMicrophone[static_cast(AudioState::OFF)]->setVisible(false); //top circle image imageCircleTop = new gui::Image( this, 116, 82, 0,0, "circle_top" ); imageCircleBottom = new gui::Image( this, 106, 266, 0,0, "circle_bottom" ); durationLabel = new gui::Label(this, 0, 220, 480, 80 ); durationLabel->setFilled( false ); durationLabel->setBorderColor( gui::ColorNoColor ); durationLabel->setFont("gt_pressura_regular_24"); durationLabel->setAlignement( gui::Alignment(gui::Alignment::ALIGN_HORIZONTAL_CENTER, gui::Alignment::ALIGN_VERTICAL_BOTTOM)); numberLabel = new gui::Label(this, 11, 150, 480-22, 80 ); numberLabel->setFilled( false ); numberLabel->setBorderColor( gui::ColorNoColor ); numberLabel->setFont("gt_pressura_regular_44"); numberLabel->setAlignement( gui::Alignment(gui::Alignment::ALIGN_HORIZONTAL_CENTER, gui::Alignment::ALIGN_VERTICAL_BOTTOM)); //define navigation between labels rects[static_cast(FocusRects::Speaker)]->setNavigationItem( NavigationDirection::LEFT, rects[static_cast(FocusRects::Micrphone)]); rects[static_cast(FocusRects::Speaker)]->setNavigationItem( NavigationDirection::RIGHT, rects[static_cast(FocusRects::Micrphone)]); rects[static_cast(FocusRects::Micrphone)]->setNavigationItem( NavigationDirection::LEFT, rects[static_cast(FocusRects::Speaker)]); rects[static_cast(FocusRects::Micrphone)]->setNavigationItem( NavigationDirection::RIGHT, rects[static_cast(FocusRects::Speaker)]); //focus callbacks rects[static_cast(FocusRects::Speaker)]->focusChangedCallback = [=] (gui::Item& item){ LOG_INFO("Speaker gets focus" ); bottomBar->setText( BottomBar::Side::CENTER, utils::localize.get("common_speaker")); return true; }; rects[static_cast(FocusRects::Micrphone)]->focusChangedCallback = [=] (gui::Item& item){ LOG_INFO("Mute gets focus" ); bottomBar->setText( BottomBar::Side::CENTER, utils::localize.get("common_mute")); return true; }; //activation callbacks rects[static_cast(FocusRects::Speaker)]->activatedCallback = [=] (gui::Item& item){ LOG_INFO("Speaker activated" ); //update icon imageSpeaker[static_cast(speakerState)]->setVisible(false); speakerState = (speakerState == AudioState::ON)?AudioState::OFF:AudioState::ON; imageSpeaker[static_cast(speakerState)]->setVisible(true); application->refreshWindow( RefreshModes::GUI_REFRESH_FAST ); (speakerState == AudioState::ON)? AudioServiceAPI::RoutingSpeakerPhone(this->application,true): AudioServiceAPI::RoutingSpeakerPhone(this->application,false); return true; }; rects[static_cast(FocusRects::Micrphone)]->activatedCallback = [=] (gui::Item& item){ LOG_INFO("Mute activated" ); //update icon imageMicrophone[static_cast(microphoneState)]->setVisible(false); microphoneState = (microphoneState == AudioState::ON)?AudioState::OFF:AudioState::ON; imageMicrophone[static_cast(microphoneState)]->setVisible(true); application->refreshWindow( RefreshModes::GUI_REFRESH_FAST ); (microphoneState == AudioState::ON)? AudioServiceAPI::RoutingMute(this->application,false): AudioServiceAPI::RoutingMute(this->application,true); return true; }; } void CallWindow::destroyInterface() { AppWindow::destroyInterface(); // delete titleLabel; // delete numberLabel; // delete durationLabel; // delete imageCircleBottom; // delete imageCircleTop; // delete imageMessage; // delete rects[0]; // delete rects[1]; children.clear(); } CallWindow::~CallWindow() { } void CallWindow::setState( State state ) { this->state = state; setVisibleState(); } const CallWindow::State& CallWindow::getState() { return state; } void CallWindow::setVisibleState() { // imageMessage->setVisible(false); rects[static_cast(FocusRects::Speaker)]->setVisible(false); rects[static_cast(FocusRects::Micrphone)]->setVisible(false); durationLabel->setVisible(false); //show state of the window switch( state ) { case State::INCOMING_CALL: { bottomBar->setActive(gui::BottomBar::Side::LEFT, true ); bottomBar->setActive(gui::BottomBar::Side::CENTER, true ); bottomBar->setActive(gui::BottomBar::Side::RIGHT, true ); bottomBar->setText( gui::BottomBar::Side::LEFT, utils::localize.get("app_call_answer") ); bottomBar->setText( gui::BottomBar::Side::CENTER, utils::localize.get("app_call_message") ); bottomBar->setText( gui::BottomBar::Side::RIGHT, utils::localize.get("app_call_reject") ); durationLabel->setText(utils::localize.get("app_call_is_calling")); // imageMessage->setVisible(true); }break; case State::CALL_ENDED: { bottomBar->setActive(gui::BottomBar::Side::LEFT, false ); bottomBar->setActive(gui::BottomBar::Side::CENTER, false ); bottomBar->setActive(gui::BottomBar::Side::RIGHT, false ); // bottomBar->setText( gui::BottomBar::Side::RIGHT, utils::localize.get("app_call_return") ); // durationLabel->setText(utils::localize.get("app_call_call_ended")); }break; case State::CALL_IN_PROGRESS: { // titleLabel->setText("CALL_IN_PROGRESS"); durationLabel->setVisible(true); bottomBar->setActive(gui::BottomBar::Side::LEFT, false ); bottomBar->setActive(gui::BottomBar::Side::CENTER, false ); bottomBar->setActive(gui::BottomBar::Side::RIGHT, true ); bottomBar->setText( gui::BottomBar::Side::RIGHT, utils::localize.get("app_call_end_call") ); rects[static_cast(FocusRects::Speaker)]->setVisible(true); rects[static_cast(FocusRects::Micrphone)]->setVisible(true); imageSpeaker[static_cast(speakerState)]->setVisible(true); imageMicrophone[static_cast(microphoneState)]->setVisible(true); setFocusItem( rects[static_cast(FocusRects::Speaker)] ); }break; case State::IDLE: { // titleLabel->setText("IDLE"); }break; case State::OUTGOING_CALL: { // titleLabel->setText("OUTGOING_CALL"); bottomBar->setActive(gui::BottomBar::Side::LEFT, false ); bottomBar->setActive(gui::BottomBar::Side::CENTER, false ); bottomBar->setActive(gui::BottomBar::Side::RIGHT, true ); bottomBar->setText( gui::BottomBar::Side::RIGHT, utils::localize.get("app_call_end_call") ); }break; }; } void CallWindow::setCallNumber( std::string ) { } void CallWindow::updateDuration( uint32_t duration ) { uint32_t seconds = 0; uint32_t minutes = 0; uint32_t hours = 0; uint32_t days = 0; days = duration / 86400; duration -= days*86400; hours = duration / 3600; duration -= hours*3600; minutes = duration / 60; duration -= minutes*60; seconds = duration; std::stringstream ss; if( days ) ss<setText( ss.str()); } bool CallWindow::handleSwitchData( SwitchData* data ) { if( data == nullptr ) { LOG_ERROR("Received null pointer"); return false; } app::CallSwitchData* callData = reinterpret_cast(data); if( callData->getType() == app::CallSwitchData::Type::INCOMMING_CALL ) { app::IncommingCallData* incData = reinterpret_cast( data ); state = State::INCOMING_CALL; numberLabel->setText( incData->getPhoneNumber()); } setVisibleState(); application->refreshWindow( RefreshModes::GUI_REFRESH_FAST ); return true; } void CallWindow::onBeforeShow( ShowMode mode, uint32_t command, SwitchData* data ) { } bool CallWindow::handleLeftButton() { if( state == State::INCOMING_CALL ) { auto ret = CellularServiceAPI::AnswerIncomingCall(application); LOG_INFO("AnswerIncomingCall: %s",(ret?"OK":"FAIL")); return true; } else if( state == State::OUTGOING_CALL ) { } else if( state == State::CALL_ENDED ) { } else if( state == State::CALL_IN_PROGRESS ) { } return false; } bool CallWindow::handleCenterButton() { if( state == State::INCOMING_CALL ) { auto ret = CellularServiceAPI::HangupCall(application); LOG_INFO("HangupCall: %s",(ret?"OK":"FAIL")); //TODO switch to message templates window return true; } else if( state == State::OUTGOING_CALL ) { } else if( state == State::CALL_ENDED ) { } else if( state == State::CALL_IN_PROGRESS ) { } return false; } bool CallWindow::handleRightButton() { if( state == State::INCOMING_CALL ) { auto ret = CellularServiceAPI::HangupCall(application); LOG_INFO("HangupCall: %s",(ret?"OK":"FAIL")); return true; } else if( state == State::OUTGOING_CALL ) { auto ret = CellularServiceAPI::HangupCall(application); LOG_INFO("HangupCall: %s",(ret?"OK":"FAIL")); } // else if( state == State::CALL_ENDED ) { // //return to previous application // sapm::ApplicationManager::messageSwitchPreviousApplication( application ); // return true; // } else if( state == State::CALL_IN_PROGRESS ) { auto ret = CellularServiceAPI::HangupCall(application); LOG_INFO("HangupCall: %s",(ret?"OK":"FAIL")); return true; } return false; } bool CallWindow::onInput( const InputEvent& inputEvent ) { LOG_INFO("key code: %d", static_cast(inputEvent.keyCode)); //check if any of the lower inheritance onInput methods catch the event bool ret = AppWindow::onInput( inputEvent ); if( ret ) { //refresh window only when key is other than enter if( inputEvent.keyCode != KeyCode::KEY_ENTER ) application->render( RefreshModes::GUI_REFRESH_FAST ); return true; } bool handled = false; //process only if key is released if( inputEvent.state != InputEvent::State::keyReleasedShort ) { if( inputEvent.keyCode == KeyCode::KEY_ENTER ) { handled = handleCenterButton(); } else if( inputEvent.keyCode == KeyCode::KEY_LF ) { handled = handleLeftButton(); } else if( inputEvent.keyCode == KeyCode::KEY_RF ) { handled = handleRightButton(); } } if( handled ) application->refreshWindow( RefreshModes::GUI_REFRESH_FAST); return false; } } /* namespace gui */