Mega Code Archive

 
Categories / Delphi / Multimedia
 

Notilus - tid3v1

// < Görkem SARI > // < notilus_hack@hotmail.com > { *************************************************************************** } { } { Audio Tools Library (Freeware) } { Class TID3v1 - for manipulating with ID3v1 tags } { } { Copyright (c) 2001 by Jurgen Faul } { E-mail: jfaul@gmx.de } { http://jfaul.de/atl } { } { Version 1.0 (25 July 2001) } { - Full support for ID3v1.0 & ID3v1.1 tags (read/write) } { } { *************************************************************************** } unit ID3v1; interface uses Classes, SysUtils; const MAX_MUSIC_GENRES = 148; { Max. number of music genres } DEFAULT_GENRE = 255; { Index for default genre } { Used with VersionID property } TAG_VERSION_1_0 = 1; { Index for ID3v1.0 tag } TAG_VERSION_1_1 = 2; { Index for ID3v1.1 tag } var MusicGenre: array [0..MAX_MUSIC_GENRES - 1] of string; { Genre names } type { Used in TID3v1 class } String04 = string[4]; { String with max. 4 symbols } String30 = string[30]; { String with max. 30 symbols } { Class TID3v1 } TID3v1 = class(TObject) private { Private declarations } FExists: Boolean; FVersionID: Byte; FTitle: String30; FArtist: String30; FAlbum: String30; FYear: String04; FComment: String30; FTrack: Byte; FGenreID: Byte; procedure FSetTitle(const NewTitle: String30); procedure FSetArtist(const NewArtist: String30); procedure FSetAlbum(const NewAlbum: String30); procedure FSetYear(const NewYear: String04); procedure FSetComment(const NewComment: String30); procedure FSetTrack(const NewTrack: Byte); procedure FSetGenreID(const NewGenreID: Byte); function FGetGenre: string; public { Public declarations } constructor Create; { Create object } procedure ResetData; { Reset all data } function ReadFromFile(const FileName: string): Boolean; { Load tag } function RemoveFromFile(const FileName: string): Boolean; { Delete tag } function SaveToFile(const FileName: string): Boolean; { Save tag } property Exists: Boolean read FExists; { True if tag found } property VersionID: Byte read FVersionID; { Version code } property Title: String30 read FTitle write FSetTitle; { Song title } property Artist: String30 read FArtist write FSetArtist; { Artist name } property Album: String30 read FAlbum write FSetAlbum; { Album name } property Year: String04 read FYear write FSetYear; { Year } property Comment: String30 read FComment write FSetComment; { Comment } property Track: Byte read FTrack write FSetTrack; { Track number } property GenreID: Byte read FGenreID write FSetGenreID; { Genre code } property Genre: string read FGetGenre; { Genre name } end; implementation type { Real structure of ID3v1 tag } TagRecord = record Header: array [1..3] of Char; { Tag header - must be "TAG" } Title: array [1..30] of Char; { Title data } Artist: array [1..30] of Char; { Artist data } Album: array [1..30] of Char; { Album data } Year: array [1..4] of Char; { Year data } Comment: array [1..30] of Char; { Comment data } Genre: Byte; { Genre data } end; { ********************* Auxiliary functions & procedures ******************** } function ReadTag(const FileName: string; var TagData: TagRecord): Boolean; var SourceFile: file; begin try Result := true; { Set read-access and open file } AssignFile(SourceFile, FileName); FileMode := 0; Reset(SourceFile, 1); { Read tag } Seek(SourceFile, FileSize(SourceFile) - 128); BlockRead(SourceFile, TagData, 128); CloseFile(SourceFile); except { Error } Result := false; end; end; { --------------------------------------------------------------------------- } function RemoveTag(const FileName: string): Boolean; var SourceFile: file; begin try Result := true; { Allow write-access and open file } FileSetAttr(FileName, 0); AssignFile(SourceFile, FileName); FileMode := 2; Reset(SourceFile, 1); { Delete tag } Seek(SourceFile, FileSize(SourceFile) - 128); Truncate(SourceFile); CloseFile(SourceFile); except { Error } Result := false; end; end; { --------------------------------------------------------------------------- } function SaveTag(const FileName: string; TagData: TagRecord): Boolean; var SourceFile: file; begin try Result := true; { Allow write-access and open file } FileSetAttr(FileName, 0); AssignFile(SourceFile, FileName); FileMode := 2; Reset(SourceFile, 1); { Write tag } Seek(SourceFile, FileSize(SourceFile)); BlockWrite(SourceFile, TagData, SizeOf(TagData)); CloseFile(SourceFile); except { Error } Result := false; end; end; { --------------------------------------------------------------------------- } function GetTagVersion(const TagData: TagRecord): Byte; begin Result := TAG_VERSION_1_0; { Terms for ID3v1.1 } if ((TagData.Comment[29] = #0) and (TagData.Comment[30] <> #0)) or ((TagData.Comment[29] = #32) and (TagData.Comment[30] <> #32)) then Result := TAG_VERSION_1_1; end; { ********************** Private functions & procedures ********************* } procedure TID3v1.FSetTitle(const NewTitle: String30); begin FTitle := TrimRight(NewTitle); end; { --------------------------------------------------------------------------- } procedure TID3v1.FSetArtist(const NewArtist: String30); begin FArtist := TrimRight(NewArtist); end; { --------------------------------------------------------------------------- } procedure TID3v1.FSetAlbum(const NewAlbum: String30); begin FAlbum := TrimRight(NewAlbum); end; { --------------------------------------------------------------------------- } procedure TID3v1.FSetYear(const NewYear: String04); begin FYear := TrimRight(NewYear); end; { --------------------------------------------------------------------------- } procedure TID3v1.FSetComment(const NewComment: String30); begin FComment := TrimRight(NewComment); end; { --------------------------------------------------------------------------- } procedure TID3v1.FSetTrack(const NewTrack: Byte); begin FTrack := NewTrack; end; { --------------------------------------------------------------------------- } procedure TID3v1.FSetGenreID(const NewGenreID: Byte); begin FGenreID := NewGenreID; end; { --------------------------------------------------------------------------- } function TID3v1.FGetGenre: string; begin Result := ''; { Return an empty string if the current GenreID is not valid } if FGenreID in [0..MAX_MUSIC_GENRES - 1] then Result := MusicGenre[FGenreID]; end; { ********************** Public functions & procedures ********************** } constructor TID3v1.Create; begin inherited; ResetData; end; { --------------------------------------------------------------------------- } procedure TID3v1.ResetData; begin FExists := false; FVersionID := TAG_VERSION_1_0; FTitle := ''; FArtist := ''; FAlbum := ''; FYear := ''; FComment := ''; FTrack := 0; FGenreID := DEFAULT_GENRE; end; { --------------------------------------------------------------------------- } function TID3v1.ReadFromFile(const FileName: string): Boolean; var TagData: TagRecord; begin { Reset and load tag data from file to variable } ResetData; Result := ReadTag(FileName, TagData); { Process data if loaded and tag header OK } if (Result) and (TagData.Header = 'TAG') then begin FExists := true; FVersionID := GetTagVersion(TagData); { Fill properties with tag data } FTitle := TrimRight(TagData.Title); FArtist := TrimRight(TagData.Artist); FAlbum := TrimRight(TagData.Album); FYear := TrimRight(TagData.Year); if FVersionID = TAG_VERSION_1_0 then FComment := TrimRight(TagData.Comment) else begin FComment := TrimRight(Copy(TagData.Comment, 1, 28)); FTrack := Ord(TagData.Comment[30]); end; FGenreID := TagData.Genre; end; end; { --------------------------------------------------------------------------- } function TID3v1.RemoveFromFile(const FileName: string): Boolean; var TagData: TagRecord; begin { Find tag } Result := ReadTag(FileName, TagData); { Delete tag if loaded and tag header OK } if (Result) and (TagData.Header = 'TAG') then Result := RemoveTag(FileName); end; { --------------------------------------------------------------------------- } function TID3v1.SaveToFile(const FileName: string): Boolean; var TagData: TagRecord; begin { Prepare tag record } FillChar(TagData, SizeOf(TagData), 0); TagData.Header := 'TAG'; Move(FTitle[1], TagData.Title, Length(FTitle)); Move(FArtist[1], TagData.Artist, Length(FArtist)); Move(FAlbum[1], TagData.Album, Length(FAlbum)); Move(FYear[1], TagData.Year, Length(FYear)); Move(FComment[1], TagData.Comment, Length(FComment)); if FTrack > 0 then begin TagData.Comment[29] := #0; TagData.Comment[30] := Chr(FTrack); end; TagData.Genre := FGenreID; { Delete old tag and write new tag } Result := (RemoveFromFile(FileName)) and (SaveTag(FileName, TagData)); end; { ************************** Initialize music genres ************************ } initialization begin { Standard genres } MusicGenre[0] := 'Blues'; MusicGenre[1] := 'Classic Rock'; MusicGenre[2] := 'Country'; MusicGenre[3] := 'Dance'; MusicGenre[4] := 'Disco'; MusicGenre[5] := 'Funk'; MusicGenre[6] := 'Grunge'; MusicGenre[7] := 'Hip-Hop'; MusicGenre[8] := 'Jazz'; MusicGenre[9] := 'Metal'; MusicGenre[10] := 'New Age'; MusicGenre[11] := 'Oldies'; MusicGenre[12] := 'Other'; MusicGenre[13] := 'Pop'; MusicGenre[14] := 'R&B'; MusicGenre[15] := 'Rap'; MusicGenre[16] := 'Reggae'; MusicGenre[17] := 'Rock'; MusicGenre[18] := 'Techno'; MusicGenre[19] := 'Industrial'; MusicGenre[20] := 'Alternative'; MusicGenre[21] := 'Ska'; MusicGenre[22] := 'Death Metal'; MusicGenre[23] := 'Pranks'; MusicGenre[24] := 'Soundtrack'; MusicGenre[25] := 'Euro-Techno'; MusicGenre[26] := 'Ambient'; MusicGenre[27] := 'Trip-Hop'; MusicGenre[28] := 'Vocal'; MusicGenre[29] := 'Jazz+Funk'; MusicGenre[30] := 'Fusion'; MusicGenre[31] := 'Trance'; MusicGenre[32] := 'Classical'; MusicGenre[33] := 'Instrumental'; MusicGenre[34] := 'Acid'; MusicGenre[35] := 'House'; MusicGenre[36] := 'Game'; MusicGenre[37] := 'Sound Clip'; MusicGenre[38] := 'Gospel'; MusicGenre[39] := 'Noise'; MusicGenre[40] := 'AlternRock'; MusicGenre[41] := 'Bass'; MusicGenre[42] := 'Soul'; MusicGenre[43] := 'Punk'; MusicGenre[44] := 'Space'; MusicGenre[45] := 'Meditative'; MusicGenre[46] := 'Instrumental Pop'; MusicGenre[47] := 'Instrumental Rock'; MusicGenre[48] := 'Ethnic'; MusicGenre[49] := 'Gothic'; MusicGenre[50] := 'Darkwave'; MusicGenre[51] := 'Techno-Industrial'; MusicGenre[52] := 'Electronic'; MusicGenre[53] := 'Pop-Folk'; MusicGenre[54] := 'Eurodance'; MusicGenre[55] := 'Dream'; MusicGenre[56] := 'Southern Rock'; MusicGenre[57] := 'Comedy'; MusicGenre[58] := 'Cult'; MusicGenre[59] := 'Gangsta'; MusicGenre[60] := 'Top 40'; MusicGenre[61] := 'Christian Rap'; MusicGenre[62] := 'Pop/Funk'; MusicGenre[63] := 'Jungle'; MusicGenre[64] := 'Native American'; MusicGenre[65] := 'Cabaret'; MusicGenre[66] := 'New Wave'; MusicGenre[67] := 'Psychadelic'; MusicGenre[68] := 'Rave'; MusicGenre[69] := 'Showtunes'; MusicGenre[70] := 'Trailer'; MusicGenre[71] := 'Lo-Fi'; MusicGenre[72] := 'Tribal'; MusicGenre[73] := 'Acid Punk'; MusicGenre[74] := 'Acid Jazz'; MusicGenre[75] := 'Polka'; MusicGenre[76] := 'Retro'; MusicGenre[77] := 'Musical'; MusicGenre[78] := 'Rock & Roll'; MusicGenre[79] := 'Hard Rock'; { Extended genres } MusicGenre[80] := 'Folk'; MusicGenre[81] := 'Folk-Rock'; MusicGenre[82] := 'National Folk'; MusicGenre[83] := 'Swing'; MusicGenre[84] := 'Fast Fusion'; MusicGenre[85] := 'Bebob'; MusicGenre[86] := 'Latin'; MusicGenre[87] := 'Revival'; MusicGenre[88] := 'Celtic'; MusicGenre[89] := 'Bluegrass'; MusicGenre[90] := 'Avantgarde'; MusicGenre[91] := 'Gothic Rock'; MusicGenre[92] := 'Progessive Rock'; MusicGenre[93] := 'Psychedelic Rock'; MusicGenre[94] := 'Symphonic Rock'; MusicGenre[95] := 'Slow Rock'; MusicGenre[96] := 'Big Band'; MusicGenre[97] := 'Chorus'; MusicGenre[98] := 'Easy Listening'; MusicGenre[99] := 'Acoustic'; MusicGenre[100]:= 'Humour'; MusicGenre[101]:= 'Speech'; MusicGenre[102]:= 'Chanson'; MusicGenre[103]:= 'Opera'; MusicGenre[104]:= 'Chamber Music'; MusicGenre[105]:= 'Sonata'; MusicGenre[106]:= 'Symphony'; MusicGenre[107]:= 'Booty Bass'; MusicGenre[108]:= 'Primus'; MusicGenre[109]:= 'Porn Groove'; MusicGenre[110]:= 'Satire'; MusicGenre[111]:= 'Slow Jam'; MusicGenre[112]:= 'Club'; MusicGenre[113]:= 'Tango'; MusicGenre[114]:= 'Samba'; MusicGenre[115]:= 'Folklore'; MusicGenre[116]:= 'Ballad'; MusicGenre[117]:= 'Power Ballad'; MusicGenre[118]:= 'Rhythmic Soul'; MusicGenre[119]:= 'Freestyle'; MusicGenre[120]:= 'Duet'; MusicGenre[121]:= 'Punk Rock'; MusicGenre[122]:= 'Drum Solo'; MusicGenre[123]:= 'A capella'; MusicGenre[124]:= 'Euro-House'; MusicGenre[125]:= 'Dance Hall'; MusicGenre[126]:= 'Goa'; MusicGenre[127]:= 'Drum & Bass'; MusicGenre[128]:= 'Club-House'; MusicGenre[129]:= 'Hardcore'; MusicGenre[130]:= 'Terror'; MusicGenre[131]:= 'Indie'; MusicGenre[132]:= 'BritPop'; MusicGenre[133]:= 'Negerpunk'; MusicGenre[134]:= 'Polsk Punk'; MusicGenre[135]:= 'Beat'; MusicGenre[136]:= 'Christian Gangsta Rap'; MusicGenre[137]:= 'Heavy Metal'; MusicGenre[138]:= 'Black Metal'; MusicGenre[139]:= 'Crossover'; MusicGenre[140]:= 'Contemporary Christian'; MusicGenre[141]:= 'Christian Rock'; MusicGenre[142]:= 'Merengue'; MusicGenre[143]:= 'Salsa'; MusicGenre[144]:= 'Trash Metal'; MusicGenre[145]:= 'Anime'; MusicGenre[146]:= 'JPop'; MusicGenre[147]:= 'Synthpop'; end; end. { Herkese iyi çalışmalar... Görkem SARI notilus_hack@hotmail.com }