Only Texttags supported.
For using, see the example at the end of code!
Code: Select all
;======================================================================
; Module: TagReader.pbi
;
; Author: Thomas (ts-soft) Schulz
; Date: Oct 18, 2013
; Version: 0.4
; Target Compiler: PureBasic 5.2+
; Target OS: All
; License: Free, unrestricted, no warranty whatsoever
; Use at your own risk
;======================================================================
; History:
; Version 0.4
; fixed: Reading Unicode Tags (ID3v2.x) by Thorsten1867
; Version 0.3
; + added genre and track v1 Tags
; fixed a bug with only v1 Tags
;
; Version 0.2
; fixed a bug in Reading v1 Tags
DeclareModule TagReader
Interface iTagReader
Destroy()
GetTagList.s()
GetContent.s(Tag.s)
EndInterface
Declare New_MP3TagObj(FileName.s)
EndDeclareModule
Module TagReader
EnableExplicit
Structure TagReader
ID.a[3]
version.a[2]
flags.b
size.l
*memory
EndStructure
Structure TagReader_Class
*vTable
Map Tags.s()
AvailableTags.s
EndStructure
Procedure Destroy(*obj.TagReader_Class)
If *obj
FreeMap(*obj\Tags())
FreeMemory(*obj)
EndIf
EndProcedure
Procedure.s GetTagList(*obj.TagReader_Class)
If *obj
ProcedureReturn *obj\AvailableTags
EndIf
EndProcedure
Procedure.s GetContent(*obj.TagReader_Class, Tag.s)
If *obj
ProcedureReturn *obj\Tags(Tag)
EndIf
EndProcedure
Procedure New_MP3TagObj(FileName.s)
; fixed: Reading Unicode Tags (ID3v2.x) by Thorsten1867
Protected *obj.TagReader_Class
Protected FF, i, pos, size, TextEncoding.b, ID3.TagReader
Protected frame, FrameID.s, content.s, *mem, b
Dim genre.s(147)
If FileSize(FileName) <= 0 : ProcedureReturn #False : EndIf
*obj = AllocateMemory(SizeOf(TagReader_Class))
If *obj
InitializeStructure(*obj, TagReader_Class)
*obj\vTable = ?vTable
Restore genre
For i = 0 To 146
Read.s genre(i)
Next
FF = ReadFile(#PB_Any, FileName)
If FF
;{ ----- ID3v1 -----
FileSeek(FF, Lof(FF) - 128)
*mem = AllocateMemory(128)
If *mem
ReadData(FF, *mem, 128)
If PeekS(*mem, 3, #PB_Ascii) = "TAG"
content = Trim(PeekS(*mem + 3, 30, #PB_Ascii))
If content <> ""
*obj\Tags("TITLE") = content
*obj\AvailableTags + "TITLE" + #LF$
EndIf
content = Trim(PeekS(*mem + 33, 30, #PB_Ascii))
If content <> ""
*obj\Tags("ARTIST") = content
*obj\AvailableTags + "ARTIST" + #LF$
EndIf
content = Trim(PeekS(*mem + 63, 30, #PB_Ascii))
If content <> ""
*obj\Tags("ALBUM") = content
*obj\AvailableTags + "ALBUM" + #LF$
EndIf
content = Trim(PeekS(*mem + 93, 4, #PB_Ascii))
If content <> ""
*obj\Tags("YEAR") = content
*obj\AvailableTags + "YEAR" + #LF$
EndIf
content = Trim(PeekS(*mem + 97, 30, #PB_Ascii))
If content <> ""
*obj\Tags("COMMENT") = content
*obj\AvailableTags + "COMMENT" + #LF$
EndIf
b = PeekA(*mem + 126)
If b > 0
*obj\Tags("TRACK") = Str(b)
*obj\AvailableTags + "TRACK" + #LF$
EndIf
b = PeekA(*mem + 127)
If b > -1 And b < 147
*obj\Tags("GENRE") = genre(b)
*obj\AvailableTags + "GENRE" + #LF$
EndIf
EndIf
FreeMemory(*mem)
EndIf ;}
;{ ----- ID3v2.x -----
FileSeek(FF, 0)
ReadData(FF, @ID3, 6)
If PeekS(@ID3\ID[0], 3, #PB_Ascii) <> "ID3" ;{ kein ID3v2 vorhanden
CloseFile(FF)
If *obj\AvailableTags = ""
FreeMemory(*obj)
ProcedureReturn #False
Else
ProcedureReturn *obj
EndIf
EndIf ;}
For i = 3 To 0 Step -1
ID3\size + ReadAsciiCharacter(FF) << (7 * i)
Next
If ID3\size > 0
ID3\memory = AllocateMemory(ID3\size)
ReadData(FF, ID3\memory, ID3\size)
EndIf
CloseFile(FF)
If ID3\memory > 0
; --- FrameHeader (10 Byte) ---
Repeat
size = 0
frame = PeekL(ID3\memory + pos)
If frame
; FrameID (4 Byte)
FrameID = PeekS(@frame, 4, #PB_Ascii)
pos + SizeOf(Long)
If FrameID <> ""
; FrameSize (4 Byte)
For i = 3 To 0 Step -1
size + PeekA(ID3\memory + pos) << (7 * i)
pos + SizeOf(Ascii)
Next
; Flags (2 Byte)
pos + 2
; TextEncoding (1 Byte)
TextEncoding = PeekB(ID3\memory + pos)&$FF
pos + 1
; Content (size-1)
If pos + size <= ID3\size
If TextEncoding = 0
content = PeekS(ID3\memory + pos, size-1, #PB_Ascii)
ElseIf TextEncoding = 1
content = PeekS(ID3\memory + pos + 2, (size / 2) -1, #PB_Unicode)
EndIf
Else
Break
EndIf
pos + size - 1
If content <> ""
If Left(content, 1) <> Chr(255)
*obj\Tags(FrameID) = content
*obj\AvailableTags + FrameID + #LF$
EndIf
EndIf
EndIf
Else
Break
EndIf
Until pos >= ID3\size
*obj\AvailableTags = Left(*obj\AvailableTags, Len(*obj\AvailableTags) - 1)
FreeMemory(ID3\memory)
ProcedureReturn *obj
EndIf ;}
EndIf
EndIf
ProcedureReturn #False
EndProcedure
DataSection
vTable:
Data.i @Destroy()
Data.i @GetTagList()
Data.i @GetContent()
genre:
Data.s "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", "Hip-Hop", "Jazz", "Metal"
Data.s "New Age", "Oldies", "Other", "Pop", "R&B", "Rap", "Reggae", "Rock", "Techno", "Industrial"
Data.s "Alternative", "Ska", "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk"
Data.s "Fusion", "Trance", "Classical", "Instrumental", "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise"
Data.s "AlternRock", "Bass", "Soul", "Punk", "Space", "Meditative", "Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic"
Data.s "Darkwave", "Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta"
Data.s "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret", "New Wave", "Psychadelic", "Rave", "Showtunes"
Data.s "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock"
Data.s "Folk", "Folk-Rock", "National Folk", "Swing", "Fast Fusion", "Bebob", "Latin", "Revival", "Celtic", "Bluegrass"
Data.s "Avantgarde", "Gothic Rock", "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock", "Big Band", "Chorus", "Easy Listening", "Acoustic"
Data.s "Humour", "Speech", "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus", "Porn Groove"
Data.s "Satire", "Slow Jam", "Club", "Tango", "Samba", "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle"
Data.s "Duet", "Punk Rock", "Drum Solo", "Acapella", "Euro-House", "Dance Hall", "Goa", "Drum & Bass", "Club-House", "Hardcore", "Terror", "indie", "Brit Pop", "Negerpunk"
Data.s "Polsk Punk", "Beat", "Christian Gangsta Rap", "Heavy Metal", "Black Metal", "Crossover", "Comteporary Christian"
Data.s "Christian Rock", "Merengue", "Salsa", "Trash Metal", "Anime", "JPop", "Synth Pop"
EndDataSection
EndModule
CompilerIf #PB_Compiler_IsMainFile
EnableExplicit
Define.s MP3, tList
Define.i i, c
Define.TagReader::iTagReader TR
MP3 = OpenFileRequester("", "Select MP3 File", "MP3 Files (*.mp3)|*.mp3", 0)
If MP3 <> ""
TR = TagReader::New_MP3TagObj(MP3)
If TR
tList = TR\GetTagList()
c = CountString(tList, #LF$)
For i = 1 To c
Debug StringField(tList, i, #LF$) + " " + TR\GetContent(StringField(tList, i, #LF$))
Next
TR\Destroy()
EndIf
EndIf
CompilerEndIf