℡风雨烟尘 发表于 2013-3-18 08:55:17

做了个播放器 求改进


共享链接:http://163.fm/U5hpzsk提取码:cIHPiixp
1.在歌单上无法实现点击播放只能右键快捷播放
2.不能实现自动下载歌词
求大牛改进源码

℡风雨烟尘 发表于 2013-3-18 08:57:18

是用delphi的

阿里呱呱 发表于 2013-3-27 14:03:12

下来学习学习!!!!!!

aminghanhua 发表于 2013-5-14 15:55:49

本帖最后由 aminghanhua 于 2013-5-14 16:13 编辑

procedure TForm1.Lv1DblClick(Sender: TObject);
begin
if Lv1.Items.Count <> 0 then
begin
   if Lv.ItemIndex <> -1 then
    begin
    form1.mp1.URL:=Lv1.Selected.Caption;
    form1.mp1.controls.play;
    end;
end;
end;unit lyric;//歌词显示单元
interface
uses Classes,SysUtils;
type
TOneLyric=Record
time:longint;
lyStr:string;
end;
TLyric=class
private
FFilename:string;
FOffset:integer; //时间补偿值 其单位是毫秒,正值表示整体提前,负值相反。这是用于总体调整显示快慢的。
FAur:string; //艺人名
FBy:string; //编者(指编辑LRC歌词的人)
FAl:string; //专辑名
FTi:string; //曲名
FCount:integer;
FLyricArray : array of TOneLyric;
function GetLyric(i:integer): TOneLyric ;
function ExistTime(vTime:longint):boolean;
procedure sortLyric;
procedure ResetLyrics(FTxt:Tstrings);
protected
public
constructor Create;
destructor Destroy; override;
procedure loadLyric(afilename:string);
procedure SetTxt(aLyrics:Tstrings);
procedure UnloadLyric(strs:Tstrings);
//整体提前(正值)或整体延后(负值)atime毫秒
function ChgOffset(atime:integer):boolean;
//提前(正值)/延后(负值)某一句歌词 aTime毫秒
function ChgOneLyric(oldTime:longint;aTime:integer):boolean;
//保存歌词内容到文件
function SaveLyricsToFile(vFileName:string):boolean;
property filename:string read ffilename;
property Ar:string read FAur;
property By:string read FBy;
property Al:string read FAl;
property Ti:string read FTi;
property Offset :integer read FOffset;
property LyricArray: TOneLyric read GetLyric ;
property Count:integer read FCount;
end;
implementation
constructor TLyric.Create;
begin
inherited Create;
FTi:='';
FAur:='';
Fal:='';
FBy:='';
FOffset:=0;
end;
function TLyric.ExistTime(vTime:longint):boolean;
var i:integer;
begin
result:=false;
for i:=0 to length(FLyricArray) -1 do
if FLyricArray.time =vTime then
begin
result:=true;
break;
end;
end;
procedure TLyric.loadLyric(afilename:string);
var
FTxt:Tstrings;
begin
FTi:='';
FAur:='';
Fal:='';
FBy:='';
FOffset:=0;
FFilename:=afilename;
//载入歌词
FTxt:=TStringlist.create;
FTxt.LoadFromFile(Ffilename);
ResetLyrics(FTxt);
FTxt.Clear;
FTxt.free;
end;
procedure TLyric.SetTxt(aLyrics:Tstrings);
begin
FTi:='';
FAur:='';
Fal:='';
FBy:='';
FOffset:=0;
//载入歌词
ResetLyrics(aLyrics);
end;
//根据歌词文件 载入每行歌词
procedure TLyric.ResetLyrics(FTxt:Tstrings);
var i:integer;
function makeOneLyric(CurLyric:string):string;
var p1,p2,p3:integer;
timestr,lyricstr:string;
time1,time2:longint;
isFuSign:boolean;
begin
p1:=pos('[',CurLyric);//第一个‘[’位置
if p1=0 then begin //判断是否非法行
result:= CurLyric; //无 '['
exit;
end;
p2:=pos(']',CurLyric); //第一个‘]’位置
if p2=0 then begin
result:= CurLyric;
exit; //无 ']'
end;
timestr:=copy(curLyric,p1+1,p2-p1-1);
//左右两边为歌词
lyricStr:= copy(curLyric,1,p1-1) + copy(curLyric,p2+1,length(curLyric)-p2) ;
lyricStr:=makeOneLyric(lyricStr);
if copy(Lowercase(timeStr),1,2)='ar' then //作者信息
FAur:= copy(timestr,4,length(timestr)-3)
else if copy(Lowercase(timeStr),1,2)='ti' then //曲目标题
FTi:= copy(timestr,4,length(timestr)-3)
else if copy(Lowercase(timeStr),1,2)='al' then //专辑名
FAl:= copy(timestr,4,length(timestr)-3)
else if copy(Lowercase(timeStr),1,2)='by' then //编辑LRC歌词的人
FBy:= copy(timestr,4,length(timestr)-3)
else if copy(Lowercase(timeStr),1,6)='offset' then //时间补偿值
try
FOffset:= strtoint(copy(timestr,8,length(timestr)-7))
except
FOffset:=0;
end
else //此时为 时间标记
begin
p3:= pos(':',timestr) ;
if p3>0 then begin //判断是否非法行
isFuSign:=false;
try
time1:=strtoint(copy(timestr,1,p3-1))*1000;
if time1<0 then
isFuSign:=true; //记录 该 时间标签 为 负(小于零)
except
//非法歌词行
exit; //分钟有误
end;
try
time2:= trunc( strtofloat(copy(timestr,p3+1,length(timestr)-p3)) *1000);
if isFuSign then
time2:=-time2;
except
exit; //秒 有误
end;
if not ExistTime(time1*60+time2) then
begin
setLength(FLyricArray,length(FLyricArray)+1);
//if trim(lyricStr)=' then
// lyricStr:= '(Music)';
with FLyricArray do
begin
time :=time1*60+time2;
lystr:=lyricStr;
end;
result:=lyricStr;
end;
end;
end;

end;
begin
SetLength(FLyricArray,0);

//解析歌词各部分
for i:= 0 to FTxt.count-1 do
begin
makeOneLyric(FTxt) ;
end;

FCount:=length(FLyricArray) ;
sortLyric;

{if FTi<>' then FTi:= replaceWithchr(FTi,'&','&&');
if FAur<>' then FAur:= replaceWithchr(FAur,'&','&&');
if FAl<>' then FAl:= replaceWithchr(FAl,'&','&&');
if FBy<>' then FBy:= replaceWithchr(FBy,'&','&&');
}
//根据 整体时间偏移,重新计算每句歌词时间
for i:=0 to length(FLyricArray)-1 do
begin
//FLyricArray.lyStr := replaceWithchr(FLyricArray.lyStr,'&','&&');

if FLyricArray.time >= 0 then
begin
if FLyricArray.time - FOffset>=0 then
FLyricArray.time:=FLyricArray.time - FOffset ;

end
else
FLyricArray.time:=0;
end;
end;

procedure TLyric.UnloadLyric(strs:Tstrings);
var i:integer;
begin
SetLength(FLyricArray,strs.Count );
FCount:= strs.Count;
for i:=0 to strs.Count -1 do
begin
FLyricArray.time :=0;
FLyricArray.lyStr := strs;
end;

FTi:='';
FAur:='';
Fal:='';
FBy:='';
FOffset:=0;

end;

destructor TLyric.Destroy;
begin
SetLength(FLyricArray,0);

inherited Destroy;
end;

function TLyric.GetLyric(i:integer): TOneLyric ;
begin
if (i>=0) and (i<length(FLyricArray)) then
result:=FLyricArray ;
end;

procedure TLyric.sortLyric;
var i,j:integer;
tmpLyric:TOneLyric;
begin
for i:=0 to length(FLyricArray)-2 do
begin
for j:=i to length(FLyricArray)-1 do
begin
if FLyricArray.time < FLyricArray.time then
begin
tmpLyric:= FLyricArray;
FLyricArray:= FLyricArray;
FLyricArray:= tmpLyric;
end;
end;
end;
end;

function TLyric.ChgOffset(atime:integer):boolean;//提前(正值)或延后(负值)atime毫秒
var i,numberLine:integer;
p1,p2,p3:integer;
timestr,lyricstr,CurLyric,signStr:string;
aOffset:longint;
afind:boolean;
FTxt:Tstrings;
begin
Result:=false;

//修改offset 保存文件
afind:=false;
aOffset:=0;
numberLine:=-1;

FTxt:=TStringlist.create;
try
FTxt.LoadFromFile(FFilename);

for i:=0 to FTxt.Count-1 do
begin
curLyric:=fTxt;

p1:=pos('[',CurLyric);//第一个‘[’位置
if p1=0 then begin //判断是否非法行
continue; //无 '['
end;
p2:=pos(']',CurLyric); //第一个‘]’位置
if p2=0 then begin
continue; //无 ']'
end;

timestr:=copy(curLyric,p1+1,p2-p1-1);
//左右两边为歌词
lyricStr:= copy(curLyric,1,p1-1) + copy(curLyric,p2+1,length(curLyric)-p2) ;

if copy(Lowercase(timeStr),1,6)='offset' then //找到 时间补偿串
begin
try
aOffset:= strtoint(copy(timestr,8,length(timestr)-7));
except
continue;
end ;
fTxt:=copy(curLyric,1,p1-1)
+''
+copy(curLyric,p2+1,length(curLyric)-p2);

if aOffset+aTime=0 then
FTxt.Delete(i);

fTxt.SaveToFile(FFilename);
afind:=true;
break;
end
else
begin
if numberLine=-1 then
begin
signStr:=copy(Lowercase(timeStr),1,2) ;
if (signStr<>'ar') and (signStr<>'al') and (signStr<>'ti') and (signStr<>'by') then begin
p3:= pos(':',timestr) ;
if p3>0 then //为时间标记
numberLine:=i; //记录行号
end;
end;
end;
end;

if (not afind) and (numberLine<>-1) then
begin
//fTxt.Add('');
fTxt.Insert(numberline, '');
fTxt.SaveToFile(FFilename);
end;

//重新载入歌词
loadLyric(FFilename);

result:=true;

FTxt.Clear;
finally
FTxt.free;
end;
end;

function TLyric.ChgOneLyric(oldTime:longint;aTime:integer):boolean;
var i:integer;
FTxt:Tstrings;
AjustOk:boolean;
thisLyric:string;

function AjustOneLine(var curLyric:string):boolean;
var
isFu:boolean;//该时间是否为负.

p1,p2,p3:integer;
timestr,left_lyric,right_lyric:string; //
time1,time2:longint;
findok:boolean;
isValid:boolean;//

NewTimeLabel:string;
NewTime:longint;

UseMS:boolean;
begin
//---------该串内 是否有标签 ----------
p1:=pos('[',CurLyric);//第一个‘[’位置
if p1=0 then begin //判断是否非法行
Result:=false; //无 '['
exit;
end;
p2:=pos(']',CurLyric); //第一个‘]’位置
if p2=0 then begin
result:= false;
exit; //无 ']'
end;
//==========串内 是否有标签==========

//----------目前标签 是否是 指定时间的 标签----------
timestr:=copy(curLyric,p1+1,p2-p1-1);

Left_lyric:= copy(curLyric,1,p1-1);
Right_lyric:= copy(curLyric,p2+1,length(curLyric)-p2) ;

isValid:=true;
findok:=false;
p3:= pos(':',timestr) ;
if p3>0 then begin //判断是否 合法时间标签
isFu:=false;
try
time1:=strtoint(copy(timestr,1,p3-1))*1000;
if time1<0 then
isFu:=true;
except
//非法歌词行
isValid:=false; //分钟有误
end;

try
if isValid then
begin
time2:= trunc( strtofloat(copy(timestr,p3+1,length(timestr)-p3)) *1000);
if isFu then
time2:=-time2;
end;
except
isValid:=false; //秒 有误
end;

if isValid and (time1*60+time2 - FOffset = oldtime) then //找到 指定时间串
findOk:=true; //找到 啦 啦 啦 ...

end; //非法行 判断结束
//==========是否找到 指定时间标签==========
//-------找到 和 没找到 之后的处理 ----------
if findok then begin
Result:= true;
//根据 老时间标签(timerstr)
//生成 新的时间标签
NewTime:=time1*60+time2 - aTime;
//根据 原来是否使用毫秒 和 目前调整的偏移时间是否属于毫秒级别
// 来决定 是否 使用毫秒
UseMS:= (Pos('.',timestr)>0) or (aTime mod 1000 <>0);
//转化时间为时间串例如: 72秒 ==>> '00:01:12.000'
NewTimeLabel:=ConvertTimeToTimestr(NewTime,0,false,true,UseMS,true);
//返回 新的歌词部分
curLyric := left_Lyric + '[' + NewTimeLabel + ']'+ Right_Lyric;
end
else //还 没找到
begin //在 该行歌词剩余部分 找找看
if AjustOneLine(Right_lyric) then
begin
//在剩余部分内找到了
curLyric:= Left_lyric+ '[' + timestr +']' +Right_lyric ;
Result:=true;
end
//else 剩余部分内 没有的话 ,只好返回 false 啦
// (函数开始处,已经默认=false)
end;
//=========找到 和 没找到 之后的处理==========
end; //end function AjustOneLine
begin
AjustOk:=false;
Result:=false;
FTxt:=TStringlist.create;
try
FTxt.LoadFromFile(FFilename);
for i:=0 to FTxt.Count-1 do
begin
thisLyric:=FTxt;
if AjustOneLine(thisLyric) then
begin
AjustOk:=true;
//更新 新生成 的歌词行
FTxt:=thisLyric;
break;
end;
end;
if AjustOk then
begin
//保存歌词文件
FTxt.SaveToFile(FFilename);
//重新载入歌词
loadLyric(FFilename);
Result:=true;
end;

FTxt.Clear;
finally
FTxt.free;
end;
end;
//保存歌词内容到文件
function TLyric.SaveLyricsToFile(vFileName:string):boolean;
var i:integer;
aTxt:Tstrings ;
begin
result:=false;
if FCount<=0 then exit;
aTxt:=Tstringlist.Create;
try
if FTi <>' then
aTxt.Add('歌名:'+FTi);
if FAur <>' then
aTxt.Add('歌手:'+FAur);
if Fal <>' then
aTxt.Add('专辑:'+Fal);
// if Fby <>' then
// lbxpreview.Items.Add('歌词编辑:'+Fby);
if aTxt.Count >0 then
aTxt.Add('--- --- --- --- --- --- ---');
for i:=0 to FCount-1 do
aTxt.Add(LyricArray.lyStr ) ;
aTxt.SaveToFile(vFilename);
Result:=true;
finally
aTxt.Free;
end;
end;
end.

℡风雨烟尘 发表于 2013-5-14 16:15:42

aminghanhua 发表于 2013-5-14 15:55 static/image/common/back.gif


多谢帮忙,学习了

aminghanhua 发表于 2013-5-14 16:22:25

从千千静听网站下载歌词的流程为:
1、根据歌手以及歌曲名称找歌词单列表
服务器地址为:
http://ttlrcct2.qianqian.com/dll/lyricsvr.dll?sh?Artist={0}&Title={1}&Flags=0
{0}为歌手名的UNICODE编码字符串
{1}为歌曲名的UNICODE编码字符串
注意
歌手名,歌曲名需要去空格、"'"、转换成小写等操作。
UNICODE编码时需要按字节转换为16进制,而不是按字符。

2、上面的操作获取到类似下面的xml结果。
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <lrc id="70437" artist="胡彦斌" title="男人 KTV"></lrc>
  <lrc id="204568" artist="胡彦斌" title="男人KTV"></lrc>
</result>
3、我们选择其中一个歌词进行下载。
根据选择歌词的ID,artist,title生成一个校验字符串(CODE)根据ID以及CODE去下面的地址获取歌词。
http://ttlrcct2.qianqian.com/dll/lyricsvr.dll?dl?Id={0}&Code={1}
{0}:ID
{1}:CODE

tlwangxd 发表于 2014-10-27 16:03:07

学习
页: [1]
查看完整版本: 做了个播放器 求改进