Commit 5d90c3bc authored by Kateryna Kostiuk's avatar Kateryna Kostiuk

media: link to avModel

Change-Id: I0a904813749d3ddc645878fad107aacdee9cd9bc
parent 8ba71157
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#import "RingWindowController.h" #import "RingWindowController.h"
#import "PreferencesWindowController.h" #import "PreferencesWindowController.h"
#import <string>
@interface AppDelegate : NSObject <NSApplicationDelegate, NSUserNotificationCenterDelegate> @interface AppDelegate : NSObject <NSApplicationDelegate, NSUserNotificationCenterDelegate>
...@@ -28,5 +29,6 @@ ...@@ -28,5 +29,6 @@
- (void) showMainWindow; - (void) showMainWindow;
- (void) showDialpad; - (void) showDialpad;
- (BOOL) checkForRingAccount; - (BOOL) checkForRingAccount;
- (std::vector<std::string>) getActiveCalls;
@end @end
...@@ -350,6 +350,9 @@ static void ReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNet ...@@ -350,6 +350,9 @@ static void ReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNet
[self.dialpad.window makeKeyAndOrderFront:self]; [self.dialpad.window makeKeyAndOrderFront:self];
} }
-(std::vector<std::string>) getActiveCalls {
return lrc->activeCalls();
}
- (BOOL) checkForRingAccount - (BOOL) checkForRingAccount
{ {
...@@ -364,39 +367,6 @@ static void ReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNet ...@@ -364,39 +367,6 @@ static void ReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNet
forEventClass:kInternetEventClass andEventID:kAEGetURL]; forEventClass:kInternetEventClass andEventID:kAEGetURL];
} }
/**
* Recognized patterns:
* - ring:<hash>
* - ring://<hash>
*/
- (void)handleGetURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
{
NSString* query = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
NSURL* url = [[NSURL alloc] initWithString:query];
NSString* ringID = [url host];
if (!ringID) {
//not a valid NSURL, try to parse query directly
ringID = [query substringFromIndex:@"ring:".length];
}
// check for a valid ring hash
NSCharacterSet *hexSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789abcdefABCDEF"];
BOOL valid = [[ringID stringByTrimmingCharactersInSet:hexSet] isEqualToString:@""];
if(valid && ringID.length == 40) {
Call* c = CallModel::instance().dialingCall();
c->setDialNumber(QString::fromNSString([NSString stringWithFormat:@"ring:%@",ringID]));
c << Call::Action::ACCEPT;
} else {
NSAlert *alert = [[NSAlert alloc] init];
[alert addButtonWithTitle:@"OK"];
[alert setMessageText:@"Error"];
[alert setInformativeText:@"ringID cannot be read from this URL."];
[alert setAlertStyle:NSWarningAlertStyle];
[alert runModal];
}
}
- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag - (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag
{ {
if([self checkForRingAccount]) { if([self checkForRingAccount]) {
......
...@@ -18,8 +18,9 @@ ...@@ -18,8 +18,9 @@
*/ */
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "LrcModelsProtocol.h"
@interface AudioPrefsVC : NSViewController <NSMenuDelegate, NSPathControlDelegate, NSOpenSavePanelDelegate> { @interface AudioPrefsVC : NSViewController <LrcModelsProtocol> {
} }
......
/* /*
* Copyright (C) 2015-2016 Savoir-faire Linux Inc. * Copyright (C) 2015-2016 Savoir-faire Linux Inc.
* Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com> * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
* Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -18,203 +19,73 @@ ...@@ -18,203 +19,73 @@
*/ */
#import "AudioPrefsVC.h" #import "AudioPrefsVC.h"
#import <audio/settings.h> //LRC
#import <media/recordingmodel.h> #import <api/avmodel.h>
#import <QUrl>
#import <audio/inputdevicemodel.h>
#import <audio/outputdevicemodel.h>
#import <qitemselectionmodel.h>
#import "utils.h"
@interface AudioPrefsVC () @interface AudioPrefsVC ()
@property (assign) IBOutlet NSPathControl *recordingsPathControl;
@property (assign) IBOutlet NSPopUpButton *outputDeviceList; @property (assign) IBOutlet NSPopUpButton *outputDeviceList;
@property (assign) IBOutlet NSPopUpButton *inputDeviceList; @property (assign) IBOutlet NSPopUpButton *inputDeviceList;
@property (assign) IBOutlet NSButton *alwaysRecordingButton;
@property (assign) IBOutlet NSButton *muteDTMFButton;
@property (assign) IBOutlet NSTextField *recordingHeaderTitle;
@property (assign) IBOutlet NSTextField *recordingpathLabel;
@property (assign) IBOutlet NSLayoutConstraint* audioMarginTopConstraint;
@property (assign) IBOutlet NSLayoutConstraint* audioMarginBottomConstraint;
@end @end
@implementation AudioPrefsVC @implementation AudioPrefsVC
@synthesize recordingsPathControl, recordingHeaderTitle, recordingpathLabel;
@synthesize outputDeviceList; @synthesize outputDeviceList;
@synthesize inputDeviceList; @synthesize inputDeviceList;
@synthesize alwaysRecordingButton; @synthesize avModel;
@synthesize muteDTMFButton; QMetaObject::Connection audioDeviceEvent;
@synthesize audioMarginTopConstraint, audioMarginBottomConstraint;
- (void)loadView -(id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil avModel:(lrc::api::AVModel*) avModel
{ {
[super loadView]; if (self = [self initWithNibName:nibNameOrNil bundle:nibBundleOrNil])
{
QModelIndex qInputIdx = Audio::Settings::instance().inputDeviceModel()->selectionModel()->currentIndex(); self.avModel = avModel;
QModelIndex qOutputIdx = Audio::Settings::instance().outputDeviceModel()->selectionModel()->currentIndex();
[self.outputDeviceList addItemWithTitle:
Audio::Settings::instance().outputDeviceModel()->data(qOutputIdx, Qt::DisplayRole).toString().toNSString()];
[self.inputDeviceList addItemWithTitle:
Audio::Settings::instance().inputDeviceModel()->data(qInputIdx, Qt::DisplayRole).toString().toNSString()];
[self.alwaysRecordingButton setState:
media::RecordingModel::instance().isAlwaysRecording() ? NSOnState:NSOffState];
[self.muteDTMFButton setState:
Audio::Settings::instance().areDTMFMuted()?NSOnState:NSOffState];
NSArray* pathComponentArray = [self pathComponentArrayWithCurrentUrl:media::RecordingModel::instance().recordPath().toNSString()];
[recordingsPathControl setPathComponentCells:pathComponentArray];
if (appSandboxed()) {
[alwaysRecordingButton setHidden:YES];
[recordingsPathControl setEnabled:NO];
[recordingsPathControl setHidden: YES];
[recordingHeaderTitle setHidden: YES];
[recordingpathLabel setHidden: YES];
audioMarginTopConstraint.constant = 10.0f;
audioMarginBottomConstraint.constant = 67.0f;
} }
return self;
} }
- (IBAction)toggleMuteDTMF:(NSButton *)sender - (void)loadView
{ {
Audio::Settings::instance().setDTMFMuted([sender state] == NSOnState); [super loadView];
[self connectdDeviceEvent];
[self addDevices];
} }
- (IBAction)toggleAlwaysRecording:(NSButton *)sender -(void) addDevices {
{ [inputDeviceList removeAllItems];
media::RecordingModel::instance().setAlwaysRecording([sender state] == NSOnState); [outputDeviceList removeAllItems];
auto inputDevices = avModel->getAudioInputDevices();
auto inputDevice = avModel->getInputDevice();
for (auto device : inputDevices) {
[inputDeviceList addItemWithTitle: @(device.c_str())];
}
[inputDeviceList selectItemWithTitle:@(inputDevice.c_str())];
auto outputDevices = avModel->getAudioOutputDevices();
auto outputDevice = avModel->getOutputDevice();
for (auto device : outputDevices) {
[outputDeviceList addItemWithTitle: @(device.c_str())];
}
[outputDeviceList selectItemWithTitle:@(outputDevice.c_str())];
} }
- (IBAction)pathControlSingleClick:(id)sender { -(void)connectdDeviceEvent {
// Select that chosen component of the path. QObject::disconnect(audioDeviceEvent);
NSArray* pathComponentArray = [self pathComponentArrayWithCurrentUrl:[[self.recordingsPathControl clickedPathComponentCell] URL].path]; audioDeviceEvent = QObject::connect(avModel,
[recordingsPathControl setPathComponentCells:pathComponentArray]; &lrc::api::AVModel::deviceEvent,
media::RecordingModel::instance().setRecordPath(QString::fromNSString([self.recordingsPathControl.URL path])); [=]() {
[self addDevices];
});
} }
- (IBAction)chooseOutput:(id)sender { - (IBAction)chooseOutput:(id)sender {
int index = [sender indexOfSelectedItem]; int index = [sender indexOfSelectedItem];
QModelIndex qIdx = Audio::Settings::instance().outputDeviceModel()->index(index, 0); auto output = [self.outputDeviceList itemTitleAtIndex:index];
Audio::Settings::instance().outputDeviceModel()->selectionModel()->setCurrentIndex( avModel->setOutputDevice([output UTF8String]);
qIdx, QItemSelectionModel::ClearAndSelect);
} }
- (IBAction)chooseInput:(id)sender { - (IBAction)chooseInput:(id)sender {
int index = [sender indexOfSelectedItem]; int index = [sender indexOfSelectedItem];
QModelIndex qIdx = Audio::Settings::instance().inputDeviceModel()->index(index, 0); auto input = [self.inputDeviceList itemTitleAtIndex:index];
Audio::Settings::instance().inputDeviceModel()->selectionModel()->setCurrentIndex( avModel->setInputDevice([input UTF8String]);
qIdx, QItemSelectionModel::ClearAndSelect);
}
#pragma mark - NSPathControl delegate methods
/*
Assemble a set of custom cells to display into an array to pass to the path control.
*/
- (NSArray *)pathComponentArrayWithCurrentUrl:(NSString *) url
{
NSMutableArray *pathComponentArray = [[NSMutableArray alloc] init];
NSFileManager *fileManager = [[NSFileManager alloc] init];
NSURL* downloadURL = [fileManager URLForDirectory:NSDownloadsDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
NSPathComponentCell *componentCell;
componentCell = [self componentCellForType:kGenericFolderIcon withTitle:@"Downloads" URL:downloadURL];
[pathComponentArray addObject:componentCell];
NSString * downloads = [downloadURL path];
if([url isEqualToString:downloads]) {
return pathComponentArray;
}
if(![url isEqualToString:@""]) {
NSString * name = [url componentsSeparatedByString:@"/"].lastObject;
if(!name) {
return pathComponentArray;
}
componentCell = [self componentCellForType:kGenericFolderIcon withTitle:name URL:[NSURL URLWithString: url]];
[pathComponentArray addObject:componentCell];
}
return pathComponentArray;
}
/*
This method is used by pathComponentArray to create a NSPathComponent cell based on icon, title and URL information.
Each path component needs an icon, URL and title.
*/
- (NSPathComponentCell *)componentCellForType:(OSType)withIconType withTitle:(NSString *)title URL:(NSURL *)url
{
NSPathComponentCell *componentCell = [[NSPathComponentCell alloc] init];
NSImage *iconImage = [[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(withIconType)];
[componentCell setImage:iconImage];
[componentCell setURL:url];
[componentCell setTitle:title];
return componentCell;
}
/*
Delegate method of NSPathControl to determine how the NSOpenPanel will look/behave.
*/
- (void)pathControl:(NSPathControl *)pathControl willDisplayOpenPanel:(NSOpenPanel *)openPanel
{
NSLog(@"willDisplayOpenPanel");
[openPanel setAllowsMultipleSelection:NO];
[openPanel setCanChooseDirectories:YES];
[openPanel setCanChooseFiles:NO];
[openPanel setResolvesAliases:YES];
[openPanel setTitle:NSLocalizedString(@"Choose a directory", @"Open panel title")];
[openPanel setPrompt:NSLocalizedString(@"Choose directory", @"Open panel prompt for 'Choose a directory'")];
[openPanel setDelegate:self];
}
- (void)pathControl:(NSPathControl *)pathControl willPopUpMenu:(NSMenu *)menu
{
}
#pragma mark - NSOpenSavePanelDelegate delegate methods
- (BOOL)panel:(id)sender validateURL:(NSURL *)url error:(NSError **)outError
{
[recordingsPathControl setURL:url];
return YES;
}
- (BOOL) panel:(id)sender shouldEnableURL:(NSURL*)url {
return YES;
}
#pragma mark - NSMenuDelegate methods
- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel
{
QModelIndex qIdx;
if (inputDeviceList.menu == menu) {
qIdx = Audio::Settings::instance().inputDeviceModel()->index(index);
[item setTitle:Audio::Settings::instance().inputDeviceModel()->data(qIdx, Qt::DisplayRole).toString().toNSString()];
} else {
qIdx = Audio::Settings::instance().outputDeviceModel()->index(index);
[item setTitle:Audio::Settings::instance().outputDeviceModel()->data(qIdx, Qt::DisplayRole).toString().toNSString()];
}
return YES;
}
- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu
{
if (inputDeviceList.menu == menu)
return Audio::Settings::instance().inputDeviceModel()->rowCount();
else
return Audio::Settings::instance().outputDeviceModel()->rowCount();
} }
@end @end
...@@ -23,6 +23,12 @@ ...@@ -23,6 +23,12 @@
#import "views/CallView.h" #import "views/CallView.h"
#import <api/account.h> #import <api/account.h>
namespace lrc {
namespace api {
class AVModel;
}
}
@protocol CallViewControllerDelegate @protocol CallViewControllerDelegate
-(void) conversationInfoUpdatedFor:(const std::string&) conversationID; -(void) conversationInfoUpdatedFor:(const std::string&) conversationID;
...@@ -39,5 +45,6 @@ ...@@ -39,5 +45,6 @@
-(void) hideWithAnimation:(BOOL)animate; -(void) hideWithAnimation:(BOOL)animate;
-(void) setCurrentCall:(const std::string&)callUid -(void) setCurrentCall:(const std::string&)callUid
conversation:(const std::string&)convUid conversation:(const std::string&)convUid
account:(const lrc::api::account::Info*)account; account:(const lrc::api::account::Info*)account
avModel:(lrc::api::AVModel *)avModel;
@end @end
This diff is collapsed.
...@@ -36,16 +36,6 @@ ...@@ -36,16 +36,6 @@
- (void)windowDidLoad { - (void)windowDidLoad {
[super windowDidLoad]; [super windowDidLoad];
QObject::connect(CallModel::instance().selectionModel(),
&QItemSelectionModel::currentChanged,
[=](const QModelIndex &current, const QModelIndex &previous) {
[composerField setStringValue:@""];
[composerField setNeedsDisplay:YES];
if(!current.isValid()) {
[self.window close];
}
});
} }
- (IBAction)dtmfPressed:(id)sender - (IBAction)dtmfPressed:(id)sender
...@@ -66,11 +56,6 @@ ...@@ -66,11 +56,6 @@
- (void) sendDTMF:(NSString*) dtmf - (void) sendDTMF:(NSString*) dtmf
{ {
if (auto current = CallModel::instance().selectedCall()) {
current->playDTMF(QString::fromUtf8([dtmf UTF8String]));
}
[composerField setStringValue:
[NSString stringWithFormat: @"%@ %@", [composerField stringValue], dtmf]];
} }
///Accessibility ///Accessibility
......
...@@ -81,7 +81,7 @@ static auto const kVideoPrefsIdentifer = @"VideoPrefsIdentifer"; ...@@ -81,7 +81,7 @@ static auto const kVideoPrefsIdentifer = @"VideoPrefsIdentifer";
{ {
[[prefsContainer subviews] [[prefsContainer subviews]
makeObjectsPerformSelector:@selector(removeFromSuperview)]; makeObjectsPerformSelector:@selector(removeFromSuperview)];
currentVC = [[AudioPrefsVC alloc] initWithNibName:@"AudioPrefs" bundle:nil]; currentVC = [[AudioPrefsVC alloc] initWithNibName:@"AudioPrefs" bundle:nil avModel: self.avModel];
[self resizeWindowWithFrame:currentVC.view.frame]; [self resizeWindowWithFrame:currentVC.view.frame];
[prefsContainer addSubview:currentVC.view]; [prefsContainer addSubview:currentVC.view];
} }
...@@ -132,4 +132,9 @@ static auto const kVideoPrefsIdentifer = @"VideoPrefsIdentifer"; ...@@ -132,4 +132,9 @@ static auto const kVideoPrefsIdentifer = @"VideoPrefsIdentifer";
return (frame.size.height - contentRect.size.height); return (frame.size.height - contentRect.size.height);
} }
- (BOOL)windowShouldClose:(id)sender {
[self.window orderOut:self];
return NO;
}
@end @end
...@@ -29,7 +29,7 @@ namespace lrc { ...@@ -29,7 +29,7 @@ namespace lrc {
} }
} }
@interface RingWindowController : NSWindowController <NSSharingServicePickerDelegate, ChooseAccountDelegate, LrcModelsProtocol, CallViewControllerDelegate> { @interface RingWindowController : NSWindowController <NSSharingServicePickerDelegate, ChooseAccountDelegate, LrcModelsProtocol, CallViewControllerDelegate,NSWindowDelegate> {
IBOutlet NSView *currentView; IBOutlet NSView *currentView;
} }
......
...@@ -103,6 +103,8 @@ typedef NS_ENUM(NSInteger, ViewState) { ...@@ -103,6 +103,8 @@ typedef NS_ENUM(NSInteger, ViewState) {
self.dataTransferModel = dataTransferModel; self.dataTransferModel = dataTransferModel;
self.behaviorController = behaviorController; self.behaviorController = behaviorController;
self.avModel = avModel; self.avModel = avModel;
self.avModel->useAVFrame(YES);
avModel->deactivateOldVideoModels();
} }
return self; return self;
} }
...@@ -137,6 +139,7 @@ typedef NS_ENUM(NSInteger, ViewState) { ...@@ -137,6 +139,7 @@ typedef NS_ENUM(NSInteger, ViewState) {
[settingsVC hide]; [settingsVC hide];
break; break;
case SHOW_CALL_SCREEN: case SHOW_CALL_SCREEN:
self.avModel->useAVFrame(YES);
[self accountSettingsShouldOpen: NO]; [self accountSettingsShouldOpen: NO];
if (![currentCallVC.view superview]) { if (![currentCallVC.view superview]) {
[callView addSubview:[currentCallVC view] positioned:NSWindowAbove relativeTo:nil]; [callView addSubview:[currentCallVC view] positioned:NSWindowAbove relativeTo:nil];
...@@ -223,7 +226,6 @@ typedef NS_ENUM(NSInteger, ViewState) { ...@@ -223,7 +226,6 @@ typedef NS_ENUM(NSInteger, ViewState) {
NSResponder * viewNextResponder = [self nextResponder]; NSResponder * viewNextResponder = [self nextResponder];
[self setNextResponder: [conversationVC getMessagesView]]; [self setNextResponder: [conversationVC getMessagesView]];
[[conversationVC getMessagesView] setNextResponder: viewNextResponder]; [[conversationVC getMessagesView] setNextResponder: viewNextResponder];
self.avModel->useAVFrame(YES);
} }
- (void) connect - (void) connect
...@@ -240,7 +242,8 @@ typedef NS_ENUM(NSInteger, ViewState) { ...@@ -240,7 +242,8 @@ typedef NS_ENUM(NSInteger, ViewState) {
[currentCallVC setCurrentCall:convInfo.callId [currentCallVC setCurrentCall:convInfo.callId
conversation:convInfo.uid conversation:convInfo.uid
account:accInfo]; account:accInfo
avModel: avModel];
[self changeViewTo:SHOW_CALL_SCREEN]; [self changeViewTo:SHOW_CALL_SCREEN];
}); });
...@@ -257,7 +260,8 @@ typedef NS_ENUM(NSInteger, ViewState) { ...@@ -257,7 +260,8 @@ typedef NS_ENUM(NSInteger, ViewState) {
[currentCallVC setCurrentCall:convInfo.callId [currentCallVC setCurrentCall:convInfo.callId
conversation:convInfo.uid conversation:convInfo.uid
account:accInfo]; account:accInfo
avModel: avModel];
[smartViewVC selectConversation: convInfo model:accInfo->conversationModel.get()]; [smartViewVC selectConversation: convInfo model:accInfo->conversationModel.get()];
[self changeViewTo:SHOW_CALL_SCREEN]; [self changeViewTo:SHOW_CALL_SCREEN];
}); });
...@@ -589,7 +593,8 @@ typedef NS_ENUM(NSInteger, ViewState) { ...@@ -589,7 +593,8 @@ typedef NS_ENUM(NSInteger, ViewState) {
} }
[currentCallVC setCurrentCall:[callId UTF8String] [currentCallVC setCurrentCall:[callId UTF8String]
conversation:[conversationId UTF8String] conversation:[conversationId UTF8String]
account:&accInfo]; account:&accInfo
avModel:avModel];
[self changeViewTo:SHOW_CALL_SCREEN]; [self changeViewTo:SHOW_CALL_SCREEN];
} }
...@@ -608,4 +613,9 @@ typedef NS_ENUM(NSInteger, ViewState) { ...@@ -608,4 +613,9 @@ typedef NS_ENUM(NSInteger, ViewState) {
} }
[self changeViewTo:SHOW_CONVERSATION_SCREEN]; [self changeViewTo:SHOW_CONVERSATION_SCREEN];
} }
- (BOOL)windowShouldClose:(id)sender {
[NSApp hide:nil];
return NO;
}
@end @end
This diff is collapsed.
...@@ -483,8 +483,6 @@ namespace Interfaces { ...@@ -483,8 +483,6 @@ namespace Interfaces {
QVariant ImageManipulationDelegate::decorationRole(const Account* acc) QVariant ImageManipulationDelegate::decorationRole(const Account* acc)
{ {
Q_UNUSED(acc) Q_UNUSED(acc)
if (auto pro = ProfileModel::instance().selectedProfile())
return contactPhoto(pro->person(), decorationSize);
return QVariant(); return QVariant();
} }
......
...@@ -23,5 +23,6 @@ ...@@ -23,5 +23,6 @@
@interface CallMTKView: MTKView @interface CallMTKView: MTKView
-(void)renderWithPixelBuffer:(CVPixelBufferRef)buffer size:(CGSize)size rotation: (float)rotation fillFrame: (bool)fill; -(void)renderWithPixelBuffer:(CVPixelBufferRef)buffer size:(CGSize)size rotation: (float)rotation fillFrame: (bool)fill;
-(void)fillWithBlack; -(void)fillWithBlack;
-(void)setupView;
@property bool stopRendering; @property bool stopRendering;
@end @end
...@@ -53,60 +53,64 @@ struct Uniforms { ...@@ -53,60 +53,64 @@ struct Uniforms {
{ {
self = [super initWithFrame:frame]; self = [super initWithFrame:frame];
if (self) { if (self) {
id<MTLDevice> device = MTLCreateSystemDefaultDevice(); [self setupView];
self.device = device; }
commandQueue = [device newCommandQueue]; return self;
self.colorPixelFormat = MTLPixelFormatBGRA8Unorm; }
commandQueue = [device newCommandQueue];
CVReturn err = CVMetalTextureCacheCreate(kCFAllocatorDefault, -(void)setupView {
NULL, id<MTLDevice> device = MTLCreateSystemDefaultDevice();
self.device, self.device = device;
NULL, commandQueue = [device newCommandQueue];
&textureCache); self.colorPixelFormat = MTLPixelFormatBGRA8Unorm;
commandQueue = [device newCommandQueue];
vertexBuffer = [device newBufferWithBytes:&kImagePlaneVertexData CVReturn err = CVMetalTextureCacheCreate(kCFAllocatorDefault,
length:sizeof(kImagePlaneVertexData) NULL,
options:MTLResourceCPUCacheModeDefaultCache]; self.device,
NULL,
&textureCache);
NSString *resourcePath = [[NSBundle mainBundle] resourcePath]; vertexBuffer = [device newBufferWithBytes:&kImagePlaneVertexData
NSString *libraryPath = [resourcePath stringByAppendingPathComponent:@"Shader.metallib"]; length:sizeof(kImagePlaneVertexData)
id <MTLLibrary> library = [device newLibraryWithFile:libraryPath error:nil]; options:MTLResourceCPUCacheModeDefaultCache];
id<MTLFunction> vertexFunc = [library newFunctionWithName:@"imageVertex"];
id<MTLFunction> fragmentFunc = [library newFunctionWithName:@"imageFragment"];
// Create a vertex descriptor for our image plane vertex buffer NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
MTLVertexDescriptor *imagePlaneVertexDescriptor = [[MTLVertexDescriptor alloc] init]; NSString *libraryPath = [resourcePath stringByAppendingPathComponent:@"Shader.metallib"];
id <MTLLibrary> library = [device newLibraryWithFile:libraryPath error:nil];
id<MTLFunction> vertexFunc = [library newFunctionWithName:@"imageVertex"];
id<MTLFunction> fragmentFunc = [library newFunctionWithName:@"imageFragment"];
// Positions. // Create a vertex descriptor for our image plane vertex buffer
imagePlaneVertexDescriptor.attributes[kVertexAttributePosition].format = MTLVertexFormatFloat2; MTLVertexDescriptor *imagePlaneVertexDescriptor = [[MTLVertexDescriptor alloc] init];
imagePlaneVertexDescriptor.attributes[kVertexAttributePosition].offset = 0;
imagePlaneVertexDescriptor.attributes[kVertexAttributePosition].bufferIndex = kBufferIndexMeshPositions;
// Texture coordinates. // Positions.
imagePlaneVertexDescriptor.attributes[kVertexAttributeTexcoord].format = MTLVertexFormatFloat2; imagePlaneVertexDescriptor.attributes[kVertexAttributePosition].format = MTLVertexFormatFloat2;
imagePlaneVertexDescriptor.attributes[kVertexAttributeTexcoord].offset = 8; imagePlaneVertexDescriptor.attributes[kVertexAttributePosition].offset = 0;
imagePlaneVertexDescriptor.attributes[kVertexAttributeTexcoord].bufferIndex = kBufferIndexMeshPositions; imagePlaneVertexDescriptor.attributes[kVertexAttributePosition].bufferIndex = kBufferIndexMeshPositions;
// Position Buffer Layout // Texture coordinates.
imagePlaneVertexDescriptor.layouts[kBufferIndexMeshPositions].stride = 16; imagePlaneVertexDescriptor.attributes[kVertexAttributeTexcoord].format = MTLVertexFormatFloat2;
imagePlaneVertexDescriptor.layouts[kBufferIndexMeshPositions].stepRate = 1; imagePlaneVertexDescriptor.attributes[kVertexAttributeTexcoord].offset = 8;
imagePlaneVertexDescriptor.layouts[kBufferIndexMeshPositions].stepFunction = MTLVertexStepFunctionPerVertex; imagePlaneVertexDescriptor.attributes[kVertexAttributeTexcoord].bufferIndex = kBufferIndexMeshPositions;
MTLRenderPipelineDescriptor *pipelineDescriptor = [MTLRenderPipelineDescriptor new]; // Position Buffer Layout
pipelineDescriptor.vertexFunction = vertexFunc; imagePlaneVertexDescriptor.layouts[kBufferIndexMeshPositions].stride = 16;
pipelineDescriptor.fragmentFunction = fragmentFunc; imagePlaneVertexDescriptor.layouts[kBufferIndexMeshPositions].stepRate = 1;
pipelineDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm; imagePlaneVertexDescriptor.layouts[kBufferIndexMeshPositions].stepFunction = MTLVertexStepFunctionPerVertex;
pipelineDescriptor.vertexDescriptor = imagePlaneVertexDescriptor;
pipeline = [device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:NULL]; MTLRenderPipelineDescriptor *pipelineDescriptor = [MTLRenderPipelineDescriptor new];
MTLDepthStencilDescriptor *depthStateDescriptor = [[MTLDepthStencilDescriptor alloc] init]; pipelineDescriptor.vertexFunction = vertexFunc;
depthStateDescriptor.depthCompareFunction = MTLCompareFunctionAlways; pipelineDescriptor.fragmentFunction = fragmentFunc;
depthStateDescriptor.depthWriteEnabled = NO; pipelineDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
depthState = [device newDepthStencilStateWithDescriptor:depthStateDescriptor]; pipelineDescriptor.vertexDescriptor = imagePlaneVertexDescriptor;
self.preferredFramesPerSecond = 30;
} pipeline = [device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:NULL];
return self; MTLDepthStencilDescriptor *depthStateDescriptor = [[MTLDepthStencilDescriptor alloc] init];
depthStateDescriptor.depthCompareFunction = MTLCompareFunctionAlways;
depthStateDescriptor.depthWriteEnabled = NO;
depthState = [device newDepthStencilStateWithDescriptor:depthStateDescriptor];
self.preferredFramesPerSecond = 30;
} }
- (void)fillWithBlack { - (void)fillWithBlack {
......
...@@ -26,6 +26,10 @@ ...@@ -26,6 +26,10 @@
-(void) callShouldToggleFullScreen; -(void) callShouldToggleFullScreen;
-(void) mouseIsMoving:(BOOL) move; -(void) mouseIsMoving:(BOOL) move;
-(void) screenShare;
-(void) switchToDevice:(int)deviceID;
-(void) switchToFile:(std::string)uri;
-(std::vector<std::string>) getDeviceList;
@end @end
......
...@@ -20,19 +20,8 @@ ...@@ -20,19 +20,8 @@
#import "CallView.h" #import "CallView.h"
#import "CallLayer.h" #import "CallLayer.h"
#import <QItemSelectionModel>
#import <QAbstractProxyModel>
#import <QUrl> #import <QUrl>
#import <video/configurationproxy.h>
#import <video/sourcemodel.h>
#import <media/video.h>
#import <callmodel.h>
#import <video/previewmanager.h>
#import <video/renderer.h>
#import <video/device.h>
#import <video/devicemodel.h>
@interface CallView () @interface CallView ()
@property NSMenu *contextualMenu; @property NSMenu *contextualMenu;
...@@ -183,9 +172,11 @@ ...@@ -183,9 +172,11 @@
contextualMenu = [[NSMenu alloc] initWithTitle:@"Switch camera"]; contextualMenu = [[NSMenu alloc] initWithTitle:@"Switch camera"];
for(int i = 0 ; i < Video::DeviceModel::instance().devices().size() ; ++i) { auto devices = [self.callDelegate getDeviceList];
Video::Device* device = Video::DeviceModel::instance().devices()[i];
[contextualMenu insertItemWithTitle:device->name().toNSString() action:@selector(switchInput:) keyEquivalent:@"" atIndex:i]; for(int i = 0 ; i < devices.size() ; ++i) {
std::string device = devices[i];
[contextualMenu insertItemWithTitle:@(device.c_str()) action:@selector(switchInput:) keyEquivalent:@"" atIndex:i];
}