Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 1 | /* |
Alexandre Lision | 9fe374b | 2016-01-06 10:17:31 -0500 | [diff] [blame] | 2 | * Copyright (C) 2015-2016 Savoir-faire Linux Inc. |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 3 | * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com> |
| 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify |
| 6 | * it under the terms of the GNU General Public License as published by |
| 7 | * the Free Software Foundation; either version 3 of the License, or |
| 8 | * (at your option) any later version. |
| 9 | * |
| 10 | * This program is distributed in the hope that it will be useful, |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | * GNU General Public License for more details. |
| 14 | * |
| 15 | * You should have received a copy of the GNU General Public License |
| 16 | * along with this program; if not, write to the Free Software |
| 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 18 | */ |
| 19 | #import "CurrentCallVC.h" |
Kateryna Kostiuk | 00dcbff | 2019-07-11 15:42:13 -0400 | [diff] [blame] | 20 | extern "C" { |
| 21 | #import "libavutil/frame.h" |
| 22 | #import "libavutil/display.h" |
| 23 | } |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 24 | |
| 25 | #import <QuartzCore/QuartzCore.h> |
| 26 | |
Alexandre Lision | 210fe21 | 2016-01-27 11:15:13 -0500 | [diff] [blame] | 27 | ///Qt |
| 28 | #import <QMimeData> |
| 29 | #import <QtMacExtras/qmacfunctions.h> |
| 30 | #import <QtCore/qabstractitemmodel.h> |
Alexandre Lision | 210fe21 | 2016-01-27 11:15:13 -0500 | [diff] [blame] | 31 | #import <QPixmap> |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 32 | #import <QUrl> |
Alexandre Lision | 210fe21 | 2016-01-27 11:15:13 -0500 | [diff] [blame] | 33 | |
| 34 | ///LRC |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 35 | #import <video/renderer.h> |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 36 | #import <api/newcallmodel.h> |
| 37 | #import <api/call.h> |
| 38 | #import <api/conversationmodel.h> |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 39 | #import <api/avmodel.h> |
Alexandre Lision | 210fe21 | 2016-01-27 11:15:13 -0500 | [diff] [blame] | 40 | #import <globalinstances.h> |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 41 | |
Alexandre Lision | 6200531 | 2016-01-28 15:55:16 -0500 | [diff] [blame] | 42 | #import "AppDelegate.h" |
Alexandre Lision | f47a256 | 2015-06-15 15:48:29 -0400 | [diff] [blame] | 43 | #import "views/ITProgressIndicator.h" |
Alexandre Lision | 74dd47f | 2015-04-14 13:47:42 -0400 | [diff] [blame] | 44 | #import "views/CallView.h" |
Kateryna Kostiuk | 81afce7 | 2018-10-30 16:40:50 -0400 | [diff] [blame] | 45 | #import "views/NSColor+RingTheme.h" |
Alexandre Lision | 210fe21 | 2016-01-27 11:15:13 -0500 | [diff] [blame] | 46 | #import "delegates/ImageManipulationDelegate.h" |
Alexandre Lision | 16d9c0a | 2015-08-10 12:05:15 -0400 | [diff] [blame] | 47 | #import "ChatVC.h" |
Alexandre Lision | 4baba4c | 2016-02-11 13:00:57 -0500 | [diff] [blame] | 48 | #import "views/IconButton.h" |
Anthony Léonard | 6f81975 | 2018-01-05 09:53:40 -0500 | [diff] [blame] | 49 | #import "utils.h" |
Kateryna Kostiuk | 00dcbff | 2019-07-11 15:42:13 -0400 | [diff] [blame] | 50 | #import "views/CallMTKView.h" |
Kateryna Kostiuk | c5fd3b9 | 2019-07-24 10:12:44 -0400 | [diff] [blame] | 51 | #import "VideoCommon.h" |
Kateryna Kostiuk | 88a6ee8 | 2019-09-10 17:55:08 -0400 | [diff] [blame] | 52 | #import "views/GradientView.h" |
Kateryna Kostiuk | 6891d4f | 2019-09-19 17:44:33 -0400 | [diff] [blame] | 53 | #import "views/MovableView.h" |
Alexandre Lision | 74dd47f | 2015-04-14 13:47:42 -0400 | [diff] [blame] | 54 | |
Kateryna Kostiuk | 1ba5a01 | 2018-12-12 17:07:38 -0500 | [diff] [blame] | 55 | @interface CurrentCallVC () <NSPopoverDelegate> { |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 56 | std::string convUid_; |
| 57 | std::string callUid_; |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 58 | std::string confUid_; |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 59 | const lrc::api::account::Info *accountInfo_; |
Anthony Léonard | 66a050c | 2018-01-03 16:32:34 -0500 | [diff] [blame] | 60 | NSTimer* refreshDurationTimer; |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 61 | } |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 62 | |
Alexandre Lision | 210fe21 | 2016-01-27 11:15:13 -0500 | [diff] [blame] | 63 | // Main container |
| 64 | @property (unsafe_unretained) IBOutlet NSSplitView* splitView; |
Kateryna Kostiuk | 89398b6 | 2018-11-20 16:45:04 -0500 | [diff] [blame] | 65 | @property (unsafe_unretained) IBOutlet NSView* backgroundImage; |
Kateryna Kostiuk | 81afce7 | 2018-10-30 16:40:50 -0400 | [diff] [blame] | 66 | @property (unsafe_unretained) IBOutlet NSBox* bluerBackgroundEffect; |
Alexandre Lision | 210fe21 | 2016-01-27 11:15:13 -0500 | [diff] [blame] | 67 | |
Alexandre Lision | 89edc6a | 2015-11-09 11:30:47 -0500 | [diff] [blame] | 68 | // Header info |
| 69 | @property (unsafe_unretained) IBOutlet NSView* headerContainer; |
Kateryna Kostiuk | 2aa3923 | 2019-10-10 11:55:11 -0400 | [diff] [blame] | 70 | @property (unsafe_unretained) IBOutlet NSView* headerGradientView; |
Alexandre Lision | 89edc6a | 2015-11-09 11:30:47 -0500 | [diff] [blame] | 71 | @property (unsafe_unretained) IBOutlet NSTextField* timeSpentLabel; |
| 72 | |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 73 | // info |
| 74 | @property (unsafe_unretained) IBOutlet NSStackView* infoContainer; |
| 75 | @property (unsafe_unretained) IBOutlet NSImageView* contactPhoto; |
| 76 | @property (unsafe_unretained) IBOutlet NSTextField* contactNameLabel; |
| 77 | @property (unsafe_unretained) IBOutlet NSTextField* callStateLabel; |
| 78 | @property (unsafe_unretained) IBOutlet NSTextField* contactIdLabel; |
| 79 | @property (unsafe_unretained) IBOutlet IconButton* cancelCallButton; |
| 80 | @property (unsafe_unretained) IBOutlet IconButton* pickUpButton; |
| 81 | @property (unsafe_unretained) IBOutlet ITProgressIndicator *loadingIndicator; |
Andreas Traczyk | 77a50d5 | 2018-05-08 17:47:31 -0400 | [diff] [blame] | 82 | |
Alexandre Lision | 89edc6a | 2015-11-09 11:30:47 -0500 | [diff] [blame] | 83 | // Call Controls |
Kateryna Kostiuk | 88a6ee8 | 2019-09-10 17:55:08 -0400 | [diff] [blame] | 84 | @property (unsafe_unretained) IBOutlet GradientView* controlsPanel; |
Kateryna Kostiuk | 2aa3923 | 2019-10-10 11:55:11 -0400 | [diff] [blame] | 85 | @property (unsafe_unretained) IBOutlet NSStackView* controlsStackView; |
Alexandre Lision | 6200531 | 2016-01-28 15:55:16 -0500 | [diff] [blame] | 86 | |
Alexandre Lision | 4baba4c | 2016-02-11 13:00:57 -0500 | [diff] [blame] | 87 | @property (unsafe_unretained) IBOutlet IconButton* holdOnOffButton; |
| 88 | @property (unsafe_unretained) IBOutlet IconButton* hangUpButton; |
| 89 | @property (unsafe_unretained) IBOutlet IconButton* recordOnOffButton; |
Alexandre Lision | 4baba4c | 2016-02-11 13:00:57 -0500 | [diff] [blame] | 90 | @property (unsafe_unretained) IBOutlet IconButton* muteAudioButton; |
| 91 | @property (unsafe_unretained) IBOutlet IconButton* muteVideoButton; |
Alexandre Lision | 4baba4c | 2016-02-11 13:00:57 -0500 | [diff] [blame] | 92 | @property (unsafe_unretained) IBOutlet IconButton* transferButton; |
| 93 | @property (unsafe_unretained) IBOutlet IconButton* addParticipantButton; |
| 94 | @property (unsafe_unretained) IBOutlet IconButton* chatButton; |
Andreas Traczyk | 77a50d5 | 2018-05-08 17:47:31 -0400 | [diff] [blame] | 95 | @property (unsafe_unretained) IBOutlet IconButton* qualityButton; |
Alexandre Lision | d18fa27 | 2015-06-15 11:18:03 -0400 | [diff] [blame] | 96 | |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 97 | // Video |
Alexandre Lision | 58cab67 | 2015-06-09 15:25:40 -0400 | [diff] [blame] | 98 | @property (unsafe_unretained) IBOutlet CallView *videoView; |
Kateryna Kostiuk | 00dcbff | 2019-07-11 15:42:13 -0400 | [diff] [blame] | 99 | @property (unsafe_unretained) IBOutlet CallMTKView *previewView; |
Kateryna Kostiuk | 6891d4f | 2019-09-19 17:44:33 -0400 | [diff] [blame] | 100 | @property (unsafe_unretained) IBOutlet MovableView *movableBaseForView; |
| 101 | @property (unsafe_unretained) IBOutlet NSView* hidePreviewBackground; |
| 102 | @property (unsafe_unretained) IBOutlet NSButton* hidePreviewButton; |
Kateryna Kostiuk | 00dcbff | 2019-07-11 15:42:13 -0400 | [diff] [blame] | 103 | |
| 104 | @property (unsafe_unretained) IBOutlet CallMTKView *videoMTKView; |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 105 | |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 106 | @property RendererConnectionsHolder* renderConnections; |
Alexandre Lision | ef6333a | 2015-03-24 12:30:31 -0400 | [diff] [blame] | 107 | @property QMetaObject::Connection videoStarted; |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 108 | @property QMetaObject::Connection callStateChanged; |
Alexandre Lision | b65c027 | 2015-07-22 15:51:29 -0400 | [diff] [blame] | 109 | @property QMetaObject::Connection messageConnection; |
Kateryna Kostiuk | 133364b | 2018-10-31 11:36:08 -0400 | [diff] [blame] | 110 | @property QMetaObject::Connection profileUpdatedConnection; |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 111 | |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 112 | //conference |
| 113 | @property (unsafe_unretained) IBOutlet NSStackView *callingWidgetsContainer; |
| 114 | |
| 115 | @property (strong) NSPopover* brokerPopoverVC; |
| 116 | |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 117 | @property (strong) IBOutlet ChatVC* chatVC; |
| 118 | |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 119 | @end |
| 120 | |
| 121 | @implementation CurrentCallVC |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 122 | lrc::api::AVModel* mediaModel; |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 123 | NSMutableDictionary *connectingCalls; |
Kateryna Kostiuk | 6891d4f | 2019-09-19 17:44:33 -0400 | [diff] [blame] | 124 | |
| 125 | NSInteger const PREVIEW_WIDTH = 185; |
| 126 | NSInteger const PREVIEW_HEIGHT = 130; |
Kateryna Kostiuk | 2aa3923 | 2019-10-10 11:55:11 -0400 | [diff] [blame] | 127 | NSInteger const HIDE_PREVIEW_BUTTON_SIZE = 25; |
Kateryna Kostiuk | 6891d4f | 2019-09-19 17:44:33 -0400 | [diff] [blame] | 128 | NSInteger const PREVIEW_MARGIN = 20; |
| 129 | |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 130 | @synthesize holdOnOffButton, hangUpButton, recordOnOffButton, pickUpButton, chatButton, transferButton, addParticipantButton, timeSpentLabel, muteVideoButton, muteAudioButton, controlsPanel, headerContainer, videoView, previewView, splitView, loadingIndicator, backgroundImage, bluerBackgroundEffect, hidePreviewButton, hidePreviewBackground, movableBaseForView, infoContainer, contactPhoto, contactNameLabel, callStateLabel, contactIdLabel, cancelCallButton, headerGradientView, controlsStackView, callingWidgetsContainer, brokerPopoverVC; |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 131 | |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 132 | @synthesize renderConnections; |
Kateryna Kostiuk | 00dcbff | 2019-07-11 15:42:13 -0400 | [diff] [blame] | 133 | CVPixelBufferPoolRef pixelBufferPoolDistantView; |
| 134 | CVPixelBufferRef pixelBufferDistantView; |
| 135 | CVPixelBufferPoolRef pixelBufferPoolPreview; |
| 136 | CVPixelBufferRef pixelBufferPreview; |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 137 | |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 138 | /* update call and conversation info |
| 139 | * set info for chat view |
| 140 | * connect signals |
| 141 | */ |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 142 | -(void) setCurrentCall:(const std::string&)callUid |
| 143 | conversation:(const std::string&)convUid |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 144 | account:(const lrc::api::account::Info*)account |
| 145 | avModel:(lrc::api::AVModel *)avModel; |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 146 | { |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 147 | if(account == nil) |
| 148 | return; |
Alexandre Lision | ef6333a | 2015-03-24 12:30:31 -0400 | [diff] [blame] | 149 | |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 150 | mediaModel = avModel; |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 151 | auto* callModel = account->callModel.get(); |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 152 | |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 153 | if (not callModel->hasCall(callUid)){ |
| 154 | callUid_.clear(); |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 155 | confUid_.clear(); |
Alexandre Lision | 2db8f47 | 2015-07-22 15:05:46 -0400 | [diff] [blame] | 156 | return; |
| 157 | } |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 158 | callUid_ = callUid; |
| 159 | convUid_ = convUid; |
| 160 | accountInfo_ = account; |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 161 | auto convIt = getConversationFromUid(convUid_, *accountInfo_->conversationModel); |
| 162 | confUid_ = convIt->confId; |
Anthony Léonard | 4b0935f | 2017-12-26 12:05:22 -0500 | [diff] [blame] | 163 | [self.chatVC setConversationUid:convUid model:account->conversationModel.get()]; |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 164 | [self connectSignals]; |
| 165 | } |
| 166 | |
| 167 | -(void) connectSignals { |
| 168 | auto* callModel = accountInfo_->callModel.get(); |
| 169 | auto* convModel = accountInfo_->conversationModel.get(); |
| 170 | //monitor for updated call state |
| 171 | QObject::disconnect(self.callStateChanged); |
| 172 | self.callStateChanged = QObject::connect(callModel, |
| 173 | &lrc::api::NewCallModel::callStatusChanged, |
| 174 | [self](const std::string callId) { |
| 175 | if ([self isCurrentCall: callId]) { |
| 176 | [self updateCall]; |
| 177 | } |
| 178 | }); |
| 179 | /* monitor media for messaging text messaging */ |
| 180 | QObject::disconnect(self.messageConnection); |
| 181 | self.messageConnection = QObject::connect(convModel, |
| 182 | &lrc::api::ConversationModel::interactionStatusUpdated, |
| 183 | [self] (std::string convUid, |
| 184 | uint64_t msgId, |
| 185 | lrc::api::interaction::Info msg) { |
| 186 | if (msg.type == lrc::api::interaction::Type::TEXT) { |
| 187 | if(not [[self splitView] isSubviewCollapsed:[[[self splitView] subviews] objectAtIndex: 1]]){ |
| 188 | return; |
| 189 | } |
| 190 | [self uncollapseRightView]; |
| 191 | } |
| 192 | }); |
| 193 | //monitor for updated profile |
| 194 | QObject::disconnect(self.profileUpdatedConnection); |
| 195 | self.profileUpdatedConnection = |
| 196 | QObject::connect(accountInfo_->contactModel.get(), |
| 197 | &lrc::api::ContactModel::contactAdded, |
| 198 | [self](const std::string &contactUri) { |
| 199 | auto convIt = getConversationFromUid(convUid_, *accountInfo_->conversationModel.get()); |
| 200 | if (convIt == accountInfo_->conversationModel->allFilteredConversations().end()) { |
| 201 | return; |
| 202 | } |
| 203 | if (convIt->participants.empty()) { |
| 204 | return; |
| 205 | |
| 206 | } |
| 207 | auto& contact = accountInfo_->contactModel->getContact(convIt->participants[0]); |
| 208 | if (contact.profileInfo.type == lrc::api::profile::Type::RING && contact.profileInfo.uri == contactUri) |
| 209 | accountInfo_->conversationModel->makePermanent(convUid_); |
| 210 | [contactPhoto setImage: [self getContactImageOfSize:120.0 withDefaultAvatar:YES]]; |
| 211 | [self.delegate conversationInfoUpdatedFor:convUid_]; |
| 212 | [self setBackground]; |
| 213 | }); |
| 214 | [self connectVideoSignals]; |
| 215 | } |
| 216 | |
| 217 | -(void) updatePendingCalls { |
| 218 | for (NSView *view in callingWidgetsContainer.subviews) { |
| 219 | view.removeFromSuperview; |
| 220 | } |
| 221 | NSDictionary * calls = connectingCalls[@(callUid_.c_str())]; |
| 222 | for (NSViewController * callView in calls.allValues) { |
| 223 | [self.callingWidgetsContainer addView: callView.view inGravity:NSStackViewGravityBottom]; |
| 224 | } |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 225 | } |
| 226 | |
Kateryna Kostiuk | 88a6ee8 | 2019-09-10 17:55:08 -0400 | [diff] [blame] | 227 | -(void) setUpButtons:(lrc::api::call::Info&)callInfo isRecording:(BOOL) isRecording { |
| 228 | muteAudioButton.image = callInfo.audioMuted ? [NSImage imageNamed:@"ic_action_mute_audio.png"] : |
| 229 | [NSImage imageNamed:@"ic_action_audio.png"]; |
| 230 | muteVideoButton.image = callInfo.videoMuted ? [NSImage imageNamed:@"ic_action_mute_video.png"] : |
| 231 | [NSImage imageNamed:@"ic_action_video.png"]; |
| 232 | [muteVideoButton setHidden: callInfo.isAudioOnly ? YES: NO]; |
| 233 | if (isRecording) { |
| 234 | [recordOnOffButton startBlinkAnimationfrom:[NSColor buttonBlinkColorColor] to:[NSColor whiteColor] scaleFactor: 1 duration: 1.5]; |
| 235 | } else { |
| 236 | [recordOnOffButton stopBlinkAnimation]; |
| 237 | } |
| 238 | } |
| 239 | |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 240 | - (void) setUpPreviewFrame { |
Kateryna Kostiuk | 6891d4f | 2019-09-19 17:44:33 -0400 | [diff] [blame] | 241 | CGPoint previewOrigin = CGPointMake(self.videoView.frame.size.width - PREVIEW_WIDTH - PREVIEW_MARGIN, PREVIEW_MARGIN); |
| 242 | movableBaseForView.frame = CGRectMake(previewOrigin.x, previewOrigin.y, PREVIEW_WIDTH, PREVIEW_HEIGHT); |
Kateryna Kostiuk | 6891d4f | 2019-09-19 17:44:33 -0400 | [diff] [blame] | 243 | self.movableBaseForView.movable = true; |
| 244 | previewView.frame = movableBaseForView.bounds; |
Kateryna Kostiuk | 2aa3923 | 2019-10-10 11:55:11 -0400 | [diff] [blame] | 245 | hidePreviewBackground.frame = [self frameForExpendPreviewButton]; |
| 246 | hidePreviewButton.contentTintColor = [NSColor blackColor]; |
Kateryna Kostiuk | 6891d4f | 2019-09-19 17:44:33 -0400 | [diff] [blame] | 247 | } |
| 248 | |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 249 | - (void)awakeFromNib |
| 250 | { |
Alexandre Lision | ef6333a | 2015-03-24 12:30:31 -0400 | [diff] [blame] | 251 | [self.view setWantsLayer:YES]; |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 252 | |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 253 | renderConnections = [[RendererConnectionsHolder alloc] init]; |
Alexandre Lision | ef6333a | 2015-03-24 12:30:31 -0400 | [diff] [blame] | 254 | |
Alexandre Lision | f47a256 | 2015-06-15 15:48:29 -0400 | [diff] [blame] | 255 | [loadingIndicator setColor:[NSColor whiteColor]]; |
Andreas Traczyk | 77a50d5 | 2018-05-08 17:47:31 -0400 | [diff] [blame] | 256 | [loadingIndicator setNumberOfLines:200]; |
| 257 | [loadingIndicator setWidthOfLine:4]; |
| 258 | [loadingIndicator setLengthOfLine:4]; |
| 259 | [loadingIndicator setInnerMargin:59]; |
Alexandre Lision | f47a256 | 2015-06-15 15:48:29 -0400 | [diff] [blame] | 260 | |
Alexandre Lision | a1eee3c | 2015-08-10 13:44:51 -0400 | [diff] [blame] | 261 | [self.videoView setCallDelegate:self]; |
Kateryna Kostiuk | 81afce7 | 2018-10-30 16:40:50 -0400 | [diff] [blame] | 262 | [bluerBackgroundEffect setWantsLayer:YES]; |
Kateryna Kostiuk | 89398b6 | 2018-11-20 16:45:04 -0500 | [diff] [blame] | 263 | [backgroundImage setWantsLayer: YES]; |
| 264 | backgroundImage.layer.contentsGravity = kCAGravityResizeAspectFill; |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 265 | movableBaseForView.wantsLayer = YES; |
Kateryna Kostiuk | 2aa3923 | 2019-10-10 11:55:11 -0400 | [diff] [blame] | 266 | movableBaseForView.shadow = [[NSShadow alloc] init]; |
| 267 | movableBaseForView.layer.shadowOpacity = 0.6; |
| 268 | movableBaseForView.layer.shadowColor = [[NSColor blackColor] CGColor]; |
| 269 | movableBaseForView.layer.shadowOffset = NSMakeSize(0, -3); |
| 270 | movableBaseForView.layer.shadowRadius = 10; |
| 271 | previewView.wantsLayer = YES; |
| 272 | previewView.layer.cornerRadius = 5; |
| 273 | previewView.layer.masksToBounds = true; |
| 274 | hidePreviewBackground.wantsLayer = YES; |
| 275 | hidePreviewBackground.layer.cornerRadius = 5; |
| 276 | hidePreviewBackground.layer.maskedCorners = kCALayerMinXMinYCorner; |
| 277 | hidePreviewBackground.layer.masksToBounds = true; |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 278 | movableBaseForView.hostingView = self.videoView; |
| 279 | [movableBaseForView setAutoresizingMask: NSViewNotSizable | NSViewMaxXMargin | NSViewMaxYMargin | NSViewMinXMargin | NSViewMinYMargin]; |
| 280 | [previewView setAutoresizingMask: NSViewNotSizable | NSViewMaxXMargin | NSViewMaxYMargin | NSViewMinXMargin | NSViewMinYMargin]; |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 281 | connectingCalls = [[NSMutableDictionary alloc] init]; |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 282 | } |
| 283 | |
Anthony Léonard | 66a050c | 2018-01-03 16:32:34 -0500 | [diff] [blame] | 284 | -(void) updateDurationLabel |
| 285 | { |
| 286 | if (accountInfo_ != nil) { |
| 287 | auto* callModel = accountInfo_->callModel.get(); |
| 288 | if (callModel->hasCall(callUid_)) { |
| 289 | auto& callStatus = callModel->getCall(callUid_).status; |
| 290 | if (callStatus != lrc::api::call::Status::ENDED && |
| 291 | callStatus != lrc::api::call::Status::TERMINATING && |
| 292 | callStatus != lrc::api::call::Status::INVALID) { |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 293 | [timeSpentLabel setStringValue:@(callModel->getFormattedCallDuration(callUid_).c_str())]; |
Anthony Léonard | 66a050c | 2018-01-03 16:32:34 -0500 | [diff] [blame] | 294 | return; |
| 295 | } |
| 296 | } |
| 297 | } |
| 298 | |
| 299 | // If call is not running anymore or accountInfo_ is not set for any reason |
| 300 | // we stop the refresh loop |
| 301 | [refreshDurationTimer invalidate]; |
| 302 | refreshDurationTimer = nil; |
Anthony Léonard | 66a050c | 2018-01-03 16:32:34 -0500 | [diff] [blame] | 303 | } |
| 304 | |
Andreas Traczyk | 77a50d5 | 2018-05-08 17:47:31 -0400 | [diff] [blame] | 305 | -(void) updateCall |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 306 | { |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 307 | if (accountInfo_ == nil) |
| 308 | return; |
Alexandre Lision | bb5dbcd | 2015-07-09 16:36:47 -0400 | [diff] [blame] | 309 | |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 310 | auto* callModel = accountInfo_->callModel.get(); |
| 311 | if (not callModel->hasCall(callUid_)) { |
| 312 | return; |
| 313 | } |
Alexandre Lision | 89edc6a | 2015-11-09 11:30:47 -0500 | [diff] [blame] | 314 | |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 315 | auto currentCall = callModel->getCall(callUid_); |
| 316 | NSLog(@"\n status %@ \n",@(lrc::api::call::to_string(currentCall.status).c_str())); |
Anthony Léonard | 8ee2678 | 2018-01-05 10:23:04 -0500 | [diff] [blame] | 317 | auto convIt = getConversationFromUid(convUid_, *accountInfo_->conversationModel); |
Andreas Traczyk | 77a50d5 | 2018-05-08 17:47:31 -0400 | [diff] [blame] | 318 | if (convIt != accountInfo_->conversationModel->allFilteredConversations().end()) { |
| 319 | NSString* bestName = bestNameForConversation(*convIt, *accountInfo_->conversationModel); |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 320 | [contactNameLabel setStringValue:bestName]; |
Andreas Traczyk | 77a50d5 | 2018-05-08 17:47:31 -0400 | [diff] [blame] | 321 | NSString* ringID = bestIDForConversation(*convIt, *accountInfo_->conversationModel); |
| 322 | if([bestName isEqualToString:ringID]) { |
| 323 | ringID = @""; |
| 324 | } |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 325 | [contactIdLabel setStringValue:ringID]; |
Andreas Traczyk | 77a50d5 | 2018-05-08 17:47:31 -0400 | [diff] [blame] | 326 | } |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 327 | [self setupContactInfo:contactPhoto]; |
Andreas Traczyk | 77a50d5 | 2018-05-08 17:47:31 -0400 | [diff] [blame] | 328 | |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 329 | confUid_ = convIt->confId; |
| 330 | [muteAudioButton setHidden:!confUid_.empty()]; |
| 331 | [muteVideoButton setHidden:!confUid_.empty()]; |
| 332 | [recordOnOffButton setHidden:!confUid_.empty()]; |
| 333 | |
Anthony Léonard | 66a050c | 2018-01-03 16:32:34 -0500 | [diff] [blame] | 334 | [timeSpentLabel setStringValue:@(callModel->getFormattedCallDuration(callUid_).c_str())]; |
Anthony Léonard | 66a050c | 2018-01-03 16:32:34 -0500 | [diff] [blame] | 335 | if (refreshDurationTimer == nil) |
| 336 | refreshDurationTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 |
| 337 | target:self |
| 338 | selector:@selector(updateDurationLabel) |
| 339 | userInfo:nil |
| 340 | repeats:YES]; |
Kateryna Kostiuk | 81afce7 | 2018-10-30 16:40:50 -0400 | [diff] [blame] | 341 | [self setBackground]; |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 342 | |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 343 | using Status = lrc::api::call::Status; |
Kateryna Kostiuk | 88a6ee8 | 2019-09-10 17:55:08 -0400 | [diff] [blame] | 344 | if (currentCall.status == Status::PAUSED) { |
| 345 | [holdOnOffButton startBlinkAnimationfrom:[NSColor buttonBlinkColorColor] to:[NSColor whiteColor] scaleFactor: 1.0 duration: 1.5]; |
| 346 | } else { |
| 347 | [holdOnOffButton stopBlinkAnimation]; |
| 348 | } |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 349 | |
Kateryna Kostiuk | a740481 | 2019-10-28 12:24:46 -0400 | [diff] [blame] | 350 | [self setUpButtons: currentCall isRecording: (callModel->isRecording([self getcallID]) || mediaModel->getAlwaysRecord())]; |
| 351 | |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 352 | [videoView setShouldAcceptInteractions: currentCall.status == Status::IN_PROGRESS]; |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 353 | callStateLabel.stringValue = currentCall.status == Status::INCOMING_RINGING ? @"wants to talk to you" : @(to_string(currentCall.status).c_str()); |
| 354 | loadingIndicator.hidden = (currentCall.status == Status::SEARCHING || |
| 355 | currentCall.status == Status::CONNECTING || |
| 356 | currentCall.status == Status::OUTGOING_RINGING) ? NO : YES; |
| 357 | pickUpButton.hidden = (currentCall.status == Status::INCOMING_RINGING) ? NO : YES; |
| 358 | callStateLabel.hidden = (currentCall.status == Status::IN_PROGRESS) ? YES : NO; |
| 359 | cancelCallButton.hidden = (currentCall.status == Status::IN_PROGRESS || |
| 360 | currentCall.status == Status::PAUSED) ? YES : NO; |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 361 | callingWidgetsContainer.hidden = (currentCall.status == Status::IN_PROGRESS) ? NO : YES; |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 362 | |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 363 | switch (currentCall.status) { |
| 364 | case Status::SEARCHING: |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 365 | case Status::CONNECTING: |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 366 | case Status::OUTGOING_RINGING: |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 367 | case Status::INCOMING_RINGING: |
| 368 | [infoContainer setHidden: NO]; |
Andreas Traczyk | 77a50d5 | 2018-05-08 17:47:31 -0400 | [diff] [blame] | 369 | [headerContainer setHidden:YES]; |
Kateryna Kostiuk | 2aa3923 | 2019-10-10 11:55:11 -0400 | [diff] [blame] | 370 | [headerGradientView setHidden:YES]; |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 371 | [controlsPanel setHidden:YES]; |
Kateryna Kostiuk | 2aa3923 | 2019-10-10 11:55:11 -0400 | [diff] [blame] | 372 | [controlsStackView setHidden:YES]; |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 373 | [self.videoMTKView fillWithBlack]; |
| 374 | [self.previewView fillWithBlack]; |
| 375 | [hidePreviewBackground setHidden:YES]; |
| 376 | [self.previewView setHidden: YES]; |
| 377 | [self.videoMTKView setHidden: YES]; |
| 378 | self.previewView.stopRendering = true; |
| 379 | self.videoMTKView.stopRendering = true; |
| 380 | [backgroundImage setHidden:NO]; |
| 381 | [bluerBackgroundEffect setHidden:NO]; |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 382 | break; |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 383 | case Status::PAUSED: |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 384 | [infoContainer setHidden: NO]; |
| 385 | [headerContainer setHidden:NO]; |
Kateryna Kostiuk | 2aa3923 | 2019-10-10 11:55:11 -0400 | [diff] [blame] | 386 | [headerGradientView setHidden:NO]; |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 387 | [controlsPanel setHidden:NO]; |
Kateryna Kostiuk | 2aa3923 | 2019-10-10 11:55:11 -0400 | [diff] [blame] | 388 | [controlsStackView setHidden:NO]; |
Kateryna Kostiuk | 00dcbff | 2019-07-11 15:42:13 -0400 | [diff] [blame] | 389 | [backgroundImage setHidden:NO]; |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 390 | [bluerBackgroundEffect setHidden:NO]; |
| 391 | if(!currentCall.isAudioOnly) { |
| 392 | [self.videoMTKView fillWithBlack]; |
| 393 | [self.previewView fillWithBlack]; |
| 394 | [hidePreviewBackground setHidden:YES]; |
| 395 | [self.previewView setHidden: YES]; |
| 396 | [self.videoMTKView setHidden: YES]; |
| 397 | self.previewView.stopRendering = true; |
| 398 | self.videoMTKView.stopRendering = true; |
| 399 | } |
Kateryna Kostiuk | 00dcbff | 2019-07-11 15:42:13 -0400 | [diff] [blame] | 400 | break; |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 401 | case Status::INACTIVE: |
Kateryna Kostiuk | 00dcbff | 2019-07-11 15:42:13 -0400 | [diff] [blame] | 402 | if(currentCall.isAudioOnly) { |
| 403 | [self setUpAudioOnlyView]; |
| 404 | } else { |
| 405 | [self setUpVideoCallView]; |
| 406 | } |
| 407 | break; |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 408 | case Status::IN_PROGRESS: |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 409 | [headerContainer setHidden:NO]; |
Kateryna Kostiuk | 2aa3923 | 2019-10-10 11:55:11 -0400 | [diff] [blame] | 410 | [headerGradientView setHidden:NO]; |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 411 | [controlsPanel setHidden:NO]; |
Kateryna Kostiuk | 2aa3923 | 2019-10-10 11:55:11 -0400 | [diff] [blame] | 412 | [controlsStackView setHidden:NO]; |
Kateryna Kostiuk | 81afce7 | 2018-10-30 16:40:50 -0400 | [diff] [blame] | 413 | if(currentCall.isAudioOnly) { |
| 414 | [self setUpAudioOnlyView]; |
| 415 | } else { |
| 416 | [self setUpVideoCallView]; |
| 417 | } |
Andreas Traczyk | 77a50d5 | 2018-05-08 17:47:31 -0400 | [diff] [blame] | 418 | break; |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 419 | case Status::CONNECTED: |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 420 | break; |
| 421 | case Status::ENDED: |
| 422 | case Status::TERMINATING: |
| 423 | case Status::INVALID: |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 424 | case Status::PEER_BUSY: |
| 425 | case Status::TIMEOUT: |
| 426 | connectingCalls[@(callUid_.c_str())] = nil; |
| 427 | //[self cleanUp]; |
| 428 | [self.delegate callFinished]; |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 429 | break; |
| 430 | } |
Alexandre Lision | 4d9905e | 2016-01-22 12:01:36 -0500 | [diff] [blame] | 431 | } |
| 432 | |
Kateryna Kostiuk | 81afce7 | 2018-10-30 16:40:50 -0400 | [diff] [blame] | 433 | -(void) setUpVideoCallView { |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 434 | [previewView fillWithBlack]; |
| 435 | [self.videoMTKView fillWithBlack]; |
Kateryna Kostiuk | 81afce7 | 2018-10-30 16:40:50 -0400 | [diff] [blame] | 436 | [previewView setHidden: NO]; |
Kateryna Kostiuk | 00dcbff | 2019-07-11 15:42:13 -0400 | [diff] [blame] | 437 | [self.videoMTKView setHidden:NO]; |
Kateryna Kostiuk | 0ee5cbd | 2019-10-08 12:14:33 -0400 | [diff] [blame] | 438 | [hidePreviewBackground setHidden: self.previewView.stopRendering]; |
Kateryna Kostiuk | 81afce7 | 2018-10-30 16:40:50 -0400 | [diff] [blame] | 439 | [bluerBackgroundEffect setHidden:YES]; |
Kateryna Kostiuk | 81afce7 | 2018-10-30 16:40:50 -0400 | [diff] [blame] | 440 | [backgroundImage setHidden:YES]; |
Kateryna Kostiuk | 0ee5cbd | 2019-10-08 12:14:33 -0400 | [diff] [blame] | 441 | self.previewView.stopRendering = false; |
| 442 | self.videoMTKView.stopRendering = false; |
Kateryna Kostiuk | 81afce7 | 2018-10-30 16:40:50 -0400 | [diff] [blame] | 443 | } |
| 444 | |
| 445 | -(void) setUpAudioOnlyView { |
Kateryna Kostiuk | 00dcbff | 2019-07-11 15:42:13 -0400 | [diff] [blame] | 446 | [self.previewView setHidden: YES]; |
| 447 | [self.videoMTKView setHidden: YES]; |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 448 | [hidePreviewBackground setHidden: YES]; |
| 449 | [bluerBackgroundEffect setHidden:NO]; |
| 450 | [backgroundImage setHidden:NO]; |
Kateryna Kostiuk | 81afce7 | 2018-10-30 16:40:50 -0400 | [diff] [blame] | 451 | } |
| 452 | |
| 453 | -(void) setBackground { |
Andreas Traczyk | 77a50d5 | 2018-05-08 17:47:31 -0400 | [diff] [blame] | 454 | auto* convModel = accountInfo_->conversationModel.get(); |
| 455 | auto it = getConversationFromUid(convUid_, *convModel); |
Kateryna Kostiuk | 81afce7 | 2018-10-30 16:40:50 -0400 | [diff] [blame] | 456 | NSImage *image= [self getContactImageOfSize:120.0 withDefaultAvatar:NO]; |
| 457 | if(image) { |
Kateryna Kostiuk | 89398b6 | 2018-11-20 16:45:04 -0500 | [diff] [blame] | 458 | CIImage * ciImage = [[CIImage alloc] initWithData:[image TIFFRepresentation]]; |
| 459 | CIContext *context = [[CIContext alloc] init]; |
| 460 | CIFilter *clamp = [CIFilter filterWithName:@"CIAffineClamp"]; |
| 461 | [clamp setValue:[NSAffineTransform transform] forKey:@"inputTransform"]; |
| 462 | [clamp setValue:ciImage forKey: kCIInputImageKey]; |
Kateryna Kostiuk | 81afce7 | 2018-10-30 16:40:50 -0400 | [diff] [blame] | 463 | CIFilter* bluerFilter = [CIFilter filterWithName:@"CIGaussianBlur"]; |
| 464 | [bluerFilter setDefaults]; |
Kateryna Kostiuk | 89398b6 | 2018-11-20 16:45:04 -0500 | [diff] [blame] | 465 | [bluerFilter setValue:[NSNumber numberWithFloat: 9] forKey:@"inputRadius"]; |
| 466 | [bluerFilter setValue:[clamp valueForKey:kCIOutputImageKey] forKey: kCIInputImageKey]; |
| 467 | CIImage *result = [bluerFilter valueForKey:kCIOutputImageKey]; |
| 468 | CGRect extent = [result extent]; |
| 469 | CGImageRef cgImage = [context createCGImage:result fromRect: [ciImage extent]]; |
| 470 | NSImage *bluredImage = [[NSImage alloc] initWithCGImage:cgImage size:NSSizeFromCGSize(CGSizeMake(image.size.width, image.size.height))]; |
| 471 | backgroundImage.layer.contents = bluredImage; |
Kateryna Kostiuk | 81afce7 | 2018-10-30 16:40:50 -0400 | [diff] [blame] | 472 | [backgroundImage setHidden:NO]; |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 473 | [bluerBackgroundEffect setFillColor:[NSColor darkGrayColor]]; |
| 474 | [bluerBackgroundEffect setAlphaValue:0.6]; |
Kateryna Kostiuk | 81afce7 | 2018-10-30 16:40:50 -0400 | [diff] [blame] | 475 | } else { |
Kateryna Kostiuk | 2aa3923 | 2019-10-10 11:55:11 -0400 | [diff] [blame] | 476 | contactNameLabel.textColor = [NSColor textColor]; |
Kateryna Kostiuk | 2aa3923 | 2019-10-10 11:55:11 -0400 | [diff] [blame] | 477 | contactIdLabel.textColor = [NSColor textColor]; |
| 478 | callStateLabel.textColor = [NSColor textColor]; |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 479 | backgroundImage.layer.contents = nil; |
Kateryna Kostiuk | 2aa3923 | 2019-10-10 11:55:11 -0400 | [diff] [blame] | 480 | [bluerBackgroundEffect setFillColor:[NSColor windowBackgroundColor]]; |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 481 | [bluerBackgroundEffect setAlphaValue:1]; |
Kateryna Kostiuk | 81afce7 | 2018-10-30 16:40:50 -0400 | [diff] [blame] | 482 | [backgroundImage setHidden:YES]; |
Andreas Traczyk | 77a50d5 | 2018-05-08 17:47:31 -0400 | [diff] [blame] | 483 | } |
| 484 | } |
| 485 | |
Kateryna Kostiuk | 133364b | 2018-10-31 11:36:08 -0400 | [diff] [blame] | 486 | -(NSImage *) getContactImageOfSize: (double) size withDefaultAvatar:(BOOL) shouldDrawDefault { |
Kateryna Kostiuk | 81afce7 | 2018-10-30 16:40:50 -0400 | [diff] [blame] | 487 | auto* convModel = accountInfo_->conversationModel.get(); |
| 488 | auto convIt = getConversationFromUid(convUid_, *convModel); |
| 489 | if (convIt == convModel->allFilteredConversations().end()) { |
| 490 | return nil; |
| 491 | } |
| 492 | if(shouldDrawDefault) { |
| 493 | auto& imgManip = reinterpret_cast<Interfaces::ImageManipulationDelegate&>(GlobalInstances::pixmapManipulator()); |
| 494 | QVariant photo = imgManip.conversationPhoto(*convIt, *accountInfo_, QSize(size, size), NO); |
| 495 | return QtMac::toNSImage(qvariant_cast<QPixmap>(photo)); |
| 496 | } |
| 497 | auto contact = accountInfo_->contactModel->getContact(convIt->participants[0]); |
| 498 | NSData *imageData = [[NSData alloc] initWithBase64EncodedString:@(contact.profileInfo.avatar.c_str()) options:NSDataBase64DecodingIgnoreUnknownCharacters]; |
| 499 | return [[NSImage alloc] initWithData:imageData]; |
| 500 | } |
| 501 | |
Kateryna Kostiuk | 81afce7 | 2018-10-30 16:40:50 -0400 | [diff] [blame] | 502 | -(void) setupContactInfo:(NSImageView*)imageView |
| 503 | { |
| 504 | [imageView setImage: [self getContactImageOfSize:120.0 withDefaultAvatar:YES]]; |
| 505 | } |
| 506 | |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 507 | -(void)collapseRightView |
| 508 | { |
| 509 | NSView *right = [[splitView subviews] objectAtIndex:1]; |
| 510 | NSView *left = [[splitView subviews] objectAtIndex:0]; |
| 511 | NSRect leftFrame = [left frame]; |
| 512 | [right setHidden:YES]; |
| 513 | [splitView display]; |
| 514 | } |
| 515 | |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 516 | -(void) connectVideoSignals |
| 517 | { |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 518 | if (accountInfo_ == nil) |
| 519 | return; |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 520 | [self connectRenderer]; |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 521 | } |
| 522 | |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 523 | -(void) connectRenderer |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 524 | { |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 525 | QObject::disconnect(renderConnections.frameUpdated); |
| 526 | QObject::disconnect(renderConnections.stopped); |
| 527 | QObject::disconnect(renderConnections.started); |
| 528 | renderConnections.started = |
| 529 | QObject::connect(mediaModel, |
| 530 | &lrc::api::AVModel::rendererStarted, |
| 531 | [=](const std::string& id) { |
| 532 | if (id == lrc::api::video::PREVIEW_RENDERER_ID) { |
| 533 | [self.previewView setHidden:NO]; |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 534 | [hidePreviewBackground setHidden: NO]; |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 535 | self.previewView.stopRendering = false; |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 536 | } else if ([self isCurrentCall: id]) { |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 537 | [self mouseIsMoving: NO]; |
| 538 | self.videoMTKView.stopRendering = false; |
| 539 | [self.videoMTKView setHidden:NO]; |
| 540 | [bluerBackgroundEffect setHidden:YES]; |
| 541 | [backgroundImage setHidden:YES]; |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 542 | } |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 543 | }); |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 544 | renderConnections.stopped = |
| 545 | QObject::connect(mediaModel, |
| 546 | &lrc::api::AVModel::rendererStopped, |
| 547 | [=](const std::string& id) { |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 548 | if (id == lrc::api::video::PREVIEW_RENDERER_ID) { |
| 549 | [self.previewView setHidden:YES]; |
| 550 | self.previewView.stopRendering = true; |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 551 | } else if ([self isCurrentCall: id]) { |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 552 | [self mouseIsMoving: YES]; |
| 553 | self.videoMTKView.stopRendering = true; |
| 554 | [self.videoMTKView setHidden:YES]; |
| 555 | [bluerBackgroundEffect setHidden:NO]; |
| 556 | [backgroundImage setHidden:NO]; |
Kateryna Kostiuk | 00dcbff | 2019-07-11 15:42:13 -0400 | [diff] [blame] | 557 | } |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 558 | }); |
| 559 | renderConnections.frameUpdated = |
| 560 | QObject::connect(mediaModel, |
| 561 | &lrc::api::AVModel::frameUpdated, |
| 562 | [=](const std::string& id) { |
| 563 | if (id == lrc::api::video::PREVIEW_RENDERER_ID) { |
| 564 | auto renderer = &mediaModel->getRenderer(lrc::api::video::PREVIEW_RENDERER_ID); |
| 565 | if(!renderer->isRendering()) { |
| 566 | return; |
| 567 | } |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 568 | [hidePreviewBackground setHidden: self.previewView.stopRendering]; |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 569 | [self renderer: renderer renderFrameForPreviewView:previewView]; |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 570 | } else if ([self isCurrentCall: id]) { |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 571 | auto renderer = &mediaModel->getRenderer(id); |
| 572 | if(!renderer->isRendering()) { |
| 573 | return; |
| 574 | } |
| 575 | [self renderer:renderer renderFrameForDistantView: self.videoMTKView]; |
Kateryna Kostiuk | 732b406 | 2018-11-28 09:59:28 -0500 | [diff] [blame] | 576 | } |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 577 | }); |
| 578 | } |
| 579 | |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 580 | -(void) renderer: (const lrc::api::video::Renderer*)renderer renderFrameForPreviewView:(CallMTKView*) view |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 581 | { |
Kateryna Kostiuk | 00dcbff | 2019-07-11 15:42:13 -0400 | [diff] [blame] | 582 | @autoreleasepool { |
| 583 | auto framePtr = renderer->currentAVFrame(); |
| 584 | auto frame = framePtr.get(); |
| 585 | if(!frame || !frame->width || !frame->height) { |
| 586 | return; |
| 587 | } |
| 588 | auto frameSize = CGSizeMake(frame->width, frame->height); |
| 589 | auto rotation = 0; |
| 590 | if (frame->data[3] != NULL && (CVPixelBufferRef)frame->data[3]) { |
| 591 | [view renderWithPixelBuffer:(CVPixelBufferRef)frame->data[3] |
| 592 | size: frameSize |
| 593 | rotation: rotation |
| 594 | fillFrame: true]; |
| 595 | return; |
| 596 | } |
| 597 | else if (CVPixelBufferRef pixelBuffer = [self getBufferForPreviewFromFrame:frame]) { |
| 598 | [view renderWithPixelBuffer: pixelBuffer |
| 599 | size: frameSize |
| 600 | rotation: rotation |
| 601 | fillFrame: true]; |
| 602 | } |
| 603 | } |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 604 | } |
| 605 | |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 606 | -(void) renderer: (const lrc::api::video::Renderer*)renderer renderFrameForDistantView:(CallMTKView*) view |
Anthony Léonard | 14e7bf3 | 2017-06-08 08:13:16 -0400 | [diff] [blame] | 607 | { |
Kateryna Kostiuk | 00dcbff | 2019-07-11 15:42:13 -0400 | [diff] [blame] | 608 | @autoreleasepool { |
| 609 | auto framePtr = renderer->currentAVFrame(); |
| 610 | auto frame = framePtr.get(); |
| 611 | if(!frame || !frame->width || !frame->height) { |
| 612 | return; |
| 613 | } |
| 614 | auto frameSize = CGSizeMake(frame->width, frame->height); |
| 615 | auto rotation = 0; |
| 616 | if (auto matrix = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX)) { |
| 617 | const int32_t* data = reinterpret_cast<int32_t*>(matrix->data); |
| 618 | rotation = av_display_rotation_get(data); |
| 619 | } |
| 620 | if (frame->data[3] != NULL && (CVPixelBufferRef)frame->data[3]) { |
| 621 | [view renderWithPixelBuffer: (CVPixelBufferRef)frame->data[3] |
| 622 | size: frameSize |
| 623 | rotation: rotation |
| 624 | fillFrame: false]; |
| 625 | } |
| 626 | if (CVPixelBufferRef pixelBuffer = [self getBufferForDistantViewFromFrame:frame]) { |
| 627 | [view renderWithPixelBuffer: pixelBuffer |
| 628 | size: frameSize |
| 629 | rotation: rotation |
| 630 | fillFrame: false]; |
| 631 | } |
Kateryna Kostiuk | bcf24e9 | 2018-11-20 10:09:06 -0500 | [diff] [blame] | 632 | } |
Anthony Léonard | 14e7bf3 | 2017-06-08 08:13:16 -0400 | [diff] [blame] | 633 | } |
| 634 | |
Kateryna Kostiuk | 00dcbff | 2019-07-11 15:42:13 -0400 | [diff] [blame] | 635 | -(CVPixelBufferRef) getBufferForPreviewFromFrame:(const AVFrame*)frame { |
Kateryna Kostiuk | c5fd3b9 | 2019-07-24 10:12:44 -0400 | [diff] [blame] | 636 | [VideoCommon fillPixelBuffr:&pixelBufferPreview fromFrame:frame bufferPool:&pixelBufferPoolPreview]; |
| 637 | CVPixelBufferRef buffer = pixelBufferPreview; |
| 638 | return buffer; |
Kateryna Kostiuk | 00dcbff | 2019-07-11 15:42:13 -0400 | [diff] [blame] | 639 | } |
| 640 | |
| 641 | -(CVPixelBufferRef) getBufferForDistantViewFromFrame:(const AVFrame*)frame { |
Kateryna Kostiuk | c5fd3b9 | 2019-07-24 10:12:44 -0400 | [diff] [blame] | 642 | [VideoCommon fillPixelBuffr:&pixelBufferDistantView fromFrame:frame bufferPool:&pixelBufferPoolDistantView]; |
| 643 | CVPixelBufferRef buffer = pixelBufferDistantView; |
| 644 | return buffer; |
Kateryna Kostiuk | 00dcbff | 2019-07-11 15:42:13 -0400 | [diff] [blame] | 645 | } |
| 646 | |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 647 | - (void) initFrame |
| 648 | { |
| 649 | [self.view setFrame:self.view.superview.bounds]; |
| 650 | [self.view setHidden:YES]; |
| 651 | self.view.layer.position = self.view.frame.origin; |
Alexandre Lision | bb5dbcd | 2015-07-09 16:36:47 -0400 | [diff] [blame] | 652 | [self collapseRightView]; |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 653 | } |
| 654 | |
| 655 | # pragma private IN/OUT animations |
| 656 | |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 657 | -(void)uncollapseRightView |
| 658 | { |
| 659 | NSView *left = [[splitView subviews] objectAtIndex:0]; |
| 660 | NSView *right = [[splitView subviews] objectAtIndex:1]; |
| 661 | [right setHidden:NO]; |
| 662 | |
| 663 | CGFloat dividerThickness = [splitView dividerThickness]; |
| 664 | |
| 665 | // get the different frames |
| 666 | NSRect leftFrame = [left frame]; |
| 667 | NSRect rightFrame = [right frame]; |
| 668 | |
| 669 | leftFrame.size.width = (leftFrame.size.width - rightFrame.size.width - dividerThickness); |
| 670 | rightFrame.origin.x = leftFrame.size.width + dividerThickness; |
| 671 | [left setFrameSize:leftFrame.size]; |
| 672 | [right setFrame:rightFrame]; |
| 673 | [splitView display]; |
| 674 | |
| 675 | [self.chatVC takeFocus]; |
| 676 | } |
| 677 | |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 678 | -(void) cleanUp |
| 679 | { |
Anthony Léonard | 5c28764 | 2018-02-21 15:54:19 -0500 | [diff] [blame] | 680 | if(self.splitView.isInFullScreenMode) |
| 681 | [self.splitView exitFullScreenModeWithOptions:nil]; |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 682 | QObject::disconnect(renderConnections.frameUpdated); |
| 683 | QObject::disconnect(renderConnections.started); |
| 684 | QObject::disconnect(renderConnections.stopped); |
Anthony Léonard | c0013bb | 2018-02-20 16:23:02 -0500 | [diff] [blame] | 685 | QObject::disconnect(self.messageConnection); |
Alexandre Lision | 883719f | 2015-10-22 17:37:45 -0400 | [diff] [blame] | 686 | |
Alexandre Lision | 4baba4c | 2016-02-11 13:00:57 -0500 | [diff] [blame] | 687 | [self.chatButton setPressed:NO]; |
Alexandre Lision | 883719f | 2015-10-22 17:37:45 -0400 | [diff] [blame] | 688 | [self collapseRightView]; |
Alexandre Lision | 5722777 | 2016-01-15 17:19:36 -0500 | [diff] [blame] | 689 | |
Alexandre Lision | 5722777 | 2016-01-15 17:19:36 -0500 | [diff] [blame] | 690 | [timeSpentLabel setStringValue:@""]; |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 691 | [contactIdLabel setStringValue:@""]; |
| 692 | [contactNameLabel setStringValue:@""]; |
| 693 | [contactPhoto setImage:nil]; |
Kateryna Kostiuk | 81afce7 | 2018-10-30 16:40:50 -0400 | [diff] [blame] | 694 | //background view |
| 695 | [bluerBackgroundEffect setHidden:NO]; |
| 696 | [backgroundImage setHidden:NO]; |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 697 | backgroundImage.layer.contents = nil; |
Kateryna Kostiuk | 00dcbff | 2019-07-11 15:42:13 -0400 | [diff] [blame] | 698 | [self.previewView setHidden:YES]; |
| 699 | [self.videoMTKView setHidden:YES]; |
Kateryna Kostiuk | 9e9f782 | 2019-09-27 11:29:45 -0400 | [diff] [blame] | 700 | |
| 701 | contactNameLabel.textColor = [NSColor highlightColor]; |
| 702 | contactNameLabel.textColor = [NSColor highlightColor]; |
| 703 | contactIdLabel.textColor = [NSColor highlightColor]; |
| 704 | callStateLabel.textColor = [NSColor highlightColor]; |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 705 | } |
| 706 | |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 707 | /* |
| 708 | * update ui |
| 709 | */ |
| 710 | |
Andreas Traczyk | ecdc4fa | 2018-03-22 16:11:47 -0400 | [diff] [blame] | 711 | -(void) setupCallView |
| 712 | { |
| 713 | if (accountInfo_ == nil) |
| 714 | return; |
| 715 | |
| 716 | auto* callModel = accountInfo_->callModel.get(); |
Andreas Traczyk | ecdc4fa | 2018-03-22 16:11:47 -0400 | [diff] [blame] | 717 | |
Andreas Traczyk | ecdc4fa | 2018-03-22 16:11:47 -0400 | [diff] [blame] | 718 | /* check if text media is already present */ |
| 719 | if(not callModel->hasCall(callUid_)) |
| 720 | return; |
| 721 | |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 722 | // when call comes in we want to show the controls/header |
| 723 | [self mouseIsMoving: YES]; |
Andreas Traczyk | ecdc4fa | 2018-03-22 16:11:47 -0400 | [diff] [blame] | 724 | [loadingIndicator setAnimates:YES]; |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 725 | auto currentCall = callModel->getCall([self getcallID]); |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 726 | [previewView setHidden: YES]; |
| 727 | [self setUpPreviewFrame]; |
| 728 | [self updatePendingCalls]; |
Andreas Traczyk | 77a50d5 | 2018-05-08 17:47:31 -0400 | [diff] [blame] | 729 | [self updateCall]; |
Andreas Traczyk | ecdc4fa | 2018-03-22 16:11:47 -0400 | [diff] [blame] | 730 | } |
| 731 | |
| 732 | -(void) showWithAnimation:(BOOL)animate |
| 733 | { |
| 734 | if (!animate) { |
| 735 | [self.view setHidden:NO]; |
| 736 | [self setupCallView]; |
| 737 | return; |
| 738 | } |
| 739 | |
| 740 | CGRect frame = CGRectOffset(self.view.superview.bounds, -self.view.superview.bounds.size.width, 0); |
| 741 | [self.view setHidden:NO]; |
| 742 | |
| 743 | [CATransaction begin]; |
| 744 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"]; |
| 745 | [animation setFromValue:[NSValue valueWithPoint:frame.origin]]; |
| 746 | [animation setToValue:[NSValue valueWithPoint:self.view.superview.bounds.origin]]; |
| 747 | [animation setDuration:0.2f]; |
| 748 | [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]]; |
| 749 | [CATransaction setCompletionBlock:^{ |
| 750 | [self setupCallView]; |
| 751 | }]; |
| 752 | |
| 753 | [self.view.layer addAnimation:animation forKey:animation.keyPath]; |
| 754 | [CATransaction commit]; |
| 755 | } |
| 756 | |
| 757 | -(void) hideWithAnimation:(BOOL)animate |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 758 | { |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 759 | if(self.view.frame.origin.x < 0) { |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 760 | return; |
| 761 | } |
| 762 | |
Andreas Traczyk | ecdc4fa | 2018-03-22 16:11:47 -0400 | [diff] [blame] | 763 | if (!animate) { |
| 764 | [self.view setHidden:YES]; |
| 765 | return; |
| 766 | } |
| 767 | |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 768 | CGRect frame = CGRectOffset(self.view.frame, -self.view.frame.size.width, 0); |
| 769 | [CATransaction begin]; |
| 770 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"]; |
| 771 | [animation setFromValue:[NSValue valueWithPoint:self.view.frame.origin]]; |
| 772 | [animation setToValue:[NSValue valueWithPoint:frame.origin]]; |
| 773 | [animation setDuration:0.2f]; |
Alexandre Lision | 22d615b | 2016-01-25 12:54:34 -0500 | [diff] [blame] | 774 | [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]]; |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 775 | |
| 776 | [CATransaction setCompletionBlock:^{ |
| 777 | [self.view setHidden:YES]; |
Alexandre Lision | ef6333a | 2015-03-24 12:30:31 -0400 | [diff] [blame] | 778 | // first make sure everything is disconnected |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 779 | [self cleanUp]; |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 780 | // if (currentCall_) { |
| 781 | // [self animateIn]; |
| 782 | // } |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 783 | }]; |
| 784 | [self.view.layer addAnimation:animation forKey:animation.keyPath]; |
Alexandre Lision | a1c6d75 | 2015-06-23 12:27:38 -0400 | [diff] [blame] | 785 | |
| 786 | [self.view.layer setPosition:frame.origin]; |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 787 | [CATransaction commit]; |
| 788 | } |
| 789 | |
| 790 | /** |
| 791 | * Debug purpose |
| 792 | */ |
| 793 | -(void) dumpFrame:(CGRect) frame WithName:(NSString*) name |
| 794 | { |
| 795 | NSLog(@"frame %@ : %f %f %f %f \n\n",name ,frame.origin.x, frame.origin.y, frame.size.width, frame.size.height); |
| 796 | } |
| 797 | |
Alexandre Lision | 58cab67 | 2015-06-09 15:25:40 -0400 | [diff] [blame] | 798 | #pragma mark - Button methods |
| 799 | |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 800 | - (IBAction)hangUp:(id)sender { |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 801 | if (accountInfo_ == nil) |
| 802 | return; |
| 803 | |
| 804 | auto* callModel = accountInfo_->callModel.get(); |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 805 | callModel->hangUp([self getcallID]); |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 806 | } |
| 807 | |
| 808 | - (IBAction)accept:(id)sender { |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 809 | if (accountInfo_ == nil) |
| 810 | return; |
| 811 | |
Anthony Léonard | f584cc5 | 2018-01-19 12:00:19 -0500 | [diff] [blame] | 812 | // If we accept a conversation with a non trusted contact, we first accept it |
| 813 | auto convIt = getConversationFromUid(convUid_, *accountInfo_->conversationModel.get()); |
| 814 | if (convIt != accountInfo_->conversationModel->allFilteredConversations().end()) { |
| 815 | auto& contact = accountInfo_->contactModel->getContact(convIt->participants[0]); |
| 816 | if (contact.profileInfo.type == lrc::api::profile::Type::PENDING) |
| 817 | accountInfo_->conversationModel->makePermanent(convUid_); |
| 818 | } |
| 819 | |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 820 | auto* callModel = accountInfo_->callModel.get(); |
| 821 | |
| 822 | callModel->accept(callUid_); |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 823 | } |
| 824 | |
| 825 | - (IBAction)toggleRecording:(id)sender { |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 826 | if (accountInfo_ == nil) |
| 827 | return; |
| 828 | |
| 829 | auto* callModel = accountInfo_->callModel.get(); |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 830 | callModel->toggleAudioRecord(callUid_); |
Kateryna Kostiuk | 88a6ee8 | 2019-09-10 17:55:08 -0400 | [diff] [blame] | 831 | if (callModel->isRecording(callUid_)) { |
| 832 | [recordOnOffButton startBlinkAnimationfrom:[NSColor buttonBlinkColorColor] to:[NSColor whiteColor] scaleFactor: 1 duration: 1.5]; |
| 833 | } else { |
| 834 | [recordOnOffButton stopBlinkAnimation]; |
| 835 | } |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 836 | } |
| 837 | |
| 838 | - (IBAction)toggleHold:(id)sender { |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 839 | if (accountInfo_ == nil) |
| 840 | return; |
| 841 | |
| 842 | auto* callModel = accountInfo_->callModel.get(); |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 843 | callModel->togglePause([self getcallID]); |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 844 | } |
| 845 | |
Alexandre Lision | 6200531 | 2016-01-28 15:55:16 -0500 | [diff] [blame] | 846 | - (IBAction)showDialpad:(id)sender { |
| 847 | AppDelegate* appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate]; |
| 848 | [appDelegate showDialpad]; |
| 849 | } |
| 850 | |
Alexandre Lision | 58cab67 | 2015-06-09 15:25:40 -0400 | [diff] [blame] | 851 | -(IBAction)toggleChat:(id)sender; |
| 852 | { |
| 853 | BOOL rightViewCollapsed = [[self splitView] isSubviewCollapsed:[[[self splitView] subviews] objectAtIndex: 1]]; |
| 854 | if (rightViewCollapsed) { |
| 855 | [self uncollapseRightView]; |
Alexandre Lision | 58cab67 | 2015-06-09 15:25:40 -0400 | [diff] [blame] | 856 | } else { |
| 857 | [self collapseRightView]; |
| 858 | } |
Alexandre Lision | 6200531 | 2016-01-28 15:55:16 -0500 | [diff] [blame] | 859 | [chatButton setPressed:rightViewCollapsed]; |
Alexandre Lision | 58cab67 | 2015-06-09 15:25:40 -0400 | [diff] [blame] | 860 | } |
| 861 | |
Alexandre Lision | d18fa27 | 2015-06-15 11:18:03 -0400 | [diff] [blame] | 862 | - (IBAction)muteAudio:(id)sender |
| 863 | { |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 864 | if (accountInfo_ == nil) |
| 865 | return; |
| 866 | |
| 867 | auto* callModel = accountInfo_->callModel.get(); |
Kateryna Kostiuk | 54d7697 | 2018-06-07 15:45:07 -0400 | [diff] [blame] | 868 | auto currentCall = callModel->getCall(callUid_); |
| 869 | if (currentCall.audioMuted) { |
| 870 | muteAudioButton.image = [NSImage imageNamed:@"ic_action_audio.png"]; |
| 871 | } else { |
| 872 | muteAudioButton.image = [NSImage imageNamed:@"ic_action_mute_audio.png"]; |
| 873 | } |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 874 | callModel->toggleMedia(callUid_, lrc::api::NewCallModel::Media::AUDIO); |
Alexandre Lision | d18fa27 | 2015-06-15 11:18:03 -0400 | [diff] [blame] | 875 | } |
| 876 | |
| 877 | - (IBAction)muteVideo:(id)sender |
| 878 | { |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 879 | if (accountInfo_ == nil) |
| 880 | return; |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 881 | auto* callModel = accountInfo_->callModel.get(); |
Kateryna Kostiuk | 54d7697 | 2018-06-07 15:45:07 -0400 | [diff] [blame] | 882 | auto currentCall = callModel->getCall(callUid_); |
| 883 | if(!currentCall.isAudioOnly) { |
| 884 | if (currentCall.videoMuted) { |
| 885 | muteVideoButton.image = [NSImage imageNamed:@"ic_action_video.png"]; |
| 886 | } else { |
| 887 | muteVideoButton.image = [NSImage imageNamed:@"ic_action_mute_video.png"]; |
| 888 | } |
| 889 | } |
Olivier Soldano | 994971f | 2017-12-05 16:30:12 -0500 | [diff] [blame] | 890 | callModel->toggleMedia(callUid_, lrc::api::NewCallModel::Media::VIDEO); |
Alexandre Lision | d18fa27 | 2015-06-15 11:18:03 -0400 | [diff] [blame] | 891 | } |
Alexandre Lision | 883719f | 2015-10-22 17:37:45 -0400 | [diff] [blame] | 892 | |
| 893 | - (IBAction)toggleTransferView:(id)sender { |
Kateryna Kostiuk | 1ba5a01 | 2018-12-12 17:07:38 -0500 | [diff] [blame] | 894 | |
Alexandre Lision | f23ec5a | 2015-07-16 11:24:06 -0400 | [diff] [blame] | 895 | } |
Alexandre Lision | d18fa27 | 2015-06-15 11:18:03 -0400 | [diff] [blame] | 896 | |
Alexandre Lision | 89edc6a | 2015-11-09 11:30:47 -0500 | [diff] [blame] | 897 | - (IBAction)toggleAddParticipantView:(id)sender { |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 898 | if (brokerPopoverVC != nullptr) { |
| 899 | [brokerPopoverVC performClose:self]; |
| 900 | brokerPopoverVC = NULL; |
| 901 | } else { |
| 902 | auto* contactSelectorVC = [[ChooseContactVC alloc] initWithNibName:@"ChooseContactVC" bundle:nil]; |
| 903 | auto* convModel = accountInfo_->conversationModel.get(); |
| 904 | [contactSelectorVC setConversationModel:convModel andCurrentConversation: convUid_]; |
| 905 | contactSelectorVC.delegate = self; |
| 906 | brokerPopoverVC = [[NSPopover alloc] init]; |
| 907 | [brokerPopoverVC setContentSize:contactSelectorVC.view.frame.size]; |
| 908 | [brokerPopoverVC setContentViewController:contactSelectorVC]; |
| 909 | [brokerPopoverVC setAnimates:YES]; |
| 910 | [brokerPopoverVC setBehavior:NSPopoverBehaviorTransient]; |
| 911 | [brokerPopoverVC setDelegate:self]; |
| 912 | [brokerPopoverVC showRelativeToRect:[sender bounds] ofView:sender preferredEdge:NSMinYEdge]; |
| 913 | } |
Alexandre Lision | 89edc6a | 2015-11-09 11:30:47 -0500 | [diff] [blame] | 914 | } |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 915 | |
Kateryna Kostiuk | 6891d4f | 2019-09-19 17:44:33 -0400 | [diff] [blame] | 916 | - (IBAction)hidePreview:(id)sender { |
| 917 | CGRect previewFrame = previewView.frame; |
Kateryna Kostiuk | 2aa3923 | 2019-10-10 11:55:11 -0400 | [diff] [blame] | 918 | CGRect newPreviewFrame;//, bcHidePreviewFrame; |
| 919 | if (previewFrame.size.width > HIDE_PREVIEW_BUTTON_SIZE) { |
Kateryna Kostiuk | 6891d4f | 2019-09-19 17:44:33 -0400 | [diff] [blame] | 920 | self.movableBaseForView.movable = false; |
| 921 | newPreviewFrame = self.getVideoPreviewCollapsedSize; |
Kateryna Kostiuk | 6891d4f | 2019-09-19 17:44:33 -0400 | [diff] [blame] | 922 | hidePreviewButton.image = [NSImage imageNamed: NSImageNameTouchBarEnterFullScreenTemplate]; |
| 923 | } else { |
| 924 | self.movableBaseForView.movable = true; |
| 925 | newPreviewFrame = CGRectMake(0, 0, PREVIEW_WIDTH, PREVIEW_HEIGHT); |
Kateryna Kostiuk | 6891d4f | 2019-09-19 17:44:33 -0400 | [diff] [blame] | 926 | hidePreviewButton.image = [NSImage imageNamed: NSImageNameTouchBarExitFullScreenTemplate]; |
| 927 | } |
| 928 | [NSAnimationContext runAnimationGroup:^(NSAnimationContext * _Nonnull context) { |
| 929 | context.duration = 0.2f; |
| 930 | context.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseOut]; |
| 931 | previewView.animator.frame = newPreviewFrame; |
| 932 | } completionHandler: nil]; |
Kateryna Kostiuk | 6891d4f | 2019-09-19 17:44:33 -0400 | [diff] [blame] | 933 | } |
Alexandre Lision | 89edc6a | 2015-11-09 11:30:47 -0500 | [diff] [blame] | 934 | |
Alexandre Lision | 58cab67 | 2015-06-09 15:25:40 -0400 | [diff] [blame] | 935 | #pragma mark - NSSplitViewDelegate |
| 936 | |
| 937 | /* Return YES if the subview should be collapsed because the user has double-clicked on an adjacent divider. If a split view has a delegate, and the delegate responds to this message, it will be sent once for the subview before a divider when the user double-clicks on that divider, and again for the subview after the divider, but only if the delegate returned YES when sent -splitView:canCollapseSubview: for the subview in question. When the delegate indicates that both subviews should be collapsed NSSplitView's behavior is undefined. |
| 938 | */ |
| 939 | - (BOOL)splitView:(NSSplitView *)splitView shouldCollapseSubview:(NSView *)subview forDoubleClickOnDividerAtIndex:(NSInteger)dividerIndex; |
| 940 | { |
| 941 | NSView* rightView = [[splitView subviews] objectAtIndex:1]; |
| 942 | return ([subview isEqual:rightView]); |
| 943 | } |
| 944 | |
| 945 | |
| 946 | - (BOOL)splitView:(NSSplitView *)splitView canCollapseSubview:(NSView *)subview; |
| 947 | { |
| 948 | NSView* rightView = [[splitView subviews] objectAtIndex:1]; |
| 949 | return ([subview isEqual:rightView]); |
| 950 | } |
| 951 | |
| 952 | |
Alexandre Lision | a1eee3c | 2015-08-10 13:44:51 -0400 | [diff] [blame] | 953 | # pragma mark - CallnDelegate |
Alexandre Lision | 58cab67 | 2015-06-09 15:25:40 -0400 | [diff] [blame] | 954 | |
| 955 | - (void) callShouldToggleFullScreen |
| 956 | { |
| 957 | if(self.splitView.isInFullScreenMode) |
| 958 | [self.splitView exitFullScreenModeWithOptions:nil]; |
| 959 | else { |
| 960 | NSApplicationPresentationOptions options = NSApplicationPresentationDefault +NSApplicationPresentationAutoHideDock + |
| 961 | NSApplicationPresentationAutoHideMenuBar + NSApplicationPresentationAutoHideToolbar; |
| 962 | NSDictionary *opts = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInt:options], |
| 963 | NSFullScreenModeApplicationPresentationOptions, nil]; |
| 964 | |
| 965 | [self.splitView enterFullScreenMode:[NSScreen mainScreen] withOptions:opts]; |
| 966 | } |
| 967 | } |
| 968 | |
Alexandre Lision | a1eee3c | 2015-08-10 13:44:51 -0400 | [diff] [blame] | 969 | -(void) mouseIsMoving:(BOOL) move |
| 970 | { |
Kateryna Kostiuk | 2aa3923 | 2019-10-10 11:55:11 -0400 | [diff] [blame] | 971 | [[controlsPanel animator] setAlphaValue:move];// fade out |
| 972 | [[controlsStackView animator] setAlphaValue:move]; |
Alexandre Lision | a1eee3c | 2015-08-10 13:44:51 -0400 | [diff] [blame] | 973 | [[headerContainer animator] setAlphaValue:move]; |
Kateryna Kostiuk | 2aa3923 | 2019-10-10 11:55:11 -0400 | [diff] [blame] | 974 | [[headerGradientView animator] setAlphaValue:move]; |
Alexandre Lision | a1eee3c | 2015-08-10 13:44:51 -0400 | [diff] [blame] | 975 | } |
| 976 | |
Kateryna Kostiuk | 89398b6 | 2018-11-20 16:45:04 -0500 | [diff] [blame] | 977 | - (BOOL)splitView:(NSSplitView *)splitView shouldHideDividerAtIndex:(NSInteger)dividerIndex |
| 978 | { |
| 979 | return YES; |
| 980 | } |
| 981 | |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 982 | -(void) screenShare { |
| 983 | NSScreen *mainScreen = [NSScreen mainScreen]; |
| 984 | NSRect screenFrame = mainScreen.frame; |
| 985 | QRect captureRect = QRect(screenFrame.origin.x, screenFrame.origin.y, screenFrame.size.width, screenFrame.size.height); |
| 986 | mediaModel->setDisplay(0, screenFrame.origin.x, screenFrame.origin.y, screenFrame.size.width, screenFrame.size.height); |
| 987 | } |
| 988 | -(void) switchToDevice:(int)deviceID { |
| 989 | auto devices = mediaModel->getDevices(); |
| 990 | auto device = devices[deviceID]; |
| 991 | mediaModel->switchInputTo(device); |
| 992 | } |
| 993 | |
| 994 | -(std::vector<std::string>) getDeviceList { |
Kateryna Kostiuk | 6453310 | 2019-10-29 15:34:29 -0400 | [diff] [blame^] | 995 | std::vector<std::string> devicesVector; |
| 996 | for (auto device : mediaModel->getDevices()) { |
| 997 | try { |
| 998 | auto settings = mediaModel->getDeviceSettings(device); |
| 999 | devicesVector.emplace_back(settings.name); |
| 1000 | } catch (...) {} |
| 1001 | } |
| 1002 | return devicesVector; |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 1003 | } |
| 1004 | |
Kateryna Kostiuk | 32cf6be | 2019-10-28 12:22:45 -0400 | [diff] [blame] | 1005 | -(NSString*) getDefaultDeviceName { |
| 1006 | auto type = mediaModel->getCurrentRenderedDevice(callUid_).type; |
| 1007 | switch (type) { |
| 1008 | case lrc::api::video::DeviceType::CAMERA: |
Kateryna Kostiuk | 6453310 | 2019-10-29 15:34:29 -0400 | [diff] [blame^] | 1009 | try { |
| 1010 | auto device = mediaModel->getCurrentRenderedDevice(callUid_).name; |
| 1011 | auto settings = mediaModel->getDeviceSettings(device); |
| 1012 | return @(settings.name.c_str()); |
| 1013 | } catch (...) {} |
Kateryna Kostiuk | 32cf6be | 2019-10-28 12:22:45 -0400 | [diff] [blame] | 1014 | case lrc::api::video::DeviceType::DISPLAY: |
| 1015 | return NSLocalizedString(@"Share screen", @"Contextual menu entry"); |
| 1016 | default: |
| 1017 | return @""; |
| 1018 | } |
| 1019 | } |
| 1020 | |
Kateryna Kostiuk | 5d90c3b | 2019-07-18 12:03:52 -0400 | [diff] [blame] | 1021 | -(void) switchToFile:(std::string)uri { |
| 1022 | mediaModel->setInputFile(QUrl::fromLocalFile(uri.c_str()).toLocalFile().toStdString()); |
| 1023 | } |
| 1024 | |
Kateryna Kostiuk | 6891d4f | 2019-09-19 17:44:33 -0400 | [diff] [blame] | 1025 | -(CGRect) getVideoPreviewCollapsedSize { |
| 1026 | CGPoint origin; |
| 1027 | switch (movableBaseForView.closestCorner) { |
| 1028 | case TOP_LEFT: |
Kateryna Kostiuk | 2aa3923 | 2019-10-10 11:55:11 -0400 | [diff] [blame] | 1029 | origin = CGPointMake(0, movableBaseForView.frame.size.height - HIDE_PREVIEW_BUTTON_SIZE); |
Kateryna Kostiuk | 6891d4f | 2019-09-19 17:44:33 -0400 | [diff] [blame] | 1030 | break; |
| 1031 | case BOTTOM_LEFT: |
| 1032 | origin = CGPointMake(0, 0); |
| 1033 | break; |
| 1034 | case TOP_RIGHT: |
Kateryna Kostiuk | 2aa3923 | 2019-10-10 11:55:11 -0400 | [diff] [blame] | 1035 | origin = CGPointMake(movableBaseForView.frame.size.width - HIDE_PREVIEW_BUTTON_SIZE, movableBaseForView.frame.size.height - HIDE_PREVIEW_BUTTON_SIZE); |
Kateryna Kostiuk | 6891d4f | 2019-09-19 17:44:33 -0400 | [diff] [blame] | 1036 | break; |
| 1037 | case BOTTOM_RIGHT: |
Kateryna Kostiuk | 2aa3923 | 2019-10-10 11:55:11 -0400 | [diff] [blame] | 1038 | origin = CGPointMake(movableBaseForView.frame.size.width - HIDE_PREVIEW_BUTTON_SIZE, 0); |
Kateryna Kostiuk | 6891d4f | 2019-09-19 17:44:33 -0400 | [diff] [blame] | 1039 | break; |
| 1040 | } |
Kateryna Kostiuk | 2aa3923 | 2019-10-10 11:55:11 -0400 | [diff] [blame] | 1041 | return CGRectMake(origin.x, origin.y, HIDE_PREVIEW_BUTTON_SIZE, HIDE_PREVIEW_BUTTON_SIZE); |
Kateryna Kostiuk | 6891d4f | 2019-09-19 17:44:33 -0400 | [diff] [blame] | 1042 | } |
| 1043 | |
Kateryna Kostiuk | 2aa3923 | 2019-10-10 11:55:11 -0400 | [diff] [blame] | 1044 | -(CGRect) frameForExpendPreviewButton { |
| 1045 | CGPoint origin = CGPointMake(self.previewView.frame.size.width - HIDE_PREVIEW_BUTTON_SIZE, |
| 1046 | self.previewView.frame.size.height - HIDE_PREVIEW_BUTTON_SIZE); |
| 1047 | return CGRectMake(origin.x, origin.y, HIDE_PREVIEW_BUTTON_SIZE, HIDE_PREVIEW_BUTTON_SIZE); |
Kateryna Kostiuk | 6891d4f | 2019-09-19 17:44:33 -0400 | [diff] [blame] | 1048 | } |
| 1049 | |
Kateryna Kostiuk | 4db6109 | 2019-10-17 16:57:40 -0400 | [diff] [blame] | 1050 | # pragma mark -ChooseContactVCDelegate |
| 1051 | |
| 1052 | -(void)callToContact:(std::string)contactUri convUID:(std::string)convID { |
| 1053 | if (brokerPopoverVC != nullptr) { |
| 1054 | [brokerPopoverVC performClose:self]; |
| 1055 | brokerPopoverVC = NULL; |
| 1056 | } |
| 1057 | auto* callModel = accountInfo_->callModel.get(); |
| 1058 | auto currentCall = callModel->getCall([self getcallID]); |
| 1059 | auto* convModel = accountInfo_->conversationModel.get(); |
| 1060 | auto newCall = callModel->callAndAddParticipant(contactUri, |
| 1061 | [self getcallID], |
| 1062 | currentCall.isAudioOnly); |
| 1063 | [self addPreviewForContactUri:contactUri call: newCall]; |
| 1064 | } |
| 1065 | |
| 1066 | -(void)joinCall:(std::string)callId { |
| 1067 | if (brokerPopoverVC != nullptr) { |
| 1068 | [brokerPopoverVC performClose:self]; |
| 1069 | brokerPopoverVC = NULL; |
| 1070 | } |
| 1071 | auto* callModel = accountInfo_->callModel.get(); |
| 1072 | callModel->joinCalls([self getcallID], callId); |
| 1073 | } |
| 1074 | |
| 1075 | # pragma mark -CallInConferenceVCDelegate |
| 1076 | |
| 1077 | -(void)removePreviewForContactUri:(std::string)uri forCall:(std::string) callId { |
| 1078 | NSMutableDictionary * calls = connectingCalls[@(callId.c_str())]; |
| 1079 | if (!calls) { |
| 1080 | return; |
| 1081 | } |
| 1082 | NSViewController *callView = calls[@(uri.c_str())]; |
| 1083 | if (!callView) { |
| 1084 | return; |
| 1085 | } |
| 1086 | calls[@(uri.c_str())] = nil; |
| 1087 | [self.callingWidgetsContainer removeView:callView.view]; |
| 1088 | } |
| 1089 | |
| 1090 | -(void)addPreviewForContactUri:(std::string)uri call:(std::string)callId { |
| 1091 | NSMutableDictionary *calls = connectingCalls[@(callUid_.c_str())]; |
| 1092 | if (!calls) { |
| 1093 | calls = [[NSMutableDictionary alloc] init]; |
| 1094 | } |
| 1095 | if (calls[@(uri.c_str())]) { |
| 1096 | return; |
| 1097 | } |
| 1098 | CallInConferenceVC *callingView = [self callingViewForCallId: callId]; |
| 1099 | calls[@(uri.c_str())] = callingView; |
| 1100 | connectingCalls[@(callUid_.c_str())] = calls; |
| 1101 | [self.callingWidgetsContainer addView:callingView.view inGravity:NSStackViewGravityBottom]; |
| 1102 | [self.callingWidgetsContainer updateConstraints]; |
| 1103 | [self.callingWidgetsContainer updateLayer]; |
| 1104 | [self.callingWidgetsContainer setNeedsDisplay:YES]; |
| 1105 | } |
| 1106 | |
| 1107 | -(CallInConferenceVC*) callingViewForCallId:(std::string)callId { |
| 1108 | CallInConferenceVC *callView = [[CallInConferenceVC alloc] |
| 1109 | initWithNibName:@"CallInConferenceVC" |
| 1110 | bundle:nil |
| 1111 | callId:callId |
| 1112 | accountInfo:accountInfo_]; |
| 1113 | callView.delegate = self; |
| 1114 | callView.initiatorCallId = callUid_; |
| 1115 | return callView; |
| 1116 | } |
| 1117 | |
| 1118 | -(std::string)getcallID { |
| 1119 | return confUid_.empty() ? callUid_ : confUid_; |
| 1120 | } |
| 1121 | |
| 1122 | -(bool)isCurrentCall:(std::string)callId { |
| 1123 | return (callId == confUid_ || callId == callUid_); |
| 1124 | } |
| 1125 | |
| 1126 | #pragma mark Popover delegate |
| 1127 | |
| 1128 | - (void)popoverWillClose:(NSNotification *)notification |
| 1129 | { |
| 1130 | if (brokerPopoverVC != nullptr) { |
| 1131 | [brokerPopoverVC performClose:self]; |
| 1132 | brokerPopoverVC = NULL; |
| 1133 | } |
| 1134 | } |
Alexandre Lision | c514805 | 2015-03-04 15:10:35 -0500 | [diff] [blame] | 1135 | @end |