Articles   Members Online:
-Article/Tip Search
-News Group Search over 21 Million news group articles.
-Delphi/Pascal
-CBuilder/C++
-C#Builder/C#
-JBuilder/Java
-Kylix
Member Area
-Home
-Account Center
-Top 10 NEW!!
-Submit Article/Tip
-Forums Upgraded!!
-My Articles
-Edit Information
-Login/Logout
-Become a Member
-Why sign up!
-Newsletter
-Chat Online!
-Indexes NEW!!
Employment
-Build your resume
-Find a job
-Post a job
-Resume Search
Contacts
-Contacts
-Feedbacks
-Link to us
-Privacy/Disclaimer
Embarcadero
Visit Embarcadero
Embarcadero Community
JEDI
Links
How to read infos in MP3 files Turn on/off line numbers in source code. Switch to Orginial background IDE or DSP color Comment or reply to this aritlce/tip for discussion. Bookmark this article to my favorite article(s). Print this article
28-Sep-03
Category
VCL-General
Language
Delphi 4.x
Views
138
User Rating
No Votes
# Votes
0
Replies
0
Publisher:
DSP, Administrator
Reference URL:
DKB
			 Author: Herbert Poltnik

How to read infos in MP3 files

Answer:

1   {
2      Description:
3      Component MP3Info extracts/saves any ID3 Tag into/from it's
4      properties from/to MP3 file.
5      Keywords: MP3 ID3 TAG INFO
6   
7      Author: Rok Krulec (Rok@fpp.edu) (http://Rok.fpp.edu)
8      Primary site: ftp://ftp.fpp.edu/pub/people/Rok_Krulec/mp3i-v12.zip
9   
10  If you use this component, I would like to get 1 American dollar to Rok Krulec, 
11  Zagrad 6, 3000 Celje, Slovenia, Europe.
12  
13  Description of Variables, Properties, Methods and Events:
14      Genres: TStrings;                         - List of Genres
15      constructor Create(AOwner: TComponent);   - Creates an instance
16      destructor Destroy; override;             - Destroys an instance
17      method Save;                              - Saves ID3 Tag to file
18      method RemoveID3;                         - Removes ID3 Tag form file
19      property Filename: TFilename;             - Filename of MP3 file, when changed 
20  it opens a new MP3 file
21      property Artist: String;                  - Artist   (30 Chars)
22      property Title: String;                   - Title    (30 Chars)
23      property Album: String;                   - Album    (30 Chars)
24      property Year: String;                    - Year     ( 4 chars)
25      property Comment: String;                 - Comment  (30 Chars)
26      property Genre: String;                   - Genre               [Read Only]
27      Property GenreID: Byte;                   - Genre ID
28      property Valid: Boolean;                  - Is ID3 valid        [Read Only]
29      property Saved: Boolean;                  - Save success        [Read Only]
30      property Error: String;                   - Error Message       [Read Only]
31      property onChangeFile:TNotifyEvent;       - Triggers when other file is openned
32      property onChange:TNotifyEvent;           - Triggers when one of propertis is 
33  changed (Artist, Title, Album, Year, Comment, GenreID)
34      property onError:TNotifyEvent;            - Triggers when errors ocure (Wrong 
35  filename, Frong fileformat)
36  }
37  
38  unit MP3Info;
39  
40  interface
41  
42  uses
43    SysUtils, Classes;
44  
45  const
46    TAGLEN = 127;
47  
48  type
49    TMP3Info = class(TComponent)
50    private
51      { Private declarations }
52      vFilename: TFilename;
53      vMP3Tag, vArtist, vTitle, vAlbum, vComment, vYear, vGenre, vError: string;
54      vGenreID: Byte;
55      vValid: Boolean;
56      vSaved: Boolean;
57      vChangeFileEvent, vChangeEvent, vErrorEvent: TNotifyEvent;
58      procedure SetFilename(Filename: TFilename);
59      procedure SetArtist(Artist: string);
60      procedure SetTitle(Title: string);
61      procedure SetAlbum(Album: string);
62      procedure SetYear(Year: string);
63      procedure SetComment(Comment: string);
64      procedure SetGenreID(ID: Byte);
65      procedure Open;
66    protected
67      { Protected declarations }
68    public
69      { Public declarations }
70    published
71      { Published declarations }
72      Genres: TStrings;
73      constructor Create(AOwner: TComponent); override;
74      destructor Destroy; override;
75      procedure Save;
76      procedure RemoveID3;
77      property Filename: TFilename read vFilename write SetFilename;
78      property Artist: string read vArtist write SetArtist;
79      property Title: string read vTitle write SetTitle;
80      property Album: string read vAlbum write SetAlbum;
81      property Year: string read vYear write SetYear;
82      property Comment: string read vComment write SetComment;
83      property Genre: string read vGenre;
84      property GenreID: Byte read vGenreID write SetGenreID;
85      property Valid: Boolean read vValid;
86      property Saved: Boolean read vSaved;
87      property Error: string read vError;
88      property onChangeFile: TNotifyEvent read vChangeFileEvent write 
89  vChangeFileEvent;
90      property onChange: TNotifyEvent read vChangeEvent write vChangeEvent;
91      property onError: TNotifyEvent read vErrorEvent write vErrorEvent;
92    end;
93  
94  procedure register;
95  
96  implementation
97  
98  constructor TMP3Info.Create(AOwner: TComponent);
99  begin
100   inherited Create(AOwner);
101   Genres := TStringList.Create;
102   vGenreID := 12;
103   vValid := false;
104   vSaved := false;
105 
106   { Fill the Genres String List so one can use it combo boxes e.t.c. Example: 
107 ComboBox.Items.Assign(MP3Info.Genres) }
108   Genres.CommaText :=
109     '"Blues","Classic 
110 Rock","Country","Dance","Disco","Funk","Grunge","Hip-Hop","Jazz","Metal","New 
111 Age","Oldies",'
112     + 
113 '"Other","Pop","R&B","Rap","Reggae","Rock","Techno","Industrial","Alternative","Ska"
114 ,"Death Metal","Pranks",'
115     + 
116 '"Soundtrack","Euro-Techno","Ambient","Trip-Hop","Vocal","Jazz+Funk","Fusion","Tranc
117 e","Classical","Instrumental",'
118     + '"Acid","House","Game","Sound 
119 Clip","Gospel","Noise","AlternRock","Bass","Soul","Punk","Space","Meditative",'
120     + '"Instrumental Pop","Instrumental 
121 Rock","Ethnic","Gothic","Darkwave","Techno-Industrial","Electronic","Pop-Folk",'
122     + '"Eurodance","Dream","Southern Rock","Comedy","Cult","Gangsta","Top 
123 40","Christian Rap","Pop/Funk","Jungle",'
124     + '"Native American","Cabaret","New 
125 Wave","Psychedelic","Rave","Showtunes","Trailer","Lo-Fi","Tribal","Acid Punk",'
126     + '"Acid Jazz","Polka","Retro","Musical","Rock & Roll","Hard 
127 Rock","Folk","Folk/Rock","National Folk","Swing","Bebob",'
128     + '"Latin","Revival","Celtic","Bluegrass","Avantgarde","Gothic 
129 Rock","Progressive Rock","Psychedelic Rock","Symphonic Rock",'
130     + '"Slow Rock","Big Band","Chorus","Easy 
131 Listening","Acoustic","Humour","Speech","Chanson","Opera","Chamber Music","Sonata",'
132     + '"Symphony","Booty Bass","Primus","Porn Groove","Satire","Slow 
133 Jam","Club","Tango","Samba","Folklore"'
134 
135 end;
136 
137 destructor TMP3Info.Destroy;
138 begin
139   inherited Destroy;
140 end;
141 
142 { Procedure to run when Filename property is changed }
143 
144 procedure TMP3Info.SetFilename(Filename: TFilename);
145 begin
146   vFilename := Filename;
147   Open;
148 end;
149 
150 procedure TMP3Info.SetArtist(Artist: string);
151 begin
152   vArtist := Copy(Artist, 0, 30);
153   if Assigned(onChange) then
154     onChange(Self);
155 end;
156 
157 procedure TMP3Info.SetTitle(Title: string);
158 begin
159   vTitle := Copy(Title, 0, 30);
160   if Assigned(onChange) then
161     onChange(Self);
162 end;
163 
164 procedure TMP3Info.SetAlbum(Album: string);
165 begin
166   vAlbum := Copy(Album, 0, 30);
167   if Assigned(onChange) then
168     onChange(Self);
169 end;
170 
171 procedure TMP3Info.SetYear(Year: string);
172 begin
173   vYear := Copy(Year, 0, 4);
174   if Assigned(onChange) then
175     onChange(Self);
176 end;
177 
178 procedure TMP3Info.SetComment(Comment: string);
179 begin
180   vComment := Copy(Comment, 0, 30);
181   if Assigned(onChange) then
182     onChange(Self);
183 end;
184 
185 procedure TMP3Info.SetGenreID(ID: Byte);
186 begin
187   if ((ID > 255) or (ID > Genres.Count - 1)) then
188     ID := 12;
189   vGenreID := ID;
190   vGenre := Genres[vGenreID]; //this line is important because after changing
191   //vGenreID whitout it vGenre will be the same like before !!!
192   if Assigned(onChange) then
193     onChange(Self);
194 end;
195 
196 { Opens file with Filename property, reads ID3 Tag and sets properties }
197 
198 procedure TMP3Info.Open;
199 
200 { Strips empty spaces at the end of word }
201   function Strip(WordToStrip: string; CharToStripAway: Char): string;
202   var
203     i: Integer;
204   begin
205     for i := length(WordToStrip) downto 1 do
206     begin
207       if WordToStrip[i] <> ' ' then
208       begin
209         Strip := Copy(WordToStrip, 0, i);
210         exit;
211       end;
212     end;
213     Strip := '';
214   end;
215 
216 var
217   dat: file of char;
218   id3: array[0..TAGLEN] of char;
219 begin
220   vSaved := false;
221   vValid := True;
222   if FileExists(vFilename) then
223   begin
224     assignfile(dat, vFilename);
225     reset(dat);
226     seek(dat, FileSize(dat) - 128);
227     blockread(dat, id3, 128);
228     closefile(dat);
229     vMP3tag := copy(id3, 1, 3);
230     if vMP3Tag = 'TAG' then
231     begin
232       vTitle := strip(copy(id3, 4, 30), ' ');
233       vArtist := strip(copy(id3, 34, 30), ' ');
234       vAlbum := strip(copy(id3, 64, 30), ' ');
235       vComment := strip(copy(id3, 98, 30), ' ');
236       vYear := strip(copy(id3, 94, 4), ' ');
237       vGenreID := ord(id3[127]);
238       if vGenreID > Genres.Count then
239         vGenreID := 12;
240       vGenre := Genres[vGenreID];
241       { Trigger OnChange Event }
242       if Assigned(onChangeFile) then
243         onChangeFile(Self);
244     end
245     else
246     begin
247       vValid := False;
248       vTitle := '';
249       vArtist := '';
250       vAlbum := '';
251       vComment := '';
252       vYear := '';
253       vGenreID := 12;
254       vError := 'Wrong file format or no ID3 Tag !';
255       if Assigned(onError) then
256         onError(Self);
257     end;
258   end
259   else
260   begin
261     vValid := False;
262     vError := 'File doesn`t exist !';
263     if Assigned(onError) then
264       onError(Self);
265   end;
266 end;
267 
268 { Removes the ID3-tag from currently open file }
269 
270 procedure TMP3Info.RemoveID3;
271 var
272   dat: file of char;
273 begin
274   // does the file exist ?
275   if not FileExists(vFilename) then
276   begin
277     vError := 'File doesn`t exist !';
278     if Assigned(onError) then
279       onError(Self);
280     exit;
281   end;
282   // is the file already untagged ?
283   if (vValid = false) then
284   begin
285     vError := 'File is already untagged !';
286     if Assigned(onError) then
287       onError(Self);
288     exit;
289   end;
290   // remove readonly-attribute
291   if (FileGetAttr(vFilename) and faReadOnly > 0) then
292     FileSetAttr(vFileName, FileGetAttr(vFilename) - faReadOnly);
293   // if readonly attr. already exists it cannot be removed to cut ID3 Tag
294   if (FileGetAttr(vFilename) and faReadOnly > 0) then
295   begin
296     vError := 'Canīt write ID3 tag information !';
297     if Assigned(onError) then
298       onError(Self);
299     exit;
300   end;
301   // open current mp3 file if ID3 tag exists
302   if (vValid = true) then
303   begin
304     {I-}
305     assignfile(dat, vFilename);
306     reset(dat);
307     {I+}
308     if IOResult <> 0 then
309     begin
310       vError := 'Could not open file !';
311       if Assigned(onError) then
312         onError(Self);
313       exit;
314     end;
315     seek(dat, FileSize(dat) - 128);
316     truncate(dat); // cut all 128 bytes of file
317     closefile(dat);
318     vValid := false; // set vValid to false because the tag has been removed
319   end;
320 end;
321 
322 { Saves ID3 Tag to currently opened file }
323 
324 procedure TMP3Info.Save;
325 
326 { Empties 128 character array }{ Don't tell me that there is a function for this in 
327 Pascal }
328   procedure EmptyArray(var Destination: array of char);
329   var
330     i: Integer;
331   begin
332     for i := 0 to TAGLEN do
333     begin
334       Destination[i] := ' ';
335     end;
336   end;
337 
338   { Insert a substring into character array at index position of array }
339   procedure InsertToArray(Source: string; var Destination: array of char; Index:
340     Integer);
341   var
342     i: Integer;
343   begin
344     for i := 0 to length(Source) - 1 do
345     begin
346       Destination[Index + i] := Source[i + 1];
347     end;
348   end;
349 
350 var
351   dat: file of char;
352   id3: array[0..TAGLEN] of char;
353 begin
354   vSaved := true;
355   // does the filename exist ?
356   if FileExists(vFilename) then
357   begin
358     // fill 128 bytes long array with ID3 Tag information
359     EmptyArray(id3);
360     InsertToArray('TAG', id3, 0);
361     InsertToArray(vTitle, id3, 3);
362     InsertToArray(vArtist, id3, 33);
363     InsertToArray(vAlbum, id3, 63);
364     InsertToArray(vComment, id3, 97);
365     InsertToArray(vYear, id3, 93);
366     id3[127] := chr(vGenreID);
367     // remove readonly-attribute
368     if (FileGetAttr(vFilename) and faReadOnly > 0) then
369       FileSetAttr(vFileName, FileGetAttr(vFilename) - faReadOnly);
370     // if readonly attr. already exists it cannot be removed to write ID3
371     if (FileGetAttr(vFilename) and faReadOnly > 0) then
372     begin
373       vSaved := False;
374       vError := 'Canīt write ID3 tag information !';
375       if Assigned(onError) then
376         onError(Self);
377       exit;
378     end;
379     // if valid then overwrite existing ID3 Tag, else append to file
380     if (vValid = True) then
381     begin
382       {I-}
383       assignfile(dat, vFilename);
384       reset(dat);
385       seek(dat, FileSize(dat) - 128);
386       blockwrite(dat, id3, 128);
387       closefile(dat);
388       {I+}
389       if IOResult <> 0 then
390         vSaved := false;
391     end
392     else
393     begin
394       {I-}
395       assignfile(dat, vFilename);
396       reset(dat);
397       seek(dat, FileSize(dat));
398       blockwrite(dat, id3, 128);
399       closefile(dat);
400       {I+}
401       if IOResult <> 0 then
402         vSaved := false;
403     end
404   end
405   else
406   begin
407     vValid := False;
408     vSaved := False;
409     vError := 'File doesn`t exist or is not valid !';
410     if Assigned(onError) then
411       onError(Self);
412   end;
413 end;
414 
415 procedure register;
416 begin
417   RegisterComponents('Samples', [TMP3Info]);
418 end;
419 
420 end.
421 
422 {
423    The ID3 Information is stored in the last 128 bytes of an MP3 file.
424    The ID3 has the following fields, and the offsets given here, are from 0-127
425 
426    Field       Length            offsets
427    -------------------------------------
428    Tag           3                0-2
429    Songname     30                3-32
430    Artist       30                33-62
431    Album        30                63-92
432    Year          4                93-96
433    Comment      30                97-126
434    Genre         1                127
435 }


			
Vote: How useful do you find this Article/Tip?
Bad Excellent
1 2 3 4 5 6 7 8 9 10

 

Advertisement
Share this page
Advertisement
Download from Google

Copyright © Mendozi Enterprises LLC