blob: dea1d5bb5ce000218f632860925652999a861a7c [file] [log] [blame]
Alexandre Lisionc5148052015-03-04 15:10:35 -05001/*
Alexandre Lision9fe374b2016-01-06 10:17:31 -05002 * Copyright (C) 2015-2016 Savoir-faire Linux Inc.
Alexandre Lisionc5148052015-03-04 15:10:35 -05003 * 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 Lisionc5148052015-03-04 15:10:35 -050018 */
19#import "CurrentCallVC.h"
20
21#import <QuartzCore/QuartzCore.h>
22
Alexandre Lision210fe212016-01-27 11:15:13 -050023///Qt
24#import <QMimeData>
25#import <QtMacExtras/qmacfunctions.h>
26#import <QtCore/qabstractitemmodel.h>
27#import <QItemSelectionModel>
28#import <QItemSelection>
29#import <QPixmap>
30
31///LRC
Alexandre Lisionc5148052015-03-04 15:10:35 -050032#import <video/previewmanager.h>
33#import <video/renderer.h>
Olivier Soldano994971f2017-12-05 16:30:12 -050034#import <api/newcallmodel.h>
35#import <api/call.h>
36#import <api/conversationmodel.h>
Alexandre Lision210fe212016-01-27 11:15:13 -050037#import <globalinstances.h>
Alexandre Lisionc5148052015-03-04 15:10:35 -050038
Alexandre Lision62005312016-01-28 15:55:16 -050039#import "AppDelegate.h"
Alexandre Lisionf47a2562015-06-15 15:48:29 -040040#import "views/ITProgressIndicator.h"
Alexandre Lision74dd47f2015-04-14 13:47:42 -040041#import "views/CallView.h"
Alexandre Lision210fe212016-01-27 11:15:13 -050042#import "delegates/ImageManipulationDelegate.h"
Alexandre Lision2db8f472015-07-22 15:05:46 -040043#import "PersonLinkerVC.h"
Alexandre Lision16d9c0a2015-08-10 12:05:15 -040044#import "ChatVC.h"
Alexandre Lision883719f2015-10-22 17:37:45 -040045#import "BrokerVC.h"
Alexandre Lision4baba4c2016-02-11 13:00:57 -050046#import "views/IconButton.h"
Anthony Léonard14e7bf32017-06-08 08:13:16 -040047#import "views/CallLayer.h"
Anthony Léonard6f819752018-01-05 09:53:40 -050048#import "utils.h"
Alexandre Lision74dd47f2015-04-14 13:47:42 -040049
Alexandre Lisionc5148052015-03-04 15:10:35 -050050@interface RendererConnectionsHolder : NSObject
51
52@property QMetaObject::Connection frameUpdated;
53@property QMetaObject::Connection started;
54@property QMetaObject::Connection stopped;
55
56@end
57
58@implementation RendererConnectionsHolder
59
60@end
61
Olivier Soldano994971f2017-12-05 16:30:12 -050062@interface CurrentCallVC () <NSPopoverDelegate, ContactLinkedDelegate> {
63 std::string convUid_;
64 std::string callUid_;
65 const lrc::api::account::Info *accountInfo_;
Anthony Léonard66a050c2018-01-03 16:32:34 -050066 NSTimer* refreshDurationTimer;
Olivier Soldano994971f2017-12-05 16:30:12 -050067}
Alexandre Lisionc5148052015-03-04 15:10:35 -050068
Alexandre Lision210fe212016-01-27 11:15:13 -050069// Main container
70@property (unsafe_unretained) IBOutlet NSSplitView* splitView;
71
Alexandre Lision89edc6a2015-11-09 11:30:47 -050072// Header info
73@property (unsafe_unretained) IBOutlet NSView* headerContainer;
Alexandre Lision883719f2015-10-22 17:37:45 -040074@property (unsafe_unretained) IBOutlet NSTextField* personLabel;
75@property (unsafe_unretained) IBOutlet NSTextField* stateLabel;
Alexandre Lision89edc6a2015-11-09 11:30:47 -050076@property (unsafe_unretained) IBOutlet NSTextField* timeSpentLabel;
Alexandre Lision210fe212016-01-27 11:15:13 -050077@property (unsafe_unretained) IBOutlet NSImageView* personPhoto;
Alexandre Lision89edc6a2015-11-09 11:30:47 -050078
Andreas Traczyk77a50d52018-05-08 17:47:31 -040079@property (unsafe_unretained) IBOutlet NSImageView* outgoingPhoto;
80@property (unsafe_unretained) IBOutlet NSTextField* outgoingPersonLabel;
81@property (unsafe_unretained) IBOutlet NSTextField* outgoingStateLabel;
82@property (unsafe_unretained) IBOutlet NSTextField* outgoingId;
83
Alexandre Lision89edc6a2015-11-09 11:30:47 -050084// Call Controls
85@property (unsafe_unretained) IBOutlet NSView* controlsPanel;
Alexandre Lision62005312016-01-28 15:55:16 -050086
Alexandre Lision4baba4c2016-02-11 13:00:57 -050087@property (unsafe_unretained) IBOutlet IconButton* holdOnOffButton;
88@property (unsafe_unretained) IBOutlet IconButton* hangUpButton;
89@property (unsafe_unretained) IBOutlet IconButton* recordOnOffButton;
90@property (unsafe_unretained) IBOutlet IconButton* pickUpButton;
91@property (unsafe_unretained) IBOutlet IconButton* muteAudioButton;
92@property (unsafe_unretained) IBOutlet IconButton* muteVideoButton;
Alexandre Lision4baba4c2016-02-11 13:00:57 -050093@property (unsafe_unretained) IBOutlet IconButton* transferButton;
94@property (unsafe_unretained) IBOutlet IconButton* addParticipantButton;
95@property (unsafe_unretained) IBOutlet IconButton* chatButton;
Andreas Traczyk77a50d52018-05-08 17:47:31 -040096@property (unsafe_unretained) IBOutlet IconButton* qualityButton;
Alexandre Lisiond18fa272015-06-15 11:18:03 -040097
Alexandre Lision62005312016-01-28 15:55:16 -050098@property (unsafe_unretained) IBOutlet NSView* advancedPanel;
99@property (unsafe_unretained) IBOutlet IconButton* advancedButton;
100
Alexandre Lisiond18fa272015-06-15 11:18:03 -0400101
Alexandre Lision89edc6a2015-11-09 11:30:47 -0500102// Join call panel
103@property (unsafe_unretained) IBOutlet NSView* joinPanel;
104@property (unsafe_unretained) IBOutlet NSButton* mergeCallsButton;
105
Alexandre Lision2db8f472015-07-22 15:05:46 -0400106@property (strong) NSPopover* addToContactPopover;
Alexandre Lision89edc6a2015-11-09 11:30:47 -0500107@property (strong) NSPopover* brokerPopoverVC;
Alexandre Lision883719f2015-10-22 17:37:45 -0400108@property (strong) IBOutlet ChatVC* chatVC;
Alexandre Lisionf23ec5a2015-07-16 11:24:06 -0400109
Alexandre Lision210fe212016-01-27 11:15:13 -0500110// Ringing call panel
111@property (unsafe_unretained) IBOutlet NSView* ringingPanel;
112@property (unsafe_unretained) IBOutlet NSImageView* incomingPersonPhoto;
113@property (unsafe_unretained) IBOutlet NSTextField* incomingDisplayName;
114
115// Outgoing call panel
116@property (unsafe_unretained) IBOutlet NSView* outgoingPanel;
117@property (unsafe_unretained) IBOutlet ITProgressIndicator *loadingIndicator;
Alexandre Lisionc5148052015-03-04 15:10:35 -0500118
119// Video
Alexandre Lision58cab672015-06-09 15:25:40 -0400120@property (unsafe_unretained) IBOutlet CallView *videoView;
Alexandre Lision58cab672015-06-09 15:25:40 -0400121@property (unsafe_unretained) IBOutlet NSView *previewView;
Alexandre Lisionc5148052015-03-04 15:10:35 -0500122
123@property RendererConnectionsHolder* previewHolder;
124@property RendererConnectionsHolder* videoHolder;
Alexandre Lisionef6333a2015-03-24 12:30:31 -0400125@property QMetaObject::Connection videoStarted;
Alexandre Lision4d9905e2016-01-22 12:01:36 -0500126@property QMetaObject::Connection selectedCallChanged;
Alexandre Lisionb65c0272015-07-22 15:51:29 -0400127@property QMetaObject::Connection messageConnection;
128@property QMetaObject::Connection mediaAddedConnection;
Alexandre Lisionc5148052015-03-04 15:10:35 -0500129
130@end
131
132@implementation CurrentCallVC
Olivier Soldano994971f2017-12-05 16:30:12 -0500133@synthesize personLabel, personPhoto, stateLabel, holdOnOffButton, hangUpButton,
Alexandre Lision89edc6a2015-11-09 11:30:47 -0500134 recordOnOffButton, pickUpButton, chatButton, transferButton, addParticipantButton, timeSpentLabel,
Olivier Soldano994971f2017-12-05 16:30:12 -0500135 muteVideoButton, muteAudioButton, controlsPanel, advancedPanel, advancedButton, headerContainer, videoView,
136 incomingDisplayName, incomingPersonPhoto, previewView, splitView, loadingIndicator, ringingPanel, joinPanel,
Andreas Traczyk77a50d52018-05-08 17:47:31 -0400137 outgoingPanel, outgoingPersonLabel, outgoingStateLabel, outgoingPhoto, outgoingId;
Alexandre Lisionc5148052015-03-04 15:10:35 -0500138
139@synthesize previewHolder;
140@synthesize videoHolder;
141
Olivier Soldano994971f2017-12-05 16:30:12 -0500142-(void) setCurrentCall:(const std::string&)callUid
143 conversation:(const std::string&)convUid
144 account:(const lrc::api::account::Info*)account;
Alexandre Lisionc5148052015-03-04 15:10:35 -0500145{
Olivier Soldano994971f2017-12-05 16:30:12 -0500146 if(account == nil)
147 return;
Alexandre Lisionef6333a2015-03-24 12:30:31 -0400148
Olivier Soldano994971f2017-12-05 16:30:12 -0500149 auto* callModel = account->callModel.get();
Alexandre Lisionc5148052015-03-04 15:10:35 -0500150
Olivier Soldano994971f2017-12-05 16:30:12 -0500151 if (not callModel->hasCall(callUid)){
152 callUid_.clear();
Alexandre Lision2db8f472015-07-22 15:05:46 -0400153 return;
154 }
Olivier Soldano994971f2017-12-05 16:30:12 -0500155 callUid_ = callUid;
156 convUid_ = convUid;
157 accountInfo_ = account;
Anthony Léonard4b0935f2017-12-26 12:05:22 -0500158 [self.chatVC setConversationUid:convUid model:account->conversationModel.get()];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500159}
160
161- (void)awakeFromNib
162{
163 NSLog(@"INIT CurrentCall VC");
Alexandre Lisionef6333a2015-03-24 12:30:31 -0400164 [self.view setWantsLayer:YES];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500165
Alexandre Lisionc5148052015-03-04 15:10:35 -0500166 [previewView setWantsLayer:YES];
Alexandre Lision22d615b2016-01-25 12:54:34 -0500167 [previewView.layer setBackgroundColor:[NSColor blackColor].CGColor];
168 [previewView.layer setContentsGravity:kCAGravityResizeAspectFill];
169 [previewView.layer setFrame:previewView.frame];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500170
171 [controlsPanel setWantsLayer:YES];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500172 [controlsPanel.layer setBackgroundColor:[NSColor clearColor].CGColor];
173 [controlsPanel.layer setFrame:controlsPanel.frame];
174
Alexandre Lisionef6333a2015-03-24 12:30:31 -0400175 previewHolder = [[RendererConnectionsHolder alloc] init];
176 videoHolder = [[RendererConnectionsHolder alloc] init];
177
Alexandre Lisionf47a2562015-06-15 15:48:29 -0400178 [loadingIndicator setColor:[NSColor whiteColor]];
Andreas Traczyk77a50d52018-05-08 17:47:31 -0400179 [loadingIndicator setNumberOfLines:200];
180 [loadingIndicator setWidthOfLine:4];
181 [loadingIndicator setLengthOfLine:4];
182 [loadingIndicator setInnerMargin:59];
Alexandre Lisionf47a2562015-06-15 15:48:29 -0400183
Alexandre Lisiona1eee3c2015-08-10 13:44:51 -0400184 [self.videoView setCallDelegate:self];
Kateryna Kostiuk1004caa2018-03-29 13:48:07 -0400185 CGColor* color = [[[NSColor blackColor] colorWithAlphaComponent:0.2] CGColor];
186 [headerContainer.layer setBackgroundColor:color];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500187}
188
Anthony Léonard66a050c2018-01-03 16:32:34 -0500189-(void) updateDurationLabel
190{
191 if (accountInfo_ != nil) {
192 auto* callModel = accountInfo_->callModel.get();
193 if (callModel->hasCall(callUid_)) {
194 auto& callStatus = callModel->getCall(callUid_).status;
195 if (callStatus != lrc::api::call::Status::ENDED &&
196 callStatus != lrc::api::call::Status::TERMINATING &&
197 callStatus != lrc::api::call::Status::INVALID) {
198 [timeSpentLabel setStringValue:@(callModel->getFormattedCallDuration(callUid_).c_str())];
199 return;
200 }
201 }
202 }
203
204 // If call is not running anymore or accountInfo_ is not set for any reason
205 // we stop the refresh loop
206 [refreshDurationTimer invalidate];
207 refreshDurationTimer = nil;
208 [timeSpentLabel setHidden:YES];
209}
210
Andreas Traczyk77a50d52018-05-08 17:47:31 -0400211-(void) updateCall
Alexandre Lisionc5148052015-03-04 15:10:35 -0500212{
Olivier Soldano994971f2017-12-05 16:30:12 -0500213 if (accountInfo_ == nil)
214 return;
Alexandre Lisionbb5dbcd2015-07-09 16:36:47 -0400215
Olivier Soldano994971f2017-12-05 16:30:12 -0500216 auto* callModel = accountInfo_->callModel.get();
217 if (not callModel->hasCall(callUid_)) {
218 return;
219 }
Alexandre Lision89edc6a2015-11-09 11:30:47 -0500220
Olivier Soldano994971f2017-12-05 16:30:12 -0500221 auto currentCall = callModel->getCall(callUid_);
222 NSLog(@"\n status %@ \n",@(lrc::api::call::to_string(currentCall.status).c_str()));
Anthony Léonard8ee26782018-01-05 10:23:04 -0500223 auto convIt = getConversationFromUid(convUid_, *accountInfo_->conversationModel);
Andreas Traczyk77a50d52018-05-08 17:47:31 -0400224 if (convIt != accountInfo_->conversationModel->allFilteredConversations().end()) {
225 NSString* bestName = bestNameForConversation(*convIt, *accountInfo_->conversationModel);
226 [personLabel setStringValue:bestName];
227 [outgoingPersonLabel setStringValue:bestName];
228 NSString* ringID = bestIDForConversation(*convIt, *accountInfo_->conversationModel);
229 if([bestName isEqualToString:ringID]) {
230 ringID = @"";
231 }
232 [outgoingId setStringValue:ringID];
233 }
234
Anthony Léonard66a050c2018-01-03 16:32:34 -0500235 [timeSpentLabel setStringValue:@(callModel->getFormattedCallDuration(callUid_).c_str())];
Anthony Léonard66a050c2018-01-03 16:32:34 -0500236 if (refreshDurationTimer == nil)
237 refreshDurationTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
238 target:self
239 selector:@selector(updateDurationLabel)
240 userInfo:nil
241 repeats:YES];
Olivier Soldano994971f2017-12-05 16:30:12 -0500242 [stateLabel setStringValue:@(to_string(currentCall.status).c_str())];
Andreas Traczyk77a50d52018-05-08 17:47:31 -0400243 [outgoingStateLabel setStringValue:@(to_string(currentCall.status).c_str())];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500244
Olivier Soldano994971f2017-12-05 16:30:12 -0500245 // Default values for this views
246 [loadingIndicator setHidden:YES];
Olivier Soldano994971f2017-12-05 16:30:12 -0500247 [ringingPanel setHidden:YES];
248 [outgoingPanel setHidden:YES];
249 [controlsPanel setHidden:NO];
250 [headerContainer setHidden:NO];
Anthony Léonard4b0935f2017-12-26 12:05:22 -0500251 [chatButton setHidden:NO];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500252
Olivier Soldano994971f2017-12-05 16:30:12 -0500253 using Status = lrc::api::call::Status;
254 switch (currentCall.status) {
255 case Status::SEARCHING:
256 case Status::OUTGOING_REQUESTED:
257 case Status::CONNECTING:
Andreas Traczyk77a50d52018-05-08 17:47:31 -0400258 [headerContainer setHidden:YES];
259 [outgoingPanel setHidden:NO];
260 [outgoingPhoto setHidden:NO];
261 [self setupContactInfo:outgoingPhoto];
Olivier Soldano994971f2017-12-05 16:30:12 -0500262 [loadingIndicator setHidden:NO];
Andreas Traczyk77a50d52018-05-08 17:47:31 -0400263 [controlsPanel setHidden:YES];
Olivier Soldano994971f2017-12-05 16:30:12 -0500264 break;
265 case Status::INCOMING_RINGING:
Andreas Traczyk77a50d52018-05-08 17:47:31 -0400266 [outgoingPhoto setHidden:YES];
Olivier Soldano994971f2017-12-05 16:30:12 -0500267 [controlsPanel setHidden:YES];
268 [outgoingPanel setHidden:YES];
269 [self setupIncoming:callUid_];
270 break;
271 case Status::OUTGOING_RINGING:
272 [controlsPanel setHidden:YES];
273 [outgoingPanel setHidden:NO];
Andreas Traczyk77a50d52018-05-08 17:47:31 -0400274 [loadingIndicator setHidden:NO];
275 [headerContainer setHidden:YES];
Olivier Soldano994971f2017-12-05 16:30:12 -0500276 break;
Andreas Traczyk77a50d52018-05-08 17:47:31 -0400277 /*case Status::CONFERENCE:
278 [self setupConference:currentCall];
279 break;*/
Olivier Soldano994971f2017-12-05 16:30:12 -0500280 case Status::PAUSED:
281 case Status::PEER_PAUSED:
282 case Status::INACTIVE:
283 case Status::IN_PROGRESS:
Andreas Traczyk77a50d52018-05-08 17:47:31 -0400284 // change constraints (uncollapse avatar)
285 [self setupContactInfo:personPhoto];
Kateryna Kostiuk1004caa2018-03-29 13:48:07 -0400286 [timeSpentLabel setHidden:NO];
Andreas Traczyk77a50d52018-05-08 17:47:31 -0400287 [outgoingPhoto setHidden:YES];
288 [headerContainer setHidden:NO];
289 break;
Olivier Soldano994971f2017-12-05 16:30:12 -0500290 case Status::CONNECTED:
291 case Status::AUTO_ANSWERING:
292 break;
293 case Status::ENDED:
294 case Status::TERMINATING:
295 case Status::INVALID:
296 [controlsPanel setHidden:YES];
297 [outgoingPanel setHidden:NO];
Andreas Traczykecdc4fa2018-03-22 16:11:47 -0400298 [self hideWithAnimation:false];
Olivier Soldano994971f2017-12-05 16:30:12 -0500299 break;
300 }
Alexandre Lision4d9905e2016-01-22 12:01:36 -0500301
Alexandre Lision4d9905e2016-01-22 12:01:36 -0500302}
303
Andreas Traczyk77a50d52018-05-08 17:47:31 -0400304-(void) setupContactInfo:(NSImageView*)imageView
305{
306 auto* convModel = accountInfo_->conversationModel.get();
307 auto it = getConversationFromUid(convUid_, *convModel);
308 if (it != convModel->allFilteredConversations().end()) {
309 auto& imgManip = reinterpret_cast<Interfaces::ImageManipulationDelegate&>(GlobalInstances::pixmapManipulator());
310 QVariant photo = imgManip.conversationPhoto(*it, *accountInfo_, QSize(120, 120), NO);
311 [imageView setImage:QtMac::toNSImage(qvariant_cast<QPixmap>(photo))];
312 }
313}
314
Olivier Soldano994971f2017-12-05 16:30:12 -0500315-(void) setupIncoming:(const std::string&) callId
Alexandre Lision4d9905e2016-01-22 12:01:36 -0500316{
Olivier Soldano994971f2017-12-05 16:30:12 -0500317 if (accountInfo_ == nil)
318 return;
319
320 auto* callModel = accountInfo_->callModel.get();
321 if (not callModel->hasCall(callUid_)) {
322 return;
323 }
324
325 auto call = callModel->getCall(callUid_);
326 auto* convModel = accountInfo_->conversationModel.get();
327
328 [ringingPanel setHidden:NO];
329 [controlsPanel setHidden:YES];
330 [headerContainer setHidden:YES];
Anthony Léonard6f819752018-01-05 09:53:40 -0500331 auto it = getConversationFromUid(convUid_, *convModel);
Olivier Soldano994971f2017-12-05 16:30:12 -0500332 if (it != convModel->allFilteredConversations().end()) {
333 auto& imgManip = reinterpret_cast<Interfaces::ImageManipulationDelegate&>(GlobalInstances::pixmapManipulator());
334 QVariant photo = imgManip.conversationPhoto(*it, *accountInfo_);
335 [incomingPersonPhoto setImage:QtMac::toNSImage(qvariant_cast<QPixmap>(photo))];
Anthony Léonard8ee26782018-01-05 10:23:04 -0500336 [incomingDisplayName setStringValue:bestNameForConversation(*it, *convModel)];
Olivier Soldano994971f2017-12-05 16:30:12 -0500337 }
338}
339
340
341-(void) setupConference:(Call*) c
342{
343 [videoView setShouldAcceptInteractions:YES];
344 [self.chatButton setHidden:NO];
345 [joinPanel setHidden:YES];
346 [self.addParticipantButton setHidden:NO];
347 [self.transferButton setHidden:YES];
348}
349
350-(void)collapseRightView
351{
352 NSView *right = [[splitView subviews] objectAtIndex:1];
353 NSView *left = [[splitView subviews] objectAtIndex:0];
354 NSRect leftFrame = [left frame];
355 [right setHidden:YES];
356 [splitView display];
357}
358
359- (void) changeCallSelection:(std::string&)callUid
360{
361 if (accountInfo_ == nil)
362 return;
363
364 auto* callModel = accountInfo_->callModel.get();
365 if (not callModel->hasCall(callUid)) {
366 return;
367 }
368
Alexandre Lision4d9905e2016-01-22 12:01:36 -0500369 QObject::disconnect(self.selectedCallChanged);
Olivier Soldano994971f2017-12-05 16:30:12 -0500370 self.selectedCallChanged = QObject::connect(callModel,
371 &lrc::api::NewCallModel::callStatusChanged,
372 [self](const std::string callId) {
Andreas Traczyk77a50d52018-05-08 17:47:31 -0400373 [self updateCall];
Alexandre Lision4d9905e2016-01-22 12:01:36 -0500374 });
Alexandre Lisionc5148052015-03-04 15:10:35 -0500375}
376
377-(void) connectVideoSignals
378{
Olivier Soldano994971f2017-12-05 16:30:12 -0500379 if (accountInfo_ == nil)
380 return;
381
382 auto* callModel = accountInfo_->callModel.get();
Alexandre Lision89edc6a2015-11-09 11:30:47 -0500383 QObject::disconnect(self.videoStarted);
Olivier Soldano994971f2017-12-05 16:30:12 -0500384 self.videoStarted = QObject::connect(callModel,
385 &lrc::api::NewCallModel::remotePreviewStarted,
386 [self](const std::string& callId, Video::Renderer* renderer) {
387 NSLog(@"Video started!");
Kateryna Kostiuk1004caa2018-03-29 13:48:07 -0400388 [videoView setShouldAcceptInteractions:YES];
389 [self mouseIsMoving: NO];
Olivier Soldano994971f2017-12-05 16:30:12 -0500390 [self connectVideoRenderer:renderer];
391 });
Alexandre Lisionc5148052015-03-04 15:10:35 -0500392
Olivier Soldano994971f2017-12-05 16:30:12 -0500393 if (callModel->hasCall(callUid_)) {
394 if (auto renderer = callModel->getRenderer(callUid_)) {
395 QObject::disconnect(self.videoStarted);
396 [self connectVideoRenderer: renderer];
397 }
Alexandre Lisionc5148052015-03-04 15:10:35 -0500398 }
Alexandre Lisionc5148052015-03-04 15:10:35 -0500399 [self connectPreviewRenderer];
400
401}
402
403-(void) connectPreviewRenderer
404{
Alexandre Lisionef6333a2015-03-24 12:30:31 -0400405 QObject::disconnect(previewHolder.frameUpdated);
406 QObject::disconnect(previewHolder.stopped);
407 QObject::disconnect(previewHolder.started);
Alexandre Lisiond3aa3ad2015-10-23 14:28:41 -0400408 previewHolder.started = QObject::connect(&Video::PreviewManager::instance(),
Alexandre Lisionc5148052015-03-04 15:10:35 -0500409 &Video::PreviewManager::previewStarted,
410 [=](Video::Renderer* renderer) {
Alexandre Lisionc5148052015-03-04 15:10:35 -0500411 QObject::disconnect(previewHolder.frameUpdated);
412 previewHolder.frameUpdated = QObject::connect(renderer,
413 &Video::Renderer::frameUpdated,
414 [=]() {
Alexandre Lisiond3aa3ad2015-10-23 14:28:41 -0400415 [self renderer:Video::PreviewManager::instance().previewRenderer()
Anthony Léonard14e7bf32017-06-08 08:13:16 -0400416 renderFrameForPreviewView:previewView];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500417 });
418 });
419
Alexandre Lisiond3aa3ad2015-10-23 14:28:41 -0400420 previewHolder.stopped = QObject::connect(&Video::PreviewManager::instance(),
Alexandre Lisionc5148052015-03-04 15:10:35 -0500421 &Video::PreviewManager::previewStopped,
422 [=](Video::Renderer* renderer) {
Alexandre Lisionc5148052015-03-04 15:10:35 -0500423 QObject::disconnect(previewHolder.frameUpdated);
424 [previewView.layer setContents:nil];
425 });
426
Alexandre Lisiond3aa3ad2015-10-23 14:28:41 -0400427 previewHolder.frameUpdated = QObject::connect(Video::PreviewManager::instance().previewRenderer(),
Alexandre Lisionc5148052015-03-04 15:10:35 -0500428 &Video::Renderer::frameUpdated,
429 [=]() {
Alexandre Lisiond3aa3ad2015-10-23 14:28:41 -0400430 [self renderer:Video::PreviewManager::instance().previewRenderer()
Anthony Léonard14e7bf32017-06-08 08:13:16 -0400431 renderFrameForPreviewView:previewView];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500432 });
433}
434
435-(void) connectVideoRenderer: (Video::Renderer*)renderer
436{
Alexandre Lisionef6333a2015-03-24 12:30:31 -0400437 QObject::disconnect(videoHolder.frameUpdated);
438 QObject::disconnect(videoHolder.started);
439 QObject::disconnect(videoHolder.stopped);
Olivier Soldano994971f2017-12-05 16:30:12 -0500440
441 if(renderer == nil)
442 return;
443
Alexandre Lisionc5148052015-03-04 15:10:35 -0500444 videoHolder.frameUpdated = QObject::connect(renderer,
445 &Video::Renderer::frameUpdated,
446 [=]() {
Anthony Léonard14e7bf32017-06-08 08:13:16 -0400447 [self renderer:renderer renderFrameForDistantView:videoView];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500448 });
449
450 videoHolder.started = QObject::connect(renderer,
451 &Video::Renderer::started,
452 [=]() {
Kateryna Kostiuk1004caa2018-03-29 13:48:07 -0400453 [self mouseIsMoving: NO];
454 [videoView setShouldAcceptInteractions:YES];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500455 QObject::disconnect(videoHolder.frameUpdated);
456 videoHolder.frameUpdated = QObject::connect(renderer,
457 &Video::Renderer::frameUpdated,
458 [=]() {
Anthony Léonard14e7bf32017-06-08 08:13:16 -0400459 [self renderer:renderer renderFrameForDistantView:videoView];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500460 });
461 });
462
463 videoHolder.stopped = QObject::connect(renderer,
464 &Video::Renderer::stopped,
465 [=]() {
Kateryna Kostiuk1004caa2018-03-29 13:48:07 -0400466 [self mouseIsMoving: YES];
467 [videoView setShouldAcceptInteractions:NO];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500468 QObject::disconnect(videoHolder.frameUpdated);
Anthony Léonard14e7bf32017-06-08 08:13:16 -0400469 [(CallLayer*)videoView.layer setVideoRunning:NO];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500470 });
471}
472
Anthony Léonard14e7bf32017-06-08 08:13:16 -0400473-(void) renderer: (Video::Renderer*)renderer renderFrameForPreviewView:(NSView*) view
Alexandre Lisionc5148052015-03-04 15:10:35 -0500474{
Alexandre Lisionc5148052015-03-04 15:10:35 -0500475 QSize res = renderer->size();
476
Alexandre Lision6731e132015-10-14 14:29:06 -0400477 auto frame_ptr = renderer->currentFrame();
478 auto frame_data = frame_ptr.ptr;
479 if (!frame_data)
480 return;
481
Alexandre Lisionc5148052015-03-04 15:10:35 -0500482 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
Alexandre Lision6731e132015-10-14 14:29:06 -0400483 CGContextRef newContext = CGBitmapContextCreate(frame_data,
Alexandre Lisionc5148052015-03-04 15:10:35 -0500484 res.width(),
485 res.height(),
486 8,
487 4*res.width(),
488 colorSpace,
489 kCGImageAlphaPremultipliedLast);
490
491
492 CGImageRef newImage = CGBitmapContextCreateImage(newContext);
493
494 /*We release some components*/
495 CGContextRelease(newContext);
496 CGColorSpaceRelease(colorSpace);
497
498 [CATransaction begin];
499 view.layer.contents = (__bridge id)newImage;
500 [CATransaction commit];
501
502 CFRelease(newImage);
503}
504
Anthony Léonard14e7bf32017-06-08 08:13:16 -0400505-(void) renderer: (Video::Renderer*)renderer renderFrameForDistantView:(CallView*) view
506{
Anthony Léonard14e7bf32017-06-08 08:13:16 -0400507 auto frame_ptr = renderer->currentFrame();
508 if (!frame_ptr.ptr)
509 return;
510
511 CallLayer* callLayer = (CallLayer*) view.layer;
512
Anthony Léonarda9d7c8e2018-01-03 14:41:17 -0500513 [callLayer setCurrentFrame:std::move(frame_ptr)];
Anthony Léonard14e7bf32017-06-08 08:13:16 -0400514 [callLayer setVideoRunning:YES];
515}
516
Alexandre Lisionc5148052015-03-04 15:10:35 -0500517- (void) initFrame
518{
519 [self.view setFrame:self.view.superview.bounds];
520 [self.view setHidden:YES];
521 self.view.layer.position = self.view.frame.origin;
Alexandre Lisionbb5dbcd2015-07-09 16:36:47 -0400522 [self collapseRightView];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500523}
524
525# pragma private IN/OUT animations
526
Olivier Soldano994971f2017-12-05 16:30:12 -0500527-(void)uncollapseRightView
528{
529 NSView *left = [[splitView subviews] objectAtIndex:0];
530 NSView *right = [[splitView subviews] objectAtIndex:1];
531 [right setHidden:NO];
532
533 CGFloat dividerThickness = [splitView dividerThickness];
534
535 // get the different frames
536 NSRect leftFrame = [left frame];
537 NSRect rightFrame = [right frame];
538
539 leftFrame.size.width = (leftFrame.size.width - rightFrame.size.width - dividerThickness);
540 rightFrame.origin.x = leftFrame.size.width + dividerThickness;
541 [left setFrameSize:leftFrame.size];
542 [right setFrame:rightFrame];
543 [splitView display];
544
545 [self.chatVC takeFocus];
546}
547
Alexandre Lisionc5148052015-03-04 15:10:35 -0500548-(void) cleanUp
549{
Anthony Léonard5c287642018-02-21 15:54:19 -0500550 if(self.splitView.isInFullScreenMode)
551 [self.splitView exitFullScreenModeWithOptions:nil];
Alexandre Lisionef6333a2015-03-24 12:30:31 -0400552 QObject::disconnect(videoHolder.frameUpdated);
553 QObject::disconnect(videoHolder.started);
554 QObject::disconnect(videoHolder.stopped);
555 QObject::disconnect(previewHolder.frameUpdated);
556 QObject::disconnect(previewHolder.stopped);
557 QObject::disconnect(previewHolder.started);
Anthony Léonardc0013bb2018-02-20 16:23:02 -0500558 QObject::disconnect(self.messageConnection);
Alexandre Lisionc5148052015-03-04 15:10:35 -0500559 [previewView.layer setContents:nil];
Kateryna Kostiuk1004caa2018-03-29 13:48:07 -0400560 [(CallLayer*)videoView.layer setVideoRunning:NO];
Alexandre Lision883719f2015-10-22 17:37:45 -0400561
Alexandre Lision89edc6a2015-11-09 11:30:47 -0500562 [_brokerPopoverVC performClose:self];
Alexandre Lision883719f2015-10-22 17:37:45 -0400563 [self.addToContactPopover performClose:self];
Alexandre Lision0e66aea2015-11-02 16:36:30 -0500564
Alexandre Lision89edc6a2015-11-09 11:30:47 -0500565 [self.chatButton setHidden:YES];
566 [self.addParticipantButton setHidden:YES];
567 [self.transferButton setHidden:YES];
Andreas Traczyk77a50d52018-05-08 17:47:31 -0400568 [self.qualityButton setHidden:YES];
Alexandre Lision89edc6a2015-11-09 11:30:47 -0500569
Alexandre Lision4baba4c2016-02-11 13:00:57 -0500570 [self.chatButton setPressed:NO];
Alexandre Lision89edc6a2015-11-09 11:30:47 -0500571 [self.mergeCallsButton setState:NSOffState];
Alexandre Lision883719f2015-10-22 17:37:45 -0400572 [self collapseRightView];
Alexandre Lision57227772016-01-15 17:19:36 -0500573
574 [personLabel setStringValue:@""];
575 [timeSpentLabel setStringValue:@""];
576 [stateLabel setStringValue:@""];
Andreas Traczyk77a50d52018-05-08 17:47:31 -0400577
578 [outgoingPersonLabel setStringValue:@""];
579 [outgoingStateLabel setStringValue:@""];
Alexandre Lision62005312016-01-28 15:55:16 -0500580
581 [advancedButton setPressed:NO];
582 [advancedPanel setHidden:YES];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500583}
584
Andreas Traczykecdc4fa2018-03-22 16:11:47 -0400585-(void) setupCallView
586{
587 if (accountInfo_ == nil)
588 return;
589
590 auto* callModel = accountInfo_->callModel.get();
591 auto* convModel = accountInfo_->conversationModel.get();
592
593 // when call comes in we want to show the controls/header
Kateryna Kostiuk1004caa2018-03-29 13:48:07 -0400594 [self mouseIsMoving: YES];
595 [videoView setShouldAcceptInteractions: NO];
Andreas Traczykecdc4fa2018-03-22 16:11:47 -0400596
597 [self connectVideoSignals];
598 /* check if text media is already present */
599 if(not callModel->hasCall(callUid_))
600 return;
601
602 [loadingIndicator setAnimates:YES];
Andreas Traczyk77a50d52018-05-08 17:47:31 -0400603 [self updateCall];
Andreas Traczykecdc4fa2018-03-22 16:11:47 -0400604
605 /* monitor media for messaging text messaging */
606 QObject::disconnect(self.messageConnection);
607 self.messageConnection = QObject::connect(convModel,
608 &lrc::api::ConversationModel::interactionStatusUpdated,
609 [self] (std::string convUid,
610 uint64_t msgId,
611 lrc::api::interaction::Info msg) {
612 if (msg.type == lrc::api::interaction::Type::TEXT) {
613 if(not [[self splitView] isSubviewCollapsed:[[[self splitView] subviews] objectAtIndex: 1]]){
614 return;
615 }
616 [self uncollapseRightView];
617 }
618 });
619}
620
621-(void) showWithAnimation:(BOOL)animate
622{
623 if (!animate) {
624 [self.view setHidden:NO];
625 [self setupCallView];
626 return;
627 }
628
629 CGRect frame = CGRectOffset(self.view.superview.bounds, -self.view.superview.bounds.size.width, 0);
630 [self.view setHidden:NO];
631
632 [CATransaction begin];
633 CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
634 [animation setFromValue:[NSValue valueWithPoint:frame.origin]];
635 [animation setToValue:[NSValue valueWithPoint:self.view.superview.bounds.origin]];
636 [animation setDuration:0.2f];
637 [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]];
638 [CATransaction setCompletionBlock:^{
639 [self setupCallView];
640 }];
641
642 [self.view.layer addAnimation:animation forKey:animation.keyPath];
643 [CATransaction commit];
644}
645
646-(void) hideWithAnimation:(BOOL)animate
Alexandre Lisionc5148052015-03-04 15:10:35 -0500647{
Alexandre Lisionc5148052015-03-04 15:10:35 -0500648 if(self.view.frame.origin.x < 0) {
Alexandre Lisionc5148052015-03-04 15:10:35 -0500649 return;
650 }
651
Andreas Traczykecdc4fa2018-03-22 16:11:47 -0400652 if (!animate) {
Kateryna Kostiuk1004caa2018-03-29 13:48:07 -0400653 [self cleanUp];
Andreas Traczykecdc4fa2018-03-22 16:11:47 -0400654 [self.view setHidden:YES];
655 return;
656 }
657
Alexandre Lisionc5148052015-03-04 15:10:35 -0500658 CGRect frame = CGRectOffset(self.view.frame, -self.view.frame.size.width, 0);
659 [CATransaction begin];
660 CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
661 [animation setFromValue:[NSValue valueWithPoint:self.view.frame.origin]];
662 [animation setToValue:[NSValue valueWithPoint:frame.origin]];
663 [animation setDuration:0.2f];
Alexandre Lision22d615b2016-01-25 12:54:34 -0500664 [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500665
666 [CATransaction setCompletionBlock:^{
667 [self.view setHidden:YES];
Alexandre Lisionef6333a2015-03-24 12:30:31 -0400668 // first make sure everything is disconnected
Alexandre Lisionc5148052015-03-04 15:10:35 -0500669 [self cleanUp];
Olivier Soldano994971f2017-12-05 16:30:12 -0500670// if (currentCall_) {
671// [self animateIn];
672// }
Alexandre Lisionc5148052015-03-04 15:10:35 -0500673 }];
674 [self.view.layer addAnimation:animation forKey:animation.keyPath];
Alexandre Lisiona1c6d752015-06-23 12:27:38 -0400675
676 [self.view.layer setPosition:frame.origin];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500677 [CATransaction commit];
678}
679
680/**
681 * Debug purpose
682 */
683-(void) dumpFrame:(CGRect) frame WithName:(NSString*) name
684{
685 NSLog(@"frame %@ : %f %f %f %f \n\n",name ,frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
686}
687
Alexandre Lision58cab672015-06-09 15:25:40 -0400688#pragma mark - Button methods
689
Alexandre Lisionc5148052015-03-04 15:10:35 -0500690- (IBAction)hangUp:(id)sender {
Olivier Soldano994971f2017-12-05 16:30:12 -0500691 if (accountInfo_ == nil)
692 return;
693
694 auto* callModel = accountInfo_->callModel.get();
695
696 callModel->hangUp(callUid_);
Alexandre Lisionc5148052015-03-04 15:10:35 -0500697}
698
699- (IBAction)accept:(id)sender {
Olivier Soldano994971f2017-12-05 16:30:12 -0500700 if (accountInfo_ == nil)
701 return;
702
Anthony Léonardf584cc52018-01-19 12:00:19 -0500703 // If we accept a conversation with a non trusted contact, we first accept it
704 auto convIt = getConversationFromUid(convUid_, *accountInfo_->conversationModel.get());
705 if (convIt != accountInfo_->conversationModel->allFilteredConversations().end()) {
706 auto& contact = accountInfo_->contactModel->getContact(convIt->participants[0]);
707 if (contact.profileInfo.type == lrc::api::profile::Type::PENDING)
708 accountInfo_->conversationModel->makePermanent(convUid_);
709 }
710
Olivier Soldano994971f2017-12-05 16:30:12 -0500711 auto* callModel = accountInfo_->callModel.get();
712
713 callModel->accept(callUid_);
Alexandre Lisionc5148052015-03-04 15:10:35 -0500714}
715
716- (IBAction)toggleRecording:(id)sender {
Olivier Soldano994971f2017-12-05 16:30:12 -0500717 if (accountInfo_ == nil)
718 return;
719
720 auto* callModel = accountInfo_->callModel.get();
721
722 callModel->toggleAudioRecord(callUid_);
Alexandre Lisionc5148052015-03-04 15:10:35 -0500723}
724
725- (IBAction)toggleHold:(id)sender {
Olivier Soldano994971f2017-12-05 16:30:12 -0500726 if (accountInfo_ == nil)
727 return;
728
729 auto* callModel = accountInfo_->callModel.get();
730
731 callModel->togglePause(callUid_);
Alexandre Lisionc5148052015-03-04 15:10:35 -0500732}
733
Alexandre Lision62005312016-01-28 15:55:16 -0500734- (IBAction)toggleAdvancedControls:(id)sender {
735 [advancedButton setPressed:!advancedButton.isPressed];
736 [advancedPanel setHidden:![advancedButton isPressed]];
737}
738
739- (IBAction)showDialpad:(id)sender {
740 AppDelegate* appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
741 [appDelegate showDialpad];
742}
743
Alexandre Lision58cab672015-06-09 15:25:40 -0400744-(IBAction)toggleChat:(id)sender;
745{
746 BOOL rightViewCollapsed = [[self splitView] isSubviewCollapsed:[[[self splitView] subviews] objectAtIndex: 1]];
747 if (rightViewCollapsed) {
748 [self uncollapseRightView];
Alexandre Lision58cab672015-06-09 15:25:40 -0400749 } else {
750 [self collapseRightView];
751 }
Alexandre Lision62005312016-01-28 15:55:16 -0500752 [chatButton setPressed:rightViewCollapsed];
Alexandre Lision58cab672015-06-09 15:25:40 -0400753}
754
Alexandre Lisiond18fa272015-06-15 11:18:03 -0400755- (IBAction)muteAudio:(id)sender
756{
Olivier Soldano994971f2017-12-05 16:30:12 -0500757 if (accountInfo_ == nil)
758 return;
759
760 auto* callModel = accountInfo_->callModel.get();
761
762 callModel->toggleMedia(callUid_, lrc::api::NewCallModel::Media::AUDIO);
Alexandre Lisiond18fa272015-06-15 11:18:03 -0400763}
764
765- (IBAction)muteVideo:(id)sender
766{
Olivier Soldano994971f2017-12-05 16:30:12 -0500767 if (accountInfo_ == nil)
768 return;
769
770 auto* callModel = accountInfo_->callModel.get();
771
772 callModel->toggleMedia(callUid_, lrc::api::NewCallModel::Media::VIDEO);
Alexandre Lisiond18fa272015-06-15 11:18:03 -0400773}
Alexandre Lision883719f2015-10-22 17:37:45 -0400774
775- (IBAction)toggleTransferView:(id)sender {
Alexandre Lision89edc6a2015-11-09 11:30:47 -0500776 if (_brokerPopoverVC != nullptr) {
777 [_brokerPopoverVC performClose:self];
778 _brokerPopoverVC = NULL;
Alexandre Lision62005312016-01-28 15:55:16 -0500779 [self.transferButton setPressed:NO];
Alexandre Lision883719f2015-10-22 17:37:45 -0400780 } else {
Alexandre Lision89edc6a2015-11-09 11:30:47 -0500781 auto* brokerVC = [[BrokerVC alloc] initWithMode:BrokerMode::TRANSFER];
782 _brokerPopoverVC = [[NSPopover alloc] init];
783 [_brokerPopoverVC setContentSize:brokerVC.view.frame.size];
784 [_brokerPopoverVC setContentViewController:brokerVC];
785 [_brokerPopoverVC setAnimates:YES];
786 [_brokerPopoverVC setBehavior:NSPopoverBehaviorTransient];
787 [_brokerPopoverVC setDelegate:self];
788 [_brokerPopoverVC showRelativeToRect:[sender bounds] ofView:sender preferredEdge:NSMinYEdge];
Alexandre Lision883719f2015-10-22 17:37:45 -0400789 [videoView setCallDelegate:nil];
790 }
Alexandre Lisionf23ec5a2015-07-16 11:24:06 -0400791}
Alexandre Lisiond18fa272015-06-15 11:18:03 -0400792
Alexandre Lision89edc6a2015-11-09 11:30:47 -0500793- (IBAction)toggleAddParticipantView:(id)sender {
794 if (_brokerPopoverVC != nullptr) {
795 [_brokerPopoverVC performClose:self];
796 _brokerPopoverVC = NULL;
Alexandre Lision62005312016-01-28 15:55:16 -0500797 [self.addParticipantButton setPressed:NO];
Alexandre Lision89edc6a2015-11-09 11:30:47 -0500798 } else {
799 auto* brokerVC = [[BrokerVC alloc] initWithMode:BrokerMode::CONFERENCE];
800 _brokerPopoverVC = [[NSPopover alloc] init];
801 [_brokerPopoverVC setContentSize:brokerVC.view.frame.size];
802 [_brokerPopoverVC setContentViewController:brokerVC];
803 [_brokerPopoverVC setAnimates:YES];
804 [_brokerPopoverVC setBehavior:NSPopoverBehaviorTransient];
805 [_brokerPopoverVC setDelegate:self];
806 [_brokerPopoverVC showRelativeToRect:[sender bounds] ofView:sender preferredEdge:NSMinYEdge];
807 [videoView setCallDelegate:nil];
808 }
809}
810
811/**
812 * Merge current call with its parent call
813 */
814- (IBAction)mergeCalls:(id)sender
815{
Olivier Soldano994971f2017-12-05 16:30:12 -0500816// auto current = CallModel::instance().selectedCall();
817// current->joinToParent();
Alexandre Lision89edc6a2015-11-09 11:30:47 -0500818}
819
Alexandre Lision2db8f472015-07-22 15:05:46 -0400820#pragma mark - NSPopOverDelegate
821
Alexandre Lision266fca02015-09-28 14:47:05 -0400822- (void)popoverWillClose:(NSNotification *)notification
823{
Alexandre Lision89edc6a2015-11-09 11:30:47 -0500824 if (_brokerPopoverVC != nullptr) {
825 [_brokerPopoverVC performClose:self];
826 _brokerPopoverVC = NULL;
Alexandre Lision883719f2015-10-22 17:37:45 -0400827 }
Alexandre Lision266fca02015-09-28 14:47:05 -0400828
Alexandre Lision2db8f472015-07-22 15:05:46 -0400829 if (self.addToContactPopover != nullptr) {
830 [self.addToContactPopover performClose:self];
831 self.addToContactPopover = NULL;
832 }
Alexandre Lision883719f2015-10-22 17:37:45 -0400833
Alexandre Lision62005312016-01-28 15:55:16 -0500834 [self.transferButton setPressed:NO];
Alexandre Lision89edc6a2015-11-09 11:30:47 -0500835 [self.addParticipantButton setState:NSOffState];
Alexandre Lision883719f2015-10-22 17:37:45 -0400836}
837
838- (void)popoverDidClose:(NSNotification *)notification
839{
840 [videoView setCallDelegate:self];
Alexandre Lision2db8f472015-07-22 15:05:46 -0400841}
842
843#pragma mark - ContactLinkedDelegate
844
845- (void)contactLinked
846{
847 if (self.addToContactPopover != nullptr) {
848 [self.addToContactPopover performClose:self];
849 self.addToContactPopover = NULL;
850 }
851}
852
Alexandre Lision58cab672015-06-09 15:25:40 -0400853#pragma mark - NSSplitViewDelegate
854
855/* 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.
856 */
857- (BOOL)splitView:(NSSplitView *)splitView shouldCollapseSubview:(NSView *)subview forDoubleClickOnDividerAtIndex:(NSInteger)dividerIndex;
858{
859 NSView* rightView = [[splitView subviews] objectAtIndex:1];
860 return ([subview isEqual:rightView]);
861}
862
863
864- (BOOL)splitView:(NSSplitView *)splitView canCollapseSubview:(NSView *)subview;
865{
866 NSView* rightView = [[splitView subviews] objectAtIndex:1];
867 return ([subview isEqual:rightView]);
868}
869
870
Alexandre Lisiona1eee3c2015-08-10 13:44:51 -0400871# pragma mark - CallnDelegate
Alexandre Lision58cab672015-06-09 15:25:40 -0400872
873- (void) callShouldToggleFullScreen
874{
875 if(self.splitView.isInFullScreenMode)
876 [self.splitView exitFullScreenModeWithOptions:nil];
877 else {
878 NSApplicationPresentationOptions options = NSApplicationPresentationDefault +NSApplicationPresentationAutoHideDock +
879 NSApplicationPresentationAutoHideMenuBar + NSApplicationPresentationAutoHideToolbar;
880 NSDictionary *opts = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInt:options],
881 NSFullScreenModeApplicationPresentationOptions, nil];
882
883 [self.splitView enterFullScreenMode:[NSScreen mainScreen] withOptions:opts];
884 }
885}
886
Alexandre Lisiona1eee3c2015-08-10 13:44:51 -0400887-(void) mouseIsMoving:(BOOL) move
888{
889 [[controlsPanel animator] setAlphaValue:move]; // fade out
890 [[headerContainer animator] setAlphaValue:move];
891}
892
Alexandre Lisionc5148052015-03-04 15:10:35 -0500893@end