cordova-plugin-trtc/src/ios/VideoCallingViewController.m

421 lines
17 KiB
Objective-C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// VideoCallingViewController.m
// TRTC-API-Example-OC
//
// Created by bluedang on 2021/4/12.
//
/*
实时视频通话功能
TRTC APP 实时视频通话功能
本文件展示如何集成实时视频通话功能
1、切换摄像头 API:[[_trtcCloud getDeviceManager] switchCamera:_isFrontCamera];
2、打开关闭摄像头 API: [self.trtcCloud startLocalPreview:_isFrontCamera view:_localVideoView];
[self.trtcCloud stopLocalPreview];
3、切换听筒与扬声器 API[[_trtcCloud getDeviceManager] setAudioRoute:TXAudioRouteEarpiece];
[[_trtcCloud getDeviceManager] setAudioRoute:TXAudioRouteSpeakerphone];
4、静音当前设备其他人将无法听到该设备的声音 API: [_trtcCloud muteLocalAudio:YES];
参考文档https://cloud.tencent.com/document/product/647/42044
*/
/*
Real-Time Audio Call
TRTC Audio Call
This document shows how to integrate the real-time audio call feature.
1. Switch between the speaker and receiver: [[_trtcCloud getDeviceManager] setAudioRoute:TXAudioRouteSpeakerphone]
2. Mute the device so that others wont hear the audio of the device: [_trtcCloud muteLocalAudio:YES]
3. Display other network and volume information: delegate -> onNetworkQuality, onUserVoiceVolume
Documentation: https://cloud.tencent.com/document/product/647/42046
*/
#import "VideoCallingViewController.h"
#import "TrtcUserInfo.h"
#import "CordovaEventKit.h"
#import "UIView+Toast.h"
#import "Events.h"
#import "UserUpdateListener.h"
static const NSInteger maxRemoteUserNum = 7;
@interface VideoCallingViewController ()<TRTCCloudDelegate>
@property (weak, nonatomic) IBOutlet UIButton *backButton;
@property (weak, nonatomic) IBOutlet UIButton *micButton;
@property (weak, nonatomic) IBOutlet UIButton *spakeButton;
@property (weak, nonatomic) IBOutlet UIButton *camareButton;
@property (weak, nonatomic) IBOutlet UIButton *subVisibleButton;
@property (weak, nonatomic) IBOutlet UIButton *viewRotateButton;
@property (strong, nonatomic) IBOutletCollection(UIView) NSArray *remoteViewArr;
@property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *subViewBtnArr;
@property (strong, nonatomic) IBOutletCollection(UILabel) NSArray *displayLabelArr;
@property (weak, nonatomic) IBOutlet UILabel *displayLabel;
@property (assign, nonatomic) UInt32 roomId;
@property (strong, nonatomic) NSString* userId;
@property(nonatomic, assign) UInt32 sdkAppId;
@property (strong, nonatomic) NSString* userSig;
@property (strong, nonatomic) TRTCCloud *trtcCloud;
@property (strong, nonatomic) NSMutableOrderedSet *remoteUidSet;
@property (strong, nonatomic) NSMutableArray<TrtcUserInfo*> *viewUsers;
@property (assign, nonatomic) BOOL isFrontCamera;
@property (assign, nonatomic) BOOL *hasShareUser;
@property (assign, nonatomic) BOOL *hiddenAllSubView;
@property (assign, nonatomic) NSInteger rotation;
@end
@implementation VideoCallingViewController
static VideoCallingViewController* _self;
+(VideoCallingViewController*)viewController{
return _self;
}
- (TRTCCloud*)trtcCloud {
if (!_trtcCloud) {
_trtcCloud = [TRTCCloud sharedInstance];
}
return _trtcCloud;
}
- (NSMutableOrderedSet<TrtcUserInfo*> *)remoteUidSet {
if (!_remoteUidSet) {
_remoteUidSet = [[NSMutableOrderedSet alloc] initWithCapacity:maxRemoteUserNum];
}
return _remoteUidSet;
}
- (NSMutableArray<TrtcUserInfo*> *)viewUsers {
if (!_viewUsers) {
_viewUsers = [[NSMutableArray alloc] initWithCapacity:maxRemoteUserNum];
}
return _viewUsers;
}
- (instancetype)initWithRoomId:(UInt32)roomId userId:(NSString *)userId appId:(UInt32)appId userSig:(NSString *)userSig{
NSLog(@"TRTC - initWithRoomId:::::");
self = [super initWithNibName:NSStringFromClass([self class]) bundle:nil];
if (self) {
_roomId = roomId;
_userId = userId;
_sdkAppId = appId;
_userSig = userSig;
}
NSLog(@"TRTC - roomid:%d,userID:%@,sdkAppid:%d,userSig:%@",_roomId,_userId,_sdkAppId,_userSig);
_self = self;
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];
self.isFrontCamera = NO;
self.trtcCloud.delegate = self;
[self setupDefaultUIConfig];
[self setupTRTCCloud];
[self.view sendSubviewToBack:self.view];
}
- (void)setupDefaultUIConfig {
NSLog(@"TRTC - setupDefaultUIConfig:::::");
// UIFont*font = [UIFont size:24];
// NSMutableAttributedString *attributedStr = [[NSMutableAttributedString alloc] initWithString:@"\U0000e679" attributes: @{NSFontAttributeName:font}];
// [_backButton setFont:(API_DEPRECATED("Specify an attributed title with a custom font", ios(2.0, 3.0)) UIFont *)]
// [_backButton setAttributedTitle:attributedStr forState:UIControlStateNormal];
// self.backButton.titleLabel.font = ;
[_backButton setTitle:@"\U0000e679" forState:UIControlStateNormal];
[_micButton setTitle:@"\U0000e67a" forState:UIControlStateNormal];
[_micButton setTitle:@"\U0000e658" forState:UIControlStateSelected];
[_spakeButton setTitle:@"\U0000e664" forState:UIControlStateNormal];
[_spakeButton setTitle:@"\U0000e775" forState:UIControlStateSelected];
[_camareButton setTitle:@"\U0000e824" forState:UIControlStateNormal];
[_subVisibleButton setTitle:@"\U0000e695" forState:UIControlStateNormal];
[_subVisibleButton setTitle:@"\U0000e81a" forState:UIControlStateSelected];
[_viewRotateButton setTitle:@"\U0000e657" forState:UIControlStateNormal];
_displayLabel.text = @"";
_displayLabel.hidden = NO;
_rotation = 0;
[Events addListener:@"userinfo.update" listener: [[UserUpdateListener alloc] init] ];
}
- (void)setupTRTCCloud {
[[self remoteUidSet] removeAllObjects];
[self.trtcCloud startLocalPreview:_isFrontCamera view:self.view];
TRTCParams *params = [TRTCParams new];
params.sdkAppId = _sdkAppId;
params.roomId = _roomId;
params.userId = _userId;
params.role = TRTCRoleAnchor;
params.userSig = _userSig;
[self.trtcCloud enterRoom:params appScene:TRTCAppSceneVideoCall];
TRTCVideoEncParam *encParams = [TRTCVideoEncParam new];
encParams.videoResolution = TRTCVideoResolution_640_360;
encParams.videoBitrate = 550;
encParams.videoFps = 15;
[self.trtcCloud setVideoEncoderParam:encParams];
[self.trtcCloud startLocalAudio:TRTCAudioQualityMusic];
}
- (void)dealloc {
[self.trtcCloud exitRoom];
[TRTCCloud destroySharedIntance];
}
- (void)changeUser:(NSInteger) a and:(NSInteger) b{
if(a == b || a < 0 || b < 0){return;}
NSInteger x = a > b ? b : a;
NSInteger y = a > b ? a : b;
if([self remoteUidSet].count > y && x>-1){
// 交换
NSLog(@"TRTC - onSubViewClcik:::::Before change:%@,%@",[[self remoteUidSet][x] personid],[[self remoteUidSet][y] personid]);
TrtcUserInfo* info = [self remoteUidSet][x];
TrtcUserInfo* info2 = [self remoteUidSet][y];
[_remoteUidSet removeObjectAtIndex:x];
[_remoteUidSet setObject:info atIndex: y-1];
[_remoteUidSet insertObject:info2 atIndex:x];
NSLog(@"TRTC - onSubViewClcik:::::after change:%@,%@",[[self remoteUidSet][x] personid],[[self remoteUidSet][y] personid]);
[self refreshRemoteVideoViews];
NSDictionary *event = [[NSDictionary alloc]initWithObjectsAndKeys:
[[NSString alloc] initWithFormat:@"%d",_roomId],@"room",info2.personid,@"userId", nil];
[CordovaEventKit fireEvent:@"onLayoutChangeMessage" obj:event];
}
}
#pragma mark - IBActions
- (IBAction)onSubVisibleChange:(UIButton*)sender {
NSLog(@"TRTC - onSubVisibleChange:::::before:%@",[NSNumber numberWithBool:sender.selected]);
sender.selected = !sender.selected;
NSLog(@"TRTC - onSubVisibleChange:::::after:%@",[NSNumber numberWithBool:sender.selected]);
[self refreshRemoteVideoViews];
}
- (IBAction)onVideoRotate:(UIButton*)sender {
NSLog(@"TRTC - onRouteChange:::::,%@,local index: %ld",[[self remoteUidSet][0] personid],[_viewUsers indexOfObject:_userId]);
TRTCRenderParams *params = [[TRTCRenderParams alloc] init];
params.fillMode = TRTCVideoFillMode_Fit;
_rotation += 1;
_rotation = _rotation > 3 ? 0 : _rotation;
params.rotation = _rotation;
// [_trtcCloud stopRemoteView:[[self viewUsers][0] personid] streamType:TRTCVideoStreamTypeBig];
[_trtcCloud setRemoteRenderParams:[[self remoteUidSet][0] personid] streamType:TRTCVideoStreamTypeBig params:params];
// [_trtcCloud updateRemoteView:self.view streamType:TRTCVideoStreamTypeBig forUser:[[self remoteUidSet][0] personid]];
// [_trtcCloud startRemoteView:[[self viewUsers][0] personid] streamType: TRTCVideoStreamTypeBig view:self.view];
}
- (IBAction)onBackClick:(UIButton*)sender {
NSLog(@"TRTC - onBackClick:::::");
[self.trtcCloud exitRoom];
[TRTCCloud destroySharedIntance];
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)onSwitchCameraClick:(UIButton*)sender {
NSLog(@"TRTC - onSwitchCameraClick:::::");
_isFrontCamera = !_isFrontCamera;
[[_trtcCloud getDeviceManager] switchCamera:_isFrontCamera];
}
- (IBAction)onMicCaptureClick:(UIButton*)sender {
NSLog(@"TRTC - onMicCaptureClick:::::");
sender.selected = !sender.selected;
if ([sender isSelected]) {
[_trtcCloud muteLocalAudio:YES];
} else {
[_trtcCloud muteLocalAudio:NO];
}
}
- (IBAction)onSwitchSpeakerClick:(UIButton*)sender {
NSLog(@"TRTC - onSwitchSpeakerClick:::::");
sender.selected = !sender.selected;
if ([sender isSelected]) {
[[_trtcCloud getDeviceManager] setAudioRoute:TXAudioRouteEarpiece];
} else {
[[_trtcCloud getDeviceManager] setAudioRoute:TXAudioRouteSpeakerphone];
}
}
- (IBAction)onSubViewClcik:(UIButton*)sender {
NSLog(@"TRTC - onSubViewClcik:::::button");
NSInteger index = [_subViewBtnArr indexOfObject:sender];
if (index == NSNotFound) {return;}
index = index + 1;
[self changeUser:0 and:index];
}
#pragma mark - TRTCCloud Delegate
- (void)onEnterRoom:(NSInteger) result{
NSLog(@"TRTC - onEnterRoom, %ld",result);
[_trtcCloud startLocalPreview:_isFrontCamera view:self.view];
// 添加本地用户到用户列表
TrtcUserInfo *info = [[TrtcUserInfo alloc] initWithPersonid:_userId];
[info setLocal:YES];
NSInteger index = [[self remoteUidSet] indexOfObject:info];
if (index != NSNotFound) {
return;
} else {
[[self remoteUidSet] addObject:info];
}
NSDictionary *event = [[NSDictionary alloc]initWithObjectsAndKeys:
[[NSString alloc] initWithFormat:@"%d",_roomId],@"room",_userId,@"userId", nil];
[CordovaEventKit fireEvent:@"onLayoutChangeMessage" obj:event];
}
- (void)onUserVideoAvailable:(NSString *)userId available:(BOOL)available {
NSLog(@"TRTC - onUserVideoAvailable, user:%@,available%@",userId, available ? @"YES":@"NO");
// 添加远端用户到用户列表
TrtcUserInfo *info = [[TrtcUserInfo alloc] initWithPersonid:userId];
NSInteger index = [[self remoteUidSet] indexOfObject:info];
if (available) {
if (index != NSNotFound) { return; }
if([info isShareUser]){
_hasShareUser = YES;
}
[[self remoteUidSet] addObject:info];
} else {
if (index == NSNotFound) { return; }
if([info isShareUser]){
_hasShareUser = NO;
_hiddenAllSubView = NO;
}
[_trtcCloud stopRemoteView:userId streamType:TRTCVideoStreamTypeSmall];
[[self remoteUidSet] removeObject:userId];
}
[self refreshRemoteVideoViews];
if(_hasShareUser){
// 切换分享屏幕到主窗口
[self changeUser:0 and:[[self remoteUidSet] indexOfObject:info]];
// 隐藏所有子窗口
_hiddenAllSubView = YES;
[self refreshRemoteVideoViews];
// [_trtcCloud stopLocalPreview];
}
NSDictionary *event = @{@"room": [[NSString alloc] initWithFormat:@"%d", _roomId], @"userId": userId, @"available": [NSNumber numberWithBool:available]};
[CordovaEventKit fireEvent:@"onUserVideoAvailable" obj:event];
}
- (void)refreshRemoteVideoViews {
NSLog(@"TRTC - refreshRemoteVideoViews:%ld",_remoteViewArr.count);
_subVisibleButton.hidden = _hasShareUser != nil;
_viewRotateButton.hidden = _hasShareUser == nil;
_viewRotateButton.enabled = !_viewRotateButton.hidden;
for (int i = 0; i <= _remoteViewArr.count; i++) {
TrtcUserInfo* nUser = [self remoteUidSet].count > i ? [self remoteUidSet][i] : nil;
TrtcUserInfo* oUser = [self viewUsers].count > i ? [self viewUsers][i] : nil;
UIView* view = i == 0 ? self.view : _remoteViewArr[i-1];
UILabel* label = i ==0 ? _displayLabel : _displayLabelArr[i-1];
UIButton* btn = i ==0 ? nil : _subViewBtnArr[i-1];
NSLog(@"TRTC - refreshRemoteVideoViews - new : %@, o: %@",nUser == nil ? nil : [nUser personid],oUser == nil ? nil : [oUser personid]);
if((_hiddenAllSubView || ![_subVisibleButton isSelected]) && i!=0){
[view setHidden:YES];
[label setHidden:YES];
}else{
if(nUser != nil){
if([nUser isEqual:oUser] && ![view isHidden]){
if([nUser isLocalUser]){
[label setText:@""];
} else if([nUser displayName] == nil || [nUser displayName].length == 0) {
[label setText:[NSString stringWithFormat:@"%@%@",[nUser personid], [nUser isShareUser] ? @"的屏幕分享" : @""]];
} else {
[label setText:[NSString stringWithFormat:@"%@%@",[nUser displayName], [nUser isShareUser] ? @"的屏幕分享" : @""]];
}
[label sizeToFit];
continue;
}
TRTCRenderParams *params = [[TRTCRenderParams alloc] init];
params.rotation = 0;
params.fillMode = [nUser isShareUser] ? TRTCVideoFillMode_Fit : TRTCVideoFillMode_Fill;
if([nUser isLocalUser]){
[_trtcCloud startLocalPreview:_isFrontCamera view:view];
[_trtcCloud setLocalRenderParams:params];
[label setText:@""];
[label sizeToFit];
} else {
[_trtcCloud setRemoteRenderParams:[nUser personid] streamType:i == 0 ? TRTCVideoStreamTypeBig : TRTCVideoStreamTypeSmall params:params];
[_trtcCloud startRemoteView:[nUser personid] streamType:i == 0 ? TRTCVideoStreamTypeBig : TRTCVideoStreamTypeSmall view:view];
if([nUser displayName] == nil || [nUser displayName].length == 0) {
[label setText:[NSString stringWithFormat:@"%@%@",[nUser personid], [nUser isShareUser] ? @"的屏幕分享" : @""]];
} else {
[label setText:[NSString stringWithFormat:@"%@%@",[nUser displayName], [nUser isShareUser] ? @"的屏幕分享" : @""]];
}
[label sizeToFit];
}
[label setHidden:NO];
[view setHidden:NO];
if(btn != nil){
[btn setHidden:NO];
}
} else {
[view setHidden:YES];
[label setHidden:YES];
if(btn != nil){
[btn setHidden:YES];
}
}
}
if(nUser != nil){
[self viewUsers].count > i ? [self viewUsers][i] = nUser : [[self viewUsers] addObject:nUser];
}else {
while([self viewUsers].count > i){
[[self viewUsers] removeObjectAtIndex:i];
}
}
}
}
- (void) onError:(TXLiteAVError)errCode errMsg:(NSString *)errMsg extInfo:(NSDictionary *)extInfo{
NSLog(@"TRTC - onError::sdk callback onError code: %d,msg: %@,extInfo: %@",errCode,errMsg,extInfo);
dispatch_async(dispatch_get_main_queue(), ^{
[self.view makeToast: [[NSString alloc] initWithFormat:@"%@[%d]",errMsg,errCode]];
});
// [self.trtcCloud exitRoom];
// [TRTCCloud destroySharedIntance];
// [self dismissViewControllerAnimated:YES completion:nil];
}
- (void) onExitRoom:(NSInteger)reason{
if (reason == 2) {
dispatch_async(dispatch_get_main_queue(), ^{
[self.view makeToast: @"远程协助已结束"];
});
}
[self dismissViewControllerAnimated:YES completion:nil];
}
@end