From cba46f79f7111bdedac9fc8e74af7c067affb9d7 Mon Sep 17 00:00:00 2001 From: Nicolas Jager <nicolas.jager@savoirfairelinux.com> Date: Fri, 2 Dec 2016 16:04:50 -0500 Subject: [PATCH] call : adds pause and multiple calls managment. - adds pause/unpause logic for calls and ui. - allows to make several calls at the same time. Change-Id: If5dbcb64b12c445b38474f8d959a0b492d7b6812 Tuleap: #790 --- Globals.h | 1 + MainPage.xaml.cpp | 31 +++++++++++++--- MainPage.xaml.h | 1 + RingD.cpp | 89 ++++++++++++++++++++++++++++++--------------- RingD.h | 5 +++ RingDebug.h | 4 +- SmartPanel.xaml.cpp | 46 ++++++++++++++++++----- SmartPanel.xaml.h | 1 + VideoPage.xaml | 6 +-- VideoPage.xaml.cpp | 59 +++++++++++++++++++++++++++--- VideoPage.xaml.h | 3 ++ 11 files changed, 192 insertions(+), 54 deletions(-) diff --git a/Globals.h b/Globals.h index 0aeb0b4..957c1a2 100644 --- a/Globals.h +++ b/Globals.h @@ -8,6 +8,7 @@ public enum class CallStatus { SEARCHING, IN_PROGRESS, PAUSED, + PEER_PAUSED, ENDED, TERMINATING }; diff --git a/MainPage.xaml.cpp b/MainPage.xaml.cpp index 6cac721..13b692c 100644 --- a/MainPage.xaml.cpp +++ b/MainPage.xaml.cpp @@ -88,12 +88,13 @@ MainPage::MainPage() ref new WindowVisibilityChangedEventHandler(this, &MainPage::Application_VisibilityChanged); applicationSuspendingEventToken = Application::Current->Suspending += - ref new SuspendingEventHandler(this, &MainPage::Application_Suspending); + ref new SuspendingEventHandler(this, &MainPage::Application_Suspending); applicationResumingEventToken = Application::Current->Resuming += - ref new EventHandler<Object^>(this, &MainPage::Application_Resuming); + ref new EventHandler<Object^>(this, &MainPage::Application_Resuming); RingD::instance->registrationStateErrorGeneric += ref new RingClientUWP::RegistrationStateErrorGeneric(this, &RingClientUWP::MainPage::OnregistrationStateErrorGeneric); RingD::instance->registrationStateRegistered += ref new RingClientUWP::RegistrationStateRegistered(this, &RingClientUWP::MainPage::OnregistrationStateRegistered); + RingD::instance->callPlaced += ref new RingClientUWP::CallPlaced(this, &RingClientUWP::MainPage::OncallPlaced); } void @@ -160,10 +161,10 @@ RingClientUWP::MainPage::showLoadingOverlay(bool load, bool modal) TimeSpan delay; delay.Duration = 10000 * 50; ThreadPoolTimer^ delayTimer = ThreadPoolTimer::CreateTimer( - ref new TimerElapsedHandler([this](ThreadPoolTimer^ source) + ref new TimerElapsedHandler([this](ThreadPoolTimer^ source) { Dispatcher->RunAsync(CoreDispatcherPriority::High, - ref new DispatchedHandler([this]() + ref new DispatchedHandler([this]() { OnResize(nullptr, nullptr); })); @@ -255,7 +256,21 @@ void RingClientUWP::MainPage::OnhidePreviewPage() void RingClientUWP::MainPage::OnsummonVideoPage() { - auto videoPage = dynamic_cast<VideoPage^>(_videoFrame_->Content); + auto item = SmartPanelItemsViewModel::instance->_selectedItem; + auto videoPage = dynamic_cast<VideoPage^>(_videoFrame_->Content);; + + if (item) { + switch (item->_callStatus) { + case CallStatus::IN_PROGRESS: + videoPage->screenVideo(true); + break; + case CallStatus::PEER_PAUSED: + case CallStatus::PAUSED: + videoPage->screenVideo(false); + break; + } + } + videoPage->chatOpen = false; videoPage->updatePageContent(); showFrame(_videoFrame_); @@ -460,3 +475,9 @@ void RingClientUWP::MainPage::OnregistrationStateRegistered() { showLoadingOverlay(false, false); } + + +void RingClientUWP::MainPage::OncallPlaced(Platform::String ^callId) +{ + showFrame(_welcomeFrame_); +} diff --git a/MainPage.xaml.h b/MainPage.xaml.h index 6c9b433..40ad098 100644 --- a/MainPage.xaml.h +++ b/MainPage.xaml.h @@ -80,5 +80,6 @@ private: void OncloseMessageTextPage(); void OnregistrationStateErrorGeneric(const std::string& accountId); void OnregistrationStateRegistered(); + void OncallPlaced(Platform::String ^callId); }; } diff --git a/RingD.cpp b/RingD.cpp index 928ac97..4d5ff8a 100644 --- a/RingD.cpp +++ b/RingD.cpp @@ -246,39 +246,31 @@ void RingClientUWP::RingD::acceptIncommingCall(String^ callId) void RingClientUWP::RingD::placeCall(Contact^ contact) { MSG_("!--->> placeCall"); - auto to = contact->ringID_; - String^ accountId; if (contact->_accountIdAssociated->IsEmpty()) { - accountId = AccountListItemsViewModel::instance->_selectedItem->_account->accountID_; MSG_("adding account id to contact"); - contact->_accountIdAssociated = accountId; + contact->_accountIdAssociated = AccountListItemsViewModel::instance->_selectedItem->_account->accountID_; } - else { - accountId = contact->_accountIdAssociated; - } - - auto to2 = Utils::toString(to); - auto accountId2 = Utils::toString(accountId); - - auto callId2 = DRing::placeCall(accountId2, to2); - if (callId2.empty()) { - WNG_("call not created, the daemon didn't return a call Id"); - return; - } - - auto callId = Utils::toPlatformString(callId2); - - _callIdsList->Append(callId); + auto task = ref new RingD::Task(Request::PlaceCall); + task->_accountId_new = Utils::toString(contact->_accountIdAssociated); + task->_ringId_new = Utils::toString(contact->ringID_); + tasksList_.push(task); - //auto con = ContactsViewModel::instance->findContactByName(to); - auto item = SmartPanelItemsViewModel::instance->findItem(contact); - item->_callId = callId; - MSG_("$1 place call with id : " + Utils::toString(item->_callId)); +} - callPlaced(callId); +void RingClientUWP::RingD::pauseCall(const std::string & callId) +{ + auto task = ref new RingD::Task(Request::PauseCall); + task->_callid_new = callId; + tasksList_.push(task); +} +void RingClientUWP::RingD::unPauseCall(const std::string & callId) +{ + auto task = ref new RingD::Task(Request::UnPauseCall); + task->_callid_new = callId; + tasksList_.push(task); } void RingClientUWP::RingD::cancelOutGoingCall2(String ^ callId) @@ -294,13 +286,13 @@ void RingClientUWP::RingD::hangUpCall2(String ^ callId) tasksList_.push(ref new RingD::Task(Request::HangUpCall, callId)); } -void RingClientUWP::RingD::pauseCall(String ^ callId) +void RingClientUWP::RingD::pauseCall(String ^ callId) // do not use it, rm during refacto { MSG_("$1 pauseCall : " + Utils::toString(callId)); tasksList_.push(ref new RingD::Task(Request::PauseCall, callId)); } -void RingClientUWP::RingD::unPauseCall(String ^ callId) +void RingClientUWP::RingD::unPauseCall(String ^ callId) // do not use it, rm during refacto { MSG_("$1 unPauseCall : " + Utils::toString(callId)); tasksList_.push(ref new RingD::Task(Request::UnPauseCall, callId)); @@ -409,6 +401,24 @@ RingD::registerCallbacks() } })); }), + DRing::exportable_callback<DRing::CallSignal::PeerHold>([this]( + const std::string& callId, + bool state) + { + // why this cllaback exist ? why are we not using stateChange ? + MSG_("<PeerHold>"); + MSG_("callId = " + callId); + MSG_("state = " + Utils::toString(state.ToString())); + + CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync( + CoreDispatcherPriority::High, ref new DispatchedHandler([=]() + { + if (state) + stateChange(Utils::toPlatformString(callId), CallStatus::PEER_PAUSED, 0); + else + stateChange(Utils::toPlatformString(callId), CallStatus::IN_PROGRESS, 0); + })); + }), DRing::exportable_callback<DRing::CallSignal::StateChange>([this]( const std::string& callId, const std::string& state, @@ -829,6 +839,21 @@ RingD::dequeueTasks() switch (request) { case Request::None: break; + case Request::PlaceCall: + { + auto callId = DRing::placeCall(task->_accountId_new, task->_ringId_new); + CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::High, + ref new DispatchedHandler([=]() { + + auto contact = ContactsViewModel::instance->findContactByRingId(Utils::toPlatformString(task->_ringId_new)); + auto item = SmartPanelItemsViewModel::instance->findItem(contact); + item->_callId = Utils::toPlatformString(callId); + //MSG_("$1 place call with id : " + Utils::toString(item->_callId)); + + callPlaced(Utils::toPlatformString(callId)); + + })); + } case Request::AddRingAccount: { std::map<std::string, std::string> ringAccountDetails; @@ -887,12 +912,12 @@ RingD::dequeueTasks() break; case Request::PauseCall: { - DRing::hold(Utils::toString(task->_callId)); + DRing::hold(task->_callid_new); } break; case Request::UnPauseCall: { - DRing::unhold(Utils::toString(task->_callId)); + DRing::unhold(task->_callid_new); } break; case Request::RegisterDevice: @@ -1161,6 +1186,12 @@ RingClientUWP::CallStatus RingClientUWP::RingD::translateCallStatus(String^ stat if (state == "CONNECTING") return CallStatus::SEARCHING; + if (state == "HOLD") + return CallStatus::PAUSED; + + if (state == "PEER_PAUSED") + return CallStatus::PEER_PAUSED; + return CallStatus::NONE; } diff --git a/RingD.h b/RingD.h index 28b0f75..39bed58 100644 --- a/RingD.h +++ b/RingD.h @@ -109,6 +109,8 @@ internal: void refuseIncommingCall(String^ call); void acceptIncommingCall(String^ call); void placeCall(Contact^ contact); + void pauseCall(const std::string& callId); + void unPauseCall(const std::string& callId); /*void cancelOutGoingCall2(String^ callId);*/ // marche pas CallStatus translateCallStatus(String^ state); String^ getUserName(); @@ -163,6 +165,7 @@ private: RefuseIncommingCall, AcceptIncommingCall, CancelOutGoingCall, + PlaceCall, HangUpCall, PauseCall, UnPauseCall, @@ -217,6 +220,8 @@ private: std::string _accountId_new; std::string _password_new; std::string _publicUsername_new; + std::string _callid_new; + std::string _ringId_new; }; /* functions */ diff --git a/RingDebug.h b/RingDebug.h index 9f3ec26..a7d4951 100644 --- a/RingDebug.h +++ b/RingDebug.h @@ -52,9 +52,9 @@ public: internal: enum class Type { DMN, MSG, WNG, ERR }; void print(const std::string& message, const Type& type, - std::string file, int line); + std::string file, int line); void print(String^ message, const Type& type, - std::string file, int line); + std::string file, int line); void print(Exception^ e, std::string file, int line); /* event */ diff --git a/SmartPanel.xaml.cpp b/SmartPanel.xaml.cpp index f546ef2..4233325 100644 --- a/SmartPanel.xaml.cpp +++ b/SmartPanel.xaml.cpp @@ -80,7 +80,7 @@ SmartPanel::SmartPanel() auto uri = ref new Windows::Foundation::Uri(image_path); _selectedAccountAvatar_->ImageSource = ref new BitmapImage(uri); }); - ContactsViewModel::instance->contactDataModified += ref new ContactDataModified([this](Contact^ contact){ + ContactsViewModel::instance->contactDataModified += ref new ContactDataModified([this](Contact^ contact) { }); AccountsViewModel::instance->updateScrollView += ref new UpdateScrollView([this]() { _accountsListScrollView_->UpdateLayout(); @@ -129,6 +129,13 @@ SmartPanel::SmartPanel() summonVideoPage(); break; } + case CallStatus::PEER_PAUSED: + case CallStatus::PAUSED: + { + _smartList_->SelectedItem = item; + summonVideoPage(); + break; + } default: break; } @@ -152,6 +159,7 @@ SmartPanel::SmartPanel() }); RingD::instance->registrationStateErrorGeneric += ref new RingClientUWP::RegistrationStateErrorGeneric(this, &RingClientUWP::Views::SmartPanel::OnregistrationStateErrorGeneric); RingD::instance->registrationStateRegistered += ref new RingClientUWP::RegistrationStateRegistered(this, &RingClientUWP::Views::SmartPanel::OnregistrationStateRegistered); + RingD::instance->callPlaced += ref new RingClientUWP::CallPlaced(this, &RingClientUWP::Views::SmartPanel::OncallPlaced); } void @@ -389,7 +397,9 @@ SmartPanel::_smartList__SelectionChanged(Platform::Object^ sender, Windows::UI:: auto contact = item->_contact; - if (item->_callStatus == CallStatus::IN_PROGRESS) { + if (item->_callStatus == CallStatus::IN_PROGRESS + || item->_callStatus == CallStatus::PAUSED + || item->_callStatus == CallStatus::PEER_PAUSED) { if (contact) { contact->_unreadMessages = 0; ContactsViewModel::instance->saveContactsToFile(); @@ -480,6 +490,11 @@ RingClientUWP::Views::SmartPanel::_acceptIncomingCallBtn__Click(Platform::Object auto item = dynamic_cast<SmartPanelItem^>(button->DataContext); if (item) { auto callId = item->_callId; + + for (auto it : SmartPanelItemsViewModel::instance->itemsList) + if (it->_callStatus != CallStatus::IN_PROGRESS) + RingD::instance->pauseCall(Utils::toString(it->_callId)); + RingD::instance->acceptIncommingCall(callId); } } @@ -497,7 +512,13 @@ SmartPanel::_callContact__Click(Platform::Object^ sender, Windows::UI::Xaml::Rou if (item) { auto contact = item->_contact; if (contact) + { + for (auto it : SmartPanelItemsViewModel::instance->itemsList) + if (it->_callStatus == CallStatus::IN_PROGRESS) + RingD::instance->pauseCall(Utils::toString(it->_callId)); + RingD::instance->placeCall(contact); + } } } } @@ -528,14 +549,14 @@ void RingClientUWP::Views::SmartPanel::Grid_PointerEntered(Platform::Object^ sen /// item->_hovered = Windows::UI::Xaml::Visibility::Visible; /// for now use this, do not merge with the for loop above, to make easier to remove that part later - bool anyCall = false; + /*bool anyCall = false; for (auto it : SmartPanelItemsViewModel::instance->itemsList) { if (it->_callStatus != CallStatus::NONE && it->_callStatus != CallStatus::ENDED) anyCall = true; } - if (anyCall == false) - item->_hovered = Windows::UI::Xaml::Visibility::Visible; + if (anyCall == false)*/ + item->_hovered = Windows::UI::Xaml::Visibility::Visible; } @@ -1194,7 +1215,7 @@ RingClientUWP::Views::SmartPanel::_selectedAccountAvatarContainer__PointerReleas std::string profilePath = RingD::instance->getLocalFolder() + ".profile"; _mkdir(profilePath.c_str()); std::ofstream file((profilePath + "\\profile_image.png"), - std::ios::out | std::ios::trunc | std::ios::binary); + std::ios::out | std::ios::trunc | std::ios::binary); if (file.is_open()) { file << fileBuffer; file.close(); @@ -1237,14 +1258,14 @@ void RingClientUWP::Views::SmartPanel::Grid_PointerMoved(Platform::Object^ sende /// item->_hovered = Windows::UI::Xaml::Visibility::Visible; /// for now use this, do not merge with the for loop above, to make easier to remove that part later - bool anyCall = false; + /*bool anyCall = false; for (auto it : SmartPanelItemsViewModel::instance->itemsList) { if (it->_callStatus != CallStatus::NONE && it->_callStatus != CallStatus::ENDED) anyCall = true; } - if (anyCall == false) - item->_hovered = Windows::UI::Xaml::Visibility::Visible; + if (anyCall == false)*/ + item->_hovered = Windows::UI::Xaml::Visibility::Visible; } @@ -1681,4 +1702,9 @@ void RingClientUWP::Views::SmartPanel::_PINTextBox__GotFocus(Platform::Object^ s void RingClientUWP::Views::SmartPanel::OnregistrationStateRegistered() { _addAccountNo__Click(nullptr, nullptr); -} \ No newline at end of file +} + +void RingClientUWP::Views::SmartPanel::OncallPlaced(Platform::String ^callId) +{ + _smartList_->SelectedItem = nullptr; +} diff --git a/SmartPanel.xaml.h b/SmartPanel.xaml.h index 18981b1..be2ef33 100644 --- a/SmartPanel.xaml.h +++ b/SmartPanel.xaml.h @@ -170,6 +170,7 @@ private: void OnregistrationStateErrorGeneric(const std::string& accountId); void _PINTextBox__GotFocus(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); void OnregistrationStateRegistered(); + void OncallPlaced(Platform::String ^callId); }; } } diff --git a/VideoPage.xaml b/VideoPage.xaml index 1f7a6df..b78265f 100644 --- a/VideoPage.xaml +++ b/VideoPage.xaml @@ -174,9 +174,9 @@ <Image Name="IncomingVideoImage" Grid.Column="0" Canvas.ZIndex="-1"/> - <TextBlock Name="_MutedVideoIcon_" + <TextBlock Name="_callPaused_" Grid.Column="0" - Text="" + Text="" Foreground="White" FontSize="200" VerticalAlignment="Center" @@ -299,7 +299,7 @@ <Button x:Name="_btnPause_" PointerEntered="btnAny_entered" PointerExited="btnAny_exited" - Tapped="_btnPause__Tapped" Visibility="Collapsed"> + Tapped="_btnPause__Tapped"> <SymbolIcon Symbol="Pause"/> </Button> <Button x:Name="_btnChat_" diff --git a/VideoPage.xaml.cpp b/VideoPage.xaml.cpp index d8342d9..0b6b7db 100644 --- a/VideoPage.xaml.cpp +++ b/VideoPage.xaml.cpp @@ -122,13 +122,34 @@ VideoPage::VideoPage() RingD::instance->stateChange += ref new StateChange([&](String^ callId, CallStatus state, int code) { - if (state == CallStatus::ENDED) { + switch (state) { + case CallStatus::IN_PROGRESS: + { + for (auto it : SmartPanelItemsViewModel::instance->itemsList) + if (it->_callStatus != CallStatus::IN_PROGRESS && it->_callId != callId) + RingD::instance->pauseCall(Utils::toString(it->_callId)); + + _callPaused_->Visibility = Windows::UI::Xaml::Visibility::Collapsed; + IncomingVideoImage->Visibility = Windows::UI::Xaml::Visibility::Visible; +// PreviewImage->Visibility = Windows::UI::Xaml::Visibility::Visible; + break; + } + case CallStatus::ENDED: Video::VideoManager::instance->rendererManager()->raiseClearRenderTarget(); + break; + case CallStatus::PEER_PAUSED: + case CallStatus::PAUSED: + _callPaused_->Visibility = Windows::UI::Xaml::Visibility::Visible; + IncomingVideoImage->Visibility = Windows::UI::Xaml::Visibility::Collapsed; +// PreviewImage->Visibility = Windows::UI::Xaml::Visibility::Collapsed; + break; } }); RingD::instance->incomingMessage += ref new RingClientUWP::IncomingMessage(this, &RingClientUWP::Views::VideoPage::OnincomingMessage); RingD::instance->incomingVideoMuted += ref new RingClientUWP::IncomingVideoMuted(this, &RingClientUWP::Views::VideoPage::OnincomingVideoMuted); + VideoManager::instance->captureManager()->startPreviewing += ref new RingClientUWP::StartPreviewing(this, &RingClientUWP::Views::VideoPage::OnstartPreviewing); + VideoManager::instance->captureManager()->stopPreviewing += ref new RingClientUWP::StopPreviewing(this, &RingClientUWP::Views::VideoPage::OnstopPreviewing); } void @@ -159,6 +180,22 @@ void RingClientUWP::Views::VideoPage::scrollDown() _scrollView_->ScrollToVerticalOffset(_scrollView_->ScrollableHeight); } +void RingClientUWP::Views::VideoPage::screenVideo(bool state) +{ + if (state) { + Video::VideoManager::instance->rendererManager()->raiseClearRenderTarget(); + _callPaused_->Visibility = Windows::UI::Xaml::Visibility::Collapsed; + IncomingVideoImage->Visibility = Windows::UI::Xaml::Visibility::Visible; + PreviewImage->Visibility = Windows::UI::Xaml::Visibility::Visible; + } else { + _callPaused_->Visibility = Windows::UI::Xaml::Visibility::Visible; + IncomingVideoImage->Visibility = Windows::UI::Xaml::Visibility::Collapsed; + PreviewImage->Visibility = Windows::UI::Xaml::Visibility::Collapsed; + } + + +} + void RingClientUWP::Views::VideoPage::_sendBtn__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) { @@ -212,11 +249,11 @@ void RingClientUWP::Views::VideoPage::_btnHangUp__Tapped(Platform::Object^ sende void RingClientUWP::Views::VideoPage::_btnPause__Tapped(Platform::Object^ sender, Windows::UI::Xaml::Input::TappedRoutedEventArgs^ e) { - /*auto item = SmartPanelItemsViewModel::instance->_selectedItem; + auto item = SmartPanelItemsViewModel::instance->_selectedItem; if (item->_callStatus == CallStatus::IN_PROGRESS) - RingD::instance->pauseCall(item->_callId); + RingD::instance->pauseCall(Utils::toString(item->_callId)); else if (item->_callStatus == CallStatus::PAUSED) - RingD::instance->unPauseCall(item->_callId);*/ + RingD::instance->unPauseCall(Utils::toString(item->_callId)); pauseCall(); } @@ -373,7 +410,7 @@ void RingClientUWP::Views::VideoPage::_btnVideo__Click(Platform::Object^ sender, void RingClientUWP::Views::VideoPage::OnincomingVideoMuted(Platform::String ^callId, bool state) { - /*_MutedVideoIcon_->Visibility = (state) + /*_callPaused_->Visibility = (state) ? Windows::UI::Xaml::Visibility::Visible : Windows::UI::Xaml::Visibility::Collapsed;*/ @@ -381,3 +418,15 @@ void RingClientUWP::Views::VideoPage::OnincomingVideoMuted(Platform::String ^cal ? Windows::UI::Xaml::Visibility::Collapsed : Windows::UI::Xaml::Visibility::Visible; } + + +void RingClientUWP::Views::VideoPage::OnstartPreviewing() +{ + PreviewImage->Visibility = Windows::UI::Xaml::Visibility::Visible; +} + + +void RingClientUWP::Views::VideoPage::OnstopPreviewing() +{ + PreviewImage->Visibility = Windows::UI::Xaml::Visibility::Collapsed; +} diff --git a/VideoPage.xaml.h b/VideoPage.xaml.h index ef4cb8b..210e83c 100644 --- a/VideoPage.xaml.h +++ b/VideoPage.xaml.h @@ -76,6 +76,7 @@ public: } void scrollDown(); + void screenVideo(bool state); protected: virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override; @@ -119,6 +120,8 @@ private: void OnincomingMessage(Platform::String ^callId, Platform::String ^payload); void _btnVideo__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); void OnincomingVideoMuted(Platform::String ^callId, bool state); + void OnstartPreviewing(); + void OnstopPreviewing(); }; } } \ No newline at end of file -- GitLab