完成ios端功能 #1

Merged
fandd merged 5 commits from feature-ios into master 2022-04-08 17:21:41 +08:00
13 changed files with 292 additions and 147 deletions
Showing only changes of commit 10d1e562ee - Show all commits

View File

@ -44,12 +44,16 @@
<source-file src="src/ios/Events.m"/>
<header-file src="src/ios/Listener.h"/>
<source-file src="src/ios/Listener.m"/>
<header-file src="src/ios/UserUpdateListener.h"/>
<source-file src="src/ios/UserUpdateListener.m"/>
<header-file src="src/ios/TrtcUserInfo.h"/>
<source-file src="src/ios/TrtcUserInfo.m"/>
<header-file src="src/ios/Toast/UIView+Toast.h"/>
<source-file src="src/ios/Toast/UIView+Toast.m"/>
<header-file src="src/ios/UIView+Toast.h"/>
<source-file src="src/ios/UIView+Toast.m"/>
<header-file src="src/ios/VideoCallingViewController.h"/>
<source-file src="src/ios/VideoCallingViewController.m"/>
@ -64,7 +68,7 @@
<framework src="src/ios/FFmpeg.xcframework" custom="true" embed="true"/>
<framework src="src/ios/SoundTouch.xcframework" custom="true" embed="true"/>
<framework src="src/ios/TXLiteAVSDK_TRTC.framework" custom="true"/>
<framework src="src/ios/TXLiteAVSDK_ReplayKitExt.framework" custom="true"/>
<!-- <framework src="src/ios/TXLiteAVSDK_ReplayKitExt.framework" custom="true"/>-->
</platform>

View File

@ -13,7 +13,7 @@
@implementation Events
static NSString* PREFIX = @"com.tencent.trtc.event";
static NSDictionary *events = nil;
static NSDictionary<NSString*,NSMutableOrderedSet<Listener*>*> *events = nil;
+ (void)fireEvent: (NSString*)event{
[Events fireEvent: nil];
@ -21,7 +21,7 @@ static NSDictionary *events = nil;
+ (void)fireEvent: (NSString*)event extra:(NSDictionary*)extra{
[Events init];
NSLog(@"TRTC - Events::fireEvent --- event:%@,extra:%@",event,extra);
NSMutableArray* listeners = [self getEventListener:event];
NSMutableOrderedSet* listeners = [self getEventListener:event];
if(listeners != nil && listeners.count > 0 ){
for (Listener* listener in listeners) {
NSLog(@"TRTC - Events::fireEvent --- event:%@,listener:%@",event,listener);
@ -32,7 +32,7 @@ static NSDictionary *events = nil;
+ (void)addListener: (NSString*)event listener:(Listener*)listener{
[Events init];
NSLog(@"TRTC - Events::addListener --- event:%@,listener:%@",event,listener);
NSMutableArray* listeners = [self getEventListener:event];
NSMutableOrderedSet* listeners = [self getEventListener:event];
if(![listeners containsObject:listener]){
[listeners addObject:listener];
}
@ -40,7 +40,7 @@ static NSDictionary *events = nil;
+ (void)removeListener: (NSString*)event listener:(Listener*)listener{
[Events init];
NSLog(@"TRTC - Events::removeListener --- event:%@,listener:%@",event,listener);
NSMutableArray* listeners = [self getEventListener:event];
NSMutableOrderedSet* listeners = [self getEventListener:event];
if([listeners containsObject:listener]){
[listeners removeObject:listener];
}
@ -48,15 +48,13 @@ static NSDictionary *events = nil;
+ (void)init{
if( events == nil){
events = [NSDictionary new];
NSMutableOrderedSet* listeners = [[NSMutableOrderedSet alloc] init];
events = [[NSDictionary alloc] initWithObjectsAndKeys:listeners,@"com.tencent.trtc.eventuserinfo.update", nil];
}
}
+ (NSMutableArray*) getEventListener: (NSString*)event{
+ (NSMutableOrderedSet*) getEventListener: (NSString*)event{
[Events init];
NSString* key = [[NSString alloc] initWithFormat:@"%@%@", PREFIX, event ];
if([events objectForKey:key] == nil){
NSMutableArray* listeners = [NSMutableArray array];
[events setValue:listeners forKey:key];
}
return [events objectForKey:key];
return [events valueForKey:key];
}
@end

View File

@ -9,7 +9,7 @@
#define Listener_h
#endif /* Listener_h */
@interface Listener
@interface Listener:NSObject
{}
- (instancetype)init;
- (void)on: (NSDictionary*)extra;

21
src/ios/Listener.m Normal file
View File

@ -0,0 +1,21 @@
//
// Listener.m
// shuto-cne
//
// Created by on 2022/3/30.
//
#import <Foundation/Foundation.h>
#import "Listener.h"
@interface Listener()
{}
- (instancetype)init;
- (void)on: (NSDictionary*)extra;
@end
@implementation Listener
- (instancetype)init{
return self;
}
- (void)on: (NSDictionary*)extra{}
@end

31
src/ios/TrtcUserInfo.h Normal file
View File

@ -0,0 +1,31 @@
//
// TrtcUserInfo.h
// shuto-cne
//
// Created by 范大德 on 2022/3/30.
//
#ifndef TrtcUserInfo_h
#define TrtcUserInfo_h
#endif /* TrtcUserInfo_h */
@interface TrtcUserInfo: NSObject
{}
// 自定义类的初始化方法
// 过去类型instancetype 是 id 类型
- (instancetype)initWithPersonid:(NSString *)personid;
- (NSString*) personid;
-(NSString *)displayName;
-(BOOL)isShareUser;
-(BOOL)isLocalUser;
-(void)setLocal:(BOOL) value;
-(void)setDisplayName:(NSString *)value;
@end

View File

@ -6,22 +6,13 @@
//
#import <Foundation/Foundation.h>
@interface TrtcUserInfo : NSObject
#import "TrtcUserInfo.h"
@interface TrtcUserInfo()
{
NSString* personid;
NSString* displayName;
BOOL local;
}
//
// instancetype id
- (instancetype)initWithPersonid:(NSString *)personid;
- (NSString*) personid;
@end
@implementation TrtcUserInfo

View File

@ -0,0 +1,18 @@
//
// UserUpdateListener.h
// shuto-cne
//
// Created by 范大德 on 2022/3/30.
//
#ifndef UserUpdateListener_h
#define UserUpdateListener_h
#endif /* UserUpdateListener_h */
#import "Listener.h"
@interface UserUpdateListener:Listener
{}
@end

View File

@ -5,11 +5,9 @@
// Created by on 2022/3/29.
//
#import <Foundation/Foundation.h>
#import "Listener.h"
#import "TrtcUserInfo.m"
#import "UserUpdateListener.h"
#import "VideoCallingViewController.h"
@interface UserUpdateListener : Listener
@interface UserUpdateListener()
{}
@end
@implementation UserUpdateListener
@ -20,16 +18,7 @@
-(void)on: (NSDictionary*)extra{
NSLog(@"TRTC - userinfo.update -- userID:%@,displayname:%@",extra[@"userId"],extra[@"displayName"]);
TrtcUserInfo *user = [[TrtcUserInfo alloc] initWithPersonid:extra[@"userId"]];
NSInteger index = [[[VideoCallingViewController viewController] remoteUidSet] indexOfObject: user];
NSLog(@"TRTC - userinfo.update -- userId:%@,index:%ld",extra[@"userId"],index);
if (index != NSNotFound) { return; }
TrtcUserInfo *obj = [[VideoCallingViewController viewController] remoteUidSet][index];
[obj setDisplayName: extra[@"displayName"]];
dispatch_async(dispatch_get_main_queue(), ^{
[[VideoCallingViewController viewController] refreshRemoteVideoViews];
});
[[VideoCallingViewController viewController]updateUser:extra];
}
@end

View File

@ -6,7 +6,6 @@
//
#import <UIKit/UIKit.h>
//#import "TrtcOptions.h"
#import <TXLiteAVSDK_TRTC/TRTCCloud.h>
@ -18,6 +17,7 @@ NS_ASSUME_NONNULL_BEGIN
- (NSMutableOrderedSet *)remoteUidSet;
+(VideoCallingViewController*)viewController;
- (void)refreshRemoteVideoViews;
- (void) updateUser:(NSDictionary*)extra;
@end
NS_ASSUME_NONNULL_END

View File

@ -30,11 +30,11 @@ Real-Time Audio Call
#import "VideoCallingViewController.h"
#import "TrtcUserInfo.m"
#import "TrtcUserInfo.h"
#import "CordovaEventKit.h"
#import "Toast/UIView+Toast.h"
#import "UIView+Toast.h"
#import "Events.h"
#import "UserUpdateListener.m"
#import "UserUpdateListener.h"
static const NSInteger maxRemoteUserNum = 7;
@ -103,6 +103,19 @@ static const NSInteger maxRemoteUserNum = 7;
return self;
}
- (void) updateUser:(NSDictionary*)extra{
NSLog(@"TRTC - userinfo.update -- userID:%@,displayname:%@",extra[@"userId"],extra[@"displayName"]);
TrtcUserInfo *user = [[TrtcUserInfo alloc]initWithPersonid:extra[@"userId"]];
NSInteger index = [[self remoteUidSet] indexOfObject: user];
NSLog(@"TRTC - userinfo.update -- userId:%@,index:%ld",extra[@"userId"],index);
if (index != NSNotFound) { return; }
TrtcUserInfo *obj = [self remoteUidSet][index];
[obj setDisplayName: extra[@"displayName"]];
dispatch_async(dispatch_get_main_queue(), ^{
[self refreshRemoteVideoViews];
});
}
- (void)viewDidLoad {
[super viewDidLoad];
@ -119,7 +132,7 @@ static const NSInteger maxRemoteUserNum = 7;
_displayLabel.text = @"我";
_displayLabel.hidden = NO;
_rotation = 0;
[Events addListener:@"userinfo.update" listener: [UserUpdateListener init] ];
[Events addListener:@"userinfo.update" listener: [[UserUpdateListener alloc] init] ];
}

View File

@ -1,29 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina5_5" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="VideoCallingViewController">
<connections>
<outlet property="audioOptionsLabel" destination="XO4-yA-tc4" id="5k8-Lj-Oa2"/>
<outlet property="captureCamButton" destination="bER-FL-1Pr" id="8eP-bR-0ac"/>
<outlet property="hansFreeButton" destination="1ok-0H-gMn" id="9lz-ge-ocw"/>
<outlet property="muteButton" destination="n5g-Xo-TlH" id="DoM-8n-z9q"/>
<outlet property="switchCamButton" destination="RhW-u5-l40" id="z8O-ba-9W8"/>
<outlet property="videoOptionsLabel" destination="YEx-nY-vge" id="XpX-iU-igL"/>
<outlet property="displayLabel" destination="YvU-M3-dYi" id="51r-fe-mFR"/>
<outlet property="subVisibleButton" destination="qp6-PK-LBy" id="eyH-u5-0dn"/>
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
<outlet property="viewRotateButton" destination="rF6-xK-afO" id="cn9-hg-AYV"/>
<outletCollection property="remoteViewArr" destination="Kbh-1W-XwY" id="nUp-5a-Xzv"/>
<outletCollection property="remoteViewArr" destination="MBM-E8-DcQ" id="Kml-lI-eY2"/>
<outletCollection property="remoteViewArr" destination="ZEJ-k9-h9o" id="Dpa-XO-wvu"/>
<outletCollection property="remoteViewArr" destination="X9k-lT-qBv" id="v8m-xW-j33"/>
<outletCollection property="remoteViewArr" destination="onQ-DT-Yct" id="AXN-8c-H6e"/>
<outletCollection property="remoteViewArr" destination="cDr-2L-E86" id="XHg-z0-cal"/>
<outletCollection property="displayLabelArr" destination="bTi-oL-YQO" id="FbS-pO-ofo"/>
<outletCollection property="displayLabelArr" destination="XZp-OY-07f" id="UA7-Ky-ODc"/>
<outletCollection property="displayLabelArr" destination="x2c-r3-mbd" id="8tE-hB-ImW"/>
<outletCollection property="displayLabelArr" destination="IbE-C4-eSC" id="R4x-VL-wHM"/>
<outletCollection property="displayLabelArr" destination="Sb1-bA-J6q" id="Yal-GN-3Sv"/>
<outletCollection property="displayLabelArr" destination="twT-zq-iCy" id="pHx-JS-dcf"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
@ -33,6 +35,16 @@
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Kbh-1W-XwY" userLabel="remoteVideoView1">
<rect key="frame" x="314" y="50" width="90" height="160"/>
<subviews>
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Label1" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bTi-oL-YQO">
<rect key="frame" x="0.0" y="139" width="48" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
<color key="backgroundColor" red="0.0" green="0.34100000000000003" blue="0.29399999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="160" id="auE-6N-CzV"/>
@ -41,6 +53,16 @@
</view>
<view tag="1" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="MBM-E8-DcQ" userLabel="remoteVideoView2">
<rect key="frame" x="314" y="226" width="90" height="160"/>
<subviews>
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Label2" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XZp-OY-07f">
<rect key="frame" x="0.0" y="139" width="52" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
<color key="backgroundColor" red="0.0" green="0.34100000000000003" blue="0.29399999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="width" constant="90" id="1kk-EX-8rm"/>
@ -49,6 +71,16 @@
</view>
<view tag="2" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ZEJ-k9-h9o" userLabel="remoteVideoView3">
<rect key="frame" x="314" y="402" width="90" height="160"/>
<subviews>
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Label3" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="x2c-r3-mbd">
<rect key="frame" x="0.0" y="139" width="52" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
<color key="backgroundColor" red="0.0" green="0.34100000000000003" blue="0.29399999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="160" id="N5Y-DF-8xu"/>
@ -57,6 +89,16 @@
</view>
<view tag="3" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="X9k-lT-qBv" userLabel="remoteVideoView4">
<rect key="frame" x="10" y="50" width="90" height="160"/>
<subviews>
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Label4" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="IbE-C4-eSC">
<rect key="frame" x="0.0" y="139" width="52" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
<color key="backgroundColor" red="0.0" green="0.34100000000000003" blue="0.29399999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="width" constant="90" id="ZMf-aQ-nNf"/>
@ -65,6 +107,16 @@
</view>
<view tag="4" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="onQ-DT-Yct" userLabel="remoteVideoView5">
<rect key="frame" x="10" y="226" width="90" height="160"/>
<subviews>
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Label5" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Sb1-bA-J6q">
<rect key="frame" x="0.0" y="139" width="52" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
<color key="backgroundColor" red="0.0" green="0.34100000000000003" blue="0.29399999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="160" id="BFk-Gh-7v4"/>
@ -73,92 +125,122 @@
</view>
<view tag="5" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="cDr-2L-E86" userLabel="remoteVideoView6">
<rect key="frame" x="10" y="402" width="90" height="160"/>
<subviews>
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Label6" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="twT-zq-iCy">
<rect key="frame" x="0.0" y="139" width="52" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
<color key="backgroundColor" red="0.0" green="0.34100000000000003" blue="0.29399999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="width" constant="90" id="CVu-hM-f8k"/>
<constraint firstAttribute="height" constant="160" id="Ydt-pt-cM4"/>
</constraints>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YEx-nY-vge">
<rect key="frame" x="20" y="543" width="100" height="35"/>
<constraints>
<constraint firstAttribute="height" constant="35" id="H8X-UA-JOq"/>
<constraint firstAttribute="width" constant="100" id="UTC-BW-0G0"/>
</constraints>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="rzV-fr-mUd">
<rect key="frame" x="0.0" y="0.0" width="41" height="31"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="plain" image="chevron.backward" catalog="system" title=" "/>
<connections>
<action selector="onBackClick:" destination="-1" eventType="touchUpInside" id="aV2-bn-bDv"/>
</connections>
</button>
<stackView opaque="NO" contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="XCN-Qr-goF">
<rect key="frame" x="82" y="666" width="250" height="50"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" selected="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="cqv-YF-v7M">
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
<constraints>
<constraint firstAttribute="width" constant="50" id="dwe-bq-Wq8"/>
<constraint firstAttribute="height" constant="50" id="iQf-fV-QIk"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="36"/>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" image="mic.slash" catalog="system">
<preferredSymbolConfiguration key="preferredSymbolConfiguration" scale="large"/>
</state>
<state key="selected" image="mic" catalog="system">
<preferredSymbolConfiguration key="preferredSymbolConfiguration" scale="large"/>
</state>
<connections>
<action selector="onMicCaptureClick:" destination="-1" eventType="touchUpInside" id="74S-01-YUi"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="iNs-1U-f8V">
<rect key="frame" x="50" y="0.0" width="50" height="50"/>
<constraints>
<constraint firstAttribute="width" constant="50" id="N3O-bv-Nk0"/>
</constraints>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" image="speaker.wave.2" catalog="system">
<preferredSymbolConfiguration key="preferredSymbolConfiguration" scale="large"/>
</state>
<state key="selected" image="ear" catalog="system">
<preferredSymbolConfiguration key="preferredSymbolConfiguration" scale="large"/>
</state>
<connections>
<action selector="onSwitchSpeakerClick:" destination="-1" eventType="touchUpInside" id="QhV-mp-sQc"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" selected="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="S9T-PM-Hhz">
<rect key="frame" x="100" y="0.0" width="50" height="50"/>
<constraints>
<constraint firstAttribute="width" constant="50" id="PuT-SC-nBb"/>
</constraints>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" image="camera.rotate" catalog="system">
<preferredSymbolConfiguration key="preferredSymbolConfiguration" scale="large"/>
</state>
<state key="selected" image="camera.rotate" catalog="system">
<preferredSymbolConfiguration key="preferredSymbolConfiguration" scale="large"/>
</state>
<connections>
<action selector="onSwitchCameraClick:" destination="-1" eventType="touchUpInside" id="oQG-9m-ga4"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" selected="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qp6-PK-LBy">
<rect key="frame" x="150" y="0.0" width="50" height="50"/>
<constraints>
<constraint firstAttribute="width" constant="50" id="U8G-VC-E4h"/>
</constraints>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" image="eye.slash" catalog="system">
<preferredSymbolConfiguration key="preferredSymbolConfiguration" scale="large"/>
</state>
<state key="selected" image="eye" catalog="system">
<preferredSymbolConfiguration key="preferredSymbolConfiguration" scale="large"/>
</state>
<connections>
<action selector="onSubVisibleChange:" destination="-1" eventType="touchUpInside" id="ZHg-NL-PVq"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="rF6-xK-afO">
<rect key="frame" x="200" y="0.0" width="50" height="50"/>
<constraints>
<constraint firstAttribute="width" constant="50" id="xJB-cA-Wjz"/>
</constraints>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" title=" " image="rotate.right" catalog="system">
<preferredSymbolConfiguration key="preferredSymbolConfiguration" scale="large"/>
</state>
<connections>
<action selector="onVideoRotate:" destination="-1" eventType="touchUpInside" id="isy-8q-IGB"/>
</connections>
</button>
</subviews>
</stackView>
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YvU-M3-dYi">
<rect key="frame" x="10" y="704" width="40" height="21"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
<color key="backgroundColor" red="0.0" green="0.34100000000000003" blue="0.29399999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" systemColor="systemRedColor"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XO4-yA-tc4">
<rect key="frame" x="20" y="626" width="100" height="35"/>
<constraints>
<constraint firstAttribute="height" constant="35" id="38M-1n-NSm"/>
<constraint firstAttribute="width" constant="100" id="nfo-RZ-LlB"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" systemColor="systemRedColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="RhW-u5-l40">
<rect key="frame" x="20" y="586" width="120" height="30"/>
<color key="backgroundColor" red="0.20392156859999999" green="0.78039215689999997" blue="0.34901960780000002" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="NQE-Vx-NNP"/>
<constraint firstAttribute="width" constant="120" id="c8E-Xh-xpO"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<state key="normal" title="button">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
<connections>
<action selector="onSwitchCameraClick:" destination="-1" eventType="touchUpInside" id="acE-9c-8zt"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="bER-FL-1Pr">
<rect key="frame" x="165" y="586" width="120" height="30"/>
<color key="backgroundColor" red="0.20392156859999999" green="0.78039215689999997" blue="0.34901960780000002" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="YnS-j5-8C9"/>
<constraint firstAttribute="width" constant="120" id="wR8-yi-lqY"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<state key="normal" title="button">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
<connections>
<action selector="onVideoCaptureClick:" destination="-1" eventType="touchUpInside" id="wId-i7-9ED"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1ok-0H-gMn">
<rect key="frame" x="165" y="671" width="120" height="30"/>
<color key="backgroundColor" red="0.20392156859999999" green="0.78039215689999997" blue="0.34901960780000002" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="ZMC-7r-P4h"/>
<constraint firstAttribute="width" constant="120" id="nLE-kk-sMA"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<state key="normal" title="button">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
<connections>
<action selector="onSwitchSpeakerClick:" destination="-1" eventType="touchUpInside" id="xz7-7K-thr"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="n5g-Xo-TlH">
<rect key="frame" x="20" y="671" width="120" height="30"/>
<color key="backgroundColor" red="0.20392156859999999" green="0.78039215689999997" blue="0.34901960780000002" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="qSh-EQ-Mgr"/>
<constraint firstAttribute="width" constant="120" id="u4R-Dl-Oyg"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<state key="normal" title="button">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
<connections>
<action selector="onMicCaptureClick:" destination="-1" eventType="touchUpInside" id="iec-4d-VGC"/>
</connections>
</button>
</subviews>
<viewLayoutGuide key="safeArea" id="Q5M-cg-NOt"/>
<color key="backgroundColor" red="0.1176470588" green="0.1176470588" blue="0.12941176469999999" alpha="1" colorSpace="calibratedRGB"/>
@ -166,34 +248,32 @@
<constraint firstItem="MBM-E8-DcQ" firstAttribute="top" secondItem="Kbh-1W-XwY" secondAttribute="bottom" constant="16" id="1yJ-zP-b2C"/>
<constraint firstItem="cDr-2L-E86" firstAttribute="centerX" secondItem="onQ-DT-Yct" secondAttribute="centerX" id="3fJ-Ut-5UD"/>
<constraint firstItem="X9k-lT-qBv" firstAttribute="leading" secondItem="Q5M-cg-NOt" secondAttribute="leading" constant="10" id="8GX-Xg-ir5"/>
<constraint firstItem="rzV-fr-mUd" firstAttribute="leading" secondItem="Q5M-cg-NOt" secondAttribute="leading" id="98P-U1-kNm"/>
<constraint firstItem="onQ-DT-Yct" firstAttribute="top" secondItem="X9k-lT-qBv" secondAttribute="bottom" constant="16" id="BW3-oz-96z"/>
<constraint firstItem="RhW-u5-l40" firstAttribute="top" secondItem="YEx-nY-vge" secondAttribute="bottom" constant="8" symbolic="YES" id="EJy-1l-REu"/>
<constraint firstItem="Q5M-cg-NOt" firstAttribute="trailing" secondItem="Kbh-1W-XwY" secondAttribute="trailing" constant="10" id="EaZ-v3-NGd"/>
<constraint firstItem="onQ-DT-Yct" firstAttribute="leading" secondItem="X9k-lT-qBv" secondAttribute="leading" id="KM5-ip-GY3"/>
<constraint firstItem="n5g-Xo-TlH" firstAttribute="leading" secondItem="XO4-yA-tc4" secondAttribute="leading" id="Kl4-e8-eXH"/>
<constraint firstItem="Q5M-cg-NOt" firstAttribute="bottom" secondItem="n5g-Xo-TlH" secondAttribute="bottom" constant="35" id="Ncs-Wh-q0R"/>
<constraint firstItem="bER-FL-1Pr" firstAttribute="top" secondItem="RhW-u5-l40" secondAttribute="top" id="OXw-DU-P4a"/>
<constraint firstItem="RhW-u5-l40" firstAttribute="leading" secondItem="YEx-nY-vge" secondAttribute="leading" id="QQN-eN-A1U"/>
<constraint firstItem="XCN-Qr-goF" firstAttribute="centerX" secondItem="Q5M-cg-NOt" secondAttribute="centerX" id="Rl1-fY-2iF"/>
<constraint firstItem="X9k-lT-qBv" firstAttribute="top" secondItem="Kbh-1W-XwY" secondAttribute="top" id="SuC-17-FjX"/>
<constraint firstItem="ZEJ-k9-h9o" firstAttribute="top" secondItem="MBM-E8-DcQ" secondAttribute="bottom" constant="16" id="Tmr-ve-Msw"/>
<constraint firstItem="bER-FL-1Pr" firstAttribute="leading" secondItem="RhW-u5-l40" secondAttribute="trailing" constant="25" id="bOX-nj-TnL"/>
<constraint firstItem="1ok-0H-gMn" firstAttribute="leading" secondItem="n5g-Xo-TlH" secondAttribute="trailing" constant="25" id="en1-gb-m19"/>
<constraint firstItem="XO4-yA-tc4" firstAttribute="leading" secondItem="RhW-u5-l40" secondAttribute="leading" id="eqE-CR-yeC"/>
<constraint firstItem="1ok-0H-gMn" firstAttribute="top" secondItem="n5g-Xo-TlH" secondAttribute="top" id="gyW-dI-1YD"/>
<constraint firstItem="XO4-yA-tc4" firstAttribute="top" secondItem="RhW-u5-l40" secondAttribute="bottom" constant="10" id="ifn-o5-XfJ"/>
<constraint firstItem="rzV-fr-mUd" firstAttribute="top" secondItem="Q5M-cg-NOt" secondAttribute="top" id="Ucj-DC-JKE"/>
<constraint firstItem="Q5M-cg-NOt" firstAttribute="bottom" secondItem="XCN-Qr-goF" secondAttribute="bottom" constant="20" id="YiA-vD-j7g"/>
<constraint firstItem="cDr-2L-E86" firstAttribute="top" secondItem="onQ-DT-Yct" secondAttribute="bottom" constant="16" id="jZv-Bd-JgO"/>
<constraint firstItem="YEx-nY-vge" firstAttribute="leading" secondItem="Q5M-cg-NOt" secondAttribute="leading" constant="20" id="mE6-KR-pBU"/>
<constraint firstItem="n5g-Xo-TlH" firstAttribute="top" secondItem="XO4-yA-tc4" secondAttribute="bottom" constant="10" id="nUl-n3-I9i"/>
<constraint firstItem="Q5M-cg-NOt" firstAttribute="trailing" secondItem="MBM-E8-DcQ" secondAttribute="trailing" constant="10" id="t3x-XY-dgu"/>
<constraint firstItem="Kbh-1W-XwY" firstAttribute="top" secondItem="Q5M-cg-NOt" secondAttribute="top" constant="50" id="u7E-0d-lDq"/>
<constraint firstItem="Q5M-cg-NOt" firstAttribute="trailing" secondItem="ZEJ-k9-h9o" secondAttribute="trailing" constant="10" id="x2T-zZ-Prk"/>
</constraints>
<point key="canvasLocation" x="137.68115942028987" y="124.55357142857142"/>
<point key="canvasLocation" x="137.68115942028987" y="123.91304347826087"/>
</view>
</objects>
<resources>
<systemColor name="systemRedColor">
<color red="1" green="0.23137254901960785" blue="0.18823529411764706" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
<image name="camera.rotate" catalog="system" width="128" height="94"/>
<image name="chevron.backward" catalog="system" width="96" height="128"/>
<image name="ear" catalog="system" width="105" height="128"/>
<image name="eye" catalog="system" width="128" height="81"/>
<image name="eye.slash" catalog="system" width="128" height="86"/>
<image name="mic" catalog="system" width="108" height="128"/>
<image name="mic.slash" catalog="system" width="108" height="128"/>
<image name="rotate.right" catalog="system" width="118" height="128"/>
<image name="speaker.wave.2" catalog="system" width="128" height="90"/>
</resources>
</document>