blob: 0ead73b69af89e3f97b44da0f56ea3df9f4f9496 [file] [log] [blame]
Sébastien Blin1f915762020-08-03 13:27:42 -04001/*
2 * Copyright (C) 2020 by Savoir-faire Linux
3 * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>
Sébastien Blin8940f3c2020-07-23 17:03:11 -04004 * Author: Anthony Léonard <anthony.leonard@savoirfairelinux.com>
Sébastien Blin1f915762020-08-03 13:27:42 -04005 * Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com>
6 * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
7 * Author: Isa Nanic <isa.nanic@savoirfairelinux.com>
8 * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
Sébastien Blin8940f3c2020-07-23 17:03:11 -04009 * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
Sébastien Blin1f915762020-08-03 13:27:42 -040010 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 */
24
25#include "calladapter.h"
26
27#include "globalsystemtray.h"
28#include "utils.h"
29
Ming Rui Zhang44dba712020-08-25 14:32:34 -040030CallAdapter::CallAdapter(QObject* parent)
Sébastien Blin1f915762020-08-03 13:27:42 -040031 : QmlAdapterBase(parent)
32 , oneSecondTimer_(new QTimer(this))
33{}
34
35CallAdapter::~CallAdapter() {}
36
37void
38CallAdapter::initQmlObject()
39{
Sébastien Blin6607e0e2020-07-24 15:15:47 -040040 connectCallModel(LRCInstance::getCurrAccId());
Sébastien Blin1f915762020-08-03 13:27:42 -040041
42 connect(&LRCInstance::behaviorController(),
43 &BehaviorController::showIncomingCallView,
44 this,
45 &CallAdapter::slotShowIncomingCallView);
Sébastien Blin5f35e192020-08-06 15:24:57 -040046 connect(&LRCInstance::instance(),
47 &LRCInstance::currentAccountChanged,
48 this,
49 &CallAdapter::slotAccountChanged);
Sébastien Blin1f915762020-08-03 13:27:42 -040050 connect(&LRCInstance::behaviorController(),
51 &BehaviorController::showCallView,
52 this,
53 &CallAdapter::slotShowCallView);
54}
55
56void
Sébastien Blin5f35e192020-08-06 15:24:57 -040057CallAdapter::slotAccountChanged()
58{
59 connectCallModel(LRCInstance::getCurrAccId());
60}
61
62void
Sébastien Blin1f915762020-08-03 13:27:42 -040063CallAdapter::placeAudioOnlyCall()
64{
ababi0b686642020-08-18 17:21:28 +020065 const auto convUid = LRCInstance::getCurrentConvUid();
66 if (!convUid.isEmpty()) {
67 LRCInstance::getCurrentConversationModel()->placeAudioOnlyCall(convUid);
Sébastien Blin1f915762020-08-03 13:27:42 -040068 }
69}
70
71void
72CallAdapter::placeCall()
73{
ababi0b686642020-08-18 17:21:28 +020074 const auto convUid = LRCInstance::getCurrentConvUid();
75 if (!convUid.isEmpty()) {
76 LRCInstance::getCurrentConversationModel()->placeCall(convUid);
Sébastien Blin1f915762020-08-03 13:27:42 -040077 }
78}
79
80void
Ming Rui Zhang44dba712020-08-25 14:32:34 -040081CallAdapter::hangUpACall(const QString& accountId, const QString& convUid)
Sébastien Blin1f915762020-08-03 13:27:42 -040082{
ababi0b686642020-08-18 17:21:28 +020083 auto* convModel = LRCInstance::getCurrentConversationModel();
84 const auto convInfo = convModel->getConversationForUID(convUid);
Sébastien Blin1f915762020-08-03 13:27:42 -040085 if (!convInfo.uid.isEmpty()) {
86 LRCInstance::getAccountInfo(accountId).callModel->hangUp(convInfo.callId);
87 }
88}
89
90void
Ming Rui Zhang44dba712020-08-25 14:32:34 -040091CallAdapter::refuseACall(const QString& accountId, const QString& convUid)
Sébastien Blin1f915762020-08-03 13:27:42 -040092{
ababi0b686642020-08-18 17:21:28 +020093 auto* convModel = LRCInstance::getCurrentConversationModel();
94 const auto convInfo = convModel->getConversationForUID(convUid);
Sébastien Blin1f915762020-08-03 13:27:42 -040095 if (!convInfo.uid.isEmpty()) {
96 LRCInstance::getAccountInfo(accountId).callModel->refuse(convInfo.callId);
97 }
98}
99
100void
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400101CallAdapter::acceptACall(const QString& accountId, const QString& convUid)
Sébastien Blin1f915762020-08-03 13:27:42 -0400102{
103 emit incomingCallNeedToSetupMainView(accountId, convUid);
ababi0b686642020-08-18 17:21:28 +0200104 auto* convModel = LRCInstance::getCurrentConversationModel();
105 const auto convInfo = convModel->getConversationForUID(convUid);
Sébastien Blin1f915762020-08-03 13:27:42 -0400106 if (!convInfo.uid.isEmpty()) {
107 LRCInstance::getAccountInfo(accountId).callModel->accept(convInfo.callId);
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400108 auto& accInfo = LRCInstance::getAccountInfo(convInfo.accountId);
Sébastien Blin1f915762020-08-03 13:27:42 -0400109 accInfo.callModel->setCurrentCall(convInfo.callId);
110 }
111}
112
113void
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400114CallAdapter::slotShowIncomingCallView(const QString& accountId, const conversation::Info& convInfo)
Sébastien Blin1f915762020-08-03 13:27:42 -0400115{
ababi0b686642020-08-18 17:21:28 +0200116 auto* callModel = LRCInstance::getCurrentCallModel();
Sébastien Blin1f915762020-08-03 13:27:42 -0400117
118 if (!callModel->hasCall(convInfo.callId)) {
119 /*
120 * Connection to close potential incoming call page when it is not current account.
121 */
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400122 auto& accInfo = LRCInstance::accountModel().getAccountInfo(accountId);
Sébastien Blin1f915762020-08-03 13:27:42 -0400123
124 QObject::disconnect(closeIncomingCallPageConnection_);
125
126 closeIncomingCallPageConnection_
127 = QObject::connect(accInfo.callModel.get(),
128 &lrc::api::NewCallModel::callStatusChanged,
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400129 [this, accountId, uid = convInfo.uid](const QString& callId) {
130 auto& accInfo = LRCInstance::accountModel().getAccountInfo(
Sébastien Blin1f915762020-08-03 13:27:42 -0400131 accountId);
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400132 auto& callModel = accInfo.callModel;
Sébastien Blin1f915762020-08-03 13:27:42 -0400133 auto call = callModel->getCall(callId);
134
135 switch (call.status) {
136 case lrc::api::call::Status::INVALID:
137 case lrc::api::call::Status::INACTIVE:
138 case lrc::api::call::Status::ENDED:
139 case lrc::api::call::Status::PEER_BUSY:
140 case lrc::api::call::Status::TIMEOUT:
141 case lrc::api::call::Status::TERMINATING: {
142 if (!uid.isEmpty())
143 emit closePotentialIncomingCallPageWindow(accountId, uid);
144 break;
145 }
146 default:
147 break;
148 }
149
150 emit updateConversationSmartList();
151 QObject::disconnect(closeIncomingCallPageConnection_);
152 });
153 /*
154 * Show incoming call page only.
155 */
Sébastien Blincdcf43c2020-07-23 14:51:47 -0400156 auto accountProperties = LRCInstance::accountModel().getAccountConfig(accountId);
157 if (!accountProperties.autoAnswer && !accountProperties.isRendezVous) {
158 emit showIncomingCallPage(accountId, convInfo.uid);
159 }
Sébastien Blin1f915762020-08-03 13:27:42 -0400160 return;
161 }
162
163 auto call = callModel->getCall(convInfo.callId);
164 auto isCallSelected = LRCInstance::getCurrentConvUid() == convInfo.uid;
165
166 if (call.isOutgoing) {
167 if (isCallSelected) {
168 emit showOutgoingCallPage(accountId, convInfo.uid);
169 emit showCallStack(accountId, convInfo.uid);
170 }
171 } else {
172 auto selectedAccountId = LRCInstance::getCurrentAccountInfo().id;
173 auto accountProperties = LRCInstance::accountModel().getAccountConfig(selectedAccountId);
Sébastien Blincdcf43c2020-07-23 14:51:47 -0400174 if (!accountProperties.autoAnswer && !accountProperties.isRendezVous) {
Sébastien Blin1f915762020-08-03 13:27:42 -0400175 emit showIncomingCallPage(accountId, convInfo.uid);
176 }
177 }
178
ababi76b94aa2020-08-24 17:46:30 +0200179 emit callStatusChanged(static_cast<int>(call.status), accountId, convInfo.uid);
Sébastien Blin1f915762020-08-03 13:27:42 -0400180
181 emit updateConversationSmartList();
182}
183
184void
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400185CallAdapter::slotShowCallView(const QString& accountId, const lrc::api::conversation::Info& convInfo)
Sébastien Blin1f915762020-08-03 13:27:42 -0400186{
187 updateCall(convInfo.uid, accountId);
188}
189
190void
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400191CallAdapter::updateCall(const QString& convUid, const QString& accountId, bool forceCallOnly)
Sébastien Blin1f915762020-08-03 13:27:42 -0400192{
193 accountId_ = accountId.isEmpty() ? accountId_ : accountId;
194 convUid_ = convUid.isEmpty() ? convUid_ : convUid;
195
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400196 auto* convModel = LRCInstance::getCurrentConversationModel();
ababi0b686642020-08-18 17:21:28 +0200197 const auto convInfo = convModel->getConversationForUID(convUid_);
Sébastien Blin1f915762020-08-03 13:27:42 -0400198 if (convInfo.uid.isEmpty()) {
199 return;
200 }
201
202 auto call = LRCInstance::getCallInfoForConversation(convInfo, forceCallOnly);
203 if (!call) {
204 return;
205 }
206
207 if (call->isAudioOnly) {
208 emit showAudioCallPage(accountId_, convUid_);
209 } else {
210 emit showVideoCallPage(accountId_, convUid_, call->id);
211 }
212
213 updateCallOverlay(convInfo);
214
215 /*
216 * Preview.
217 */
218 emit previewVisibilityNeedToChange(shouldShowPreview(forceCallOnly));
219
220 emit showCallStack(accountId_, convUid_);
221}
222
223bool
224CallAdapter::shouldShowPreview(bool force)
225{
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400226 bool shouldShowPreview {false};
ababi0b686642020-08-18 17:21:28 +0200227 auto* convModel = LRCInstance::getCurrentConversationModel();
228 const auto convInfo = convModel->getConversationForUID(convUid_);
Sébastien Blin1f915762020-08-03 13:27:42 -0400229 if (convInfo.uid.isEmpty()) {
230 return shouldShowPreview;
231 }
232 auto call = LRCInstance::getCallInfoForConversation(convInfo, force);
233 if (call) {
234 shouldShowPreview = !call->isAudioOnly && !(call->status == lrc::api::call::Status::PAUSED)
235 && !call->videoMuted && call->type != lrc::api::call::Type::CONFERENCE;
236 }
237 return shouldShowPreview;
238}
239
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400240QVariantList
241CallAdapter::getConferencesInfos()
242{
243 QVariantList map;
ababi0b686642020-08-18 17:21:28 +0200244 auto* convModel = LRCInstance::getCurrentConversationModel();
245 const auto convInfo = convModel->getConversationForUID(convUid_);
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400246 if (convInfo.uid.isEmpty())
247 return map;
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400248 auto callId = convInfo.confId.isEmpty() ? convInfo.callId : convInfo.confId;
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400249 if (!callId.isEmpty()) {
250 try {
251 auto call = LRCInstance::getCurrentCallModel()->getCall(callId);
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400252 for (const auto& participant : call.participantsInfos) {
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400253 QJsonObject data;
254 data["x"] = participant["x"].toInt();
255 data["y"] = participant["y"].toInt();
256 data["w"] = participant["w"].toInt();
257 data["h"] = participant["h"].toInt();
258 data["active"] = participant["active"] == "true";
259 auto bestName = participant["uri"];
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400260 auto& accInfo = LRCInstance::accountModel().getAccountInfo(accountId_);
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400261 data["isLocal"] = false;
262 if (bestName == accInfo.profileInfo.uri) {
263 bestName = tr("me");
264 data["isLocal"] = true;
265 } else {
266 try {
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400267 auto& contact = LRCInstance::getCurrentAccountInfo()
268 .contactModel->getContact(participant["uri"]);
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400269 bestName = Utils::bestNameForContact(contact);
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400270 } catch (...) {
271 }
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400272 }
273 data["bestName"] = bestName;
274
275 map.push_back(QVariant(data));
276 }
277 return map;
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400278 } catch (...) {
279 }
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400280 }
281 return map;
282}
283
Sébastien Blin1f915762020-08-03 13:27:42 -0400284void
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400285CallAdapter::connectCallModel(const QString& accountId)
Sébastien Blin1f915762020-08-03 13:27:42 -0400286{
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400287 auto& accInfo = LRCInstance::accountModel().getAccountInfo(accountId);
Sébastien Blin1f915762020-08-03 13:27:42 -0400288
289 QObject::disconnect(callStatusChangedConnection_);
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400290 QObject::disconnect(onParticipantsChangedConnection_);
291
292 onParticipantsChangedConnection_ = QObject::connect(
293 accInfo.callModel.get(),
294 &lrc::api::NewCallModel::onParticipantsChanged,
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400295 [this, accountId](const QString& confId) {
296 auto& accInfo = LRCInstance::accountModel().getAccountInfo(accountId);
297 auto& callModel = accInfo.callModel;
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400298 auto call = callModel->getCall(confId);
ababi0b686642020-08-18 17:21:28 +0200299 const auto convInfo = LRCInstance::getConversationFromCallId(confId);
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400300 if (!convInfo.uid.isEmpty()) {
301 // Convert to QML
302 QVariantList map;
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400303 for (const auto& participant : call.participantsInfos) {
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400304 QJsonObject data;
305 data["x"] = participant["x"].toInt();
306 data["y"] = participant["y"].toInt();
307 data["w"] = participant["w"].toInt();
308 data["h"] = participant["h"].toInt();
309 data["uri"] = participant["uri"];
310 data["active"] = participant["active"] == "true";
311 auto bestName = participant["uri"];
312 data["isLocal"] = false;
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400313 auto& accInfo = LRCInstance::accountModel().getAccountInfo(accountId_);
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400314 if (bestName == accInfo.profileInfo.uri) {
315 bestName = tr("me");
316 data["isLocal"] = true;
317 } else {
318 try {
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400319 auto& contact = LRCInstance::getCurrentAccountInfo()
320 .contactModel->getContact(participant["uri"]);
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400321 bestName = Utils::bestNameForContact(contact);
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400322 } catch (...) {
323 }
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400324 }
325 data["bestName"] = bestName;
326 map.push_back(QVariant(data));
327 }
328 emit updateParticipantsInfos(map, accountId, confId);
329 }
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400330 });
Sébastien Blin1f915762020-08-03 13:27:42 -0400331
332 callStatusChangedConnection_ = QObject::connect(
333 accInfo.callModel.get(),
334 &lrc::api::NewCallModel::callStatusChanged,
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400335 [this, accountId](const QString& callId) {
336 auto& accInfo = LRCInstance::accountModel().getAccountInfo(accountId);
337 auto& callModel = accInfo.callModel;
ababi0b686642020-08-18 17:21:28 +0200338 const auto call = callModel->getCall(callId);
Sébastien Blin1f915762020-08-03 13:27:42 -0400339
340 /*
341 * Change status label text.
342 */
ababi0b686642020-08-18 17:21:28 +0200343 const auto convInfo = LRCInstance::getConversationFromCallId(callId);
Sébastien Blin1f915762020-08-03 13:27:42 -0400344 if (!convInfo.uid.isEmpty()) {
ababi76b94aa2020-08-24 17:46:30 +0200345 emit callStatusChanged(static_cast<int>(call.status), accountId, convInfo.uid);
Sébastien Blin1f915762020-08-03 13:27:42 -0400346 }
347
348 switch (call.status) {
349 case lrc::api::call::Status::INVALID:
350 case lrc::api::call::Status::INACTIVE:
351 case lrc::api::call::Status::ENDED:
352 case lrc::api::call::Status::PEER_BUSY:
353 case lrc::api::call::Status::TIMEOUT:
354 case lrc::api::call::Status::TERMINATING: {
355 LRCInstance::renderer()->removeDistantRenderer(callId);
356 if (convInfo.uid.isEmpty()) {
357 break;
358 }
359 /*
360 * If it's a conference, change the smartlist index
361 * to the next remaining participant.
362 */
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400363 bool forceCallOnly {false};
Sébastien Blin1f915762020-08-03 13:27:42 -0400364 if (!convInfo.confId.isEmpty()) {
365 auto callList = LRCInstance::getAPI().getConferenceSubcalls(convInfo.confId);
366 if (callList.empty()) {
367 auto lastConferencee = LRCInstance::instance().popLastConferencee(
368 convInfo.confId);
369 callList.append(lastConferencee);
370 forceCallOnly = true;
371 }
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400372 for (const auto& callId : callList) {
Sébastien Blin1f915762020-08-03 13:27:42 -0400373 if (!callModel->hasCall(callId)) {
374 continue;
375 }
376 auto otherConv = LRCInstance::getConversationFromCallId(callId);
377 if (!otherConv.uid.isEmpty() && otherConv.uid != convInfo.uid) {
378 /*
379 * Reset the call view corresponding accountId, uid.
380 */
381 LRCInstance::setSelectedConvId(otherConv.uid);
382 showCallStack(otherConv.accountId, otherConv.uid, true);
383 updateCall(otherConv.uid, otherConv.accountId, forceCallOnly);
384 }
385 }
386 } else {
387 emit closeCallStack(accountId, convInfo.uid);
388 emit closePotentialIncomingCallPageWindow(accountId, convInfo.uid);
389 }
390
391 break;
392 }
393 case lrc::api::call::Status::CONNECTED:
394 case lrc::api::call::Status::IN_PROGRESS: {
ababi0b686642020-08-18 17:21:28 +0200395 const auto convInfo = LRCInstance::getConversationFromCallId(callId, accountId);
Sébastien Blin1f915762020-08-03 13:27:42 -0400396 if (!convInfo.uid.isEmpty() && convInfo.uid == LRCInstance::getCurrentConvUid()) {
397 accInfo.conversationModel->selectConversation(convInfo.uid);
398 }
399 LRCInstance::renderer()->addDistantRenderer(callId);
400 updateCall();
401 LRCInstance::getAccountInfo(accountId).callModel->setCurrentCall(callId);
402 break;
403 }
404 case lrc::api::call::Status::PAUSED:
405 updateCall();
406 default:
407 break;
408 }
409
410 emit updateConversationSmartList();
411 });
412}
413
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400414void
415CallAdapter::sipInputPanelPlayDTMF(const QString& key)
416{
417 auto callId = LRCInstance::getCallIdForConversationUid(convUid_, accountId_);
418 if (callId.isEmpty() || !LRCInstance::getCurrentCallModel()->hasCall(callId)) {
419 return;
420 }
421
422 LRCInstance::getCurrentCallModel()->playDTMF(callId, key);
423}
424
Sébastien Blin1f915762020-08-03 13:27:42 -0400425/*
426 * For Call Overlay
427 */
428void
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400429CallAdapter::updateCallOverlay(const lrc::api::conversation::Info& convInfo)
Sébastien Blin1f915762020-08-03 13:27:42 -0400430{
431 setTime(accountId_, convUid_);
432 QObject::disconnect(oneSecondTimer_);
433 QObject::connect(oneSecondTimer_, &QTimer::timeout, [this] { setTime(accountId_, convUid_); });
434 oneSecondTimer_->start(20);
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400435 auto& accInfo = LRCInstance::accountModel().getAccountInfo(accountId_);
Sébastien Blin1f915762020-08-03 13:27:42 -0400436
437 auto call = LRCInstance::getCallInfoForConversation(convInfo);
438 if (!call) {
439 return;
440 }
441
442 bool isPaused = call->status == lrc::api::call::Status::PAUSED;
443 bool isAudioOnly = call->isAudioOnly && !isPaused;
444 bool isAudioMuted = call->audioMuted && (call->status != lrc::api::call::Status::PAUSED);
445 bool isVideoMuted = call->videoMuted && !isPaused && !call->isAudioOnly;
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400446 bool isRecording = isRecordingThisCall();
Sébastien Blin1f915762020-08-03 13:27:42 -0400447
448 emit updateOverlay(isPaused,
449 isAudioOnly,
450 isAudioMuted,
451 isVideoMuted,
452 isRecording,
453 accInfo.profileInfo.type == lrc::api::profile::Type::SIP,
454 !convInfo.confId.isEmpty(),
455 Utils::bestNameForConversation(convInfo,
456 *LRCInstance::getCurrentConversationModel()));
457}
458
459void
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400460CallAdapter::hangupCall(const QString& uri)
Sébastien Blin1f915762020-08-03 13:27:42 -0400461{
ababi0b686642020-08-18 17:21:28 +0200462 const auto convInfo = LRCInstance::getConversationFromPeerUri(uri, accountId_);
Sébastien Blin1f915762020-08-03 13:27:42 -0400463 if (!convInfo.uid.isEmpty()) {
464 auto callModel = LRCInstance::getAccountInfo(accountId_).callModel.get();
465 if (callModel->hasCall(convInfo.callId)) {
466 /*
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400467 * Store the last remaining participant of the conference,
468 * so we can switch the smartlist index after termination.
469 */
Sébastien Blin1f915762020-08-03 13:27:42 -0400470 if (!convInfo.confId.isEmpty()) {
471 auto callList = LRCInstance::getAPI().getConferenceSubcalls(convInfo.confId);
472 if (callList.size() == 2) {
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400473 for (const auto& cId : callList) {
Sébastien Blin1f915762020-08-03 13:27:42 -0400474 if (cId != convInfo.callId) {
475 LRCInstance::instance().pushLastConferencee(convInfo.confId, cId);
476 }
477 }
478 }
479 }
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400480
481 callModel->hangUp(convInfo.callId);
482 }
483 }
484}
485
486void
487CallAdapter::maximizeParticipant(const QString& uri, bool isActive)
488{
ababi0b686642020-08-18 17:21:28 +0200489 auto* callModel = LRCInstance::getAccountInfo(accountId_).callModel.get();
490 auto* convModel = LRCInstance::getCurrentConversationModel();
491 const auto conversation = convModel->getConversationForUID(LRCInstance::getCurrentConvUid());
492 const auto confId = conversation.confId;
493
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400494 QString callId;
495 if (LRCInstance::getCurrentAccountInfo().profileInfo.uri != uri) {
ababi0b686642020-08-18 17:21:28 +0200496 const auto convInfo = LRCInstance::getConversationFromPeerUri(uri, accountId_);
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400497 if (!convInfo.uid.isEmpty()) {
498 callId = convInfo.callId;
499 }
500 }
501 try {
ababi0b686642020-08-18 17:21:28 +0200502 const auto call = callModel->getCall(confId);
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400503 switch (call.layout) {
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400504 case lrc::api::call::Layout::GRID:
505 callModel->setActiveParticipant(confId, callId);
506 callModel->setConferenceLayout(confId, lrc::api::call::Layout::ONE_WITH_SMALL);
507 break;
508 case lrc::api::call::Layout::ONE_WITH_SMALL:
509 callModel->setActiveParticipant(confId, callId);
510 callModel->setConferenceLayout(confId,
511 isActive ? lrc::api::call::Layout::ONE
512 : lrc::api::call::Layout::ONE_WITH_SMALL);
513 break;
514 case lrc::api::call::Layout::ONE:
515 callModel->setActiveParticipant(confId, callId);
516 callModel->setConferenceLayout(confId, lrc::api::call::Layout::GRID);
517 break;
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400518 };
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400519 } catch (...) {
520 }
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400521}
522
523void
524CallAdapter::minimizeParticipant()
525{
ababi0b686642020-08-18 17:21:28 +0200526 auto* callModel = LRCInstance::getAccountInfo(accountId_).callModel.get();
527 auto* convModel = LRCInstance::getCurrentConversationModel();
528 const auto conversation = convModel->getConversationForUID(LRCInstance::getCurrentConvUid());
529 const auto confId = conversation.confId;
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400530 try {
531 auto call = callModel->getCall(confId);
532 switch (call.layout) {
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400533 case lrc::api::call::Layout::GRID:
534 break;
535 case lrc::api::call::Layout::ONE_WITH_SMALL:
536 callModel->setConferenceLayout(confId, lrc::api::call::Layout::GRID);
537 break;
538 case lrc::api::call::Layout::ONE:
539 callModel->setConferenceLayout(confId, lrc::api::call::Layout::ONE_WITH_SMALL);
540 break;
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400541 };
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400542 } catch (...) {
543 }
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400544}
545
546void
547CallAdapter::hangUpThisCall()
548{
ababi0b686642020-08-18 17:21:28 +0200549 auto* convModel = LRCInstance::getCurrentConversationModel();
550 const auto convInfo = convModel->getConversationForUID(convUid_);
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400551 if (!convInfo.uid.isEmpty()) {
ababi0b686642020-08-18 17:21:28 +0200552 auto* callModel = LRCInstance::getAccountInfo(accountId_).callModel.get();
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400553 if (!convInfo.confId.isEmpty() && callModel->hasCall(convInfo.confId)) {
554 callModel->hangUp(convInfo.confId);
555 } else if (callModel->hasCall(convInfo.callId)) {
Sébastien Blin1f915762020-08-03 13:27:42 -0400556 callModel->hangUp(convInfo.callId);
557 }
558 }
559}
560
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400561bool
562CallAdapter::isRecordingThisCall()
563{
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400564 auto& accInfo = LRCInstance::accountModel().getAccountInfo(accountId_);
565 auto& convModel = accInfo.conversationModel;
ababi0b686642020-08-18 17:21:28 +0200566 const auto convInfo = convModel->getConversationForUID(convUid_);
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400567 return accInfo.callModel->isRecording(convInfo.confId)
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400568 || accInfo.callModel->isRecording(convInfo.callId);
Sébastien Blin8940f3c2020-07-23 17:03:11 -0400569}
570
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400571bool
572CallAdapter::isCurrentMaster() const
573{
ababi0b686642020-08-18 17:21:28 +0200574 auto* convModel = LRCInstance::getCurrentConversationModel();
575 const auto convInfo = convModel->getConversationForUID(convUid_);
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400576 if (!convInfo.uid.isEmpty()) {
ababi0b686642020-08-18 17:21:28 +0200577 auto* callModel = LRCInstance::getAccountInfo(accountId_).callModel.get();
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400578 try {
579 if (!convInfo.confId.isEmpty() && callModel->hasCall(convInfo.confId)) {
580 return true;
581 } else {
582 auto call = callModel->getCall(convInfo.callId);
583 return call.participantsInfos.size() == 0;
584 }
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400585 } catch (...) {
586 }
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400587 }
588 return true;
589}
590
591int
592CallAdapter::getCurrentLayoutType() const
593{
ababi0b686642020-08-18 17:21:28 +0200594 auto* convModel = LRCInstance::getCurrentConversationModel();
595 const auto convInfo = convModel->getConversationForUID(convUid_);
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400596 if (!convInfo.uid.isEmpty()) {
ababi0b686642020-08-18 17:21:28 +0200597 auto* callModel = LRCInstance::getAccountInfo(accountId_).callModel.get();
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400598 try {
599 auto call = callModel->getCall(convInfo.confId);
600 return Utils::toUnderlyingValue(call.layout);
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400601 } catch (...) {
602 }
Sébastien Blin6607e0e2020-07-24 15:15:47 -0400603 }
604 return -1;
605}
606
Sébastien Blin1f915762020-08-03 13:27:42 -0400607void
608CallAdapter::holdThisCallToggle()
609{
ababi0b686642020-08-18 17:21:28 +0200610 const auto callId = LRCInstance::getCallIdForConversationUid(convUid_, accountId_);
Sébastien Blin1f915762020-08-03 13:27:42 -0400611 if (callId.isEmpty() || !LRCInstance::getCurrentCallModel()->hasCall(callId)) {
612 return;
613 }
ababi0b686642020-08-18 17:21:28 +0200614 auto* callModel = LRCInstance::getCurrentCallModel();
Sébastien Blin1f915762020-08-03 13:27:42 -0400615 if (callModel->hasCall(callId)) {
616 callModel->togglePause(callId);
617 }
618 emit showOnHoldLabel(true);
619}
620
621void
622CallAdapter::muteThisCallToggle()
623{
ababi0b686642020-08-18 17:21:28 +0200624 const auto callId = LRCInstance::getCallIdForConversationUid(convUid_, accountId_);
Sébastien Blin1f915762020-08-03 13:27:42 -0400625 if (callId.isEmpty() || !LRCInstance::getCurrentCallModel()->hasCall(callId)) {
626 return;
627 }
ababi0b686642020-08-18 17:21:28 +0200628 auto* callModel = LRCInstance::getCurrentCallModel();
Sébastien Blin1f915762020-08-03 13:27:42 -0400629 if (callModel->hasCall(callId)) {
630 callModel->toggleMedia(callId, lrc::api::NewCallModel::Media::AUDIO);
631 }
632}
633
634void
635CallAdapter::recordThisCallToggle()
636{
ababi0b686642020-08-18 17:21:28 +0200637 const auto callId = LRCInstance::getCallIdForConversationUid(convUid_, accountId_);
Sébastien Blin1f915762020-08-03 13:27:42 -0400638 if (callId.isEmpty() || !LRCInstance::getCurrentCallModel()->hasCall(callId)) {
639 return;
640 }
ababi0b686642020-08-18 17:21:28 +0200641 auto* callModel = LRCInstance::getCurrentCallModel();
Sébastien Blin1f915762020-08-03 13:27:42 -0400642 if (callModel->hasCall(callId)) {
643 callModel->toggleAudioRecord(callId);
644 }
645}
646
647void
648CallAdapter::videoPauseThisCallToggle()
649{
ababi0b686642020-08-18 17:21:28 +0200650 const auto callId = LRCInstance::getCallIdForConversationUid(convUid_, accountId_);
Sébastien Blin1f915762020-08-03 13:27:42 -0400651 if (callId.isEmpty() || !LRCInstance::getCurrentCallModel()->hasCall(callId)) {
652 return;
653 }
ababi0b686642020-08-18 17:21:28 +0200654 auto* callModel = LRCInstance::getCurrentCallModel();
Sébastien Blin1f915762020-08-03 13:27:42 -0400655 if (callModel->hasCall(callId)) {
656 callModel->toggleMedia(callId, lrc::api::NewCallModel::Media::VIDEO);
657 }
658 emit previewVisibilityNeedToChange(shouldShowPreview(false));
659}
660
661void
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400662CallAdapter::setTime(const QString& accountId, const QString& convUid)
Sébastien Blin1f915762020-08-03 13:27:42 -0400663{
ababi0b686642020-08-18 17:21:28 +0200664 const auto callId = LRCInstance::getCallIdForConversationUid(convUid, accountId);
Sébastien Blin1f915762020-08-03 13:27:42 -0400665 if (callId.isEmpty() || !LRCInstance::getCurrentCallModel()->hasCall(callId)) {
666 return;
667 }
ababi0b686642020-08-18 17:21:28 +0200668 const auto callInfo = LRCInstance::getCurrentCallModel()->getCall(callId);
Sébastien Blin1f915762020-08-03 13:27:42 -0400669 if (callInfo.status == lrc::api::call::Status::IN_PROGRESS
670 || callInfo.status == lrc::api::call::Status::PAUSED) {
671 auto timeString = LRCInstance::getCurrentCallModel()->getFormattedCallDuration(callId);
672 emit updateTimeText(timeString);
673 }
Ming Rui Zhang44dba712020-08-25 14:32:34 -0400674}