summaryrefslogtreecommitdiff
path: root/plugins/Utils.pas/playlist.pas
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-10-08 18:43:29 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-10-08 18:43:29 +0000
commit864081102a5f252415f41950b3039a896b4ae9c5 (patch)
treec6b764651e9dd1f8f53b98eab05f16ba4a492a79 /plugins/Utils.pas/playlist.pas
parentdb5149b48346c417e18add5702a9dfe7f6e28dd0 (diff)
Awkwars's plugins - welcome to our trunk
git-svn-id: http://svn.miranda-ng.org/main/trunk@1822 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/Utils.pas/playlist.pas')
-rw-r--r--plugins/Utils.pas/playlist.pas480
1 files changed, 480 insertions, 0 deletions
diff --git a/plugins/Utils.pas/playlist.pas b/plugins/Utils.pas/playlist.pas
new file mode 100644
index 0000000000..2ffe0143d6
--- /dev/null
+++ b/plugins/Utils.pas/playlist.pas
@@ -0,0 +1,480 @@
+{Playlist process}
+unit playlist;
+
+interface
+
+type
+ tPlaylist = class
+ private
+ fShuffle :boolean;
+ plSize :cardinal; // playlist entries
+ plCapacity:cardinal;
+ base :pWideChar;
+ name :pWideChar;
+ descr :pWideChar;
+ plStrings :array of PWideChar;
+ CurElement:cardinal;
+ PlOrder :array of cardinal;
+ CurOrder :cardinal;
+
+ procedure SetShuffle(value:boolean);
+ function GetShuffle:boolean;
+ procedure DoShuffle;
+
+ function GetTrackNumber:integer;
+ procedure SetTrackNumber(value:integer);
+
+ procedure AddLine(name,descr:pWideChar;new:boolean=true);
+ function ProcessElement(num:integer=-1):PWideChar; //virtual;
+
+ public
+ constructor Create(fname:pWideChar);
+ destructor Free;
+
+ procedure SetBasePath(path:pWideChar);
+
+ function GetSong(number:integer=-1):pWideChar;
+ function GetCount:integer;
+
+ function Next :pWideChar;
+ function Previous:pWideChar;
+
+ property Track :integer read GetTrackNumber write SetTrackNumber;
+ property Shuffle:boolean read GetShuffle write SetShuffle;
+ end;
+
+function isPlaylist(fname:pWideChar):integer;
+function CreatePlaylist(fname:pWideChar):tPlaylist;
+function CreatePlaylistBuf(buf:pointer;format:integer):tPlaylist;
+
+implementation
+
+uses windows, common, io, memini;//, m_api, mirutils;
+
+const
+ plSizeStart = 2048;
+ plSizeStep = 256;
+const
+ pltM3OLD = $100;
+ pltM3UTF = $200;
+
+type
+ tM3UPlaylist = class(tPlaylist)
+ private
+ public
+ constructor Create(fName:pWideChar);
+ constructor CreateBuf(buf:pointer);
+ end;
+
+ tPLSPlaylist = class(tPlaylist)
+ private
+ public
+ constructor Create(fname:pWideChar);
+ constructor CreateBuf(buf:pointer);
+ end;
+
+function isPlaylist(fname:pWideChar):integer;
+var
+ ext:array [0..7] of WideChar;
+begin
+ GetExt(fname,ext,7);
+ if StrCmpW(ext,'M3U',3)=0 then result:=1
+ else if StrCmpW(ext,'PLS' )=0 then result:=2
+ else result:=0;
+end;
+
+function CreatePlaylist(fname:pWideChar):tPlaylist;
+begin
+ case isPlaylist(fname) of
+ 1: result:=tM3UPlaylist.Create(fname);
+ 2: result:=tPLSPlaylist.Create(fname);
+ else result:=nil;
+ end;
+end;
+
+function CreatePlaylistBuf(buf:pointer;format:integer):tPlaylist;
+begin
+ case format of
+ 1: result:=tM3UPlaylist.CreateBuf(buf);
+ 2: result:=tPLSPlaylist.CreateBuf(buf);
+ else result:=nil;
+ end;
+end;
+
+//----- -----
+
+function SkipLine(var p:PWideChar):bool;
+begin
+ while p^>=' ' do inc(p);
+ while p^<=' ' do // Skip spaces too
+ begin
+ if p^=#0 then
+ begin
+ result:=false;
+ exit;
+ end;
+ p^:=#0;
+ inc(p);
+ end;
+ result:=true;
+end;
+
+constructor tM3UPlaylist.CreateBuf(buf:pointer);
+var
+ p:PAnsiChar;
+ pp,pd:pWideChar;
+ plBufW:pWideChar;
+ lname,ldescr:pWideChar;
+ finish:boolean;
+ pltNew:boolean;
+begin
+ inherited;
+
+ p:=buf;
+ if (pdword(p)^ and $00FFFFFF)=$00BFBBEF then
+ begin
+ inc(p,3);
+ UTF8ToWide(p,plBufW)
+ end
+ else
+ AnsiToWide(p,plBufW);
+
+ pp:=plBufW;
+ pltNew:=StrCmpW(pp,'#EXTM3U',7)=0;
+ if pltNew then SkipLine(pp);
+
+ ldescr:=nil;
+ finish:=false;
+ repeat
+ if pltNew then
+ begin
+ pd:=StrScanW(pp,',');
+ if pd<>nil then
+ begin
+ ldescr:=pd+1;
+ if not SkipLine(pp) then break;
+ end;
+ end;
+ lname:=pp;
+ finish:=SkipLine(pp);
+ AddLine(lname,ldescr);
+ until not finish;
+
+ mFreeMem(plBufW);
+end;
+
+constructor tM3UPlaylist.Create(fName:pWideChar);
+var
+ f:THANDLE;
+ i:integer;
+ plBuf:pAnsiChar;
+begin
+ f:=Reset(fName);
+
+ if f<>THANDLE(INVALID_HANDLE_VALUE) then
+ begin
+ i:=integer(FileSize(f));
+ if i=-1 then
+ i:=integer(GetFSize(fName));
+ if i<>-1 then
+ begin
+ mGetMem(plBuf,i+1);
+ BlockRead(f,plBuf^,i);
+ CloseHandle(f);
+ plBuf[i]:=#0;
+ CreateBuf(plBuf);
+ mFreeMem(plBuf);
+ end;
+ end;
+
+end;
+
+//----- -----
+
+constructor tPLSPlaylist.CreateBuf(buf:pointer);
+var
+ lname,ldescr:pWideChar;
+ section,storage,sectionlist:pointer;
+ ffile,ftitle:array [0..31] of AnsiChar;
+ f,t:pAnsiChar;
+ i,size:integer;
+begin
+ inherited;
+
+ storage:=OpenStorageBuf(buf);
+ if storage=nil then
+ exit;
+ sectionlist:=GetSectionList(storage);
+ section:=SearchSection(storage,sectionlist);
+ FreeSectionList(sectionlist);
+
+ size:=GetParamSectionInt(section,'NumberOfEntries');
+ f:=StrCopyE(ffile ,'File');
+ t:=StrCopyE(ftitle,'Title');
+ for i:=1 to size do
+ begin
+ IntToStr(f,i);
+ AnsiToWide(GetParamSectionStr(section,ffile),lname);
+
+ IntToStr(t,i);
+ AnsiToWide(GetParamSectionStr(section,ftitle),ldescr);
+
+ AddLine(lname,ldescr,false);
+ end;
+
+ CloseStorage(storage);
+end;
+
+constructor tPLSPlaylist.Create(fName:pWideChar);
+var
+ buf:pAnsiChar;
+ h:THANDLE;
+ size:integer;
+begin
+ if FileExists(fname) then
+ begin
+ h:=Reset(fname);
+ if h<>THANDLE(INVALID_HANDLE_VALUE) then
+ begin
+ size:=FileSize(h);
+ if size>0 then
+ begin
+ GetMem(buf,size+1);
+ BlockRead(h,buf^,size);
+ buf[size]:=#0;
+ CreateBuf(buf);
+ FreeMem(buf);
+ end;
+ CloseHandle(h);
+ end;
+ end;
+end;
+
+//----- -----
+
+constructor tPlaylist.Create(fName:pWideChar);
+begin
+// inherited;
+
+ CurElement:=0;
+ base:=nil;
+ name:=nil;
+ descr:=nil;
+ Shuffle:=false;
+ plSize:=0;
+
+ SetBasePath(fname);
+end;
+
+destructor tPlaylist.Free;
+var
+ i:integer;
+begin
+ PlOrder:=nil;
+
+ mFreeMem(base);
+ mFreeMem(name);
+ mFreeMem(descr);
+
+ for i:=0 to plSize-1 do
+ begin
+ mFreeMem(plStrings[i*2]);
+ mFreeMem(plStrings[i*2+1]);
+ end;
+ plStrings:=nil;
+
+// inherited;
+end;
+
+procedure tPlaylist.AddLine(name,descr:pWideChar;new:boolean=true);
+begin
+ if plCapacity=0 then
+ begin
+ plCapacity:=plSizeStart;
+ SetLength(plStrings,plSizeStart*2);
+ fillChar(plStrings[0],plSizeStart*2*SizeOf(pWideChar),0);
+ end
+ else if plSize=plCapacity then
+ begin
+ inc(plCapacity,plSizeStep);
+ SetLength(plStrings,plCapacity*2);
+ fillChar(plStrings[plSize],plSizeStep*2*SizeOf(pWideChar),0);
+ end;
+ if new then
+ begin
+ StrDupW(plStrings[plSize*2 ],name);
+ StrDupW(plStrings[plSize*2+1],descr);
+ end
+ else
+ begin
+ plStrings[plSize*2 ]:=name;
+ plStrings[plSize*2+1]:=descr;
+ end;
+ inc(plSize);
+end;
+
+procedure tPlaylist.SetBasePath(path:pWideChar);
+var
+ buf:array [0..MAX_PATH-1] of WideChar;
+ p,pp:pWideChar;
+begin
+ mFreeMem(base);
+
+ pp:=ExtractW(path,false);
+ p:=StrCopyEW(buf,pp);
+ mFreeMem(pp);
+
+ if ((p-1)^<>'\') and ((p-1)^<>'/') then
+ begin
+ if StrScanW(buf,'/')<>nil then
+ p^:='/'
+ else
+ p^:='\';
+ inc(p);
+ end;
+ p^:=#0;
+ StrDupW(base,buf);
+end;
+
+function tPlaylist.GetCount:integer;
+begin
+ result:=plSize;
+end;
+
+function tPlaylist.GetTrackNumber:integer;
+begin
+ if fShuffle then
+ result:=CurOrder
+ else
+ result:=CurElement;
+end;
+
+procedure tPlaylist.SetTrackNumber(value:integer);
+begin
+ if value<0 then
+ value:=0
+ else if value>=Integer(plSize) then
+ value:=plSize-1;
+
+ if fShuffle then
+ CurOrder:=value
+ else
+ CurElement:=value;
+end;
+
+function tPlaylist.ProcessElement(num:integer=-1):pWideChar;
+begin
+ if num<0 then
+ num:=Track
+ else if num>=integer(plSize) then
+ num:=plSize-1;
+ if fShuffle then
+ num:=PlOrder[num];
+
+ result:=plStrings[num*2];
+end;
+
+function tPlaylist.GetSong(number:integer=-1):PWideChar;
+var
+ buf:array [0..MAX_PATH-1] of WideChar;
+begin
+ result:=ProcessElement(number);
+
+ if (result<>nil) and not isPathAbsolute(result) and (base<>nil) then
+ begin
+ StrCopyW(StrCopyEW(buf,base),result);
+ StrDupW(result,buf);
+ end
+ else
+ StrDupW(result,result);
+end;
+
+procedure tPlaylist.SetShuffle(value:boolean);
+begin
+ if value then
+ begin
+// if not fShuffle then // need to set Shuffle
+ DoShuffle;
+ end;
+
+ fShuffle:=value;
+end;
+
+function tPlaylist.GetShuffle:boolean;
+begin
+ result:=fShuffle;
+end;
+
+procedure tPlaylist.DoShuffle;
+var
+ i,RandInx: cardinal;
+ SwapItem: cardinal;
+begin
+ SetLength(PlOrder,plSize);
+ Randomize;
+ for i:=0 to plSize-1 do
+ PlOrder[i]:=i;
+ if plSize>1 then
+ begin
+ for i:=0 to plSize-2 do
+ begin
+ RandInx:=cardinal(Random(plSize-i));
+ SwapItem:=PlOrder[i];
+ PlOrder[i ]:=PlOrder[RandInx];
+ PlOrder[RandInx]:=SwapItem;
+ end;
+ end;
+ CurOrder:=0;
+end;
+
+function tPlaylist.Next:PWideChar;
+begin
+ if plSize<>0 then
+ begin
+ if not Shuffle then
+ begin
+ inc(CurElement);
+ if CurElement=plSize then
+ CurElement:=0;
+ end
+ else // if mode=plShuffle then
+ begin
+ inc(CurOrder);
+ if CurOrder=plSize then
+ begin
+ DoShuffle;
+ CurOrder:=0;
+ end;
+ end;
+ result:=GetSong;
+ end
+ else
+ result:=nil;
+end;
+
+function tPlaylist.Previous:PWideChar;
+begin
+ if plSize<>0 then
+ begin
+ if not Shuffle then
+ begin
+ if CurElement=0 then
+ CurElement:=plSize;
+ Dec(CurElement);
+ end
+ else // if mode=plShuffle then
+ begin
+ if CurOrder=0 then
+ begin
+ DoShuffle;
+ CurOrder:=plSize;
+ end;
+ dec(CurOrder);
+ end;
+ result:=GetSong;
+ end
+ else
+ result:=nil;
+end;
+
+end.