KSAccompanyWebViewController.m 64 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658
  1. //
  2. // KSAccompanyWebViewController.m
  3. // KulexiuForTeacher
  4. //
  5. // Created by Kyle on 2022/3/20.
  6. //
  7. #import "KSAccompanyWebViewController.h"
  8. #import "RecordCheckManager.h"
  9. #import "KSAQRecordManager.h"
  10. #import "KSWebSocketManager.h"
  11. #import "KSVideoRecordManager.h"
  12. #import "KSWebNavView.h"
  13. #import "KSAudioSessionManager.h"
  14. #import "KSCloudBeatView.h"
  15. #import "MidiPlayerEngine.h"
  16. #import "AccompanyLoadingView.h"
  17. #import "KSPremissionAlert.h"
  18. #define KSMidiSongFileKey (@"KSDownloadMidiSong")
  19. #import "KulexiuForStudent-swift.h"
  20. #import "kSNewPlayer.h"
  21. #import "KSMediaEditor.h"
  22. #import "KSMediaMergeView.h"
  23. @interface KSAccompanyWebViewController ()<KSAQRecordManagerDelegate,KSAudioSessionManagerDelegate,PlayerEngineDelegate,TunerDelegate,kSNewPlayerManagerDelegate>
  24. @property (nonatomic, strong) KSAudioSessionManager *audioSessionManager;
  25. @property (nonatomic, assign) MetronomeType beatType;
  26. @property (nonatomic, strong) MidiPlayerEngine *playerEngine; // player
  27. @property (nonatomic, assign) BOOL initEngineSuccess; // 加载引擎是否成功
  28. @property (nonatomic, assign) float songOriginalSpeed;
  29. @property (nonatomic, assign) float currentSpeed; // 当前播放的速度
  30. @property (nonatomic, assign) BOOL isPlaying; // 是否正在播放的状态
  31. @property (nonatomic, strong) NSString *currentSongId; // song id
  32. @property (nonatomic, strong) NSDictionary *configEngineParm; // 初始化mid播放引擎的参数
  33. @property (nonatomic, strong) NSMutableDictionary *metronomeParm; // 节拍器播放的参数
  34. // 是否发送了musicXML信息
  35. @property (nonatomic, assign) BOOL hasSendStartMessage;
  36. @property (nonatomic, strong) KSAQRecordManager *AQManager;
  37. @property (nonatomic, strong) KSWebSocketManager *socketManager;
  38. @property (nonatomic, strong) NSMutableDictionary *evaluatParm;
  39. // 录制的message
  40. @property (nonatomic, strong) NSMutableDictionary *recordParm;
  41. // 评测开始时发送recordStart消息的标识
  42. @property (nonatomic, assign) BOOL isCompareStart;
  43. // 校音开始时发送 checkStart消息标识
  44. @property (nonatomic, assign) BOOL isSoundCheckStart;
  45. // 自定义UI控件容器
  46. @property (nonatomic, strong) UIView *viewContainer;
  47. @property (nonatomic, strong) KSVideoRecordManager *videoRecordManager;
  48. @property (nonatomic, strong) NSDictionary *endRecordParm;
  49. @property (nonatomic, assign) BOOL isCameraOpen;
  50. @property (nonatomic, strong) AccompanyLoadingView *loadingView;
  51. @property (nonatomic, assign) BOOL isTunerRuning;
  52. @property (nonatomic, strong) Tuner *tuner;
  53. // 延迟校准开始时发送 AdjustStart消息标识
  54. @property (nonatomic, assign) BOOL isDelayCheckStart;
  55. // 检测延迟播放器
  56. @property (nonatomic, strong) kSNewPlayer *dingPlayer;
  57. @property (nonatomic, strong) kSNewPlayer *dongPlayer;
  58. // 音频播放器
  59. @property (nonatomic, strong) kSNewPlayer *musicPlayer;
  60. // 录音开始时间
  61. @property (nonatomic, assign) NSTimeInterval recordStartTime;
  62. // 播放开始时间
  63. @property (nonatomic, assign) NSTimeInterval playerStartTime;
  64. // 播放延迟
  65. @property (nonatomic, assign) NSInteger offsetTime;
  66. @property (nonatomic, assign) BOOL dingPlayerReady;
  67. @property (nonatomic, assign) BOOL dongPlayerReady;
  68. @property (nonatomic, assign) BOOL musicPlayerReady;
  69. @property (nonatomic, strong) NSDictionary *playerParm;
  70. @property (nonatomic, strong) NSMutableArray *delayArray;
  71. @property (nonatomic, assign) NSInteger checkIndex;
  72. @property (nonatomic, assign) NSInteger firstFrequence;
  73. @property (nonatomic, assign) NSInteger secondFrequence;
  74. @property (nonatomic, strong) NSURL *bgAudioUrl;
  75. @property (nonatomic, strong) NSURL *recordUrl;
  76. @property (nonatomic, strong) NSString *accompanyUrl;
  77. @end
  78. @implementation KSAccompanyWebViewController
  79. - (void)handerAudioInterruption {
  80. if (_playerEngine) {
  81. [self stopPlayAction];
  82. }
  83. }
  84. - (void)resumeAudioSession {
  85. // 恢复
  86. if (_playerEngine) {
  87. [self.playerEngine resumeAUGraph];
  88. }
  89. }
  90. // 打断处理
  91. - (void)audioInterruption {
  92. if (_videoRecordManager) {
  93. [self.videoRecordManager resetSession];
  94. }
  95. [self handerAudioInterruption];
  96. }
  97. - (void)ignorRecordVideo {
  98. if (_videoRecordManager) {
  99. self.videoRecordManager.skipSaveRecord = YES;
  100. }
  101. }
  102. - (void)stopSession {
  103. if (_videoRecordManager) {
  104. [self.videoRecordManager stopSession];
  105. }
  106. }
  107. - (void)resetPlayerConfig {
  108. [self freeMp3Player]; // 若之前有播放器,剔除
  109. self.firstFrequence = 800;
  110. self.secondFrequence = 800;
  111. self.dingPlayerReady = NO;
  112. self.dongPlayerReady = NO;
  113. self.musicPlayerReady = NO;
  114. self.recordStartTime = 0;
  115. self.playerStartTime = 0;
  116. self.offsetTime = 0;
  117. }
  118. - (void)initMp3Player:(NSString *)musicUrl checkUrl:(NSString *)checkUrl {
  119. [self resetPlayerConfig];
  120. self.accompanyUrl = musicUrl;
  121. [self.musicPlayer preparePlaySongWithUrl:musicUrl];
  122. [self.dingPlayer preparePlaySongWithUrl:checkUrl];
  123. [self.dongPlayer preparePlaySongWithUrl:checkUrl];
  124. [self prepareMusic];
  125. }
  126. - (void)prepareMusic {
  127. self.dingPlayer.isMute = YES;
  128. [self.dingPlayer startPlay];
  129. self.dongPlayer.isMute = YES;
  130. [self.dongPlayer startPlay];
  131. self.musicPlayer.isMute = YES;
  132. [self.musicPlayer startPlay];
  133. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  134. [self.musicPlayer puasePlay];
  135. self.musicPlayer.isMute = NO;
  136. [self.dingPlayer puasePlay];
  137. self.dingPlayer.isMute = NO;
  138. [self.dongPlayer puasePlay];
  139. self.dongPlayer.isMute = NO;
  140. [self configPlayerDelegate];
  141. });
  142. }
  143. - (void)freeMp3Player {
  144. if (_dingPlayer) {
  145. [self.dingPlayer freePlayer];
  146. }
  147. if (_dongPlayer) {
  148. [self.dongPlayer freePlayer];
  149. }
  150. if (_musicPlayer) {
  151. [self.musicPlayer freePlayer];
  152. }
  153. }
  154. - (void)stopMp3Player {
  155. if (_dingPlayer) {
  156. [self.dingPlayer puasePlay];
  157. }
  158. if (_dongPlayer) {
  159. [self.dongPlayer puasePlay];
  160. }
  161. if (_musicPlayer) {
  162. [self.musicPlayer puasePlay];
  163. }
  164. }
  165. - (void)viewDidLoad {
  166. [super viewDidLoad];
  167. // Do any additional setup after loading the view.
  168. [self configAudioSession];
  169. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appEnterBackground) name:@"appEnterBackground" object:nil];
  170. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appEnterForeground) name:@"appEnterForeground" object:nil];
  171. }
  172. - (void)checkMessage:(id)message {
  173. NSDictionary *result = [message mj_JSONObject];
  174. NSString *type = [[result ks_dictionaryValueForKey:@"header"] ks_stringValueForKey:@"type"];
  175. NSString *commond = [[result ks_dictionaryValueForKey:@"header"] ks_stringValueForKey:@"commond"];
  176. if ([type isEqualToString:@"DELAY_CHECK"] && [commond isEqualToString:@"recordEnd"]) {
  177. NSDictionary *body = [result ks_dictionaryValueForKey:@"body"];
  178. NSTimeInterval micDelay = [body ks_doubleValueForKey:@"firstNoteDelayDuration"] - self.offsetTime;
  179. [self.delayArray addObject:[NSNumber numberWithDouble:micDelay]];
  180. }
  181. }
  182. - (void)connectSocketService {
  183. MJWeakSelf;
  184. self.socketManager.didReceiveMessage = ^(id _Nonnull message) {
  185. dispatch_async(dispatch_get_main_queue(), ^{
  186. [weakSelf checkMessage:message];
  187. // api
  188. NSMutableDictionary *sendMessage = [NSMutableDictionary dictionary];
  189. [sendMessage setValue:@"sendResult" forKey:@"api"];
  190. [sendMessage setValue:message forKey:@"content"];
  191. // 服务返回数据传给H5
  192. [weakSelf postMessage:sendMessage];
  193. });
  194. };
  195. self.socketManager.connectionStatus = ^(BOOL isSuccess) {
  196. dispatch_async(dispatch_get_main_queue(), ^{
  197. if (!isSuccess) {
  198. // NSLog(@"-----连接失败");
  199. if (weakSelf.hasSendStartMessage) {
  200. if (weakSelf.AQManager.isRunning) {
  201. NSDictionary *postParm = @{@"api" : @"cancelEvaluating",
  202. @"content" : @{@"reson":@"服务异常,请重试"}
  203. };
  204. [weakSelf postMessage:postParm];
  205. [weakSelf stopRecordService];
  206. weakSelf.isCompareStart = NO;
  207. weakSelf.isSoundCheckStart = NO;
  208. weakSelf.isDelayCheckStart = NO;
  209. }
  210. }
  211. else if (weakSelf.evaluatParm) {
  212. NSMutableDictionary *sendParm = [NSMutableDictionary dictionaryWithDictionary:weakSelf.evaluatParm];
  213. NSDictionary *valueDic = [weakSelf.evaluatParm ks_dictionaryValueForKey:@"content"];
  214. [valueDic setValue:@"服务异常,请重试" forKey:@"reson"];
  215. [sendParm setValue:valueDic forKey:@"content"];
  216. [weakSelf postMessage:sendParm];
  217. weakSelf.hasSendStartMessage = YES;
  218. weakSelf.isCompareStart = NO;
  219. weakSelf.isSoundCheckStart = NO;
  220. weakSelf.isDelayCheckStart = NO;
  221. }
  222. else { // 其他断开
  223. if (weakSelf.AQManager.isRunning) {
  224. NSDictionary *postParm = @{@"api" : @"cancelEvaluating",
  225. @"content" : @{@"reson":@"服务异常,请重试"}
  226. };
  227. [weakSelf postMessage:postParm];
  228. [weakSelf stopRecordService];
  229. weakSelf.isCompareStart = NO;
  230. weakSelf.isSoundCheckStart = NO;
  231. weakSelf.isDelayCheckStart = NO;
  232. }
  233. }
  234. }
  235. else {
  236. // NSLog(@"-----连接成功");
  237. if (weakSelf.hasSendStartMessage == NO && weakSelf.evaluatParm) {
  238. NSDictionary *content = [weakSelf.evaluatParm ks_dictionaryValueForKey:@"content"];
  239. NSString *sendData = [weakSelf configDataCommond:@"musicXml" body:content type:@"SOUND_COMPARE"];
  240. [weakSelf sendDataToSocketService:sendData];
  241. [weakSelf postMessage:weakSelf.evaluatParm];
  242. weakSelf.hasSendStartMessage = YES;
  243. }
  244. }
  245. });
  246. };
  247. [self.socketManager SRWebSocketOpen];
  248. }
  249. - (void)appEnterBackground {
  250. NSDictionary *parm = @{@"api":@"suspendPlay"};
  251. [self postMessage:parm];
  252. [self handerAudioInterruption];
  253. }
  254. - (void)appEnterForeground {
  255. if (self.isCameraOpen) {
  256. if ([self.videoRecordManager getSessionStatusisActive] == NO) {
  257. [self.videoRecordManager configSessiondisplayInView:self.viewContainer];
  258. }
  259. }
  260. }
  261. - (void)initWebView {
  262. [self.scrollView removeFromSuperview];
  263. [self.view addSubview:self.viewContainer];
  264. [self.viewContainer mas_makeConstraints:^(MASConstraintMaker *make) {
  265. make.left.right.top.bottom.mas_equalTo(self.view);
  266. }];
  267. if (self.myWebView == nil) {
  268. WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
  269. config.selectionGranularity = WKSelectionGranularityDynamic;
  270. config.allowsInlineMediaPlayback = YES;
  271. config.mediaTypesRequiringUserActionForPlayback = NO;
  272. config.processPool = [KSBaseWKWebViewController singleWkProcessPool];
  273. config.websiteDataStore = [WKWebsiteDataStore defaultDataStore];
  274. [self configUserAgent:config];
  275. //自定义的WKScriptMessageHandler 是为了解决内存不释放的问题
  276. WeakWebViewScriptMessageDelegate *weakScriptMessageDelegate = [[WeakWebViewScriptMessageDelegate alloc] initWithDelegate:self];
  277. //这个类主要用来做native与JavaScript的交互管理
  278. WKUserContentController * wkUController = [[WKUserContentController alloc] init];
  279. [wkUController addScriptMessageHandler:weakScriptMessageDelegate name:@"COLEXIU"];
  280. config.userContentController = wkUController;
  281. WKPreferences *preferences = [WKPreferences new];
  282. // 是否支出javaScript
  283. preferences.javaScriptEnabled = YES;
  284. //不通过用户交互,是否可以打开窗口
  285. preferences.javaScriptCanOpenWindowsAutomatically = YES;
  286. config.preferences = preferences;
  287. self.myWebView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:config];
  288. self.myWebView.opaque = NO;
  289. self.myWebView.UIDelegate = self;
  290. self.myWebView.navigationDelegate = self;
  291. self.myWebView.scrollView.bounces = NO;
  292. self.myWebView.backgroundColor = [UIColor clearColor];
  293. self.myWebView.scrollView.backgroundColor = [UIColor clearColor];
  294. // 加载进度条和title
  295. [self.myWebView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
  296. [self.view addSubview:self.myWebView];
  297. [self.myWebView mas_makeConstraints:^(MASConstraintMaker *make) {
  298. make.left.right.mas_equalTo(self.view);
  299. make.top.mas_equalTo(self.view.mas_top);
  300. make.bottom.mas_equalTo(self.view.mas_bottom);
  301. }];
  302. self.myWebView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
  303. [self setupProgress];
  304. [self loadRequest];
  305. }
  306. else {
  307. [self.myWebView reload];
  308. }
  309. }
  310. - (void)configUserAgent:(WKWebViewConfiguration *)config {
  311. NSString *oldUserAgent = config.applicationNameForUserAgent;
  312. NSString *newAgent = [NSString stringWithFormat:@"%@ %@ %@",oldUserAgent,@"ORCHESTRAAPPI",@"ORCHESTRASTUDENT"];
  313. config.applicationNameForUserAgent = newAgent;
  314. }
  315. - (void)configRecordManager {
  316. self.AQManager = [[KSAQRecordManager alloc] init];
  317. self.AQManager.delegate = self;
  318. }
  319. - (void)viewWillAppear:(BOOL)animated {
  320. [super viewWillAppear:animated];
  321. [self connectSocketService];
  322. if (self.isCameraOpen) {
  323. [self.videoRecordManager configSessiondisplayInView:self.viewContainer];
  324. }
  325. }
  326. - (void)viewWillDisappear:(BOOL)animated {
  327. [super viewWillDisappear:animated];
  328. if (_AQManager) {
  329. [_AQManager freeAudioQueue];
  330. _AQManager = nil;
  331. }
  332. if (_socketManager) {
  333. [self.socketManager SRWebSocketClose];
  334. _socketManager = nil;
  335. }
  336. // 返回不保存视频
  337. [self ignorRecordVideo];
  338. [self stopSession];
  339. // 如果退出评测页面 清除 playerEngine
  340. if (self.playerEngine) {
  341. [self.playerEngine cleanup];
  342. self.playerEngine = nil;
  343. }
  344. [self stopTuner];
  345. BOOL isBack = [self isViewPopDismiss];
  346. if (isBack) {
  347. [self freeMp3Player];
  348. }
  349. }
  350. - (void)sendDataToSocketService:(id)data {
  351. if (_socketManager) {
  352. [self.socketManager sendData:data];
  353. }
  354. }
  355. #pragma mark --- WKScriptMessageHandler
  356. - (void)userContentController:(WKUserContentController *)userContentController
  357. didReceiveScriptMessage:(WKScriptMessage *)message {
  358. if ([message.name isEqualToString:@"COLEXIU"]) {
  359. NSDictionary *parm = [self convertJsonStringToNSDictionary:message.body];
  360. NSLog(@"---- receive parm %@", [parm mj_JSONString]);
  361. // 回到主线程
  362. dispatch_async(dispatch_get_main_queue(), ^{
  363. if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"createMusicPlayer"]) {
  364. NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
  365. NSString *musicUrl = [content ks_stringValueForKey:@"musicSrc"];
  366. NSString *checkUrl = [content ks_stringValueForKey:@"tuneSrc"];
  367. self.playerParm = parm;
  368. [self initMp3Player:musicUrl checkUrl:checkUrl];
  369. }
  370. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"startEvaluating"]) { // 开始评测
  371. [self configRecordManager];
  372. self.hasSendStartMessage = NO;
  373. PREMISSIONTYPE isOk = [RecordCheckManager checkPermissionShowAlert:NO showInView:nil];
  374. if (isOk == PREMISSIONTYPE_YES) {
  375. self.evaluatParm = [NSMutableDictionary dictionaryWithDictionary:parm];
  376. // 如果socket 连上了
  377. if (self.socketManager.socketReadyState == SR_OPEN) {
  378. NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
  379. NSString *sendData = [self configDataCommond:@"musicXml" body:content type:@"SOUND_COMPARE"];
  380. [self sendDataToSocketService:sendData];
  381. [self postMessage:parm];
  382. self.hasSendStartMessage = YES;
  383. }
  384. else {
  385. [self connectSocketService];
  386. }
  387. }
  388. else {
  389. NSDictionary *postParm = @{@"api" : @"cancelEvaluating",
  390. @"content" : @{@"reson":@"没有麦克风权限"}
  391. };
  392. [self postMessage:postParm];
  393. }
  394. }
  395. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"endEvaluating"]) {// 停止评测
  396. self.evaluatParm = nil;
  397. [self stopRecordService];
  398. [self postMessage:parm];
  399. [self sendEndMessage];
  400. [self stopMp3Player]; // 停止播放
  401. }
  402. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cancelEvaluating"]) { // 取消评测
  403. self.evaluatParm = nil;
  404. [self stopRecordService];
  405. [self postMessage:parm];
  406. [self sendEndMessage];
  407. [self stopMp3Player]; // 停止播放
  408. }
  409. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"startRecording"]) { // 开始录制
  410. if (self.videoRecordManager) {
  411. [self.videoRecordManager clearVideoFile];
  412. }
  413. [self postMessage:parm];
  414. self.isCompareStart = YES;
  415. [self startRecordService];
  416. }
  417. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"endRecording"]) { // 停止录音
  418. self.recordParm = nil;
  419. [self stopRecordService];
  420. [self postMessage:parm];
  421. }
  422. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"pauseRecording"]) {
  423. [self puaseRecordService];
  424. [self postMessage:parm];
  425. }
  426. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"resumeRecording"]) {
  427. [self resumeRecordService];
  428. [self postMessage:parm];
  429. }
  430. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"isWiredHeadsetOn"]) {
  431. [self configAudioDeviceType:parm];
  432. }
  433. // 发送消息给socket service
  434. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"proxyMessage"]) {
  435. [self sendMessageToSocket:parm];
  436. }
  437. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"proxyServiceMessage"]) {
  438. NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
  439. NSString *sendData = [content mj_JSONString];
  440. NSLog(@"proxyServiceMessage ------- %@",sendData);
  441. [self sendDataToSocketService:sendData];
  442. }
  443. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"openCamera"]) { // 开启摄像头
  444. PREMISSIONTYPE canOpenCamera = [RecordCheckManager checkCameraPremissionAvaiable:NO showInView:nil];
  445. PREMISSIONTYPE albumEnable = [RecordCheckManager checkPhotoLibraryPremissionAvaiable:NO showInView:nil];
  446. if (canOpenCamera == PREMISSIONTYPE_YES) {
  447. self.isCameraOpen = YES;
  448. [self.videoRecordManager configSessiondisplayInView:self.viewContainer];
  449. [self postMessage:parm];
  450. }
  451. if (albumEnable == PREMISSIONTYPE_NO) {
  452. [self showAlertWithMessage:@"请开启相册访问权限" type:CHECKDEVICETYPE_CAMREA];
  453. }
  454. }
  455. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"closeCamera"]) { // 关闭摄像头
  456. self.isCameraOpen = NO;
  457. if (self->_videoRecordManager) {
  458. [self.videoRecordManager removeDisplay];
  459. }
  460. [self postMessage:parm];
  461. }
  462. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"startCapture"]) { // 开始录制
  463. // 需要合成音频
  464. [self.videoRecordManager setIgnoreAudio:YES];
  465. [RecordCheckManager checkPhotoLibraryPremissionAvaiable:YES showInView:self.view];
  466. self.videoRecordManager.audioUrl = self.AQManager.audioUrl;
  467. [self.videoRecordManager startRecord];
  468. [self postMessage:parm];
  469. }
  470. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"endCapture"]) { // 结束录制
  471. if (self->_videoRecordManager) {
  472. self.endRecordParm = parm;
  473. [self.videoRecordManager stopRecord];
  474. }
  475. else {
  476. [self postMessage:parm];
  477. }
  478. }
  479. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"setCaptureMode"]) {
  480. NSString *modeString = [[parm ks_dictionaryValueForKey:@"content"] ks_stringValueForKey:@"mode"];
  481. BOOL isIgnoreAudio = [modeString isEqualToString:@"evaluating"];
  482. [self postMessage:parm];
  483. [self.videoRecordManager setIgnoreAudio:isIgnoreAudio];
  484. }
  485. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"startSoundCheck"]) { // 开始校音
  486. [self configRecordManager];
  487. [self postMessage:parm];
  488. self.isCompareStart = NO;
  489. self.isSoundCheckStart = YES;
  490. self.isDelayCheckStart = NO;
  491. [self startRecordService];
  492. }
  493. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"endSoundCheck"]) {
  494. // 结束校音
  495. self.isSoundCheckStart = NO;
  496. [self stopRecordService];
  497. [self postMessage:parm];
  498. }
  499. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"videoUpdate"]) { // 上传
  500. NSMutableDictionary *sendParm = [NSMutableDictionary dictionaryWithDictionary:parm];
  501. NSMutableDictionary *contentParm = [NSMutableDictionary dictionaryWithDictionary:[sendParm ks_dictionaryValueForKey:@"content"]];
  502. if (self.videoRecordManager) {
  503. MJWeakSelf;
  504. [self.videoRecordManager saveVideoCallback:^(BOOL isSuccess, NSString * _Nullable message) {
  505. if (isSuccess) {
  506. [LOADING_MANAGER MBShowAUTOHidingInWindow:@"已保存到相册"];
  507. [weakSelf uploadVideoWithParm:contentParm sendParm:sendParm];
  508. }
  509. }];
  510. }
  511. }
  512. #pragma mark -------- 云教练原生播放对接
  513. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudDetail"]) { // 初始化方法
  514. /**
  515. api: 'cloudDetail',
  516. content: {
  517. midi: '',
  518. denominator: 4,
  519. numerator: 4,
  520. // xml整体原始速度
  521. originalSpeed: 90,
  522. // 间隔(ms)
  523. interval: 50
  524. }
  525. */
  526. [self configAudioSession];
  527. // 重置track num array
  528. self.configEngineParm = [parm copy];
  529. NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
  530. NSString *midiUrl = [content ks_stringValueForKey:@"midi"];
  531. NSInteger denominator = [content ks_integerValueForKey:@"denominator"];
  532. NSInteger numerator = [content ks_integerValueForKey:@"numerator"];
  533. NSString *beatString = [NSString stringWithFormat:@"%zd/%zd", numerator,denominator];
  534. self.beatType = [self getBeatTypeFromString:beatString];
  535. float originalSpeed = [content ks_floatValueForKey:@"originalSpeed"];
  536. self.songOriginalSpeed = originalSpeed;
  537. self.currentSpeed = originalSpeed;
  538. NSInteger reportInterval = [content ks_integerValueForKey:@"interval"];
  539. // 下载midi文件
  540. BOOL hasSaveSong = [self checkSongHasSaveWithSongUrl:midiUrl];
  541. NSString *fileName = [[midiUrl componentsSeparatedByString:@"/"] lastObject];
  542. NSString *filePath = [self getFilePathWithName:fileName];
  543. if (hasSaveSong) {
  544. [self configPlayerEngineWithSong:filePath reportTime:reportInterval];
  545. }
  546. else {
  547. MJWeakSelf;
  548. [self downloadMidiFile:midiUrl success:^{
  549. [weakSelf configPlayerEngineWithSong:filePath reportTime:reportInterval];
  550. } faliure:^{
  551. }];
  552. }
  553. }
  554. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudGetMediaStatus"]) { // 获取播放状态
  555. /**
  556. api: 'cloudGetMediaStatus',
  557. content: {
  558. status: 'init' | 'play' | 'suspend'
  559. }
  560. */
  561. NSString *engineStatus = @"init";
  562. if (self.initEngineSuccess) {
  563. if (self.isPlaying) {
  564. engineStatus = @"play";
  565. }
  566. else {
  567. engineStatus = @"suspend";
  568. }
  569. }
  570. NSMutableDictionary *valueDic = [NSMutableDictionary dictionaryWithDictionary:[parm ks_dictionaryValueForKey:@"content"]];
  571. [valueDic setValue:engineStatus forKey:@"status"];
  572. NSMutableDictionary *sendParm = [NSMutableDictionary dictionaryWithDictionary:parm];
  573. [sendParm setValue:valueDic forKey:@"content"];
  574. [self postMessage:sendParm];
  575. }
  576. // 播放、暂停、进度、播放结束、跳转指定位置
  577. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudPlay"]) { // 播放
  578. /**
  579. api: 'cloudPlay',
  580. content: {
  581. // 当前曲目id
  582. songID: 0,
  583. // xml整体原始速度
  584. originalSpeed: 90,
  585. // 当前选择速度
  586. speed: 90,
  587. // 开始时间(ms)
  588. startTime: 0
  589. // 播放频率
  590. hertz:440
  591. }
  592. */
  593. NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
  594. self.currentSongId = [content ks_stringValueForKey:@"songID"];
  595. float speed = [content ks_floatValueForKey:@"speed"];
  596. float originalSpeed = [content ks_floatValueForKey:@"originalSpeed"];
  597. double rate = speed / originalSpeed;
  598. self.currentSpeed = speed;
  599. float hertz = [content ks_floatValueForKey:@"hertz"];
  600. // 播放的hertz
  601. [self.playerEngine adjustPitchByHZ:hertz];
  602. [self.playerEngine setMusicPlayerSpeed:rate];
  603. Float64 startTime = [content ks_doubleValueForKey:@"startTime"];
  604. NSLog(@"------%@", [content ks_stringValueForKey:@"startTime"]);
  605. [self.playerEngine setProgressTime:(startTime/1000)];
  606. // 播放
  607. [self playAction];
  608. [self postMessage:parm];
  609. }
  610. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudSuspend"]) { // 暂停
  611. /**
  612. api: 'cloudSuspend',
  613. content: {
  614. // 当前曲目id
  615. songID: 0,
  616. }
  617. */
  618. [self stopPlayAction];
  619. [self postMessage:parm];
  620. }
  621. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudSetCurrentTime"]) { // // 跳转指定位置
  622. /**
  623. api: 'cloudSetCurrentTime',
  624. content: {
  625. // 当前曲目id
  626. songID: 0,
  627. // 指定位置时间(ms)
  628. currentTime: 0
  629. }
  630. */
  631. NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
  632. Float64 currentTime = [content ks_doubleValueForKey:@"currentTime"];
  633. if (self.playerEngine) {
  634. [self.playerEngine setProgressTime:(currentTime/1000)];
  635. }
  636. [self postMessage:parm];
  637. }
  638. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudChangeSpeed"]) { // 调速 范围(45-270整数)
  639. /**
  640. api: 'cloudChangeSpeed',
  641. content: {
  642. // 当前曲目id
  643. songID: 0,
  644. // 调整速度
  645. speed: 90
  646. // xml整体原始速度
  647. originalSpeed: 90,
  648. }
  649. */
  650. NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
  651. float speed = [content ks_floatValueForKey:@"speed"];
  652. float originalSpeed = [content ks_floatValueForKey:@"originalSpeed"];
  653. double rate = speed / originalSpeed;
  654. self.currentSpeed = speed;
  655. [self.playerEngine setMusicPlayerSpeed:rate];
  656. // 回报信息
  657. [self postMessage:parm];
  658. }
  659. // 设置每个轨道音量
  660. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudVolume"]) {
  661. /**
  662. api: 'cloudVolume',
  663. content: {
  664. parts: [
  665. {
  666. name: '',
  667. volume: 90,//0-100
  668. }
  669. ]
  670. }
  671. */
  672. NSLog(@"-cloudVolume -----%@",parm);
  673. NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
  674. int instrumentId = [content ks_intValueForKey:@"activeMidiId"];
  675. float volume = [content ks_floatValueForKey:@"activeMidiVolume"];
  676. if (instrumentId < 0) {
  677. [self postMessage:parm];
  678. [self.playerEngine getAllTrackVolume];
  679. return;
  680. }
  681. [self.playerEngine volumeTrackVolumeWithInstrumentId:instrumentId volume:volume/100];
  682. [self postMessage:parm];
  683. [self.playerEngine getAllTrackVolume];
  684. }
  685. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudMetronome"]) { // 节拍器播放
  686. self.metronomeParm = [NSMutableDictionary dictionaryWithDictionary:parm];
  687. NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
  688. NSInteger repeatCount = [content ks_integerValueForKey:@"repeat"];
  689. NSInteger denominator = [content ks_integerValueForKey:@"denominator"];
  690. NSInteger numerator = [content ks_integerValueForKey:@"numerator"];
  691. NSInteger supplement = [content ks_integerValueForKey:@"supplement"];
  692. NSString *beatString = [NSString stringWithFormat:@"%zd/%zd", numerator,denominator];
  693. self.beatType = [self getBeatTypeFromString:beatString];
  694. [self showBeatViewRepeatCount:repeatCount supplement:supplement];
  695. }
  696. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudDestroy"]) { // 销毁播放器
  697. self.initEngineSuccess = NO;
  698. // 重置track num array
  699. self.isPlaying = NO;
  700. if (self.playerEngine) {
  701. [self.playerEngine cleanup];
  702. self.playerEngine = nil;
  703. }
  704. }
  705. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudLoading"]) { // loading
  706. NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
  707. BOOL showLoading = [content ks_boolValueForKey:@"show"];
  708. if (showLoading) {
  709. [self showCustomLoading];
  710. }
  711. else {
  712. [self removeCustomLoadingView];
  713. }
  714. }
  715. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudAccompanyMessage"]) { // 获取伴奏
  716. NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
  717. NSString *accompanyUrl = [content ks_stringValueForKey:@"accompanyUrl"];
  718. if (![NSString isEmptyString:accompanyUrl]) {
  719. NSString *fileName = [[accompanyUrl componentsSeparatedByString:@"/"] lastObject];
  720. NSString *filePath = [self getAccompanyFilePathWithName:fileName];
  721. NSURL *fileUrl = [[NSURL alloc] initFileURLWithPath:filePath];
  722. if ([self checkSongHasSaveAccompanyWithSongUrl:accompanyUrl]) {
  723. [self configVideoRecord:fileUrl];
  724. }
  725. else {
  726. MJWeakSelf;
  727. [self downloadUrl:accompanyUrl success:^{
  728. [weakSelf configVideoRecord:fileUrl];
  729. } faliure:nil];
  730. }
  731. }
  732. else {
  733. [LOADING_MANAGER MBShowAUTOHidingInWindow:@"当前曲目无mp3伴奏"];
  734. [self configVideoRecord:nil];
  735. }
  736. }
  737. // 跟音
  738. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"cloudToggleFollow"]) {
  739. NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
  740. NSString *status = [content ks_stringValueForKey:@"state"];
  741. if ([status isEqualToString:@"start"]) { // 开始
  742. [self startTuner];
  743. }
  744. else if ([status isEqualToString:@"end"]) { // 结束
  745. [self stopTuner];
  746. }
  747. }
  748. // 延迟检测
  749. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"startTune"]) { // 延迟测试开始
  750. NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
  751. NSInteger count = [content ks_integerValueForKey:@"count"];
  752. if (count == 0) {
  753. [self.delayArray removeAllObjects];
  754. self.checkIndex = 0;
  755. }
  756. self.checkIndex += 1;
  757. [self configRecordManager];
  758. [self postMessage:parm];
  759. self.isCompareStart = NO;
  760. self.isSoundCheckStart = NO;
  761. self.isDelayCheckStart = YES;
  762. [self startRecordService];
  763. }
  764. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"endTune"]) { // 延迟测试结束
  765. self.isDelayCheckStart = NO;
  766. [self stopRecordService];
  767. [self postMessage:parm];
  768. [self stopMp3Player];
  769. [self sendAdjustEndMessage]; // 发送结束消息
  770. }
  771. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"finishTune"]) { // 延迟测试结束
  772. NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
  773. NSInteger errorCount = 0;
  774. NSInteger totalDelay = 0;
  775. for (NSInteger index = 0 ; index < self.delayArray.count; index++) {
  776. NSInteger micDelay = [self.delayArray[index] integerValue];
  777. if (micDelay > 10 && micDelay < 100) {
  778. totalDelay += micDelay;
  779. }
  780. else {
  781. errorCount++;
  782. }
  783. }
  784. NSMutableDictionary *contentParm = [NSMutableDictionary dictionaryWithDictionary:content];
  785. if (errorCount > 1) { // 错误次数过多
  786. [contentParm setValue:@(NO) forKey:@"result"];
  787. }
  788. else {
  789. [contentParm setValue:@(YES) forKey:@"result"];
  790. NSInteger averageDelay = totalDelay / (self.delayArray.count - errorCount);
  791. UserDefaultSet([NSNumber numberWithDouble:averageDelay], @"micDelay");
  792. }
  793. NSMutableDictionary *sendParm = [NSMutableDictionary dictionary];
  794. [sendParm setValue:@"finishTune" forKey:@"api"];
  795. [sendParm setValue:contentParm forKey:@"content"];
  796. [self postMessage:sendParm];
  797. [self.delayArray removeAllObjects];
  798. self.checkIndex = 0;
  799. }
  800. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"getDeviceDelay"]) {
  801. NSInteger micDelay = [UserDefaultObjectForKey(@"micDelay") integerValue];
  802. NSMutableDictionary *content = [NSMutableDictionary dictionaryWithDictionary:[parm ks_dictionaryValueForKey:@"content"]];
  803. [content setValue:[NSNumber numberWithInteger:micDelay] forKey:@"value"];
  804. NSMutableDictionary *sendParm = [NSMutableDictionary dictionary];
  805. [sendParm setValue:@"getDeviceDelay" forKey:@"api"];
  806. [sendParm setValue:content forKey:@"content"];
  807. [self postMessage:sendParm];
  808. }
  809. // 音视频合成
  810. else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"openAdjustRecording"]) {
  811. KSMediaMergeView *mergeView = [[KSMediaMergeView alloc] init];
  812. [self.view addSubview:mergeView];
  813. [mergeView mas_makeConstraints:^(MASConstraintMaker *make) {
  814. make.left.right.top.bottom.mas_equalTo(self.view);
  815. }];
  816. NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
  817. mergeView.recordId = [content ks_stringValueForKey:@"recordId"];
  818. mergeView.songName = [content ks_stringValueForKey:@"title"];
  819. mergeView.coverImage = [content ks_stringValueForKey:@"coverImg"];
  820. if (self.AQManager) {
  821. self.recordUrl = self.AQManager.audioUrl;
  822. }
  823. MJWeakSelf;
  824. [mergeView configWithVideoUrl:self.videoRecordManager.videoFileURL bgAudioUrl:self.bgAudioUrl remoteBgUrl:self.accompanyUrl recordUrl:self.recordUrl offsetTime:self.offsetTime mergeCallback:^{
  825. [weakSelf musicPublishCallBack:content];
  826. }];
  827. }
  828. else {
  829. [super handleScriptMessageSource:parm];
  830. }
  831. });
  832. }
  833. }
  834. - (void)musicPublishCallBack:(NSDictionary *)content {
  835. NSMutableDictionary *parm = [NSMutableDictionary dictionary];
  836. [parm setValue:@"hideComplexButton" forKey:@"api"];
  837. [parm setValue:@{} forKey:@"content"];
  838. [self postMessage:parm];
  839. }
  840. - (void)uploadVideoWithParm:(NSMutableDictionary *)contentParm sendParm:(NSMutableDictionary *)sendParm {
  841. MJWeakSelf;
  842. [self.videoRecordManager uploadRecordVideoSuccess:^(NSString * _Nonnull videoUrl) {
  843. [contentParm setValue:@"success" forKey:@"type"];
  844. [contentParm setValue:videoUrl forKey:@"filePath"];
  845. [contentParm setValue:@"上传成功" forKey:@"message"];
  846. [sendParm setValue:contentParm forKey:@"content"];
  847. [weakSelf postMessage:sendParm];
  848. } failure:^(NSString * _Nonnull desc) {
  849. [contentParm setValue:@"error" forKey:@"type"];
  850. [contentParm setValue:desc forKey:@"message"];
  851. [sendParm setValue:contentParm forKey:@"content"];
  852. [weakSelf postMessage:sendParm];
  853. }];
  854. }
  855. - (void)showAlertWithMessage:(NSString *)message type:(CHECKDEVICETYPE)deviceType {
  856. [KSPremissionAlert shareInstanceDisplayImage:deviceType message:message showInView:self.view cancel:^{
  857. } confirm:^{
  858. [self openSettingView];
  859. }];
  860. }
  861. - (void)openSettingView {
  862. [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil];
  863. }
  864. - (void)downloadUrl:(NSString *)url success:(void(^)(void))success faliure:(void(^)(void))faliure {
  865. [KSNetworkingManager downloadFileRequestWithFileUrl:url progress:^(int64_t bytesRead, int64_t totalBytes) {
  866. } success:^(NSURL * _Nonnull fileUrl) {
  867. if ([self saveAccompanyFileWithUrl:fileUrl accompanyUrl:url]) {
  868. success();
  869. }
  870. } faliure:^(NSError * _Nonnull error) {
  871. }];
  872. }
  873. - (void)configVideoRecord:(NSURL *)path {
  874. self.videoRecordManager.bgAudioUrl = path;
  875. }
  876. - (void)showBeatViewRepeatCount:(NSInteger)repeatCount supplement:(NSInteger)supplement {
  877. KSCloudBeatView *beatView = [KSCloudBeatView shareInstanceWithBeatType:self.beatType speed:self.currentSpeed repeatCount:repeatCount supplement:supplement];
  878. MJWeakSelf;
  879. [beatView startPlayWithEndCallback:^(BOOL isCancle) {
  880. if (isCancle) { // 取消
  881. [weakSelf sendEndMetronomeMessage:YES];
  882. }
  883. else { // 播放完成
  884. [weakSelf sendEndMetronomeMessage:NO];
  885. }
  886. }];
  887. [self.view addSubview:beatView];
  888. }
  889. - (void)sendEndMetronomeMessage:(BOOL)isCancel {
  890. NSString *status = isCancel ? @"cancel" : @"finish";
  891. NSMutableDictionary *valueDic = [NSMutableDictionary dictionaryWithDictionary:[self.metronomeParm ks_dictionaryValueForKey:@"content"]];
  892. [valueDic setValue:status forKey:@"status"];
  893. NSMutableDictionary *sendParm = [NSMutableDictionary dictionaryWithDictionary:self.metronomeParm];
  894. [sendParm setValue:valueDic forKey:@"content"];
  895. [self postMessage:sendParm];
  896. }
  897. - (void)downloadMidiFile:(NSString *)midiUrl success:(void(^)(void))success faliure:(void(^)(void))faliure {
  898. [KSNetworkingManager downloadFileRequestWithFileUrl:midiUrl progress:^(int64_t bytesRead, int64_t totalBytes) {
  899. } success:^(NSURL * _Nonnull fileUrl) {
  900. if ([self saveMidiFileWithUrl:fileUrl midiUrl:midiUrl]) {
  901. success();
  902. }
  903. } faliure:^(NSError * _Nonnull error) {
  904. faliure();
  905. }];
  906. }
  907. - (BOOL)saveMidiFileWithUrl:(NSURL *)fileUrl midiUrl:(NSString *)midiUrl {
  908. NSData *sourceData = [NSData dataWithContentsOfURL:fileUrl];
  909. NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
  910. NSString *filePath= [cachePath stringByAppendingPathComponent:@"MidiSong"];
  911. // 先创建子目录
  912. NSFileManager *fileManager = [NSFileManager defaultManager];
  913. if (![fileManager fileExistsAtPath:filePath]) {
  914. [fileManager createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:nil];
  915. }else{
  916. NSLog(@"已创建文件夹");
  917. }
  918. NSString *fileName = [[midiUrl componentsSeparatedByString:@"/"] lastObject];
  919. NSString *tempPath = [filePath stringByAppendingPathComponent:fileName];
  920. BOOL success = [sourceData writeToFile:tempPath atomically:NO];
  921. return success;
  922. }
  923. - (NSString *)getFilePathWithName:(NSString *)fileName {
  924. NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
  925. NSString *filePath= [cachePath stringByAppendingPathComponent:@"MidiSong"];
  926. return [filePath stringByAppendingPathComponent:fileName];;
  927. }
  928. - (BOOL)checkSongHasSaveWithSongUrl:(NSString *)songUrl {
  929. BOOL hasSaveFile = NO;
  930. NSString *fileName = [[songUrl componentsSeparatedByString:@"/"] lastObject];
  931. NSString *filePath = [self getFilePathWithName:fileName];
  932. NSFileManager *fileManager = [NSFileManager defaultManager];
  933. if ([fileManager fileExistsAtPath:filePath]) {
  934. hasSaveFile = YES;
  935. }
  936. return hasSaveFile;
  937. }
  938. - (void)sendMessageToSocket:(NSDictionary *)parm {
  939. NSString *messageHeader = @"proxyMessage";
  940. NSString *sendMessage = [self configDataCommond:messageHeader body:[parm ks_dictionaryValueForKey:@"content"]];
  941. [self sendDataToSocketService:sendMessage];
  942. }
  943. - (void)configAudioDeviceType:(NSDictionary *)parm {
  944. AUDIODEVICE_TYPE type = [KSAQRecordManager queryAudioOutputDeviceType];
  945. NSString *valueStr = @"";
  946. BOOL checkIsWired = NO;
  947. switch (type) {
  948. case AUDIODEVICE_TYPE_HEADPHONE:
  949. {
  950. valueStr = @"有线耳机";
  951. checkIsWired = YES;
  952. }
  953. break;
  954. case AUDIODEVICE_TYPE_BLUETOOTH:
  955. {
  956. valueStr = @"蓝牙耳机";
  957. checkIsWired = YES;
  958. }
  959. break;
  960. case AUDIODEVICE_TYPE_NONE:
  961. {
  962. valueStr = @"";
  963. checkIsWired = NO;
  964. }
  965. break;
  966. default:
  967. break;
  968. }
  969. NSMutableDictionary *valueDic = [NSMutableDictionary dictionaryWithDictionary:[parm ks_dictionaryValueForKey:@"content"]];
  970. [valueDic setValue:valueStr forKey:@"type"];
  971. [valueDic setValue:[NSNumber numberWithBool:checkIsWired] forKey:@"checkIsWired"];
  972. NSMutableDictionary *sendParm = [NSMutableDictionary dictionaryWithDictionary:parm];
  973. [sendParm setValue:valueDic forKey:@"content"];
  974. [self postMessage:sendParm];
  975. }
  976. - (void)startRecordService {
  977. if (self.AQManager.isRunning) {
  978. [self.AQManager stopRecord];
  979. }
  980. [self.AQManager startRecord];
  981. }
  982. - (void)stopRecordService {
  983. if (self.AQManager.isRunning) {
  984. [self.AQManager stopRecord];
  985. }
  986. }
  987. - (void)puaseRecordService {
  988. if (self.AQManager.isRunning) {
  989. [self.AQManager pauserRecord];
  990. }
  991. }
  992. - (void)resumeRecordService {
  993. [self.AQManager resumeRecord];
  994. }
  995. - (void)sendEndMessage {
  996. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  997. // 上传停止的信息 发送给服务端
  998. NSString *endMessage = @"recordEnd";
  999. NSString *endData = [self configDataCommond:endMessage body:nil type:@"SOUND_COMPARE"];
  1000. [self sendDataToSocketService:endData];
  1001. self.isCompareStart = NO;
  1002. NSLog(@"---- send end message");
  1003. });
  1004. }
  1005. - (void)sendAdjustEndMessage {
  1006. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  1007. // 上传停止的信息 发送给服务端
  1008. NSString *endMessage = @"recordEnd";
  1009. NSString *endData = [self configDataCommond:endMessage body:nil type:@"DELAY_CHECK"];
  1010. [self sendDataToSocketService:endData];
  1011. self.isDelayCheckStart = NO;
  1012. NSLog(@"---- send adjust end message");
  1013. });
  1014. }
  1015. - (void)sendOffsetTimeToService {
  1016. // 上传停止的信息 发送给服务端
  1017. NSString *offsetMessage = @"audioPlayStart";
  1018. NSTimeInterval micDelay = [UserDefault(@"micDelay") doubleValue];
  1019. NSDictionary *dic = @{@"offsetTime" : [NSNumber numberWithInteger:self.offsetTime], @"micDelay": [NSNumber numberWithInteger:micDelay]};
  1020. NSString *endData = [self configDataCommond:offsetMessage body:dic type:@"SOUND_COMPARE"];
  1021. NSLog(@"------ %@", endData);
  1022. [self sendDataToSocketService:endData];
  1023. self.isCompareStart = NO;
  1024. }
  1025. #pragma mark-------- KSAQRecordManagerDelegate
  1026. - (void)recordInterruption {
  1027. NSDictionary *postParm = @{@"api" : @"cancelEvaluating",
  1028. @"content" : @{@"reson":@"录制错误,请重试"}
  1029. };
  1030. [self postMessage:postParm];
  1031. }
  1032. - (void)audioRouteChange:(AUDIODEVICE_TYPE)type {
  1033. NSString *valueStr = @"";
  1034. BOOL checkIsWired = NO;
  1035. switch (type) {
  1036. case AUDIODEVICE_TYPE_HEADPHONE:
  1037. {
  1038. valueStr = @"有线耳机";
  1039. checkIsWired = YES;
  1040. }
  1041. break;
  1042. case AUDIODEVICE_TYPE_BLUETOOTH:
  1043. {
  1044. valueStr = @"蓝牙耳机";
  1045. checkIsWired = YES;
  1046. }
  1047. break;
  1048. case AUDIODEVICE_TYPE_NONE:
  1049. {
  1050. valueStr = @"";
  1051. checkIsWired = NO;
  1052. }
  1053. break;
  1054. default:
  1055. break;
  1056. }
  1057. NSDictionary *postParm = @{@"api" : @"listenerWiredStatus",
  1058. @"content" : @{@"type":valueStr,
  1059. @"checkIsWired":[NSNumber numberWithBool:checkIsWired]
  1060. }
  1061. };
  1062. [self postMessage:postParm];
  1063. }
  1064. - (void)audioRecord:(KSAQRecordManager *)audioRecord didRecordAudioData:(void *)data length:(UInt32)length {
  1065. if (self.socketManager.socketReadyState != SR_OPEN) {
  1066. return;
  1067. }
  1068. NSData *pushData = [[NSData alloc] initWithBytes:data length:length];
  1069. if (self.isCompareStart) { // 发送评测开始消息
  1070. dispatch_async(dispatch_get_main_queue(), ^{
  1071. NSDate *date = [NSDate date];
  1072. NSTimeInterval inteveral = [date timeIntervalSince1970];
  1073. double beginTime = inteveral - audioRecord.sampleTime;
  1074. NSDictionary *parm = @{
  1075. @"api" : @"recordStartTime",
  1076. @"content" : @{@"inteveral" : [NSNumber numberWithDouble:beginTime]}
  1077. };
  1078. [self postMessage:parm];
  1079. });
  1080. NSLog(@"--------- send start message");
  1081. _isCompareStart = NO;
  1082. NSString *startMessage = @"recordStart";
  1083. NSString *startString = [self configDataCommond:startMessage body:nil type:@"SOUND_COMPARE"];
  1084. [self sendDataToSocketService:startString];
  1085. }
  1086. else if (self.isSoundCheckStart) { // 校音开始
  1087. NSLog(@"--------- send check start message");
  1088. _isSoundCheckStart = NO;
  1089. NSString *checkStartMessage = @"start";
  1090. NSString *startString = [self configDataCommond:checkStartMessage body:nil type:@"PITCH_DETECTION"];
  1091. [self sendDataToSocketService:startString];
  1092. }
  1093. else if (self.isDelayCheckStart) {
  1094. NSLog(@"--------- send delay check start message");
  1095. _isDelayCheckStart = NO;
  1096. NSString *checkStartMessage = @"recordStart";
  1097. NSInteger frequence = 0.0f;
  1098. if (self.checkIndex % 2 == 0) {
  1099. frequence = self.secondFrequence;
  1100. }
  1101. else {
  1102. frequence = self.firstFrequence;
  1103. }
  1104. NSDictionary *parm = @{@"HZ" : @(frequence)};
  1105. NSString *startString = [self configDataCommond:checkStartMessage body:parm type:@"DELAY_CHECK"];
  1106. [self sendDataToSocketService:startString];
  1107. }
  1108. // NSLog(@"--------- send audio data length %d", length);
  1109. [self sendDataToSocketService:pushData];
  1110. }
  1111. - (NSString *)configDataCommond:(NSString *)commond body:(id)bodyMessage type:(NSString *)dataType {
  1112. NSMutableDictionary *parm = [NSMutableDictionary dictionary];
  1113. if (bodyMessage) {
  1114. [parm setValue:bodyMessage forKey:@"body"];
  1115. }
  1116. NSMutableDictionary *headerParm = [NSMutableDictionary dictionary];
  1117. if ([NSString isEmptyString:commond]) {
  1118. [headerParm setValue:@"" forKey:@"commond"];
  1119. }
  1120. else {
  1121. [headerParm setValue:commond forKey:@"commond"];
  1122. }
  1123. if (![NSString isEmptyString:dataType]) {
  1124. [headerParm setValue:dataType forKey:@"type"];
  1125. }
  1126. [headerParm setValue:@(200) forKey:@"status"];
  1127. [parm setValue:headerParm forKey:@"header"];
  1128. return [parm mj_JSONString];
  1129. }
  1130. - (NSString *)configDataCommond:(NSString *)commond body:(id)bodyMessage {
  1131. NSMutableDictionary *parm = [NSMutableDictionary dictionary];
  1132. if (bodyMessage) {
  1133. [parm setValue:bodyMessage forKey:@"body"];
  1134. }
  1135. if ([NSString isEmptyString:commond]) {
  1136. [parm setValue:@{@"commond":@""} forKey:@"header"];
  1137. }
  1138. else {
  1139. [parm setValue:@{@"commond":commond} forKey:@"header"];
  1140. }
  1141. return [parm mj_JSONString];
  1142. }
  1143. - (KSWebSocketManager *)socketManager {
  1144. if (!_socketManager) {
  1145. _socketManager = [[KSWebSocketManager alloc] init];
  1146. }
  1147. return _socketManager;
  1148. }
  1149. #pragma mark --- lazying
  1150. - (UIView *)viewContainer {
  1151. if (!_viewContainer) {
  1152. _viewContainer = [[UIView alloc] init];
  1153. }
  1154. return _viewContainer;
  1155. }
  1156. - (KSVideoRecordManager *)videoRecordManager {
  1157. if (!_videoRecordManager) {
  1158. MJWeakSelf;
  1159. _videoRecordManager = [[KSVideoRecordManager alloc] initSessionRecordCallback:^(BOOL isSuccess, NSString * _Nullable message) {
  1160. if (isSuccess) {
  1161. [weakSelf showSuccessMessage:message];
  1162. }
  1163. else {
  1164. if (![NSString isEmptyString:message]) {
  1165. [LOADING_MANAGER MBShowAUTOHidingInWindow:message];
  1166. }
  1167. }
  1168. }];
  1169. }
  1170. return _videoRecordManager;
  1171. }
  1172. - (void)showSuccessMessage:(NSString *)message {
  1173. [LOADING_MANAGER MBShowAUTOHidingInWindow:message];
  1174. // 成功
  1175. if (self.endRecordParm) {
  1176. [self postMessage:self.endRecordParm];
  1177. self.endRecordParm = nil;
  1178. }
  1179. }
  1180. - (MetronomeType)getBeatTypeFromString:(NSString *)typeString {
  1181. if ([typeString isEqualToString:@"1/4"]) {
  1182. return MetronomeType1V4;
  1183. }
  1184. else if ([typeString isEqualToString:@"2/4"]) {
  1185. return MetronomeType2V4;
  1186. }
  1187. else if ([typeString isEqualToString:@"3/4"]) {
  1188. return MetronomeType3V4;
  1189. }
  1190. else if ([typeString isEqualToString:@"4/4"]) {
  1191. return MetronomeType4V4;
  1192. }
  1193. else if ([typeString isEqualToString:@"3/8"]) {
  1194. return MetronomeType3V8;
  1195. }
  1196. else if ([typeString isEqualToString:@"6/8"]) {
  1197. return MetronomeType6V8;
  1198. }
  1199. else {
  1200. return MetronomeType4V4;
  1201. }
  1202. }
  1203. #pragma mark ------- midi 播放相关
  1204. - (void)configPlayerEngineWithSong:(NSString *)songPath reportTime:(NSInteger)reportTime {
  1205. self.initEngineSuccess = NO;
  1206. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  1207. self.playerEngine = [[MidiPlayerEngine alloc] init];
  1208. self.playerEngine.reportTime = reportTime;
  1209. self.playerEngine.delegate = self;
  1210. [self.playerEngine configSoundFilePath:[[NSBundle mainBundle]
  1211. pathForResource:@"synthgms" ofType:@"sf2"]];
  1212. [self.playerEngine loadMIDIFileWithString:songPath];
  1213. });
  1214. }
  1215. - (void)configAudioSession {
  1216. self.audioSessionManager = [[KSAudioSessionManager alloc] init];
  1217. self.audioSessionManager.delegate = self;
  1218. [self.audioSessionManager configAudioSession:AUDIOCONFIG_PLAYANDRECORD];
  1219. }
  1220. #pragma mark ---- PlayerEngineDelegate
  1221. /** 进度更新
  1222. api: 'cloudTimeUpdae',
  1223. content: {
  1224. // 当前曲目id
  1225. songID: 0,
  1226. // 当前位置时间(ms)
  1227. currentTime: 0
  1228. }
  1229. */
  1230. /** 播放结束事件
  1231. api: 'cloudplayed',
  1232. content: {
  1233. // 当前曲目id
  1234. songID: 0,
  1235. }
  1236. */
  1237. - (void)ProgressUpdated:(float)progress currentTime:(MusicTimeStamp)currentTime {
  1238. if (self.isPlaying == NO) {
  1239. return;
  1240. }
  1241. // 回调
  1242. NSMutableDictionary *sendParm = [NSMutableDictionary dictionary];
  1243. [sendParm setValue:@"cloudTimeUpdae" forKey:@"api"];
  1244. NSMutableDictionary *content = [NSMutableDictionary dictionary];
  1245. [content setValue:self.currentSongId forKey:@"songID"];
  1246. [content setValue:@(currentTime*1000) forKey:@"currentTime"];
  1247. [sendParm setValue:content forKey:@"content"];
  1248. [self postMessage:sendParm];
  1249. }
  1250. - (void)playEnd {
  1251. [self stopPlayAction];
  1252. NSMutableDictionary *sendParm = [NSMutableDictionary dictionary];
  1253. [sendParm setValue:@"cloudplayed" forKey:@"api"];
  1254. NSMutableDictionary *content = [NSMutableDictionary dictionary];
  1255. [content setValue:self.currentSongId forKey:@"songID"];
  1256. [sendParm setValue:content forKey:@"content"];
  1257. [self postMessage:sendParm];
  1258. }
  1259. - (void)initPlayerEngineSuccess:(float)totalTime {
  1260. self.initEngineSuccess = YES;
  1261. if (self.configEngineParm) {
  1262. NSMutableDictionary *sendParm = [NSMutableDictionary dictionaryWithDictionary:self.configEngineParm];
  1263. NSMutableDictionary *content = [NSMutableDictionary dictionaryWithDictionary:[sendParm ks_dictionaryValueForKey:@"content"]];
  1264. [content setValue:@(totalTime*1000) forKey:@"midiDuration"];
  1265. [sendParm setValue:content forKey:@"content"];
  1266. [self postMessage:sendParm];
  1267. self.configEngineParm = nil;
  1268. }
  1269. }
  1270. // 总时长
  1271. - (void)GetMusicTotalTime:(float)time {
  1272. }
  1273. #pragma mark ----- 播放控制
  1274. - (void)playAction {
  1275. self.isPlaying = YES;
  1276. [self.playerEngine playMIDIFile];
  1277. }
  1278. - (void)stopPlayAction {
  1279. self.isPlaying = NO;
  1280. if ([self.playerEngine isPlayingFile]) {
  1281. [self.playerEngine stopPlayingMIDIFile];
  1282. }
  1283. }
  1284. #pragma mark ----- 小酷AI loading
  1285. - (AccompanyLoadingView *)loadingView {
  1286. if (!_loadingView) {
  1287. _loadingView = [AccompanyLoadingView shareInstance];
  1288. MJWeakSelf;
  1289. [_loadingView loadingCallback:^{
  1290. [weakSelf backAction];
  1291. }];
  1292. }
  1293. return _loadingView;
  1294. }
  1295. - (void)showCustomLoading {
  1296. if ([self.view.subviews containsObject:self.loadingView]) {
  1297. return;
  1298. }
  1299. [self.view addSubview:self.loadingView];
  1300. [self.loadingView mas_makeConstraints:^(MASConstraintMaker *make) {
  1301. make.left.top.right.bottom.mas_equalTo(self.view);
  1302. }];
  1303. [self.view bringSubviewToFront:self.loadingView];
  1304. [self.loadingView showLoading];
  1305. }
  1306. - (void)removeCustomLoadingView {
  1307. [self.loadingView stopLoading];
  1308. }
  1309. #pragma mark ----- 跟音模块
  1310. - (void)startTuner {
  1311. if (self.isTunerRuning == NO) {
  1312. self.isTunerRuning = YES;
  1313. [self.tuner start];
  1314. }
  1315. }
  1316. - (void)stopTuner {
  1317. if (self.isTunerRuning) {
  1318. self.isTunerRuning = NO;
  1319. [self.tuner stop];
  1320. }
  1321. }
  1322. - (Tuner *)tuner {
  1323. if (!_tuner) {
  1324. _tuner = [[Tuner alloc] initWithThreshold:0 smoothing:0.25];
  1325. _tuner.delegate = self;
  1326. }
  1327. return _tuner;
  1328. }
  1329. - (void)tunerDidUpdate:(Tuner *)tuner output:(TunerOutput *)output {
  1330. if (output.amplitude < 0.01) {
  1331. }
  1332. else {
  1333. // 回调频率
  1334. NSDictionary *parm = @{
  1335. @"api" : @"cloudFollowTime",
  1336. @"content" : @{@"frequency" : [NSNumber numberWithDouble:output.frequency]}
  1337. };
  1338. [self postMessage:parm];
  1339. }
  1340. NSLog(@"-------- %@%zd --- distance :%f frequence : %f" , output.pitch, output.octave, output.distance, output.frequency);
  1341. }
  1342. #pragma mark ---- 保存伴奏
  1343. - (BOOL)saveAccompanyFileWithUrl:(NSURL *)fileUrl accompanyUrl:(NSString *)accompanyUrl {
  1344. NSData *sourceData = [NSData dataWithContentsOfURL:fileUrl];
  1345. NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
  1346. NSString *filePath= [cachePath stringByAppendingPathComponent:@"AccompanySong"];
  1347. // 先创建子目录
  1348. NSFileManager *fileManager = [NSFileManager defaultManager];
  1349. if (![fileManager fileExistsAtPath:filePath]) {
  1350. [fileManager createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:nil];
  1351. }else{
  1352. NSLog(@"已创建文件夹");
  1353. }
  1354. NSString *fileName = [[accompanyUrl componentsSeparatedByString:@"/"] lastObject];
  1355. NSString *tempPath = [filePath stringByAppendingPathComponent:fileName];
  1356. BOOL success = [sourceData writeToFile:tempPath atomically:NO];
  1357. return success;
  1358. }
  1359. - (NSString *)getAccompanyFilePathWithName:(NSString *)fileName {
  1360. NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
  1361. NSString *filePath= [cachePath stringByAppendingPathComponent:@"AccompanySong"];
  1362. return [filePath stringByAppendingPathComponent:fileName];;
  1363. }
  1364. - (BOOL)checkSongHasSaveAccompanyWithSongUrl:(NSString *)songUrl {
  1365. BOOL hasSaveFile = NO;
  1366. NSString *fileName = [[songUrl componentsSeparatedByString:@"/"] lastObject];
  1367. NSString *filePath = [self getAccompanyFilePathWithName:fileName];
  1368. NSFileManager *fileManager = [NSFileManager defaultManager];
  1369. if ([fileManager fileExistsAtPath:filePath]) {
  1370. hasSaveFile = YES;
  1371. }
  1372. return hasSaveFile;
  1373. }
  1374. #pragma mark ---- player
  1375. - (void)configPlayerDelegate {
  1376. self.dingPlayer.delegate = self;
  1377. self.dongPlayer.delegate = self;
  1378. self.musicPlayer.delegate = self;
  1379. }
  1380. - (kSNewPlayer *)dingPlayer {
  1381. if (!_dingPlayer) {
  1382. _dingPlayer = [[kSNewPlayer alloc] init];
  1383. }
  1384. return _dingPlayer;
  1385. }
  1386. - (kSNewPlayer *)dongPlayer {
  1387. if (!_dongPlayer) {
  1388. _dongPlayer = [[kSNewPlayer alloc] init];
  1389. }
  1390. return _dongPlayer;
  1391. }
  1392. - (kSNewPlayer *)musicPlayer {
  1393. if (!_musicPlayer) {
  1394. _musicPlayer = [[kSNewPlayer alloc] init];
  1395. }
  1396. return _musicPlayer;
  1397. }
  1398. #pragma mark ---- new player delegate
  1399. - (void)getSongCurrentTime:(NSInteger)currentTime andTotalTime:(NSInteger)totalTime andProgress:(CGFloat)progress currentInterval:(NSTimeInterval)currentInterval playTime:(NSTimeInterval)playTime inPlayer:(kSNewPlayer *)player {
  1400. if (player == self.dingPlayer || player == self.dongPlayer) {
  1401. if (playTime >= 300 && playTime < 310 && self.recordStartTime > 0) {
  1402. NSLog(@" --- check player start play time %f", currentInterval*1000 - playTime);
  1403. self.playerStartTime = currentInterval*1000 - playTime;
  1404. self.offsetTime = self.playerStartTime - self.recordStartTime;
  1405. NSLog(@"--------- check player offset time -- %zd", self.offsetTime);
  1406. }
  1407. }
  1408. if (playTime >= 300 && playTime < 310 && player == self.musicPlayer) {
  1409. if (self.recordStartTime > 0) {
  1410. NSLog(@" --- music player start play time %f", currentInterval*1000 - playTime);
  1411. self.playerStartTime = currentInterval*1000 - playTime;
  1412. self.offsetTime = self.playerStartTime - self.recordStartTime;
  1413. NSLog(@"--------- music play offset time -- %zd", self.offsetTime);
  1414. [self sendOffsetTimeToService];
  1415. }
  1416. NSLog(@"------- record start time %f", self.recordStartTime);
  1417. }
  1418. // 回调进度
  1419. if (player == self.musicPlayer) {
  1420. // NSLog(@"------ music play progress - %f", progress);
  1421. // 回调进度
  1422. NSDictionary *parm = @{
  1423. @"api" : @"playProgress",
  1424. @"content" : @{@"currentTime" : [NSNumber numberWithInteger:currentTime],
  1425. @"totalDuration" : [NSNumber numberWithInteger:totalTime],
  1426. }
  1427. };
  1428. // NSLog(@" -----music play progress %@---- ", parm);
  1429. [self postMessage:parm];
  1430. }
  1431. }
  1432. - (void)sendPlayerReadyMsg {
  1433. if (self.playerParm) {
  1434. [self postMessage:self.playerParm];
  1435. }
  1436. }
  1437. - (void)preparePlay:(kSNewPlayer *)player {
  1438. if (player == self.musicPlayer) {
  1439. self.musicPlayerReady = YES;
  1440. }
  1441. else if (player == self.dingPlayer) {
  1442. self.dingPlayerReady = YES;
  1443. }
  1444. else if (player == self.dongPlayer) {
  1445. self.dongPlayerReady = YES;
  1446. }
  1447. // 如果都准备好
  1448. if (self.musicPlayerReady && self.dingPlayerReady && self.dongPlayerReady) {
  1449. [self sendPlayerReadyMsg];
  1450. }
  1451. }
  1452. - (NSMutableArray *)delayArray {
  1453. if (!_delayArray) {
  1454. _delayArray = [NSMutableArray array];
  1455. }
  1456. return _delayArray;
  1457. }
  1458. /*
  1459. #pragma mark - Navigation
  1460. // In a storyboard-based application, you will often want to do a little preparation before navigation
  1461. - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
  1462. // Get the new view controller using [segue destinationViewController].
  1463. // Pass the selected object to the new view controller.
  1464. }
  1465. */
  1466. @end