diff --git a/talk/examples/ios/AppRTCDemo/APPRTCAppClient.h b/talk/examples/ios/AppRTCDemo/APPRTCAppClient.h deleted file mode 100755 index 41a795eba..000000000 --- a/talk/examples/ios/AppRTCDemo/APPRTCAppClient.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * libjingle - * Copyright 2013, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import - -#import "GAEChannelClient.h" - -// Called when there are RTCICEServers. -@protocol ICEServerDelegate - -- (void)onICEServers:(NSArray*)servers; - -@end - -@class RTCMediaConstraints; - -// Negotiates signaling for chatting with apprtc.appspot.com "rooms". -// Uses the client<->server specifics of the apprtc AppEngine webapp. -// -// To use: create an instance of this object (registering a message handler) and -// call connectToRoom(). apprtc.appspot.com will signal that is successful via -// onOpen through the browser channel. Then you should call sendData() and wait -// for the registered handler to be called with received messages. -@interface APPRTCAppClient : NSObject - -@property(nonatomic, weak, readonly) id ICEServerDelegate; -@property(nonatomic, weak, readonly) id messageHandler; -@property(nonatomic, assign) BOOL initiator; -@property(nonatomic, copy, readonly) RTCMediaConstraints* videoConstraints; - -- (id)initWithICEServerDelegate:(id)delegate - messageHandler:(id)handler; -- (void)connectToRoom:(NSURL*)room; -- (void)sendData:(NSData*)data; - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -// Disallow init and don't add to documentation -- (id)init __attribute__(( - unavailable("init is not a supported initializer for this class."))); -#endif /* DOXYGEN_SHOULD_SKIP_THIS */ - -@end diff --git a/talk/examples/ios/AppRTCDemo/APPRTCAppClient.m b/talk/examples/ios/AppRTCDemo/APPRTCAppClient.m deleted file mode 100755 index 9ef0a7a74..000000000 --- a/talk/examples/ios/AppRTCDemo/APPRTCAppClient.m +++ /dev/null @@ -1,348 +0,0 @@ -/* - * libjingle - * Copyright 2013, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import "APPRTCAppClient.h" - -#import - -#import "GAEChannelClient.h" -#import "RTCICEServer.h" -#import "APPRTCAppDelegate.h" -#import "RTCMediaConstraints.h" - -@interface APPRTCAppClient () - -@property(nonatomic, strong) dispatch_queue_t backgroundQueue; -@property(nonatomic, copy) NSString* baseURL; -@property(nonatomic, strong) GAEChannelClient* gaeChannel; -@property(nonatomic, copy) NSString* postMessageUrl; -@property(nonatomic, copy) NSString* pcConfig; -@property(nonatomic, strong) NSMutableString* roomHtml; -@property(atomic, strong) NSMutableArray* sendQueue; -@property(nonatomic, copy) NSString* token; - -@property(nonatomic, assign) BOOL verboseLogging; - -@end - -@implementation APPRTCAppClient - -- (id)initWithICEServerDelegate:(id)delegate - messageHandler:(id)handler { - if (self = [super init]) { - _ICEServerDelegate = delegate; - _messageHandler = handler; - _backgroundQueue = dispatch_queue_create("RTCBackgroundQueue", - DISPATCH_QUEUE_SERIAL); - _sendQueue = [NSMutableArray array]; - // Uncomment to see Request/Response logging. - // _verboseLogging = YES; - } - return self; -} - -#pragma mark - Public methods - -- (void)connectToRoom:(NSURL*)url { - NSURLRequest* request = [self getRequestFromUrl:url]; - [NSURLConnection connectionWithRequest:request delegate:self]; -} - -- (void)sendData:(NSData*)data { - [self maybeLogMessage:@"Send message"]; - - dispatch_async(self.backgroundQueue, ^{ - [self.sendQueue addObject:[data copy]]; - - if ([self.postMessageUrl length] < 1) { - return; - } - for (NSData* data in self.sendQueue) { - NSString* url = - [NSString stringWithFormat:@"%@/%@", - self.baseURL, self.postMessageUrl]; - [self sendData:data withUrl:url]; - } - [self.sendQueue removeAllObjects]; - }); -} - -#pragma mark - Internal methods - -- (NSString*)findVar:(NSString*)name strippingQuotes:(BOOL)strippingQuotes { - NSError* error; - NSString* pattern = - [NSString stringWithFormat:@".*\n *var %@ = ([^\n]*);\n.*", name]; - NSRegularExpression* regexp = - [NSRegularExpression regularExpressionWithPattern:pattern - options:0 - error:&error]; - NSAssert(!error, - @"Unexpected error compiling regex: ", - error.localizedDescription); - - NSRange fullRange = NSMakeRange(0, [self.roomHtml length]); - NSArray* matches = - [regexp matchesInString:self.roomHtml options:0 range:fullRange]; - if ([matches count] != 1) { - [self showMessage:[NSString stringWithFormat:@"%d matches for %@ in %@", - [matches count], - name, - self.roomHtml]]; - return nil; - } - NSRange matchRange = [matches[0] rangeAtIndex:1]; - NSString* value = [self.roomHtml substringWithRange:matchRange]; - if (strippingQuotes) { - NSAssert([value length] > 2, - @"Can't strip quotes from short string: [%@]", - value); - NSAssert(([value characterAtIndex:0] == '\'' && - [value characterAtIndex:[value length] - 1] == '\''), - @"Can't strip quotes from unquoted string: [%@]", - value); - value = [value substringWithRange:NSMakeRange(1, [value length] - 2)]; - } - return value; -} - -- (NSURLRequest*)getRequestFromUrl:(NSURL*)url { - self.roomHtml = [NSMutableString stringWithCapacity:20000]; - NSString* path = - [NSString stringWithFormat:@"https:%@", [url resourceSpecifier]]; - NSURLRequest* request = - [NSURLRequest requestWithURL:[NSURL URLWithString:path]]; - return request; -} - -- (void)maybeLogMessage:(NSString*)message { - if (self.verboseLogging) { - NSLog(@"%@", message); - } -} - -- (void)sendData:(NSData*)data withUrl:(NSString*)url { - NSMutableURLRequest* request = - [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]]; - request.HTTPMethod = @"POST"; - [request setHTTPBody:data]; - NSURLResponse* response; - NSError* error; - NSData* responseData = [NSURLConnection sendSynchronousRequest:request - returningResponse:&response - error:&error]; - NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response; - int status = [httpResponse statusCode]; - NSAssert(status == 200, - @"Bad response [%d] to message: %@\n\n%@", - status, - [NSString stringWithUTF8String:[data bytes]], - [NSString stringWithUTF8String:[responseData bytes]]); -} - -- (void)showMessage:(NSString*)message { - NSLog(@"%@", message); - UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"Unable to join" - message:message - delegate:nil - cancelButtonTitle:@"OK" - otherButtonTitles:nil]; - [alertView show]; -} - -- (void)updateICEServers:(NSMutableArray*)ICEServers - withTurnServer:(NSString*)turnServerUrl { - if ([turnServerUrl length] < 1) { - [self.ICEServerDelegate onICEServers:ICEServers]; - return; - } - dispatch_async(self.backgroundQueue, ^(void) { - NSMutableURLRequest* request = [NSMutableURLRequest - requestWithURL:[NSURL URLWithString:turnServerUrl]]; - [request addValue:@"Mozilla/5.0" forHTTPHeaderField:@"user-agent"]; - [request addValue:@"https://apprtc.appspot.com" - forHTTPHeaderField:@"origin"]; - NSURLResponse* response; - NSError* error; - NSData* responseData = [NSURLConnection sendSynchronousRequest:request - returningResponse:&response - error:&error]; - if (!error) { - NSDictionary* json = - [NSJSONSerialization JSONObjectWithData:responseData - options:0 - error:&error]; - NSAssert(!error, @"Unable to parse. %@", error.localizedDescription); - NSString* username = json[@"username"]; - NSString* password = json[@"password"]; - NSArray* uris = json[@"uris"]; - for (int i = 0; i < [uris count]; ++i) { - NSString* turnServer = [uris objectAtIndex:i]; - RTCICEServer* ICEServer = - [[RTCICEServer alloc] initWithURI:[NSURL URLWithString:turnServer] - username:username - password:password]; - NSLog(@"Added ICE Server: %@", ICEServer); - [ICEServers addObject:ICEServer]; - } - } else { - NSLog(@"Unable to get TURN server. Error: %@", error.description); - } - - dispatch_async(dispatch_get_main_queue(), ^(void) { - [self.ICEServerDelegate onICEServers:ICEServers]; - }); - }); -} - -#pragma mark - NSURLConnectionDataDelegate methods - -- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data { - NSString* roomHtml = [NSString stringWithUTF8String:[data bytes]]; - [self maybeLogMessage:[NSString stringWithFormat:@"Received %d chars", - [roomHtml length]]]; - [self.roomHtml appendString:roomHtml]; -} - -- (void)connection:(NSURLConnection*)connection - didReceiveResponse:(NSURLResponse*)response { - NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response; - int statusCode = [httpResponse statusCode]; - [self - maybeLogMessage: - [NSString stringWithFormat: - @"Response received\nURL\n%@\nStatus [%d]\nHeaders\n%@", - [httpResponse URL], - statusCode, - [httpResponse allHeaderFields]]]; - NSAssert(statusCode == 200, @"Invalid response of %d received.", statusCode); -} - -- (void)connectionDidFinishLoading:(NSURLConnection*)connection { - [self maybeLogMessage:[NSString stringWithFormat:@"finished loading %d chars", - [self.roomHtml length]]]; - NSRegularExpression* fullRegex = - [NSRegularExpression regularExpressionWithPattern:@"room is full" - options:0 - error:nil]; - if ([fullRegex - numberOfMatchesInString:self.roomHtml - options:0 - range:NSMakeRange(0, [self.roomHtml length])]) { - [self showMessage:@"Room full"]; - APPRTCAppDelegate* ad = - (APPRTCAppDelegate*)[[UIApplication sharedApplication] delegate]; - [ad closeVideoUI]; - return; - } - - NSString* fullUrl = [[[connection originalRequest] URL] absoluteString]; - NSRange queryRange = [fullUrl rangeOfString:@"?"]; - self.baseURL = [fullUrl substringToIndex:queryRange.location]; - [self maybeLogMessage:[NSString - stringWithFormat:@"Base URL: %@", self.baseURL]]; - - self.initiator = [[self findVar:@"initiator" strippingQuotes:NO] boolValue]; - self.token = [self findVar:@"channelToken" strippingQuotes:YES]; - if (!self.token) - return; - [self maybeLogMessage:[NSString stringWithFormat:@"Token: %@", self.token]]; - - NSString* roomKey = [self findVar:@"roomKey" strippingQuotes:YES]; - NSString* me = [self findVar:@"me" strippingQuotes:YES]; - if (!roomKey || !me) - return; - self.postMessageUrl = - [NSString stringWithFormat:@"/message?r=%@&u=%@", roomKey, me]; - [self maybeLogMessage:[NSString stringWithFormat:@"POST message URL: %@", - self.postMessageUrl]]; - - NSString* pcConfig = [self findVar:@"pcConfig" strippingQuotes:NO]; - if (!pcConfig) - return; - [self maybeLogMessage:[NSString - stringWithFormat:@"PC Config JSON: %@", pcConfig]]; - - NSString* turnServerUrl = [self findVar:@"turnUrl" strippingQuotes:YES]; - if (turnServerUrl) { - [self maybeLogMessage:[NSString - stringWithFormat:@"TURN server request URL: %@", - turnServerUrl]]; - } - - NSError* error; - NSData* pcData = [pcConfig dataUsingEncoding:NSUTF8StringEncoding]; - NSDictionary* json = - [NSJSONSerialization JSONObjectWithData:pcData options:0 error:&error]; - NSAssert(!error, @"Unable to parse. %@", error.localizedDescription); - NSArray* servers = [json objectForKey:@"iceServers"]; - NSMutableArray* ICEServers = [NSMutableArray array]; - for (NSDictionary* server in servers) { - NSString* url = [server objectForKey:@"urls"]; - NSString* username = json[@"username"]; - NSString* credential = [server objectForKey:@"credential"]; - if (!username) { - username = @""; - } - if (!credential) { - credential = @""; - } - [self maybeLogMessage:[NSString - stringWithFormat:@"url [%@] - credential [%@]", - url, - credential]]; - RTCICEServer* ICEServer = - [[RTCICEServer alloc] initWithURI:[NSURL URLWithString:url] - username:username - password:credential]; - NSLog(@"Added ICE Server: %@", ICEServer); - [ICEServers addObject:ICEServer]; - } - [self updateICEServers:ICEServers withTurnServer:turnServerUrl]; - - NSString* mc = [self findVar:@"mediaConstraints" strippingQuotes:NO]; - if (mc) { - error = nil; - NSData* mcData = [mc dataUsingEncoding:NSUTF8StringEncoding]; - json = - [NSJSONSerialization JSONObjectWithData:mcData options:0 error:&error]; - NSAssert(!error, @"Unable to parse. %@", error.localizedDescription); - if ([[json objectForKey:@"video"] boolValue]) { - _videoConstraints = [[RTCMediaConstraints alloc] init]; - } - } - - [self - maybeLogMessage:[NSString - stringWithFormat:@"About to open GAE with token: %@", - self.token]]; - self.gaeChannel = - [[GAEChannelClient alloc] initWithToken:self.token - delegate:self.messageHandler]; -} - -@end diff --git a/talk/examples/ios/AppRTCDemo/APPRTCAppDelegate.h b/talk/examples/ios/AppRTCDemo/APPRTCAppDelegate.h deleted file mode 100755 index dd810f74c..000000000 --- a/talk/examples/ios/AppRTCDemo/APPRTCAppDelegate.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * libjingle - * Copyright 2013, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import - -#import "GAEChannelClient.h" -#import "APPRTCAppClient.h" -#import "RTCSessionDescriptionDelegate.h" -#import "RTCVideoSource.h" -// Used to send a message to an apprtc.appspot.com "room". -@protocol APPRTCSendMessage - -- (void)sendData:(NSData*)data; -// Logging helper. -- (void)displayLogMessage:(NSString*)message; -@end - -@class APPRTCViewController; -@class RTCVideoTrack; - -// 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 APPRTCAppDelegate : UIResponder - -@property(strong, nonatomic) UIWindow* window; -@property(strong, nonatomic) APPRTCViewController* viewController; -@property (strong, nonatomic) RTCVideoSource* videoSource; - -- (void)closeVideoUI; - -@end diff --git a/talk/examples/ios/AppRTCDemo/APPRTCAppDelegate.m b/talk/examples/ios/AppRTCDemo/APPRTCAppDelegate.m deleted file mode 100755 index 87d1f53d6..000000000 --- a/talk/examples/ios/AppRTCDemo/APPRTCAppDelegate.m +++ /dev/null @@ -1,575 +0,0 @@ -/* - * libjingle - * Copyright 2013, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import - -#import "APPRTCAppDelegate.h" - -#import "APPRTCViewController.h" -#import "RTCEAGLVideoView.h" -#import "RTCICECandidate.h" -#import "RTCICEServer.h" -#import "RTCMediaConstraints.h" -#import "RTCMediaStream.h" -#import "RTCPair.h" -#import "RTCPeerConnection.h" -#import "RTCPeerConnectionDelegate.h" -#import "RTCPeerConnectionFactory.h" -#import "RTCSessionDescription.h" -#import "RTCStatsDelegate.h" -#import "RTCVideoRenderer.h" -#import "RTCVideoCapturer.h" -#import "RTCVideoTrack.h" - -@interface PCObserver : NSObject - -- (id)initWithDelegate:(id)delegate; - -@property(nonatomic, strong) RTCEAGLVideoView* videoView; - -@end - -@implementation PCObserver { - id _delegate; -} - -- (id)initWithDelegate:(id)delegate { - if (self = [super init]) { - _delegate = delegate; - } - return self; -} - -#pragma mark - RTCPeerConnectionDelegate - -- (void)peerConnectionOnError:(RTCPeerConnection*)peerConnection { - dispatch_async(dispatch_get_main_queue(), ^(void) { - NSLog(@"PCO onError."); - NSAssert(NO, @"PeerConnection failed."); - }); -} - -- (void)peerConnection:(RTCPeerConnection*)peerConnection - signalingStateChanged:(RTCSignalingState)stateChanged { - dispatch_async(dispatch_get_main_queue(), ^(void) { - NSLog(@"PCO onSignalingStateChange: %d", stateChanged); - }); -} - -- (void)peerConnection:(RTCPeerConnection*)peerConnection - addedStream:(RTCMediaStream*)stream { - dispatch_async(dispatch_get_main_queue(), ^(void) { - NSLog(@"PCO onAddStream."); - NSAssert([stream.audioTracks count] <= 1, - @"Expected at most 1 audio stream"); - NSAssert([stream.videoTracks count] <= 1, - @"Expected at most 1 video stream"); - if ([stream.videoTracks count] != 0) { - self.videoView.videoTrack = stream.videoTracks[0]; - } - }); -} - -- (void)peerConnection:(RTCPeerConnection*)peerConnection - removedStream:(RTCMediaStream*)stream { - dispatch_async(dispatch_get_main_queue(), - ^(void) { NSLog(@"PCO onRemoveStream."); }); -} - -- (void)peerConnectionOnRenegotiationNeeded:(RTCPeerConnection*)peerConnection { - dispatch_async(dispatch_get_main_queue(), ^(void) { - NSLog(@"PCO onRenegotiationNeeded - ignoring because AppRTC has a " - "predefined negotiation strategy"); - }); -} - -- (void)peerConnection:(RTCPeerConnection*)peerConnection - gotICECandidate:(RTCICECandidate*)candidate { - dispatch_async(dispatch_get_main_queue(), ^(void) { - NSLog(@"PCO onICECandidate.\n Mid[%@] Index[%d] Sdp[%@]", - candidate.sdpMid, - candidate.sdpMLineIndex, - candidate.sdp); - NSDictionary* json = @{ - @"type" : @"candidate", - @"label" : [NSNumber numberWithInt:candidate.sdpMLineIndex], - @"id" : candidate.sdpMid, - @"candidate" : candidate.sdp - }; - NSError* error; - NSData* data = - [NSJSONSerialization dataWithJSONObject:json options:0 error:&error]; - if (!error) { - [_delegate sendData:data]; - } else { - NSAssert(NO, - @"Unable to serialize JSON object with error: %@", - error.localizedDescription); - } - }); -} - -- (void)peerConnection:(RTCPeerConnection*)peerConnection - iceGatheringChanged:(RTCICEGatheringState)newState { - dispatch_async(dispatch_get_main_queue(), - ^(void) { NSLog(@"PCO onIceGatheringChange. %d", newState); }); -} - -- (void)peerConnection:(RTCPeerConnection*)peerConnection - iceConnectionChanged:(RTCICEConnectionState)newState { - dispatch_async(dispatch_get_main_queue(), ^(void) { - NSLog(@"PCO onIceConnectionChange. %d", newState); - if (newState == RTCICEConnectionConnected) - [self displayLogMessage:@"ICE Connection Connected."]; - NSAssert(newState != RTCICEConnectionFailed, @"ICE Connection failed!"); - }); -} - -- (void)peerConnection:(RTCPeerConnection*)peerConnection - didOpenDataChannel:(RTCDataChannel*)dataChannel { - NSAssert(NO, @"AppRTC doesn't use DataChannels"); -} - -#pragma mark - Private - -- (void)displayLogMessage:(NSString*)message { - [_delegate displayLogMessage:message]; -} - -@end - -@interface APPRTCAppDelegate () - -@property(nonatomic, strong) APPRTCAppClient* client; -@property(nonatomic, strong) PCObserver* pcObserver; -@property(nonatomic, strong) RTCPeerConnection* peerConnection; -@property(nonatomic, strong) RTCPeerConnectionFactory* peerConnectionFactory; -@property(nonatomic, strong) NSMutableArray* queuedRemoteCandidates; - -@end - -@implementation APPRTCAppDelegate { - NSTimer* _statsTimer; -} - -#pragma mark - UIApplicationDelegate methods - -- (BOOL)application:(UIApplication*)application - didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { - [RTCPeerConnectionFactory initializeSSL]; - self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; - self.viewController = - [[APPRTCViewController alloc] initWithNibName:@"APPRTCViewController" - bundle:nil]; - self.window.rootViewController = self.viewController; - _statsTimer = - [NSTimer scheduledTimerWithTimeInterval:10 - target:self - selector:@selector(didFireStatsTimer:) - userInfo:nil - repeats:YES]; - [self.window makeKeyAndVisible]; - return YES; -} - -- (void)applicationWillResignActive:(UIApplication*)application { - [self displayLogMessage:@"Application lost focus, connection broken."]; - [self closeVideoUI]; -} - -- (void)applicationDidEnterBackground:(UIApplication*)application { -} - -- (void)applicationWillEnterForeground:(UIApplication*)application { -} - -- (void)applicationDidBecomeActive:(UIApplication*)application { -} - -- (void)applicationWillTerminate:(UIApplication*)application { -} - -- (BOOL)application:(UIApplication*)application - openURL:(NSURL*)url - sourceApplication:(NSString*)sourceApplication - annotation:(id)annotation { - if (self.client) { - return NO; - } - self.client = [[APPRTCAppClient alloc] initWithICEServerDelegate:self - messageHandler:self]; - [self.client connectToRoom:url]; - return YES; -} - -- (void)displayLogMessage:(NSString*)message { - NSAssert([NSThread isMainThread], @"Called off main thread!"); - NSLog(@"%@", message); - [self.viewController displayText:message]; -} - -#pragma mark - RTCSendMessage method - -- (void)sendData:(NSData*)data { - [self.client sendData:data]; -} - -#pragma mark - ICEServerDelegate method - -- (void)onICEServers:(NSArray*)servers { - self.queuedRemoteCandidates = [NSMutableArray array]; - self.peerConnectionFactory = [[RTCPeerConnectionFactory alloc] init]; - RTCMediaConstraints* constraints = [[RTCMediaConstraints alloc] - initWithMandatoryConstraints: - @[ - [[RTCPair alloc] initWithKey:@"OfferToReceiveAudio" value:@"true"], - [[RTCPair alloc] initWithKey:@"OfferToReceiveVideo" value:@"true"] - ] - optionalConstraints: - @[ - [[RTCPair alloc] initWithKey:@"internalSctpDataChannels" - value:@"true"], - [[RTCPair alloc] initWithKey:@"DtlsSrtpKeyAgreement" - value:@"true"] - ]]; - self.pcObserver = [[PCObserver alloc] initWithDelegate:self]; - self.peerConnection = - [self.peerConnectionFactory peerConnectionWithICEServers:servers - constraints:constraints - delegate:self.pcObserver]; - RTCMediaStream* lms = - [self.peerConnectionFactory mediaStreamWithLabel:@"ARDAMS"]; - - // The iOS simulator doesn't provide any sort of camera capture - // support or emulation (http://goo.gl/rHAnC1) so don't bother - // trying to open a local stream. - RTCVideoTrack* localVideoTrack; -#if !TARGET_IPHONE_SIMULATOR - NSString* cameraID = nil; - for (AVCaptureDevice* captureDevice in - [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) { - if (captureDevice.position == AVCaptureDevicePositionFront) { - cameraID = [captureDevice localizedName]; - break; - } - } - NSAssert(cameraID, @"Unable to get the front camera id"); - - RTCVideoCapturer* capturer = - [RTCVideoCapturer capturerWithDeviceName:cameraID]; - self.videoSource = [self.peerConnectionFactory - videoSourceWithCapturer:capturer - constraints:self.client.videoConstraints]; - localVideoTrack = - [self.peerConnectionFactory videoTrackWithID:@"ARDAMSv0" - source:self.videoSource]; - if (localVideoTrack) { - [lms addVideoTrack:localVideoTrack]; - } - self.viewController.localVideoView.videoTrack = localVideoTrack; -#else - self.viewController.localVideoView.hidden = YES; -#endif - - self.pcObserver.videoView = self.viewController.remoteVideoView; - [lms addAudioTrack:[self.peerConnectionFactory audioTrackWithID:@"ARDAMSa0"]]; - [self.peerConnection addStream:lms constraints:constraints]; - [self displayLogMessage:@"onICEServers - added local stream."]; -} - -#pragma mark - GAEMessageHandler methods - -- (void)onOpen { - if (!self.client.initiator) { - [self displayLogMessage:@"Callee; waiting for remote offer"]; - return; - } - [self displayLogMessage:@"GAE onOpen - create offer."]; - RTCPair* audio = - [[RTCPair alloc] initWithKey:@"OfferToReceiveAudio" value:@"true"]; - RTCPair* video = - [[RTCPair alloc] initWithKey:@"OfferToReceiveVideo" value:@"true"]; - NSArray* mandatory = @[ audio, video ]; - RTCMediaConstraints* constraints = - [[RTCMediaConstraints alloc] initWithMandatoryConstraints:mandatory - optionalConstraints:nil]; - [self.peerConnection createOfferWithDelegate:self constraints:constraints]; - [self displayLogMessage:@"PC - createOffer."]; -} - -- (void)onMessage:(NSDictionary*)messageData { - NSString* type = messageData[@"type"]; - NSAssert(type, @"Missing type: %@", messageData); - [self displayLogMessage:[NSString stringWithFormat:@"GAE onMessage type - %@", - type]]; - if ([type isEqualToString:@"candidate"]) { - NSString* mid = messageData[@"id"]; - NSNumber* sdpLineIndex = messageData[@"label"]; - NSString* sdp = messageData[@"candidate"]; - RTCICECandidate* candidate = - [[RTCICECandidate alloc] initWithMid:mid - index:sdpLineIndex.intValue - sdp:sdp]; - if (self.queuedRemoteCandidates) { - [self.queuedRemoteCandidates addObject:candidate]; - } else { - [self.peerConnection addICECandidate:candidate]; - } - } else if ([type isEqualToString:@"offer"] || - [type isEqualToString:@"answer"]) { - NSString* sdpString = messageData[@"sdp"]; - RTCSessionDescription* sdp = [[RTCSessionDescription alloc] - initWithType:type - sdp:[APPRTCAppDelegate preferISAC:sdpString]]; - [self.peerConnection setRemoteDescriptionWithDelegate:self - sessionDescription:sdp]; - [self displayLogMessage:@"PC - setRemoteDescription."]; - } else if ([type isEqualToString:@"bye"]) { - [self closeVideoUI]; - UIAlertView* alertView = - [[UIAlertView alloc] initWithTitle:@"Remote end hung up" - message:@"dropping PeerConnection" - delegate:nil - cancelButtonTitle:@"OK" - otherButtonTitles:nil]; - [alertView show]; - } else { - NSAssert(NO, @"Invalid message: %@", messageData); - } -} - -- (void)onClose { - [self displayLogMessage:@"GAE onClose."]; - [self closeVideoUI]; -} - -- (void)onError:(int)code withDescription:(NSString*)description { - [self displayLogMessage:[NSString stringWithFormat:@"GAE onError: %d, %@", - code, description]]; - [self closeVideoUI]; -} - -#pragma mark - RTCSessionDescriptionDelegate methods - -// Match |pattern| to |string| and return the first group of the first -// match, or nil if no match was found. -+ (NSString*)firstMatch:(NSRegularExpression*)pattern - withString:(NSString*)string { - NSTextCheckingResult* result = - [pattern firstMatchInString:string - options:0 - range:NSMakeRange(0, [string length])]; - if (!result) - return nil; - return [string substringWithRange:[result rangeAtIndex:1]]; -} - -// Mangle |origSDP| to prefer the ISAC/16k audio codec. -+ (NSString*)preferISAC:(NSString*)origSDP { - int mLineIndex = -1; - NSString* isac16kRtpMap = nil; - NSArray* lines = [origSDP componentsSeparatedByString:@"\n"]; - NSRegularExpression* isac16kRegex = [NSRegularExpression - regularExpressionWithPattern:@"^a=rtpmap:(\\d+) ISAC/16000[\r]?$" - options:0 - error:nil]; - for (int i = 0; - (i < [lines count]) && (mLineIndex == -1 || isac16kRtpMap == nil); - ++i) { - NSString* line = [lines objectAtIndex:i]; - if ([line hasPrefix:@"m=audio "]) { - mLineIndex = i; - continue; - } - isac16kRtpMap = [self firstMatch:isac16kRegex withString:line]; - } - if (mLineIndex == -1) { - NSLog(@"No m=audio line, so can't prefer iSAC"); - return origSDP; - } - if (isac16kRtpMap == nil) { - NSLog(@"No ISAC/16000 line, so can't prefer iSAC"); - return origSDP; - } - NSArray* origMLineParts = - [[lines objectAtIndex:mLineIndex] componentsSeparatedByString:@" "]; - NSMutableArray* newMLine = - [NSMutableArray arrayWithCapacity:[origMLineParts count]]; - int origPartIndex = 0; - // Format is: m= ... - [newMLine addObject:[origMLineParts objectAtIndex:origPartIndex++]]; - [newMLine addObject:[origMLineParts objectAtIndex:origPartIndex++]]; - [newMLine addObject:[origMLineParts objectAtIndex:origPartIndex++]]; - [newMLine addObject:isac16kRtpMap]; - for (; origPartIndex < [origMLineParts count]; ++origPartIndex) { - if (![isac16kRtpMap - isEqualToString:[origMLineParts objectAtIndex:origPartIndex]]) { - [newMLine addObject:[origMLineParts objectAtIndex:origPartIndex]]; - } - } - NSMutableArray* newLines = [NSMutableArray arrayWithCapacity:[lines count]]; - [newLines addObjectsFromArray:lines]; - [newLines replaceObjectAtIndex:mLineIndex - withObject:[newMLine componentsJoinedByString:@" "]]; - return [newLines componentsJoinedByString:@"\n"]; -} - -- (void)peerConnection:(RTCPeerConnection*)peerConnection - didCreateSessionDescription:(RTCSessionDescription*)origSdp - error:(NSError*)error { - dispatch_async(dispatch_get_main_queue(), ^(void) { - if (error) { - [self displayLogMessage:@"SDP onFailure."]; - NSAssert(NO, error.description); - return; - } - [self displayLogMessage:@"SDP onSuccess(SDP) - set local description."]; - RTCSessionDescription* sdp = [[RTCSessionDescription alloc] - initWithType:origSdp.type - sdp:[APPRTCAppDelegate preferISAC:origSdp.description]]; - [self.peerConnection setLocalDescriptionWithDelegate:self - sessionDescription:sdp]; - - [self displayLogMessage:@"PC setLocalDescription."]; - NSDictionary* json = @{@"type" : sdp.type, @"sdp" : sdp.description}; - NSError* error; - NSData* data = - [NSJSONSerialization dataWithJSONObject:json options:0 error:&error]; - NSAssert(!error, - @"%@", - [NSString stringWithFormat:@"Error: %@", error.description]); - [self sendData:data]; - }); -} - -- (void)peerConnection:(RTCPeerConnection*)peerConnection - didSetSessionDescriptionWithError:(NSError*)error { - dispatch_async(dispatch_get_main_queue(), ^(void) { - if (error) { - [self displayLogMessage:@"SDP onFailure."]; - NSAssert(NO, error.description); - return; - } - - [self displayLogMessage:@"SDP onSuccess() - possibly drain candidates"]; - if (!self.client.initiator) { - if (self.peerConnection.remoteDescription && - !self.peerConnection.localDescription) { - [self displayLogMessage:@"Callee, setRemoteDescription succeeded"]; - RTCPair* audio = [[RTCPair alloc] initWithKey:@"OfferToReceiveAudio" - value:@"true"]; - RTCPair* video = [[RTCPair alloc] initWithKey:@"OfferToReceiveVideo" - value:@"true"]; - NSArray* mandatory = @[ audio, video ]; - RTCMediaConstraints* constraints = [[RTCMediaConstraints alloc] - initWithMandatoryConstraints:mandatory - optionalConstraints:nil]; - [self.peerConnection createAnswerWithDelegate:self - constraints:constraints]; - [self displayLogMessage:@"PC - createAnswer."]; - } else { - [self displayLogMessage:@"SDP onSuccess - drain candidates"]; - [self drainRemoteCandidates]; - } - } else { - if (self.peerConnection.remoteDescription) { - [self displayLogMessage:@"SDP onSuccess - drain candidates"]; - [self drainRemoteCandidates]; - } - } - }); -} - -#pragma mark - RTCStatsDelegate methods - -- (void)peerConnection:(RTCPeerConnection*)peerConnection - didGetStats:(NSArray*)stats { - dispatch_async(dispatch_get_main_queue(), ^{ - NSString* message = [NSString stringWithFormat:@"Stats:\n %@", stats]; - [self displayLogMessage:message]; - }); -} - -#pragma mark - internal methods - -- (void)disconnect { - [self.client - sendData:[@"{\"type\": \"bye\"}" dataUsingEncoding:NSUTF8StringEncoding]]; - [self.peerConnection close]; - self.peerConnection = nil; - self.pcObserver = nil; - self.client = nil; - self.videoSource = nil; - self.peerConnectionFactory = nil; - [RTCPeerConnectionFactory deinitializeSSL]; -} - -- (void)drainRemoteCandidates { - for (RTCICECandidate* candidate in self.queuedRemoteCandidates) { - [self.peerConnection addICECandidate:candidate]; - } - self.queuedRemoteCandidates = nil; -} - -- (NSString*)unHTMLifyString:(NSString*)base { - // TODO(hughv): Investigate why percent escapes are being added. Removing - // them isn't necessary on Android. - // convert HTML escaped characters to UTF8. - NSString* removePercent = - [base stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; - // remove leading and trailing ". - NSRange range; - range.length = [removePercent length] - 2; - range.location = 1; - NSString* removeQuotes = [removePercent substringWithRange:range]; - // convert \" to ". - NSString* removeEscapedQuotes = - [removeQuotes stringByReplacingOccurrencesOfString:@"\\\"" - withString:@"\""]; - // convert \\ to \. - NSString* removeBackslash = - [removeEscapedQuotes stringByReplacingOccurrencesOfString:@"\\\\" - withString:@"\\"]; - return removeBackslash; -} - -- (void)didFireStatsTimer:(NSTimer *)timer { - if (self.peerConnection) { - [self.peerConnection getStatsWithDelegate:self - mediaStreamTrack:nil - statsOutputLevel:RTCStatsOutputLevelDebug]; - } -} - -#pragma mark - public methods - -- (void)closeVideoUI { - [self.viewController resetUI]; - [self disconnect]; -} - -@end diff --git a/talk/examples/ios/AppRTCDemo/APPRTCViewController.h b/talk/examples/ios/AppRTCDemo/APPRTCViewController.h deleted file mode 100755 index 1737a138a..000000000 --- a/talk/examples/ios/AppRTCDemo/APPRTCViewController.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * libjingle - * Copyright 2013, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import - -@class RTCEAGLVideoView; - -// The view controller that is displayed when AppRTCDemo is loaded. -@interface APPRTCViewController : UIViewController - -@property(weak, nonatomic) IBOutlet UITextField* roomInput; -@property(weak, nonatomic) IBOutlet UITextView* instructionsView; -@property(weak, nonatomic) IBOutlet UITextView* logView; -@property(weak, nonatomic) IBOutlet UIView* blackView; - -@property(nonatomic, strong) RTCEAGLVideoView* localVideoView; -@property(nonatomic, strong) RTCEAGLVideoView* remoteVideoView; - -- (void)displayText:(NSString*)text; -- (void)resetUI; - -@end diff --git a/talk/examples/ios/AppRTCDemo/APPRTCViewController.m b/talk/examples/ios/AppRTCDemo/APPRTCViewController.m deleted file mode 100755 index bdd8b5036..000000000 --- a/talk/examples/ios/AppRTCDemo/APPRTCViewController.m +++ /dev/null @@ -1,150 +0,0 @@ -/* - * libjingle - * Copyright 2013, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import "APPRTCViewController.h" - -#import -#import "RTCEAGLVideoView.h" - -@interface APPRTCViewController () -@property(nonatomic, assign) UIInterfaceOrientation statusBarOrientation; -@end - -@implementation APPRTCViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - self.statusBarOrientation = - [UIApplication sharedApplication].statusBarOrientation; - self.roomInput.delegate = self; - [self.roomInput becomeFirstResponder]; -} - -- (void)viewDidLayoutSubviews { - if (self.statusBarOrientation != - [UIApplication sharedApplication].statusBarOrientation) { - self.statusBarOrientation = - [UIApplication sharedApplication].statusBarOrientation; - [[NSNotificationCenter defaultCenter] - postNotificationName:@"StatusBarOrientationDidChange" - object:nil]; - } -} - -- (void)displayText:(NSString*)text { - dispatch_async(dispatch_get_main_queue(), ^(void) { - NSString* output = - [NSString stringWithFormat:@"%@\n%@", self.logView.text, text]; - self.logView.text = output; - [self.logView - scrollRangeToVisible:NSMakeRange([self.logView.text length], 0)]; - }); -} - -- (void)resetUI { - [self.roomInput resignFirstResponder]; - self.roomInput.text = nil; - self.roomInput.hidden = NO; - self.instructionsView.hidden = NO; - self.logView.hidden = YES; - self.logView.text = nil; - self.blackView.hidden = YES; - - [self.remoteVideoView removeFromSuperview]; - self.remoteVideoView = nil; - - [self.localVideoView removeFromSuperview]; - self.localVideoView = nil; -} - -// TODO(fischman): Use video dimensions from the incoming video stream -// and resize the Video View accordingly w.r.t. aspect ratio. -enum { - // Remote video view dimensions. - kRemoteVideoWidth = 640, - kRemoteVideoHeight = 480, - // Padding space for local video view with its parent. - kLocalViewPadding = 20 -}; - -- (void)setupCaptureSession { - self.blackView.hidden = NO; - - CGSize videoSize = - CGSizeMake(kRemoteVideoWidth, kRemoteVideoHeight); - CGRect remoteVideoFrame = - AVMakeRectWithAspectRatioInsideRect(videoSize, - self.blackView.bounds); - CGRect localVideoFrame = remoteVideoFrame; - // TODO(tkchin): use video dimensions from incoming video stream - // and handle rotation. - localVideoFrame.size.width = remoteVideoFrame.size.height / 4; - localVideoFrame.size.height = remoteVideoFrame.size.width / 4; - localVideoFrame.origin.x = CGRectGetMaxX(remoteVideoFrame) - - localVideoFrame.size.width - kLocalViewPadding; - localVideoFrame.origin.y = CGRectGetMaxY(remoteVideoFrame) - - localVideoFrame.size.height - kLocalViewPadding; - - self.remoteVideoView = - [[RTCEAGLVideoView alloc] initWithFrame:remoteVideoFrame]; - [self.blackView addSubview:self.remoteVideoView]; - self.remoteVideoView.transform = CGAffineTransformMakeScale(-1, 1); - - self.localVideoView = - [[RTCEAGLVideoView alloc] initWithFrame:localVideoFrame]; - [self.blackView addSubview:self.localVideoView]; -} - -#pragma mark - UITextFieldDelegate - -- (void)textFieldDidEndEditing:(UITextField*)textField { - NSString* room = textField.text; - if ([room length] == 0) { - return; - } - textField.hidden = YES; - self.instructionsView.hidden = YES; - self.logView.hidden = NO; - // TODO(hughv): Instead of launching a URL with apprtc scheme, change to - // prepopulating the textField with a valid URL missing the room. This allows - // the user to have the simplicity of just entering the room or the ability to - // override to a custom appspot instance. Remove apprtc:// when this is done. - NSString* url = - [NSString stringWithFormat:@"apprtc://apprtc.appspot.com/?r=%@", room]; - [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]]; - - dispatch_async(dispatch_get_main_queue(), ^{ [self setupCaptureSession]; }); -} - -- (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; -} - -@end diff --git a/talk/examples/ios/AppRTCDemo/AppRTCDemo-Prefix.pch b/talk/examples/ios/AppRTCDemo/AppRTCDemo-Prefix.pch deleted file mode 100755 index 3ac2c3b1a..000000000 --- a/talk/examples/ios/AppRTCDemo/AppRTCDemo-Prefix.pch +++ /dev/null @@ -1,40 +0,0 @@ -/* - * libjingle - * Copyright 2013, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// -// Prefix header for all source files of the 'AppRTCDemo' target in the -// 'AppRTCDemo' project -// - -#import - -#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 -#import diff --git a/talk/examples/ios/AppRTCDemo/GAEChannelClient.h b/talk/examples/ios/AppRTCDemo/GAEChannelClient.h deleted file mode 100755 index 8c7d5d347..000000000 --- a/talk/examples/ios/AppRTCDemo/GAEChannelClient.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * libjingle - * Copyright 2013, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import - -// These methods will be called by the AppEngine chanel. The documentation -// for these methods is found here. (Yes, it is a JS API.) -// https://developers.google.com/appengine/docs/java/channel/javascript -@protocol GAEMessageHandler - -- (void)onOpen; -- (void)onMessage:(NSDictionary*)data; -- (void)onClose; -- (void)onError:(int)code withDescription:(NSString *)description; - -@end - -// Initialize with a token for an AppRTC data channel. This will load -// ios_channel.html and use the token to establish a data channel between the -// application and AppEngine. -@interface GAEChannelClient : NSObject - -- (id)initWithToken:(NSString *)token delegate:(id)delegate; - -@end diff --git a/talk/examples/ios/AppRTCDemo/GAEChannelClient.m b/talk/examples/ios/AppRTCDemo/GAEChannelClient.m deleted file mode 100755 index fcd0787ef..000000000 --- a/talk/examples/ios/AppRTCDemo/GAEChannelClient.m +++ /dev/null @@ -1,116 +0,0 @@ -/* - * libjingle - * Copyright 2013, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import "GAEChannelClient.h" - -#import "RTCPeerConnectionFactory.h" - -@interface GAEChannelClient () - -@property(nonatomic, assign) id delegate; -@property(nonatomic, strong) UIWebView* webView; - -@end - -@implementation GAEChannelClient - -- (id)initWithToken:(NSString*)token delegate:(id)delegate { - self = [super init]; - if (self) { - _webView = [[UIWebView alloc] init]; - _webView.delegate = self; - _delegate = delegate; - NSString* htmlPath = - [[NSBundle mainBundle] pathForResource:@"ios_channel" ofType:@"html"]; - NSURL* htmlUrl = [NSURL fileURLWithPath:htmlPath]; - NSString* path = [NSString - stringWithFormat:@"%@?token=%@", [htmlUrl absoluteString], token]; - - [_webView - loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:path]]]; - } - return self; -} - -- (void)dealloc { - _webView.delegate = nil; - [_webView stopLoading]; -} - -#pragma mark - UIWebViewDelegate method - -+ (NSDictionary*)jsonStringToDictionary:(NSString*)str { - NSData* data = [str dataUsingEncoding:NSUTF8StringEncoding]; - NSError* error; - NSDictionary* dict = - [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; - NSAssert(!error, @"Invalid JSON? %@", str); - return dict; -} - -- (BOOL)webView:(UIWebView*)webView - shouldStartLoadWithRequest:(NSURLRequest*)request - navigationType:(UIWebViewNavigationType)navigationType { - NSString* scheme = [request.URL scheme]; - NSAssert(scheme, @"scheme is nil: %@", request); - if (![scheme isEqualToString:@"js-frame"]) { - return YES; - } - - dispatch_async(dispatch_get_main_queue(), ^(void) { - NSString* queuedMessage = [webView - stringByEvaluatingJavaScriptFromString:@"popQueuedMessage();"]; - NSAssert([queuedMessage length], @"Empty queued message from JS"); - - NSDictionary* queuedMessageDict = - [GAEChannelClient jsonStringToDictionary:queuedMessage]; - NSString* method = queuedMessageDict[@"type"]; - NSAssert(method, @"Missing method: %@", queuedMessageDict); - NSDictionary* payload = queuedMessageDict[@"payload"]; // May be nil. - - if ([method isEqualToString:@"onopen"]) { - [self.delegate onOpen]; - } else if ([method isEqualToString:@"onmessage"]) { - NSDictionary* payloadData = - [GAEChannelClient jsonStringToDictionary:payload[@"data"]]; - [self.delegate onMessage:payloadData]; - } else if ([method isEqualToString:@"onclose"]) { - [self.delegate onClose]; - } else if ([method isEqualToString:@"onerror"]) { - NSNumber* codeNumber = payload[@"code"]; - int code = [codeNumber intValue]; - NSAssert([codeNumber isEqualToNumber:[NSNumber numberWithInt:code]], - @"Unexpected non-integral code: %@", payload); - [self.delegate onError:code withDescription:payload[@"description"]]; - } else { - NSAssert(NO, @"Invalid message sent from UIWebView: %@", queuedMessage); - } - }); - return NO; -} - -@end diff --git a/talk/examples/ios/AppRTCDemo/Info.plist b/talk/examples/ios/AppRTCDemo/Info.plist deleted file mode 100755 index a32be860f..000000000 --- a/talk/examples/ios/AppRTCDemo/Info.plist +++ /dev/null @@ -1,75 +0,0 @@ - - - - - BuildMachineOSBuild - 12E55 - CFBundleDevelopmentRegion - en - CFBundleDisplayName - AppRTCDemo - CFBundleExecutable - AppRTCDemo - CFBundleIcons - - CFBundlePrimaryIcon - - CFBundleIconFiles - - Icon.png - - - - CFBundleIdentifier - com.google.AppRTCDemo - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - AppRTCDemo - CFBundlePackageType - APPL - CFBundleResourceSpecification - ResourceRules.plist - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleSupportedPlatforms - - iPhoneOS - - CFBundleURLTypes - - - CFBundleTypeRole - Editor - CFBundleURLName - com.google.apprtcdemo - CFBundleURLSchemes - - apprtc - - - - CFBundleVersion - 1.0 - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarTintParameters - - UINavigationBar - - Style - UIBarStyleDefault - Translucent - - - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - - - diff --git a/talk/examples/ios/AppRTCDemo/ResourceRules.plist b/talk/examples/ios/AppRTCDemo/ResourceRules.plist deleted file mode 100755 index e7ec329dc..000000000 --- a/talk/examples/ios/AppRTCDemo/ResourceRules.plist +++ /dev/null @@ -1,25 +0,0 @@ - - - - - rules - - .* - - Info.plist - - omit - - weight - 10 - - ResourceRules.plist - - omit - - weight - 100 - - - - diff --git a/talk/examples/ios/AppRTCDemo/en.lproj/APPRTCViewController.xib b/talk/examples/ios/AppRTCDemo/en.lproj/APPRTCViewController.xib deleted file mode 100755 index 62807fe1a..000000000 --- a/talk/examples/ios/AppRTCDemo/en.lproj/APPRTCViewController.xib +++ /dev/null @@ -1,716 +0,0 @@ - - - - 1536 - 13B42 - 4514 - 1265 - 696.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 3747 - - - IBNSLayoutConstraint - IBProxyObject - IBUITextField - IBUITextView - IBUIView - - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - PluginDependencyRecalculationVersion - - - - - IBFilesOwner - IBCocoaTouchFramework - - - IBFirstResponder - IBCocoaTouchFramework - - - - 274 - - - - 292 - {{20, 20}, {280, 141}} - - - - _NS:9 - - 1 - MSAxIDEAA - - YES - NO - IBCocoaTouchFramework - Use Safari and open a URL with a scheme of apprtc to load the test app and connect. i.e. apprtc://apprtc.appspot.com/?r=12345678 Or just enter the room below to connect to apprtc. - - 2 - IBCocoaTouchFramework - - - 1 - 14 - - - HelveticaNeue - 14 - 16 - - - - - 292 - {{20, 180}, {280, 30}} - - - - _NS:9 - NO - YES - IBCocoaTouchFramework - 0 - - 3 - apprtc room - - 3 - MAA - - 2 - - - YES - 17 - - 2 - 3 - IBCocoaTouchFramework - - - - - - - -2147483356 - {{20, 20}, {280, 190}} - - - - _NS:9 - - YES - YES - IBCocoaTouchFramework - NO - - - 2 - IBCocoaTouchFramework - - - - - - - -2147483356 - {{20, 228}, {280, 300}} - - - - _NS:9 - - 3 - MAA - - IBCocoaTouchFramework - - - {{0, 20}, {320, 548}} - - - - - 3 - MC43NQA - - - NO - - - IBUIScreenMetrics - - YES - - - - - - {320, 568} - {568, 320} - - - IBCocoaTouchFramework - Retina 4-inch Full Screen - 2 - - IBCocoaTouchFramework - - - - - - - view - - - - 7 - - - - roomInput - - - - 108 - - - - instructionsView - - - - 127 - - - - logView - - - - 138 - - - - blackView - - - - 151 - - - - - - 0 - - - - - - -1 - - - File's Owner - - - -2 - - - - - 6 - - - - - 4 - 0 - - 4 - 1 - - 20 - - 1000 - - 8 - 23 - 3 - NO - - - - 3 - 0 - - 3 - 1 - - 228 - - 1000 - - 3 - 9 - 3 - NO - - - - 5 - 0 - - 5 - 1 - - 0.0 - - 1000 - - 6 - 24 - 2 - NO - - - - 6 - 0 - - 6 - 1 - - 0.0 - - 1000 - - 6 - 24 - 2 - NO - - - - 6 - 0 - - 6 - 1 - - 20 - - 1000 - - 0 - 29 - 3 - NO - - - - 5 - 0 - - 5 - 1 - - 20 - - 1000 - - 0 - 29 - 3 - NO - - - - 4 - 0 - - 4 - 1 - - 0.0 - - 1000 - - 6 - 24 - 2 - NO - - - - 3 - 0 - - 3 - 1 - - 20 - - 1000 - - 0 - 29 - 3 - NO - - - - 6 - 0 - - 6 - 1 - - 20 - - 1000 - - 0 - 29 - 3 - NO - - - - 5 - 0 - - 5 - 1 - - 20 - - 1000 - - 0 - 29 - 3 - NO - - - - 6 - 0 - - 6 - 1 - - 20 - - 1000 - - 0 - 29 - 3 - NO - - - - 3 - 0 - - 3 - 1 - - 20 - - 1000 - - 0 - 29 - 3 - NO - - - - 5 - 0 - - 5 - 1 - - 20 - - 1000 - - 0 - 29 - 3 - NO - - - - - - - - - - 57 - - - - - 8 - 0 - - 0 - 1 - - 141 - - 1000 - - 3 - 9 - 1 - NO - - - - - - 62 - - - - - 63 - - - - - 66 - - - - - 104 - - - - - - 107 - - - - - 123 - - - - - 126 - - - - - 128 - - - - - 8 - 0 - - 0 - 1 - - 190 - - 1000 - - 3 - 9 - 1 - NO - - - - - - 133 - - - - - 137 - - - - - 139 - - - - - 141 - - - - - 142 - - - - - 148 - - - - - 149 - - - - - 153 - - - - - 154 - - - - - 155 - - - - - - - APPRTCViewController - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - UIResponder - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - - - - - - - - - - - - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - - - 155 - - - - - APPRTCViewController - UIViewController - - UIView - UITextField - UITextView - UITextView - - - - blackView - UIView - - - roomInput - UITextField - - - instructionsView - UITextView - - - logView - UITextView - - - - IBProjectSource - ./Classes/APPRTCViewController.h - - - - NSLayoutConstraint - NSObject - - IBProjectSource - ./Classes/NSLayoutConstraint.h - - - - - 0 - IBCocoaTouchFramework - YES - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - - - YES - 3 - YES - 3747 - - diff --git a/talk/examples/ios/AppRTCDemo/ios_channel.html b/talk/examples/ios/AppRTCDemo/ios_channel.html deleted file mode 100755 index 86846dd68..000000000 --- a/talk/examples/ios/AppRTCDemo/ios_channel.html +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - - diff --git a/talk/examples/ios/AppRTCDemo/main.m b/talk/examples/ios/AppRTCDemo/main.m deleted file mode 100755 index e9a1f63ef..000000000 --- a/talk/examples/ios/AppRTCDemo/main.m +++ /dev/null @@ -1,37 +0,0 @@ -/* - * libjingle - * Copyright 2013, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import - -#import "APPRTCAppDelegate.h" - -int main(int argc, char* argv[]) { - @autoreleasepool { - return UIApplicationMain( - argc, argv, nil, NSStringFromClass([APPRTCAppDelegate class])); - } -} diff --git a/talk/examples/ios/README b/talk/examples/ios/README deleted file mode 100755 index 9c0d13417..000000000 --- a/talk/examples/ios/README +++ /dev/null @@ -1,3 +0,0 @@ -This directory contains an example iOS client for http://apprtc.appspot.com - -See ../../app/webrtc/objc/README for information on how to use it. diff --git a/talk/examples/ios/AppRTCDemo/Default.png b/talk/examples/objc/AppRTCDemo/ios/Default.png old mode 100755 new mode 100644 similarity index 100% rename from talk/examples/ios/AppRTCDemo/Default.png rename to talk/examples/objc/AppRTCDemo/ios/Default.png diff --git a/talk/examples/ios/Icon.png b/talk/examples/objc/Icon.png old mode 100755 new mode 100644 similarity index 100% rename from talk/examples/ios/Icon.png rename to talk/examples/objc/Icon.png