// // RQMusicManager.m // JSJP // // Created by 张嵘 on 2021/8/17. // #import "RQMusicManager.h" static void *kStatusKVOKey = &kStatusKVOKey; static void *kDurationKVOKey = &kDurationKVOKey; static void *kBufferingRatioKVOKey = &kBufferingRatioKVOKey; @interface RQMusicManager () @property (nonatomic, readwrite, strong) DOUAudioStreamer *streamer; @property (nonatomic, readwrite, copy) DOUAudioStreamerStatusBlock audioStreamerStatusBlock; @property (nonatomic, readwrite, copy) NSString *urlString; @end @implementation RQMusicManager @def_singleton(RQMusicManager); - (void)rq_cancelStreamer { if (_streamer != nil) { [_streamer pause]; if (self.audioStreamerStatusBlock) { self.audioStreamerStatusBlock(DOUAudioStreamerPaused); } [_streamer removeObserver:self forKeyPath:@"status"]; [_streamer removeObserver:self forKeyPath:@"duration"]; [_streamer removeObserver:self forKeyPath:@"bufferingRatio"]; _streamer = nil; _urlString = nil; } } - (void)rq_resetStreamer { [self rq_cancelStreamer]; RQTrack *track = [[RQTrack alloc] init]; self.urlString = track.audioFileURL.path; _streamer = [DOUAudioStreamer streamerWithAudioFile:track]; [_streamer addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:kStatusKVOKey]; [_streamer addObserver:self forKeyPath:@"duration" options:NSKeyValueObservingOptionNew context:kDurationKVOKey]; [_streamer addObserver:self forKeyPath:@"bufferingRatio" options:NSKeyValueObservingOptionNew context:kBufferingRatioKVOKey]; [_streamer play]; [self rq_setupHintForStreamer]; } - (void)rq_resetStreamerWithURLString:(NSString *)urlString { [self rq_cancelStreamer]; RQTrack *track = [[RQTrack alloc] init]; track.audioFileURL = [NSURL URLWithString:urlString]; self.urlString = urlString; _streamer = [DOUAudioStreamer streamerWithAudioFile:track]; [_streamer addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:kStatusKVOKey]; [_streamer addObserver:self forKeyPath:@"duration" options:NSKeyValueObservingOptionNew context:kDurationKVOKey]; [_streamer addObserver:self forKeyPath:@"bufferingRatio" options:NSKeyValueObservingOptionNew context:kBufferingRatioKVOKey]; [_streamer play]; [self rq_setupHintForStreamer]; } - (void)rq_resetStreamerWithURLString:(NSString *)urlString DOUAudioStreamerStatusBlock:(DOUAudioStreamerStatusBlock)audioStreamerStatusBlock { dispatch_async_on_main_queue(^{ _audioStreamerStatusBlock = nil; _audioStreamerStatusBlock = audioStreamerStatusBlock; [self rq_cancelStreamer]; RQTrack *track = [[RQTrack alloc] init]; track.audioFileURL = [NSURL URLWithString:urlString]; self.urlString = urlString; _streamer = [DOUAudioStreamer streamerWithAudioFile:track]; [_streamer addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:kStatusKVOKey]; [_streamer addObserver:self forKeyPath:@"duration" options:NSKeyValueObservingOptionNew context:kDurationKVOKey]; [_streamer addObserver:self forKeyPath:@"bufferingRatio" options:NSKeyValueObservingOptionNew context:kBufferingRatioKVOKey]; [_streamer play]; [self rq_setupHintForStreamer]; }); } - (void)rq_resetStreamerWithDOUAudioStreamerStatusBlock:(DOUAudioStreamerStatusBlock)audioStreamerStatusBlock { _audioStreamerStatusBlock = nil; _audioStreamerStatusBlock = audioStreamerStatusBlock; [self rq_resetStreamer]; } - (void)rq_setupHintForStreamer { [DOUAudioStreamer setHintWithAudioFile:self.audioTrack]; } - (void)_updateStatus { if (self.audioStreamerStatusBlock) { self.audioStreamerStatusBlock([_streamer status]); } switch ([_streamer status]) { case DOUAudioStreamerPlaying: break; case DOUAudioStreamerPaused: break; case DOUAudioStreamerIdle: break; case DOUAudioStreamerFinished: break; case DOUAudioStreamerBuffering: break; case DOUAudioStreamerError: NSLog(@"%@",@"DOUAudioStreamerError"); break; } } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (context == kStatusKVOKey) { [self performSelector:@selector(_updateStatus) onThread:[NSThread mainThread] withObject:nil waitUntilDone:NO]; } else if (context == kDurationKVOKey) { } else if (context == kBufferingRatioKVOKey) { } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } - (RQTrack *)audioTrack { if (!_audioTrack) { _audioTrack = [[RQTrack alloc] init]; } return _audioTrack; } @end