ID3v2.3 Tags auslesen

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
a14xerus
Beiträge: 1440
Registriert: 14.12.2005 15:51
Wohnort: Aachen

ID3v2.3 Tags auslesen

Beitrag von a14xerus »

Hier ist ein Grundgerüst um die ID3v2(.3) Tags auszulesen
Ob es ASCII oder Unicode ist, wird für jeden Frame erkannt.
Die ExeDatei selber sollte nicht Unicode sein

Code: Alles auswählen

; ID3 Example for PB 4.xx
; Coder: 'a14xerus' (http://www.alexander-n.de)
; with friendly support of 'Padde'
; 06.06.2007
; Reference for ID3v2: http://www.id3.org/id3v2.3.0
EnableExplicit


UseJPEGImageDecoder()
UsePNGImageDecoder()


Structure Tags ; Only a few Tags, a list of all tags on http://www.id3.org
  Title.s     ; "TIT2"
  Artist.s    ; "TPE1"
  Album.s     ; "TALB"
  Year.s      ; ...
  Genre.s
  URL.s
  Copyright.s
  track.s
  image.l
EndStructure

Global Tags.Tags
Global file.s = OpenFileRequester("","","MP3|*.mp3",0)


Procedure GetID3v1Tag(Filename.s,*infos.Tags)
  Protected *mem, header$, Result.l
  If ReadFile(0,Filename)
    *mem =  AllocateMemory(128) ; allocate 128 byte
    If *mem
      FileSeek(0,Lof(0)-128)
      ReadData(0,*mem , 128)    ; read the last 128 byte
      header$ = PeekS(*mem , 3)
      If header$ = "TAG"                              ;  3 chars
        With *infos
          \Title     = Trim(PeekS(*mem  +   3, 30))   ; 30 chars
          \Artist    = Trim(PeekS(*mem  +  33, 30))   ; 30 chars
          \Album     = Trim(PeekS(*mem  +  63, 30))   ; 30 chars
          \Year      = Trim(PeekS(*mem  +  93,  4))   ;  4 chars
          ; \Comment   = Trim(PeekS(*mem  +  97, 29))   ; 30 chars
          \track     = Trim(PeekS(*mem  + 126,  1))   ;  1 chars
          \Genre     = Trim(PeekS(*mem  + 127,  1))   ;  1 chars
        EndWith
        Result = #True
      EndIf
      FreeMemory(*mem)
    EndIf
    CloseFile(0)
  EndIf
  ProcedureReturn Result
EndProcedure


Procedure frameTXXX(id.s, FrameSize.l, *infos.Tags)
  Protected TextEncoding.b, *mem, Contents.s
  
  TextEncoding = ReadByte(0)&$FF ; TXXX Textencoding
  FrameSize - 1 ; subtract TextEncoding-Byte from size
  If FrameSize <= 0
    ProcedureReturn #False
  EndIf
  *mem = AllocateMemory(FrameSize)
  ReadData(0,*mem, FrameSize)
  If TextEncoding = 0
    Contents = PeekS(*mem,FrameSize,#PB_Ascii)
  ElseIf TextEncoding = 1
    Contents = PeekS(*mem+2,FrameSize-2,#PB_UTF16)
  EndIf
  FreeMemory(*mem)
  
  With *infos
    Select id
      Case "TIT2"
        \Title = Contents
      Case "TPE1"
        \Artist = Contents
      Case "TALB"
        \Album = Contents
      Case "TYER"
        \Year = Contents
      Case "TCON"
        \Genre = Contents
      Case "TCOP"
        \Copyright = Contents
      Case "TRCK"
        \track = Contents
    EndSelect
  EndWith
  ProcedureReturn #True
EndProcedure
Procedure frameWXXX(id.s, FrameSize.l, *infos.Tags)
  Protected Contents.s
  ReadByte(0) ; WXXX Textencoding for Description (URLs are allways ASCII)
  FrameSize - 1
  If FrameSize <= 0
    ProcedureReturn #False
  EndIf
  Contents = Space(FrameSize)
  ReadData(0,@Contents, FrameSize)
  *infos\URL = Contents
  ProcedureReturn #True
EndProcedure
Procedure frameAPIC(id.s, FrameSize.l, *infos.Tags)
  Protected TextEncoding.b, tmp.l, *mem
  tmp = Loc(0)
  TextEncoding = ReadByte(0) ; APIC Textencoding
  If TextEncoding = 0
    ReadString(0,#PB_Ascii) ; APIC MIME (ASCII)
  ElseIf TextEncoding = 1
    ReadString(0,#PB_UTF16) ; APIC MIME (UTF16 / Unicode)
  EndIf
  If ReadByte(0)&$FF = $03 ; APIC Picture Typ ($03 = Cover front) (for overview look at http://www.id3.org)
    If TextEncoding = 0
      ReadString(0,#PB_Ascii) ; APIC Description (ASCII)
    ElseIf TextEncoding = 1
      ReadString(0,#PB_UTF16) ; APIC Description (UTF16)
    EndIf
    FrameSize - (Loc(0)-tmp) ; subtract the desciptions from the framesize to get the picturesize
    *mem = AllocateMemory(FrameSize)
    ReadData(0,*mem, FrameSize)
    *infos\image = CatchImage(-1,*mem,FrameSize,#PB_Image_DisplayFormat)
    FreeMemory(*mem)
  EndIf
EndProcedure

Procedure GetID3v2Tag(Filename.s,*infos.Tags)
  Protected ID3.s, ID3Size, Byte.l, Size.l, FrameID.s, FrameSize.l, location.l
  If ReadFile(0,Filename)
    ID3.s = Space(3)
    ReadData(0,@ID3, 3)
    If ID3 = "ID3" And ReadByte(0) = $03 ; must be ID3v2.3.x !
      ReadByte(0) ; Revision  (not needed)
      ReadByte(0) ; Flags     (not needed)
      ID3Size = 0             ; get hole Size of ID3Tag
      ID3Size = ReadLong(0)
      ID3Size = ((ID3Size&$FF)<<24)+((ID3Size&$FF00)<<8)+((ID3Size&$FF0000)>>8)+((ID3Size>>24)&$FF)
    Else
      ; no ID3v2.3.x tag present
      CloseFile(0)
      ProcedureReturn #False
    EndIf
    
    Size.l = 0
    Repeat
      ; examine All frames
      
      ; / Frameheader starts
      FrameID.s = Space(4) 
      ReadData(0,@FrameID, 4)   ; Read FrameID (allways 4 chars)
      
      If Asc(Left(FrameID, 1)) = 0
        CloseFile(0)
        ProcedureReturn #True
      EndIf
      
      FrameSize = 0
      FrameSize = ReadLong(0)   ; get framesize ( the framesize is the size of the values excluding the frameheader)
      FrameSize = ((FrameSize&$FF)<<24)+((FrameSize&$FF00)<<8)+((FrameSize&$FF0000)>>8)+((FrameSize>>24)&$FF)
      Size + FrameSize
      
      ReadByte(0): ReadByte(0) ; Frame Flags (not needed)
      
      If FrameSize < 1 :  ProcedureReturn #False : EndIf
      
      ; \ Frameheader ends (Frameheader allways 10 Bytes)
      
      location = Loc(0) + FrameSize ; set 'location'value to end of the actual frame
      
      ; / Framebody starts
      
      Select FrameID  ; Read teh FrameID (Overview on http://www.id3.org)
        Case "TIT2", "TPE1", "TALB", "TYER", "TCON", "TCOP", "TRCK"
          frameTXXX(FrameID, FrameSize, *infos)
        Case "WXXX"
          frameWXXX(FrameID, FrameSize, *infos)
        Case "APIC"
          frameAPIC(FrameID, FrameSize, *infos)
      EndSelect
      
      ; \ Framebody ends
      
      FileSeek(0,location) ; Jump to the end of the frame.
      ; (if something went wrong nevertheless you are at the right location in the file)
      
    Until Size >= ID3Size ; stop if tag size reached/exceeded 
    CloseFile(0)
  EndIf
EndProcedure
 

Procedure GetID3Tag(Filename.s,*infos.Tags)
  With *infos ; delete the old settings
    \Album = ""
    \Artist = ""
    \Copyright = ""
    \Genre = ""
    \Title = ""
    \track = ""
    \URL = ""
    \Year = ""
    If \image
      FreeImage(\image)
    EndIf
    \image = 0
  EndWith
  
  If Not Filename
    ProcedureReturn #False
  EndIf
  
  GetID3v1Tag(Filename,*infos) ; if there are old ID3v1 Tags, read them out
  GetID3v2Tag(Filename,*infos) ; read the new Version (ID3v2)
EndProcedure
 


GetID3Tag(file,@Tags)

;- DEMO:

With Tags
  Debug "Album: "+\Album
  Debug "Artist: "+\Artist
  Debug "Copyright: "+\Copyright
  Debug "Genre: "+\Genre
  Debug "Title: "+\Title
  Debug "Track: "+\track
  Debug "URL: "+\URL
  Debug "Year: "+\Year
EndWith
If Tags\image
  If OpenWindow(0,0,0,200,200,"")
    If CreateGadgetList(WindowID(0))
      ImageGadget(0,0,0,200,200,ImageID(Tags\image))
      While WaitWindowEvent() <> 16 : Wend
    EndIf
  EndIf
EndIf
Zuletzt geändert von a14xerus am 06.06.2007 19:13, insgesamt 1-mal geändert.
Benutzeravatar
Vermilion
Beiträge: 1846
Registriert: 08.04.2006 16:00
Computerausstattung: Apple iMac (2010) & HP Notebook
Wohnort: Heidekreis

Beitrag von Vermilion »

Läuft! :allright:
Bild

Immer die neueste PureBasic Version. Auf allem Betriebssystemen. Ich bin ein OS-Nomad!
es_91
Beiträge: 383
Registriert: 25.01.2011 04:48

Re: ID3v2.3 Tags auslesen

Beitrag von es_91 »

Vielen, vielen Dank!! :lurk:
Franky_FR
Beiträge: 53
Registriert: 08.05.2019 10:06

Re: ID3v2.3 Tags auslesen

Beitrag von Franky_FR »

Weiß jemand, warum der Code mit PB 5.73 x64 nicht mehr funktioniert ? Nur leere Felder ! Ich vermute wegen Unicode ?

// Edit: Full-Quote entfernt (Kiffi)
Benutzeravatar
mk-soft
Beiträge: 3695
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: ID3v2.3 Tags auslesen

Beitrag von mk-soft »

.l nach .i

PeekS(..., Len, #PB_Ascii)
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
HeX0R
Beiträge: 2954
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win10 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2
Kontaktdaten:

Re: ID3v2.3 Tags auslesen

Beitrag von HeX0R »

War es jetzt echt nötig den ganzen Code mit ins Zitat zu nehmen?
Franky_FR
Beiträge: 53
Registriert: 08.05.2019 10:06

Re: ID3v2.3 Tags auslesen

Beitrag von Franky_FR »

Vermutlich nicht, aber die Frage bezog sich ja darauf. Natürlich kann man auch drei Posts nach oben scrollen ... :)
Aber hat das irgendwelche Nachteile ? Habe ich bisher nicht drüber nachgedacht.
Benutzeravatar
HeX0R
Beiträge: 2954
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win10 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2
Kontaktdaten:

Re: ID3v2.3 Tags auslesen

Beitrag von HeX0R »

Beim Zitieren versucht man sich nur auf relevante Dinge zu beziehen.
So ein Beitrag wird beim lesen schnell unangenehm, wenn dort überall irrelevanter Text oder Code auftaucht.
Richtig schlimm wird es für die, die StarGates Browsererweiterung nutzen, dort wird der Code dann nämlich nicht als kleiner iFrame angezeigt, sondern in voller Länge.
Dort musst Du dann unnötig lange nach unten scrollen, um für die Diskussion relevante Dinge zu finden.
Benutzeravatar
Kiffi
Beiträge: 10621
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: ID3v2.3 Tags auslesen

Beitrag von Kiffi »

<OT>Ich habe das Voll-Zitat mal entfernt</OT>
Hygge
Franky_FR
Beiträge: 53
Registriert: 08.05.2019 10:06

Re: ID3v2.3 Tags auslesen

Beitrag von Franky_FR »

HeX0R hat geschrieben: 24.06.2021 21:29 Richtig schlimm wird es für die, die StarGates Browsererweiterung nutzen, dort wird der Code dann nämlich nicht als kleiner iFrame angezeigt, sondern in voller Länge.
Dort musst Du dann unnötig lange nach unten scrollen, um für die Diskussion relevante Dinge zu finden.
Ach, alles klar, dann weiß ich Bescheid.
Antworten