unit id3; interface uses classes,sysutils; const MaxID3Genre=147; ID3Genre: array[0..MaxID3Genre] of string = ( 'Blues', 'Classic Rock', 'Country', 'Dance', 'Disco', 'Funk', 'Grunge', 'Hip-Hop', 'Jazz', 'Metal', 'New Age', 'Oldies', 'Other', 'Pop', 'R&B', 'Rap', 'Reggae', 'Rock', 'Techno', 'Industrial', 'Alternative', 'Ska', 'Death Metal', 'Pranks', 'Soundtrack', 'Euro-Techno', 'Ambient', 'Trip-Hop', 'Vocal', 'Jazz+Funk', 'Fusion', 'Trance', 'Classical', 'Instrumental', 'Acid', 'House', 'Game', 'Sound Clip', 'Gospel', 'Noise', 'AlternRock', 'Bass', 'Soul', 'Punk', 'Space', 'Meditative', 'Instrumental Pop', 'Instrumental Rock', 'Ethnic', 'Gothic', 'Darkwave', 'Techno-Industrial', 'Electronic', 'Pop-Folk', 'Eurodance', 'Dream', 'Southern Rock', 'Comedy', 'Cult', 'Gangsta', 'Top 40', 'Christian Rap', 'Pop/Funk', 'Jungle', 'Native American', 'Cabaret', 'New Wave', 'Psychadelic', 'Rave', 'Showtunes', 'Trailer', 'Lo-Fi', 'Tribal', 'Acid Punk', 'Acid Jazz', 'Polka', 'Retro', 'Musical', 'Rock & Roll', 'Hard Rock', 'Folk', 'Folk-Rock', 'National Folk', 'Swing', 'Fast Fusion', 'Bebob', 'Latin', 'Revival', 'Celtic', 'Bluegrass', 'Avantgarde', 'Gothic Rock', 'Progressive Rock', 'Psychedelic Rock', 'Symphonic Rock', 'Slow Rock', 'Big Band', 'Chorus', 'Easy Listening', 'Acoustic', 'Humour', 'Speech', 'Chanson', 'Opera', 'Chamber Music', 'Sonata', 'Symphony', 'Booty Bass', 'Primus', 'Porn Groove', 'Satire', 'Slow Jam', 'Club', 'Tango', 'Samba', 'Folklore', 'Ballad', 'Power Ballad', 'Rhythmic Soul', 'Freestyle', 'Duet', 'Punk Rock', 'Drum Solo', 'Acapella', 'Euro-House', 'Dance Hall', 'Goa', 'Drum & Bass', 'Club-House', 'Hardcore', 'Terror', 'Indie', 'BritPop', 'Negerpunk', 'Polsk Punk', 'Beat', 'Christian Gangsta Rap', 'Heavy Metal', 'Black Metal', 'Crossover', 'Contemporary Christian', 'Christian Rock', 'Merengue', 'Salsa', 'Trash Metal', 'Anime', 'Jpop', 'Synthpop' {and probably more to come} ); type tid3tag = record field : string; track : string; artist : string; album : string; year : string; comments : string; genre : string; trackno : integer; end; function readtag(fn : string) : tid3tag; function writetag(fn : string;tag : tid3tag) : boolean; function readversion2tag(fn : string) : tid3tag; implementation procedure makesize(s : string; l : integer); begin if length(s)<l then begin while(length(s)<l) do begin s:=s+#0; end; end; if length(s)>l then s:=copy(s,1,l); end; function checkvalidtag(f : tfilestream) : boolean; var tag : array [0..3] of char; begin f.Seek(f.size-128,soFromBeginning); f.read(tag,3); if uppercase(tag)<>'TAG' then result:=false else result:=true; end; function readtag(fn : string) : tid3tag; var readbytes : integer; f : tfilestream; pc : array[0..255] of char; begin fillchar(result,sizeof(tid3tag),0); result.field:=''; try if fileexists(fn)=false then exit; f:= tfilestream.Create(fn,fmOpenRead or fmShareDenyNone ); except exit; end; if checkvalidtag(f)=false then begin; f.free; result:=readversion2tag(fn); exit; end; f.Seek(f.size-128,soFromBeginning); fillchar(pc,255,0); readbytes:=f.read(pc,3); if readbytes<>3 then begin;f.free;exit;end;; result.field:=pc; fillchar(pc,255,0); readbytes:=f.read(pc,30); if readbytes<>30 then begin;f.free;exit;end;; result.track:=''; result.track:=pc; fillchar(pc,255,0); readbytes:=f.read(pc,30); if readbytes<>30 then begin;f.free;exit;end;; result.artist:=''; result.artist:=pc; fillchar(pc,255,0); readbytes:=f.read(pc,30); if readbytes<>30 then begin;f.free;exit;end;; result.album:=''; result.album:=pc; fillchar(pc,255,0); readbytes:=f.read(pc,4); if readbytes<>4 then begin;f.free;exit;end;; result.year:=pc; fillchar(pc,255,0); readbytes:=f.read(pc,30); if readbytes<>30 then begin;f.free;exit;end; result.trackno:=ord(pc[29]); result.comments:=pc; fillchar(pc,255,0); readbytes:=f.read(pc,1); if readbytes<>1 then begin;f.free;exit;end;; if (pc='') then result.genre:='Unclassified' else if ord(pc[0])<MaxID3Genre then result.genre:=ID3Genre[ord(pc[0])]; f.free; end; function writetag(fn : string;tag : tid3tag) : boolean; var f : tfilestream; written : integer; pc : array[0..255] of char; begin result:=false; try f:= tfilestream.Create(fn,fmOpenReadWrite); except exit; end; if checkvalidtag(f)=false then f.Seek(f.size,soFromBeginning) else f.Seek(f.size-128,soFromBeginning); makesize(tag.field,3); makesize(tag.track,30); makesize(tag.artist,30); makesize(tag.album,30); makesize(tag.year,4); makesize(tag.comments,30); makesize(tag.genre,1); strpcopy(pc,tag.field); written:=f.Write(pc,3); if written<>3 then begin;f.free;exit;end;; strpcopy(pc,tag.track); written:=f.Write(pc,30); if written<>30 then begin;f.free;exit;end;; strpcopy(pc,tag.artist); written:=f.write(pc,30); if written<>30 then begin;f.free;exit;end;; strpcopy(pc,tag.album); written:=f.write(pc,30); if written<>30 then begin;f.free;exit;end;; strpcopy(pc,tag.year); written:=f.write(pc,4); if written<>4 then begin;f.free;exit;end;; strpcopy(pc,tag.comments); written:=f.write(pc,30); if written<>30 then begin;f.free;exit;end;; strpcopy(pc,tag.genre); written:=f.write(pc,1); if written<>1 then begin;f.free;exit;end;; result:=true; f.free; end; function readversion2tag(fn : string) : tid3tag; var f : tfilestream; ms : tmemorystream; sr : string; scrap : integer; p : longint; sz : longint; z : string; function readframe(tag : string) : string; begin p:=pos(tag,sr); if p>0 then begin z:=copy(sr,p+length(tag),4); z:=inttostr(ord(z[1]))+inttostr(ord(z[2]))+inttostr(ord(z[3]))+inttostr(ord(z[4])); sz:=strtoint(z); result:=copy(sr,p+length(tag)+6,sz); end; end; begin try f:=tfilestream.Create(fn,fmOpenRead or fmShareDenyNone ); except exit; end; ms:=tmemorystream.Create; ms.LoadFromStream(f); setlength(sr,ms.size+1); ms.Seek(0,soFromBeginning); ms.read(sr[1],ms.size-1); ms.free; f.free; if pos('ID3',sr)=0 then begin setlength(sr,0); exit; end; result.track:=trim(readframe('TIT2')); result.artist:=trim(readframe('TPE1')); try result.album:=trim(readframe('TALB')); val(readframe('TRCK'),result.trackno,scrap); except end; result.year:=''; try result.year:=trim(readframe('TYER')); except end; result.genre:=trim(readframe('TCON')); setlength(sr,0); end; end.