platform:ios,'8.0' target "GLMusicBox" do pod 'FreeStreamer', '~> 3.7.3' pod 'SDWebImage', '~> 4.0.0' pod 'MJRefresh', '~> 3.1.11' pod 'Masonry', '~> 1.0.2' pod 'Reachability', '~> 3.2' pod 'AFNetworking', '~> 3.0' pod 'IQKeyboardManager', '~> 3.3.2' end
#import "FSAudioStream.h"
@class GLMusicLRCModel;
typedef NS_ENUM(NSInteger,GLLoopState){
GLSingleLoop = 0,//单曲循环
GLForeverLoop,//重复循环
GLRandomLoop,//随机播放
GLOnceLoop//列表一次顺序播放
};
@protocol GLMusicPlayerDelegate/**
*
实时更新
*
**/
- (void)updateProgressWithCurrentPosition:(FSStreamPosition)currentPosition endPosition:(FSStreamPosition)endPosition;
- (void)updateMusicLrc;
@end
@interface GLMusicPlayer : FSAudioStream
/**
*
播放列表
*
**/
@property (nonatomic,strong) NSMutableArray *musicListArray;
/**
当前播放歌曲的歌词
*/
@property (nonatomic,strong) NSMutableArray *musicLRCArray;
/**
*
当前播放
*
**/
@property (nonatomic,assign,readonly) NSUInteger currentIndex;
/**
*
当前播放的音乐的标题
*
**/
@property (nonatomic,strong) NSString *currentTitle;
/**
是否是暂停状态
*/
@property (nonatomic,assign) BOOL isPause;
@property (nonatomic,weak) idglPlayerDelegate;
//默认 重复循环 GLForeverLoop
@property (nonatomic,assign) GLLoopState loopState;
/**
*
单例播放器
*
**/
+ (instancetype)defaultPlayer;
/**
播放队列中的指定的文件
@param index 序号
*/
- (void)playMusicAtIndex:(NSUInteger)index;
/**
播放前一首
*/
- (void)playFont;
/**
播放下一首
*/
- (void)playNext;
@end
+ (instancetype)defaultPlayer
{
static GLMusicPlayer *player = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
FSStreamConfiguration *config = [[FSStreamConfiguration alloc] init];
config.httpConnectionBufferSize *=2;
config.enableTimeAndPitchConversion = YES;
player = [[super alloc] initWithConfiguration:config];
player.delegate = (id)self;
player.onFailure = ^(FSAudioStreamError error, NSString *errorDescription) {
//播放错误
//有待解决
};
player.onCompletion = ^{
//播放完成
NSLog(@" 打印信息: 播放完成1");
};
player.onStateChange = ^(FSAudioStreamState state) {
switch (state) {
case kFsAudioStreamPlaying:
{
NSLog(@" 打印信息 playing.....");
player.isPause = NO;
[GLMiniMusicView shareInstance].palyButton.selected = YES;
}
break;
case kFsAudioStreamStopped:
{
NSLog(@" 打印信息 stop.....%@",player.url.absoluteString);
}
break;
case kFsAudioStreamPaused:
{
//pause
player.isPause = YES;
[GLMiniMusicView shareInstance].palyButton.selected = NO;
NSLog(@" 打印信息: pause");
}
break;
case kFsAudioStreamPlaybackCompleted:
{
NSLog(@" 打印信息: 播放完成2");
[player playMusicForState];
}
break;
default:
break;
}
};
//设置音量
[player setVolume:0.5];
//设置播放速率
[player setPlayRate:1];
player.loopState = GLForeverLoop;
});
return player;
}
- (void)playFromURL:(NSURL *)url
{
//根据地址 在本地找歌词
NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"musiclist" ofType:@"plist"]];
for (NSString *playStringKey in dic.allKeys) {
if ([[dic valueForKey:playStringKey] isEqualToString:url.absoluteString]) {
self.currentTitle = playStringKey;
break;
}
}
[self stop];
if (![url.absoluteString isEqualToString:self.url.absoluteString]) {
[super playFromURL:url];
}else{
[self play];
}
NSLog(@" 当前播放歌曲:%@",self.currentTitle);
[GLMiniMusicView shareInstance].titleLable.text = self.currentTitle;
//获取歌词
NSString *lrcFile = [NSString stringWithFormat:@"%@.lrc",self.currentTitle];
self.musicLRCArray = [NSMutableArray arrayWithArray:[GLMusicLRCModel musicLRCModelsWithLRCFileName:lrcFile]];
if (![self.musicListArray containsObject:url]) {
[self.musicListArray addObject:url];
}
//更新主界面歌词UI
if (self.glPlayerDelegate && [self.glPlayerDelegate respondsToSelector:@selector(updateMusicLrc)])
{
[self.glPlayerDelegate updateMusicLrc];
}
_currentIndex = [self.musicListArray indexOfObject:url];
if (!_progressTimer) {
_progressTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateProgress)];
[_progressTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}
}
if (!_progressTimer) {
_progressTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateProgress)];
[_progressTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}
- (void)updateProgress
{
if (self.glPlayerDelegate && [self.glPlayerDelegate respondsToSelector:@selector(updateProgressWithCurrentPosition:endPosition:)])
{
[self.glPlayerDelegate updateProgressWithCurrentPosition:self.currentTimePlayed endPosition:self.duration];
}
[self showLockScreenCurrentTime:(self.currentTimePlayed.second + self.currentTimePlayed.minute * 60) totalTime:(self.duration.second + self.duration.minute * 60)];
}
typedef struct {
unsigned minute;
unsigned second;
/**
* Playback time in seconds.
*/
float playbackTimeInSeconds;
/**
* Position within the stream, where 0 is the beginning
* and 1.0 is the end.
*/
float position;
} FSStreamPosition;
#pragma mark == GLMusicPlayerDelegate
- (void)updateProgressWithCurrentPosition:(FSStreamPosition)currentPosition endPosition:(FSStreamPosition)endPosition
{
//更新进度条
self.playerControlView.slider.value = currentPosition.position;
self.playerControlView.leftTimeLable.text = [NSString translationWithMinutes:currentPosition.minute seconds:currentPosition.second];
self.playerControlView.rightTimeLable.text = [NSString translationWithMinutes:endPosition.minute seconds:endPosition.second];
//更新歌词
[self updateMusicLrcForRowWithCurrentTime:currentPosition.position *(endPosition.minute *60 + endPosition.second)];
self.playerControlView.palyMusicButton.selected = [GLMusicPlayer defaultPlayer].isPause;
}
@interface GLSlider : UIControl
//进度条颜色
@property (nonatomic,strong) UIColor *progressColor;
//缓存条颜色
@property (nonatomic,strong) UIColor *progressCacheColor;
//滑块颜色
@property (nonatomic,strong) UIColor *thumbColor;
//设置进度值 0-1
@property (nonatomic,assign) CGFloat value;
//设置缓存进度值 0-1
@property (nonatomic,assign) CGFloat cacheValue;
@end
static CGFloat const kProgressHeight = 2;
static CGFloat const kProgressLeftPadding = 2;
static CGFloat const kThumbHeight = 16;
@interface GLSlider()
//滑块 默认
@property (nonatomic,strong) CALayer *thumbLayer;
//进度条
@property (nonatomic,strong) CALayer *progressLayer;
//缓存进度条
@property (nonatomic,strong) CALayer *progressCacheLayer;
@property (nonatomic,assign) BOOL isTouch;
@end
@implementation GLSlider
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self addSubLayers];
}
return self;
}
....
@interface GLMusicLrcLable : UILabel //进度 @property (nonatomic,assign) CGFloat progress; @end
#import "GLMusicLrcLable.h"
@implementation GLMusicLrcLable
- (void)setProgress:(CGFloat)progress
{
_progress = progress;
//重绘
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
CGRect fillRect = CGRectMake(0, 0, self.bounds.size.width * _progress, self.bounds.size.height);
[UICOLOR_FROM_RGB(45, 185, 105) set];
UIRectFillUsingBlendMode(fillRect, kCGBlendModeSourceIn);
}
@end
//设置当前行的状态
[currentCell reloadCellForSelect:YES];
//取消上一行的选中状态
[previousCell reloadCellForSelect:NO];
- (void)reloadCellForSelect:(BOOL)select
{
if (select) {
_lrcLable.font = [UIFont systemFontOfSize:17];
}else{
_lrcLable.font = [UIFont systemFontOfSize:14];
_lrcLable.progress = 0;
}
}
[ti:老人与海] [ar:海鸣威 ] [al:单曲] [by:www.5nd.com From 那时花开] [00:04.08]老人与海 海鸣威 [00:08.78]海鸣威 [00:37.06]秋天的夜凋零在漫天落叶里面 [00:42.43]泛黄世界一点一点随风而渐远 [00:47.58]冬天的雪白色了你我的情人节 [00:53.24]消失不见 爱的碎片 [00:57.87]Rap: [00:59.32]翻开尘封的相片 [01:00.87]想起和你看过 的那些老旧默片 [01:02.50]老人与海的情节 [01:04.23]画面中你却依稀 在浮现
#import @interface GLMusicLRCModel : NSObject //该段歌词对应的时间 @property (nonatomic,assign) NSTimeInterval time; //歌词 @property (nonatomic,strong) NSString *title; /** * 将特点的歌词格式进行转换 * **/ + (id)musicLRCWithString:(NSString *)string; /** * 根据歌词的路径返回歌词模型数组 * **/ + (NSArray *)musicLRCModelsWithLRCFileName:(NSString *)name; @end
#import "GLMusicLRCModel.h"
@implementation GLMusicLRCModel
+(id)musicLRCWithString:(NSString *)string
{
GLMusicLRCModel *model = [[GLMusicLRCModel alloc] init];
NSArray *lrcLines =[string componentsSeparatedByString:@"]"];
if (lrcLines.count == 2) {
model.title = lrcLines[1];
NSString *timeString = lrcLines[0];
timeString = [timeString stringByReplacingOccurrencesOfString:@"[" withString:@""];
timeString = [timeString stringByReplacingOccurrencesOfString:@"]" withString:@""];
NSArray *times = [timeString componentsSeparatedByString:@":"];
if (times.count == 2) {
NSTimeInterval time = [times[0] integerValue]*60 + [times[1] floatValue];
model.time = time;
}
}else if(lrcLines.count == 1){
}
return model;
}
+(NSArray *)musicLRCModelsWithLRCFileName:(NSString *)name
{
NSString *lrcPath = [[NSBundle mainBundle] pathForResource:name ofType:nil];
NSString *lrcString = [NSString stringWithContentsOfFile:lrcPath encoding:NSUTF8StringEncoding error:nil];
NSArray *lrcLines = [lrcString componentsSeparatedByString:@"\n"];
NSMutableArray *lrcModels = [NSMutableArray array];
for (NSString *lrcLineString in lrcLines) {
if ([lrcLineString hasPrefix:@"[ti"] || [lrcLineString hasPrefix:@"[ar"] || [lrcLineString hasPrefix:@"[al"] || ![lrcLineString hasPrefix:@"["]) {
continue;
}
GLMusicLRCModel *lrcModel = [GLMusicLRCModel musicLRCWithString:lrcLineString];
[lrcModels addObject:lrcModel];
}
return lrcModels;
}
@end
#pragma mark == UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [GLMusicPlayer defaultPlayer].musicLRCArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MusicLRCTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"musicLrc" forIndexPath:indexPath];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.backgroundColor = [UIColor clearColor];
cell.contentView.backgroundColor = [UIColor clearColor];
cell.lrcModel = [GLMusicPlayer defaultPlayer].musicLRCArray[indexPath.row];
if (indexPath.row == self.currentLcrIndex) {
[cell reloadCellForSelect:YES];
}else{
[cell reloadCellForSelect:NO];
}
return cell;
}
//逐行更新歌词
- (void)updateMusicLrcForRowWithCurrentTime:(NSTimeInterval)currentTime
{
for (int i = 0; i < [GLMusicPlayer defaultPlayer].musicLRCArray.count; i ++) {
GLMusicLRCModel *model = [GLMusicPlayer defaultPlayer].musicLRCArray[i];
NSInteger next = i + 1;
GLMusicLRCModel *nextLrcModel = nil;
if (next < [GLMusicPlayer defaultPlayer].musicLRCArray.count) {
nextLrcModel = [GLMusicPlayer defaultPlayer].musicLRCArray[next];
}
if (self.currentLcrIndex != i && currentTime >= model.time)
{
BOOL show = NO;
if (nextLrcModel) {
if (currentTime < nextLrcModel.time) {
show = YES;
}
}else{
show = YES;
}
if (show) {
NSIndexPath *currentIndexPath = [NSIndexPath indexPathForRow:i inSection:0];
NSIndexPath *previousIndexPath = [NSIndexPath indexPathForRow:self.currentLcrIndex inSection:0];
self.currentLcrIndex = i;
MusicLRCTableViewCell *currentCell = [self.lrcTableView cellForRowAtIndexPath:currentIndexPath];
MusicLRCTableViewCell *previousCell = [self.lrcTableView cellForRowAtIndexPath:previousIndexPath];
//设置当前行的状态
[currentCell reloadCellForSelect:YES];
//取消上一行的选中状态
[previousCell reloadCellForSelect:NO];
if (!self.isDrag) {
[self.lrcTableView scrollToRowAtIndexPath:currentIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
}
}
}
if (self.currentLcrIndex == i) {
MusicLRCTableViewCell *cell = [self.lrcTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
CGFloat totalTime = 0;
if (nextLrcModel) {
totalTime = nextLrcModel.time - model.time;
}else{
totalTime = [GLMusicPlayer defaultPlayer].duration.minute * 60 + [GLMusicPlayer defaultPlayer].duration.second - model.time;
}
CGFloat progressTime = currentTime - model.time;
cell.lrcLable.progress = progressTime / totalTime;
}
}
}
typedef NS_ENUM(NSInteger,GLLoopState){
GLSingleLoop = 0,//单曲循环
GLForeverLoop,//重复循环
GLRandomLoop,//随机播放
GLOnceLoop//列表一次顺序播放
};
//不同状态下 播放歌曲
- (void)playMusicForState
{
switch (self.loopState) {
case GLSingleLoop:
{
[self playMusicAtIndex:self.currentIndex];
}
break;
case GLForeverLoop:
{
if (self.currentIndex == self.musicListArray.count-1) {
[self playMusicAtIndex:0];
}else{
[self playMusicAtIndex:self.currentIndex + 1];
}
}
break;
case GLRandomLoop:
{
//取随机值
int index = arc4random() % self.musicListArray.count;
[self playMusicAtIndex:index];
}
break;
case GLOnceLoop:
{
if (self.currentIndex == self.musicListArray.count-1) {
[self stop];
}else{
[self playMusicAtIndex:self.currentIndex + 1];
}
}
break;
default:
break;
}
}
AVAudioSession *session = [AVAudioSession sharedInstance]; // [session setActive:YES error:nil]; [session setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil]; [session setCategory:AVAudioSessionCategoryPlayback error:nil]; [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
#pragma mark == event response
-(void)remoteControlReceivedWithEvent:(UIEvent *)event{
NSLog(@"%ld",event.subtype);
if (event.type == UIEventTypeRemoteControl) {
switch (event.subtype) {
case UIEventSubtypeRemoteControlPlay:
{
//点击播放按钮或者耳机线控中间那个按钮
[[GLMusicPlayer defaultPlayer] pause];
}
break;
case UIEventSubtypeRemoteControlPause:
{
//点击暂停按钮
[[GLMusicPlayer defaultPlayer] pause];
}
break;
case UIEventSubtypeRemoteControlStop :
{
//点击停止按钮
[[GLMusicPlayer defaultPlayer] stop];
}
break;
case UIEventSubtypeRemoteControlTogglePlayPause:
{
//点击播放与暂停开关按钮(iphone抽屉中使用这个)
[[GLMusicPlayer defaultPlayer] pause];
}
break;
case UIEventSubtypeRemoteControlNextTrack:
{
//点击下一曲按钮或者耳机中间按钮两下
[[GLMusicPlayer defaultPlayer] playNext];
}
break;
case UIEventSubtypeRemoteControlPreviousTrack:
{
//点击上一曲按钮或者耳机中间按钮三下
[[GLMusicPlayer defaultPlayer] playFont];
}
break;
case UIEventSubtypeRemoteControlBeginSeekingBackward:
{
//快退开始 点击耳机中间按钮三下不放开
}
break;
case UIEventSubtypeRemoteControlEndSeekingBackward:
{
//快退结束 耳机快退控制松开后
}
break;
case UIEventSubtypeRemoteControlBeginSeekingForward:
{
//开始快进 耳机中间按钮两下不放开
}
break;
case UIEventSubtypeRemoteControlEndSeekingForward:
{
//快进结束 耳机快进操作松开后
}
break;
default:
break;
}
}
}
NSMutableDictionary *musicInfoDict = [[NSMutableDictionary alloc] init];
//设置歌曲题目
[musicInfoDict setObject:self.currentTitle forKey:MPMediaItemPropertyTitle];
//设置歌手名
[musicInfoDict setObject:@"" forKey:MPMediaItemPropertyArtist];
//设置专辑名
[musicInfoDict setObject:@"" forKey:MPMediaItemPropertyAlbumTitle];
//设置歌曲时长
[musicInfoDict setObject:[NSNumber numberWithFloat:totalTime]
forKey:MPMediaItemPropertyPlaybackDuration];
//设置已经播放时长
[musicInfoDict setObject:[NSNumber numberWithFloat:currentTime]
forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime];
[[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:musicInfoDict];
//监听锁屏状态 lock=1则为锁屏状态
uint64_t locked;
__block int token = 0;
notify_register_dispatch("com.apple.springboard.lockstate",&token,dispatch_get_main_queue(),^(int t){
});
notify_get_state(token, &locked);
//监听屏幕点亮状态 screenLight = 1则为变暗关闭状态
uint64_t screenLight;
__block int lightToken = 0;
notify_register_dispatch("com.apple.springboard.hasBlankedScreen",&lightToken,dispatch_get_main_queue(),^(int t){
});
notify_get_state(lightToken, &screenLight);
- (void)playFromURL:(NSURL *)url
{
//根据地址 在本地找歌词
NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"musiclist" ofType:@"plist"]];
for (NSString *playStringKey in dic.allKeys) {
if ([[dic valueForKey:playStringKey] isEqualToString:url.absoluteString]) {
self.currentTitle = playStringKey;
break;
}
}
[self stop];
if (![url.absoluteString isEqualToString:self.url.absoluteString]) {
[super playFromURL:url];
}else{
[self play];
}
- (void)suspentFM {
if (self.isSuspendFM==YES) return;
if (self.Buffering ==YES) {
[_audioStream stop];
}else {
[_audioStream pause];
}
self.isSuspendFM = YES;
_suspentBtn.hidden = NO;
}
if ( progressView.progress<0.007) {
self.Buffering = YES;
}else {
self.Buffering = NO;
}
FSStreamPosition cur = self.audioStream.currentTimePlayed;
self.playbackTime =cur.playbackTimeInSeconds/1;
self.ProgressView.progress = cur.position;//播放进度
self.progress = cur.position;
float prebuffer = (float)self.audioStream.prebufferedByteCount;
float contentlength = (float)self.audioStream.contentLength;
if (contentlength>0) {
self.ProgressView.cacheProgress = prebuffer /contentlength;//缓存进度
}
机械节能产品生产企业官网模板...
大气智能家居家具装修装饰类企业通用网站模板...
礼品公司网站模板
宽屏简约大气婚纱摄影影楼模板...
蓝白WAP手机综合医院类整站源码(独立后台)...苏ICP备2024110244号-2 苏公网安备32050702011978号 增值电信业务经营许可证编号:苏B2-20251499 | Copyright 2018 - 2025 源码网商城 (www.ymwmall.com) 版权所有