blob: 078e617e1b5982b5bb836a3c596ea4a1ea767698 [file] [log] [blame]
Alexandre Lisionc5148052015-03-04 15:10:35 -05001/*
2 * Copyright (C) 2004-2015 Savoir-Faire Linux Inc.
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.
18 *
19 * Additional permission under GNU GPL version 3 section 7:
20 *
21 * If you modify this program, or any covered work, by linking or
22 * combining it with the OpenSSL project's OpenSSL library (or a
23 * modified version of that library), containing parts covered by the
24 * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
25 * grants you additional permission to convey the resulting work.
26 * Corresponding Source for a non-source form of such a combination
27 * shall include the source code for the parts of OpenSSL used as well
28 * as that of the covered work.
29 */
30#import "CurrentCallVC.h"
31
32#import <QuartzCore/QuartzCore.h>
33
34#import <call.h>
35#import <callmodel.h>
36#import <useractionmodel.h>
37#import <contactmethod.h>
38#import <qabstractitemmodel.h>
39#import <QItemSelectionModel>
40#import <QItemSelection>
Alexandre Lisionc5148052015-03-04 15:10:35 -050041#import <video/previewmanager.h>
42#import <video/renderer.h>
Alexandre Lision58cab672015-06-09 15:25:40 -040043#import <media/text.h>
Alexandre Lisionc5148052015-03-04 15:10:35 -050044
Alexandre Lision74dd47f2015-04-14 13:47:42 -040045#import "views/CallView.h"
46
Alexandre Lisionc5148052015-03-04 15:10:35 -050047@interface RendererConnectionsHolder : NSObject
48
49@property QMetaObject::Connection frameUpdated;
50@property QMetaObject::Connection started;
51@property QMetaObject::Connection stopped;
52
53@end
54
55@implementation RendererConnectionsHolder
56
57@end
58
59@interface CurrentCallVC ()
60
Alexandre Lision58cab672015-06-09 15:25:40 -040061@property (unsafe_unretained) IBOutlet NSTextField *personLabel;
62@property (unsafe_unretained) IBOutlet NSTextField *stateLabel;
63@property (unsafe_unretained) IBOutlet NSButton *holdOnOffButton;
64@property (unsafe_unretained) IBOutlet NSButton *hangUpButton;
65@property (unsafe_unretained) IBOutlet NSButton *recordOnOffButton;
66@property (unsafe_unretained) IBOutlet NSButton *pickUpButton;
Alexandre Lisiond18fa272015-06-15 11:18:03 -040067@property (unsafe_unretained) IBOutlet NSButton *muteAudioButton;
68@property (unsafe_unretained) IBOutlet NSButton *muteVideoButton;
69
70
Alexandre Lision58cab672015-06-09 15:25:40 -040071@property (unsafe_unretained) IBOutlet NSTextField *timeSpentLabel;
72@property (unsafe_unretained) IBOutlet NSView *controlsPanel;
73@property (unsafe_unretained) IBOutlet NSSplitView *splitView;
74@property (unsafe_unretained) IBOutlet NSButton *chatButton;
Alexandre Lisionc5148052015-03-04 15:10:35 -050075
76@property QHash<int, NSButton*> actionHash;
77
78// Video
Alexandre Lision58cab672015-06-09 15:25:40 -040079@property (unsafe_unretained) IBOutlet CallView *videoView;
Alexandre Lisionc5148052015-03-04 15:10:35 -050080@property CALayer* videoLayer;
Alexandre Lision58cab672015-06-09 15:25:40 -040081@property (unsafe_unretained) IBOutlet NSView *previewView;
Alexandre Lisionc5148052015-03-04 15:10:35 -050082@property CALayer* previewLayer;
83
84@property RendererConnectionsHolder* previewHolder;
85@property RendererConnectionsHolder* videoHolder;
Alexandre Lisionef6333a2015-03-24 12:30:31 -040086@property QMetaObject::Connection videoStarted;
Alexandre Lisionc5148052015-03-04 15:10:35 -050087
88@end
89
90@implementation CurrentCallVC
Alexandre Lisiond18fa272015-06-15 11:18:03 -040091@synthesize personLabel, actionHash, stateLabel, holdOnOffButton, hangUpButton,
92 recordOnOffButton, pickUpButton, chatButton, timeSpentLabel,
93 muteVideoButton, muteAudioButton, controlsPanel, videoView,
94 videoLayer, previewLayer, previewView, splitView;
Alexandre Lisionc5148052015-03-04 15:10:35 -050095
96@synthesize previewHolder;
97@synthesize videoHolder;
98
Alexandre Lisionef6333a2015-03-24 12:30:31 -040099- (void) updateAllActions
Alexandre Lisionc5148052015-03-04 15:10:35 -0500100{
101 for(int i = 0 ; i <= CallModel::instance()->userActionModel()->rowCount() ; i++) {
Alexandre Lisionef6333a2015-03-24 12:30:31 -0400102 [self updateActionAtIndex:i];
103 }
104}
105
106- (void) updateActionAtIndex:(int) row
107{
108 const QModelIndex& idx = CallModel::instance()->userActionModel()->index(row,0);
109 UserActionModel::Action action = qvariant_cast<UserActionModel::Action>(idx.data(UserActionModel::Role::ACTION));
110 NSButton* a = actionHash[(int) action];
111 if (a != nil) {
112 [a setEnabled:(idx.flags() & Qt::ItemIsEnabled)];
113 [a setState:(idx.data(Qt::CheckStateRole) == Qt::Checked) ? NSOnState : NSOffState];
114
115 if(action == UserActionModel::Action::HOLD) {
Alexandre Lisiond18fa272015-06-15 11:18:03 -0400116 NSString* imgName = (a.state == NSOnState ? @"ic_action_holdoff" : @"ic_action_hold");
117 [a setImage:[NSImage imageNamed:imgName]];
118
Alexandre Lisionef6333a2015-03-24 12:30:31 -0400119 }
120 if(action == UserActionModel::Action::RECORD) {
121 [a setTitle:(a.state == NSOnState ? @"Record off" : @"Record")];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500122 }
123 }
124}
125
126-(void) updateCall
127{
128 QModelIndex callIdx = CallModel::instance()->selectionModel()->currentIndex();
Alexandre Lision58cab672015-06-09 15:25:40 -0400129 [personLabel setStringValue:callIdx.data(Qt::DisplayRole).toString().toNSString()];
130 [timeSpentLabel setStringValue:callIdx.data((int)Call::Role::Length).toString().toNSString()];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500131
Alexandre Lision58cab672015-06-09 15:25:40 -0400132 Call::State state = callIdx.data((int)Call::Role::State).value<Call::State>();
Alexandre Lisionc5148052015-03-04 15:10:35 -0500133
134 switch (state) {
Alexandre Lisione6dbf092015-04-11 17:19:35 -0400135 case Call::State::DIALING:
136 [stateLabel setStringValue:@"Dialing"];
137 break;
138 case Call::State::NEW:
139 [stateLabel setStringValue:@"New"];
140 break;
Alexandre Lisionc5148052015-03-04 15:10:35 -0500141 case Call::State::INITIALIZATION:
142 [stateLabel setStringValue:@"Initializing"];
Alexandre Lision74dd47f2015-04-14 13:47:42 -0400143 [videoView setShouldAcceptInteractions:NO];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500144 break;
145 case Call::State::RINGING:
146 [stateLabel setStringValue:@"Ringing"];
Alexandre Lision74dd47f2015-04-14 13:47:42 -0400147 [videoView setShouldAcceptInteractions:NO];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500148 break;
149 case Call::State::CURRENT:
150 [stateLabel setStringValue:@"Current"];
Alexandre Lision74dd47f2015-04-14 13:47:42 -0400151 [videoView setShouldAcceptInteractions:YES];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500152 break;
153 case Call::State::HOLD:
154 [stateLabel setStringValue:@"On Hold"];
Alexandre Lision74dd47f2015-04-14 13:47:42 -0400155 [videoView setShouldAcceptInteractions:NO];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500156 break;
157 case Call::State::BUSY:
158 [stateLabel setStringValue:@"Busy"];
Alexandre Lision74dd47f2015-04-14 13:47:42 -0400159 [videoView setShouldAcceptInteractions:NO];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500160 break;
161 case Call::State::OVER:
162 [stateLabel setStringValue:@"Finished"];
Alexandre Lision74dd47f2015-04-14 13:47:42 -0400163 [videoView setShouldAcceptInteractions:NO];
164 if(videoView.isInFullScreenMode)
165 [videoView exitFullScreenModeWithOptions:nil];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500166 break;
Alexandre Lisione6dbf092015-04-11 17:19:35 -0400167 case Call::State::ABORTED:
168 [stateLabel setStringValue:@"Aborted"];
169 break;
Alexandre Lisionc5148052015-03-04 15:10:35 -0500170 case Call::State::FAILURE:
171 [stateLabel setStringValue:@"Failure"];
Alexandre Lision74dd47f2015-04-14 13:47:42 -0400172 [videoView setShouldAcceptInteractions:NO];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500173 break;
Alexandre Lisione6dbf092015-04-11 17:19:35 -0400174 case Call::State::INCOMING:
175 [stateLabel setStringValue:@"Incoming"];
176 break;
Alexandre Lisionc5148052015-03-04 15:10:35 -0500177 default:
Alexandre Lisione6dbf092015-04-11 17:19:35 -0400178 [stateLabel setStringValue:@""];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500179 break;
180 }
181
182}
183
184- (void)awakeFromNib
185{
186 NSLog(@"INIT CurrentCall VC");
Alexandre Lisionef6333a2015-03-24 12:30:31 -0400187 [self.view setWantsLayer:YES];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500188 [self.view setLayer:[CALayer layer]];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500189
190 [controlsPanel setWantsLayer:YES];
191 [controlsPanel setLayer:[CALayer layer]];
192 [controlsPanel.layer setZPosition:2.0];
193 [controlsPanel.layer setBackgroundColor:[NSColor whiteColor].CGColor];
194
Alexandre Lisionef6333a2015-03-24 12:30:31 -0400195 actionHash[ (int)UserActionModel::Action::ACCEPT] = pickUpButton;
196 actionHash[ (int)UserActionModel::Action::HOLD ] = holdOnOffButton;
197 actionHash[ (int)UserActionModel::Action::RECORD] = recordOnOffButton;
198 actionHash[ (int)UserActionModel::Action::HANGUP] = hangUpButton;
Alexandre Lisiond18fa272015-06-15 11:18:03 -0400199 actionHash[ (int)UserActionModel::Action::MUTE_AUDIO] = muteAudioButton;
200 actionHash[ (int)UserActionModel::Action::MUTE_VIDEO] = muteVideoButton;
Alexandre Lisionc5148052015-03-04 15:10:35 -0500201
Alexandre Lisionc5148052015-03-04 15:10:35 -0500202 videoLayer = [CALayer layer];
203 [videoView setWantsLayer:YES];
204 [videoView setLayer:videoLayer];
205 [videoView.layer setBackgroundColor:[NSColor blackColor].CGColor];
206 [videoView.layer setFrame:videoView.frame];
207 [videoView.layer setContentsGravity:kCAGravityResizeAspect];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500208
209 previewLayer = [CALayer layer];
210 [previewView setWantsLayer:YES];
211 [previewView setLayer:previewLayer];
212 [previewLayer setBackgroundColor:[NSColor blackColor].CGColor];
Alexandre Lisionef6333a2015-03-24 12:30:31 -0400213 [previewLayer setContentsGravity:kCAGravityResizeAspectFill];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500214 [previewLayer setFrame:previewView.frame];
215
216 [controlsPanel setWantsLayer:YES];
217 [controlsPanel setLayer:[CALayer layer]];
218 [controlsPanel.layer setBackgroundColor:[NSColor clearColor].CGColor];
219 [controlsPanel.layer setFrame:controlsPanel.frame];
220
Alexandre Lisionef6333a2015-03-24 12:30:31 -0400221 previewHolder = [[RendererConnectionsHolder alloc] init];
222 videoHolder = [[RendererConnectionsHolder alloc] init];
223
Alexandre Lision58cab672015-06-09 15:25:40 -0400224 [self.videoView setFullScreenDelegate:self];
225
Alexandre Lisionc5148052015-03-04 15:10:35 -0500226 [self connect];
227}
228
229- (void) connect
230{
231 QObject::connect(CallModel::instance()->selectionModel(),
232 &QItemSelectionModel::currentChanged,
233 [=](const QModelIndex &current, const QModelIndex &previous) {
Alexandre Lisionc5148052015-03-04 15:10:35 -0500234 if(!current.isValid()) {
235 [self animateOut];
236 return;
237 }
Alexandre Lision58cab672015-06-09 15:25:40 -0400238 [self collapseRightView];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500239 [self updateCall];
Alexandre Lisionef6333a2015-03-24 12:30:31 -0400240 [self updateAllActions];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500241 [self animateOut];
242 });
243
244 QObject::connect(CallModel::instance(),
245 &QAbstractItemModel::dataChanged,
246 [=](const QModelIndex &topLeft, const QModelIndex &bottomRight) {
Alexandre Lisionc5148052015-03-04 15:10:35 -0500247 [self updateCall];
248 });
249
250 QObject::connect(CallModel::instance()->userActionModel(),
251 &QAbstractItemModel::dataChanged,
252 [=](const QModelIndex &topLeft, const QModelIndex &bottomRight) {
Alexandre Lisionc5148052015-03-04 15:10:35 -0500253 const int first(topLeft.row()),last(bottomRight.row());
254 for(int i = first; i <= last;i++) {
Alexandre Lisionef6333a2015-03-24 12:30:31 -0400255 [self updateActionAtIndex:i];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500256 }
257 });
258
259 QObject::connect(CallModel::instance(),
260 &CallModel::callStateChanged,
261 [self](Call* c, Call::State state) {
Alexandre Lisionc5148052015-03-04 15:10:35 -0500262 [self updateCall];
263 });
264}
265
266-(void) connectVideoSignals
267{
268 QModelIndex idx = CallModel::instance()->selectionModel()->currentIndex();
269 Call* call = CallModel::instance()->getCall(idx);
Alexandre Lision58cab672015-06-09 15:25:40 -0400270 self.videoStarted = QObject::connect(call,
Alexandre Lisionc5148052015-03-04 15:10:35 -0500271 &Call::videoStarted,
272 [=](Video::Renderer* renderer) {
Alexandre Lisionef6333a2015-03-24 12:30:31 -0400273 NSLog(@"Video started!");
Alexandre Lisionef6333a2015-03-24 12:30:31 -0400274 [self connectVideoRenderer:renderer];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500275 });
276
277 if(call->videoRenderer())
278 {
Alexandre Lisionc5148052015-03-04 15:10:35 -0500279 [self connectVideoRenderer:call->videoRenderer()];
280 }
281
282 [self connectPreviewRenderer];
283
284}
285
286-(void) connectPreviewRenderer
287{
Alexandre Lisionef6333a2015-03-24 12:30:31 -0400288 QObject::disconnect(previewHolder.frameUpdated);
289 QObject::disconnect(previewHolder.stopped);
290 QObject::disconnect(previewHolder.started);
Alexandre Lisionc5148052015-03-04 15:10:35 -0500291 previewHolder.started = QObject::connect(Video::PreviewManager::instance(),
292 &Video::PreviewManager::previewStarted,
293 [=](Video::Renderer* renderer) {
Alexandre Lisionc5148052015-03-04 15:10:35 -0500294 QObject::disconnect(previewHolder.frameUpdated);
295 previewHolder.frameUpdated = QObject::connect(renderer,
296 &Video::Renderer::frameUpdated,
297 [=]() {
298 [self renderer:Video::PreviewManager::instance()->previewRenderer()
299 renderFrameForView:previewView];
300 });
301 });
302
303 previewHolder.stopped = QObject::connect(Video::PreviewManager::instance(),
304 &Video::PreviewManager::previewStopped,
305 [=](Video::Renderer* renderer) {
Alexandre Lisionc5148052015-03-04 15:10:35 -0500306 QObject::disconnect(previewHolder.frameUpdated);
307 [previewView.layer setContents:nil];
308 });
309
310 previewHolder.frameUpdated = QObject::connect(Video::PreviewManager::instance()->previewRenderer(),
311 &Video::Renderer::frameUpdated,
312 [=]() {
313 [self renderer:Video::PreviewManager::instance()->previewRenderer()
314 renderFrameForView:previewView];
315 });
316}
317
318-(void) connectVideoRenderer: (Video::Renderer*)renderer
319{
Alexandre Lisionef6333a2015-03-24 12:30:31 -0400320 QObject::disconnect(videoHolder.frameUpdated);
321 QObject::disconnect(videoHolder.started);
322 QObject::disconnect(videoHolder.stopped);
Alexandre Lisionc5148052015-03-04 15:10:35 -0500323 videoHolder.frameUpdated = QObject::connect(renderer,
324 &Video::Renderer::frameUpdated,
325 [=]() {
326 [self renderer:renderer renderFrameForView:videoView];
327 });
328
329 videoHolder.started = QObject::connect(renderer,
330 &Video::Renderer::started,
331 [=]() {
Alexandre Lisionc5148052015-03-04 15:10:35 -0500332 QObject::disconnect(videoHolder.frameUpdated);
333 videoHolder.frameUpdated = QObject::connect(renderer,
334 &Video::Renderer::frameUpdated,
335 [=]() {
336 [self renderer:renderer renderFrameForView:videoView];
337 });
338 });
339
340 videoHolder.stopped = QObject::connect(renderer,
341 &Video::Renderer::stopped,
342 [=]() {
Alexandre Lisionc5148052015-03-04 15:10:35 -0500343 QObject::disconnect(videoHolder.frameUpdated);
344 [videoView.layer setContents:nil];
345 });
346}
347
348-(void) renderer: (Video::Renderer*)renderer renderFrameForView:(NSView*) view
349{
350 const QByteArray& data = renderer->currentFrame();
351 QSize res = renderer->size();
352
353 auto buf = reinterpret_cast<const unsigned char*>(data.data());
354
355 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
356 CGContextRef newContext = CGBitmapContextCreate((void *)buf,
357 res.width(),
358 res.height(),
359 8,
360 4*res.width(),
361 colorSpace,
362 kCGImageAlphaPremultipliedLast);
363
364
365 CGImageRef newImage = CGBitmapContextCreateImage(newContext);
366
367 /*We release some components*/
368 CGContextRelease(newContext);
369 CGColorSpaceRelease(colorSpace);
370
371 [CATransaction begin];
372 view.layer.contents = (__bridge id)newImage;
373 [CATransaction commit];
374
375 CFRelease(newImage);
376}
377
378- (void) initFrame
379{
380 [self.view setFrame:self.view.superview.bounds];
381 [self.view setHidden:YES];
382 self.view.layer.position = self.view.frame.origin;
383}
384
385# pragma private IN/OUT animations
386
387-(void) animateIn
388{
389 NSLog(@"animateIn");
390 CGRect frame = CGRectOffset(self.view.superview.bounds, -self.view.superview.bounds.size.width, 0);
391 [self.view setHidden:NO];
392
393 [CATransaction begin];
394 CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
395 [animation setFromValue:[NSValue valueWithPoint:frame.origin]];
396 [animation setToValue:[NSValue valueWithPoint:self.view.superview.bounds.origin]];
397 [animation setDuration:0.2f];
398 [animation setTimingFunction:[CAMediaTimingFunction functionWithControlPoints:.7 :0.9 :1 :1]];
399 [CATransaction setCompletionBlock:^{
Alexandre Lisionc5148052015-03-04 15:10:35 -0500400 [self connectVideoSignals];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500401 }];
402 [self.view.layer addAnimation:animation forKey:animation.keyPath];
403
404 [CATransaction commit];
405}
406
407-(void) cleanUp
408{
Alexandre Lisionef6333a2015-03-24 12:30:31 -0400409 QObject::disconnect(videoHolder.frameUpdated);
410 QObject::disconnect(videoHolder.started);
411 QObject::disconnect(videoHolder.stopped);
412 QObject::disconnect(previewHolder.frameUpdated);
413 QObject::disconnect(previewHolder.stopped);
414 QObject::disconnect(previewHolder.started);
Alexandre Lisionc5148052015-03-04 15:10:35 -0500415 [videoView.layer setContents:nil];
416 [previewView.layer setContents:nil];
417}
418
419-(void) animateOut
420{
421 NSLog(@"animateOut");
422 if(self.view.frame.origin.x < 0) {
423 NSLog(@"Already hidden");
424 if (CallModel::instance()->selectionModel()->currentIndex().isValid()) {
425 [self animateIn];
426 }
427 return;
428 }
429
430 CGRect frame = CGRectOffset(self.view.frame, -self.view.frame.size.width, 0);
431 [CATransaction begin];
432 CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
433 [animation setFromValue:[NSValue valueWithPoint:self.view.frame.origin]];
434 [animation setToValue:[NSValue valueWithPoint:frame.origin]];
435 [animation setDuration:0.2f];
436 [animation setTimingFunction:[CAMediaTimingFunction functionWithControlPoints:.7 :0.9 :1 :1]];
437
438 [CATransaction setCompletionBlock:^{
439 [self.view setHidden:YES];
Alexandre Lisionef6333a2015-03-24 12:30:31 -0400440 // first make sure everything is disconnected
Alexandre Lisionc5148052015-03-04 15:10:35 -0500441 [self cleanUp];
Alexandre Lisionc5148052015-03-04 15:10:35 -0500442 if (CallModel::instance()->selectionModel()->currentIndex().isValid()) {
443 [self animateIn];
444 }
445 }];
446 [self.view.layer addAnimation:animation forKey:animation.keyPath];
447 [CATransaction commit];
448}
449
450/**
451 * Debug purpose
452 */
453-(void) dumpFrame:(CGRect) frame WithName:(NSString*) name
454{
455 NSLog(@"frame %@ : %f %f %f %f \n\n",name ,frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
456}
457
Alexandre Lision58cab672015-06-09 15:25:40 -0400458-(void)collapseRightView
459{
460 NSView *right = [[splitView subviews] objectAtIndex:1];
461 NSView *left = [[splitView subviews] objectAtIndex:0];
462 NSRect leftFrame = [left frame];
463 [right setHidden:YES];
464 [splitView display];
465}
Alexandre Lisionc5148052015-03-04 15:10:35 -0500466
Alexandre Lision58cab672015-06-09 15:25:40 -0400467-(void)uncollapseRightView
468{
469 NSView *left = [[splitView subviews] objectAtIndex:0];
470 NSView *right = [[splitView subviews] objectAtIndex:1];
471 [right setHidden:NO];
472
473 CGFloat dividerThickness = [splitView dividerThickness];
474
475 // get the different frames
476 NSRect leftFrame = [left frame];
477 NSRect rightFrame = [right frame];
478
479 leftFrame.size.width = (leftFrame.size.width - rightFrame.size.width - dividerThickness);
480 rightFrame.origin.x = leftFrame.size.width + dividerThickness;
481 [left setFrameSize:leftFrame.size];
482 [right setFrame:rightFrame];
483 [splitView display];
484}
485
486
487#pragma mark - Button methods
488
Alexandre Lisionc5148052015-03-04 15:10:35 -0500489- (IBAction)hangUp:(id)sender {
490 CallModel::instance()->getCall(CallModel::instance()->selectionModel()->currentIndex()) << Call::Action::REFUSE;
491}
492
493- (IBAction)accept:(id)sender {
494 CallModel::instance()->getCall(CallModel::instance()->selectionModel()->currentIndex()) << Call::Action::ACCEPT;
495}
496
497- (IBAction)toggleRecording:(id)sender {
Alexandre Lision66643432015-06-04 11:59:36 -0400498 CallModel::instance()->getCall(CallModel::instance()->selectionModel()->currentIndex()) << Call::Action::RECORD_AUDIO;
Alexandre Lisionc5148052015-03-04 15:10:35 -0500499}
500
501- (IBAction)toggleHold:(id)sender {
502 CallModel::instance()->getCall(CallModel::instance()->selectionModel()->currentIndex()) << Call::Action::HOLD;
503}
504
Alexandre Lision58cab672015-06-09 15:25:40 -0400505-(IBAction)toggleChat:(id)sender;
506{
507 BOOL rightViewCollapsed = [[self splitView] isSubviewCollapsed:[[[self splitView] subviews] objectAtIndex: 1]];
508 if (rightViewCollapsed) {
509 [self uncollapseRightView];
510 CallModel::instance()->getCall(CallModel::instance()->selectionModel()->currentIndex())->addOutgoingMedia<Media::Text>();
511 } else {
512 [self collapseRightView];
513 }
514 [chatButton setState:rightViewCollapsed];
515}
516
Alexandre Lisiond18fa272015-06-15 11:18:03 -0400517- (IBAction)muteAudio:(id)sender
518{
519 UserActionModel* uam = CallModel::instance()->userActionModel();
520 uam << UserActionModel::Action::MUTE_AUDIO;
521}
522
523- (IBAction)muteVideo:(id)sender
524{
525 UserActionModel* uam = CallModel::instance()->userActionModel();
526 uam << UserActionModel::Action::MUTE_VIDEO;
527}
528
Alexandre Lision58cab672015-06-09 15:25:40 -0400529#pragma mark - NSSplitViewDelegate
530
531/* 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.
532 */
533- (BOOL)splitView:(NSSplitView *)splitView shouldCollapseSubview:(NSView *)subview forDoubleClickOnDividerAtIndex:(NSInteger)dividerIndex;
534{
535 NSView* rightView = [[splitView subviews] objectAtIndex:1];
536 return ([subview isEqual:rightView]);
537}
538
539
540- (BOOL)splitView:(NSSplitView *)splitView canCollapseSubview:(NSView *)subview;
541{
542 NSView* rightView = [[splitView subviews] objectAtIndex:1];
543 return ([subview isEqual:rightView]);
544}
545
546
547# pragma mark - FullScreenDelegate
548
549- (void) callShouldToggleFullScreen
550{
551 if(self.splitView.isInFullScreenMode)
552 [self.splitView exitFullScreenModeWithOptions:nil];
553 else {
554 NSApplicationPresentationOptions options = NSApplicationPresentationDefault +NSApplicationPresentationAutoHideDock +
555 NSApplicationPresentationAutoHideMenuBar + NSApplicationPresentationAutoHideToolbar;
556 NSDictionary *opts = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInt:options],
557 NSFullScreenModeApplicationPresentationOptions, nil];
558
559 [self.splitView enterFullScreenMode:[NSScreen mainScreen] withOptions:opts];
560 }
561}
562
Alexandre Lisionc5148052015-03-04 15:10:35 -0500563@end