{Модуль для работы с MP3 Tag'ами ID3 Новый тип: TMp3Tag Новая константа: Genres (список жанров) Функции: function IndexToGenre(Index:byte):string; - Возвращает жанр по его индексу function GenreToIndex(Genre:string):byte; - Возвращает индекс жанра function GetMP3Tag(var Mp3Tag:TMP3Tag;FileName:string):boolean; // - Читает TAG из файла (True - успешно, False - ошибка) function SetMp3Tag(Mp3Tag:TMP3Tag;FileName:string):boolean; // - Сохраняет TAG в файл (True - успешно, False - ошибка) function DeleteMp3Tag(FileName:string):boolean; // - Удаляет TAG из файла (True - успешно, False - ошибка или TAG не найден) function TagExists(FileName:string):boolean; // - Возвращает True, если в файле обнаружен TAG; False - если нет (или при ошибке) Пример использования: var Mp3Tag:TMp3Tag; Mp3File:string; begin Mp3File:='C:\Music\song.mp3'; if TagExists(Mp3File) then begin if GetMp3Tag(Mp3Tag, Mp3File) then ShowMessage('Название: '+Mp3Tag.Title+#13+#10+'Жанр: '+IndexToGenre(Mp3Tag.Genre)) else ShowMessage('ОШИБКА'); end else ShowMessage('TAG не найден'); end; Зависимости: SysUtils, Classes ***************************************************** } unit UMP3Tags; interface uses SysUtils, Classes; type TMP3Tag = record FileName: string; Title, Artist, Album: string[30]; Year: string[4]; Comment: string[29]; Track, Genre: byte; end; function IndexToGenre(Index: byte): string; function GenreToIndex(Genre: string): byte; function GetMP3Tag(var Mp3Tag: TMP3Tag; FileName: string): boolean; function SetMp3Tag(Mp3Tag: TMP3Tag; FileName: string): boolean; function DeleteMp3Tag(FileName: string): boolean; function TagExists(FileName: string): boolean; const Genres: array[0..125] 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 Brass', 'Primus', 'Porn Groove', 'Satire', 'Slow Jam', 'Club', 'Tango', 'Samba', 'Folklore', 'Ballad', 'Poweer Ballad', 'Rhytmic Soul', 'Freestyle', 'Duet', 'Punk Rock', 'Drum Solo', 'A Capela', 'Euro-House', 'Dance Hall'); implementation function GetMP3Tag(var Mp3Tag: TMP3Tag; FileName: string): boolean; var tag: array[0..127] of char; F: file; I: byte; S: string; function DelSpace(s: string): string; begin Result := s; if length(Result) = 0 then exit; while s[length(Result)] in [' ', #0] do begin delete(Result, length(Result), 1); if Result = '' then break; end; end; begin Result := false; if not FileExists(FileName) then exit; mp3tag.FileName := FileName; mp3tag.Title := ExtractFileName(ChangeFileExt(FileName, '')); mp3tag.Artist := 'Unknown'; mp3tag.Album := 'Unknown'; mp3tag.Year := ''; mp3tag.Comment := ''; mp3tag.Genre := 255; mp3tag.Track := 0; try AssignFile(F, FileName); {$I-} Reset(F, 1); Seek(F, FileSize(F) - 128); BlockRead(f, tag, 128); CloseFile(F); {$I+} if IOResult = 0 then begin s := ''; for i := 0 to 127 do s := s + tag[i]; if copy(s, 1, 3) = 'TAG' then begin mp3tag.Title := DelSpace(copy(S, 4, 30)); mp3tag.Artist := DelSpace(copy(S, 34, 30)); mp3tag.Album := DelSpace(copy(S, 64, 30)); mp3tag.Year := DelSpace(copy(S, 94, 4)); mp3tag.Comment := DelSpace(copy(S, 98, 29)); mp3tag.Track := Ord(S[127]); mp3tag.Genre := Ord(S[128]); Result := true; end; end; except Result := false; end; end; function SetMp3Tag(MP3Tag: TMP3Tag; FileName: string): boolean; var mp3Str: TFileStream; TExists: boolean; procedure WriteString(Str: string; Count: byte); var i: integer; CH: char; begin CH := #0; for i := 1 to Count do begin if I <= Length(Str) then Mp3Str.Write(Str[i], 1) else Mp3Str.Write(CH, 1); end; end; begin Result := false; if not FileExists(FileName) then exit; try FileSetAttr(filename, 0); TExists := TagExists(filename); Mp3Str := TFileStream.create(FileName, fmOpenWrite); if not TExists then Mp3Str.Seek(Mp3Str.Size, 0) else Mp3Str.Seek(Mp3Str.Size - 128, 0); WriteString('TAG', 3); WriteString(MP3Tag.Title, 30); WriteString(MP3Tag.Artist, 30); WriteString(MP3Tag.Album, 30); WriteString(MP3Tag.Year, 4); WriteString(MP3Tag.Comment, 29); Mp3Str.Write(MP3Tag.Track, 1); Mp3Str.Write(MP3Tag.Genre, 1); Mp3Str.Free; Result := true; except Result := false; end; end; function DeleteMp3Tag(FileName: string): boolean; var F: file; begin Result := false; if not TagExists(FileName) then exit; try FileSetAttr(filename, 0); AssignFile(F, filename); Reset(F, 1); Seek(F, FileSize(F) - 128); Truncate(F); CloseFile(F); Result := true; except Result := false; end; end; function TagExists(FileName: string): boolean; var Tag: array[0..2] of char; F: file; begin Result := false; try FileSetAttr(filename, 0); if FileExists(FileName) then begin AssignFile(F, FileName); {$I-} Reset(F, 1); Seek(F, FileSize(F) - 128); BlockRead(f, tag, 3); CloseFile(F); {$I+} if IOResult = 0 then if Tag = 'TAG' then Result := true; end; except Result := false; end; end; function IndexToGenre(Index: byte): string; begin if Index <= 125 then Result := Genres[Index] else Result := ''; end; function GenreToIndex(Genre: string): byte; var i: byte; begin if Genre <> '' then begin for i := 0 to 125 do if UpperCase(Genres[i]) = UpperCase(Genre) then begin Result := i; exit; end; end else Result := 255; end; end. |