Kann da jemand helfen ?
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()
;- Constants
#ID3_BinaryReturn=0
#ID3_ImageReturn=1
;- Structures
Structure TagV1 ; Only a few Tags, a list of all tags on http://www.id3.org
tag.s
title.s ; "TIT2"
artist.s ; "TPE1"
album.s ; "TALB"
year.s ; ...
genre.s
URL.s
Copyright.s
track.s
EndStructure
Structure TagV2 ; 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
lyrics.s
image.l
EndStructure
Global Tags.TagV2
Global TagV1.TagV1
;- ID3 Tag Version 1 Read
Procedure GetID3v1Tag(filename.s,*infos.TagV1)
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
;- ID3 Tag Version 2 Procedures
Procedure frameTXXX(id.s, FrameSize.l, *infos.TagV2)
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", "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.TagV2)
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.TagV2)
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 FrameUSLT(id.s, FrameSize.l, *infos.TagV2) ; Hacked together by Localmotion34 - Props to a14xerus for finding Framseize code that WORKS
Protected TextEncoding.b, tmp.l, *mem
tmp = Loc(0)
TextEncoding = ReadByte(0) ; USLT Textencoding
If TextEncoding = 0
ReadString(0,#PB_Ascii) ; APIC MIME (ASCII)
ElseIf TextEncoding = 1
ReadString(0,#PB_UTF16) ; APIC MIME (UTF16 / Unicode)
EndIf
FrameSize -(Loc(0)-tmp) ; subtract the desciptions from the framesize to get the picturesize
If FrameSize>0
*mem = AllocateMemory(FrameSize)
ReadData(0,*mem, FrameSize)
*infos\lyrics = PeekS(*mem,FrameSize)
FreeMemory(*mem)
Else
*infos\lyrics =""
EndIf
EndProcedure
Procedure GetID3v2Tag(filename.s,*infos.TagV2)
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
;;; F*ck you Id3lib.org. your Sh*t documentation makes it IMPOSSIBLE to get correct frame sizes
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) ; props to a14xerus
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", "TPE2"
frameTXXX(FrameID, FrameSize, *infos)
Case "WXXX"
frameWXXX(FrameID, FrameSize, *infos)
Case "APIC"
frameAPIC(FrameID, FrameSize, *infos)
Case "USLT"
FrameUSLT(FrameID, FrameSize, *infos)
; Debug "found lyrics"
; Debug FrameSize
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.TagV1, *info.TagV2)
With *info ; delete the old settings
\album = ""
\artist = ""
\Copyright = ""
\genre = ""
\title = ""
\track = ""
\URL = ""
\year = ""
\lyrics=""
If \image
FreeImage(\image)
EndIf
\image = 0
EndWith
If filename=""
ProcedureReturn #False
EndIf
Debug "Datei zum bearbeiten ist "+filename
GetID3v1Tag(filename,*infos) ; if there are old ID3v1 Tags, read them out
GetID3v2Tag(filename,*info) ; read the new Version (ID3v2)
EndProcedure
;- Lower Level Procedures for ID3 Tag Version 2 Reading
Procedure frameAPICReturn(id.s, FrameSize.l, *infos.TagV2, BinaryOrImage)
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)
Select BinaryOrImage
Case 0
ProcedureReturn *mem
Case 1
*infos\image = CatchImage(-1,*mem,FrameSize,#PB_Image_DisplayFormat)
FreeMemory(*mem)
ProcedureReturn *infos\image
EndSelect
EndIf
EndProcedure
Procedure ID3GetImage(filename.s) ; Returns a HBITMAP
Protected ID3.s, ID3Size, byte.l, Size.l, FrameID.s, FrameSize.l, Location.l, *infos.TagV2
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
*infos.TagV2=AllocateMemory(SizeOf(TagV2))
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) ; props to a14xerus
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
Case "APIC"
returnimage.l=frameAPICReturn(FrameID, FrameSize, *infos, #ID3_ImageReturn)
Break
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)
FreeMemory(*infos)
ProcedureReturn returnimage
EndIf
EndProcedure
Procedure ID3GetImageBinaryData(filename.s);Returns compressed image data--YOU have to decode it and/or write it to a file!!!!!!
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
*infos.TagV2=AllocateMemory(SizeOf(TagV2))
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) ; props to a14xerus
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
Case "APIC"
imagemem.l=frameAPICReturn(FrameID, FrameSize, *infos, #ID3_BinaryReturn)
Break
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)
FreeMemory(*infos)
ProcedureReturn imagemem
EndIf
EndProcedure
Procedure.s FrameUSLTreturn(id.s, FrameSize.l, *infos.TagV2) ; Hacked together by Localmotion34 - Props to a14xerus for finding Framseize code that WORKS
Protected TextEncoding.b, tmp.l, *mem
tmp = Loc(0)
TextEncoding = ReadByte(0) ; USLT Textencoding
If TextEncoding = 0
ReadString(0,#PB_Ascii) ; APIC MIME (ASCII)
ElseIf TextEncoding = 1
ReadString(0,#PB_UTF16) ; APIC MIME (UTF16 / Unicode)
EndIf
FrameSize -(Loc(0)-tmp) ; subtract the desciptions from the framesize to get the picturesize
If FrameSize>0
*mem = AllocateMemory(FrameSize)
ReadData(0,*mem, FrameSize)
*infos\lyrics = PeekS(*mem,FrameSize)
FreeMemory(*mem)
ProcedureReturn *infos\lyrics
Else
*infos\lyrics =""
ProcedureReturn ""
EndIf
EndProcedure
Procedure.s ID3GetSongLyrics(filename.s)
Protected ID3.s, ID3Size, byte.l, Size.l, FrameID.s, FrameSize.l, Location.l, *infos.TagV2
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 ""
EndIf
*infos.TagV2=AllocateMemory(SizeOf(TagV2))
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) ; props to a14xerus
Size + FrameSize
ReadByte(0): ReadByte(0) ; Frame Flags (not needed)
If FrameSize < 1 : ProcedureReturn "" : EndIf
; \ Frameheader ends (Frameheader allways 10 Bytes)
Location = Loc(0) + FrameSize ; set 'location'value to end of the actual frame
; / Framebody starts
Select FrameID
Case "USLT"
returntext.s=FrameUSLTreturn(FrameID, FrameSize, *infos)
Break
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)
FreeMemory(*infos)
If Len(returntext)>0
ProcedureReturn returntext
Else
ProcedureReturn ""
EndIf
EndIf
EndProcedure
;- DEMO Useage
If OpenWindow(0, 259, 217, 855, 388, "ID3 Tags", #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered)
ListIconGadget(20,5,40,200,300,"MP3 File",180,#PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect|#PB_ListIcon_AlwaysShowSelection)
hwnd = ImageGadget(40,220,40,300,300,0,#PB_Image_Border) ; AKJ
ButtonGadget(1,240,10,90,25,"Open MP3") ; AKJ Cater for large fonts
ButtonGadget(2,40,10,90,25,"Select Files")
ButtonGadget(3,140,10,90,25,"Get ID3 Image")
ButtonGadget(4,340,10,140,25,"Extract Selected ID3 Image")
ButtonGadget(5,490,10,140,25,"Extract Selected Lyrics")
EditorGadget(50,530,40,300,300,#PB_Editor_ReadOnly)
EndIf
Repeat
Select WaitWindowEvent()
Case #PB_Event_Gadget
Select EventGadget()
Case 1 ; Button gadget
MP3File.s = OpenFileRequester("Select MP3 File", "", "MP3 Files (*.mp3)|*.mp3", 0)
Debug MP3File
If MP3File
GetID3Tag(MP3File,@TagV1,@Tags)
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
Debug \lyrics
EndWith
If Tags\image
ResizeImage(Tags\image,300,300,#PB_Image_Smooth)
SetGadgetState(40,ImageID(Tags\image))
Else
SetGadgetState(40,0)
EndIf
If Tags\lyrics
SetGadgetText(50,Tags\lyrics)
Else
SetGadgetText(50,"")
EndIf
EndIf
Case 2
mp3files$= OpenFileRequester("Select MP3 File", "", "MP3 Files (*.mp3)|*.mp3", 0,#PB_Requester_MultiSelection)
If mp3files$
ClearGadgetItems(20)
While mp3files$
mp3files$ = NextSelectedFileName()
AddGadgetItem(20,-1,mp3files$)
Wend
EndIf
Case 3
MP3File.s = OpenFileRequester("Select MP3 File", "", "MP3 Files (*.mp3)|*.mp3", 0)
pbimage=ID3GetImage(MP3File)
If pbimage
ResizeImage(pbimage,300,300,#PB_Image_Smooth)
SetGadgetState(40,ImageID(pbimage))
EndIf
Case 4
JPEGFile.s = SaveFileRequester("Save ID3 Tag Image To File", "", "JPEG Files (*.jpg)|*.jpg", 0)
If JPEGFile
If GetExtensionPart(JPEGFile)<> LCase("jpg")
JPEGFile+".jpg"
EndIf
MP3File.s=GetGadgetItemText(20,GetGadgetState(20),0)
If FileSize(MP3File)>0
memorybuffer=ID3GetImageBinaryData(MP3File)
If CreateFile(10,JPEGFile)
WriteData(10,memorybuffer, MemorySize(memorybuffer))
CloseFile(10)
EndIf
EndIf
EndIf
Case 5
textFile.s = SaveFileRequester("Save ID3 Lyrics To File", "", "Text Files (*.txt)|*.txt", 0)
If textFile
If GetExtensionPart(textFile)<> LCase("txt")
textFile+".txt"
EndIf
MP3File.s=GetGadgetItemText(20,GetGadgetState(20),0)
If FileSize(MP3File)>0
text.s=ID3GetSongLyrics(MP3File)
If Len(text)>0
If CreateFile(10,textFile)
WriteData(10,@text, Len(text))
CloseFile(10)
EndIf
EndIf
EndIf
EndIf
Case 20
MP3File.s=GetGadgetItemText(20,GetGadgetState(20),0)
GetID3Tag(MP3File,@TagV1,@Tags)
If Tags\image
ResizeImage(Tags\image,300,300,#PB_Image_Smooth)
SetGadgetState(40,ImageID(Tags\image))
Else
SetGadgetState(40,0)
EndIf
If Tags\lyrics
SetGadgetText(50,Tags\lyrics)
Else
SetGadgetText(50,"")
EndIf
EndSelect
Case #PB_Event_Menu
Select EventMenu()
EndSelect
Case #PB_Event_CloseWindow
Quit=1
EndSelect
Until Quit=1