?
Solved

Mp3 tags

Posted on 2003-03-14
3
Medium Priority
?
497 Views
Last Modified: 2010-04-04
Hi

I want to read following tags from a MP3-file

Artist , Album , Title , Year , Genre , Track

Have two components that does the trick, but not all 6 infos each.
I want one code that does it, anyone can help me.

Its the Track - reading i missing
0
Comment
Question by:SvanteMusic
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
3 Comments
 

Accepted Solution

by:
ivan_llanas earned 400 total points
ID: 8140046

  Here is the full component I'm using in one of my programs that lets you get and set these 6 infos and all the others present in a ID3-tag v1.x


---------8<------------8<------------8<---------
{ *************************************************************************** }
{                                                                             }
{ Audio Tools Library (Freeware)                                              }
{ Class TID3v1 - for manipulating with ID3v1 tags                             }
{                                                                             }
{ Copyright (c) 2001,2002 by Jurgen Faul                                      }
{ E-mail: jfaul@gmx.de                                                        }
{ http://jfaul.de/atl                                                         }
{                                                                             }
{ Version 1.0 (25 July 2001)                                                  }
{   - Reading & writing support for ID3v1.x tags                              }
{   - Tag info: title, artist, album, track, year, genre, comment             }
{                                                                             }
{ *************************************************************************** }

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;
      FChanged : boolean;
      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);
      procedure FSetGenre(const NewGenre: String);
      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 write FSetGenre;     { Genre name }

      property Changed : boolean read FChanged;
  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
   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);
end;

{ --------------------------------------------------------------------------- }
function SaveTag(const FileName: string; TagData: TagRecord): Boolean;
var SourceFile : file;
    Tmp        : TagRecord;
    v          : integer;
begin
   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) - 128);
   BlockRead(SourceFile, Tmp, 128);

   if (Tmp.Header='TAG') then  v := FileSize(SourceFile) - 128 // Update Tag
   else                        v := FileSize(SourceFile);      // Write New Tag

   Seek (SourceFile, v);

   BlockWrite (SourceFile, TagData, SizeOf(TagData));
   CloseFile  (SourceFile);
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);
  FChanged := true;
end;

{ --------------------------------------------------------------------------- }

procedure TID3v1.FSetArtist(const NewArtist: String30);
begin
  FArtist := TrimRight(NewArtist);
  FChanged := true;
end;

{ --------------------------------------------------------------------------- }

procedure TID3v1.FSetAlbum(const NewAlbum: String30);
begin
  FAlbum := TrimRight(NewAlbum);
  FChanged := true;
end;

{ --------------------------------------------------------------------------- }

procedure TID3v1.FSetYear(const NewYear: String04);
begin
  FYear := TrimRight(NewYear);
  FChanged := true;
end;

{ --------------------------------------------------------------------------- }

procedure TID3v1.FSetComment(const NewComment: String30);
begin
  FComment := TrimRight(NewComment);
  FChanged := true;
end;

{ --------------------------------------------------------------------------- }

procedure TID3v1.FSetTrack(const NewTrack: Byte);
begin
  FTrack := NewTrack;
  FChanged := true;
end;

{ --------------------------------------------------------------------------- }

procedure TID3v1.FSetGenreID(const NewGenreID: Byte);
begin
  FGenreID := NewGenreID;
  FChanged := true;
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;

//------------------------------------------------------------------------------
procedure TID3v1.FSetGenre(const NewGenre: String);
var i : integer;
begin
   for i:=0 to MAX_MUSIC_GENRES-1 do
   if CompareText (NewGenre, MusicGenre[i])=0 then
   begin
      FGenreID := i;
      FChanged := true;
      Exit;
   end
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;
  FChanged := false;
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;
    FChanged := false;
  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
  begin
     Result := false;
     try Result := RemoveTag(FileName);
     finally if result then ResetData;
     end;
  end;
  FChanged := false;
end;

{ --------------------------------------------------------------------------- }
function TID3v1.SaveToFile(const FileName: string): Boolean;
var
  TagData: TagRecord;
begin
  result := false;
  { 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;
  try
     { Delete old tag and write new tag }
     Result := SaveTag(FileName, TagData);
  finally
     if result then FExists := true;
     FChanged := FChanged and not result;
  end;
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.
---------8<------------8<------------8<---------

0
 

Expert Comment

by:sumguy_
ID: 8141416
if you go to http://delphi.about.com/library/weekly/aa112800a.htm there is a tutorial on creating a basic Mp3 player which also shows you know to create an mp3 Tag editor (with all the features) without using components.
0
 

Author Comment

by:SvanteMusic
ID: 8142117
Hi

Thanks for the code, it was easy to use.

It helped me / my program alot.


LL
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
In this video, Percona Director of Solution Engineering Jon Tobin discusses the function and features of Percona Server for MongoDB. How Percona can help Percona can help you determine if Percona Server for MongoDB is the right solution for …
How to fix incompatible JVM issue while installing Eclipse While installing Eclipse in windows, got one error like above and unable to proceed with the installation. This video describes how to successfully install Eclipse. How to solve incompa…
Suggested Courses

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question