851 lines
34 KiB
Objective-C
Executable File
851 lines
34 KiB
Objective-C
Executable File
//
|
||
// LNAgoraEngine.m
|
||
// SoundRiver
|
||
//
|
||
// Created by ln007 on 2019/8/29.
|
||
//
|
||
|
||
#import "QXAgoraEngine.h"
|
||
|
||
|
||
#import "QXRoomMessageManager.h"
|
||
#import "QXAgoraEngineEx.h"
|
||
#import <ReplayKit/ReplayKit.h>
|
||
|
||
@interface QXAgoraEngine ()<AgoraRtcEngineDelegate,AgoraMusicContentCenterEventDelegate,AgoraRtcMediaPlayerDelegate>
|
||
|
||
|
||
|
||
@property (nonatomic , strong) NSString *currentChannel;
|
||
@property (nonatomic , assign) NSUInteger currentUid;
|
||
|
||
|
||
@property (nonatomic , assign) NSInteger page;
|
||
|
||
@property (nonatomic , strong) QXSongListModel* songModel;
|
||
|
||
@property (nonatomic , strong)NSMutableArray *bgMusicArray;
|
||
|
||
|
||
@property (nonatomic , strong)AgoraScreenCaptureParameters2 *screenParams;
|
||
@property (nonatomic , strong)RPSystemBroadcastPickerView *systemBroadcastPicker;
|
||
@property (nonatomic , strong)AgoraRtcChannelMediaOptions *option;
|
||
@property (nonatomic , assign) BOOL isOpenMic;
|
||
@end
|
||
|
||
@implementation QXAgoraEngine
|
||
|
||
|
||
+(instancetype)sharedEngine {
|
||
static dispatch_once_t onceToken;
|
||
static QXAgoraEngine *instance;
|
||
dispatch_once(&onceToken, ^{
|
||
instance = [[QXAgoraEngine alloc] init];
|
||
});
|
||
if (!instance.agoraKit) {
|
||
[instance initializeAgoraEngine];
|
||
}
|
||
return instance;
|
||
}
|
||
|
||
|
||
//初始化
|
||
- (void)initializeAgoraEngine {
|
||
self.agoraKit = [AgoraRtcEngineKit sharedEngineWithAppId:AgoraAuthId delegate:self];
|
||
[self.agoraKit enableAudioVolumeIndication:200 smooth:3 reportVad:NO];
|
||
[self.agoraKit getCurrentMonotonicTimeInMs];
|
||
[self.agoraKit setAudioProfile:AgoraAudioProfileMusicHighQualityStereo];
|
||
[self.agoraKit setAudioScenario:AgoraAudioScenarioChorus];
|
||
[self setChannelProfile];
|
||
self.agoraKit.delegate = self;
|
||
[self.agoraKit setParameters:@"{\"che.audio.custom_payload_type\":73}"];
|
||
[self.agoraKit setParameters:@"{\"che.audio.custom_bitrate\":128000}"];
|
||
[self.agoraKit setParameters:@"{\"rtc.enable_nasa2\": true}"];
|
||
[self.agoraKit setParameters:@"{\"rtc.use_audio4\": true}" ];
|
||
[self.agoraKit enableVideo];
|
||
[self.agoraKit enableAudio];
|
||
AgoraVideoEncoderConfiguration *encoderConfig = [[AgoraVideoEncoderConfiguration alloc] initWithSize:CGSizeMake(960, 540)
|
||
frameRate:(AgoraVideoFrameRateFps15)
|
||
bitrate:AgoraVideoBitrateStandard
|
||
orientationMode:(AgoraVideoOutputOrientationModeFixedPortrait)
|
||
mirrorMode:(AgoraVideoMirrorModeAuto)];
|
||
[self.agoraKit setVideoEncoderConfiguration:encoderConfig];
|
||
|
||
}
|
||
-(void)rtcEngine:(AgoraRtcEngineKit *)engine didOccurError:(AgoraErrorCode)errorCode{
|
||
QXLOG(@"声网状态---%ld",errorCode)
|
||
}
|
||
//设置频道模式为直播
|
||
- (void)setChannelProfile {
|
||
[self.agoraKit setChannelProfile:AgoraChannelProfileLiveBroadcasting];
|
||
}
|
||
|
||
//加入直播频道
|
||
- (void)joinChannel:(NSString *)channelId withRoom:(UIViewController *)chatRoom agora_token:(NSString*)agora_token agora_rtm_token:(NSString*)agora_rtm_token isUpSeat:(BOOL)isUpSeat successBock:(nonnull void (^)(void))successBock{
|
||
if (isUpSeat) {
|
||
self.option.clientRoleType = AgoraClientRoleBroadcaster;
|
||
}else{
|
||
self.option.clientRoleType = AgoraClientRoleAudience;
|
||
}
|
||
if (_currentChannel.length > 0) {
|
||
if (![_currentChannel isEqualToString:channelId]) {
|
||
[self switchToChannel:channelId withRoom:chatRoom agora_token:agora_token agora_rtm_token:agora_rtm_token isUpSeat:isUpSeat successBock:successBock];
|
||
}
|
||
}else{
|
||
__weak typeof(self)weakSelf = self;
|
||
[self.agoraKit joinChannelByToken:agora_token channelId:channelId uid:QXGlobal.shareGlobal.loginModel.user_id.longLongValue mediaOptions:self.option joinSuccess:^(NSString * _Nonnull channel, NSUInteger uid, NSInteger elapsed) {
|
||
[weakSelf onInitKTVCenterWithToken:agora_rtm_token];
|
||
[weakSelf muteLocalAudioStream:YES];
|
||
[weakSelf muteAllRemoteAudioStreams:NO];
|
||
self.option.publishMicrophoneTrack = YES;
|
||
self.option.publishMediaPlayerAudioTrack = YES;
|
||
self.option.enableAudioRecordingOrPlayout = YES;
|
||
self.option.publishMediaPlayerId = [self->_ktvPlayer getMediaPlayerId];
|
||
[self.agoraKit updateChannelWithMediaOptions:self.option];
|
||
// 当远端用户加入频道后,显示指定 uid 的远端视频流
|
||
|
||
if (successBock) {
|
||
successBock();
|
||
}
|
||
}];
|
||
|
||
|
||
}
|
||
}
|
||
|
||
//- (void)joinExChannel:(NSString *)channelId withRoom:(UIViewController *)chatRoom agora_token:(NSString*)agora_token agora_rtm_token:(NSString*)agora_rtm_token successBock:(void(^)(void))successBock{
|
||
// [self.agoraKit joinChannelExByToken:<#(NSString * _Nullable)#> channelId:<#(NSString * _Nonnull)#> userAccount:<#(NSString * _Nonnull)#> delegate:<#(id<AgoraRtcEngineDelegate> _Nullable)#> mediaOptions:<#(AgoraRtcChannelMediaOptions * _Nonnull)#> joinSuccess:<#^(NSString * _Nonnull channel, NSUInteger uid, NSInteger elapsed)joinSuccessBlock#>]
|
||
//}
|
||
//切换用户角色
|
||
/*
|
||
该方法在加入频道前后都可以调用:
|
||
|
||
加入直播频道前,调用该方法将用户设置为主播或观众。
|
||
直播过程中,调用该方法将用户角色由观众切换为主播(上麦),或由主播切换为观众。
|
||
*/
|
||
- (void)setClientRoleBroadcaster:(BOOL)isBroadcaster {
|
||
[self.agoraKit setClientRole:isBroadcaster ? AgoraClientRoleBroadcaster : AgoraClientRoleAudience];
|
||
}
|
||
|
||
|
||
- (void)rtcEngine:(AgoraRtcEngineKit * _Nonnull)engine tokenPrivilegeWillExpire:(NSString *_Nonnull)token{
|
||
// [self.agoraKit renewToken:<#(NSString * _Nonnull)#>]
|
||
}
|
||
|
||
//离开频道
|
||
-(void)leaveChannel {
|
||
int result = [self.agoraKit leaveChannel:^(AgoraChannelStats * _Nonnull stat) {
|
||
QXLOG(@"声网进入退出频道回调");
|
||
}];
|
||
QXLOG(@"声网退出频道result---------%@",result);
|
||
//需要退出聊天室
|
||
self.chatRoom = nil;
|
||
self.currentChannel = nil;
|
||
}
|
||
|
||
//切换频道
|
||
- (void)switchToChannel:(NSString *)channelId withRoom:(UIViewController *)chatRoom agora_token:(NSString *)agora_token agora_rtm_token:(NSString *)agora_rtm_token isUpSeat:(BOOL)isUpSeat successBock:(void (^)(void))successBock{
|
||
__weak typeof(self)weakSelf = self;
|
||
[self.agoraKit leaveChannel:^(AgoraChannelStats * _Nonnull stat) {
|
||
[self.agoraKit joinChannelByToken:agora_token channelId:channelId uid:QXGlobal.shareGlobal.loginModel.user_id.longLongValue mediaOptions:self.option joinSuccess:^(NSString * _Nonnull channel, NSUInteger uid, NSInteger elapsed) {
|
||
[weakSelf onInitKTVCenterWithToken:agora_rtm_token];
|
||
[weakSelf muteLocalAudioStream:YES];
|
||
[weakSelf muteAllRemoteAudioStreams:NO];
|
||
AgoraRtcChannelMediaOptions *option = [AgoraRtcChannelMediaOptions new];
|
||
option.publishMicrophoneTrack = YES;
|
||
option.publishMediaPlayerAudioTrack = YES;
|
||
option.enableAudioRecordingOrPlayout = YES;
|
||
option.publishMediaPlayerId = [self->_ktvPlayer getMediaPlayerId];
|
||
[self.agoraKit updateChannelWithMediaOptions:option];
|
||
if (successBock) {
|
||
successBock();
|
||
}
|
||
}];
|
||
}];
|
||
}
|
||
|
||
//销毁
|
||
- (void)destroyEngine
|
||
{
|
||
if (!self.agoraKit) {
|
||
return;
|
||
}
|
||
[AgoraRtcEngineKit destroy];
|
||
self.agoraKit = nil;
|
||
[self.ktvAmcc destroyMusicPlayer:_ktvPlayer];
|
||
_ktvPlayer = nil;
|
||
[self.ktvAmcc registerEventDelegate:nil];
|
||
[AgoraMusicContentCenter destroy];
|
||
self.ktvAmcc = nil;
|
||
self.isOpenMic = NO;
|
||
}
|
||
|
||
//禁麦
|
||
- (void)muteLocalAudioStream:(BOOL)mute
|
||
{
|
||
// [self.agoraKit enableLocalAudio:!mute];
|
||
// if ([self.songModel.user_id isEqualToString:QXGlobal.shareGlobal.loginModel.user_id]) {
|
||
// /// 当前唱歌者为自己时 只是停止声音监听
|
||
// [self.agoraKit muteRecordingSignal:mute];
|
||
// }else{
|
||
// [self.agoraKit muteRecordingSignal:mute];
|
||
// [self.agoraKit muteLocalAudioStream:mute];
|
||
// }
|
||
|
||
int result = [self.agoraKit muteLocalAudioStream:mute];
|
||
QXLOG(@"音频模块禁麦---%d",result);
|
||
// [self setClientRoleBroadcaster:!mute];
|
||
|
||
// [self.agoraKit muteRecordingSignal:mute];
|
||
}
|
||
-(void)enableAudio:(BOOL)enble{
|
||
self.isOpenMic = enble;
|
||
int result = [self.agoraKit enableLocalAudio:enble];
|
||
QXLOG(@"音频模块启动---%d",result);
|
||
}
|
||
//切换为耳机播放
|
||
- (int)setEnableSpeakerphone:(BOOL)enableSpeaker
|
||
{
|
||
return [self.agoraKit setEnableSpeakerphone:enableSpeaker];
|
||
}
|
||
|
||
- (BOOL)isSpeakerphoneEnabled
|
||
{
|
||
return [self.agoraKit isSpeakerphoneEnabled];
|
||
}
|
||
|
||
- (int)muteAllRemoteAudioStreams:(BOOL)mute
|
||
{
|
||
return [self.agoraKit muteAllRemoteAudioStreams:mute];
|
||
}
|
||
|
||
- (int)startAudioMixing:(NSString * _Nonnull)filePath
|
||
loopback:(BOOL)loopback
|
||
replace:(BOOL)replace
|
||
cycle:(NSInteger)cycle
|
||
{
|
||
// self.isPlay = YES;
|
||
return [self.agoraKit startAudioMixing:filePath loopback:loopback cycle:cycle startPos:0];
|
||
}
|
||
- (int)paseAudioMixing{
|
||
|
||
|
||
// self.isPlay = NO;
|
||
|
||
return [self.agoraKit pauseAudioMixing];
|
||
}
|
||
|
||
- (int)stopAudioMixing{
|
||
|
||
// self.isPlay = NO;
|
||
|
||
return [self.agoraKit stopAudioMixing];
|
||
}
|
||
- (int)resumeAudioMixing{
|
||
// self.isPlay = YES;
|
||
return [self.agoraKit resumeAudioMixing];
|
||
|
||
}
|
||
|
||
|
||
- (int)adjustAudioMixingVolume:(NSInteger)volume{
|
||
return [self.agoraKit adjustAudioMixingVolume:volume];
|
||
|
||
}
|
||
- (double)getEffectsVolume{
|
||
return [self.agoraKit getEffectsVolume];
|
||
}
|
||
|
||
|
||
#pragma mark-用户信息管理
|
||
- (void)registerLocalUserAccount
|
||
{
|
||
[self.agoraKit registerLocalUserAccount:@"" appId:AgoraAuthId];
|
||
}
|
||
|
||
- (void)RequestMusicURLData:(NSString *)MusicID{
|
||
// LNNetworkAPI *api = [[LNNetworkAPI alloc] initWithUrl:@"api/Song/index" parameters:@{@"input":MusicID,@"filter":@"name",@"type":@"netease",@"page":@"1"}];
|
||
// [api startRequestWithCompletionBlockWithSuccess:^(__kindof YTKBaseRequest * _Nonnull request, NSDictionary * _Nonnull result) {
|
||
// if ([result[@"status"] integerValue] == 1) {
|
||
//
|
||
// NSArray *DataDic = result[@"data"];
|
||
// NSDictionary *dic = DataDic[0];
|
||
//
|
||
// NSString * filePath = [dic objectForKey:@"url"];
|
||
//
|
||
// BOOL loopback = NO;
|
||
// BOOL replace = NO;
|
||
// NSInteger cycle = 1;
|
||
//
|
||
//
|
||
// // 开始播放混音
|
||
// [self.agoraKit startAudioMixing: filePath loopback: loopback replace: replace cycle: cycle];
|
||
//
|
||
// }else{
|
||
// [SRToastTool showTips:result[@"info"]];
|
||
// }
|
||
// } failure:^(__kindof YTKBaseRequest * _Nonnull request, NSString * _Nonnull errorInfo) {
|
||
// [SRToastTool showError:errorInfo];
|
||
// }];
|
||
}
|
||
|
||
|
||
|
||
#pragma mark-Enginedelegate
|
||
- (void)rtcEngine:(AgoraRtcEngineKit *)engine didLeaveChannelWithStats:(AgoraChannelStats *)stats
|
||
{
|
||
|
||
}
|
||
|
||
|
||
-(void)rtcEngine:(AgoraRtcEngineKit *)engine localAudioStateChanged:(AgoraAudioLocalState)state reason:(AgoraAudioLocalReason)reason{
|
||
QXLOG(@"%lu",(unsigned long)state);
|
||
}
|
||
|
||
- (void)rtcEngine:(AgoraRtcEngineKit *)engine audioMixingStateChanged:(AgoraAudioMixingStateType)state reasonCode:(AgoraAudioMixingReasonCode)reasonCode{
|
||
QXLOG(@"音乐播放状态改变%lu",(long)state);
|
||
switch (state) {
|
||
case AgoraAudioMixingStateTypePlaying:
|
||
{
|
||
|
||
}
|
||
break;
|
||
case AgoraAudioMixingStateTypePaused:
|
||
{
|
||
|
||
}
|
||
break;
|
||
case AgoraAudioMixingStateTypeStopped:
|
||
{
|
||
// if (self.delegate && [self.delegate respondsToSelector:@selector(rtcEngineLocalAudioMixingDidFinish)]) {
|
||
// [self.delegate rtcEngineLocalAudioMixingDidFinish];
|
||
// return;
|
||
// }
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
-(void)rtcEngine:(AgoraRtcEngineKit *)engine didOfflineOfUid:(NSUInteger)uid reason:(AgoraUserOfflineReason)reason{
|
||
// NSDictionary *parm = @{
|
||
// @"user_id":[NSNumber numberWithInteger:uid],
|
||
// @"is_online":[NSNumber numberWithBool:NO],
|
||
// };
|
||
// [[NSNotificationCenter defaultCenter] postNotificationName:noticeRoomUserOnlineStatusDidChanged object:parm];
|
||
}
|
||
|
||
-(void)rtcEngine:(AgoraRtcEngineKit *)engine didJoinedOfUid:(NSUInteger)uid elapsed:(NSInteger)elapsed{
|
||
// NSDictionary *parm = @{
|
||
// @"user_id":[NSNumber numberWithInteger:uid],
|
||
// @"is_online":[NSNumber numberWithBool:YES],
|
||
// };
|
||
// [[NSNotificationCenter defaultCenter] postNotificationName:noticeRoomUserOnlineStatusDidChanged object:parm];
|
||
}
|
||
/// 说话声音大小
|
||
-(void)rtcEngine:(AgoraRtcEngineKit *)engine reportAudioVolumeIndicationOfSpeakers:(NSArray<AgoraRtcAudioVolumeInfo *> *)speakers totalVolume:(NSInteger)totalVolume{
|
||
// NSMutableDictionary *usersSoundLevels = [NSMutableDictionary dictionary];
|
||
// for (AgoraRtcAudioVolumeInfo *info in speakers) {
|
||
// if (info.uid == 0) {
|
||
// [usersSoundLevels setValue:@(info.volume) forKey:QXGlobal.shareGlobal.loginModel.user_id];
|
||
// }else{
|
||
// [usersSoundLevels setValue:@(info.volume) forKey:[NSString stringWithFormat:@"%lu",info.uid]];
|
||
// }
|
||
// }
|
||
// if (self.delegate && [self.delegate respondsToSelector:@selector(onRTCEngineRoomPublishSoundLevelUpdate:)]) {
|
||
// [self.delegate onRTCEngineRoomPublishSoundLevelUpdate:speakers];
|
||
// }
|
||
for (AgoraRtcAudioVolumeInfo *info in speakers) {
|
||
[[NSNotificationCenter defaultCenter] postNotificationName:noticeUserSpeak object:info];
|
||
}
|
||
}
|
||
-(void)rtcEngine:(AgoraRtcEngineKit *)engine remoteVideoStats:(AgoraRtcRemoteVideoStats *)stats{
|
||
NSLog(@"uid=%ld直播远端视频状态",stats.uid);
|
||
}
|
||
-(void)rtcEngine:(AgoraRtcEngineKit *)engine firstRemoteVideoFrameOfUid:(NSUInteger)uid size:(CGSize)size elapsed:(NSInteger)elapsed{
|
||
NSLog(@"uid=%ld直播远端视频首次加载",uid);
|
||
if (self.delegate && [self.delegate respondsToSelector:@selector(rtcEngineVideoFirstLoadWithUid:size:)]) {
|
||
[self.delegate rtcEngineVideoFirstLoadWithUid:uid size:size];
|
||
}
|
||
}
|
||
-(void)rtcEngine:(AgoraRtcEngineKit *)engine videoSizeChangedOfSourceType:(AgoraVideoSourceType)sourceType uid:(NSUInteger)uid size:(CGSize)size rotation:(NSInteger)rotation{
|
||
|
||
}
|
||
-(void)rtcEngine:(AgoraRtcEngineKit *)engine remoteVideoStateChangedOfUid:(NSUInteger)uid state:(AgoraVideoRemoteState)state reason:(AgoraVideoRemoteReason)reason elapsed:(NSInteger)elapsed{
|
||
NSLog(@"uid=%ld---直播远端视频状态发生变化status=%ld",uid,state);
|
||
if (state == AgoraVideoRemoteStateStopped) {
|
||
if (self.delegate && [self.delegate respondsToSelector:@selector(rtcEngineVideoDidStop:)]) {
|
||
[self.delegate rtcEngineVideoDidStop:uid];
|
||
}
|
||
}else if (state == AgoraVideoRemoteStateStarting) {
|
||
if (self.delegate && [self.delegate respondsToSelector:@selector(rtcEngineVideoDidStart:)]) {
|
||
[self.delegate rtcEngineVideoDidStart:uid];
|
||
}
|
||
}else{
|
||
// if (self.delegate && [self.delegate respondsToSelector:@selector(rtcEngineVideoDidStart:)]) {
|
||
// [self.delegate rtcEngineVideoDidStart:uid];
|
||
// }
|
||
}
|
||
}
|
||
-(void)rtcEngine:(AgoraRtcEngineKit *)engine channelMediaRelayStateDidChange:(AgoraChannelMediaRelayState)state error:(AgoraChannelMediaRelayError)error{
|
||
NSLog(@"channelMediaRelayStateDidChange");
|
||
}
|
||
-(void)rtcEngine:(AgoraRtcEngineKit *)engine localVideoStateChangedOfState:(AgoraVideoLocalState)state reason:(AgoraLocalVideoStreamReason)reason sourceType:(AgoraVideoSourceType)sourceType{
|
||
NSLog(@"localVideoStateChangedOfState");
|
||
if (state == AgoraVideoLocalStateCapturing && sourceType == AgoraVideoSourceTypeScreen) {
|
||
self.option.publishScreenCaptureAudio = YES;
|
||
self.option.publishScreenCaptureVideo = YES;
|
||
self.option.publishCameraTrack = NO;
|
||
[self.agoraKit updateChannelWithMediaOptions:self.option];
|
||
|
||
}else if (state == AgoraVideoLocalStateStopped && sourceType == AgoraVideoSourceTypeScreen) {
|
||
[self.agoraKit stopScreenCapture];
|
||
}
|
||
}
|
||
-(void)rtcEngine:(AgoraRtcEngineKit *)engine audioMixingPositionChanged:(NSInteger)position{
|
||
|
||
}
|
||
|
||
//- (void)rtcEngineLocalAudioMixingDidFinish:(AgoraRtcEngineKit *_Nonnull)engine{
|
||
// if (self.delegate && [self.delegate respondsToSelector:@selector(rtcEngineLocalAudioMixingDidFinish)]) {
|
||
// [self.delegate rtcEngineLocalAudioMixingDidFinish];
|
||
// return;
|
||
// }
|
||
// NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
|
||
// NSString *filePath = [cachePath stringByAppendingPathComponent:@"testPlist.plist"];
|
||
//
|
||
// NSMutableArray *MusicListArray = [NSMutableArray arrayWithContentsOfFile:filePath];
|
||
//
|
||
// NSInteger index = self.index;
|
||
// switch (self.playType) {
|
||
// case 0:
|
||
//
|
||
// break;
|
||
// case 1:
|
||
//
|
||
// index = MusicListArray.count - 1;
|
||
//
|
||
// index = arc4random() % index;
|
||
//
|
||
// break;
|
||
// case 2:
|
||
//
|
||
// if (index == MusicListArray.count - 1) {
|
||
// index = 0;
|
||
// }//如果不是最后一首下标加1
|
||
// else{
|
||
// index++;
|
||
// }
|
||
// break;
|
||
// default:
|
||
// break;
|
||
// }
|
||
//
|
||
// NSDictionary *dic = MusicListArray[index];
|
||
// NSString * filePathstr = [dic objectForKey:@"songid"];
|
||
// [self RequestMusicURLData:filePathstr];
|
||
//}
|
||
|
||
|
||
-(void)addBgMusic:(QXSongListModel *)music{
|
||
if (self.bgMusicArray.count == 0 && self.songModel == nil) {
|
||
[self.bgMusicArray addObject:music];
|
||
[self nextBgMusic];
|
||
}else{
|
||
[self.bgMusicArray addObject:music];
|
||
}
|
||
|
||
}
|
||
-(void)nextBgMusic{
|
||
if (self.bgMusicArray.count > 0) {
|
||
QXSongListModel *music = self.bgMusicArray.firstObject;
|
||
[self ktv_EndSing];
|
||
[self ktv_StartSing:YES withSong:music];
|
||
if (self.delegate && [self.delegate respondsToSelector:@selector(rtcEngineBackgroundMusicNextSong:)]) {
|
||
[self.delegate rtcEngineBackgroundMusicNextSong:music];
|
||
}
|
||
[self.bgMusicArray removeObject:self.songModel];
|
||
}else{
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
showToast(@"已经是最后一首了");
|
||
});
|
||
|
||
}
|
||
|
||
}
|
||
-(void)pausePlayMusic{
|
||
[self.ktvPlayer pause];
|
||
}
|
||
-(void)resumePlayMusic{
|
||
[self.ktvPlayer resume];
|
||
}
|
||
|
||
|
||
- (void)setUseMicrophone:(BOOL)useMicrophone {
|
||
_useMicrophone = useMicrophone;
|
||
[self.agoraKit adjustRecordingSignalVolume:useMicrophone ? 100 : 0];
|
||
|
||
}
|
||
|
||
- (void)onInitKTVCenterWithToken:(NSString*)token{
|
||
// 1.注册曲库并初始化 AgoraMusicContentCenter。
|
||
AgoraMusicContentCenterConfig *config = [AgoraMusicContentCenterConfig new];
|
||
// 填入已开启音乐内容中心项目的 App ID
|
||
config.appId = AgoraAuthId;
|
||
// 用户 ID,该 ID 可以和你加入 RTC 频道时使用的 uid 一致,但不能为 0。
|
||
config.mccUid = QXGlobal.shareGlobal.loginModel.user_id.integerValue;
|
||
// 填入用于鉴权的 Token。
|
||
config.token = token;
|
||
// AgoraRtcEngineKit 实例。
|
||
config.rtcEngine = self.agoraKit;
|
||
_ktvAmcc = [AgoraMusicContentCenter sharedContentCenterWithConfig:config];
|
||
[_ktvAmcc registerEventDelegate:self];
|
||
|
||
//创建音乐播放器。如果你需要播放音乐内容中心的音乐资源,需要使用此播放器进行播放。
|
||
_ktvPlayer = [_ktvAmcc createMusicPlayerWithDelegate:self];
|
||
|
||
}
|
||
|
||
- (void)ktv_DestoryKtvPlayer{
|
||
[_ktvPlayer stop];
|
||
self.songModel = nil;
|
||
|
||
// if (self.ktv_UpdatePlayBtnStatusBlock) {
|
||
// self.ktv_UpdatePlayBtnStatusBlock(NO);
|
||
// }
|
||
}
|
||
-(void)searchSongWithKeyword:(NSString *)keywords page:(NSInteger)page resultBlock:(nonnull SearchSongBlock)resultBlock{
|
||
self.searchSongBlock = resultBlock;
|
||
[_ktvAmcc searchMusicWithKeyWord:keywords page:page pageSize:20 jsonOption:nil];
|
||
}
|
||
|
||
//预加载回调
|
||
-(void)onPreLoadEvent:(NSString *)requestId songCode:(NSInteger)songCode percent:(NSInteger)percent lyricUrl:(NSString *)lyricUrl state:(AgoraMusicContentCenterPreloadState)state reason:(AgoraMusicContentCenterStateReason)reason{
|
||
if (state == AgoraMusicContentCenterPreloadStateOK) {
|
||
[_ktvPlayer stop];
|
||
NSInteger code = [_ktvPlayer openMediaWithSongCode:songCode startPos:0];
|
||
QXLOG(code==0?@"播放器打开成功":@"播放器打开失败");
|
||
}
|
||
}
|
||
//打开音乐资源回调
|
||
-(void)AgoraRtcMediaPlayer:(id<AgoraRtcMediaPlayerProtocol>)playerKit didChangedToState:(AgoraMediaPlayerState)state reason:(AgoraMediaPlayerReason)reason{
|
||
if (state == AgoraMediaPlayerStateOpenCompleted) {
|
||
// [_ktvPlayer play];
|
||
if (self.isPlayBgMusic) {
|
||
/// 背景音乐无需获取歌词
|
||
return;
|
||
}
|
||
[_ktvAmcc getLyricWithSongCode:_songModel.song_code lyricType:1];
|
||
[_ktvAmcc getSongSimpleInfoWithSongCode:_songModel.song_code];
|
||
}else if (state == AgoraMediaPlayerStatePlayBackCompleted || state == AgoraMediaPlayerStatePlayBackAllLoopsCompleted || state == AgoraMediaPlayerStateStopped) {
|
||
|
||
}
|
||
}
|
||
//播放进度回调
|
||
-(void)AgoraRtcMediaPlayer:(id<AgoraRtcMediaPlayerProtocol>)playerKit didChangedToPosition:(NSInteger)positionMs atTimestamp:(NSTimeInterval)timestampMs{
|
||
if (playerKit.getPlayerState == AgoraMediaPlayerStatePlaying) {
|
||
if (self.delegate && [self.delegate respondsToSelector:@selector(rtcEngineSongProgress:)]) {
|
||
[self.delegate rtcEngineSongProgress:positionMs];
|
||
}
|
||
if (self.isPlayBgMusic) {
|
||
return;
|
||
}
|
||
self.playPosition = positionMs;
|
||
NSDictionary *dict = @{
|
||
@"position":[NSNumber numberWithInteger:positionMs],
|
||
};
|
||
NSString *jsonStr = [dict jsonStringEncoded];
|
||
[[QXRoomMessageManager shared] sendChatMessage:jsonStr messageType:(QXRoomMessageTypeSongLrc) needInsertMessage:NO];
|
||
|
||
|
||
// if (self.roomInfo.is_xiangqin == 1){
|
||
// NSDictionary *body = @{@"messageType":@(BJIMMsgType_UpdateLyricPosition).stringValue,
|
||
// @"position":@(positionMs).stringValue
|
||
// };
|
||
// [[V2TIMManager sharedInstance] sendGroupCustomMessage:body.mj_JSONData to:_roomInfo.roomId priority:V2TIM_PRIORITY_NORMAL succ:^{
|
||
//
|
||
// } fail:^(int code, NSString *msg) {
|
||
// // 群聊文本消息发送失败
|
||
// }];
|
||
// }
|
||
|
||
}else if (playerKit.getPlayerState == AgoraMediaPlayerStatePlayBackAllLoopsCompleted) {
|
||
if (self.isPlayBgMusic) {
|
||
[self nextBgMusic];
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
-(void)rtcEngine:(AgoraRtcEngineKit *)engine receiveStreamMessageFromUid:(NSUInteger)uid streamId:(NSInteger)streamId data:(NSData *)data{
|
||
NSString *jsonStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
||
NSDictionary *dict = [jsonStr jsonValueDecoded];
|
||
NSInteger positionMs = [[dict objectForKey:@"position"] integerValue];
|
||
if (self.delegate && [self.delegate respondsToSelector:@selector(rtcEngineSongProgress:)]) {
|
||
[self.delegate rtcEngineSongProgress:positionMs];
|
||
}
|
||
}
|
||
/// 收藏音乐
|
||
- (void)onMusicChartsResult:(NSString *)requestId result:(NSArray<AgoraMusicChartInfo *> *)result reason:(AgoraMusicContentCenterStateReason)reason{
|
||
|
||
}
|
||
/// 搜索回调
|
||
-(void)onMusicCollectionResult:(NSString *)requestId result:(AgoraMusicCollection *)result reason:(AgoraMusicContentCenterStateReason)reason{
|
||
if (self.searchSongBlock) {
|
||
self.searchSongBlock(result.musicList,result.page == 1);
|
||
}
|
||
}
|
||
/// 歌曲信息
|
||
-(void)onSongSimpleInfoResult:(NSString *)requestId songCode:(NSInteger)songCode simpleInfo:(NSString *)simpleInfo reason:(AgoraMusicContentCenterStateReason)reason{
|
||
|
||
}
|
||
-(void)onLyricResult:(NSString *)requestId songCode:(NSInteger)songCode lyricUrl:(NSString *)lyricUrl reason:(AgoraMusicContentCenterStateReason)reason{
|
||
NSLog(@"歌词地址回调-----%ld", reason);
|
||
dispatch_async(dispatch_get_main_queue(),^{
|
||
if (self.delegate && [self.delegate respondsToSelector:@selector(rtcEngineSongLrc:)]) {
|
||
[self.delegate rtcEngineSongLrc:lyricUrl];
|
||
}
|
||
});
|
||
}
|
||
-(void)ktv_LoadLrcWithSong:(QXSongListModel *)songModel{
|
||
// if ([_ktvAmcc isPreloadedWithSongCode:_songModel.song_code] < 0) {//未预加载
|
||
// [_ktvAmcc preloadWithSongCode:_songModel.song_code];
|
||
// }
|
||
_songModel = songModel;
|
||
if ([_ktvAmcc isPreloadedWithSongCode:_songModel.song_code] < 0) {//未预加载
|
||
[_ktvAmcc preloadWithSongCode:_songModel.song_code];
|
||
}else{
|
||
NSInteger result = [_ktvPlayer openMediaWithSongCode:_songModel.song_code startPos:0];
|
||
QXLOG(@"歌词---%ld",result);
|
||
}
|
||
}
|
||
-(void)ktv_StartSing:(BOOL)isStart withSong:(nonnull QXSongListModel *)songModel{
|
||
|
||
// if (_songModel) {
|
||
// [_ktvPlayer stop];
|
||
// }
|
||
if (songModel == nil) {
|
||
return;
|
||
}
|
||
_songModel = songModel;
|
||
|
||
if (isStart) {
|
||
if ([_ktvAmcc isPreloadedWithSongCode:_songModel.song_code] < 0) {//未预加载
|
||
[_ktvAmcc preloadWithSongCode:_songModel.song_code];
|
||
// [SVProgressHUD showWithStatus:@"歌曲预加载中,请稍候"];
|
||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||
[self ktv_StartSing:YES withSong:self->_songModel];
|
||
// [SVProgressHUD dismiss];
|
||
});
|
||
}else {
|
||
NSLog(@"getPlayerState : %ld",(long)[_ktvPlayer getPlayerState]);
|
||
if ([_ktvPlayer getPlayerState] == AgoraMediaPlayerStatePaused) {
|
||
NSInteger tag = [_ktvPlayer resume];
|
||
NSLog(@"内容中心继续---%ld", tag);
|
||
}else if ([_ktvPlayer getPlayerState] == AgoraMediaPlayerStateIdle) {
|
||
NSInteger tag = [_ktvPlayer openMediaWithSongCode:_songModel.song_code startPos:0];
|
||
|
||
// [SVProgressHUD showWithStatus:@"正在打开,请稍候"];
|
||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||
[self ktv_StartSing:YES withSong:self->_songModel];
|
||
// [SVProgressHUD dismiss];
|
||
});
|
||
NSLog(@"未打开---%ld", tag);
|
||
}else if ([_ktvPlayer getPlayerState] == AgoraMediaPlayerStateOpenCompleted) {
|
||
if (self.isPlayBgMusic) {
|
||
[self ktv_OriginalSingSetting:1];
|
||
}
|
||
NSInteger tag = [_ktvPlayer play];
|
||
NSLog(@"内容中心播放---%ld", tag);
|
||
}else if ([_ktvPlayer getPlayerState] == AgoraMediaPlayerStateStopped) {
|
||
NSInteger tag = [_ktvPlayer openMediaWithSongCode:_songModel.song_code startPos:0];
|
||
NSLog(@"内容中心播放---%ld", tag);
|
||
}else if ([_ktvPlayer getPlayerState] == AgoraMediaPlayerStatePlayBackAllLoopsCompleted) {
|
||
NSInteger tag = [_ktvPlayer openMediaWithSongCode:_songModel.song_code startPos:0];
|
||
NSLog(@"内容中心播放---%ld", tag);
|
||
}
|
||
}
|
||
} else {
|
||
NSInteger tag = [_ktvPlayer pause];
|
||
NSLog(@"内容中心暂停---%ld", tag);
|
||
}
|
||
|
||
if ([_ktvPlayer getPlayerState] == AgoraMediaPlayerStatePlaying) {
|
||
AgoraRtcChannelMediaOptions *options = [AgoraRtcChannelMediaOptions new];
|
||
options.autoSubscribeAudio = YES;
|
||
options.autoSubscribeVideo = YES;
|
||
options.publishMediaPlayerId = [_ktvPlayer getMediaPlayerId];
|
||
options.publishMediaPlayerAudioTrack = YES;
|
||
[self.agoraKit updateChannelWithMediaOptions:options];
|
||
}
|
||
}
|
||
|
||
-(void)ktv_EndSing{
|
||
// if ([_ktvPlayer getPlayerState] == AgoraMediaPlayerStatePlaying) {
|
||
// [_ktvPlayer stop];
|
||
// }
|
||
[_ktvPlayer stop];
|
||
_songModel = nil;
|
||
}
|
||
-(void)ktv_OriginalSingSetting:(BOOL)isOriginal {
|
||
//原唱0 伴奏1
|
||
[self.ktvPlayer selectAudioTrack:!isOriginal];
|
||
}
|
||
|
||
-(BOOL)ktv_GetErfan {
|
||
return self.isErfan;
|
||
}
|
||
|
||
-(void)ktv_SetErfan:(BOOL)isErfan {
|
||
self.isErfan = isErfan;
|
||
[self.agoraKit enableInEarMonitoring:isErfan];
|
||
}
|
||
|
||
//-(void)ktv_setVoiceEffert{
|
||
// [self.agoraKit setAudioEffectPreset:(AgoraAudioEffectPreset)];
|
||
//}
|
||
|
||
|
||
-(void)ktv_SetRenshengVolume:(float)ratio {
|
||
int volume = ratio*400;
|
||
self.renshengVolume = volume;
|
||
// if (self.useMicrophone) {
|
||
[self.agoraKit adjustRecordingSignalVolume:volume];
|
||
// }
|
||
}
|
||
-(void)ktv_SetBanzouVolume:(float)ratio {
|
||
int volume = ratio*100;
|
||
[self.ktvPlayer adjustPlayoutVolume:volume];
|
||
[self.ktvPlayer adjustPublishSignalVolume:volume];
|
||
}
|
||
-(float)ktv_GetBanzouVolume {
|
||
int volume = [self.ktvPlayer getPlayoutVolume];
|
||
// [self.agoraKit getAudioMixingPlayoutVolume];
|
||
return volume/100.0;
|
||
}
|
||
|
||
|
||
-(NSMutableArray *)bgMusicArray{
|
||
if (!_bgMusicArray) {
|
||
_bgMusicArray = [NSMutableArray array];
|
||
}
|
||
return _bgMusicArray;
|
||
}
|
||
|
||
|
||
- (AgoraScreenCaptureParameters2 *)screenParams {
|
||
if (_screenParams == nil) {
|
||
_screenParams = [[AgoraScreenCaptureParameters2 alloc] init];
|
||
_screenParams.captureAudio = YES;
|
||
_screenParams.captureVideo = YES;
|
||
AgoraScreenAudioParameters *audioParams = [[AgoraScreenAudioParameters alloc] init];
|
||
audioParams.captureSignalVolume = 50;
|
||
_screenParams.audioParams = audioParams;
|
||
AgoraScreenVideoParameters *videoParams = [[AgoraScreenVideoParameters alloc] init];
|
||
videoParams.dimensions = [self screenShareVideoDimension];
|
||
videoParams.frameRate = AgoraVideoFrameRateFps15;
|
||
videoParams.bitrate = AgoraVideoBitrateStandard;
|
||
// _screenParams.videoParams = videoParams;
|
||
}
|
||
return _screenParams;
|
||
}
|
||
- (CGSize)screenShareVideoDimension {
|
||
CGSize screenSize = UIScreen.mainScreen.bounds.size;
|
||
CGSize boundingSize = CGSizeMake(540, 960);
|
||
CGFloat mW = boundingSize.width / screenSize.width;
|
||
CGFloat mH = boundingSize.height / screenSize.height;
|
||
if (mH < mW) {
|
||
boundingSize.width = boundingSize.height / screenSize.height * screenSize.width;
|
||
} else if (mW < mH) {
|
||
boundingSize.height = boundingSize.width / screenSize.width * screenSize.height;
|
||
}
|
||
return boundingSize;
|
||
}
|
||
-(void)startScreenCapture{
|
||
|
||
// /// 更新
|
||
//// [self prepareSystemBroadcaster];
|
||
//
|
||
// AgoraRtcChannelMediaOptions *option = [AgoraRtcChannelMediaOptions new];
|
||
// option.publishMicrophoneTrack = YES;
|
||
// option.publishMediaPlayerAudioTrack = YES;
|
||
// option.enableAudioRecordingOrPlayout = YES;
|
||
// option.publishScreenCaptureVideo = YES;
|
||
// option.publishScreenCaptureAudio = YES;
|
||
// option.publishCameraTrack = NO;
|
||
// option.clientRoleType = AgoraClientRoleBroadcaster;
|
||
// [self.agoraKit updateChannelWithMediaOptions:option];
|
||
// [self.agoraKit startScreenCapture:self.screenParams];
|
||
// [self.agoraKit muteLocalVideoStream:NO];
|
||
// [self.agoraKit enableVideo];
|
||
// [self.agoraKit enableLocalVideo:YES];
|
||
// [self prepareSystemBroadcaster];
|
||
// for (UIView *view in self.systemBroadcastPicker.subviews) {
|
||
// if ([view isKindOfClass:[UIButton class]]) {
|
||
// [((UIButton *)view) sendActionsForControlEvents:(UIControlEventAllEvents)];
|
||
// break;
|
||
// }
|
||
// }
|
||
// AgoraVideoEncoderConfiguration *encoderConfig = [[AgoraVideoEncoderConfiguration alloc] initWithSize:CGSizeMake(960, 540)
|
||
// frameRate:(AgoraVideoFrameRateFps15)
|
||
// bitrate:AgoraVideoBitrateStandard
|
||
// orientationMode:(AgoraVideoOutputOrientationModeFixedPortrait)
|
||
// mirrorMode:(AgoraVideoMirrorModeAuto)];
|
||
// [self.agoraKit setVideoEncoderConfiguration:encoderConfig];
|
||
//
|
||
// // set up local video to render your local camera preview
|
||
// AgoraRtcVideoCanvas *videoCanvas = [[AgoraRtcVideoCanvas alloc] init];
|
||
// videoCanvas.uid = QXGlobal.shareGlobal.loginModel.user_id.longLongValue;
|
||
// // the view to be binded
|
||
//// videoCanvas.view = self.localView.videoView;
|
||
// videoCanvas.renderMode = AgoraVideoRenderModeHidden;
|
||
// [self.agoraKit setupLocalVideo:videoCanvas];
|
||
// // you have to call startPreview to see local video
|
||
// [self.agoraKit startPreview];
|
||
// [self.agoraKit enableAudio];
|
||
// [self.agoraKit enableVideo];
|
||
|
||
|
||
[self.agoraKit setScreenCaptureScenario:AgoraScreenScenarioVideo];
|
||
self.option.clientRoleType = AgoraClientRoleBroadcaster;
|
||
[self.agoraKit updateChannelWithMediaOptions:self.option];
|
||
[self.agoraKit startScreenCapture:self.screenParams];
|
||
[self prepareSystemBroadcaster];
|
||
for (UIView *view in self.systemBroadcastPicker.subviews) {
|
||
if ([view isKindOfClass:[UIButton class]]) {
|
||
[((UIButton *)view) sendActionsForControlEvents:(UIControlEventAllEvents)];
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
- (void)prepareSystemBroadcaster {
|
||
CGRect frame = CGRectMake(0, 0, 60, 60);
|
||
self.systemBroadcastPicker = [[RPSystemBroadcastPickerView alloc]initWithFrame:frame];
|
||
self.systemBroadcastPicker.showsMicrophoneButton = NO;
|
||
self.systemBroadcastPicker.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin;
|
||
NSString *bundleId = [NSBundle mainBundle].bundleIdentifier;
|
||
self.systemBroadcastPicker.preferredExtension = [NSString stringWithFormat:@"%@.QXLiveScreen",bundleId];
|
||
}
|
||
|
||
|
||
-(void)startPreViewWithUid:(NSInteger)uid view:(nonnull UIView *)view{
|
||
AgoraRtcVideoCanvas* videoCanvas = [[AgoraRtcVideoCanvas alloc]init];
|
||
videoCanvas.uid = uid;
|
||
videoCanvas.view = view;
|
||
videoCanvas.renderMode = AgoraVideoRenderModeFit;
|
||
videoCanvas.setupMode = AgoraVideoViewSetupAdd;
|
||
[self.agoraKit setupRemoteVideo:videoCanvas];
|
||
}
|
||
- (AgoraRtcChannelMediaOptions *)option {
|
||
if (_option == nil) {
|
||
_option = [[AgoraRtcChannelMediaOptions alloc] init];
|
||
_option.clientRoleType = AgoraClientRoleAudience;
|
||
_option.publishCameraTrack = NO;
|
||
_option.publishMicrophoneTrack = YES;
|
||
_option.publishScreenCaptureVideo = NO;
|
||
_option.publishScreenCaptureAudio = NO;
|
||
}
|
||
return _option;
|
||
}
|
||
@end
|