Tämä komponentti Delphille lukee mp3-tiedostosta ID3v1.1-tagin ja tulkitsee sen sisältöä.
Komponentti osaa myös tuoda WinAmpista (versio yli 2.05 ja alle 3, luulisin) WinAmpin parhaillaan toistaman tiedoston nimen ja tulkita sitten sen. Tiedoston nimen tuonti pohjautuu fawkzin RampAGEen, jonka version 0.9 lähdekoodista olen ottanut mallia. Kiitos fawkz!
Toivottavasti joku hyötyy tästä jotain.
Nuo main.pas, main.dfm ja id3taga.dpr ovat esimerkkiohjelmaan kuuluvia.
Käyttö:
1. Kopioi tuo id3tag.pas johonkin hakemistoon mistä Delphi sen löytää
2. Lisää siihen tiedostoon joka käyttää TID3Tagia uses-lausekkeeseen kohta ID3Tag
3. Lisää muuttuja tyyppiä TID3Tag
4. Alusta se tyyliin muuttuja := TID3Tag.Create;
5. Käytä sitä. Eli käytä sen funktioita kuten esimerkkiohjelmassa ja lue arvot.
6. Vapauta se lopuksi eli muuttuja.Destroy;
Jos ei selvinnyt, tutki esimerkkiohjelmaa!
Toivottavasti tästä on jollekulle hyötyä, meni nimittäin aikaa tehdä se (varsinkin tuo WinAmp-osuus)
Ladattava versio (sisältää käännetyn ohjelmatiedoston):
http://dsword.se8.org/TID3Tag.zip
id3tag.pas
{*********************************************************} { } { TID3Tag } { Komponentti Delphille, jolla voi lukea ID3-tagin MP3- } { tiedostosta ja tulkita sitä. } { } { Testattu Delphillä: Borland Delpi Personal Version 6.0 } { Tuetty ID3-tagien versio: ID3v1.1 } { } { Katso: http://www.id3.org } { http://www.dv.co.yu/mpgscript/mpeghdr.htm } { } { Koodia saa käyttää täysin vapaasti. Tekijä ei ota } { mitään vastuuta koodista tai mistään mitä se tai sen } { käyttö voi aiheuttaa. } { } { Sisältää myös hienon ominaisuuden: voit hakea Winamp } { 2.x :stä tämän hetkisen kappalleen nimen ja tulkita } { sen ID3-tagin. Tämä ominaisuus perustuu fawkzin } { mIRC-DLL :ään, nimeltään RampAGE. Koodissa on otettu } { mallia RampAGEn version 0.9 lähdekoodeista, joten } { kiitos fawkzille! HUOM! Tämä toiminto on kokeellinen, } { mitä se ikinä tarkoittaakaan, koska se on aitoa True } { Purkkaa. } { } { Tehnyt: DSword } { e-mail: dsword@mbnet.fi } { WWW: http://dsword.se8.org } { } {*********************************************************} unit id3tag; interface uses SysUtils, Windows, Messages, StrUtils; type TID3Tag = class(TObject) private FFileName: string; FHeader: string; FTitle: string; FArtist: string; FAlbum: string; FYear: Word; FComment: string; FTrack: Byte; FGenre: Byte; FError: Byte; Genres: array [0..255] of string; function GetGenreName: string; public constructor Create; destructor Destroy; override; function AnalyzeFile (sFileName: string): Boolean; function AnalyzeFileFromWinamp(sClassName: string): Boolean; published property FileName: string read FFileName write FFileName; property Header: string read FHeader write FHeader; property Title: string read FTitle write FTitle; property Artist: string read FArtist write FArtist; property Album: string read FAlbum write FAlbum; property Year: Word read FYear write FYear; property Comment: string read FComment write FComment; property Track: Byte read FTrack write FTrack; property Genre: Byte read FGenre write FGenre; property GenreName:string read GetGenreName; property Error: Byte read FError; end; const // Virhekoodit *virn* IER_FILENOTFOUND = 1; // Tiedostoa ei löydy IER_HEADERINCORRECT = 2; // Tiedoston otsake on epäkelpo IER_WINAMPISOFF = 3; // WinAmp ei ole päällä IER_CANTREADMEMORY = 4; // Muistin luku epäonnistui IER_BADWINAMPVERSION = 5; // WinAmpin versio on liian vanha implementation constructor TID3Tag.Create; var i: Integer; begin inherited Create; // Määritellään genrenjen numeroille nimet Genres[ 0] := 'Blues'; Genres[ 1] := 'Classic Rock'; Genres[ 2] := 'Country'; Genres[ 3] := 'Dance'; Genres[ 4] := 'Disco'; Genres[ 5] := 'Funk'; Genres[ 6] := 'Grunge'; Genres[ 7] := 'Hip-Hop'; Genres[ 8] := 'Jazz'; Genres[ 9] := 'Metal'; Genres[10] := 'New Age'; Genres[11] := 'Oldies'; Genres[12] := 'Other'; Genres[13] := 'Pop'; Genres[14] := 'R&B'; Genres[15] := 'Rap'; Genres[16] := 'Reggae'; Genres[17] := 'Rock'; Genres[18] := 'Techno'; Genres[19] := 'Industrial'; Genres[20] := 'Alternative'; Genres[21] := 'Ska'; Genres[22] := 'Death Metal'; Genres[23] := 'Pranks'; Genres[24] := 'Soundtrack'; Genres[25] := 'Euro-Techno'; Genres[26] := 'Ambient'; Genres[27] := 'Trip-Hop'; Genres[28] := 'Vocal'; Genres[29] := 'Jazz+Funk'; Genres[30] := 'Fusion'; Genres[31] := 'Trance'; Genres[32] := 'Classical'; Genres[33] := 'Instrumental'; Genres[34] := 'Acid'; Genres[35] := 'House'; Genres[36] := 'Game'; Genres[37] := 'Sound Clip'; Genres[38] := 'Gospel'; Genres[39] := 'Noise'; Genres[40] := 'AlternRock'; Genres[41] := 'Bass'; Genres[42] := 'Soul'; Genres[43] := 'Punk'; Genres[44] := 'Space'; Genres[45] := 'Meditative'; Genres[46] := 'Instrumental Pop'; Genres[47] := 'Instrumental Rock'; Genres[48] := 'Ethnic'; Genres[49] := 'Gothic'; Genres[50] := 'Darkwave'; Genres[51] := 'Techno-Industrial'; Genres[52] := 'Electronic'; Genres[53] := 'Pop-Folk'; Genres[54] := 'Eurodance'; Genres[55] := 'Dream'; Genres[56] := 'Southern Rock'; Genres[57] := 'Comedy'; Genres[58] := 'Cult'; Genres[59] := 'Gangsta'; Genres[60] := 'Top 40'; Genres[61] := 'Christian Rap'; Genres[62] := 'Pop/Funk'; Genres[63] := 'Jungle'; Genres[64] := 'Native American'; Genres[65] := 'Cabaret'; Genres[66] := 'New Wave'; Genres[67] := 'Psychadelic'; Genres[68] := 'Rave'; Genres[69] := 'Showtunes'; Genres[70] := 'Trailer'; Genres[71] := 'Lo-Fi'; Genres[72] := 'Tribal'; Genres[73] := 'Acid Bunk'; Genres[74] := 'Acid Jazz'; Genres[75] := 'Polka'; Genres[76] := 'Retro'; Genres[77] := 'Musical'; Genres[78] := 'Rock & Roll'; Genres[79] := 'Hard Rock'; // Seuraavat ovat WinAmpin määrittelemiä Genres[80] := 'Folk'; Genres[81] := 'Folk-Rock'; Genres[82] := 'National Folk'; Genres[83] := 'Swing'; Genres[84] := 'Fast Fusion'; Genres[85] := 'Bebob'; Genres[86] := 'Latin'; Genres[87] := 'Revival'; Genres[88] := 'Celtic'; Genres[89] := 'Bluegrass'; Genres[90] := 'Avantgarde'; Genres[91] := 'Gothic Rock'; Genres[92] := 'Progressive Rock'; Genres[93] := 'Psychedelic Rock'; Genres[94] := 'Symphonic Rock'; Genres[95] := 'Slow Rock'; Genres[96] := 'Big Band'; Genres[97] := 'Chorus'; Genres[98] := 'Easy Listening'; Genres[99] := 'Acoustic'; Genres[100] := 'Humour'; Genres[101] := 'Speech'; Genres[102] := 'Chanson'; Genres[103] := 'Opera'; Genres[104] := 'Chamber Music'; Genres[105] := 'Sonata'; Genres[106] := 'Sinfony'; Genres[107] := 'Booty Brass'; Genres[108] := 'Primus'; Genres[109] := 'Porn Groove'; Genres[110] := 'Satire'; Genres[111] := 'Slow Jam'; Genres[112] := 'Club'; Genres[113] := 'Tango'; Genres[114] := 'Samba'; Genres[115] := 'Folklore'; Genres[116] := 'Ballad'; Genres[117] := 'Poweer Ballad'; Genres[118] := 'Rhytmic Soul'; Genres[119] := 'Freestyle'; Genres[110] := 'Duet'; Genres[121] := 'Punk Rock'; Genres[122] := 'Drum Solo'; Genres[123] := 'A Capela'; Genres[124] := 'Euro House'; Genres[125] := 'Dance-Half'; // Loput ovat tuntemattomia for i := 126 to 255 do Genres[i] := 'Unknown'; end; destructor TID3Tag.Destroy; begin inherited Destroy; end; function TID3Tag.AnalyzeFile(sFileName: string): Boolean; var F: File; // Tiedosto Buf: array[0..127] of Char; // Puskuri johon dataa luetaan U: string; // apumuuttuja I: Integer; // - " - begin // Oletetaan että kaikki menee hyvin. Tätä muutetaan jos menee huonosti. Result := true; // Tarkistetaan onko tiedosto olemassa if not FileExists(sFileName) then begin // Eikö? No sitten palautetaan false ja lopetetaan FError := IER_FILENOTFOUND; Result := false; Exit; end else FFileName := sFileName; // Käytetään ID3v1.1-määritystä ( ks. http://www.dv.co.yu/mpgscript/mpeghdr.htm ) AssignFile(F, FFileName); // Määritetään käytettäväksi valittua tiedostoa FileMode := 0; // Vain luku-moodi Reset(F, 1); // Avataan tiedosto, yksikön kooksi 1 tavu // Siirryttään kohtaan 128 tavua tiedoston lopusta Seek(F, FileSize(F) - 128); BlockRead(F, Buf, 128); // Luetaan 128 tavua muistiin CloseFile(F); // Suljetaan tiedosto // Muunnetaan merkkijonoksi U := ''; for I := 0 to 128 do U := U + Buf[i]; // Kopioidaan otsikko eli tavut 0-2 FHeader := Copy(U, 1, 3); // Tarkistetaan että otsikko on kunnossa if FHeader <> 'TAG' then begin FError := IER_HEADERINCORRECT; Result := false; Exit; end; // Kopioidaan kappaleen nimi eli tavut 3-32 muuttujasta Buf FTitle := Copy(U, 4, 30); // Kopioidaan artisti eli tavut 33-62 muuttujasta Buf FArtist := MidStr(U, 34, 30); // Kopioidaan albumin nimi eli tavut 63-92 muuttujasta Buf FAlbum := MidStr(U, 64, 30); // Kopioidaan julkaisuvuosi eli tavut 93-96 muuttujasta Buf // Koska vuodessa voi olla jotain mätää, käytettään varmuuden // vuoksi try..except-rakennetta. try FYear := StrToInt(MidStr(U, 94, 4)); except on EConvertError do FYear := 0; end; // Kopioidaan kommentti eli tavut 97-125 muuttujasta Buf FComment := MidStr(U, 98, 29); // Kopioidaan kappaleen numero eli tavu 126 muuttujasta Buf FTrack := Ord(Buf[126]); // Kopioidaan genren numero eli tavu 127 muuttujasta Buf FGenre := Ord(Buf[High(Buf)]); end; function TID3Tag.AnalyzeFileFromWinamp(sClassName: string): Boolean; var hwnd: THandle; // WinAmpin handle tallennetaan tähän pos, tmp: Cardinal; // pari muuttujaa id: Cardinal; // "monikäyttöinen id" *virn* luettu: Cardinal; // kuinka monta tavua luettiin buf: PChar; // puskuri, johon luetaan tiedoston nimi pt: Pointer; begin Result := true; buf := StrAlloc(257); // Varataan muistia 256 tavulle // Kiitokset fawkzille, tähän on otettu mallia RampAGE v. 0.9 :stä // Ihme kyllä sain tämän toimimaan... True Purkkaa! if sClassName <> '' then hwnd := FindWindow(PChar(sClassName), nil) else hwnd := FindWindow('Winamp v1.x', nil); // haetaan ikkunnan kahva if hwnd = 0 then begin // saatiinko kahva FError := IER_FILENOTFOUND; Result := false; Exit; end; pos := SendMessage(hwnd, WM_USER, 0, 0); // Haetaan versio if pos < $2005 then begin FError := IER_BADWINAMPVERSION; Result := false; Exit; end; GetWindowThreadProcessId(hwnd, id); id := OpenProcess(PROCESS_VM_READ, false, id); // Avataan prosessi pos := SendMessage(hwnd, WM_USER, 0, 125); // Haetaan sijainti // soittolistassa // Haetaan pointteri kappaleen nimeen pos := SendMessage(hwnd, WM_USER, pos, 211); // Muutetaan se inline-assylla oikeaan muotoon // Luulen että tämän voi tehdä jotenkin Delphilläkin... // Jos joku sen osaa, kertokoot! asm push pos pop pt end; luettu := 0; // Ja kuinka monta tavua luettiin, alusteaan tmp := 255; // Kuinka monta tavua luetaan? // Luetaan sitä WinAmpin muistia passelista kohdasta if ReadProcessMemory(id, pt, buf, tmp, luettu) = false then begin FError := IER_CANTREADMEMORY; Result := false; // Ei lopeteta, tätyyhän prosessi sulkea end; CloseHandle(id); // Suljetaan prosessi // Jos tiedosto on olemassa, käsitellään se if FileExists(String(Buf)) then AnalyzeFile(String(buf)); end; function TID3Tag.GetGenreName: string; begin Result := Genres[FGenre]; // Palautetaan genre end; end.
main.pas, esimerkkiohjelma
unit main; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls, ID3Tag; type TFrmIDAnalyzer = class(TForm) BtnAnalyze: TButton; TxtResult: TRichEdit; DlgOpen: TOpenDialog; BtnWinAmpAnalyze: TButton; procedure BtnAnalyzeClick(Sender: TObject); procedure BtnWinAmpAnalyzeClick(Sender: TObject); end; var FrmIDAnalyzer: TFrmIDAnalyzer; implementation {$R *.dfm} procedure TFrmIDAnalyzer.BtnAnalyzeClick(Sender: TObject); var F: TID3Tag; // Se objekti begin if DlgOpen.Execute then // Avataan avaus-dialogi if FileExists(DlgOpen.FileName) then // Tarkistetaan että tiedosto on olemassa begin TxtResult.Lines.Clear; F := TID3Tag.Create; // Alustetaan // Sitten yritettän analysoida if F.AnalyzeFile(DlgOpen.FileName) then begin // Onnistui, kerrotaan tulokset TxtResult.Lines.Add('Tiedoston nimi: ' + F.FileName); TxtResult.Lines.Add('Artisti: "' + Trim(F.Artist) + '"'); TxtResult.Lines.Add('Kappeleen nimi: ' + Trim(F.Title)); TxtResult.Lines.Add('Albumi: ' + Trim(F.Album)); TxtResult.Lines.Add('Vuosi: ' + IntToStr(F.Year)); TxtResult.Lines.Add('Kommentti: ' + Trim(F.Comment)); TxtResult.Lines.Add('Kappaleen numero: ' + IntToStr(F.Track)); TxtResult.Lines.Add('Genre #: ' + IntToStr(F.Genre)); TxtResult.Lines.Add('Genre: ' + Trim(F.GenreName)); end else begin // Ei onnistunut ilmoitetaan TxtResult.Lines.Add('Virhe: ' + IntToStr(F.Error)); // Jos headerissa on vikaa, kerrotaan asiasta if F.Error = IER_HEADERINCORRECT then TxtResult.Lines.Add('Virheellinen otsake! Tiedostossa ei ole ID3-tagia'); end; F.Destroy; // Lopuksi vapautetaan end; // endif FileExists(DlgOpen.FileName) end; procedure TFrmIDAnalyzer.BtnWinAmpAnalyzeClick(Sender: TObject); var F: TID3Tag; // Mikähän tämä on? begin TxtResult.Lines.Clear; // Tyhjennetään F := TID3Tag.Create; // Alustetaan if F.AnalyzeFileFromWinamp('') then begin TxtResult.Lines.Clear; TxtResult.Lines.Add('Tiedoston nimi: ' + F.FileName); TxtResult.Lines.Add('Artisti: "' + Trim(F.Artist) + '"'); TxtResult.Lines.Add('Kappeleen nimi: ' + Trim(F.Title)); TxtResult.Lines.Add('Albumi: ' + Trim(F.Album)); TxtResult.Lines.Add('Vuosi: ' + IntToStr(F.Year)); TxtResult.Lines.Add('Kommentti: ' + Trim(F.Comment)); TxtResult.Lines.Add('Kappaleen numero: ' + IntToStr(F.Track)); TxtResult.Lines.Add('Genre #: ' + IntToStr(F.Genre)); TxtResult.Lines.Add('Genre: ' + Trim(F.GenreName)); end else begin TxtResult.Lines.Add('Virhe: ' + IntToStr(F.Error)); if F.Error = IER_FILENOTFOUND then TxtResult.Lines.Add('Tiedostoa ei löydy tai WinAmp ei toista mitään.') else if F.Error = IER_HEADERINCORRECT then TxtResult.Lines.Add('Virheellinen otsake! Tiedostossa ei ole ID3-tagia') else if F.Error = IER_WINAMPISOFF then TxtResult.Lines.Add('WinAmp ei ole päällä tai luokkanimi ei ole oikein') else if F.Error = IER_BADWINAMPVERSION then TxtResult.Lines.Add('WinAmpin versio on liian vanha. HUOM! WinAmpin pitää olla versiota 2.x, kolmonen ei kelpaa!'); end; F.Destroy; // Vapautetaan rakenne end; end.
main.dfm esimerkkiohjelman lomakkeen määritys
object FrmIDAnalyzer: TFrmIDAnalyzer Left = 192 Top = 110 Width = 529 Height = 392 Caption = 'ID3v1.1-analysoija' Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] OldCreateOrder = False PixelsPerInch = 96 TextHeight = 13 object BtnAnalyze: TButton Left = 8 Top = 8 Width = 257 Height = 25 Caption = 'Analysoi' TabOrder = 0 OnClick = BtnAnalyzeClick end object TxtResult: TRichEdit Left = 8 Top = 40 Width = 505 Height = 321 Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'Courier New' Font.Style = [] Lines.Strings = ( 'Demo-ohjelma TID3Tag-komponentille' 'Kääntyy ainakin Delphi 6:lla' 'Tukee ID3v1.1 :tä' 'Ohjelmaa saa käyttää vapaasti. Ohjelman tekijä ei ole missään va' + 'stuussa' 'ohjelmasta tai mistään mitä se tai sen käyttö voi aiheuttaa.' 'Paina nappia "Analysoi" tutkiaksesi valitsemasi tiedoston' 'Paina nappia "WinAmp-analysoi" tutkiaksesi WinAmpin tällä hetkel' + 'lä ' 'toistaman' 'tiedoston.' 'Tehnyt: DSword' 'e-mail: dsword@mbnet.fi' 'WWW: http://dsword.se8.org') ParentFont = False TabOrder = 1 end object BtnWinAmpAnalyze: TButton Left = 272 Top = 8 Width = 241 Height = 25 Caption = 'WinAmp-analysoi' TabOrder = 2 OnClick = BtnWinAmpAnalyzeClick end object DlgOpen: TOpenDialog Filter = 'MP3-tiedostot|*.mp3|Kaikki tiedostot|*.*' Left = 480 Top = 328 end end
id3taga.dpr, esimerkkiohjelman päälistaus
program id3taga; uses Forms, main in 'main.pas' {FrmIDAnalyzer}; {$R *.res} begin Application.Initialize; Application.Title := 'ID3v1.1-analysoija'; Application.CreateForm(TFrmIDAnalyzer, FrmIDAnalyzer); Application.Run; end.
Miksi tuonne koodissa näytetään (bugisia) linkkejä, mutta selityksessä ei ole linkkinä tuo ladattavan version osoite?
Hyvä huomio, nyt koodissa ei näy linkkejä lainkaan, ja selityksessä olevat linkit linkitetään niin kuin pitää. Tuo antamasi linkki ohjelman kopiointiin ei tosin tällä hetkellä tunnu toimivan.
lainaus:
Tuo antamasi linkki ohjelman kopiointiin ei tosin tällä hetkellä tunnu toimivan.
Niinpä olikin, olin vahingossa kirjoittanut tiedostonnimen kokonaan pienellä vaikka se sisältää myös isoja kirjaimia. Nyt on linkki korjattu.
"Komponentti osaa myös tuoda WinAmpista (versio yli 2.05 ja alle 3, luulisin) WinAmpin parhaillaan toistaman tiedoston nimen ja tulkita sitten sen. Tiedoston nimen tuonti pohjautuu fawkzin RampAGEen, jonka version 0.9 lähdekoodista olen ottanut mallia. Kiitos fawkz!" mistähän sen rampagen saa?
lainaus:
mistähän sen rampagen saa?
Sen kun tietäisi. Ennen sen sai ainakin Putkan tiedostot-sivulta, mutta nyt se on lopetettu, eikä fawkzilla tunnu olevan enää toimivia kotisivujakaan => pyydä sitä fawkzilta.
Tuosta linkistä löytyy vielä:
https://www.ohjelmointiputka.net/tiedostot/
lainaus:
// Muutetaan se inline-assylla oikeaan muotoon // Luulen että tämän voi tehdä jotenkin Delphilläkin... // Jos joku sen osaa, kertokoot! asm push pos pop pt end;
Pointer(pos).
Toinen kommentti, tuohan ei tuollaisenaan ole mikään komponentti: komponentin luomisesta ja tuhoamisesta huolehtii ohjelma itse, ei ohjelmoija. Tosin eipä tuosta montaa riviä tarvinnut muuttaa että se komponentti ois :)
Näyttäs että linkki ei toimi. Mahtaakohan toimia WinAmp 5 ja delphi 4 kanssa.
Aihe on jo aika vanha, joten et voi enää vastata siihen.