Simple ID3v2.3.x Tag Reader for MP3 Files

Share your advanced PureBasic knowledge/code with the community.
ricardo
Addict
Addict
Posts: 2438
Joined: Fri Apr 25, 2003 7:06 pm
Location: Argentina

Post by ricardo »

KarLKoX wrote:

Code: Select all

Structure ID3TagV1Tag
     tag.s
     title.s
     artist.s
     album.s
     year.s
     comments.s
     genre.s
     track.s
EndStructure

#READ_INPUT_FILE_TAG          = 1
#WRITE_INPUT_FILE_TAG         = 2

Procedure.s padString(theString.s, dummy.b)
Protected m_idx.b
Protected m_lent.l
Protected m_newString.s

     If dummy
          m_len = 28
     Else
          m_len = 30
     EndIf
     
     m_newString = theString
     For m_idx = Len(theString) To m_len
          m_newString + Chr(0)
     Next m_idx
     Debug "m_newString.s : " + m_newString.s

     ProcedureReturn m_newString

EndProcedure

;---- HasTagV1
; Purpose: Check if a Tag V1.x exists
; Require: file ==> input file
; Return : #TRUE if the tag exists
;          #FALSE otherwise
Procedure HasTagV1(file.s)
Protected hOrgFile.l
Protected m_tag.s

     hOrgFile = ReadFile(#pb_any, file)
     If (hOrgFile <= 0)
          MessageRequester("HasTagV1::Error", "Error occured while reading " + file, 0)
          ProcedureReturn #FALSE
     EndIf     
     FileSeek(Lof()-128)
     m_tag = Space(3)
     ReadData(@m_tag, 3)
     ; Rewind
     FileSeek(0)
     CloseFile(hOrgFile)
    
     If (m_tag = "TAG")
         ProcedureReturn #TRUE
     Else
         ProcedureReturn #FALSE
     EndIf
    
EndProcedure

;---- ReadTagV1
; Purpose: Read a IDTag V1.0/1.1
; Require: file ==> input file
; Return : fill the m_tagV1Info structure if the tag exist
Procedure.b ReadTagV1(file.s)
Protected hOrgFile.l
Dim        m_temp.b(128)

     If HasTagV1(file) = #FALSE
        ;MessageRequester("Error", "No IdTagV1 found.", 0)
        ProcedureReturn #FALSE
     EndIf
    
     hOrgFile = ReadFile(#READ_INPUT_FILE_TAG, file)
     If (hOrgFile <= 0)
          MessageRequester("ReadTagV1::Error", "Error occured while reading " + file, 0)
        ProcedureReturn #FALSE
     EndIf
     FileSeek(Lof()-128)
     ReadData(@m_temp(), 128)
     CloseFile(#READ_INPUT_FILE_TAG)
            
     m_tagV1Info\tag           = PeekS(m_temp(),3)
     m_tagV1Info\title         = PeekS(m_temp()+3,30)
     m_tagV1Info\artist        = PeekS(m_temp()+33,30)
     m_tagV1Info\album         = PeekS(m_temp()+63,30)
     m_tagV1Info\year          = PeekS(m_temp()+93,4)
     m_tagV1Info\comments      = PeekS(m_temp()+97,30)
     ; IdTag V1.1 extension : the last comments byte is the track number
     If Right(m_tagV1Info\comments, 1) <> ""
         m_tagV1Info\track = PeekS(m_temp()+126, 1) ;Right(m_tagV1Info\comments, 1)
     EndIf
     m_tagV1Info\genre = Chr(PeekB(m_temp()+127))

     ProcedureReturn #TRUE
EndProcedure

;---- WriteTagV1
; Purpose: Write a IDtag V1.0/1.1
; Require: file ==> input file
;          bRemove ==> #TRUE if you want only to remove the tag
;                      #FALSE otherwise
; Return : nothing
Procedure WriteTagV1(file.s, bRemove.b, *theTag.ID3TagV1Tag)
Protected hOrgFile.l
Protected m_compteur.l
Protected m_ID3.s
Protected m_offset.l

     If HasTagV1(fichier)
       m_offset = 128 
     Else
      m_offset = 0
     EndIf
    
     hOrgFile = OpenFile(#WRITE_INPUT_FILE_TAG, file)
     If (hOrgFile = 0)
          MessageRequester("WriteTagV1::Error", "Error occured while reading " + file, 0)
          ProcedureReturn
     EndIf
     
     UseFile(#WRITE_INPUT_FILE_TAG)
     FileSeek(Lof()-m_offset)
     If bRemove = #FALSE
        m_ID3 = Space(3)
        m_ID3 = "TAG"
        WriteData(@m_ID3, 3)
        WriteData(*theTag\title, 30)
        WriteData(*theTag\artist, 30)
        WriteData(*theTag\album, 30)
        WriteData(*theTag\year, 4)
        ; Tag 1.1 extension : write the track
        If (Str(*theTag\track) <> "")
          dummy$ = padString(*theTag\comments, #TRUE)
          WriteData(@dummy$, 28)
          WriteByte(0)
          WriteByte(Val(*theTag\track))
        Else
          WriteData(padString(*theTag\comments, #FALSE), 30)
        EndIf
        WriteByte(Val(*theTag\genre))
     EndIf
    
     CloseFile(#WRITE_INPUT_FILE_TAG)
    
EndProcedure

If i write tags 2 and then try to read them it crashes.

Any help?
Post Reply