Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / examples / objc / AppRTCDemo / ios / APPRTCViewController.m
1 /*
2  * libjingle
3  * Copyright 2013, Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #if !defined(__has_feature) || !__has_feature(objc_arc)
29 #error "This file requires ARC support."
30 #endif
31
32 #import "APPRTCViewController.h"
33
34 #import <AVFoundation/AVFoundation.h>
35 #import "APPRTCConnectionManager.h"
36 #import "RTCEAGLVideoView.h"
37
38 // Padding space for local video view with its parent.
39 static CGFloat const kLocalViewPadding = 20;
40
41 @interface APPRTCViewController ()
42 <APPRTCConnectionManagerDelegate, APPRTCLogger, RTCEAGLVideoViewDelegate>
43 @property(nonatomic, assign) UIInterfaceOrientation statusBarOrientation;
44 @property(nonatomic, strong) RTCEAGLVideoView* localVideoView;
45 @property(nonatomic, strong) RTCEAGLVideoView* remoteVideoView;
46 @end
47
48 @implementation APPRTCViewController {
49   APPRTCConnectionManager* _connectionManager;
50   CGSize _localVideoSize;
51   CGSize _remoteVideoSize;
52 }
53
54 - (instancetype)initWithNibName:(NSString*)nibName
55                          bundle:(NSBundle*)bundle {
56   if (self = [super initWithNibName:nibName bundle:bundle]) {
57     _connectionManager =
58         [[APPRTCConnectionManager alloc] initWithDelegate:self
59                                                    logger:self];
60   }
61   return self;
62 }
63
64 - (void)viewDidLoad {
65   [super viewDidLoad];
66
67   self.remoteVideoView =
68       [[RTCEAGLVideoView alloc] initWithFrame:self.blackView.bounds];
69   self.remoteVideoView.delegate = self;
70   self.remoteVideoView.transform = CGAffineTransformMakeScale(-1, 1);
71   [self.blackView addSubview:self.remoteVideoView];
72
73   self.localVideoView =
74       [[RTCEAGLVideoView alloc] initWithFrame:self.blackView.bounds];
75   self.localVideoView.delegate = self;
76   [self.blackView addSubview:self.localVideoView];
77
78   self.statusBarOrientation =
79       [UIApplication sharedApplication].statusBarOrientation;
80   self.roomInput.delegate = self;
81   [self.roomInput becomeFirstResponder];
82 }
83
84 - (void)viewDidLayoutSubviews {
85   if (self.statusBarOrientation !=
86       [UIApplication sharedApplication].statusBarOrientation) {
87     self.statusBarOrientation =
88         [UIApplication sharedApplication].statusBarOrientation;
89     [[NSNotificationCenter defaultCenter]
90         postNotificationName:@"StatusBarOrientationDidChange"
91                       object:nil];
92   }
93 }
94
95 - (void)applicationWillResignActive:(UIApplication*)application {
96   [self logMessage:@"Application lost focus, connection broken."];
97   [self disconnect];
98 }
99
100 #pragma mark - APPRTCConnectionManagerDelegate
101
102 - (void)connectionManager:(APPRTCConnectionManager*)manager
103     didReceiveLocalVideoTrack:(RTCVideoTrack*)localVideoTrack {
104   self.localVideoView.hidden = NO;
105   self.localVideoView.videoTrack = localVideoTrack;
106 }
107
108 - (void)connectionManager:(APPRTCConnectionManager*)manager
109     didReceiveRemoteVideoTrack:(RTCVideoTrack*)remoteVideoTrack {
110   self.remoteVideoView.videoTrack = remoteVideoTrack;
111 }
112
113 - (void)connectionManagerDidReceiveHangup:(APPRTCConnectionManager*)manager {
114   [self showAlertWithMessage:@"Remote hung up."];
115   [self disconnect];
116 }
117
118 - (void)connectionManager:(APPRTCConnectionManager*)manager
119       didErrorWithMessage:(NSString*)message {
120   [self showAlertWithMessage:message];
121   [self disconnect];
122 }
123
124 #pragma mark - APPRTCLogger
125
126 - (void)logMessage:(NSString*)message {
127   dispatch_async(dispatch_get_main_queue(), ^{
128     NSString* output =
129         [NSString stringWithFormat:@"%@\n%@", self.logView.text, message];
130     self.logView.text = output;
131     [self.logView
132         scrollRangeToVisible:NSMakeRange([self.logView.text length], 0)];
133   });
134 }
135
136 #pragma mark - RTCEAGLVideoViewDelegate
137
138 - (void)videoView:(RTCEAGLVideoView*)videoView
139     didChangeVideoSize:(CGSize)size {
140   if (videoView == self.localVideoView) {
141     _localVideoSize = size;
142   } else if (videoView == self.remoteVideoView) {
143     _remoteVideoSize = size;
144   } else {
145     NSParameterAssert(NO);
146   }
147   [self updateVideoViewLayout];
148 }
149
150 #pragma mark - UITextFieldDelegate
151
152 - (void)textFieldDidEndEditing:(UITextField*)textField {
153   NSString* room = textField.text;
154   if ([room length] == 0) {
155     return;
156   }
157   textField.hidden = YES;
158   self.instructionsView.hidden = YES;
159   self.logView.hidden = NO;
160   NSString* url =
161       [NSString stringWithFormat:@"https://apprtc.appspot.com/?r=%@", room];
162   [_connectionManager connectToRoomWithURL:[NSURL URLWithString:url]];
163   [self setupCaptureSession];
164 }
165
166 - (BOOL)textFieldShouldReturn:(UITextField*)textField {
167   // There is no other control that can take focus, so manually resign focus
168   // when return (Join) is pressed to trigger |textFieldDidEndEditing|.
169   [textField resignFirstResponder];
170   return YES;
171 }
172
173 #pragma mark - Private
174
175 - (void)disconnect {
176   [self resetUI];
177   [_connectionManager disconnect];
178 }
179
180 - (void)showAlertWithMessage:(NSString*)message {
181   UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:nil
182                                                       message:message
183                                                      delegate:nil
184                                             cancelButtonTitle:@"OK"
185                                             otherButtonTitles:nil];
186   [alertView show];
187 }
188
189 - (void)resetUI {
190   [self.roomInput resignFirstResponder];
191   self.roomInput.text = nil;
192   self.roomInput.hidden = NO;
193   self.instructionsView.hidden = NO;
194   self.logView.hidden = YES;
195   self.logView.text = nil;
196   self.localVideoView.videoTrack = nil;
197   self.remoteVideoView.videoTrack = nil;
198   self.blackView.hidden = YES;
199 }
200
201 - (void)setupCaptureSession {
202   self.blackView.hidden = NO;
203   [self updateVideoViewLayout];
204 }
205
206 - (void)updateVideoViewLayout {
207   // TODO(tkchin): handle rotation.
208   CGSize defaultAspectRatio = CGSizeMake(4, 3);
209   CGSize localAspectRatio = CGSizeEqualToSize(_localVideoSize, CGSizeZero) ?
210       defaultAspectRatio : _localVideoSize;
211   CGSize remoteAspectRatio = CGSizeEqualToSize(_remoteVideoSize, CGSizeZero) ?
212       defaultAspectRatio : _remoteVideoSize;
213
214   CGRect remoteVideoFrame =
215       AVMakeRectWithAspectRatioInsideRect(remoteAspectRatio,
216                                           self.blackView.bounds);
217   self.remoteVideoView.frame = remoteVideoFrame;
218
219   CGRect localVideoFrame =
220       AVMakeRectWithAspectRatioInsideRect(localAspectRatio,
221                                           self.blackView.bounds);
222   localVideoFrame.size.width = localVideoFrame.size.width / 3;
223   localVideoFrame.size.height = localVideoFrame.size.height / 3;
224   localVideoFrame.origin.x = CGRectGetMaxX(self.blackView.bounds)
225       - localVideoFrame.size.width - kLocalViewPadding;
226   localVideoFrame.origin.y = CGRectGetMaxY(self.blackView.bounds)
227       - localVideoFrame.size.height - kLocalViewPadding;
228   self.localVideoView.frame = localVideoFrame;
229 }
230
231 @end