blob: 90241d550d7708663298d9d38b126da76dbb70ff [file] [log] [blame]
atraczyke9919eb2016-09-15 15:58:18 -04001/**************************************************************************
2* Copyright (C) 2016 by Savoir-faire Linux *
3* Author: Jäger Nicolas <nicolas.jager@savoirfairelinux.com> *
4* Author: Traczyk Andreas <andreas.traczyk@savoirfairelinux.com> *
5* *
6* This program is free software; you can redistribute it and/or modify *
7* it under the terms of the GNU General Public License as published by *
8* the Free Software Foundation; either version 3 of the License, or *
9* (at your option) any later version. *
10* *
11* This program is distributed in the hope that it will be useful, *
12* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14* GNU General Public License for more details. *
15* *
16* You should have received a copy of the GNU General Public License *
17* along with this program. If not, see <http://www.gnu.org/licenses/>. *
18**************************************************************************/
Nicolas Jagere069c412016-08-15 15:00:17 -040019#include "pch.h"
20
21#include "VideoPage.xaml.h"
22
atraczyk14ba30c2016-09-22 18:31:59 -040023#include <MemoryBuffer.h> // IMemoryBufferByteAccess
24
Nicolas Jagere069c412016-08-15 15:00:17 -040025using namespace RingClientUWP::Views;
Nicolas Jagerc551c362016-10-01 19:24:50 -040026using namespace ViewModel;
atraczyk14ba30c2016-09-22 18:31:59 -040027using namespace Video;
Nicolas Jagere069c412016-08-15 15:00:17 -040028
29using namespace Concurrency;
30using namespace Platform;
31using namespace Windows::Devices::Enumeration;
32using namespace Windows::Foundation;
33using namespace Windows::Foundation::Collections;
34using namespace Windows::UI::Xaml;
35using namespace Windows::UI::Xaml::Controls;
36using namespace Windows::UI::Xaml::Controls::Primitives;
37using namespace Windows::UI::Xaml::Data;
38using namespace Windows::UI::Xaml::Input;
39using namespace Windows::UI::Xaml::Media;
40using namespace Windows::UI::Xaml::Navigation;
41using namespace Windows::Media::Capture;
atraczyke9919eb2016-09-15 15:58:18 -040042using namespace Windows::ApplicationModel::Core;
43using namespace Windows::UI::Core;
Nicolas Jagere069c412016-08-15 15:00:17 -040044
atraczyk14ba30c2016-09-22 18:31:59 -040045using namespace Windows::Graphics::Display;
46using namespace Windows::Graphics::Imaging;
47using namespace Windows::Media;
48using namespace Windows::UI::Xaml::Media::Imaging;
49using namespace Windows::Media::Capture;
50using namespace Windows::Devices::Sensors;
51
Nicolas Jagere069c412016-08-15 15:00:17 -040052VideoPage::VideoPage()
53{
54 InitializeComponent();
atraczyk14ba30c2016-09-22 18:31:59 -040055
56 VideoManager::instance->captureManager()->displayInformation = DisplayInformation::GetForCurrentView();
57 VideoManager::instance->captureManager()->EnumerateWebcamsAsync();
58
59 Page::NavigationCacheMode = Navigation::NavigationCacheMode::Required;
60
61 VideoManager::instance->rendererManager()->writeVideoFrame +=
62 ref new WriteVideoFrame([this](String^ id, uint8_t* buf, int width, int height)
63 {
Nicolas Jager9edbea32016-10-03 09:13:53 -040064 CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::High,
atraczyk14ba30c2016-09-22 18:31:59 -040065 ref new DispatchedHandler([=]() {
66 try {
67 if (!VideoManager::instance->rendererManager()->renderers->Size)
68 return;
69 VideoManager::instance->rendererManager()->renderer(id)->isRendering = true;
70 create_task(WriteFrameAsSoftwareBitmapAsync(id, buf, width, height))
Nicolas Jager9edbea32016-10-03 09:13:53 -040071 .then([=](task<void> previousTask) {
atraczyk14ba30c2016-09-22 18:31:59 -040072 try {
73 previousTask.get();
74 }
75 catch (Platform::Exception^ e) {
76 WriteLine( "Caught exception from previous task.\n" );
77 }
78 });
79 }
80 catch(Platform::COMException^ e) {
81 WriteLine(e->ToString());
82 }
83 }));
84 });
85
86 VideoManager::instance->captureManager()->startPreviewing +=
87 ref new StartPreviewing([this]()
88 {
89 PreviewImage->Visibility = Windows::UI::Xaml::Visibility::Visible;
90 PreviewImage->FlowDirection = VideoManager::instance->captureManager()->mirroringPreview ?
Nicolas Jager9edbea32016-10-03 09:13:53 -040091 Windows::UI::Xaml::FlowDirection::RightToLeft :
92 Windows::UI::Xaml::FlowDirection::LeftToRight;
atraczyk14ba30c2016-09-22 18:31:59 -040093 });
94
95 VideoManager::instance->captureManager()->stopPreviewing +=
96 ref new StopPreviewing([this]()
97 {
98 PreviewImage->Source = nullptr;
99 PreviewImage->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
100 });
101
102 VideoManager::instance->captureManager()->getSink +=
103 ref new GetSink([this]()
104 {
105 return PreviewImage;
106 });
107
108 VideoManager::instance->rendererManager()->clearRenderTarget +=
109 ref new ClearRenderTarget([this]()
110 {
111 IncomingVideoImage->Source = nullptr;
112 });
113
114 RingD::instance->incomingAccountMessage +=
115 ref new IncomingAccountMessage([&](String^ accountId, String^ from, String^ payload)
116 {
117 scrollDown();
118 });
119
120 RingD::instance->stateChange +=
121 ref new StateChange([&](String^ callId, CallStatus state, int code)
122 {
123 if (state == CallStatus::ENDED) {
124 Video::VideoManager::instance->rendererManager()->raiseClearRenderTarget();
125 }
126 });
127
Nicolas Jager8f805cd2016-10-05 11:54:40 -0400128 RingD::instance->incomingMessage += ref new RingClientUWP::IncomingMessage(this, &RingClientUWP::Views::VideoPage::OnincomingMessage);
Nicolas Jagere069c412016-08-15 15:00:17 -0400129}
130
atraczyke9919eb2016-09-15 15:58:18 -0400131void
132RingClientUWP::Views::VideoPage::OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e)
133{
134 updatePageContent();
135}
Nicolas Jagere069c412016-08-15 15:00:17 -0400136
atraczyke9919eb2016-09-15 15:58:18 -0400137void RingClientUWP::Views::VideoPage::updatePageContent()
138{
Nicolas Jagerc551c362016-10-01 19:24:50 -0400139 auto item = SmartPanelItemsViewModel::instance->_selectedItem;
140 auto contact = (item) ? item->_contact : nullptr;
141
atraczyke9919eb2016-09-15 15:58:18 -0400142 if (!contact)
143 return;
144
145 _callee_->Text = contact->name_;
atraczyk5c395ea2016-09-20 17:28:09 -0400146
147 _messagesList_->ItemsSource = contact->_conversation->_messages;
148
149 scrollDown();
150}
151
152void RingClientUWP::Views::VideoPage::scrollDown()
153{
154 _scrollView_->UpdateLayout();
155 _scrollView_->ScrollToVerticalOffset(_scrollView_->ScrollableHeight);
156}
157
158void
159RingClientUWP::Views::VideoPage::_sendBtn__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
160{
161 sendMessage();
162}
163
164void
165RingClientUWP::Views::VideoPage::_messageTextBox__KeyDown(Platform::Object^ sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e)
166{
167 if (e->Key == Windows::System::VirtualKey::Enter) {
168 sendMessage();
169 }
170}
171
172void
173RingClientUWP::Views::VideoPage::sendMessage()
174{
Nicolas Jagerc551c362016-10-01 19:24:50 -0400175 auto item = SmartPanelItemsViewModel::instance->_selectedItem;
176 auto contact = item->_contact;
177
atraczyk5c395ea2016-09-20 17:28:09 -0400178 auto txt = _messageTextBox_->Text;
179
180 /* empty the textbox */
181 _messageTextBox_->Text = "";
182
183 if (!contact || txt->IsEmpty())
184 return;
185
atraczyk11e7baf2016-10-05 13:08:08 -0400186 RingD::instance->sendSIPTextMessage(txt);
atraczyk5c395ea2016-09-20 17:28:09 -0400187 scrollDown();
atraczyke9919eb2016-09-15 15:58:18 -0400188}
Nicolas Jagere069c412016-08-15 15:00:17 -0400189
190void RingClientUWP::Views::VideoPage::Button_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
191{
192}
193
194
195void RingClientUWP::Views::VideoPage::_btnCancel__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
196{
197
198}
199
200void RingClientUWP::Views::VideoPage::_btnHangUp__Tapped(Platform::Object^ sender, Windows::UI::Xaml::Input::TappedRoutedEventArgs^ e)
201{
Nicolas Jagerc551c362016-10-01 19:24:50 -0400202 auto item = SmartPanelItemsViewModel::instance->_selectedItem;
Nicolas Jager083b3ae2016-10-04 08:46:19 -0400203 RingD::instance->hangUpCall2(item->_callId);
Nicolas Jager9edbea32016-10-03 09:13:53 -0400204
Nicolas Jagere069c412016-08-15 15:00:17 -0400205 pressHangUpCall();
206}
207
208
209void RingClientUWP::Views::VideoPage::_btnPause__Tapped(Platform::Object^ sender, Windows::UI::Xaml::Input::TappedRoutedEventArgs^ e)
210{
211 pauseCall();
212}
213
214
215void RingClientUWP::Views::VideoPage::_btnChat__Tapped(Platform::Object^ sender, Windows::UI::Xaml::Input::TappedRoutedEventArgs^ e)
216{
atraczyk5c395ea2016-09-20 17:28:09 -0400217 chatOpen = !chatOpen;
218 if (chatOpen) {
219 _rowChatBx_->Height = 200;
220 chatPanelCall();
221 }
222 else {
223 _rowChatBx_->Height = 0;
224 }
Nicolas Jagere069c412016-08-15 15:00:17 -0400225}
226
227
228void RingClientUWP::Views::VideoPage::_btnAddFriend__Tapped(Platform::Object^ sender, Windows::UI::Xaml::Input::TappedRoutedEventArgs^ e)
229{
230 addContactCall();
231}
232
233
234void RingClientUWP::Views::VideoPage::_btnSwitch__Tapped(Platform::Object^ sender, Windows::UI::Xaml::Input::TappedRoutedEventArgs^ e)
235{
236 transferCall();
237}
238
239
240void RingClientUWP::Views::VideoPage::_btnMicrophone__Tapped(Platform::Object^ sender, Windows::UI::Xaml::Input::TappedRoutedEventArgs^ e)
241{
242 switchMicrophoneStateCall();
243}
244
245
246void RingClientUWP::Views::VideoPage::_btnMemo__Tapped(Platform::Object^ sender, Windows::UI::Xaml::Input::TappedRoutedEventArgs^ e)
247{
248 reccordVideoCall();
249}
250
251
252void RingClientUWP::Views::VideoPage::_btnHQ__Tapped(Platform::Object^ sender, Windows::UI::Xaml::Input::TappedRoutedEventArgs^ e)
253{
254 qualityVideoLevelCall();
255}
256
257
258void RingClientUWP::Views::VideoPage::_btnVideo__Tapped(Platform::Object^ sender, Windows::UI::Xaml::Input::TappedRoutedEventArgs^ e)
259{
260 switchVideoStateCall();
261}
262
263
264void RingClientUWP::Views::VideoPage::_videoControl__PointerMoved(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e)
265{
266 if (barFading)
267 myStoryboard->Begin();
268 barFading_ = true;
269}
270
271
272void RingClientUWP::Views::VideoPage::btnAny_entered(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e)
273{
274 barFading_ = false;
275 myStoryboard->Stop();
276}
277
278
279void RingClientUWP::Views::VideoPage::btnAny_exited(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e)
280{
281 barFading_ = true;
atraczyk14ba30c2016-09-22 18:31:59 -0400282}
283
284task<void>
285VideoPage::WriteFrameAsSoftwareBitmapAsync(String^ id, uint8_t* buf, int width, int height)
286{
287 auto vframe = ref new VideoFrame(BitmapPixelFormat::Bgra8, width, height);
288 auto frame = vframe->SoftwareBitmap;
289
290 const int BYTES_PER_PIXEL = 4;
291
292 BitmapBuffer^ buffer = frame->LockBuffer(BitmapBufferAccessMode::ReadWrite);
293 IMemoryBufferReference^ reference = buffer->CreateReference();
294
295 Microsoft::WRL::ComPtr<IMemoryBufferByteAccess> byteAccess;
296 if (SUCCEEDED(reinterpret_cast<IUnknown*>(reference)->QueryInterface(IID_PPV_ARGS(&byteAccess))))
297 {
298 byte* data;
299 unsigned capacity;
300 byteAccess->GetBuffer(&data, &capacity);
301
302 auto desc = buffer->GetPlaneDescription(0);
303
304 for (int row = 0; row < desc.Height; row++)
305 {
306 for (int col = 0; col < desc.Width; col++)
307 {
308 auto currPixel = desc.StartIndex + desc.Stride * row + BYTES_PER_PIXEL * col;
309
310 data[currPixel + 0] = buf[currPixel + 0];
311 data[currPixel + 1] = buf[currPixel + 1];
312 data[currPixel + 2] = buf[currPixel + 2];
313 }
314 }
315 }
316 delete reference;
317 delete buffer;
318
319 VideoManager::instance->rendererManager()->renderer(id)->isRendering = false;
320
321 auto sbSource = ref new Media::Imaging::SoftwareBitmapSource();
322 return create_task(sbSource->SetBitmapAsync(frame))
Nicolas Jager9edbea32016-10-03 09:13:53 -0400323 .then([this, sbSource]()
atraczyk14ba30c2016-09-22 18:31:59 -0400324 {
325 try {
326 IncomingVideoImage->Source = sbSource;
327 }
328 catch (Exception^ e) {
329 WriteException(e);
330 }
331 });
332}
Nicolas Jager8f805cd2016-10-05 11:54:40 -0400333
334
335void RingClientUWP::Views::VideoPage::OnincomingMessage(Platform::String ^callId, Platform::String ^from, Platform::String ^payload)
336{
337 scrollDown();
338}