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="&#xE767;"
+                               Text="&#xE769;"
                                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