|
@@ -6,18 +6,1074 @@
|
|
|
//
|
|
|
|
|
|
#import "KSAccompanyWebViewController.h"
|
|
|
+#import "RecordCheckManager.h"
|
|
|
+#import "KSAQRecordManager.h"
|
|
|
+#import "KSWebSocketManager.h"
|
|
|
+#import "KSVideoRecordManager.h"
|
|
|
+#import "KSWebNavView.h"
|
|
|
|
|
|
-@interface KSAccompanyWebViewController ()
|
|
|
+#import "KSAudioSessionManager.h"
|
|
|
+#import "KSCloudBeatView.h"
|
|
|
+#import "MidiPlayerEngine.h"
|
|
|
|
|
|
+#define KSMidiSongFileKey (@"KSDownloadMidiSong")
|
|
|
+
|
|
|
+@interface KSAccompanyWebViewController ()<KSAQRecordManagerDelegate,KSAudioSessionManagerDelegate,PlayerEngineDelegate>
|
|
|
+
|
|
|
+@property (nonatomic, strong) KSAudioSessionManager *audioSessionManager;
|
|
|
+
|
|
|
+@property (nonatomic, assign) MetronomeType beatType;
|
|
|
+
|
|
|
+@property (nonatomic, strong) MidiPlayerEngine *playerEngine; // player
|
|
|
+
|
|
|
+@property (nonatomic, assign) BOOL initEngineSuccess; // 加载引擎是否成功
|
|
|
+
|
|
|
+@property (nonatomic, assign) float songOriginalSpeed;
|
|
|
+
|
|
|
+@property (nonatomic, assign) float currentSpeed; // 当前播放的速度
|
|
|
+
|
|
|
+@property (nonatomic, assign) BOOL isPlaying; // 是否正在播放的状态
|
|
|
+
|
|
|
+@property (nonatomic, strong) NSString *currentSongId; // song id
|
|
|
+
|
|
|
+@property (nonatomic, strong) NSDictionary *configEngineParm; // 初始化mid播放引擎的参数
|
|
|
+
|
|
|
+@property (nonatomic, strong) NSMutableDictionary *metronomeParm; // 节拍器播放的参数
|
|
|
+
|
|
|
+// 是否发送了musicXML信息
|
|
|
+@property (nonatomic, assign) BOOL hasSendStartMessage;
|
|
|
+
|
|
|
+@property (nonatomic, strong) KSAQRecordManager *AQManager;
|
|
|
+
|
|
|
+@property (nonatomic, strong) KSWebSocketManager *socketManager;
|
|
|
+
|
|
|
+@property (nonatomic, strong) NSMutableDictionary *evaluatParm;
|
|
|
+
|
|
|
+// 录制的message
|
|
|
+@property (nonatomic, strong) NSMutableDictionary *recordParm;
|
|
|
+
|
|
|
+// 评测开始时发送recordStart消息的标识
|
|
|
+@property (nonatomic, assign) BOOL isCompareStart;
|
|
|
+// 校音开始时发送 checkStart消息标识
|
|
|
+@property (nonatomic, assign) BOOL isSoundCheckStart;
|
|
|
+
|
|
|
+// 自定义UI控件容器
|
|
|
+@property (nonatomic, strong) UIView *viewContainer;
|
|
|
+
|
|
|
+@property (nonatomic, strong) KSVideoRecordManager *videoRecordManager;
|
|
|
+
|
|
|
+@property (nonatomic, strong) NSDictionary *endRecordParm;
|
|
|
+
|
|
|
+@property (nonatomic, assign) BOOL isCameraOpen;
|
|
|
@end
|
|
|
|
|
|
@implementation KSAccompanyWebViewController
|
|
|
|
|
|
+- (void)handerAudioInterruption {
|
|
|
+ if (_playerEngine) {
|
|
|
+ [self stopPlayAction];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)resumeAudioSession {
|
|
|
+ // 恢复
|
|
|
+ if (_playerEngine) {
|
|
|
+ [self.playerEngine resumeAUGraph];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 打断处理
|
|
|
+- (void)audioInterruption {
|
|
|
+ if (_videoRecordManager) {
|
|
|
+ [self.videoRecordManager resetSession];
|
|
|
+ }
|
|
|
+ [self handerAudioInterruption];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)stopSession {
|
|
|
+ if (_videoRecordManager) {
|
|
|
+ [self.videoRecordManager stopSession];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
- (void)viewDidLoad {
|
|
|
[super viewDidLoad];
|
|
|
// Do any additional setup after loading the view.
|
|
|
+ [self configAudioSession];
|
|
|
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appEnterBackground) name:@"appEnterBackground" object:nil];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)connectSocketService {
|
|
|
+
|
|
|
+ MJWeakSelf;
|
|
|
+ self.socketManager.didReceiveMessage = ^(id _Nonnull message) {
|
|
|
+ dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
+ // api
|
|
|
+ NSMutableDictionary *sendMessage = [NSMutableDictionary dictionary];
|
|
|
+ [sendMessage setValue:@"sendResult" forKey:@"api"];
|
|
|
+ [sendMessage setValue:message forKey:@"content"];
|
|
|
+ // 服务返回数据传给H5
|
|
|
+ [weakSelf postMessage:sendMessage];
|
|
|
+ });
|
|
|
+ };
|
|
|
+ self.socketManager.connectionStatus = ^(BOOL isSuccess) {
|
|
|
+ dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
+
|
|
|
+ if (!isSuccess) {
|
|
|
+ NSLog(@"-----连接失败");
|
|
|
+ if (weakSelf.hasSendStartMessage) {
|
|
|
+ if (weakSelf.AQManager.isRunning) {
|
|
|
+ NSDictionary *postParm = @{@"api" : @"cancelEvaluating",
|
|
|
+ @"content" : @{@"reson":@"服务异常,请重试"}
|
|
|
+ };
|
|
|
+ [weakSelf postMessage:postParm];
|
|
|
+ [weakSelf stopRecordService];
|
|
|
+ weakSelf.isCompareStart = NO;
|
|
|
+ weakSelf.isSoundCheckStart = NO;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (weakSelf.evaluatParm) {
|
|
|
+ NSMutableDictionary *sendParm = [NSMutableDictionary dictionaryWithDictionary:weakSelf.evaluatParm];
|
|
|
+ NSLog(@"%@",sendParm);
|
|
|
+ NSDictionary *valueDic = [weakSelf.evaluatParm dictionaryValueForKey:@"content"];
|
|
|
+ [valueDic setValue:@"服务异常,请重试" forKey:@"reson"];
|
|
|
+ NSLog(@"%@",valueDic);
|
|
|
+ [sendParm setValue:valueDic forKey:@"content"];
|
|
|
+ [weakSelf postMessage:sendParm];
|
|
|
+ weakSelf.hasSendStartMessage = YES;
|
|
|
+ weakSelf.isCompareStart = NO;
|
|
|
+ weakSelf.isSoundCheckStart = NO;
|
|
|
+ }
|
|
|
+ else { // 其他断开
|
|
|
+ if (weakSelf.AQManager.isRunning) {
|
|
|
+ NSDictionary *postParm = @{@"api" : @"cancelEvaluating",
|
|
|
+ @"content" : @{@"reson":@"服务异常,请重试"}
|
|
|
+ };
|
|
|
+ [weakSelf postMessage:postParm];
|
|
|
+ [weakSelf stopRecordService];
|
|
|
+ weakSelf.isCompareStart = NO;
|
|
|
+ weakSelf.isSoundCheckStart = NO;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ NSLog(@"-----连接成功");
|
|
|
+ if (weakSelf.hasSendStartMessage == NO && weakSelf.evaluatParm) {
|
|
|
+ NSDictionary *content = [weakSelf.evaluatParm dictionaryValueForKey:@"content"];
|
|
|
+ NSString *sendData = [weakSelf configDataCommond:@"musicXml" body:content type:@"SOUND_COMPARE"];
|
|
|
+ [weakSelf sendDataToSocketService:sendData];
|
|
|
+ [weakSelf postMessage:weakSelf.evaluatParm];
|
|
|
+ weakSelf.hasSendStartMessage = YES;
|
|
|
+ NSLog(@"---- send musicXML message");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ };
|
|
|
+ [self.socketManager SRWebSocketOpen];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)appEnterBackground {
|
|
|
+ NSDictionary *parm = @{@"api":@"suspendPlay"};
|
|
|
+ [self postMessage:parm];
|
|
|
+ [self handerAudioInterruption];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)initWebView {
|
|
|
+ [self.view addSubview:self.navView];
|
|
|
+ CGFloat topHeight = kNaviBarHeight;
|
|
|
+ [self.navView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
+ make.left.right.top.mas_equalTo(self.view);
|
|
|
+ make.height.mas_equalTo(kNaviBarHeight);
|
|
|
+ }];
|
|
|
+ if (self.hiddenNavBar) {
|
|
|
+ topHeight = 0.0f;
|
|
|
+ [self.navView mas_updateConstraints:^(MASConstraintMaker *make) {
|
|
|
+ make.height.mas_equalTo(0);
|
|
|
+ }];
|
|
|
+ }
|
|
|
+
|
|
|
+ [self.view addSubview:self.viewContainer];
|
|
|
+ [self.viewContainer mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
+ make.left.right.top.bottom.mas_equalTo(self.view);
|
|
|
+ }];
|
|
|
+
|
|
|
+ if (self.myWebView == nil) {
|
|
|
+
|
|
|
+ WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
|
|
|
+ config.selectionGranularity = WKSelectionGranularityDynamic;
|
|
|
+ config.allowsInlineMediaPlayback = YES;
|
|
|
+ if (@available(iOS 10.0, *)) {
|
|
|
+ config.mediaTypesRequiringUserActionForPlayback = NO;
|
|
|
+ } else {
|
|
|
+ // Fallback on earlier versions
|
|
|
+ config.requiresUserActionForMediaPlayback = NO;
|
|
|
+ }
|
|
|
+ config.processPool = [KSBaseWKWebViewController singleWkProcessPool];
|
|
|
+ config.websiteDataStore = [WKWebsiteDataStore defaultDataStore];
|
|
|
+ //自定义的WKScriptMessageHandler 是为了解决内存不释放的问题
|
|
|
+ WeakWebViewScriptMessageDelegate *weakScriptMessageDelegate = [[WeakWebViewScriptMessageDelegate alloc] initWithDelegate:self];
|
|
|
+ //这个类主要用来做native与JavaScript的交互管理
|
|
|
+ WKUserContentController * wkUController = [[WKUserContentController alloc] init];
|
|
|
+ [wkUController addScriptMessageHandler:weakScriptMessageDelegate name:@"COLEXIU"];
|
|
|
+ config.userContentController = wkUController;
|
|
|
+
|
|
|
+ WKPreferences *preferences = [WKPreferences new];
|
|
|
+ // 是否支出javaScript
|
|
|
+ preferences.javaScriptEnabled = YES;
|
|
|
+ //不通过用户交互,是否可以打开窗口
|
|
|
+ preferences.javaScriptCanOpenWindowsAutomatically = YES;
|
|
|
+ config.preferences = preferences;
|
|
|
+ self.myWebView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:config];
|
|
|
+ self.myWebView.opaque = NO;
|
|
|
+ self.myWebView.UIDelegate = self;
|
|
|
+ self.myWebView.navigationDelegate = self;
|
|
|
+ self.myWebView.scrollView.bounces = NO;
|
|
|
+ self.myWebView.backgroundColor = [UIColor clearColor];
|
|
|
+ self.myWebView.scrollView.backgroundColor = [UIColor clearColor];
|
|
|
+ // 加载进度条和title
|
|
|
+ [self.myWebView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
|
|
|
+ [self.myWebView addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:NULL];
|
|
|
+ [self.view addSubview:self.myWebView];
|
|
|
+ [self.myWebView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
+ make.left.right.mas_equalTo(self.view);
|
|
|
+ make.top.mas_equalTo(self.view.mas_top).offset(topHeight);
|
|
|
+ make.bottom.mas_equalTo(self.view.mas_bottom);
|
|
|
+ }];
|
|
|
+ if (@available(iOS 11.0, *)) {
|
|
|
+ self.myWebView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
|
|
|
+ } else {
|
|
|
+ // Fallback on earlier versions
|
|
|
+ }
|
|
|
+ [self setupProgress];
|
|
|
+ // 修改userAgent
|
|
|
+ [self setUserAgent];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ [self.myWebView reload];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)configRecordManager {
|
|
|
+ self.AQManager = [[KSAQRecordManager alloc] init];
|
|
|
+ self.AQManager.delegate = self;
|
|
|
+}
|
|
|
+
|
|
|
+- (void)viewWillAppear:(BOOL)animated {
|
|
|
+ [super viewWillAppear:animated];
|
|
|
+ [self connectSocketService];
|
|
|
+ if (self.isCameraOpen) {
|
|
|
+ [self.videoRecordManager configSessiondisplayInView:self.viewContainer];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)viewWillDisappear:(BOOL)animated {
|
|
|
+ [super viewWillDisappear:animated];
|
|
|
+ if (_AQManager) {
|
|
|
+ [_AQManager freeAudioQueue];
|
|
|
+ _AQManager = nil;
|
|
|
+ }
|
|
|
+ if (_socketManager) {
|
|
|
+ [self.socketManager SRWebSocketClose];
|
|
|
+ _socketManager = nil;
|
|
|
+ }
|
|
|
+ [self stopSession];
|
|
|
+
|
|
|
+ // 如果退出评测页面 清除 playerEngine
|
|
|
+ if (self.playerEngine) {
|
|
|
+ [self.playerEngine cleanup];
|
|
|
+ self.playerEngine = nil;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+- (void)sendDataToSocketService:(id)data {
|
|
|
+ if (_socketManager) {
|
|
|
+ [self.socketManager sendData:data];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark --- WKScriptMessageHandler
|
|
|
+
|
|
|
+- (void)userContentController:(WKUserContentController *)userContentController
|
|
|
+ didReceiveScriptMessage:(WKScriptMessage *)message {
|
|
|
+ if ([message.name isEqualToString:@"COLEXIU"]) {
|
|
|
+ NSDictionary *parm = [self convertJsonStringToNSDictionary:message.body];
|
|
|
+ // 回到主线程
|
|
|
+ dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
+ if ([[parm stringValueForKey:@"api"] isEqualToString:@"startEvaluating"]) { // 开始评测
|
|
|
+ [self configRecordManager];
|
|
|
+ self.hasSendStartMessage = NO;
|
|
|
+ PREMISSIONTYPE isOk = [RecordCheckManager checkPermissionShowAlert:NO showInView:nil];
|
|
|
+ if (isOk == PREMISSIONTYPE_YES) {
|
|
|
+ self.evaluatParm = [NSMutableDictionary dictionaryWithDictionary:parm];
|
|
|
+ // 如果socket 连上了
|
|
|
+ if (self.socketManager.socketReadyState == SR_OPEN) {
|
|
|
+ NSDictionary *content = [parm dictionaryValueForKey:@"content"];
|
|
|
+ NSString *sendData = [self configDataCommond:@"musicXml" body:content type:@"SOUND_COMPARE"];
|
|
|
+ [self sendDataToSocketService:sendData];
|
|
|
+ [self postMessage:parm];
|
|
|
+ self.hasSendStartMessage = YES;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ [self connectSocketService];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ NSDictionary *postParm = @{@"api" : @"cancelEvaluating",
|
|
|
+ @"content" : @{@"reson":@"没有麦克风权限"}
|
|
|
+ };
|
|
|
+ [self postMessage:postParm];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"endEvaluating"]) {// 停止评测
|
|
|
+ self.evaluatParm = nil;
|
|
|
+ [self stopRecordService];
|
|
|
+ [self postMessage:parm];
|
|
|
+ [self sendEndMessage];
|
|
|
+ }
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"cancelEvaluating"]) { // 取消评测
|
|
|
+ self.evaluatParm = nil;
|
|
|
+ [self stopRecordService];
|
|
|
+ [self postMessage:parm];
|
|
|
+ [self sendEndMessage];
|
|
|
+ }
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"startRecording"]) { // 开始录制
|
|
|
+// self.recordParm = [NSMutableDictionary dictionaryWithDictionary:parm];
|
|
|
+ [self postMessage:parm];
|
|
|
+ self.isCompareStart = YES;
|
|
|
+ [self startRecordService];
|
|
|
+ }
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"endRecording"]) { // 停止录音
|
|
|
+ self.recordParm = nil;
|
|
|
+ [self stopRecordService];
|
|
|
+ [self postMessage:parm];
|
|
|
+ }
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"pauseRecording"]) {
|
|
|
+ [self puaseRecordService];
|
|
|
+ [self postMessage:parm];
|
|
|
+ }
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"resumeRecording"]) {
|
|
|
+ [self resumeRecordService];
|
|
|
+ [self postMessage:parm];
|
|
|
+ }
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"isWiredHeadsetOn"]) {
|
|
|
+ [self configAudioDeviceType:parm];
|
|
|
+ }
|
|
|
+ // 发送消息给socket service
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"proxyMessage"]) {
|
|
|
+ [self sendMessageToSocket:parm];
|
|
|
+ }
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"proxyServiceMessage"]) {
|
|
|
+ NSDictionary *content = [parm dictionaryValueForKey:@"content"];
|
|
|
+ NSString *sendData = [content mj_JSONString];
|
|
|
+ NSLog(@"proxyServiceMessage ------- %@",sendData);
|
|
|
+ [self sendDataToSocketService:sendData];
|
|
|
+ }
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"openCamera"]) { // 开启摄像头
|
|
|
+ PREMISSIONTYPE canOpenCamera = [RecordCheckManager checkCameraPremissionAvaiable:YES showInView:self.view];
|
|
|
+ if (canOpenCamera == PREMISSIONTYPE_YES) {
|
|
|
+ self.isCameraOpen = YES;
|
|
|
+ [self.videoRecordManager configSessiondisplayInView:self.viewContainer];
|
|
|
+ [self postMessage:parm];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"closeCamera"]) { // 关闭摄像头
|
|
|
+ self.isCameraOpen = NO;
|
|
|
+ if (self->_videoRecordManager) {
|
|
|
+ [self.videoRecordManager removeDisplay];
|
|
|
+ }
|
|
|
+ [self postMessage:parm];
|
|
|
+ }
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"startCapture"]) { // 开始录制
|
|
|
+ [RecordCheckManager checkPhotoLibraryPremissionAvaiable:YES showInView:self.view];
|
|
|
+ self.videoRecordManager.audioUrl = self.AQManager.audioUrl;
|
|
|
+ [self.videoRecordManager startRecord];
|
|
|
+ [self postMessage:parm];
|
|
|
+ }
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"endCapture"]) { // 结束录制
|
|
|
+ if (self->_videoRecordManager) {
|
|
|
+ self.endRecordParm = parm;
|
|
|
+ [self.videoRecordManager stopRecord];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ [self postMessage:parm];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"setCaptureMode"]) {
|
|
|
+ NSString *modeString = [[parm dictionaryValueForKey:@"content"] stringValueForKey:@"mode"];
|
|
|
+ BOOL isIgnoreAudio = [modeString isEqualToString:@"evaluating"];
|
|
|
+ [self postMessage:parm];
|
|
|
+ [self.videoRecordManager setIgnoreAudio:isIgnoreAudio];
|
|
|
+ }
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"startSoundCheck"]) { // 开始校音
|
|
|
+ [self configRecordManager];
|
|
|
+ [self postMessage:parm];
|
|
|
+ self.isCompareStart = NO;
|
|
|
+ self.isSoundCheckStart = YES;
|
|
|
+ [self startRecordService];
|
|
|
+ }
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"endSoundCheck"]) {
|
|
|
+ // 结束校音
|
|
|
+ self.isSoundCheckStart = NO;
|
|
|
+ [self stopRecordService];
|
|
|
+ [self postMessage:parm];
|
|
|
+ }
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"videoUpdate"]) { // 上传
|
|
|
+ NSMutableDictionary *sendParm = [NSMutableDictionary dictionaryWithDictionary:parm];
|
|
|
+ NSMutableDictionary *contentParm = [NSMutableDictionary dictionaryWithDictionary:[sendParm dictionaryValueForKey:@"content"]];
|
|
|
+ if (self.videoRecordManager) {
|
|
|
+ [self.videoRecordManager uploadRecordVideoSuccess:^(NSString * _Nonnull videoUrl) {
|
|
|
+ [contentParm setValue:@"success" forKey:@"type"];
|
|
|
+ [contentParm setValue:videoUrl forKey:@"filePath"];
|
|
|
+ [contentParm setValue:@"上传成功" forKey:@"message"];
|
|
|
+ [sendParm setValue:contentParm forKey:@"content"];
|
|
|
+
|
|
|
+ [self postMessage:sendParm];
|
|
|
+ } failure:^(NSString * _Nonnull desc) {
|
|
|
+ [contentParm setValue:@"error" forKey:@"type"];
|
|
|
+ [contentParm setValue:desc forKey:@"message"];
|
|
|
+ [sendParm setValue:contentParm forKey:@"content"];
|
|
|
+ [self postMessage:sendParm];
|
|
|
+ }];
|
|
|
+ }
|
|
|
+ }
|
|
|
+#pragma mark -------- 云教练原生播放对接
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"cloudDetail"]) { // 初始化方法
|
|
|
+ /**
|
|
|
+ api: 'cloudDetail',
|
|
|
+ content: {
|
|
|
+ midi: '',
|
|
|
+ denominator: 4,
|
|
|
+ numerator: 4,
|
|
|
+ // xml整体原始速度
|
|
|
+ originalSpeed: 90,
|
|
|
+ // 间隔(ms)
|
|
|
+ interval: 50
|
|
|
+ }
|
|
|
+ */
|
|
|
+
|
|
|
+ [self configAudioSession];
|
|
|
+ // 重置track num array
|
|
|
+ self.configEngineParm = [parm copy];
|
|
|
+ NSDictionary *content = [parm dictionaryValueForKey:@"content"];
|
|
|
+ NSString *midiUrl = [content stringValueForKey:@"midi"];
|
|
|
+ NSInteger denominator = [content integerValueForKey:@"denominator"];
|
|
|
+ NSInteger numerator = [content integerValueForKey:@"numerator"];
|
|
|
+ NSString *beatString = [NSString stringWithFormat:@"%zd/%zd", numerator,denominator];
|
|
|
+ self.beatType = [self getBeatTypeFromString:beatString];
|
|
|
+
|
|
|
+ float originalSpeed = [content floatValueForKey:@"originalSpeed"];
|
|
|
+ self.songOriginalSpeed = originalSpeed;
|
|
|
+ self.currentSpeed = originalSpeed;
|
|
|
+ NSInteger reportInterval = [content integerValueForKey:@"interval"];
|
|
|
+ // 下载midi文件
|
|
|
+ BOOL hasSaveSong = [self checkSongHasSaveWithSongUrl:midiUrl];
|
|
|
+ NSString *fileName = [[midiUrl componentsSeparatedByString:@"/"] lastObject];
|
|
|
+ NSString *filePath = [self getFilePathWithName:fileName];
|
|
|
+ if (hasSaveSong) {
|
|
|
+ [self configPlayerEngineWithSong:filePath reportTime:reportInterval];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ MJWeakSelf;
|
|
|
+ [self downloadMidiFile:midiUrl success:^{
|
|
|
+ [weakSelf configPlayerEngineWithSong:filePath reportTime:reportInterval];
|
|
|
+ } faliure:^{
|
|
|
+
|
|
|
+ }];
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"cloudGetMediaStatus"]) { // 获取播放状态
|
|
|
+ /**
|
|
|
+ api: 'cloudGetMediaStatus',
|
|
|
+ content: {
|
|
|
+ status: 'init' | 'play' | 'suspend'
|
|
|
+ }
|
|
|
+ */
|
|
|
+ NSString *engineStatus = @"init";
|
|
|
+ if (self.initEngineSuccess) {
|
|
|
+ if (self.isPlaying) {
|
|
|
+ engineStatus = @"play";
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ engineStatus = @"suspend";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ NSMutableDictionary *valueDic = [NSMutableDictionary dictionaryWithDictionary:[parm dictionaryValueForKey:@"content"]];
|
|
|
+ [valueDic setValue:engineStatus forKey:@"status"];
|
|
|
+ NSMutableDictionary *sendParm = [NSMutableDictionary dictionaryWithDictionary:parm];
|
|
|
+ [sendParm setValue:valueDic forKey:@"content"];
|
|
|
+ [self postMessage:sendParm];
|
|
|
+ }
|
|
|
+ // 播放、暂停、进度、播放结束、跳转指定位置
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"cloudPlay"]) { // 播放
|
|
|
+ /**
|
|
|
+ api: 'cloudPlay',
|
|
|
+ content: {
|
|
|
+ // 当前曲目id
|
|
|
+ songID: 0,
|
|
|
+ // xml整体原始速度
|
|
|
+ originalSpeed: 90,
|
|
|
+ // 当前选择速度
|
|
|
+ speed: 90,
|
|
|
+ // 开始时间(ms)
|
|
|
+ startTime: 0
|
|
|
+ // 播放频率
|
|
|
+ hertz:440
|
|
|
+ }
|
|
|
+ */
|
|
|
+ NSDictionary *content = [parm dictionaryValueForKey:@"content"];
|
|
|
+ self.currentSongId = [content stringValueForKey:@"songID"];
|
|
|
+ float speed = [content floatValueForKey:@"speed"];
|
|
|
+ float originalSpeed = [content floatValueForKey:@"originalSpeed"];
|
|
|
+ double rate = speed / originalSpeed;
|
|
|
+ self.currentSpeed = speed;
|
|
|
+ float hertz = [content floatValueForKey:@"hertz"];
|
|
|
+ // 播放的hertz
|
|
|
+ [self.playerEngine adjustPitchByHZ:hertz];
|
|
|
+
|
|
|
+ [self.playerEngine setMusicPlayerSpeed:rate];
|
|
|
+ Float64 startTime = [content doubleValueForKey:@"startTime"];
|
|
|
+ NSLog(@"------%@", [content stringValueForKey:@"startTime"]);
|
|
|
+ [self.playerEngine setProgressTime:(startTime/1000)];
|
|
|
+ // 播放
|
|
|
+ [self playAction];
|
|
|
+ [self postMessage:parm];
|
|
|
+ }
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"cloudSuspend"]) { // 暂停
|
|
|
+ /**
|
|
|
+ api: 'cloudSuspend',
|
|
|
+ content: {
|
|
|
+ // 当前曲目id
|
|
|
+ songID: 0,
|
|
|
+ }
|
|
|
+ */
|
|
|
+ [self stopPlayAction];
|
|
|
+ [self postMessage:parm];
|
|
|
+
|
|
|
+ }
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"cloudSetCurrentTime"]) { // // 跳转指定位置
|
|
|
+ /**
|
|
|
+ api: 'cloudSetCurrentTime',
|
|
|
+ content: {
|
|
|
+ // 当前曲目id
|
|
|
+ songID: 0,
|
|
|
+ // 指定位置时间(ms)
|
|
|
+ currentTime: 0
|
|
|
+ }
|
|
|
+ */
|
|
|
+ NSDictionary *content = [parm dictionaryValueForKey:@"content"];
|
|
|
+ Float64 currentTime = [content doubleValueForKey:@"currentTime"];
|
|
|
+ if (self.playerEngine) {
|
|
|
+ [self.playerEngine setProgressTime:(currentTime/1000)];
|
|
|
+ }
|
|
|
+ [self postMessage:parm];
|
|
|
+ }
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"cloudChangeSpeed"]) { // 调速 范围(45-270整数)
|
|
|
+ /**
|
|
|
+ api: 'cloudChangeSpeed',
|
|
|
+ content: {
|
|
|
+ // 当前曲目id
|
|
|
+ songID: 0,
|
|
|
+ // 调整速度
|
|
|
+ speed: 90
|
|
|
+ // xml整体原始速度
|
|
|
+ originalSpeed: 90,
|
|
|
+ }
|
|
|
+ */
|
|
|
+ NSDictionary *content = [parm dictionaryValueForKey:@"content"];
|
|
|
+ float speed = [content floatValueForKey:@"speed"];
|
|
|
+ float originalSpeed = [content floatValueForKey:@"originalSpeed"];
|
|
|
+ double rate = speed / originalSpeed;
|
|
|
+ self.currentSpeed = speed;
|
|
|
+ [self.playerEngine setMusicPlayerSpeed:rate];
|
|
|
+ // 回报信息
|
|
|
+ [self postMessage:parm];
|
|
|
+ }
|
|
|
+ // 设置每个轨道音量
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"cloudVolume"]) {
|
|
|
+ /**
|
|
|
+ api: 'cloudVolume',
|
|
|
+ content: {
|
|
|
+ parts: [
|
|
|
+ {
|
|
|
+ name: '',
|
|
|
+ volume: 90,//0-100
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ */
|
|
|
+// NSDictionary *content = [parm dictionaryValueForKey:@"content"];
|
|
|
+// for (NSDictionary *dic in [content arrayValueForKey:@"parts"]) {
|
|
|
+// NSInteger trackId = [self.playerEngine getSingleTrackNumByName:[dic stringValueForKey:@"name"]];
|
|
|
+// if (trackId >= 0) {
|
|
|
+// float volume = [dic floatValueForKey:@"volume"];
|
|
|
+//
|
|
|
+// [self.playerEngine volume:volume/100 WithTrack:(UInt32)trackId];
|
|
|
+// }
|
|
|
+// }
|
|
|
+ [self postMessage:parm];
|
|
|
+ [self.playerEngine getAllTrackVolume];
|
|
|
+ }
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"cloudMetronome"]) { // 节拍器播放
|
|
|
+ self.metronomeParm = [NSMutableDictionary dictionaryWithDictionary:parm];
|
|
|
+ NSDictionary *content = [parm dictionaryValueForKey:@"content"];
|
|
|
+ NSInteger repeatCount = [content integerValueForKey:@"repeat"];
|
|
|
+ NSInteger denominator = [content integerValueForKey:@"denominator"];
|
|
|
+ NSInteger numerator = [content integerValueForKey:@"numerator"];
|
|
|
+ NSInteger supplement = [content integerValueForKey:@"supplement"];
|
|
|
+ NSString *beatString = [NSString stringWithFormat:@"%zd/%zd", numerator,denominator];
|
|
|
+ self.beatType = [self getBeatTypeFromString:beatString];
|
|
|
+ [self showBeatViewRepeatCount:repeatCount supplement:supplement];
|
|
|
+ }
|
|
|
+ else if ([[parm stringValueForKey:@"api"] isEqualToString:@"cloudDestroy"]) { // 销毁播放器
|
|
|
+ self.initEngineSuccess = NO;
|
|
|
+ // 重置track num array
|
|
|
+ self.isPlaying = NO;
|
|
|
+ if (self.playerEngine) {
|
|
|
+ [self.playerEngine cleanup];
|
|
|
+ self.playerEngine = nil;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ [super handleScriptMessageSource:parm];
|
|
|
+ }
|
|
|
+
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+- (void)showBeatViewRepeatCount:(NSInteger)repeatCount supplement:(NSInteger)supplement {
|
|
|
+ KSCloudBeatView *beatView = [KSCloudBeatView shareInstanceWithBeatType:self.beatType speed:self.currentSpeed repeatCount:repeatCount supplement:supplement];
|
|
|
+ MJWeakSelf;
|
|
|
+ [beatView startPlayWithEndCallback:^(BOOL isCancle) {
|
|
|
+ if (isCancle) { // 取消
|
|
|
+ [weakSelf sendEndMetronomeMessage:YES];
|
|
|
+ }
|
|
|
+ else { // 播放完成
|
|
|
+ [weakSelf sendEndMetronomeMessage:NO];
|
|
|
+ }
|
|
|
+ }];
|
|
|
+ [self.view addSubview:beatView];
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+- (void)sendEndMetronomeMessage:(BOOL)isCancel {
|
|
|
+ NSString *status = isCancel ? @"cancel" : @"finish";
|
|
|
+ NSMutableDictionary *valueDic = [NSMutableDictionary dictionaryWithDictionary:[self.metronomeParm dictionaryValueForKey:@"content"]];
|
|
|
+ [valueDic setValue:status forKey:@"status"];
|
|
|
+ NSMutableDictionary *sendParm = [NSMutableDictionary dictionaryWithDictionary:self.metronomeParm];
|
|
|
+ [sendParm setValue:valueDic forKey:@"content"];
|
|
|
+ [self postMessage:sendParm];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)downloadMidiFile:(NSString *)midiUrl success:(void(^)(void))success faliure:(void(^)(void))faliure {
|
|
|
+ [self showhud];
|
|
|
+ [KSNetworkingManager downloadFileRequestWithFileUrl:midiUrl progress:^(int64_t bytesRead, int64_t totalBytes) {
|
|
|
+
|
|
|
+ } success:^(NSURL * _Nonnull fileUrl) {
|
|
|
+ [self removehub];
|
|
|
+ if ([self saveMidiFileWithUrl:fileUrl midiUrl:midiUrl]) {
|
|
|
+ success();
|
|
|
+ }
|
|
|
+ } faliure:^(NSError * _Nonnull error) {
|
|
|
+ faliure();
|
|
|
+ }];
|
|
|
+}
|
|
|
+
|
|
|
+- (BOOL)saveMidiFileWithUrl:(NSURL *)fileUrl midiUrl:(NSString *)midiUrl {
|
|
|
+ NSData *sourceData = [NSData dataWithContentsOfURL:fileUrl];
|
|
|
+ NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
|
|
|
+ NSString *filePath= [cachePath stringByAppendingPathComponent:@"MidiSong"];
|
|
|
+ // 先创建子目录
|
|
|
+ NSFileManager *fileManager = [NSFileManager defaultManager];
|
|
|
+ if (![fileManager fileExistsAtPath:filePath]) {
|
|
|
+ [fileManager createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:nil];
|
|
|
+ }else{
|
|
|
+ NSLog(@"已创建文件夹");
|
|
|
+ }
|
|
|
+ NSString *fileName = [[midiUrl componentsSeparatedByString:@"/"] lastObject];
|
|
|
+ NSString *tempPath = [filePath stringByAppendingPathComponent:fileName];
|
|
|
+ BOOL success = [sourceData writeToFile:tempPath atomically:NO];
|
|
|
+ return success;
|
|
|
+}
|
|
|
+
|
|
|
+- (NSString *)getFilePathWithName:(NSString *)fileName {
|
|
|
+ NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
|
|
|
+ NSString *filePath= [cachePath stringByAppendingPathComponent:@"MidiSong"];
|
|
|
+ return [filePath stringByAppendingPathComponent:fileName];;
|
|
|
+}
|
|
|
+
|
|
|
+- (BOOL)checkSongHasSaveWithSongUrl:(NSString *)songUrl {
|
|
|
+ BOOL hasSaveFile = NO;
|
|
|
+ NSString *fileName = [[songUrl componentsSeparatedByString:@"/"] lastObject];
|
|
|
+ NSString *filePath = [self getFilePathWithName:fileName];
|
|
|
+
|
|
|
+ NSFileManager *fileManager = [NSFileManager defaultManager];
|
|
|
+ if ([fileManager fileExistsAtPath:filePath]) {
|
|
|
+ hasSaveFile = YES;
|
|
|
+ }
|
|
|
+ return hasSaveFile;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+- (void)sendMessageToSocket:(NSDictionary *)parm {
|
|
|
+ NSString *messageHeader = @"proxyMessage";
|
|
|
+ NSString *sendMessage = [self configDataCommond:messageHeader body:[parm dictionaryValueForKey:@"content"]];
|
|
|
+ [self sendDataToSocketService:sendMessage];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)configAudioDeviceType:(NSDictionary *)parm {
|
|
|
+ AUDIODEVICE_TYPE type = [KSAQRecordManager queryAudioOutputDeviceType];
|
|
|
+ NSString *valueStr = @"";
|
|
|
+ BOOL checkIsWired = NO;
|
|
|
+ switch (type) {
|
|
|
+ case AUDIODEVICE_TYPE_HEADPHONE:
|
|
|
+ {
|
|
|
+ valueStr = @"有线耳机";
|
|
|
+ checkIsWired = YES;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case AUDIODEVICE_TYPE_BLUETOOTH:
|
|
|
+ {
|
|
|
+ valueStr = @"蓝牙耳机";
|
|
|
+ checkIsWired = YES;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case AUDIODEVICE_TYPE_NONE:
|
|
|
+ {
|
|
|
+ valueStr = @"";
|
|
|
+ checkIsWired = NO;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ NSMutableDictionary *valueDic = [NSMutableDictionary dictionaryWithDictionary:[parm dictionaryValueForKey:@"content"]];
|
|
|
+ [valueDic setValue:valueStr forKey:@"type"];
|
|
|
+ [valueDic setValue:[NSNumber numberWithBool:checkIsWired] forKey:@"checkIsWired"];
|
|
|
+ NSMutableDictionary *sendParm = [NSMutableDictionary dictionaryWithDictionary:parm];
|
|
|
+ [sendParm setValue:valueDic forKey:@"content"];
|
|
|
+ [self postMessage:sendParm];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)startRecordService {
|
|
|
+ if (self.AQManager.isRunning) {
|
|
|
+ [self.AQManager stopRecord];
|
|
|
+ }
|
|
|
+ [self.AQManager startRecord];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)stopRecordService {
|
|
|
+ if (self.AQManager.isRunning) {
|
|
|
+ [self.AQManager stopRecord];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)puaseRecordService {
|
|
|
+ if (self.AQManager.isRunning) {
|
|
|
+ [self.AQManager pauserRecord];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)resumeRecordService {
|
|
|
+ [self.AQManager resumeRecord];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)sendEndMessage {
|
|
|
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
|
+ // 上传停止的信息 发送给服务端
|
|
|
+ NSString *endMessage = @"recordEnd";
|
|
|
+ NSString *endData = [self configDataCommond:endMessage body:nil type:@"SOUND_COMPARE"];
|
|
|
+ [self sendDataToSocketService:endData];
|
|
|
+ self.isCompareStart = NO;
|
|
|
+ NSLog(@"---- send end message");
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark-------- KSAQRecordManagerDelegate
|
|
|
+- (void)audioRecordInterruption {
|
|
|
+ NSDictionary *postParm = @{@"api" : @"cancelEvaluating",
|
|
|
+ @"content" : @{@"reson":@"录制错误,请重试"}
|
|
|
+ };
|
|
|
+ [self postMessage:postParm];
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+- (void)audioRouteChange:(AUDIODEVICE_TYPE)type {
|
|
|
+ NSString *valueStr = @"";
|
|
|
+ BOOL checkIsWired = NO;
|
|
|
+ switch (type) {
|
|
|
+ case AUDIODEVICE_TYPE_HEADPHONE:
|
|
|
+ {
|
|
|
+ valueStr = @"有线耳机";
|
|
|
+ checkIsWired = YES;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case AUDIODEVICE_TYPE_BLUETOOTH:
|
|
|
+ {
|
|
|
+ valueStr = @"蓝牙耳机";
|
|
|
+ checkIsWired = YES;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case AUDIODEVICE_TYPE_NONE:
|
|
|
+ {
|
|
|
+ valueStr = @"";
|
|
|
+ checkIsWired = NO;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ NSDictionary *postParm = @{@"api" : @"listenerWiredStatus",
|
|
|
+ @"content" : @{@"type":valueStr,
|
|
|
+ @"checkIsWired":[NSNumber numberWithBool:checkIsWired]
|
|
|
+ }
|
|
|
+ };
|
|
|
+ [self postMessage:postParm];
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+- (void)audioRecord:(KSAQRecordManager *)audioRecord didRecordAudioData:(void *)data length:(UInt32)length {
|
|
|
+
|
|
|
+ if (self.socketManager.socketReadyState != SR_OPEN) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ NSData *pushData = [[NSData alloc] initWithBytes:data length:length];
|
|
|
+ if (self.isCompareStart) { // 发送评测开始消息
|
|
|
+ dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
+ NSDate *date = [NSDate date];
|
|
|
+ NSTimeInterval inteveral = [date timeIntervalSince1970];
|
|
|
+ double beginTime = inteveral - audioRecord.sampleTime;
|
|
|
+ NSDictionary *parm = @{
|
|
|
+ @"api" : @"recordStartTime",
|
|
|
+ @"content" : @{@"inteveral" : [NSNumber numberWithDouble:beginTime]}
|
|
|
+ };
|
|
|
+ [self postMessage:parm];
|
|
|
+ });
|
|
|
+
|
|
|
+ NSLog(@"--------- send start message");
|
|
|
+ _isCompareStart = NO;
|
|
|
+ NSString *startMessage = @"recordStart";
|
|
|
+ NSString *startString = [self configDataCommond:startMessage body:nil type:@"SOUND_COMPARE"];
|
|
|
+ [self sendDataToSocketService:startString];
|
|
|
+
|
|
|
+// // 发送开始录制的消息给H5
|
|
|
+// if (self.recordParm) {
|
|
|
+// [self postMessage:self.recordParm];
|
|
|
+// }
|
|
|
+ }
|
|
|
+ else if (self.isSoundCheckStart) { // 校音开始
|
|
|
+
|
|
|
+ NSLog(@"--------- send check start message");
|
|
|
+ _isSoundCheckStart = NO;
|
|
|
+ NSString *checkStartMessage = @"start";
|
|
|
+ NSString *startString = [self configDataCommond:checkStartMessage body:nil type:@"PITCH_DETECTION"];
|
|
|
+ [self sendDataToSocketService:startString];
|
|
|
+ }
|
|
|
+ NSLog(@"--------- send audio data length %d", length);
|
|
|
+ [self sendDataToSocketService:pushData];
|
|
|
+}
|
|
|
+
|
|
|
+- (NSString *)configDataCommond:(NSString *)commond body:(id)bodyMessage type:(NSString *)dataType {
|
|
|
+ NSMutableDictionary *parm = [NSMutableDictionary dictionary];
|
|
|
+ if (bodyMessage) {
|
|
|
+ [parm setValue:bodyMessage forKey:@"body"];
|
|
|
+ }
|
|
|
+ NSMutableDictionary *headerParm = [NSMutableDictionary dictionary];
|
|
|
+ if ([NSString isEmptyString:commond]) {
|
|
|
+ [headerParm setValue:@"" forKey:@"commond"];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ [headerParm setValue:commond forKey:@"commond"];
|
|
|
+ }
|
|
|
+ if (![NSString isEmptyString:dataType]) {
|
|
|
+ [headerParm setValue:dataType forKey:@"type"];
|
|
|
+ }
|
|
|
+ [headerParm setValue:@(200) forKey:@"status"];
|
|
|
+ [parm setValue:headerParm forKey:@"header"];
|
|
|
+ return [parm mj_JSONString];
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+- (NSString *)configDataCommond:(NSString *)commond body:(id)bodyMessage {
|
|
|
+ NSMutableDictionary *parm = [NSMutableDictionary dictionary];
|
|
|
+ if (bodyMessage) {
|
|
|
+ [parm setValue:bodyMessage forKey:@"body"];
|
|
|
+ }
|
|
|
+ if ([NSString isEmptyString:commond]) {
|
|
|
+ [parm setValue:@{@"commond":@""} forKey:@"header"];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ [parm setValue:@{@"commond":commond} forKey:@"header"];
|
|
|
+ }
|
|
|
+ return [parm mj_JSONString];
|
|
|
+}
|
|
|
+
|
|
|
+- (KSWebSocketManager *)socketManager {
|
|
|
+ if (!_socketManager) {
|
|
|
+ _socketManager = [[KSWebSocketManager alloc] init];
|
|
|
+ }
|
|
|
+ return _socketManager;
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark --- lazying
|
|
|
+- (UIView *)viewContainer {
|
|
|
+ if (!_viewContainer) {
|
|
|
+ _viewContainer = [[UIView alloc] init];
|
|
|
+ }
|
|
|
+ return _viewContainer;
|
|
|
+}
|
|
|
+
|
|
|
+- (KSVideoRecordManager *)videoRecordManager {
|
|
|
+ if (!_videoRecordManager) {
|
|
|
+ MJWeakSelf;
|
|
|
+ _videoRecordManager = [[KSVideoRecordManager alloc] initSessionRecordCallback:^(BOOL isSuccess, NSString * _Nullable message) {
|
|
|
+ if (isSuccess) {
|
|
|
+ [weakSelf showSuccessMessage:message];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if (![NSString isEmptyString:message]) {
|
|
|
+ [weakSelf MBPShow:message];
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }];
|
|
|
+ }
|
|
|
+ return _videoRecordManager;
|
|
|
+}
|
|
|
+
|
|
|
+- (void)showSuccessMessage:(NSString *)message {
|
|
|
+ [self MBPShow:message];
|
|
|
+ // 成功
|
|
|
+ if (self.endRecordParm) {
|
|
|
+ [self postMessage:self.endRecordParm];
|
|
|
+ self.endRecordParm = nil;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (MetronomeType)getBeatTypeFromString:(NSString *)typeString {
|
|
|
+ if ([typeString isEqualToString:@"1/4"]) {
|
|
|
+ return MetronomeType1V4;
|
|
|
+ }
|
|
|
+ else if ([typeString isEqualToString:@"2/4"]) {
|
|
|
+ return MetronomeType2V4;
|
|
|
+ }
|
|
|
+ else if ([typeString isEqualToString:@"3/4"]) {
|
|
|
+ return MetronomeType3V4;
|
|
|
+ }
|
|
|
+ else if ([typeString isEqualToString:@"4/4"]) {
|
|
|
+ return MetronomeType4V4;
|
|
|
+ }
|
|
|
+ else if ([typeString isEqualToString:@"3/8"]) {
|
|
|
+ return MetronomeType3V8;
|
|
|
+ }
|
|
|
+ else if ([typeString isEqualToString:@"6/8"]) {
|
|
|
+ return MetronomeType6V8;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return MetronomeType4V4;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+#pragma mark ------- midi 播放相关
|
|
|
+- (void)configPlayerEngineWithSong:(NSString *)songPath reportTime:(NSInteger)reportTime {
|
|
|
+ self.initEngineSuccess = NO;
|
|
|
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
|
+ self.playerEngine = [[MidiPlayerEngine alloc] init];
|
|
|
+ self.playerEngine.reportTime = reportTime;
|
|
|
+ self.playerEngine.delegate = self;
|
|
|
+ [self.playerEngine configSoundFilePath:[[NSBundle mainBundle]
|
|
|
+ pathForResource:@"synthgms" ofType:@"sf2"]];
|
|
|
+ [self.playerEngine loadMIDIFileWithString:songPath];
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+- (void)configAudioSession {
|
|
|
+ self.audioSessionManager = [[KSAudioSessionManager alloc] init];
|
|
|
+ self.audioSessionManager.delegate = self;
|
|
|
+ [self.audioSessionManager configAudioSession:AUDIOCONFIG_PLAYANDRECORD];
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark ---- PlayerEngineDelegate
|
|
|
+/** 进度更新
|
|
|
+ api: 'cloudTimeUpdae',
|
|
|
+ content: {
|
|
|
+ // 当前曲目id
|
|
|
+ songID: 0,
|
|
|
+ // 当前位置时间(ms)
|
|
|
+ currentTime: 0
|
|
|
+ }
|
|
|
+ */
|
|
|
+/** 播放结束事件
|
|
|
+ api: 'cloudplayed',
|
|
|
+ content: {
|
|
|
+ // 当前曲目id
|
|
|
+ songID: 0,
|
|
|
+ }
|
|
|
+ */
|
|
|
+- (void)ProgressUpdated:(float)progress currentTime:(MusicTimeStamp)currentTime {
|
|
|
+ if (self.isPlaying == NO) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 回调
|
|
|
+ NSMutableDictionary *sendParm = [NSMutableDictionary dictionary];
|
|
|
+ [sendParm setValue:@"cloudTimeUpdae" forKey:@"api"];
|
|
|
+ NSMutableDictionary *content = [NSMutableDictionary dictionary];
|
|
|
+ [content setValue:self.currentSongId forKey:@"songID"];
|
|
|
+ [content setValue:@(currentTime*1000) forKey:@"currentTime"];
|
|
|
+ [sendParm setValue:content forKey:@"content"];
|
|
|
+ [self postMessage:sendParm];
|
|
|
+// NSLog(@"------time source %@", content);
|
|
|
+}
|
|
|
+
|
|
|
+- (void)playEnd {
|
|
|
+ [self stopPlayAction];
|
|
|
+ NSMutableDictionary *sendParm = [NSMutableDictionary dictionary];
|
|
|
+ [sendParm setValue:@"cloudplayed" forKey:@"api"];
|
|
|
+ NSMutableDictionary *content = [NSMutableDictionary dictionary];
|
|
|
+ [content setValue:self.currentSongId forKey:@"songID"];
|
|
|
+ [sendParm setValue:content forKey:@"content"];
|
|
|
+ [self postMessage:sendParm];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)initPlayerEngineSuccess:(float)totalTime {
|
|
|
+ self.initEngineSuccess = YES;
|
|
|
+ if (self.configEngineParm) {
|
|
|
+ NSMutableDictionary *sendParm = [NSMutableDictionary dictionaryWithDictionary:self.configEngineParm];
|
|
|
+ NSMutableDictionary *content = [NSMutableDictionary dictionaryWithDictionary:[sendParm dictionaryValueForKey:@"content"]];
|
|
|
+ [content setValue:@(totalTime*1000) forKey:@"midiDuration"];
|
|
|
+ [sendParm setValue:content forKey:@"content"];
|
|
|
+ [self postMessage:sendParm];
|
|
|
+ self.configEngineParm = nil;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 总时长
|
|
|
+- (void)GetMusicTotalTime:(float)time {
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+#pragma mark ----- 播放控制
|
|
|
+- (void)playAction {
|
|
|
+ self.isPlaying = YES;
|
|
|
+ [self.playerEngine playMIDIFile];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)stopPlayAction {
|
|
|
+ self.isPlaying = NO;
|
|
|
+ if ([self.playerEngine isPlayingFile]) {
|
|
|
+ [self.playerEngine stopPlayingMIDIFile];
|
|
|
+ }
|
|
|
+}
|
|
|
/*
|
|
|
#pragma mark - Navigation
|
|
|
|