Move all the examples from the talk directory into the webrtc examples directory.
Significant changes: - move the libjingle_examples.gyp file into webrtc directory. - rename talk/examples/android to webrtc/examples/androidapp to avoid name conflicts. - update paths in talk/libjingle_tests.gyp to point to webrtc directory for Objective-C test. BUG= R=pthatcher@webrtc.org, tkchin@webrtc.org Review URL: https://codereview.webrtc.org/1235563006 . Cr-Commit-Position: refs/heads/master@{#9681}
17
webrtc/examples/objc/AppRTCDemo/ios/ARDAppDelegate.h
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2013 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 <UIKit/UIKit.h>
|
||||
|
||||
// The main application class of the AppRTCDemo iOS app demonstrating
|
||||
// interoperability between the Objective C implementation of PeerConnection
|
||||
// and the apprtc.appspot.com demo webapp.
|
||||
@interface ARDAppDelegate : NSObject <UIApplicationDelegate>
|
||||
@end
|
||||
52
webrtc/examples/objc/AppRTCDemo/ios/ARDAppDelegate.m
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2013 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 "ARDAppDelegate.h"
|
||||
|
||||
#import "RTCLogging.h"
|
||||
#import "RTCPeerConnectionFactory.h"
|
||||
|
||||
#import "ARDMainViewController.h"
|
||||
|
||||
@implementation ARDAppDelegate {
|
||||
UIWindow *_window;
|
||||
}
|
||||
|
||||
#pragma mark - UIApplicationDelegate methods
|
||||
|
||||
- (BOOL)application:(UIApplication *)application
|
||||
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
[RTCPeerConnectionFactory initializeSSL];
|
||||
_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||
[_window makeKeyAndVisible];
|
||||
ARDMainViewController *viewController = [[ARDMainViewController alloc] init];
|
||||
_window.rootViewController = viewController;
|
||||
|
||||
#ifndef _DEBUG
|
||||
// In debug builds the default level is LS_INFO and in non-debug builds it is
|
||||
// disabled. Continue to log to console in non-debug builds, but only
|
||||
// warnings and errors.
|
||||
RTCSetMinDebugLogLevel(kRTCLoggingSeverityWarning);
|
||||
#endif
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)applicationWillResignActive:(UIApplication *)application {
|
||||
ARDMainViewController *viewController =
|
||||
(ARDMainViewController *)_window.rootViewController;
|
||||
[viewController applicationWillResignActive:application];
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(UIApplication *)application {
|
||||
[RTCPeerConnectionFactory deinitializeSSL];
|
||||
}
|
||||
|
||||
@end
|
||||
27
webrtc/examples/objc/AppRTCDemo/ios/ARDMainView.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2015 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 <UIKit/UIKit.h>
|
||||
|
||||
@class ARDMainView;
|
||||
|
||||
@protocol ARDMainViewDelegate <NSObject>
|
||||
|
||||
- (void)mainView:(ARDMainView *)mainView didInputRoom:(NSString *)room;
|
||||
|
||||
@end
|
||||
|
||||
// The main view of AppRTCDemo. It contains an input field for entering a room
|
||||
// name on apprtc to connect to.
|
||||
@interface ARDMainView : UIView
|
||||
|
||||
@property(nonatomic, weak) id<ARDMainViewDelegate> delegate;
|
||||
|
||||
@end
|
||||
168
webrtc/examples/objc/AppRTCDemo/ios/ARDMainView.m
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright 2015 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 "ARDMainView.h"
|
||||
|
||||
#import "UIImage+ARDUtilities.h"
|
||||
|
||||
// TODO(tkchin): retrieve status bar height dynamically.
|
||||
static CGFloat const kStatusBarHeight = 20;
|
||||
|
||||
static CGFloat const kRoomTextButtonSize = 40;
|
||||
static CGFloat const kRoomTextFieldHeight = 40;
|
||||
static CGFloat const kRoomTextFieldMargin = 8;
|
||||
static CGFloat const kAppLabelHeight = 20;
|
||||
|
||||
@class ARDRoomTextField;
|
||||
@protocol ARDRoomTextFieldDelegate <NSObject>
|
||||
- (void)roomTextField:(ARDRoomTextField *)roomTextField
|
||||
didInputRoom:(NSString *)room;
|
||||
@end
|
||||
|
||||
// Helper view that contains a text field and a clear button.
|
||||
@interface ARDRoomTextField : UIView <UITextFieldDelegate>
|
||||
@property(nonatomic, weak) id<ARDRoomTextFieldDelegate> delegate;
|
||||
@end
|
||||
|
||||
@implementation ARDRoomTextField {
|
||||
UITextField *_roomText;
|
||||
UIButton *_clearButton;
|
||||
}
|
||||
|
||||
@synthesize delegate = _delegate;
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
_roomText = [[UITextField alloc] initWithFrame:CGRectZero];
|
||||
_roomText.borderStyle = UITextBorderStyleNone;
|
||||
_roomText.font = [UIFont fontWithName:@"Roboto" size:12];
|
||||
_roomText.placeholder = @"Room name";
|
||||
_roomText.delegate = self;
|
||||
[_roomText addTarget:self
|
||||
action:@selector(textFieldDidChange:)
|
||||
forControlEvents:UIControlEventEditingChanged];
|
||||
[self addSubview:_roomText];
|
||||
|
||||
_clearButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
UIImage *image = [UIImage imageForName:@"ic_clear_black_24dp.png"
|
||||
color:[UIColor colorWithWhite:0 alpha:.4]];
|
||||
|
||||
[_clearButton setImage:image forState:UIControlStateNormal];
|
||||
[_clearButton addTarget:self
|
||||
action:@selector(onClear:)
|
||||
forControlEvents:UIControlEventTouchUpInside];
|
||||
_clearButton.hidden = YES;
|
||||
[self addSubview:_clearButton];
|
||||
|
||||
// Give rounded corners and a light gray border.
|
||||
self.layer.borderWidth = 1;
|
||||
self.layer.borderColor = [[UIColor lightGrayColor] CGColor];
|
||||
self.layer.cornerRadius = 2;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews {
|
||||
CGRect bounds = self.bounds;
|
||||
_clearButton.frame = CGRectMake(CGRectGetMaxX(bounds) - kRoomTextButtonSize,
|
||||
CGRectGetMinY(bounds),
|
||||
kRoomTextButtonSize,
|
||||
kRoomTextButtonSize);
|
||||
_roomText.frame = CGRectMake(
|
||||
CGRectGetMinX(bounds) + kRoomTextFieldMargin,
|
||||
CGRectGetMinY(bounds),
|
||||
CGRectGetMinX(_clearButton.frame) - CGRectGetMinX(bounds) -
|
||||
kRoomTextFieldMargin,
|
||||
kRoomTextFieldHeight);
|
||||
}
|
||||
|
||||
- (CGSize)sizeThatFits:(CGSize)size {
|
||||
size.height = kRoomTextFieldHeight;
|
||||
return size;
|
||||
}
|
||||
|
||||
#pragma mark - UITextFieldDelegate
|
||||
|
||||
- (void)textFieldDidEndEditing:(UITextField *)textField {
|
||||
[_delegate roomTextField:self didInputRoom:textField.text];
|
||||
}
|
||||
|
||||
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
|
||||
// There is no other control that can take focus, so manually resign focus
|
||||
// when return (Join) is pressed to trigger |textFieldDidEndEditing|.
|
||||
[textField resignFirstResponder];
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)textFieldDidChange:(id)sender {
|
||||
[self updateClearButton];
|
||||
}
|
||||
|
||||
- (void)onClear:(id)sender {
|
||||
_roomText.text = @"";
|
||||
[self updateClearButton];
|
||||
[_roomText resignFirstResponder];
|
||||
}
|
||||
|
||||
- (void)updateClearButton {
|
||||
_clearButton.hidden = _roomText.text.length == 0;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface ARDMainView () <ARDRoomTextFieldDelegate>
|
||||
@end
|
||||
|
||||
@implementation ARDMainView {
|
||||
UILabel *_appLabel;
|
||||
ARDRoomTextField *_roomText;
|
||||
}
|
||||
|
||||
@synthesize delegate = _delegate;
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
_appLabel = [[UILabel alloc] initWithFrame:CGRectZero];
|
||||
_appLabel.text = @"AppRTCDemo";
|
||||
_appLabel.font = [UIFont fontWithName:@"Roboto" size:34];
|
||||
_appLabel.textColor = [UIColor colorWithWhite:0 alpha:.2];
|
||||
[_appLabel sizeToFit];
|
||||
[self addSubview:_appLabel];
|
||||
|
||||
_roomText = [[ARDRoomTextField alloc] initWithFrame:CGRectZero];
|
||||
_roomText.delegate = self;
|
||||
[self addSubview:_roomText];
|
||||
|
||||
self.backgroundColor = [UIColor whiteColor];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews {
|
||||
CGRect bounds = self.bounds;
|
||||
CGFloat roomTextWidth = bounds.size.width - 2 * kRoomTextFieldMargin;
|
||||
CGFloat roomTextHeight = [_roomText sizeThatFits:bounds.size].height;
|
||||
_roomText.frame = CGRectMake(kRoomTextFieldMargin,
|
||||
kStatusBarHeight + kRoomTextFieldMargin,
|
||||
roomTextWidth,
|
||||
roomTextHeight);
|
||||
_appLabel.center = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
|
||||
}
|
||||
|
||||
#pragma mark - ARDRoomTextFieldDelegate
|
||||
|
||||
- (void)roomTextField:(ARDRoomTextField *)roomTextField
|
||||
didInputRoom:(NSString *)room {
|
||||
[_delegate mainView:self didInputRoom:room];
|
||||
}
|
||||
|
||||
@end
|
||||
17
webrtc/examples/objc/AppRTCDemo/ios/ARDMainViewController.h
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2015 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 <UIKit/UIKit.h>
|
||||
|
||||
@interface ARDMainViewController : UIViewController
|
||||
|
||||
- (void)applicationWillResignActive:(UIApplication *)application;
|
||||
|
||||
@end
|
||||
85
webrtc/examples/objc/AppRTCDemo/ios/ARDMainViewController.m
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2015 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 "ARDMainViewController.h"
|
||||
|
||||
#import "ARDAppClient.h"
|
||||
#import "ARDMainView.h"
|
||||
#import "ARDVideoCallViewController.h"
|
||||
|
||||
@interface ARDMainViewController () <ARDMainViewDelegate>
|
||||
@end
|
||||
|
||||
@implementation ARDMainViewController
|
||||
|
||||
- (void)loadView {
|
||||
ARDMainView *mainView = [[ARDMainView alloc] initWithFrame:CGRectZero];
|
||||
mainView.delegate = self;
|
||||
self.view = mainView;
|
||||
}
|
||||
|
||||
- (void)applicationWillResignActive:(UIApplication *)application {
|
||||
// Terminate any calls when we aren't active.
|
||||
[self dismissViewControllerAnimated:NO completion:nil];
|
||||
}
|
||||
|
||||
#pragma mark - ARDMainViewDelegate
|
||||
|
||||
- (void)mainView:(ARDMainView *)mainView didInputRoom:(NSString *)room {
|
||||
if (!room.length) {
|
||||
return;
|
||||
}
|
||||
// Trim whitespaces.
|
||||
NSCharacterSet *whitespaceSet = [NSCharacterSet whitespaceCharacterSet];
|
||||
NSString *trimmedRoom = [room stringByTrimmingCharactersInSet:whitespaceSet];
|
||||
|
||||
// Check that room name is valid.
|
||||
NSError *error = nil;
|
||||
NSRegularExpressionOptions options = NSRegularExpressionCaseInsensitive;
|
||||
NSRegularExpression *regex =
|
||||
[NSRegularExpression regularExpressionWithPattern:@"\\w+"
|
||||
options:options
|
||||
error:&error];
|
||||
if (error) {
|
||||
[self showAlertWithMessage:error.localizedDescription];
|
||||
return;
|
||||
}
|
||||
NSRange matchRange =
|
||||
[regex rangeOfFirstMatchInString:trimmedRoom
|
||||
options:0
|
||||
range:NSMakeRange(0, trimmedRoom.length)];
|
||||
if (matchRange.location == NSNotFound ||
|
||||
matchRange.length != trimmedRoom.length) {
|
||||
[self showAlertWithMessage:@"Invalid room name."];
|
||||
return;
|
||||
}
|
||||
|
||||
// Kick off the video call.
|
||||
ARDVideoCallViewController *videoCallViewController =
|
||||
[[ARDVideoCallViewController alloc] initForRoom:trimmedRoom];
|
||||
videoCallViewController.modalTransitionStyle =
|
||||
UIModalTransitionStyleCrossDissolve;
|
||||
[self presentViewController:videoCallViewController
|
||||
animated:YES
|
||||
completion:nil];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)showAlertWithMessage:(NSString*)message {
|
||||
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:nil
|
||||
message:message
|
||||
delegate:nil
|
||||
cancelButtonTitle:@"OK"
|
||||
otherButtonTitles:nil];
|
||||
[alertView show];
|
||||
}
|
||||
|
||||
@end
|
||||
35
webrtc/examples/objc/AppRTCDemo/ios/ARDVideoCallView.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2015 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 <UIKit/UIKit.h>
|
||||
|
||||
#import "RTCEAGLVideoView.h"
|
||||
|
||||
@class ARDVideoCallView;
|
||||
@protocol ARDVideoCallViewDelegate <NSObject>
|
||||
|
||||
// Called when the camera switch button is pressed.
|
||||
- (void)videoCallViewDidSwitchCamera:(ARDVideoCallView *)view;
|
||||
|
||||
// Called when the hangup button is pressed.
|
||||
- (void)videoCallViewDidHangup:(ARDVideoCallView *)view;
|
||||
|
||||
@end
|
||||
|
||||
// Video call view that shows local and remote video, provides a label to
|
||||
// display status, and also a hangup button.
|
||||
@interface ARDVideoCallView : UIView
|
||||
|
||||
@property(nonatomic, readonly) UILabel *statusLabel;
|
||||
@property(nonatomic, readonly) RTCEAGLVideoView *localVideoView;
|
||||
@property(nonatomic, readonly) RTCEAGLVideoView *remoteVideoView;
|
||||
@property(nonatomic, weak) id<ARDVideoCallViewDelegate> delegate;
|
||||
|
||||
@end
|
||||
162
webrtc/examples/objc/AppRTCDemo/ios/ARDVideoCallView.m
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright 2015 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 "ARDVideoCallView.h"
|
||||
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import "UIImage+ARDUtilities.h"
|
||||
|
||||
static CGFloat const kButtonPadding = 16;
|
||||
static CGFloat const kButtonSize = 48;
|
||||
static CGFloat const kLocalVideoViewSize = 120;
|
||||
static CGFloat const kLocalVideoViewPadding = 8;
|
||||
|
||||
@interface ARDVideoCallView () <RTCEAGLVideoViewDelegate>
|
||||
@end
|
||||
|
||||
@implementation ARDVideoCallView {
|
||||
UIButton *_cameraSwitchButton;
|
||||
UIButton *_hangupButton;
|
||||
CGSize _localVideoSize;
|
||||
CGSize _remoteVideoSize;
|
||||
BOOL _useRearCamera;
|
||||
}
|
||||
|
||||
@synthesize statusLabel = _statusLabel;
|
||||
@synthesize localVideoView = _localVideoView;
|
||||
@synthesize remoteVideoView = _remoteVideoView;
|
||||
@synthesize delegate = _delegate;
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
_remoteVideoView = [[RTCEAGLVideoView alloc] initWithFrame:CGRectZero];
|
||||
_remoteVideoView.delegate = self;
|
||||
[self addSubview:_remoteVideoView];
|
||||
|
||||
// TODO(tkchin): replace this with a view that renders layer from
|
||||
// AVCaptureSession.
|
||||
_localVideoView = [[RTCEAGLVideoView alloc] initWithFrame:CGRectZero];
|
||||
_localVideoView.delegate = self;
|
||||
[self addSubview:_localVideoView];
|
||||
|
||||
// TODO(tkchin): don't display this if we can't actually do camera switch.
|
||||
_cameraSwitchButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
_cameraSwitchButton.backgroundColor = [UIColor whiteColor];
|
||||
_cameraSwitchButton.layer.cornerRadius = kButtonSize / 2;
|
||||
_cameraSwitchButton.layer.masksToBounds = YES;
|
||||
UIImage *image = [UIImage imageNamed:@"ic_switch_video_black_24dp.png"];
|
||||
[_cameraSwitchButton setImage:image forState:UIControlStateNormal];
|
||||
[_cameraSwitchButton addTarget:self
|
||||
action:@selector(onCameraSwitch:)
|
||||
forControlEvents:UIControlEventTouchUpInside];
|
||||
[self addSubview:_cameraSwitchButton];
|
||||
|
||||
_hangupButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
_hangupButton.backgroundColor = [UIColor redColor];
|
||||
_hangupButton.layer.cornerRadius = kButtonSize / 2;
|
||||
_hangupButton.layer.masksToBounds = YES;
|
||||
image = [UIImage imageForName:@"ic_call_end_black_24dp.png"
|
||||
color:[UIColor whiteColor]];
|
||||
[_hangupButton setImage:image forState:UIControlStateNormal];
|
||||
[_hangupButton addTarget:self
|
||||
action:@selector(onHangup:)
|
||||
forControlEvents:UIControlEventTouchUpInside];
|
||||
[self addSubview:_hangupButton];
|
||||
|
||||
_statusLabel = [[UILabel alloc] initWithFrame:CGRectZero];
|
||||
_statusLabel.font = [UIFont fontWithName:@"Roboto" size:16];
|
||||
_statusLabel.textColor = [UIColor whiteColor];
|
||||
[self addSubview:_statusLabel];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews {
|
||||
CGRect bounds = self.bounds;
|
||||
if (_remoteVideoSize.width > 0 && _remoteVideoSize.height > 0) {
|
||||
// Aspect fill remote video into bounds.
|
||||
CGRect remoteVideoFrame =
|
||||
AVMakeRectWithAspectRatioInsideRect(_remoteVideoSize, bounds);
|
||||
CGFloat scale = 1;
|
||||
if (remoteVideoFrame.size.width > remoteVideoFrame.size.height) {
|
||||
// Scale by height.
|
||||
scale = bounds.size.height / remoteVideoFrame.size.height;
|
||||
} else {
|
||||
// Scale by width.
|
||||
scale = bounds.size.width / remoteVideoFrame.size.width;
|
||||
}
|
||||
remoteVideoFrame.size.height *= scale;
|
||||
remoteVideoFrame.size.width *= scale;
|
||||
_remoteVideoView.frame = remoteVideoFrame;
|
||||
_remoteVideoView.center =
|
||||
CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
|
||||
} else {
|
||||
_remoteVideoView.frame = bounds;
|
||||
}
|
||||
|
||||
if (_localVideoSize.width && _localVideoSize.height > 0) {
|
||||
// Aspect fit local video view into a square box.
|
||||
CGRect localVideoFrame =
|
||||
CGRectMake(0, 0, kLocalVideoViewSize, kLocalVideoViewSize);
|
||||
localVideoFrame =
|
||||
AVMakeRectWithAspectRatioInsideRect(_localVideoSize, localVideoFrame);
|
||||
|
||||
// Place the view in the bottom right.
|
||||
localVideoFrame.origin.x = CGRectGetMaxX(bounds)
|
||||
- localVideoFrame.size.width - kLocalVideoViewPadding;
|
||||
localVideoFrame.origin.y = CGRectGetMaxY(bounds)
|
||||
- localVideoFrame.size.height - kLocalVideoViewPadding;
|
||||
_localVideoView.frame = localVideoFrame;
|
||||
} else {
|
||||
_localVideoView.frame = bounds;
|
||||
}
|
||||
|
||||
// Place hangup button in the bottom left.
|
||||
_hangupButton.frame =
|
||||
CGRectMake(CGRectGetMinX(bounds) + kButtonPadding,
|
||||
CGRectGetMaxY(bounds) - kButtonPadding -
|
||||
kButtonSize,
|
||||
kButtonSize,
|
||||
kButtonSize);
|
||||
|
||||
// Place button to the right of hangup button.
|
||||
CGRect cameraSwitchFrame = _hangupButton.frame;
|
||||
cameraSwitchFrame.origin.x =
|
||||
CGRectGetMaxX(cameraSwitchFrame) + kButtonPadding;
|
||||
_cameraSwitchButton.frame = cameraSwitchFrame;
|
||||
|
||||
[_statusLabel sizeToFit];
|
||||
_statusLabel.center =
|
||||
CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
|
||||
}
|
||||
|
||||
#pragma mark - RTCEAGLVideoViewDelegate
|
||||
|
||||
- (void)videoView:(RTCEAGLVideoView*)videoView didChangeVideoSize:(CGSize)size {
|
||||
if (videoView == _localVideoView) {
|
||||
_localVideoSize = size;
|
||||
_localVideoView.hidden = CGSizeEqualToSize(CGSizeZero, _localVideoSize);
|
||||
} else if (videoView == _remoteVideoView) {
|
||||
_remoteVideoSize = size;
|
||||
}
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)onCameraSwitch:(id)sender {
|
||||
[_delegate videoCallViewDidSwitchCamera:self];
|
||||
}
|
||||
|
||||
- (void)onHangup:(id)sender {
|
||||
[_delegate videoCallViewDidHangup:self];
|
||||
}
|
||||
|
||||
@end
|
||||
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2015 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 <UIKit/UIKit.h>
|
||||
|
||||
@interface ARDVideoCallViewController : UIViewController
|
||||
|
||||
- (instancetype)initForRoom:(NSString *)room;
|
||||
|
||||
@end
|
||||
177
webrtc/examples/objc/AppRTCDemo/ios/ARDVideoCallViewController.m
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright 2015 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 "ARDVideoCallViewController.h"
|
||||
|
||||
#import "RTCAVFoundationVideoSource.h"
|
||||
#import "RTCLogging.h"
|
||||
|
||||
#import "ARDAppClient.h"
|
||||
#import "ARDVideoCallView.h"
|
||||
|
||||
@interface ARDVideoCallViewController () <ARDAppClientDelegate,
|
||||
ARDVideoCallViewDelegate>
|
||||
@property(nonatomic, strong) RTCVideoTrack *localVideoTrack;
|
||||
@property(nonatomic, strong) RTCVideoTrack *remoteVideoTrack;
|
||||
@property(nonatomic, readonly) ARDVideoCallView *videoCallView;
|
||||
@end
|
||||
|
||||
@implementation ARDVideoCallViewController {
|
||||
ARDAppClient *_client;
|
||||
RTCVideoTrack *_remoteVideoTrack;
|
||||
RTCVideoTrack *_localVideoTrack;
|
||||
}
|
||||
|
||||
@synthesize videoCallView = _videoCallView;
|
||||
|
||||
- (instancetype)initForRoom:(NSString *)room {
|
||||
if (self = [super init]) {
|
||||
_client = [[ARDAppClient alloc] initWithDelegate:self];
|
||||
[_client connectToRoomWithId:room options:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)loadView {
|
||||
_videoCallView = [[ARDVideoCallView alloc] initWithFrame:CGRectZero];
|
||||
_videoCallView.delegate = self;
|
||||
_videoCallView.statusLabel.text =
|
||||
[self statusTextForState:RTCICEConnectionNew];
|
||||
self.view = _videoCallView;
|
||||
}
|
||||
|
||||
#pragma mark - ARDAppClientDelegate
|
||||
|
||||
- (void)appClient:(ARDAppClient *)client
|
||||
didChangeState:(ARDAppClientState)state {
|
||||
switch (state) {
|
||||
case kARDAppClientStateConnected:
|
||||
RTCLog(@"Client connected.");
|
||||
break;
|
||||
case kARDAppClientStateConnecting:
|
||||
RTCLog(@"Client connecting.");
|
||||
break;
|
||||
case kARDAppClientStateDisconnected:
|
||||
RTCLog(@"Client disconnected.");
|
||||
[self hangup];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)appClient:(ARDAppClient *)client
|
||||
didChangeConnectionState:(RTCICEConnectionState)state {
|
||||
RTCLog(@"ICE state changed: %d", state);
|
||||
__weak ARDVideoCallViewController *weakSelf = self;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
ARDVideoCallViewController *strongSelf = weakSelf;
|
||||
strongSelf.videoCallView.statusLabel.text =
|
||||
[strongSelf statusTextForState:state];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)appClient:(ARDAppClient *)client
|
||||
didReceiveLocalVideoTrack:(RTCVideoTrack *)localVideoTrack {
|
||||
self.localVideoTrack = localVideoTrack;
|
||||
}
|
||||
|
||||
- (void)appClient:(ARDAppClient *)client
|
||||
didReceiveRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack {
|
||||
self.remoteVideoTrack = remoteVideoTrack;
|
||||
_videoCallView.statusLabel.hidden = YES;
|
||||
}
|
||||
|
||||
- (void)appClient:(ARDAppClient *)client
|
||||
didError:(NSError *)error {
|
||||
NSString *message =
|
||||
[NSString stringWithFormat:@"%@", error.localizedDescription];
|
||||
[self showAlertWithMessage:message];
|
||||
[self hangup];
|
||||
}
|
||||
|
||||
#pragma mark - ARDVideoCallViewDelegate
|
||||
|
||||
- (void)videoCallViewDidHangup:(ARDVideoCallView *)view {
|
||||
[self hangup];
|
||||
}
|
||||
|
||||
- (void)videoCallViewDidSwitchCamera:(ARDVideoCallView *)view {
|
||||
// TODO(tkchin): Rate limit this so you can't tap continously on it.
|
||||
// Probably through an animation.
|
||||
[self switchCamera];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)setLocalVideoTrack:(RTCVideoTrack *)localVideoTrack {
|
||||
if (_localVideoTrack == localVideoTrack) {
|
||||
return;
|
||||
}
|
||||
[_localVideoTrack removeRenderer:_videoCallView.localVideoView];
|
||||
_localVideoTrack = nil;
|
||||
[_videoCallView.localVideoView renderFrame:nil];
|
||||
_localVideoTrack = localVideoTrack;
|
||||
[_localVideoTrack addRenderer:_videoCallView.localVideoView];
|
||||
}
|
||||
|
||||
- (void)setRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack {
|
||||
if (_remoteVideoTrack == remoteVideoTrack) {
|
||||
return;
|
||||
}
|
||||
[_remoteVideoTrack removeRenderer:_videoCallView.localVideoView];
|
||||
_remoteVideoTrack = nil;
|
||||
[_videoCallView.remoteVideoView renderFrame:nil];
|
||||
_remoteVideoTrack = remoteVideoTrack;
|
||||
[_remoteVideoTrack addRenderer:_videoCallView.remoteVideoView];
|
||||
}
|
||||
|
||||
- (void)hangup {
|
||||
self.remoteVideoTrack = nil;
|
||||
self.localVideoTrack = nil;
|
||||
[_client disconnect];
|
||||
if (![self isBeingDismissed]) {
|
||||
[self.presentingViewController dismissViewControllerAnimated:YES
|
||||
completion:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)switchCamera {
|
||||
RTCVideoSource* source = self.localVideoTrack.source;
|
||||
if ([source isKindOfClass:[RTCAVFoundationVideoSource class]]) {
|
||||
RTCAVFoundationVideoSource* avSource = (RTCAVFoundationVideoSource*)source;
|
||||
avSource.useBackCamera = !avSource.useBackCamera;
|
||||
_videoCallView.localVideoView.transform = avSource.useBackCamera ?
|
||||
CGAffineTransformIdentity : CGAffineTransformMakeScale(-1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)statusTextForState:(RTCICEConnectionState)state {
|
||||
switch (state) {
|
||||
case RTCICEConnectionNew:
|
||||
case RTCICEConnectionChecking:
|
||||
return @"Connecting...";
|
||||
case RTCICEConnectionConnected:
|
||||
case RTCICEConnectionCompleted:
|
||||
case RTCICEConnectionFailed:
|
||||
case RTCICEConnectionDisconnected:
|
||||
case RTCICEConnectionClosed:
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)showAlertWithMessage:(NSString*)message {
|
||||
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:nil
|
||||
message:message
|
||||
delegate:nil
|
||||
cancelButtonTitle:@"OK"
|
||||
otherButtonTitles:nil];
|
||||
[alertView show];
|
||||
}
|
||||
|
||||
@end
|
||||
23
webrtc/examples/objc/AppRTCDemo/ios/AppRTCDemo-Prefix.pch
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2013 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// Prefix header for all source files of the 'AppRTCDemo' target in the
|
||||
// 'AppRTCDemo' project
|
||||
//
|
||||
|
||||
#import <Availability.h>
|
||||
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0
|
||||
#warning "This project uses features only available in iOS SDK 6.0 and later."
|
||||
#endif
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
97
webrtc/examples/objc/AppRTCDemo/ios/Info.plist
Normal file
@ -0,0 +1,97 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BuildMachineOSBuild</key>
|
||||
<string>12E55</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>AppRTCDemo</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>AppRTCDemo</string>
|
||||
<key>CFBundleIcons</key>
|
||||
<dict>
|
||||
<key>CFBundlePrimaryIcon</key>
|
||||
<dict>
|
||||
<key>CFBundleIconFiles</key>
|
||||
<array>
|
||||
<string>Icon.png</string>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.google.AppRTCDemo</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>AppRTCDemo</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>iPhoneOS</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>UIStatusBarTintParameters</key>
|
||||
<dict>
|
||||
<key>UINavigationBar</key>
|
||||
<dict>
|
||||
<key>Style</key>
|
||||
<string>UIBarStyleDefault</string>
|
||||
<key>Translucent</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
</array>
|
||||
<key>UIAppFonts</key>
|
||||
<array>
|
||||
<string>Roboto-Regular.ttf</string>
|
||||
</array>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>voip</string>
|
||||
</array>
|
||||
<key>UILaunchImages</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UILaunchImageMinimumOSVersion</key>
|
||||
<string>7.0</string>
|
||||
<key>UILaunchImageName</key>
|
||||
<string>iPhone5</string>
|
||||
<key>UILaunchImageOrientation</key>
|
||||
<string>Portrait</string>
|
||||
<key>UILaunchImageSize</key>
|
||||
<string>{320, 568}</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>UILaunchImageMinimumOSVersion</key>
|
||||
<string>8.0</string>
|
||||
<key>UILaunchImageName</key>
|
||||
<string>iPhone6</string>
|
||||
<key>UILaunchImageOrientation</key>
|
||||
<string>Portrait</string>
|
||||
<key>UILaunchImageSize</key>
|
||||
<string>{375, 667}</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>UILaunchImageMinimumOSVersion</key>
|
||||
<string>8.0</string>
|
||||
<key>UILaunchImageName</key>
|
||||
<string>iPhone6p</string>
|
||||
<key>UILaunchImageOrientation</key>
|
||||
<string>Portrait</string>
|
||||
<key>UILaunchImageSize</key>
|
||||
<string>{414, 736}</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
18
webrtc/examples/objc/AppRTCDemo/ios/UIImage+ARDUtilities.h
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2015 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 <UIKit/UIKit.h>
|
||||
|
||||
@interface UIImage (ARDUtilities)
|
||||
|
||||
// Returns an color tinted version for the given image resource.
|
||||
+ (UIImage *)imageForName:(NSString *)name color:(UIColor *)color;
|
||||
|
||||
@end
|
||||
31
webrtc/examples/objc/AppRTCDemo/ios/UIImage+ARDUtilities.m
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2015 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 "UIImage+ARDUtilities.h"
|
||||
|
||||
@implementation UIImage (ARDUtilities)
|
||||
|
||||
+ (UIImage *)imageForName:(NSString *)name color:(UIColor *)color {
|
||||
UIImage *image = [UIImage imageNamed:name];
|
||||
if (!image) {
|
||||
return nil;
|
||||
}
|
||||
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0.0f);
|
||||
[color setFill];
|
||||
CGRect bounds = CGRectMake(0, 0, image.size.width, image.size.height);
|
||||
UIRectFill(bounds);
|
||||
[image drawInRect:bounds blendMode:kCGBlendModeDestinationIn alpha:1.0f];
|
||||
UIImage *coloredImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
return coloredImage;
|
||||
}
|
||||
|
||||
@end
|
||||
20
webrtc/examples/objc/AppRTCDemo/ios/main.m
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2013 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 <UIKit/UIKit.h>
|
||||
|
||||
#import "ARDAppDelegate.h"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(
|
||||
argc, argv, nil, NSStringFromClass([ARDAppDelegate class]));
|
||||
}
|
||||
}
|
||||
BIN
webrtc/examples/objc/AppRTCDemo/ios/resources/Roboto-Regular.ttf
Normal file
BIN
webrtc/examples/objc/AppRTCDemo/ios/resources/iPhone5@2x.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
webrtc/examples/objc/AppRTCDemo/ios/resources/iPhone6@2x.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
webrtc/examples/objc/AppRTCDemo/ios/resources/iPhone6p@3x.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
webrtc/examples/objc/AppRTCDemo/ios/resources/ic_call_end_black_24dp.png
Executable file
|
After Width: | Height: | Size: 316 B |
BIN
webrtc/examples/objc/AppRTCDemo/ios/resources/ic_call_end_black_24dp@2x.png
Executable file
|
After Width: | Height: | Size: 479 B |
BIN
webrtc/examples/objc/AppRTCDemo/ios/resources/ic_clear_black_24dp.png
Executable file
|
After Width: | Height: | Size: 257 B |
BIN
webrtc/examples/objc/AppRTCDemo/ios/resources/ic_clear_black_24dp@2x.png
Executable file
|
After Width: | Height: | Size: 360 B |
|
After Width: | Height: | Size: 242 B |
|
After Width: | Height: | Size: 311 B |