summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/examples/objc/AppRTCMobile/mac/APPRTCViewController.m
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/libwebrtc/examples/objc/AppRTCMobile/mac/APPRTCViewController.m
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/examples/objc/AppRTCMobile/mac/APPRTCViewController.m')
-rw-r--r--third_party/libwebrtc/examples/objc/AppRTCMobile/mac/APPRTCViewController.m407
1 files changed, 407 insertions, 0 deletions
diff --git a/third_party/libwebrtc/examples/objc/AppRTCMobile/mac/APPRTCViewController.m b/third_party/libwebrtc/examples/objc/AppRTCMobile/mac/APPRTCViewController.m
new file mode 100644
index 0000000000..982fa56b43
--- /dev/null
+++ b/third_party/libwebrtc/examples/objc/AppRTCMobile/mac/APPRTCViewController.m
@@ -0,0 +1,407 @@
+/*
+ * Copyright 2014 The WebRTC Project Authors. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#import "APPRTCViewController.h"
+
+#import <AVFoundation/AVFoundation.h>
+
+#import "sdk/objc/api/peerconnection/RTCVideoTrack.h"
+#import "sdk/objc/components/renderer/metal/RTCMTLNSVideoView.h"
+
+#import "ARDAppClient.h"
+#import "ARDCaptureController.h"
+#import "ARDSettingsModel.h"
+
+static NSUInteger const kContentWidth = 900;
+static NSUInteger const kRoomFieldWidth = 200;
+static NSUInteger const kActionItemHeight = 30;
+static NSUInteger const kBottomViewHeight = 200;
+
+@class APPRTCMainView;
+@protocol APPRTCMainViewDelegate
+
+- (void)appRTCMainView:(APPRTCMainView*)mainView
+ didEnterRoomId:(NSString*)roomId
+ loopback:(BOOL)isLoopback;
+
+@end
+
+@interface APPRTCMainView : NSView
+
+@property(nonatomic, weak) id<APPRTCMainViewDelegate> delegate;
+@property(nonatomic, readonly) NSView<RTC_OBJC_TYPE(RTCVideoRenderer)>* localVideoView;
+@property(nonatomic, readonly) NSView<RTC_OBJC_TYPE(RTCVideoRenderer)>* remoteVideoView;
+@property(nonatomic, readonly) NSTextView* logView;
+
+- (void)displayLogMessage:(NSString*)message;
+
+@end
+
+@interface APPRTCMainView () <NSTextFieldDelegate, RTC_OBJC_TYPE (RTCVideoViewDelegate)>
+@end
+@implementation APPRTCMainView {
+ NSScrollView* _scrollView;
+ NSView* _actionItemsView;
+ NSButton* _connectButton;
+ NSButton* _loopbackButton;
+ NSTextField* _roomField;
+ CGSize _localVideoSize;
+ CGSize _remoteVideoSize;
+}
+
+@synthesize delegate = _delegate;
+@synthesize localVideoView = _localVideoView;
+@synthesize remoteVideoView = _remoteVideoView;
+@synthesize logView = _logView;
+
+- (void)displayLogMessage:(NSString *)message {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ self.logView.string = [NSString stringWithFormat:@"%@%@\n", self.logView.string, message];
+ NSRange range = NSMakeRange(self.logView.string.length, 0);
+ [self.logView scrollRangeToVisible:range];
+ });
+}
+
+#pragma mark - Private
+
+- (instancetype)initWithFrame:(NSRect)frame {
+ if (self = [super initWithFrame:frame]) {
+ [self setupViews];
+ }
+ return self;
+}
+
++ (BOOL)requiresConstraintBasedLayout {
+ return YES;
+}
+
+- (void)updateConstraints {
+ NSParameterAssert(
+ _roomField != nil &&
+ _scrollView != nil &&
+ _remoteVideoView != nil &&
+ _localVideoView != nil &&
+ _actionItemsView!= nil &&
+ _connectButton != nil &&
+ _loopbackButton != nil);
+
+ [self removeConstraints:[self constraints]];
+ NSDictionary* viewsDictionary =
+ NSDictionaryOfVariableBindings(_roomField,
+ _scrollView,
+ _remoteVideoView,
+ _localVideoView,
+ _actionItemsView,
+ _connectButton,
+ _loopbackButton);
+
+ NSSize remoteViewSize = [self remoteVideoViewSize];
+ NSDictionary* metrics = @{
+ @"remoteViewWidth" : @(remoteViewSize.width),
+ @"remoteViewHeight" : @(remoteViewSize.height),
+ @"kBottomViewHeight" : @(kBottomViewHeight),
+ @"localViewHeight" : @(remoteViewSize.height / 3),
+ @"localViewWidth" : @(remoteViewSize.width / 3),
+ @"kRoomFieldWidth" : @(kRoomFieldWidth),
+ @"kActionItemHeight" : @(kActionItemHeight)
+ };
+ // Declare this separately to avoid compiler warning about splitting string
+ // within an NSArray expression.
+ NSString* verticalConstraintLeft =
+ @"V:|-[_remoteVideoView(remoteViewHeight)]-[_scrollView(kBottomViewHeight)]-|";
+ NSString* verticalConstraintRight =
+ @"V:|-[_remoteVideoView(remoteViewHeight)]-[_actionItemsView(kBottomViewHeight)]-|";
+ NSArray* constraintFormats = @[
+ verticalConstraintLeft,
+ verticalConstraintRight,
+ @"H:|-[_remoteVideoView(remoteViewWidth)]-|",
+ @"V:|-[_localVideoView(localViewHeight)]",
+ @"H:|-[_localVideoView(localViewWidth)]",
+ @"H:|-[_scrollView(==_actionItemsView)]-[_actionItemsView]-|"
+ ];
+
+ NSArray* actionItemsConstraints = @[
+ @"H:|-[_roomField(kRoomFieldWidth)]-[_loopbackButton(kRoomFieldWidth)]",
+ @"H:|-[_connectButton(kRoomFieldWidth)]",
+ @"V:|-[_roomField(kActionItemHeight)]-[_connectButton(kActionItemHeight)]",
+ @"V:|-[_loopbackButton(kActionItemHeight)]",
+ ];
+
+ [APPRTCMainView addConstraints:constraintFormats
+ toView:self
+ viewsDictionary:viewsDictionary
+ metrics:metrics];
+ [APPRTCMainView addConstraints:actionItemsConstraints
+ toView:_actionItemsView
+ viewsDictionary:viewsDictionary
+ metrics:metrics];
+ [super updateConstraints];
+}
+
+#pragma mark - Constraints helper
+
++ (void)addConstraints:(NSArray*)constraints toView:(NSView*)view
+ viewsDictionary:(NSDictionary*)viewsDictionary
+ metrics:(NSDictionary*)metrics {
+ for (NSString* constraintFormat in constraints) {
+ NSArray* constraints =
+ [NSLayoutConstraint constraintsWithVisualFormat:constraintFormat
+ options:0
+ metrics:metrics
+ views:viewsDictionary];
+ for (NSLayoutConstraint* constraint in constraints) {
+ [view addConstraint:constraint];
+ }
+ }
+}
+
+#pragma mark - Control actions
+
+- (void)startCall:(id)sender {
+ NSString* roomString = _roomField.stringValue;
+ // Generate room id for loopback options.
+ if (_loopbackButton.intValue && [roomString isEqualToString:@""]) {
+ roomString = [NSUUID UUID].UUIDString;
+ roomString = [roomString stringByReplacingOccurrencesOfString:@"-" withString:@""];
+ }
+ [self.delegate appRTCMainView:self
+ didEnterRoomId:roomString
+ loopback:_loopbackButton.intValue];
+ [self setNeedsUpdateConstraints:YES];
+}
+
+#pragma mark - RTCVideoViewDelegate
+
+- (void)videoView:(id<RTC_OBJC_TYPE(RTCVideoRenderer)>)videoView didChangeVideoSize:(CGSize)size {
+ if (videoView == _remoteVideoView) {
+ _remoteVideoSize = size;
+ } else if (videoView == _localVideoView) {
+ _localVideoSize = size;
+ } else {
+ return;
+ }
+
+ [self setNeedsUpdateConstraints:YES];
+}
+
+#pragma mark - Private
+
+- (void)setupViews {
+ NSParameterAssert([[self subviews] count] == 0);
+
+ _logView = [[NSTextView alloc] initWithFrame:NSZeroRect];
+ [_logView setMinSize:NSMakeSize(0, kBottomViewHeight)];
+ [_logView setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
+ [_logView setVerticallyResizable:YES];
+ [_logView setAutoresizingMask:NSViewWidthSizable];
+ NSTextContainer* textContainer = [_logView textContainer];
+ NSSize containerSize = NSMakeSize(kContentWidth, FLT_MAX);
+ [textContainer setContainerSize:containerSize];
+ [textContainer setWidthTracksTextView:YES];
+ [_logView setEditable:NO];
+
+ [self setupActionItemsView];
+
+ _scrollView = [[NSScrollView alloc] initWithFrame:NSZeroRect];
+ [_scrollView setTranslatesAutoresizingMaskIntoConstraints:NO];
+ [_scrollView setHasVerticalScroller:YES];
+ [_scrollView setDocumentView:_logView];
+ [self addSubview:_scrollView];
+
+ _remoteVideoView = [[RTC_OBJC_TYPE(RTCMTLNSVideoView) alloc] initWithFrame:NSZeroRect];
+ _localVideoView = [[RTC_OBJC_TYPE(RTCMTLNSVideoView) alloc] initWithFrame:NSZeroRect];
+
+ [_remoteVideoView setTranslatesAutoresizingMaskIntoConstraints:NO];
+ [self addSubview:_remoteVideoView];
+ [_localVideoView setTranslatesAutoresizingMaskIntoConstraints:NO];
+ [self addSubview:_localVideoView];
+}
+
+- (void)setupActionItemsView {
+ _actionItemsView = [[NSView alloc] initWithFrame:NSZeroRect];
+ [_actionItemsView setTranslatesAutoresizingMaskIntoConstraints:NO];
+ [self addSubview:_actionItemsView];
+
+ _roomField = [[NSTextField alloc] initWithFrame:NSZeroRect];
+ [_roomField setTranslatesAutoresizingMaskIntoConstraints:NO];
+ [[_roomField cell] setPlaceholderString: @"Enter AppRTC room id"];
+ [_actionItemsView addSubview:_roomField];
+ [_roomField setEditable:YES];
+
+ _connectButton = [[NSButton alloc] initWithFrame:NSZeroRect];
+ [_connectButton setTranslatesAutoresizingMaskIntoConstraints:NO];
+ _connectButton.title = @"Start call";
+ _connectButton.bezelStyle = NSBezelStyleSmallSquare;
+ _connectButton.target = self;
+ _connectButton.action = @selector(startCall:);
+ [_actionItemsView addSubview:_connectButton];
+
+ _loopbackButton = [[NSButton alloc] initWithFrame:NSZeroRect];
+ [_loopbackButton setTranslatesAutoresizingMaskIntoConstraints:NO];
+ _loopbackButton.title = @"Loopback";
+ [_loopbackButton setButtonType:NSButtonTypeSwitch];
+ [_actionItemsView addSubview:_loopbackButton];
+}
+
+- (NSSize)remoteVideoViewSize {
+ if (!_remoteVideoView.bounds.size.width) {
+ return NSMakeSize(kContentWidth, 0);
+ }
+ NSInteger width = MAX(_remoteVideoView.bounds.size.width, kContentWidth);
+ NSInteger height = (width/16) * 9;
+ return NSMakeSize(width, height);
+}
+
+@end
+
+@interface APPRTCViewController ()
+ <ARDAppClientDelegate, APPRTCMainViewDelegate>
+@property(nonatomic, readonly) APPRTCMainView* mainView;
+@end
+
+@implementation APPRTCViewController {
+ ARDAppClient* _client;
+ RTC_OBJC_TYPE(RTCVideoTrack) * _localVideoTrack;
+ RTC_OBJC_TYPE(RTCVideoTrack) * _remoteVideoTrack;
+ ARDCaptureController* _captureController;
+}
+
+- (void)dealloc {
+ [self disconnect];
+}
+
+- (void)viewDidAppear {
+ [super viewDidAppear];
+ [self displayUsageInstructions];
+}
+
+- (void)loadView {
+ APPRTCMainView* view = [[APPRTCMainView alloc] initWithFrame:NSZeroRect];
+ [view setTranslatesAutoresizingMaskIntoConstraints:NO];
+ view.delegate = self;
+ self.view = view;
+}
+
+- (void)windowWillClose:(NSNotification*)notification {
+ [self disconnect];
+}
+
+#pragma mark - Usage
+
+- (void)displayUsageInstructions {
+ [self.mainView displayLogMessage:
+ @"To start call:\n"
+ @"• Enter AppRTC room id (not neccessary for loopback)\n"
+ @"• Start call"];
+}
+
+#pragma mark - ARDAppClientDelegate
+
+- (void)appClient:(ARDAppClient *)client
+ didChangeState:(ARDAppClientState)state {
+ switch (state) {
+ case kARDAppClientStateConnected:
+ [self.mainView displayLogMessage:@"Client connected."];
+ break;
+ case kARDAppClientStateConnecting:
+ [self.mainView displayLogMessage:@"Client connecting."];
+ break;
+ case kARDAppClientStateDisconnected:
+ [self.mainView displayLogMessage:@"Client disconnected."];
+ [self resetUI];
+ _client = nil;
+ break;
+ }
+}
+
+- (void)appClient:(ARDAppClient *)client
+ didChangeConnectionState:(RTCIceConnectionState)state {
+}
+
+- (void)appClient:(ARDAppClient*)client
+ didCreateLocalCapturer:(RTC_OBJC_TYPE(RTCCameraVideoCapturer) *)localCapturer {
+ _captureController =
+ [[ARDCaptureController alloc] initWithCapturer:localCapturer
+ settings:[[ARDSettingsModel alloc] init]];
+ [_captureController startCapture];
+}
+
+- (void)appClient:(ARDAppClient*)client
+ didReceiveLocalVideoTrack:(RTC_OBJC_TYPE(RTCVideoTrack) *)localVideoTrack {
+ _localVideoTrack = localVideoTrack;
+ [_localVideoTrack addRenderer:self.mainView.localVideoView];
+}
+
+- (void)appClient:(ARDAppClient*)client
+ didReceiveRemoteVideoTrack:(RTC_OBJC_TYPE(RTCVideoTrack) *)remoteVideoTrack {
+ _remoteVideoTrack = remoteVideoTrack;
+ [_remoteVideoTrack addRenderer:self.mainView.remoteVideoView];
+}
+
+- (void)appClient:(ARDAppClient *)client
+ didError:(NSError *)error {
+ [self showAlertWithMessage:[NSString stringWithFormat:@"%@", error]];
+ [self disconnect];
+}
+
+- (void)appClient:(ARDAppClient *)client
+ didGetStats:(NSArray *)stats {
+}
+
+#pragma mark - APPRTCMainViewDelegate
+
+- (void)appRTCMainView:(APPRTCMainView*)mainView
+ didEnterRoomId:(NSString*)roomId
+ loopback:(BOOL)isLoopback {
+
+ if ([roomId isEqualToString:@""]) {
+ [self.mainView displayLogMessage:@"Missing room id"];
+ return;
+ }
+
+ [self disconnect];
+ ARDAppClient* client = [[ARDAppClient alloc] initWithDelegate:self];
+ [client connectToRoomWithId:roomId
+ settings:[[ARDSettingsModel alloc] init] // Use default settings.
+ isLoopback:isLoopback];
+ _client = client;
+}
+
+#pragma mark - Private
+
+- (APPRTCMainView*)mainView {
+ return (APPRTCMainView*)self.view;
+}
+
+- (void)showAlertWithMessage:(NSString*)message {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSAlert* alert = [[NSAlert alloc] init];
+ [alert setMessageText:message];
+ [alert runModal];
+ });
+}
+
+- (void)resetUI {
+ [_remoteVideoTrack removeRenderer:self.mainView.remoteVideoView];
+ [_localVideoTrack removeRenderer:self.mainView.localVideoView];
+ _remoteVideoTrack = nil;
+ _localVideoTrack = nil;
+ [self.mainView.remoteVideoView renderFrame:nil];
+ [self.mainView.localVideoView renderFrame:nil];
+}
+
+- (void)disconnect {
+ [self resetUI];
+ [_captureController stopCapture];
+ _captureController = nil;
+ [_client disconnect];
+}
+
+@end