// // VideoChatVC.m // BuguLive // // Created by Kylin on 2024/12/3. // Copyright © 2024 xfg. All rights reserved. // #import "VideoChatVC.h" #import "AudioChatTool.h" typedef void(^IsNormalChatBlock)(BOOL isNormal); @interface VideoChatVC () @property (nonatomic,strong) UIImageView * headerImgV; @property (nonatomic,strong) UILabel * nicknameLabel; @property (nonatomic,strong) UILabel * timesLabel; @property (nonatomic,strong) TRTCCloud * trtcCloud; @property (nonatomic,strong) UILabel * tipLabel; //****************** 通话中View ****************** @property (nonatomic,strong) UIView * chatBotoomView; @property (nonatomic,strong) UIButton * maikefengButton; @property (nonatomic,strong) UILabel * maikefengLabel; //呼叫中,摄像头翻转 @property (nonatomic,strong) UIButton * callingCameraSwitchButton; @property (nonatomic,strong) UILabel * callingCameraSwitchLabel; //通话中、呼叫中,摄像头开关 @property (nonatomic,strong) UIButton * chatingCameraOpenButton; @property (nonatomic,strong) UILabel * chatingCameraOpenLabel; //通话中,扬声器开关 @property (nonatomic,strong) UIButton * yangshengqiButton; @property (nonatomic,strong) UILabel * yangshengqiLabel; //通话中,摄像头翻转 @property (nonatomic,strong) UIButton * chatingCameraSwitchButton; //通话中,挂断按钮 @property (nonatomic,strong) UIButton * closeButton; @property (nonatomic,assign) int timesCount; //****************** 接听中View ****************** @property (nonatomic,strong) UIView * receiveBottomView; //摄像头翻转按钮及提示 @property (nonatomic,strong) UIButton * receivingCameraSwitchButton; @property (nonatomic,strong) UILabel * receivingCameraSwitchLabel; //接听中,摄像头开关 @property (nonatomic,strong) UIButton * receivingCameraOpenButton; @property (nonatomic,strong) UILabel * receivingCameraOpenLabel; //接听中,挂断按钮 @property (nonatomic,strong) UIButton * receivingCloseButton; //接听中,接听按钮 @property (nonatomic,strong) UIButton * receivingReceiveButton; @property(nonatomic,strong)AVAudioPlayer *player;//播放 @property (nonatomic,assign) int lastMin; @property (nonatomic,strong) UIView * smallPreviewView; @property (nonatomic,strong) UIView * bigPreviewView; @property (nonatomic,copy) IsNormalChatBlock isNormalChatBlock; @end @implementation VideoChatVC static dispatch_once_t onceToken; static VideoChatVC *_voiceRoomVC; + (instancetype)shareVoiceRoomVC{ dispatch_once(&onceToken, ^{ _voiceRoomVC = [[VideoChatVC alloc] init]; }); return _voiceRoomVC; } /**销毁房间*/ + (void)destoryShareRootVC { /**更新打开房间的状态*/ AppDelegate.sharedAppDelegate.isInAudioVideoChatVc = NO; // app.showRoomVc = NO; // app.IsInVoiceRoom = NO; NSLog(@"房间销毁了。。。。。。。。。。。1"); /**离开房间*/ // [[TMRoomMsgManager sharedRoomMsgManager] leaveRoomSendMessage]; // [[TMRoomManager sharedInstance] leavingRoom:^(AgoraChannelStats * _Nonnull stat) {}]; // [TMRoomManager destroySharedInstance]; // /**销毁消息*/ // [TMRoomMsgManager destoryRoomMsgManager]; // [_voiceRoomVC logoutGame]; [VideoChatVC.shareVoiceRoomVC closeVoiceRoom]; onceToken = 0; _voiceRoomVC = nil; NSLog(@"房间销毁了。。。。。。。。。。。2"); } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; self.navigationController.navigationBar.hidden = YES; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; self.navigationController.navigationBar.hidden = NO; } - (void)viewDidLoad { [super viewDidLoad]; AppDelegate.sharedAppDelegate.isInAudioVideoChatVc = YES; self.lastMin = -1; //基础UI [self initChatBaseUI]; // 音量监听 [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(volumeChanged:) name:@"AVSystemController_SystemVolumeDidChangeNotification" object:nil]; [[NSNotificationCenter defaultCenter] postNotificationName:@"MSG_VIDEO_LINE_CALL" object:nil]; } - (void)initChatBaseUI { // UIImageView * bgImgV = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)]; // bgImgV.image = [UIImage imageNamed:@"audioChatbgicon"]; // [self.view addSubview:bgImgV]; _bigPreviewView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)]; [self.view addSubview:self.bigPreviewView]; _smallPreviewView = [[UIView alloc] initWithFrame:CGRectMake(SCREEN_WIDTH - 120 - 20, NavigationHeight + 30, 120, 160)]; self.smallPreviewView.hidden = YES; self.smallPreviewView.layer.cornerRadius = 10; self.smallPreviewView.layer.masksToBounds = YES; self.smallPreviewView.backgroundColor = UIColor.blackColor; [self.view addSubview:self.smallPreviewView]; UIButton * backVerticalBtn = [[UIButton alloc]initWithFrame:CGRectMake(15,StatusBarHeight, 44, 44)]; [backVerticalBtn setImage:[UIImage imageNamed:@"audioChatSmallIcon"] forState:UIControlStateNormal]; [backVerticalBtn addTarget:self action:@selector(backBtnClick) forControlEvents:UIControlEventTouchUpInside]; // [self.view addSubview:backVerticalBtn]; _timesLabel = [[UILabel alloc] initWithFrame:CGRectMake(60, 0, SCREEN_WIDTH - 120, 30)]; self.timesLabel.centerY = backVerticalBtn.centerY; self.timesLabel.textAlignment = NSTextAlignmentCenter; self.timesLabel.textColor = UIColor.whiteColor; self.timesLabel.font = [UIFont boldSystemFontOfSize:16]; self.timesLabel.text = @"00:00"; self.timesLabel.hidden = YES; [self.view addSubview:self.timesLabel]; _headerImgV = [[UIImageView alloc] initWithFrame:CGRectMake((SCREEN_WIDTH - 90)/2, NavigationHeight + 133, 90, 90)]; self.headerImgV.layer.cornerRadius = 10; self.headerImgV.layer.masksToBounds = YES; [self.headerImgV sd_setImageWithURL:[NSURL URLWithString:self.mChatFriend.mHead_image] placeholderImage:kDefaultPreloadHeadImg]; [self.view addSubview:self.headerImgV]; _nicknameLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.headerImgV.bottom + 10, SCREEN_WIDTH, 30)]; self.nicknameLabel.textAlignment = NSTextAlignmentCenter; self.nicknameLabel.textColor = UIColor.whiteColor; self.nicknameLabel.font = [UIFont boldSystemFontOfSize:21]; self.nicknameLabel.text = self.mChatFriend.mNick_name; [self.view addSubview:self.nicknameLabel]; #pragma mark - 接听中UI _receiveBottomView = [[UIView alloc] initWithFrame:CGRectMake(0, SCREEN_HEIGHT - SafeAreaBottomHeight - 20 - 180, SCREEN_WIDTH, 180)]; // self.receiveBottomView.layer.borderColor = UIColor.redColor.CGColor; // self.receiveBottomView.layer.borderWidth = 1; self.receiveBottomView.hidden = YES; [self.view addSubview:self.receiveBottomView]; //摄像头翻转 _receivingCameraSwitchButton = [UIButton buttonWithType:UIButtonTypeCustom]; self.receivingCameraSwitchButton.frame = CGRectMake(30, 0, 70, 70); [self.receivingCameraSwitchButton setBackgroundImage:[UIImage imageNamed:@"receivingCameraSwitchIcon"] forState:UIControlStateNormal]; [self.receiveBottomView addSubview:self.receivingCameraSwitchButton]; [self.receivingCameraSwitchButton addTarget:self action:@selector(receivingCameraSwitchButtonClick) forControlEvents:UIControlEventTouchUpInside]; _receivingCameraSwitchLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.receivingCameraSwitchButton.bottom + 10, SCREEN_WIDTH/3, 20)]; self.receivingCameraSwitchLabel.centerX = self.receivingCameraSwitchButton.centerX; self.receivingCameraSwitchLabel.textAlignment = NSTextAlignmentCenter; self.receivingCameraSwitchLabel.font = [UIFont systemFontOfSize:16]; self.receivingCameraSwitchLabel.textColor = [UIColor colorWithHex:0x999999]; self.receivingCameraSwitchLabel.text = ASLocalizedString(@"摄像头翻转"); [self.receiveBottomView addSubview:self.receivingCameraSwitchLabel]; //摄像头开关 _receivingCameraOpenButton = [UIButton buttonWithType:UIButtonTypeCustom]; self.receivingCameraOpenButton.frame = CGRectMake(SCREEN_WIDTH - 70 - 30, 0, 70, 70); [self.receivingCameraOpenButton setBackgroundImage:[UIImage imageNamed:@"receivingCameraOpen"] forState:UIControlStateNormal]; [self.receivingCameraOpenButton setBackgroundImage:[UIImage imageNamed:@"receivingCameraClose"] forState:UIControlStateSelected]; [self.receiveBottomView addSubview:self.receivingCameraOpenButton]; [self.receivingCameraOpenButton addTarget:self action:@selector(receivingCameraOpenButtonClick) forControlEvents:UIControlEventTouchUpInside]; _receivingCameraOpenLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.receivingCameraOpenButton.bottom + 10, SCREEN_WIDTH/3, 20)]; self.receivingCameraOpenLabel.centerX = self.receivingCameraOpenButton.centerX; self.receivingCameraOpenLabel.textAlignment = NSTextAlignmentCenter; self.receivingCameraOpenLabel.font = [UIFont systemFontOfSize:16]; self.receivingCameraOpenLabel.textColor = [UIColor colorWithHex:0x999999]; self.receivingCameraOpenLabel.text = ASLocalizedString(@"摄像头已开"); [self.receiveBottomView addSubview:self.receivingCameraOpenLabel]; //挂断 _receivingCloseButton = [UIButton buttonWithType:UIButtonTypeCustom]; self.receivingCloseButton.frame = CGRectMake(self.receivingCameraSwitchButton.left, 0, 70, 70); self.receivingCloseButton.bottom = self.receiveBottomView.height; [self.receivingCloseButton setBackgroundImage:[UIImage imageNamed:@"audioclosebtnbg"] forState:UIControlStateNormal]; [self.receiveBottomView addSubview:self.receivingCloseButton]; [self.receivingCloseButton addTarget:self action:@selector(receiveCloseButtonClick) forControlEvents:UIControlEventTouchUpInside]; //接听 _receivingReceiveButton = [UIButton buttonWithType:UIButtonTypeCustom]; self.receivingReceiveButton.frame = CGRectMake(SCREEN_WIDTH - 30 - 70, self.receivingCloseButton.top, 70, 70); [self.receivingReceiveButton setBackgroundImage:[UIImage imageNamed:@"audioreceivebtnbg"] forState:UIControlStateNormal]; [self.receiveBottomView addSubview:self.receivingReceiveButton]; [self.receivingReceiveButton addTarget:self action:@selector(receivingReceiveButtonClick) forControlEvents:UIControlEventTouchUpInside]; #pragma mark - 通话中UI、呼叫中UI _chatBotoomView = [[UIView alloc] initWithFrame:CGRectMake(0, SCREEN_HEIGHT - SafeAreaBottomHeight - 180 - 20, SCREEN_WIDTH, 180)]; // self.chatBotoomView.layer.borderColor = UIColor.redColor.CGColor; // self.chatBotoomView.layer.borderWidth = 1; self.chatBotoomView.hidden = YES; [self.view addSubview:self.chatBotoomView]; //呼叫中,摄像头翻转 _callingCameraSwitchButton = [UIButton buttonWithType:UIButtonTypeCustom]; self.callingCameraSwitchButton.frame = CGRectMake(30, 0, 70, 70); [self.callingCameraSwitchButton setBackgroundImage:[UIImage imageNamed:@"receivingCameraSwitchIcon"] forState:UIControlStateNormal]; [self.chatBotoomView addSubview:self.callingCameraSwitchButton]; [self.callingCameraSwitchButton addTarget:self action:@selector(receivingCameraSwitchButtonClick) forControlEvents:UIControlEventTouchUpInside]; _callingCameraSwitchLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.callingCameraSwitchButton.bottom + 10, SCREEN_WIDTH/3, 20)]; self.callingCameraSwitchLabel.centerX = self.callingCameraSwitchButton.centerX; self.callingCameraSwitchLabel.textAlignment = NSTextAlignmentCenter; self.callingCameraSwitchLabel.font = [UIFont systemFontOfSize:16]; self.callingCameraSwitchLabel.textColor = [UIColor colorWithHex:0x999999]; self.callingCameraSwitchLabel.text = ASLocalizedString(@"摄像头翻转"); [self.chatBotoomView addSubview:self.callingCameraSwitchLabel]; //通话中,麦克风按钮 _maikefengButton = [UIButton buttonWithType:UIButtonTypeCustom]; self.maikefengButton.frame = CGRectMake(30, 0, 70, 70); [self.maikefengButton setBackgroundImage:[UIImage imageNamed:@"maikefengopen"] forState:UIControlStateNormal]; [self.maikefengButton setBackgroundImage:[UIImage imageNamed:@"maikefengclose"] forState:UIControlStateSelected]; [self.chatBotoomView addSubview:self.maikefengButton]; [self.maikefengButton addTarget:self action:@selector(maikeFengButtonClick) forControlEvents:UIControlEventTouchUpInside]; _maikefengLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.maikefengButton.bottom + 10, SCREEN_WIDTH/3, 20)]; self.maikefengLabel.centerX = self.maikefengButton.centerX; self.maikefengLabel.textAlignment = NSTextAlignmentCenter; self.maikefengLabel.font = [UIFont systemFontOfSize:16]; self.maikefengLabel.textColor = [UIColor colorWithHex:0x999999]; self.maikefengLabel.text = ASLocalizedString(@"麦克风已开启"); [self.chatBotoomView addSubview:self.maikefengLabel]; self.maikefengLabel.hidden = self.maikefengButton.hidden = YES; //通话中,扬声器开关 _yangshengqiButton = [UIButton buttonWithType:UIButtonTypeCustom]; self.yangshengqiButton.frame = CGRectMake(0, self.maikefengButton.top, 70, 70); self.yangshengqiButton.centerX = self.chatBotoomView.width/2.0; [self.yangshengqiButton setBackgroundImage:[UIImage imageNamed:@"yangshengqiclose"] forState:UIControlStateNormal]; [self.yangshengqiButton setBackgroundImage:[UIImage imageNamed:@"yangshengqiopen"] forState:UIControlStateSelected]; [self.chatBotoomView addSubview:self.yangshengqiButton]; [self.yangshengqiButton addTarget:self action:@selector(yangshengqiButtonClick) forControlEvents:UIControlEventTouchUpInside]; _yangshengqiLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.maikefengButton.bottom + 10, SCREEN_WIDTH/3, 20)]; self.yangshengqiLabel.centerX = self.yangshengqiButton.centerX; self.yangshengqiLabel.textAlignment = NSTextAlignmentCenter; self.yangshengqiLabel.font = [UIFont systemFontOfSize:16]; self.yangshengqiLabel.textColor = [UIColor colorWithHex:0x999999]; self.yangshengqiLabel.text = ASLocalizedString(@"扬声器已关"); [self.chatBotoomView addSubview:self.yangshengqiLabel]; self.yangshengqiLabel.hidden = self.yangshengqiButton.hidden = YES; //通话中,摄像头开关 _chatingCameraOpenButton = [UIButton buttonWithType:UIButtonTypeCustom]; self.chatingCameraOpenButton.frame = CGRectMake(SCREEN_WIDTH - 70 - 30, self.maikefengButton.top, 70, 70); [self.chatingCameraOpenButton setBackgroundImage:[UIImage imageNamed:@"receivingCameraOpen"] forState:UIControlStateNormal]; [self.chatingCameraOpenButton setBackgroundImage:[UIImage imageNamed:@"receivingCameraClose"] forState:UIControlStateSelected]; [self.chatBotoomView addSubview:self.chatingCameraOpenButton]; [self.chatingCameraOpenButton addTarget:self action:@selector(receivingCameraOpenButtonClick) forControlEvents:UIControlEventTouchUpInside]; _chatingCameraOpenLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.chatingCameraOpenButton.bottom + 10, SCREEN_WIDTH/3, 20)]; self.chatingCameraOpenLabel.centerX = self.chatingCameraOpenButton.centerX; self.chatingCameraOpenLabel.textAlignment = NSTextAlignmentCenter; self.chatingCameraOpenLabel.font = [UIFont systemFontOfSize:16]; self.chatingCameraOpenLabel.textColor = [UIColor colorWithHex:0x999999]; self.chatingCameraOpenLabel.text = ASLocalizedString(@"摄像头已开"); [self.chatBotoomView addSubview:self.chatingCameraOpenLabel]; //通话中,挂断按钮 _closeButton = [UIButton buttonWithType:UIButtonTypeCustom]; self.closeButton.frame = CGRectMake(0, 0, 70, 70); self.closeButton.bottom = self.chatBotoomView.height; self.closeButton.centerX = self.chatBotoomView.width/2.0; [self.closeButton setBackgroundImage:[UIImage imageNamed:@"audioclosebtnbg"] forState:UIControlStateNormal]; [self.chatBotoomView addSubview:self.closeButton]; [self.closeButton addTarget:self action:@selector(closeButtonClick) forControlEvents:UIControlEventTouchUpInside]; //通话中,摄像头翻转 _chatingCameraSwitchButton = [UIButton buttonWithType:UIButtonTypeCustom]; self.chatingCameraSwitchButton.frame = CGRectMake(0, 0, 44, 44); self.chatingCameraSwitchButton.centerX = self.chatingCameraOpenButton.centerX; self.chatingCameraSwitchButton.centerY = self.closeButton.centerY; [self.chatingCameraSwitchButton setBackgroundImage:[UIImage imageNamed:@"chatingCameraSwitchIcon"] forState:UIControlStateNormal]; [self.chatBotoomView addSubview:self.chatingCameraSwitchButton]; [self.chatingCameraSwitchButton addTarget:self action:@selector(receivingCameraSwitchButtonClick) forControlEvents:UIControlEventTouchUpInside]; self.chatingCameraSwitchButton.hidden = YES; _tipLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.chatBotoomView.top - 60, SCREEN_WIDTH, 30)]; self.tipLabel.textAlignment = NSTextAlignmentCenter; self.tipLabel.textColor = UIColor.whiteColor; self.tipLabel.font = [UIFont systemFontOfSize:16]; self.tipLabel.text = ASLocalizedString(@"邀请你视频通话"); self.tipLabel.textColor = [UIColor colorWithHex:0x999999]; self.tipLabel.hidden = YES; [self.view addSubview:self.tipLabel]; } #pragma mark - 接听中,点击事件 //接听中,摄像头翻转 - (void)receivingCameraSwitchButtonClick { self.receivingCameraSwitchButton.selected = !self.receivingCameraSwitchButton.isSelected; [[self.trtcCloud getDeviceManager] switchCamera:self.receivingCameraSwitchButton.isSelected]; } //接听中,摄像头开关 - (void)receivingCameraOpenButtonClick { self.receivingCameraOpenButton.selected = !self.receivingCameraOpenButton.isSelected; self.chatingCameraOpenButton.selected = self.receivingCameraOpenButton.isSelected; if (self.receivingCameraOpenButton.isSelected) { self.receivingCameraOpenLabel.text = ASLocalizedString(@"摄像头已关"); self.chatingCameraOpenLabel.text = ASLocalizedString(@"摄像头已关"); [self.trtcCloud stopLocalPreview]; } else { self.receivingCameraOpenLabel.text = ASLocalizedString(@"摄像头已开"); self.chatingCameraOpenLabel.text = ASLocalizedString(@"摄像头已开"); [self.trtcCloud startLocalPreview:YES view:self.bigPreviewView]; } } //是否接听,接听 - (void)receivingReceiveButtonClick { WeakSelf self.isNormalChatBlock = ^(BOOL isNormal) { if (isNormal) { [weakSelf receiveChatSendMsg]; return; } [VideoChatVC destoryShareRootVC]; }; [self askChatIsNormal]; } - (void)receiveChatSendMsg { WeakSelf SIMMsgObj *obj = [self.mChatFriend sendCustomCallVideoTextMsg:@"接听者,接听语音通话" callAudioType:AudioChatType_receive isCall:self.isZhuDongCall block:^(SResBase *resb, SIMMsgObj *newObj) { if (!resb.msuccess) { [SVProgressHUD showErrorWithStatus:resb.mmsg]; } else { //发送成功了,修改UI [weakSelf joinChannel:[NSString stringWithFormat:@"%d",self.mChatFriend.mUser_id]]; weakSelf.tipLabel.hidden = YES; weakSelf.chatBotoomView.hidden = NO; weakSelf.receiveBottomView.hidden = YES; [weakSelf reloadDataWithType:(AudioChatType_receive)]; [weakSelf.player stop]; } }]; } //是否接听,挂断通话 - (void)receiveCloseButtonClick { WeakSelf SIMMsgObj *obj = [self.mChatFriend sendCustomCallVideoTextMsg:@"接听者,挂断语音通话" callAudioType:AudioChatType_beidongClose isCall:self.isZhuDongCall block:^(SResBase *resb, SIMMsgObj *newObj) { if (!resb.msuccess) { [SVProgressHUD showErrorWithStatus:resb.mmsg]; } else { //发送成功了,直接挂断销毁视图 if (self.timesCount > 0) { if ([AudioChatTool.shareInstance.delegate respondsToSelector:@selector(sendTimes:)]){ [AudioChatTool.shareInstance.delegate sendTimes:[NSString stringWithFormat:@"%@%@",ASLocalizedString(@"视频通话时间:"), self.timesLabel.text]]; } } [VideoChatVC destoryShareRootVC]; } }]; } #pragma mark - 通话中点击事件 - (void)maikeFengButtonClick { self.maikefengButton.selected = !self.maikefengButton.isSelected; if (self.maikefengButton.isSelected) { self.maikefengLabel.text = ASLocalizedString(@"麦克风已关闭"); } else { self.maikefengLabel.text = ASLocalizedString(@"麦克风已开启"); } [self setIsMute:self.maikefengButton.isSelected]; } - (void)closeButtonClick { WeakSelf SIMMsgObj *obj = [self.mChatFriend sendCustomCallVideoTextMsg:@"发起者挂断视频通话" callAudioType:AudioChatType_zhudongClose isCall:self.isZhuDongCall block:^(SResBase *resb, SIMMsgObj *newObj) { if (!resb.msuccess) { [SVProgressHUD showErrorWithStatus:resb.mmsg]; } else { if (self.timesCount > 0) { if ([AudioChatTool.shareInstance.delegate respondsToSelector:@selector(sendTimes:)]){ [AudioChatTool.shareInstance.delegate sendTimes:[NSString stringWithFormat:@"%@%@",ASLocalizedString(@"视频通话时间:"), self.timesLabel.text]]; } } //发送成功了,直接挂断销毁视图 [VideoChatVC destoryShareRootVC]; } }]; } - (void)yangshengqiButtonClick { self.yangshengqiButton.selected = !self.yangshengqiButton.isSelected; if (self.yangshengqiButton.isSelected) { self.yangshengqiLabel.text = ASLocalizedString(@"扬声器已开"); } else { self.yangshengqiLabel.text = ASLocalizedString(@"扬声器已关"); } [self openYangshengqi:self.yangshengqiButton.isSelected]; } - (void)backBtnClick { //暂时直接退出,小屏先不考虑 [VideoChatVC destoryShareRootVC]; return; WeakSelf [[self getPresentingViewController] dismissViewControllerAnimated:YES completion:^{ [weakSelf dissmissWithSmallRoom]; }]; } - (void)closeVoiceRoom { [self.navigationController dismissViewControllerAnimated:YES completion:^{ }]; [self.trtcCloud exitRoom]; [TRTCCloud destroySharedInstance]; } - (UIViewController *)getPresentingViewController { NSLog(@"%s ---- %@",__FUNCTION__,self.presentingViewController); return self.presentingViewController ? self.presentingViewController : self; } #pragma mark /**最小化房间*/ - (void)dissmissWithSmallRoom { // self.hasSmallRoomView = YES; // __block AppDelegate *app = (AppDelegate *)[[UIApplication sharedApplication] delegate]; // app.hasSmallRoomView = YES; // app.IsInVoiceRoom = YES; // TMSmallRoomView * smallRoomView = [TMSmallRoomView sharedInstance]; // [smallRoomView updateUIWithData:self.roomDataModel.homeInfo]; // [smallRoomView show]; // @weakify(self) // [smallRoomView setEnterClickBlock:^{ // @strongify(self) // self.hasSmallRoomView = NO; // app.showRoomVc = YES; // app.hasSmallRoomView = NO; // app.IsInVoiceRoom = YES; // UIWindow *window = [UIApplication sharedApplication].keyWindow; // UINavigationController * nav = [[UINavigationController alloc] initWithRootViewController:[TMVoiceRoomVC shareVoiceRoomVC]]; // nav.modalPresentationStyle = UIModalPresentationOverFullScreen; // nav.modalTransitionStyle = UIModalTransitionStyleCoverVertical; // [window.rootViewController presentViewController:nav animated:YES completion:^{}]; // }]; // [smallRoomView setEndClickBlock:^{ // @strongify(self) // self.hasSmallRoomView = NO; // app.hasSmallRoomView = NO; // }]; } #pragma mark - ******************* 通话中,数据交互,通过消息来判断逻辑进程 ******************* - (void)reloadDataWithType:(AudioChatType)chatType { //1、请求语音通话,A给B发 B收到请求也要走这里判断,改变UI if (chatType == AudioChatType_call) { //发起者 if (self.isZhuDongCall) { self.receiveBottomView.hidden = YES; self.chatBotoomView.hidden = NO; self.tipLabel.hidden = NO; self.tipLabel.text = ASLocalizedString(@"等待对方接受邀请..."); [self startPreviewWithView:self.bigPreviewView]; return; } //接收者 self.receiveBottomView.hidden = NO; self.chatBotoomView.hidden = YES; self.tipLabel.hidden = NO; self.tipLabel.text = ASLocalizedString(@"邀请你视频通话"); [self startPreviewWithView:self.bigPreviewView]; [self playRecordWithName:@"phone_ringing" type:@"mp3" playCount:-1]; return; } //2、接收者接听通话(B给A发) if (chatType == AudioChatType_receive) { self.smallPreviewView.hidden = NO; [self.trtcCloud startRemoteView:[NSString stringWithFormat:@"%d",self.mChatFriend.mUser_id] streamType:TRTCVideoStreamTypeBig view:self.smallPreviewView]; if (self.isZhuDongCall) { [self joinChannel:[IMAPlatform sharedInstance].host.userId]; } self.receiveBottomView.hidden = YES; self.headerImgV.hidden = YES; self.nicknameLabel.hidden = YES; self.chatBotoomView.hidden = NO; self.tipLabel.hidden = YES; self.callingCameraSwitchButton.hidden = self.callingCameraSwitchLabel.hidden = YES; self.maikefengLabel.hidden = self.maikefengButton.hidden = self.yangshengqiLabel.hidden = self.yangshengqiButton.hidden = self.chatingCameraSwitchButton.hidden = NO; //开始计时,执行计费逻辑 self.timesCount = 0; [self updateTimesLabelText]; self.timesLabel.hidden = NO; return; } // /** 3、挂断通话,发起者主动挂断,A给B发 */ if (chatType == AudioChatType_zhudongClose) { [VideoChatVC destoryShareRootVC]; [self playRecordWithName:@"close" type:@"wav" playCount:0]; return; } /** 4、挂断电话,接收者挂断,B给A发 */ if (chatType == AudioChatType_beidongClose) { //接收者挂断电话,直接结束通话 [self playRecordWithName:@"close" type:@"wav" playCount:0]; [VideoChatVC destoryShareRootVC]; return; } /** 5、挂断电话,接收者忙线中,语音中或者在直播间中,B给A发 */ if (chatType == AudioChatType_isBusy) { [[BGHUDHelper sharedInstance] tipMessage:ASLocalizedString(@"对方忙")]; [self playRecordWithName:@"close" type:@"wav" playCount:0]; //刚开始就挂断,太快了,给SDK一点反应时间,晚点再销毁,不然trtc销毁不掉 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [VideoChatVC destoryShareRootVC]; }); return; } /** 6、主动询问A是否在房间等着B通话,B给A发 */ if (chatType == AudioChatType_askIsNormal) { if (self.isZhuDongCall == NO) { return; } //告诉A自己正常,正常进行通话 WeakSelf SIMMsgObj *obj = [self.mChatFriend sendCustomCallVideoTextMsg:@"发起者挂断语音通话" callAudioType:AudioChatType_notificationChatNormal isCall:self.isZhuDongCall block:^(SResBase *resb, SIMMsgObj *newObj) { if (!resb.msuccess) { [SVProgressHUD showErrorWithStatus:resb.mmsg]; } }]; return; } } - (void)updateTimesLabelText { if (AppDelegate.sharedAppDelegate.isInAudioVideoChatVc == NO) { return; } self.timesCount ++; int hour = self.timesCount/60/60; NSString * hoursStr = @"00"; if (hour > 9) { hoursStr = [NSString stringWithFormat:@"%d",hour]; } else { hoursStr = [NSString stringWithFormat:@"0%d",hour]; } int min = self.timesCount/60%60; if (self.isZhuDongCall && min > self.lastMin) { [self requestPay]; } self.lastMin = min; NSString * minStr = @"00"; if (min > 9) { minStr = [NSString stringWithFormat:@"%d",min]; } else { minStr = [NSString stringWithFormat:@"0%d",min]; } int seconds = self.timesCount%60; NSString * secondsStr = @"00"; if (seconds > 9) { secondsStr = [NSString stringWithFormat:@"%d",seconds]; } else { secondsStr = [NSString stringWithFormat:@"0%d",seconds]; } if (hour > 0) { self.timesLabel.text = [NSString stringWithFormat:@"%@:%@:%@",hoursStr,minStr,secondsStr]; } else { self.timesLabel.text = [NSString stringWithFormat:@"%@:%@",minStr,secondsStr]; } dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self updateTimesLabelText]; }); } #pragma mark - 私聊付费,发起者调用 语音跟视频聊天为1分钟调用一次调用成功继续进行聊天,返回失败则直接断开,发起者进行调用 - (void)requestPay { NSMutableDictionary *parmDict = [[NSMutableDictionary alloc] init]; [parmDict setObject:@"user" forKey:@"ctl"]; [parmDict setObject:@"chat_charging" forKey:@"act"]; [parmDict setObject:@(self.mChatFriend.mUser_id) forKey:@"other_user_id"]; [parmDict setObject:@"video_price" forKey:@"expend_type"]; [parmDict setObject:@"0" forKey:@"i_type"]; WeakSelf [[NetHttpsManager manager] POSTWithParameters:parmDict SuccessBlock:^(NSDictionary *responseJson) { if ([[responseJson valueForKeyPath:@"status"]integerValue] == 1) { NSLog(@" = = = = = = = =%@",responseJson); } else if ([[responseJson valueForKeyPath:@"status"]integerValue] == 0) { //没钱或者权限不足,挂断 [weakSelf closeButtonClick]; } } FailureBlock:^(NSError *error) { }]; } #pragma mark - ******************* 腾讯TRTC 代理方法 ******************* - (void)startPreviewWithView:(UIView *)previewView{ self.trtcCloud = [TRTCCloud sharedInstance]; [[TRTCCloud sharedInstance] addDelegate: self]; // 设置本地画面的预览模式:开启左右镜像,设置画面为填充模式 TRTCRenderParams *param = [[TRTCRenderParams alloc] init]; param.fillMode = TRTCVideoFillMode_Fill; param.mirrorType = TRTCVideoMirrorTypeDisable; [self.trtcCloud setLocalRenderParams:param]; // 启动本地摄像头的预览(localCameraVideoView 是用于渲染本地渲染画面的控件) [self.trtcCloud startLocalPreview:YES view:previewView]; // 通过 TXDeviceManager 开启自动对焦并将闪光灯打开 TXDeviceManager *manager = [self.trtcCloud getDeviceManager]; if ([manager isAutoFocusEnabled]) { [manager enableCameraAutoFocus:YES]; } //开启闪光灯,手电筒 // [manager enableCameraTorch:YES]; /// 人声模式:采样率:16k;单声道;编码码率:16kbps;具备几个模式中最强的网络抗性,适合语音通话为主的场景,比如在线会议,语音通话等。 [self.trtcCloud startLocalAudio:TRTCAudioQualitySpeech]; } - (void)joinChannel:(NSString *)room_id { TRTCParams *params = [[TRTCParams alloc] init]; // 以字符串房间号为例 params.roomId = room_id.intValue; params.userId = [IMAPlatform sharedInstance].host.userId; // 从业务后台获取到的 UserSig params.userSig = [IMALoginParam loadFromLocal].userSig; // 替换成您的 SDKAppID params.sdkAppId = TXSDKAppID; // 根据需要指定用户角色 params.role = TRTCRoleAnchor; // 根据需要指定场景 [self.trtcCloud enterRoom:params appScene:TRTCAppSceneVideoCall]; TRTCVideoEncParam *videoEncParam = [[TRTCVideoEncParam alloc] init]; videoEncParam.videoFps = 24; videoEncParam.resMode = TRTCVideoResolutionModePortrait; videoEncParam.videoResolution = TRTCVideoResolution_960_540; [self.trtcCloud setVideoEncoderParam:videoEncParam]; } #pragma mark - 静音,默认开启 - (void)setIsMute:(BOOL)isMute { if (isMute) { [self.trtcCloud muteLocalAudio:YES]; return; } [self.trtcCloud muteLocalAudio:NO]; } #pragma mark - 开启扬声器,默认关闭 - (void)openYangshengqi:(BOOL)open { if (open) { ///使用扬声器播放(即“免提”),扬声器位于手机底部,声音偏大,适合外放音乐。 [self.trtcCloud setAudioRoute:TRTCAudioModeSpeakerphone]; return; } ///使用听筒播放,听筒位于手机顶部,声音偏小,适合需要保护隐私的通话场景。 [self.trtcCloud setAudioRoute:TRTCAudioModeEarpiece]; } // 离开房间事件回调 - (void)onExitRoom:(NSInteger)reason { if (reason == 0) { NSLog(@"主动调用 exitRoom 退出房间"); } else if (reason == 1) { NSLog(@"被服务器踢出当前房间"); } else if (reason == 2) { NSLog(@"当前房间整个被解散"); } } - (void) onEnterRoom:(NSInteger ) result { NSLog(@"onEnterRoom"); if(result > 0) { //接受者进房间后,主动问一下呼叫者是否是正常状态 if (self.isZhuDongCall == NO) { WeakSelf self.isNormalChatBlock = ^(BOOL isNormal) { if (isNormal == NO) { [weakSelf closeButtonClick]; } }; [self askChatIsNormal]; } } else { // [BGHUDHelper alert:[NSString stringWithFormat:@"进入直播间直播-%ld",result]]; } } - (void)askChatIsNormal { WeakSelf SIMMsgObj *obj = [self.mChatFriend sendCustomCallVideoTextMsg:@"接听者,忙线中" callAudioType:AudioChatType_askIsNormal isCall:self.isZhuDongCall block:^(SResBase *resb, SIMMsgObj *newObj) { if (!resb.msuccess) { [SVProgressHUD showErrorWithStatus:resb.mmsg]; } else { //1秒后,如果呼叫者没有回复说自己正常,那就退出房间 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ if (weakSelf.callIsNormal && weakSelf.isNormalChatBlock) { weakSelf.isNormalChatBlock(weakSelf.callIsNormal); } else { [weakSelf judjeAskChatIsNormalBackCount:0]; } }); } }]; } - (void)judjeAskChatIsNormalBackCount:(int)count { count ++; if (count > 10) { if (self.isNormalChatBlock) { self.isNormalChatBlock(self.callIsNormal); } return; } if (self.callIsNormal) { if (self.isNormalChatBlock) { self.isNormalChatBlock(self.callIsNormal); } return; } dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self judjeAskChatIsNormalBackCount:count]; }); } - (void)onRemoteUserLeaveRoom:(NSString *)userId reason:(NSInteger)reason { //有人异常退出,可能不是正常退出的,自己也退出,不聊了 //,直接挂断销毁视图 [VideoChatVC destoryShareRootVC]; NSLog(@"%@", [NSString stringWithFormat:@"用户离开%@",userId]); } //功能描述:音量大小的反馈回调 - (void)onUserVoiceVolume:(NSArray *)userVolumes totalVolume:(NSInteger)totalVolume { /*bug:当a用户在麦上正在说话时,切换到无网状态,此时虽然还显示在麦上(im还没下线), 但观众席听不到声音,光圈还在闪烁 原因: 这时观众席speakers 里面找不到a,就不会进入for循环,就不会更新a的声音为0 解决: 1先找到 麦上的用户 2去判断有无声音 */ // NSMutableArray *wheat_type_list = [NSMutableArray arrayWithArray:self.voiceRoomVC.roomModel.wheat_type_list]; // // for (int i = 0; i < wheat_type_list.count; i ++) { // // Wheat_Type_List *info = wheat_type_list[i]; // // if (info.even_wheat.user_id) { // // BOOL online = NO; // //// for (AgoraRtcAudioVolumeInfo *speaker in speakers) { // for (TRTCVolumeInfo * volumeInfo in userVolumes) { // // NSString *uid = @""; // if (volumeInfo.userId.intValue == 0) { // uid = [IMAPlatform sharedInstance].host.userId; // online = YES; // }else if (info.even_wheat.user_id == volumeInfo.userId.intValue){ // uid = [NSString stringWithFormat:@"%@",volumeInfo.userId]; // online = YES; // } // if (online) { // info.totalVolume = volumeInfo.volume; // // [self.users updateUser:uid volume:speaker.volume]; // } // } // // wheat_type_list[i] = info; // // // if (!online) { // // [self.users updateUser:info.user_id volume:0]; // // } // } // } // self.voiceRoomVC.roomModel.wheat_type_list = wheat_type_list; // [self.voiceRoomVC setRoomModel:self.voiceRoomVC.roomModel]; // [self.uiController.micView setUsers:self.users]; } #pragma mark - ******************* 腾讯TRTC 代理方法 end ******************* #pragma mark 解决不能调为最小音量问题 - (void)volumeChanged:(NSNotification *)noti { NSDictionary *tmpDict = noti.userInfo; if (tmpDict && [tmpDict isKindOfClass:[NSDictionary class]]) { // if ([[tmpDict toString:@"AVSystemController_AudioVolumeChangeReasonNotificationParameter"] isEqualToString:@"ExplicitVolumeChange"] && !_isMuted) if ([[tmpDict toString:@"AVSystemController_AudioVolumeChangeReasonNotificationParameter"] isEqualToString:@"ExplicitVolumeChange"]) { float volume = [[tmpDict objectForKey:@"AVSystemController_AudioVolumeNotificationParameter"] floatValue]; if (volume <= 0.062500) { // [_publishController.txLivePublisher setMute:YES]; } else { // [_publishController.txLivePublisher setMute:NO]; } } } } #pragma mark - ************** 播放声音 ************ /**播放录音*/ -(void)playRecordWithName:(NSString *)musicName type:(NSString *)musicType playCount:(int)count { NSString *audioFilePath = [[NSBundle mainBundle] pathForResource:musicName ofType:musicType]; NSURL *audioFileURL = [NSURL fileURLWithPath:audioFilePath]; AVAudioSession *session = [AVAudioSession sharedInstance]; NSError *sessionError; //AVAudioSessionCategoryPlayAndRecord,这个确保了既能录音也能播放 [session setCategory:AVAudioSessionCategoryPlayback error:&sessionError]; if (session == nil) { NSLog(@"Error creating sessing:%@", [sessionError description]); } else { [session setActive:YES error:nil]; } NSError *playError; self.player = [[AVAudioPlayer alloc]initWithContentsOfURL:audioFileURL error:&playError]; //无限循环 self.player.numberOfLoops = count; // self.player.volume = 20; //当播放录音为空, 打印错误信息 if (self.player == nil) { NSLog(@"Error crenting player: %@", [playError description]); } self.player.delegate = self; if ([self.player isPlaying]) { [self.player pause]; } else { [self.player play]; } } - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { // self.player = nil; NSLog(@"播放完成"); // [self playRecord]; } @end