JXAudioPlayer.m 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. //
  2. // JXAudioPlayer.m
  3. // shiku_im
  4. //
  5. // Created by flyeagleTang on 17/1/12.
  6. // Copyright © 2017年 Reese. All rights reserved.
  7. //
  8. #import "JXAudioPlayer.h"
  9. #import "VoiceConverter.h"
  10. @implementation JXAudioPlayer
  11. @synthesize player=_player,delegate,timeLenView=_timeLenView;
  12. - (id)initWithParent:(UIView*)value{
  13. self = [super init];
  14. if (self) {
  15. self.parent = value;
  16. [self reset];
  17. _pauseBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 35, 35)];
  18. _pauseBtn.center = CGPointMake(_parent.frame.size.width/2,_parent.frame.size.height/2);
  19. [_pauseBtn setBackgroundImage:[UIImage imageNamed:@"feeds_play_btn_u"] forState:UIControlStateNormal];
  20. [_pauseBtn setBackgroundImage:[UIImage imageNamed:@"feeds_play_btn_h_u"] forState:UIControlStateSelected];
  21. [_pauseBtn addTarget:self action:@selector(switch) forControlEvents:UIControlEventTouchUpInside];
  22. [_parent addSubview:_pauseBtn];
  23. _wait = [[JXWaitView alloc] initWithParent:_parent];
  24. }
  25. return self;
  26. }
  27. -(id)init{
  28. self = [super init];
  29. if (self) {
  30. [self reset];
  31. }
  32. return self;
  33. }
  34. - (id)initWithParent:(UIView*)value frame:(CGRect)frame isLeft:(BOOL)isLeft{
  35. self = [super init];
  36. if (self) {
  37. self.parent = value;
  38. [self reset];
  39. _frame = frame;
  40. _voiceBtn = [[JXImageView alloc] initWithFrame:frame];
  41. _voiceBtn.userInteractionEnabled = YES;
  42. _voiceBtn.backgroundColor = [UIColor clearColor];
  43. _voiceBtn.layer.cornerRadius = 3;
  44. _voiceBtn.layer.masksToBounds = YES;
  45. _voiceBtn.didTouch = @selector(switch);
  46. _voiceBtn.delegate = self;
  47. [_parent addSubview:_voiceBtn];
  48. _voiceView = [[JXImageView alloc]init];
  49. _voiceView.animationDuration = 1;
  50. _voiceView.frame = CGRectMake(2, 1.5, 25, _voiceBtn.frame.size.height-3);
  51. [_voiceBtn addSubview:_voiceView];
  52. UIPanGestureRecognizer * tap = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(gotoAudioTime:)];
  53. [_voiceBtn addGestureRecognizer:tap];
  54. _timeLenView = [[UILabel alloc] init];
  55. _timeLenView.backgroundColor = [UIColor clearColor];
  56. _timeLenView.textColor = HEXCOLOR(0x999999);
  57. _timeLenView.font = [UIFont systemFontOfSize:g_constant.chatFont];
  58. _timeLenView.userInteractionEnabled = NO;
  59. [_voiceBtn addSubview:_timeLenView];
  60. _showProgress = YES;
  61. _pgBGView = [[UIView alloc] init];
  62. [_voiceBtn addSubview:_pgBGView];
  63. _progressView = [[UIProgressView alloc] init];
  64. _progressView.progress = 0.0;
  65. [_pgBGView addSubview:_progressView];
  66. _pgBGView.hidden= YES;
  67. _wait = [[JXWaitView alloc] initWithParent:_voiceBtn];
  68. self.isLeft = isLeft;
  69. }
  70. return self;
  71. }
  72. -(void)gotoAudioTime:(UIPanGestureRecognizer *)tapGes{
  73. if (!self.isPlaying) {
  74. [self switch];
  75. return;
  76. }
  77. CGPoint touchPoint = [tapGes locationInView:tapGes.view];
  78. if (touchPoint.x >= tapGes.view.frame.size.width) {
  79. return;
  80. }
  81. float progress = touchPoint.x / tapGes.view.frame.size.width;
  82. if (progress >= 1) {
  83. progress = 1;
  84. }
  85. _progressView.progress = progress;
  86. NSLog(@"ddddd%f",_player.duration*progress);
  87. _player.currentTime = _player.duration*progress;
  88. }
  89. - (void)dealloc {
  90. NSLog(@"JXAudioPlayer.dealloc");
  91. self.parent = nil;
  92. self.delegate = nil;
  93. [g_notify removeObserver:self];
  94. [self freeTimer];
  95. [self stop];
  96. }
  97. -(void)reset{
  98. _isOpened = NO;
  99. self.isPlaying = NO;
  100. _array=[[NSMutableArray alloc] init];
  101. [g_notify addObserver:self selector:@selector(playerPause:) name:kAllAudioPlayerPauseNotifaction object:nil];//开始录音
  102. [g_notify addObserver:self selector:@selector(playerStop:) name:kAllAudioPlayerStopNotifaction object:nil];//开始录音
  103. [g_notify addObserver:self selector:@selector(EnterForeground) name:UIApplicationWillEnterForegroundNotification object:nil];
  104. [self setHardware];
  105. }
  106. -(void)setHardware{
  107. // [[UIDevice currentDevice] setProximityMonitoringEnabled:YES];
  108. //初始化播放器的时候如下设置,添加监听
  109. UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
  110. AudioSessionSetProperty(kAudioSessionProperty_AudioCategory,
  111. sizeof(sessionCategory),
  112. &sessionCategory);
  113. UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
  114. AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,
  115. sizeof (audioRouteOverride),
  116. &audioRouteOverride);
  117. //默认播放
  118. AVAudioSession *audioSession = [AVAudioSession sharedInstance];
  119. if (self.isChatAudio) {
  120. BOOL flag = [g_default boolForKey:kChatVCMessageAudioIsNotPlayback];
  121. if (flag) {
  122. [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
  123. }else {
  124. [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
  125. }
  126. }else {
  127. [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
  128. }
  129. [audioSession setActive:YES error:nil];
  130. // audioSession = nil;
  131. }
  132. //处理监听触发事件
  133. -(void)sensorStateChange:(NSNotificationCenter *)notification;
  134. {
  135. BOOL flag = [g_default boolForKey:kChatVCMessageAudioIsNotPlayback];
  136. if (self.isChatAudio) {
  137. if (flag) {
  138. return;
  139. }
  140. }
  141. //如果此时手机靠近面部放在耳朵旁,那么声音将通过听筒输出,并将屏幕变暗(省电啊)
  142. if ([[UIDevice currentDevice] proximityState] == YES)
  143. {
  144. if(!self.isPlaying)//正在播放才影响
  145. return;
  146. if(![[AVAudioSession sharedInstance].category isEqualToString:AVAudioSessionCategoryPlayAndRecord]) {
  147. NSLog(@"切换到听筒模式");
  148. [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
  149. }
  150. }
  151. else
  152. {
  153. if(![[AVAudioSession sharedInstance].category isEqualToString:AVAudioSessionCategoryPlayback]) {
  154. NSLog(@"切换到免提模式");
  155. [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
  156. }
  157. if (!self.isPlaying) {
  158. [[UIDevice currentDevice] setProximityMonitoringEnabled:NO];
  159. [g_notify removeObserver:self name:@"UIDeviceProximityStateDidChangeNotification" object:nil];
  160. }else {
  161. if (self.isOpenProximityMonitoring) {
  162. [[UIDevice currentDevice] setProximityMonitoringEnabled:YES];
  163. }
  164. }
  165. }
  166. }
  167. -(void)open{
  168. if (!_audioFile) {
  169. return;
  170. }
  171. NSString* file;
  172. file = [myTempFilePath stringByAppendingString:[_audioFile lastPathComponent]];
  173. if([_audioFile rangeOfString:@"://"].location != NSNotFound){
  174. if(![[NSFileManager defaultManager]fileExistsAtPath:file]){
  175. [self downloadFile:_audioFile];
  176. return;
  177. }
  178. }else
  179. file = _audioFile;
  180. if([[[_audioFile pathExtension] uppercaseString] isEqualToString:@"AMR"])
  181. file = [VoiceConverter amrToWav:file];
  182. if(file==nil)
  183. return;
  184. if(_player)
  185. [self stop];
  186. _player = [[AVAudioPlayer alloc] initWithData:[NSData dataWithContentsOfFile:file] error:nil];
  187. _player.delegate = self;
  188. _player.volume = 10;
  189. _isOpened = YES;
  190. if(_player.prepareToPlay)
  191. [self doAudioOpen];
  192. }
  193. -(void)switch{
  194. if(_player.prepareToPlay){
  195. if(_player.isPlaying){
  196. [self pause];
  197. }
  198. else{
  199. [self play];
  200. }
  201. }else{
  202. [self open];
  203. [self play];
  204. }
  205. }
  206. -(void)play{
  207. if(!_player.prepareToPlay)
  208. return;
  209. if (!self.isNotStopLast) {
  210. [g_notify postNotificationName:kAllAudioPlayerPauseNotifaction object:self userInfo:nil];
  211. [g_notify postNotificationName:kAllVideoPlayerPauseNotifaction object:self userInfo:nil];
  212. }
  213. if (self.isChatAudio) {
  214. BOOL flag = [g_default boolForKey:kChatVCMessageAudioIsNotPlayback];
  215. if (flag) {
  216. [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
  217. }else {
  218. [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
  219. }
  220. }else {
  221. [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
  222. }
  223. [_player play];
  224. [self doPlayBegin];
  225. }
  226. -(void)pause{
  227. [self doPause];
  228. [_player pause];
  229. }
  230. -(void)stop{
  231. if(_player==nil)
  232. return;
  233. [self doPause];
  234. [_player stop];
  235. // [_player release];
  236. _player = nil;
  237. _isOpened = NO;
  238. }
  239. -(void)setParent:(UIView *)value{
  240. [self adjust];
  241. if([_parent isEqual:value])
  242. return;
  243. // [_parent release];
  244. // _parent = [value retain];
  245. _parent = value;
  246. [self adjust];
  247. }
  248. -(void)setAudioFile:(NSString *)value{
  249. if([_audioFile isEqual:value])
  250. return;
  251. // [_audioFile release];
  252. // _audioFile = [value retain];
  253. _audioFile = value;
  254. [self stop];
  255. }
  256. -(void)playerStop:(NSNotification*)notification{
  257. if([notification.object isEqual:self])
  258. return;
  259. [self stop];
  260. }
  261. -(void)playerPause:(NSNotification*)notification{
  262. if([notification.object isEqual:self])
  263. return;
  264. [self pause];
  265. }
  266. - (void)downloadFile:(NSString *)fileUrl{
  267. if([fileUrl length]<=0)
  268. return;
  269. NSString *filepath = [myTempFilePath stringByAppendingPathComponent:[fileUrl lastPathComponent]];
  270. if( ![[NSFileManager defaultManager] fileExistsAtPath:filepath])
  271. [g_server addTask:fileUrl param:nil toView:self];
  272. }
  273. - (void)didServerResultSucces:(JXConnection *)aDownload dict:(NSDictionary *)dict array:(NSArray *)array1{
  274. [_wait stop];
  275. self.audioFile = aDownload.downloadFile;
  276. [self open];
  277. // [_player play];
  278. [self play];
  279. }
  280. -(int) didServerResultFailed:(JXConnection*)aDownload dict:(NSDictionary*)dict{
  281. [_wait stop];
  282. return hide_error;
  283. }
  284. -(int) didServerConnectError:(JXConnection*)aDownload error:(NSError *)error{
  285. [_wait stop];
  286. return hide_error;
  287. }
  288. -(void) didServerConnectStart:(JXConnection*)aDownload{
  289. [_wait start];
  290. }
  291. - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player1 successfully:(BOOL)flag{
  292. [self doPlayEnd];
  293. }
  294. -(void)adjust{
  295. if(_parent==nil)
  296. return;
  297. [_parent addSubview:_voiceBtn];
  298. [_parent addSubview:_pauseBtn];
  299. _voiceBtn.frame = _frame;
  300. _pauseBtn.center = CGPointMake(_parent.frame.size.width/2,_parent.frame.size.height/2);
  301. if(_voiceBtn)
  302. _wait.parent = _voiceBtn;
  303. else
  304. _wait.parent = _parent;
  305. [_wait adjust];
  306. }
  307. - (void)audioPlayerEndInterruption:(AVAudioPlayer *)player{
  308. [self doPause];
  309. }
  310. - (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError * __nullable)error{
  311. //NSLog(@"");
  312. }
  313. -(void)doAudioOpen{
  314. if(self.delegate != nil && [self.delegate respondsToSelector:self.didAudioOpen])
  315. [self.delegate performSelectorOnMainThread:self.didAudioOpen withObject:self waitUntilDone:NO];
  316. }
  317. -(void)doPlayEnd{
  318. self.isPlaying = NO;
  319. if ([[UIDevice currentDevice] proximityState] == NO) {
  320. [[UIDevice currentDevice] setProximityMonitoringEnabled:NO]; //播放结束设置NO,结束红外感应
  321. [g_notify removeObserver:self name:@"UIDeviceProximityStateDidChangeNotification" object:nil];
  322. }
  323. _pauseBtn.selected = NO;
  324. [_voiceView stopAnimating];
  325. _progressView.progress = 0.0;
  326. _pgBGView.hidden = YES;
  327. [self freeTimer];
  328. if (!_parent) return;
  329. if(self.delegate != nil && [self.delegate respondsToSelector:self.didAudioPlayEnd])
  330. [self.delegate performSelectorOnMainThread:self.didAudioPlayEnd withObject:self waitUntilDone:NO];
  331. }
  332. -(void)doPlayBegin{
  333. self.isPlaying = YES;
  334. if (self.isOpenProximityMonitoring) {
  335. [g_notify addObserver:self selector:@selector(sensorStateChange:) name:@"UIDeviceProximityStateDidChangeNotification" object:nil];
  336. [[UIDevice currentDevice] setProximityMonitoringEnabled:YES]; //播放之前设置yes,开启红外感应
  337. }
  338. _pauseBtn.selected = YES;
  339. [_voiceView startAnimating];
  340. _pgBGView.hidden = (_timeLen >= 10 && _showProgress) ? NO : YES;
  341. if (_timer == nil) {
  342. _timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(updateProgress) userInfo:nil repeats:YES];
  343. }
  344. if(self.delegate != nil && [self.delegate respondsToSelector:self.didAudioPlayBegin])
  345. [self.delegate performSelectorOnMainThread:self.didAudioPlayBegin withObject:self waitUntilDone:NO];
  346. }
  347. -(void)doPause{
  348. self.isPlaying = NO;
  349. [[UIDevice currentDevice] setProximityMonitoringEnabled:NO]; //播放结束设置NO,结束红外感应
  350. _pauseBtn.selected = NO;
  351. [_voiceView stopAnimating];
  352. _pgBGView.hidden = YES;
  353. [self freeTimer];
  354. if(self.delegate != nil && [self.delegate respondsToSelector:self.didAudioPause])
  355. [self.delegate performSelectorOnMainThread:self.didAudioPause withObject:self waitUntilDone:NO];
  356. }
  357. -(void)freeTimer{
  358. [_timer invalidate];
  359. _timer = nil;
  360. }
  361. -(void)EnterForeground{
  362. if(_player.prepareToPlay){
  363. [self performSelector:@selector(pause) withObject:nil afterDelay:0.1];
  364. }
  365. }
  366. -(void)setIsLeft:(BOOL)value{
  367. _isLeft = value;
  368. self.timeLen = _timeLen;
  369. [_array removeAllObjects];
  370. NSString* file,*s;
  371. if(!_isLeft)
  372. file = @"voice_paly_right_";
  373. else
  374. file = @"voice_paly_left_";
  375. for(int i=1;i<=3;i++){
  376. s = [NSString stringWithFormat:@"%@%d",file,i];
  377. [_array addObject:[UIImage imageNamed:s]];
  378. }
  379. _voiceView.animationImages = _array;
  380. _voiceView.image = [_array objectAtIndex:[_array count]-1];
  381. }
  382. -(void)setTimeLen:(int)value{
  383. _timeLen = value;
  384. if(_timeLen <= 0)
  385. _timeLen = 1;
  386. int w = (JX_SCREEN_WIDTH-HEAD_SIZE-INSETS*2-70)/30;
  387. w = 70+w*self.timeLen;
  388. if(w<70)
  389. w = 70;
  390. if(w>200)
  391. w = 200;
  392. if(w>_frame.size.width)
  393. w = _frame.size.width;
  394. _timeLenView.text = [NSString stringWithFormat:@"%d''",_timeLen];
  395. CGSize size = [_timeLenView.text sizeWithAttributes:@{NSFontAttributeName:SYSFONT(g_constant.chatFont)}];
  396. if(_isLeft){
  397. _voiceView.frame = CGRectMake(INSETS, (_frame.size.height-24)/2, 24, 24);
  398. _timeLenView.frame = CGRectMake(w-size.width-10, (_frame.size.height-24)/2, size.width, 24);
  399. _timeLenView.textAlignment = NSTextAlignmentRight;
  400. _pgBGView.frame = CGRectMake(CGRectGetMaxX(_voiceView.frame), 0, CGRectGetMinX(_timeLenView.frame)-CGRectGetMaxX(_voiceView.frame)-5, _frame.size.height);
  401. }
  402. else{
  403. _voiceView.frame = CGRectMake(w-INSETS-24, (_frame.size.height-24)/2, 24, 24);
  404. _timeLenView.frame = CGRectMake(8, (_frame.size.height-24)/2, size.width, 24);
  405. _timeLenView.textAlignment = NSTextAlignmentLeft;
  406. _pgBGView.frame = CGRectMake(CGRectGetMaxX(_timeLenView.frame), 0, CGRectGetMinX(_voiceView.frame)-CGRectGetMaxX(_timeLenView.frame), _frame.size.height);
  407. }
  408. _progressView.transform = CGAffineTransformIdentity;
  409. _progressView.frame = CGRectMake(0, (CGRectGetHeight(_pgBGView.frame)-2)/2, CGRectGetWidth(_pgBGView.frame), 2);
  410. _progressView.transform = CGAffineTransformMakeScale(1.0f, 1.5f);
  411. }
  412. -(void)setHidden:(BOOL)value{
  413. _pauseBtn.hidden = value;
  414. _voiceBtn.hidden = value;
  415. }
  416. -(void)setFrame:(CGRect)value{
  417. _frame = value;
  418. [self adjust];
  419. self.isLeft = _isLeft;
  420. }
  421. -(void)updateProgress{
  422. [_progressView setProgress:(_player.currentTime/_player.duration) animated:YES];
  423. // NSLog(@"player_%f,%f",_player.currentTime,_player.duration);
  424. }
  425. @end