// // ClassroomService.m // SealClass // // Created by LiFei on 2019/2/27. // Copyright © 2019 RongCloud. All rights reserved. // #import "ClassroomService.h" #import "MemberChangeMessage.h" #import "WhiteboardMessage.h" #import "DeviceMessage.h" #import "DisplayCommandMessage.h" #import "MemberChangeMessage.h" #import "TurnPageMessage.h" #import "RoleChangedMessage.h" #import "AssistantTransferMessage.h" #import "ApplySpeechMessage.h" #import "TicketExpiredMessage.h" #import "InviteUpgradeMessage.h" #import "ControlDeviceNotifyMessage.h" #import "SongDownloadMessage.h" #import "SongDownloadCallbackMessage.h" #import "AccompanyDownloadMessage.h" #import "AccompanyDownloadCallbackMessage.h" #import "KeyChainTools.h" #import @interface ClassroomService () @property (nonatomic, copy) NSString *auth; @end @implementation ClassroomService + (instancetype)sharedService { static ClassroomService *service; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ service = [[ClassroomService alloc] init]; }); return service; } #pragma mark - IM - (void)registerCommandMessages { [[RCIM sharedRCIM] registerMessageType:[MemberChangeMessage class]]; [[RCIM sharedRCIM] registerMessageType:[WhiteboardMessage class]]; [[RCIM sharedRCIM] registerMessageType:[DeviceMessage class]]; [[RCIM sharedRCIM] registerMessageType:[DisplayCommandMessage class]]; [[RCIM sharedRCIM] registerMessageType:[TurnPageMessage class]]; [[RCIM sharedRCIM] registerMessageType:[RoleChangedMessage class]]; [[RCIM sharedRCIM] registerMessageType:[AssistantTransferMessage class]]; [[RCIM sharedRCIM] registerMessageType:[ApplySpeechMessage class]]; [[RCIM sharedRCIM] registerMessageType:[ApplySpeechResultMessage class]]; [[RCIM sharedRCIM] registerMessageType:[TicketExpiredMessage class]]; [[RCIM sharedRCIM] registerMessageType:[InviteUpgradeMessage class]]; [[RCIM sharedRCIM] registerMessageType:[ControlDeviceNotifyMessage class]]; [[RCIM sharedRCIM] registerMessageType:[NodePlayMessage class]]; [[RCIM sharedRCIM] registerMessageType:[SongDownloadMessage class]]; [[RCIM sharedRCIM] registerMessageType:[SongDownloadCallbackMessage class]]; [[RCIM sharedRCIM] registerMessageType:[AccompanyDownloadMessage class]]; [[RCIM sharedRCIM] registerMessageType:[AccompanyDownloadCallbackMessage class]]; } - (BOOL)isHoldMessage:(RCMessage *)message { BOOL needHold = NO; if ([message.content isKindOfClass:[MemberChangeMessage class]]) { needHold = NO; [self onReceiveCommandMessage:(MemberChangeMessage*)message.content]; } else if ([message.content isKindOfClass:[WhiteboardMessage class]]) { needHold = YES; [self onReceiveWhiteboardMessage:(WhiteboardMessage*)message.content]; } else if ([message.content isKindOfClass:[DeviceMessage class]]) { needHold = YES; [self onReceiveDeviceMessage:(DeviceMessage*)message.content withSenderId:message.senderUserId]; } else if([message.content isKindOfClass:[DisplayCommandMessage class]]) { needHold = YES; [self onReceiveDisplayCommandMessage:(DisplayCommandMessage*)message.content]; } else if([message.content isKindOfClass:[ApplySpeechMessage class]]) { needHold = YES; [self onReceiveApplySpeechMessage:(ApplySpeechMessage*)message.content]; } else if([message.content isKindOfClass:[TurnPageMessage class]]) { needHold = YES; [self onReceiveTurnPageMessage:(TurnPageMessage*)message.content]; } else if([message.content isKindOfClass:[RoleChangedMessage class]]) { needHold = YES; [self onReceiveRoleChangedMessage:(RoleChangedMessage*)message.content]; } else if([message.content isKindOfClass:[AssistantTransferMessage class]]) { needHold = YES; [self onReceiveAssistantTransferMessage:(AssistantTransferMessage*)message.content]; } else if([message.content isKindOfClass:[ApplySpeechResultMessage class]]) { needHold = YES; [self onReceiveSpeechResultMessage:(ApplySpeechResultMessage*)message.content]; } else if ([message.content isKindOfClass:[TicketExpiredMessage class]]) { needHold = YES; [self onReceiveTicketExpiredMessage:(TicketExpiredMessage *)message.content]; } else if ([message.content isKindOfClass:[InviteUpgradeMessage class]]) { needHold = YES; [self onReceiveInviteUpgradeMessage:(InviteUpgradeMessage *)message.content]; } else if ([message.content isKindOfClass:[ControlDeviceNotifyMessage class]]) { needHold = YES; [self onReceiveControlDeviceNotifyMessage:(ControlDeviceNotifyMessage *)message.content]; } else if ([message.content isKindOfClass:[NodePlayMessage class]]) { needHold = YES; [self onReceiveNodePlayMessage:(NodePlayMessage *)message.content]; } else if ([message.content isKindOfClass:[SongDownloadMessage class]]) { needHold = YES; } else if ([message.content isKindOfClass:[SongDownloadCallbackMessage class]]) { needHold = YES; } else if ([message.content isKindOfClass:[AccompanyDownloadMessage class]]) { // 下载伴奏消息 needHold = YES; [self onReceiveDownloadAccompanyMessage:(AccompanyDownloadMessage *)message.content]; } else if ([message.content isKindOfClass:[AccompanyDownloadCallbackMessage class]]) { needHold = YES; } return needHold; } #pragma mark - HTTP - (void)joinClassroom:(NSString *)roomId userName:(NSString *)userName isAudience:(BOOL)audience success:(void (^)(Classroom * _Nonnull))successBlock error:(void (^)(ErrorCode, NSString * _Nonnull))errorBlock { if (roomId.length == 0 || userName.length == 0) { [self callbackFailureDescription:ErrorCodeParameterError]; return; } [KSNetworkingManager roomJoinRequest:KS_POST roomId:roomId success:^(NSDictionary * _Nonnull dic) { if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) { Classroom *room = [Classroom classroomFromJson:[dic dictionaryValueForKey:@"data"]]; self.currentRoom = room; if (successBlock) { dispatch_main_async_safe(^{ successBlock(room); }) } } else { errorBlock([dic integerValueForKey:@"code"], MESSAGEKEY); } } faliure:^(NSError * _Nonnull error) { if (errorBlock) { dispatch_main_async_safe(^{ errorBlock(error.code, @"加入房间失败"); }) } }]; } - (void)joinRoomFailerNotify { if (![self checkWhetherInRoom]) { if ([self.classroomDelegate respondsToSelector:@selector(roomDidLeave)]) { [self.classroomDelegate roomDidLeave]; } return; } [KSNetworkingManager joinRoomFailureRequest:KS_POST roomId:self.currentRoom.roomId success:^(NSDictionary * _Nonnull dic) { if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) { NSLog(@"------ 通知成功"); } else { NSLog(@"------ 通知失败"); } } faliure:^(NSError * _Nonnull error) { NSLog(@"------ 通知失败"); }]; } - (void)leaveClassroom { if (![self checkWhetherInRoom]) { if ([self.classroomDelegate respondsToSelector:@selector(roomDidLeave)]) { [self.classroomDelegate roomDidLeave]; } return; } NSLog(@"leave classroom start"); [KSNetworkingManager roomLeaveRequest:KS_POST roomId:self.currentRoom.roomId success:^(NSDictionary * _Nonnull dic) { if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) { dispatch_main_async_safe(^{ if ([self.classroomDelegate respondsToSelector:@selector(roomDidLeave)]) { [self.classroomDelegate roomDidLeave]; } }); } else { dispatch_main_async_safe(^{ if ([self.classroomDelegate respondsToSelector:@selector(roomDidLeave)]) { [self.classroomDelegate roomDidLeave]; } }); NSLog(@"退出失败:%@",MESSAGEKEY); } } faliure:^(NSError * _Nonnull error) { dispatch_main_async_safe(^{ if ([self.classroomDelegate respondsToSelector:@selector(roomDidLeave)]) { [self.classroomDelegate roomDidLeave]; } }); NSLog(@"退出失败"); }]; } // 下载伴奏完成回调 - (void)adjustAccompanySongNotifer:(NSString *)songId status:(BOOL)status { if (![self checkWhetherInRoom]) { [self callbackFailureDescription:ErrorCodeUserNotExistInRoom]; return; } NSString *statusString = status == YES ? @"1" : @"2"; [KSNetworkingManager musicSheetDownNotifyRequest:KS_POST roomId:self.currentRoom.roomId status:statusString accompanimentId:songId success:^(NSDictionary * _Nonnull dic) { if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) { } else { [self callbackFailureDescription:ErrorCodeOther]; } } faliure:^(NSError * _Nonnull error) { [self callbackFailureDescription:ErrorCodeOther]; }]; } #pragma mark 操作当前用户设备状态,仅老师/学员有权限 - (void)enableDevice:(BOOL)enable withType:(DeviceType)type { if (![self checkWhetherInRoom]) { [self callbackFailureDescription:ErrorCodeUserNotExistInRoom]; return; } if (type == DeviceTypeHandup) { if (self.currentRoom.currentDisplayType == DisplayTypeStudent && [self.currentRoom.currentDisplayURI isEqualToString:UserDefault(UIDKey)]) { return; } } NSString *deviceType = [self getDeviceTypeDesc:type]; [KSNetworkingManager roomDeviceSync:KS_POST deviceType:deviceType roomId:self.currentRoom.roomId enable:enable success:^(NSDictionary * _Nonnull dic) { if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) { if (type == DeviceTypeMicrophone) { [self.currentRoom updateMember:self.currentRoom.currentMember.userId forMicrophone:enable]; } else if (type == DeviceTypeCamera) { [self.currentRoom updateMember:self.currentRoom.currentMember.userId forCamera:enable]; } else if (type == DeviceTypeMusicMode) { [self.currentRoom updateMember:self.currentRoom.currentMember.userId forMusicMode:enable]; } } else { [self callbackFailureDescription:ErrorCodeOther]; } } faliure:^(NSError * _Nonnull error) { [self callbackFailureDescription:ErrorCodeOther]; }]; } - (void)approveEnableDevice:(DeviceType)type { if (![self checkWhetherInRoom]) { [self callbackFailureDescription:ErrorCodeUserNotExistInRoom]; return; } NSString *deviceType = [self getDeviceTypeDesc:type]; [KSNetworkingManager deviceApprove:KS_POST deviceType:deviceType roomId:self.currentRoom.roomId success:^(NSDictionary * _Nonnull dic) { if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) { } else { [self callbackFailureDescription:ErrorCodeOther]; } } faliure:^(NSError * _Nonnull error) { [self callbackFailureDescription:ErrorCodeOther]; }]; } - (void)rejectEnableDevice:(DeviceType)type { if (![self checkWhetherInRoom]) { [self callbackFailureDescription:ErrorCodeUserNotExistInRoom]; return; } NSString *deviceType = [self getDeviceTypeDesc:type]; [KSNetworkingManager deviceReject:KS_POST deviceType:deviceType roomId:self.currentRoom.roomId success:^(NSDictionary * _Nonnull dic) { if ([dic integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) { } else { [self callbackFailureDescription:ErrorCodeOther]; } } faliure:^(NSError * _Nonnull error) { [self callbackFailureDescription:ErrorCodeOther]; }]; } #pragma mark - Util - (NSString *)getDeviceTypeDesc:(DeviceType)type { switch (type) { case DeviceTypeCamera: return @"CAMERA"; case DeviceTypeMicrophone: return @"MICROPHONE"; case DeviceTypeMusicMode: return @"MUSIC_MODE"; case DeviceTypeHandup: return @"HAND_UP"; case DeviceTypeExamSong: return @"EXAM_SONG"; case DeviceTypeMusicScore: return @"MUSIC_SHEET"; case DeviceTypeAccompany: return @"ACCOMPANIMENT"; default: return @""; } } #pragma mark - Helper - (BOOL)checkWhetherInRoom { return self.currentRoom.roomId.length > 0; } - (void)callbackFailureDescription:(ErrorCode)code { dispatch_main_async_safe(^{ if ([self.classroomDelegate respondsToSelector:@selector(errorDidOccur:)]) { [self.classroomDelegate errorDidOccur:code]; } }); } - (void)onReceiveCommandMessage:(MemberChangeMessage *)msg{ dispatch_main_async_safe(^{ if(msg.action == MemberChangeActionJoin) { if([self.classroomDelegate respondsToSelector:@selector(memberDidJoin:)]) { RoomMember *mem = [[RoomMember alloc] init]; mem.userId = msg.userId; mem.name = msg.userName; mem.role = (Role)msg.role; mem.joinTime = msg.timestamp; mem.cameraEnable = YES; mem.microphoneEnable = YES; mem.headUrl = msg.avatar; if ([self.currentRoom addMemeber:mem]) { [self.classroomDelegate memberDidJoin:mem]; } } }else if(msg.action == MemberChangeActionLeave){ if([self.classroomDelegate respondsToSelector:@selector(memberDidLeave:)]) { RoomMember *mem = [[RoomMember alloc] init]; mem.userId = msg.userId; mem.name = msg.userName; mem.role = (Role)msg.role; mem.joinTime = msg.timestamp; if([self.currentRoom removeMemeber:mem]) { [self.classroomDelegate memberDidLeave:mem]; } } }else if(msg.action == MemberChangeActionKick) { if ([msg.userId isEqualToString:self.currentRoom.currentMember.userId]) { if ([self.classroomDelegate respondsToSelector:@selector(roomDidLeave)]) { [self.classroomDelegate roomDidLeave]; } } else { RoomMember *mem = [self.currentRoom getMember:msg.userId]; [self.currentRoom removeMemeber:mem]; if([self.classroomDelegate respondsToSelector:@selector(memberDidKick:)]) { [self.classroomDelegate memberDidKick:mem]; } } } }); } - (void)onReceiveWhiteboardMessage:(WhiteboardMessage *)msg{ dispatch_main_async_safe(^{ if(WhiteboardActionCreate == msg.action) { if([self.classroomDelegate respondsToSelector:@selector(whiteboardDidCreate:)]) { Whiteboard *wBoard = [[Whiteboard alloc] init]; wBoard.boardId = msg.whiteboardId; wBoard.name = msg.whiteboardName; [self.classroomDelegate whiteboardDidCreate:wBoard]; } }else if (WhiteboardActionDelete == msg.action) { if([self.classroomDelegate respondsToSelector:@selector(whiteboardDidDelete:)]) { Whiteboard *wBoard = [[Whiteboard alloc] init]; wBoard.boardId = msg.whiteboardId; wBoard.name = msg.whiteboardName; [self.classroomDelegate whiteboardDidDelete:wBoard]; } } }); } - (void)onReceiveDeviceMessage:(DeviceMessage *)msg withSenderId:(NSString *)senderId{ dispatch_main_async_safe(^{ if (msg.type == DeviceTypeCamera) { [self.currentRoom updateMember:msg.userId forCamera:msg.enable]; if ([self.classroomDelegate respondsToSelector:@selector(deviceDidEnable:type:forUser:operator:)]) { [self.classroomDelegate deviceDidEnable:msg.enable type:DeviceTypeCamera forUser:[self.currentRoom getMember:msg.userId] operator:senderId]; } } else if (msg.type == DeviceTypeMicrophone) { [self.currentRoom updateMember:msg.userId forMicrophone:msg.enable]; if ([self.classroomDelegate respondsToSelector:@selector(deviceDidEnable:type:forUser:operator:)]) { [self.classroomDelegate deviceDidEnable:msg.enable type:DeviceTypeMicrophone forUser:[self.currentRoom getMember:msg.userId] operator:senderId]; } } else if (msg.type == DeviceTypeMusicMode) { [self.currentRoom updateMember:msg.userId forMusicMode:msg.enable]; if ([self.classroomDelegate respondsToSelector:@selector(deviceDidEnable:type:forUser:operator:)]) { [self.classroomDelegate deviceDidEnable:msg.enable type:DeviceTypeMusicMode forUser:[self.currentRoom getMember:msg.userId] operator:senderId]; } } else if (msg.type == DeviceTypeHandup) { [self.currentRoom updateMember:msg.userId forHandsUp:msg.enable]; if ([self.classroomDelegate respondsToSelector:@selector(deviceDidEnable:type:forUser:operator:)]) { [self.classroomDelegate deviceDidEnable:msg.enable type:DeviceTypeHandup forUser:[self.currentRoom getMember:msg.userId] operator:senderId]; } } else if (msg.type == DeviceTypeExamSong) { [self.currentRoom updateMember:msg.userId forExamSong:msg.enable]; if ([self.classroomDelegate respondsToSelector:@selector(deviceDidEnable:type:forUser:operator:)]) { [self.classroomDelegate deviceDidEnable:msg.enable type:DeviceTypeExamSong forUser:[self.currentRoom getMember:msg.userId] operator:senderId]; } } else if (msg.type == DeviceTypeAccompany) { // 伴奏 self.currentRoom.soundVolume = msg.soundVolume; [self.currentRoom updateMember:msg.userId forAccompany:msg.enable songId:msg.songId]; if ([self.classroomDelegate respondsToSelector:@selector(deviceDidEnable:type:forUser:operator:)]) { [self.classroomDelegate deviceDidEnable:msg.enable type:DeviceTypeAccompany forUser:[self.currentRoom getMember:msg.userId] operator:senderId]; } } else if (msg.type == DeviceTypeMusicScore) { // 原声 self.currentRoom.soundVolume = msg.soundVolume; [self.currentRoom updateMember:msg.userId forMusicScore:msg.enable songId:msg.songId]; if ([self.classroomDelegate respondsToSelector:@selector(deviceDidEnable:type:forUser:operator:)]) { [self.classroomDelegate deviceDidEnable:msg.enable type:DeviceTypeMusicScore forUser:[self.currentRoom getMember:msg.userId] operator:senderId]; } } }); } - (void)onReceiveDisplayCommandMessage:(DisplayCommandMessage *)msg{ NSLog(@"%@--------",msg.display); dispatch_main_async_safe(^{ [self.currentRoom updateDisplayUri:msg.display]; DisplayType type = self.currentRoom.currentDisplayType; if (type == DisplayTeacher) { NSLog(@"------- DisplayTeacher"); if ([self.classroomDelegate respondsToSelector:@selector(teacherDidDisplay)]) { [self.classroomDelegate teacherDidDisplay]; } } else if (type == DisplayWhiteboard) { if ([self.classroomDelegate respondsToSelector:@selector(whiteboardDidDisplay:)]) { [self.classroomDelegate whiteboardDidDisplay:self.currentRoom.currentDisplayURI]; } } else if (type == DisplaySharedScreen) { if ([self.classroomDelegate respondsToSelector:@selector(sharedScreenDidDisplay:)]) { [self.classroomDelegate sharedScreenDidDisplay:self.currentRoom.currentDisplayURI]; } } else if (type == DisplayNone) { if ([self.classroomDelegate respondsToSelector:@selector(noneDidDisplay)]) { [self.classroomDelegate noneDidDisplay]; } } else if (type == DisplayTypeStudent) { if ([self.classroomDelegate respondsToSelector:@selector(studentDidDisplay:)]) { [self.classroomDelegate studentDidDisplay:self.currentRoom.currentDisplayURI]; } } }); } - (void)onReceiveApplySpeechMessage:(ApplySpeechMessage *)msg { } - (void)onReceiveSpeechResultMessage:(ApplySpeechResultMessage *)msg { } - (void)onReceiveTurnPageMessage:(TurnPageMessage *)msg { } - (void)onReceiveRoleChangedMessage:(RoleChangedMessage *)msg { } - (void)onReceiveAssistantTransferMessage:(AssistantTransferMessage *)msg { } - (void)onReceiveTicketExpiredMessage:(TicketExpiredMessage *)msg { } - (void)onReceiveInviteUpgradeMessage:(InviteUpgradeMessage *)msg { } - (void)onReceiveControlDeviceNotifyMessage:(ControlDeviceNotifyMessage *)msg { dispatch_main_async_safe(^{ if (msg.action == ControlDeviceActionInvite) { if ([self.classroomDelegate respondsToSelector:@selector(deviceDidInviteEnable:ticket:)]) { [self.classroomDelegate deviceDidInviteEnable:msg.type ticket:msg.ticket]; } } else if (msg.action == ControlDeviceActionApprove) { } else if (msg.action == ControlDeviceActionReject) { } }); } - (void)onReceiveNodePlayMessage:(NodePlayMessage *)msg { dispatch_main_async_safe(^{ if (self.currentRoom.currentMember.role == RoleStudent) { if ([self.classroomDelegate respondsToSelector:@selector(playNodeAction:userId:rate:beatType:volume:)]) { [self.classroomDelegate playNodeAction:msg.enable userId:msg.userId rate:msg.rate beatType:msg.customType volume:msg.playVolume]; } } }); } // 通知下载曲目 - (void)onReceiveDownloadAccompanyMessage:(AccompanyDownloadMessage *)msg { // 通知下载曲目 dispatch_main_async_safe(^{ NSString *songUrl = msg.url; NSString *accompanyUrl = msg.mp3Url; BOOL isEmpty = [NSString isEmptyString:songUrl] && [NSString isEmptyString:accompanyUrl]; if (self.currentRoom.currentMember.role == RoleStudent) { if ([self.classroomDelegate respondsToSelector:@selector(accompanyDownloadCallback:accompanyUrl:songId:)] && !isEmpty) { // 记录曲目 ClassSongMessage *songMessage = [[ClassSongMessage alloc] init]; songMessage.musicScoreAccompanimentId = msg.examSongId.intValue; songMessage.speed = msg.speed; songMessage.url = msg.url; songMessage.mp3Url = msg.mp3Url; [self.currentRoom updateMemberAccompamy:self.currentRoom.currentMember.userId songMessage:songMessage]; [self.classroomDelegate accompanyDownloadCallback:songUrl accompanyUrl:accompanyUrl songId:msg.examSongId]; } } }); } @end