Работа с MP3 Tag-ами
Автор: Шишкин Илья
WEB-сайт: http://delphibase.endimus.com
{ **** UBPFD *********** by delphibase.endimus.com ****
>> Работа с MP3 Tag'ами
Модуль для работы с MP3 Tag'ами ID3V1 (13.12.2003)
Автор: Шишкин Илья
E-mail: Jumbot@hotmail.ru
Новый тип: 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
Автор: Шишкин Илья, jumbot@hotmail.ru, Пушкино
Copyright: Собственное написание (Шишкин Илья)
Дата: 14 декабря 2003 г.
***************************************************** }
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.
Пример использования:
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;
Доработанный вариант модуля (Shady):
{ **** UBPFD *********** by delphibase.endimus.com ****
>> Работа с MP3 Tag'ами
Модуль для работы с MP3 Tag'ами ID3V1 (13.12.2003)
Автор: Шишкин Илья
E-mail: Jumbot@hotmail.ru
Новый тип: 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
Автор: Шишкин Илья, jumbot@hotmail.ru, Пушкино
Copyright: Собственное написание (Шишкин Илья)
Дата: 14 декабря 2003 г.
***************************************************** }
unit mp3tag;
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: TFileStream;
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
f := TfileStream.Create(Filename, fmOpenread);
with f do
begin
Seek(Size - 128, 0);
Read(Tag, 128);
Free;
end;
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
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
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
F: TFileStream;
Tag: array[0..2] of char;
begin
Result := false;
try
// FileSetAttr(filename, 0); zachem ?
if FileExists(FileName) then
begin
F := TfileStream.Create(Filename, fmOpenRead);
with f do
begin
Seek(f.Size - 128, 0);
Read(tag, 3);
// BlockRead(f, tag, 3);
Free;
end;
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.
|