MusicCenterManager.m 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. //
  2. // MusicCenterManager.m
  3. // BuguLive
  4. //
  5. // Created by 岳克奎 on 16/12/16.
  6. // Copyright © 2016年 xfg. All rights reserved.
  7. //
  8. #import "MusicCenterManager.h"
  9. @implementation MusicCenterManager
  10. #pragma mark -------------------------------------life cycle -------------------------------------
  11. #pragma mark - 音乐控制中 单利
  12. /**
  13. * @brief: 音乐控制中 单利
  14. *
  15. * @discussion:我的想法是,用单利管理,这样能够通过C++的player对应的控制器来控制。播放,暂停。如果不这样,需要频繁的
  16. */
  17. static MusicCenterManager *signleton = nil;
  18. + (instancetype)allocWithZone:(struct _NSZone *)zone
  19. {
  20. static dispatch_once_t onceToken;
  21. dispatch_once(&onceToken, ^{
  22. signleton = [super allocWithZone:zone];
  23. });
  24. return signleton;
  25. }
  26. + (MusicCenterManager *)shareManager
  27. {
  28. static dispatch_once_t onceToken;
  29. dispatch_once(&onceToken, ^{
  30. signleton = [[self alloc] init];
  31. });
  32. return signleton;
  33. }
  34. + (id)copyWithZone:(struct _NSZone *)zone
  35. {
  36. return signleton;
  37. }
  38. + (id)mutableCopyWithZone:(struct _NSZone *)zone
  39. {
  40. return signleton;
  41. }
  42. #pragma mark ----------------------------------- 音 乐 控制 逻辑层 部 分(Logic) -----------------------------------
  43. #pragma mark - 音乐路径处理(L)
  44. /**
  45. * @brief: 音乐路径处理,获取完整的音乐文件地址str
  46. *
  47. */
  48. - (NSString *)searchFullFilePathOfMusicFilePathStr:(NSString *)musicFilePathStr
  49. {
  50. NSString *str = [NSString stringWithFormat:@"/Documents/%@/%@",@"music",musicFilePathStr];
  51. if (str && ![str isEqualToString:@""])
  52. {
  53. return [NSHomeDirectory() stringByAppendingString:str];
  54. }
  55. return NSHomeDirectory();
  56. }
  57. #pragma mark ------------------------------------------ set/get ----------------------------------------
  58. //musicDataManager 数据层管理中心
  59. /**
  60. * @brief: 数据层管理中心
  61. *
  62. * @Function: 我个人认为每个模块都有自己的数据层,MVCS架构臃肿,如果要移植怎么办,还是奉行高聚合,低耦合思想比较好。
  63. *
  64. * @discussion: 目前只是处理一部分,音乐不是一般的复杂
  65. */
  66. - (MusicDataManager *)musicDataManager
  67. {
  68. if (!_musicDataManager)
  69. {
  70. _musicDataManager = [MusicDataManager shareManager];
  71. }
  72. return _musicDataManager;
  73. }
  74. #pragma mark- 音乐的状态(暂时只监听有互动)
  75. /***
  76. * @brief:音乐的状态(暂时只监听有互动,预留云音乐的合并)
  77. *
  78. * @dicussion: 1.暂时这里只处理互动 后期云音乐建议代码合并到音乐调度中心
  79. * 2.通过属性的变化 来改变UI的变动。这样不用我们去找UI,调度中心属性更变,跟简单控制UI层的变化
  80. * 3.从大的方面来讲 UI层是干什么的 只是管理生命周期+SDK方法的。逻辑层的方法 应该又 单独剥离处理啊的 逻辑层管理
  81. * @use: 音乐暂停 恢复
  82. */
  83. - (void)setMusicPlayingState:(BOOL)musicPlayingState
  84. {
  85. if (_delegate && [_delegate respondsToSelector:@selector(musicStartOrStopPlayOfPlayingState:)])
  86. {
  87. _musicPlayingState = [_delegate musicStartOrStopPlayOfPlayingState:musicPlayingState];
  88. }
  89. //更变 音乐控制Btn的状态
  90. if (_dataDelegate && [_dataDelegate respondsToSelector:@selector(changeMusicBtnOfPlayStatewWithMusicPlayState:)])
  91. {
  92. [_dataDelegate changeMusicBtnOfPlayStatewWithMusicPlayState:_musicPlayingState];
  93. }
  94. //多种输入输出,例如可以耳机、USB设备同时播放
  95. [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryMultiRoute error:nil];
  96. //iOS 10下 音乐播放必须需要加
  97. [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
  98. }
  99. #pragma mark - 音乐的本地沙盒路径str
  100. /**
  101. * @brief:音乐的本地沙盒路径str
  102. *
  103. * @discussion:
  104. */
  105. - (void)setRecordMusicFilePatnStr:(NSString *)recordMusicFilePatnStr
  106. {
  107. _recordMusicFilePatnStr = recordMusicFilePatnStr;
  108. //当发生变化 就去播放
  109. [self superPlayerPlayOfSamplerateNum:44100 musicFilePathStr:_recordMusicFilePatnStr];
  110. }
  111. #pragma mark - music play 音乐播放(L)(Public)
  112. /**
  113. * @brief: 超级播放器播放
  114. *
  115. * @prama: samplerateNum 采样率
  116. * @prama: musicFilePathStr 音乐路径Str(不完整,需要再处理下)
  117. *
  118. * @Step: _musicPlayingState YES 启动音乐播放,音乐处于播放状态
  119. * @Step: 启动音乐播放器
  120. * @Step: 通过设置SDK混音代理,实现代理方法,将相应的内存里的数据 不断传入SDK混音方法里
  121. * @Step: AVAudioSession 输出设置
  122. * @Step: AVAudioSession 播放
  123. *
  124. * @use: 使用前提 采样率+路径
  125. *
  126. * @discussion: 1.在音乐VC初次创建的时候,会调这里
  127. * 2.思考:想下腾讯云,要不要把控制中心方法嫩成代理呢?
  128. */
  129. - (void)superPlayerPlayOfSamplerateNum:(int)samplerateNum musicFilePathStr:(NSString *)musicFilePathStr
  130. {
  131. //音乐路径不存在 最好判断这个文件存在与否!!!
  132. if(!musicFilePathStr)
  133. {
  134. return;
  135. }
  136. // 音乐播放
  137. if (_delegate &&[_delegate respondsToSelector:@selector(showMusicPlayOfMusicPathStr:ofSamplerateNum:)])
  138. {
  139. [_delegate showMusicPlayOfMusicPathStr:[self searchFullFilePathOfMusicFilePathStr:musicFilePathStr] ofSamplerateNum:samplerateNum];
  140. }
  141. //互动SDK 必须实现一些方法 主要是开启KTV 回响模式+音乐数据混音 SDK的方法放在SDK里处理
  142. //[self copyMusicPlayDataToSDKHD];
  143. if (_dataDelegate &&[_dataDelegate respondsToSelector:@selector(showMusicSDKMehodsWhenShowNewPlayer)])
  144. {
  145. [_dataDelegate showMusicSDKMehodsWhenShowNewPlayer];
  146. }
  147. }
  148. #pragma mark - 音乐的名称str
  149. /**
  150. * @brief: 音乐的名称str
  151. *
  152. * @discussion:
  153. */
  154. - (void)setRecordMusicNameStr:(NSString *)recordMusicNameStr
  155. {
  156. _recordMusicNameStr = recordMusicNameStr;
  157. }
  158. #pragma mark - 音乐的歌手名Str
  159. /**
  160. * @brief:音乐的歌手名Str
  161. *
  162. * @discussion:
  163. */
  164. - (void)setRecordMusicSingerStr:(NSString *)recordMusicSingerStr
  165. {
  166. _recordMusicSingerStr = recordMusicSingerStr;
  167. }
  168. #pragma mark - 当前音乐  总时间
  169. /**
  170. * @brief: 当前音乐 歌词 str
  171. *
  172. * @discussion:
  173. */
  174. - (void)setRecordMusicTotalDuration:(CGFloat)recordMusicTotalDuration
  175. {
  176. _recordMusicTotalDuration = recordMusicTotalDuration;
  177. if (_dataDelegate&&[_dataDelegate respondsToSelector:@selector(sendMusicTotalDuration:musicCurrentDuration:musicPresent:)])
  178. {
  179. [_dataDelegate sendMusicTotalDuration:_recordMusicTotalDuration musicCurrentDuration:_recordMusicCurrentDuration musicPresent:_musicPresent];
  180. }
  181. }
  182. #pragma mark - 当前音乐  总时间
  183. /**
  184. * @brief: 当前音乐 歌词 str
  185. *
  186. * @discussion:
  187. */
  188. - (void)setRecordMusicCurrentDuration:(CGFloat)recordMusicCurrentDuration
  189. {
  190. _recordMusicCurrentDuration = recordMusicCurrentDuration;
  191. if (_dataDelegate&&[_dataDelegate respondsToSelector:@selector(sendMusicTotalDuration:musicCurrentDuration:musicPresent:)])
  192. {
  193. [_dataDelegate sendMusicTotalDuration:_recordMusicTotalDuration musicCurrentDuration:_recordMusicCurrentDuration musicPresent:_musicPresent];
  194. }
  195. }
  196. - (void)setMusicPresent:(CGFloat)musicPresent
  197. {
  198. _musicPresent = musicPresent;
  199. if (_dataDelegate&&[_dataDelegate respondsToSelector:@selector(sendMusicTotalDuration:musicCurrentDuration:musicPresent:)])
  200. {
  201. [_dataDelegate sendMusicTotalDuration:_recordMusicTotalDuration musicCurrentDuration:_recordMusicCurrentDuration musicPresent:_musicPresent];
  202. }
  203. }
  204. #pragma mark - 当前音乐 歌词 str
  205. /**
  206. 当前音乐 歌词 str
  207. 1.代码为啥写在这里,还是想通过 音乐控制中心去完成 各个模块的交互??????????
  208. 2.lrcView 看成已经集成UI,我们只需要通过音乐控制中心去调度加载就ok!
  209. 3.只是集成 2行(上下行)模式
  210. VC或view需要显示 两行Lrc
  211. @param recordMusicLrcStr 歌词
  212. */
  213. - (void)setRecordMusicLrcStr:(NSString *)recordMusicLrcStr
  214. {
  215. _recordMusicLrcStr = recordMusicLrcStr;
  216. //歌词处理
  217. [self showMusicLRCofLRCDataStr:_recordMusicLrcStr musicNameStr:_recordMusicNameStr musicSingerStr:_recordMusicSingerStr complete:^(BOOL finished, NSMutableArray *lrcModelMArray, NSMutableArray *lrcPointTimeStrArray) {
  218. //将数据通过代理传走
  219. if(_dataDelegate && [_dataDelegate respondsToSelector:@selector(sendMusicOfLrcModelMArray:lrcPointTimeStrArray:musicNameStr:musicSingerStr:)])
  220. {
  221. [_dataDelegate sendMusicOfLrcModelMArray:lrcModelMArray lrcPointTimeStrArray:lrcPointTimeStrArray musicNameStr:_recordMusicNameStr musicSingerStr:_recordMusicSingerStr];
  222. }
  223. }];
  224. }
  225. #pragma mark - music 加载歌词(UI)
  226. /**
  227. * @ brief:加载歌词
  228. *
  229. * @prama : lrcDataStr 歌词
  230. * @prama : mDic 歌词 名信息
  231. * @prama : block finished lrcModelMArray 相当于我么你的歌词数据源
  232. *
  233. * @ use : 把歌词给管理中心,管理中心自动调给数据层解析数据,然后把数据 返回给对应的对象
  234. */
  235. - (void)showMusicLRCofLRCDataStr:(NSString *)lrcDataStr musicNameStr:(NSString *)musicNameStr musicSingerStr:(NSString *)musicSingerStr complete:(void(^)(BOOL finished, NSMutableArray *lrcModelMArray, NSMutableArray *lrcPointTimeStrArray))block
  236. {
  237. // 数据层处理了数据生成 lrcmode返回给控制中心
  238. [[MusicDataManager shareManager] analysisLrcStrOfMusicLRCDataStr:lrcDataStr musicNameStr:musicNameStr musicSingerStr:musicSingerStr complete:^(BOOL finished, NSMutableArray *lrcModelMArray, NSMutableArray *lrcPointTimeStrArray) {
  239. if (block)
  240. {
  241. block(finished, lrcModelMArray, lrcPointTimeStrArray);
  242. }
  243. }];
  244. }
  245. #pragma mark - 当前音乐 歌词 数据源 数组
  246. /**
  247. * @brief: 当前音乐 歌词 数据源 数组
  248. *
  249. * @discussion:
  250. */
  251. - (void)setRecordLrcDataArray:(NSArray *)recordLrcDataArray
  252. {
  253. _recordLrcDataArray = recordLrcDataArray;
  254. }
  255. #pragma mark - 记录 音乐VC 在父视图的frame
  256. /**
  257. * @brief:记录 音乐VC 在父视图的frame
  258. *
  259. * @discussion:
  260. */
  261. - (void)setRecordMusicFunctionVCFrameRect:(CGRect)recordMusicFunctionVCFrameRect
  262. {
  263. _recordMusicFunctionVCFrameRect = recordMusicFunctionVCFrameRect;
  264. }
  265. @end