Imports System.Text.UTF8Encoding
Namespace Mp3
Public Enum Mp3Genre
Blues
Classic_Rock
Country
Dance
Disco
Funk
Grunge
Hip_Hop
Jazz
Metal
New_Age
Oldies
Other
Pop
R_And_B
Rap
Reggae
Rock
Techno
Industrial
Alternative
Ska
Death_Metal
Pranks
Soundtrack
Euro_Techno
Ambient
Trip_Hop
Vocal
Jazz_Funk
Fusion
Trance
Classical
Instrumental
Acid
House
Game
Sound_Clip
Gospel
Noise
AlternRock
Bass
Soul
Punk
Space
Meditative
Instrumental_Pop
Instrumental_Rock
Ethnic
Gothic
Darkwave
Techno_Industrial
Electronic
Pop_Folk
Eurodance
Dream
Southern_Rock
Comedy
Cult
Gangsta
Top_40
Christian_Rap
Pop_Funk
Jungle
Native_American
Cabaret
New_Wave
Psychadelic
Rave
Showtunes
Trailer
Lo_Fi
Tribal
Acid_Punk
Acid_Jazz
Polka
Retro
Musical
Rock_And_Roll
Hard_Rock
End Enum
Namespace ID3v1
Public Class General
Public Shared Function GetString(ByVal Bytes As Byte()) As String
Dim Result As New System.Text.StringBuilder
For Each B As Byte In Bytes
If B = 0 Then
Exit For
Else
Result.Append(Chr(B))
End If
Next
Return Result.ToString
End Function
Public Shared Function GetBytes(ByVal S As String, ByVal Len As Int32) As Byte()
Dim Buffer(Len - 1) As Byte
For I As Int16 = 0 To Len - 1
Buffer(I) = 0
Next
Dim Str() As Byte
If S Is Nothing Then
Str = New Byte() {0}
Else
Str = UTF8.GetBytes(S)
End If
If Str.Length < Len Then
Array.ConstrainedCopy(Str, 0, Buffer, 0, Str.Length)
Else
Array.ConstrainedCopy(Str, 0, Buffer, 0, Len)
End If
Return Buffer
End Function
End Class
Public Class ID3TagV1
Private _Title As String
Private _Artist As String
Private _Album As String
Private _Year As String
Private _Comment As String
Private _Genre As Mp3Genre
Public Property Title() As String
Get
Return _Title
End Get
Set(ByVal Value As String)
_Title = Value
End Set
End Property
Public Property Artist() As String
Get
Return _Artist
End Get
Set(ByVal Value As String)
_Artist = Value
End Set
End Property
Public Property Album() As String
Get
Return _Album
End Get
Set(ByVal Value As String)
_Album = Value
End Set
End Property
Public Property Year() As String
Get
Return _Year
End Get
Set(ByVal Value As String)
_Year = Value
End Set
End Property
Public Property Comment() As String
Get
Return _Comment
End Get
Set(ByVal Value As String)
_Comment = Value
End Set
End Property
Public Property Genre() As Mp3Genre
Get
Return _Genre
End Get
Set(ByVal Value As Mp3Genre)
_Genre = Value
End Set
End Property
Public Function Read
(ByVal File As String) As Boolean
Dim Stream
As New IO.
FileStream(File, IO.
FileMode.
Open)
Dim Buffer(127) As Byte
Stream.Seek(-128, IO.SeekOrigin.End)
Stream.Read(Buffer, 0, 128)
Stream.Close()
If Not (Buffer(0) = Asc("T") And Buffer(1) = Asc("A") And Buffer(2) = Asc("G")) Then
Return False
End If
Dim Temp() As Byte
ReDim Temp(29)
Array.ConstrainedCopy(Buffer, 3, Temp, 0, 30)
Me.Title = General.GetString(Temp)
Array.ConstrainedCopy(Buffer, 33, Temp, 0, 30)
Me.Artist = General.GetString(Temp)
Array.ConstrainedCopy(Buffer, 63, Temp, 0, 30)
Me.Album = General.GetString(Temp)
ReDim Temp(3)
Array.ConstrainedCopy(Buffer, 93, Temp, 0, 4)
Me.Year = General.GetString(Temp)
ReDim Temp(29)
Array.ConstrainedCopy(Buffer, 97, Temp, 0, 30)
Me.Comment = General.GetString(Temp)
Me.Genre = Buffer(127)
Return True
End Function
Public Sub Write(ByVal File As String)
Dim Stream
As New IO.
FileStream(File, IO.
FileMode.
Open)
Dim Buffer(127) As Byte
Stream.Seek(-128, IO.SeekOrigin.End)
Stream.Read(Buffer, 0, 128)
If Buffer(0) = Asc("T") And Buffer(1) = Asc("A") And Buffer(2) = Asc("G") Then
Stream.Seek(-128, IO.SeekOrigin.End)
Else
Stream.Seek(0, IO.SeekOrigin.End)
End If
With Stream
.WriteByte(Asc("T"))
.WriteByte(Asc("A"))
.WriteByte(Asc("G"))
.Write(General.GetBytes(Me.Title, 30), 0, 30)
.Write(General.GetBytes(Me.Artist, 30), 0, 30)
.Write(General.GetBytes(Me.Album, 30), 0, 30)
.Write(General.GetBytes(Me.Year, 4), 0, 4)
.Write(General.GetBytes(Me.Comment, 30), 0, 30)
.WriteByte(Me.Genre)
.Close()
End With
End Sub
End Class
End Namespace
Namespace ID3v2
Friend Class Functions
Friend Shared Function SizeToBytes(ByVal Number As Int32) As Byte()
Dim Buffer(3) As Byte
For Index As SByte = 3 To 0 Step -1
For E As SByte = 6 To 0 Step -1
If Number >= 2 ^ (Index * 7 + E) Then
Buffer(3 - Index) += 2 ^ E
Number -= 2 ^ (Index * 7 + E)
End If
Next
Next
Return Buffer
End Function
Friend Shared Function BytesToSize(ByVal Bytes() As Byte) As Int32
Dim Result As Int32
For Index As SByte = 3 To 0 Step -1
For E As SByte = 6 To 0 Step -1
If (Bytes(3 - Index) And 2 ^ E) = 2 ^ E Then
Result += 2 ^ (Index * 7 + E)
End If
Next
Next
Return Result
End Function
Friend Shared Function ReadString(ByVal OpenStream As IO.BinaryReader) As String
Dim B As Byte
Dim Temp As New System.Text.StringBuilder
B = OpenStream.ReadByte
Do While B > 0
Temp.Append(Chr(B))
B = OpenStream.ReadByte
Loop
Return Temp.ToString
End Function
Friend Shared Sub WriteString(ByVal OpenStream As IO.BinaryWriter, ByVal S As String, Optional ByVal Terminator As Boolean = True)
For Each C As Char In S
OpenStream.Write(C)
Next
If Terminator Then
OpenStream.Write(CByte(0))
End If
End Sub
End Class
Public Class FrameHeader
<Flags()> _
Public Enum HeaderFlags
PreserveFrame = 0
PreserveFile = 1
[ReadOnly] = 2
Compression = 4
Encryption = 8
Grouping = 16
End Enum
Private _Identifier As String
Private _DataSize As Int32
Private _Flags As HeaderFlags
Public Property Identifier() As String
Get
Return _Identifier
End Get
Set(ByVal Value As String)
_Identifier = Value
End Set
End Property
Public Property DataSize() As Int32
Get
Return _DataSize
End Get
Set(ByVal Value As Int32)
_DataSize = Value
End Set
End Property
Public Property Flags() As HeaderFlags
Get
Return _Flags
End Get
Set(ByVal Value As HeaderFlags)
_Flags = Value
End Set
End Property
Sub New(ByVal ID As String)
Me.Identifier = ID
End Sub
Sub New()
End Sub
Public Function Read(ByVal OpenStream As IO.BinaryReader) As Boolean
Try
Me.Identifier = OpenStream.ReadChars(4)
Me.DataSize = Functions.BytesToSize(OpenStream.ReadBytes(4))
Dim Buffer() As Byte = OpenStream.ReadBytes(2)
'Primi 3 bit del byte 1
If (Buffer(0) And 128) = 128 Then
Me.Flags = Me.Flags Or HeaderFlags.PreserveFrame
End If
If (Buffer(0) And 64) = 64 Then
Me.Flags = Me.Flags Or HeaderFlags.PreserveFile
End If
If (Buffer(0) And 32) = 32 Then
Me.Flags = Me.Flags Or HeaderFlags.ReadOnly
End If
'Primi 3 bit del byte 2
If (Buffer(1) And 128) = 128 Then
Me.Flags = Me.Flags Or HeaderFlags.Compression
End If
If (Buffer(1) And 64) = 64 Then
Me.Flags = Me.Flags Or HeaderFlags.Encryption
End If
If (Buffer(1) And 32) = 32 Then
Me.Flags = Me.Flags Or HeaderFlags.Grouping
End If
Return True
Catch ex As Exception
Return False
End Try
End Function
Public Sub Write(ByVal OpenStream As IO.BinaryWriter)
With OpenStream
Functions.WriteString(OpenStream, Me.Identifier, False)
.Write(Functions.SizeToBytes(Me.DataSize))
Dim Buffer(1) As Byte
If (Me.Flags And HeaderFlags.PreserveFrame) = HeaderFlags.PreserveFrame Then
Buffer(0) += 128
End If
If (Me.Flags And HeaderFlags.PreserveFile) = HeaderFlags.PreserveFile Then
Buffer(0) += 64
End If
If (Me.Flags And HeaderFlags.ReadOnly) = HeaderFlags.ReadOnly Then
Buffer(0) += 32
End If
If (Me.Flags And HeaderFlags.Compression) = HeaderFlags.Compression Then
Buffer(1) += 128
End If
If (Me.Flags And HeaderFlags.Encryption) = HeaderFlags.Encryption Then
Buffer(1) += 64
End If
If (Me.Flags And HeaderFlags.Grouping) = HeaderFlags.Grouping Then
Buffer(1) += 32
End If
.Write(Buffer)
End With
End Sub
End Class
Public MustInherit Class Frame
Protected Const Null As Byte = 0
Private _Header As FrameHeader
Private _Description As String
Protected
Shared _DefaultDescriptions
As New Dictionary(Of
String,
String)
Public Property Header() As FrameHeader
Get
Return _Header
End Get
Set(ByVal value As FrameHeader)
_Header = value
End Set
End Property
Public ReadOnly Property Description() As String
Get
Return _Description
End Get
End Property
Public ReadOnly Property Size() As Int32
Get
Me.CalculateSize()
Return 10 + Me.Header.DataSize
End Get
End Property
Protected
Shared ReadOnly Property DefaultDescriptions
() As Dictionary(Of
String,
String)
Get
Return _DefaultDescriptions
End Get
End Property
Shared Sub New()
With DefaultDescriptions
.Add("TALB", "Album")
.Add("TCOM", "Compositore")
.Add("TCON", "Genere Musicale")
.Add("TCOP", "Copyright (C)")
.Add("TDAT", "Data registrazione")
.Add("TENC", "Prodotto da")
.Add("TEXT", "Autore testi")
.Add("TIME", "Durata")
.Add("TIT1", "Tipologia")
.Add("TIT2", "Titolo")
.Add("TIT3", "Sottotitolo")
.Add("TKEY", "Tonalità")
.Add("TLAN", "Lingua")
.Add("TPE1", "Artista principale")
.Add("TPE2", "Orchestra/Band")
.Add("TPE3", "Direttore d'Orchestra")
.Add("TPE4", "Remixato da")
.Add("TPUB", "Casa discografica")
.Add("TRCK", "Traccia")
.Add("TSRC", "Codice registrazione")
.Add("TSSE", "Hardware/Software utilizzati")
.Add("TYER", "Anno registrazione")
.Add("WCOM", "Home page CD")
.Add("WCOP", "Termini Copyright")
.Add("WOAR", "Sito ufficiale")
End With
End Sub
Protected Sub SetDescription()
If (Not String.IsNullOrEmpty(Me.Header.Identifier)) AndAlso DefaultDescriptions.ContainsKey(Me.Header.Identifier) Then
_Description = DefaultDescriptions(Me.Header.Identifier)
End If
End Sub
Friend Sub Initialize(ByVal Header As FrameHeader)
Me.Header = Header
Me.SetDescription()
End Sub
Protected MustOverride Sub CalculateSize()
Public MustOverride Function Read(ByVal OpenStream As IO.BinaryReader) As Boolean
Public MustOverride Sub Write(ByVal OpenStream As IO.BinaryWriter)
End Class
Public Class TextFrame
Inherits Frame
Private _Text As String
Public Property Text() As String
Get
Return _Text
End Get
Set(ByVal value As String)
_Text = value
End Set
End Property
Sub New(ByVal ID As String)
Me.Header = New FrameHeader
Me.Header.Identifier = ID
Me.SetDescription()
End Sub
Sub New(ByVal Header As FrameHeader)
Me.Header = Header
Me.SetDescription()
End Sub
Sub New()
End Sub
Protected Overrides Sub CalculateSize()
Me.Header.DataSize = Me.Text.Length + 2
End Sub
Public Overrides Function Read(ByVal OpenStream As System.IO.BinaryReader) As Boolean
Try
'Salta il byte di codifica
OpenStream.ReadByte()
'Legge il testo
Me.Text = Functions.ReadString(OpenStream)
Return True
Catch ex As Exception
Return False
End Try
End Function
Public Overrides Sub Write(ByVal OpenStream As System.IO.BinaryWriter)
Me.CalculateSize()
Me.Header.Write(OpenStream)
OpenStream.Write(CByte(0))
Functions.WriteString(OpenStream, Me.Text)
End Sub
End Class
Public Class InvolvedPeopleFrame
Inherits Frame
Private _PeopleList
As New Dictionary(Of
String,
String)
Public ReadOnly Property PeopleList
() As Dictionary(Of
String,
String)
Get
Return _PeopleList
End Get
End Property
Public Shared ReadOnly Property DefaultID() As String
Get
Return "IPLS"
End Get
End Property
Sub New(ByVal Header As FrameHeader)
Me.Header = Header
Me.SetDescription()
End Sub
Sub New(ByVal ID As String)
Me.New(New FrameHeader(ID))
End Sub
Sub New()
Me.New(DefaultID)
End Sub
Protected Overrides Sub CalculateSize()
Me.Header.DataSize = 0
For Each K As String In Me.PeopleList.Keys
Me.Header.DataSize += (K.Length + Me.PeopleList(K).Length + 2)
Next
End Sub
Public Overrides Function Read(ByVal OpenStream As System.IO.BinaryReader) As Boolean
Try
Dim Buffer() As Byte = OpenStream.ReadBytes(Me.Header.DataSize)
Dim StringBuffer As New List(Of String)
Dim Temp As New System.Text.StringBuilder
For I As Int32 = 0 To Buffer.Length - 1
If Buffer(I) = 0 Then
StringBuffer.Add(Temp.ToString)
Temp.Remove(0, Temp.Length)
Else
Temp.Append(Chr(Buffer(I)))
End If
Next
If StringBuffer.Count Mod 2 <> 0 Then
StringBuffer.Add("")
End If
Me.PeopleList.Clear()
For I As Int32 = 0 To StringBuffer.Count - 1 Step 2
Me.PeopleList.Add(StringBuffer(I), StringBuffer(I + 1))
Next
Return True
Catch Ex As Exception
Return False
End Try
End Function
Public Overrides Sub Write(ByVal OpenStream As System.IO.BinaryWriter)
Me.CalculateSize()
Me.Header.Write(OpenStream)
For Each K As String In Me.PeopleList.Keys
Functions.WriteString(OpenStream, K)
Functions.WriteString(OpenStream, Me.PeopleList(K))
Next
End Sub
End Class
Public Class SynchronizedLyricTextFrame
Inherits Frame
Public Enum TimeStampFormat As Byte
Frames = 1
Milliseconds = 2
End Enum
Public Enum TextPurpose As Byte
Unspcified
SongText
TransposedText
Movement
[Event]
Chord
Other
End Enum
Public Class SyncText
Private _Text As String
Private _Time As Int32
Public Property Text() As String
Get
Return _Text
End Get
Set(ByVal Value As String)
_Text = Value
End Set
End Property
Public Property Time() As Int32
Get
Return _Time
End Get
Set(ByVal Value As Int32)
_Time = Value
End Set
End Property
Sub New(ByVal Text As String, ByVal Time As Int32)
Me.Text = Text
Me.Time = Time
End Sub
Sub New()
End Sub
End Class
Public Class SyncTextList
Inherits List(Of SyncText)
Public Overloads Sub Add(ByVal Text As String, ByVal Time As Int32)
Me.Add(New SyncText(Text, Time))
End Sub
End Class
<VBFixedString(3)> _
Private _Language As String
Private _TimeStamp As TimeStampFormat
Private _ContentType As TextPurpose
Private _ContentDescription As String
Private _SyncTextChunks As New SyncTextList
Public Property Language() As String
Get
Return _Language
End Get
Set(ByVal Value As String)
_Language = Value
End Set
End Property
Public Property TimeStamp() As TimeStampFormat
Get
Return _TimeStamp
End Get
Set(ByVal Value As TimeStampFormat)
_TimeStamp = Value
End Set
End Property
Public Property ContentType() As TextPurpose
Get
Return _ContentType
End Get
Set(ByVal Value As TextPurpose)
_ContentType = Value
End Set
End Property
Public Property ContentDescription() As String
Get
Return _ContentDescription
End Get
Set(ByVal Value As String)
_ContentDescription = Value
End Set
End Property
Public ReadOnly Property SyncTextChunks() As SyncTextList
Get
Return _SyncTextChunks
End Get
End Property
Public Shared ReadOnly Property DefaultID() As String
Get
Return "SYLT"
End Get
End Property
Sub New(ByVal Header As FrameHeader)
Me.Header = Header
Me.SetDescription()
Me.Language = "ITA"
Me.TimeStamp = TimeStampFormat.Milliseconds
Me.ContentDescription = ""
End Sub
Sub New(ByVal ID As String)
Me.New(New FrameHeader(ID))
End Sub
Sub New()
Me.New(DefaultID)
End Sub
Protected Overrides Sub CalculateSize()
Me.Header.DataSize = 1 + Me.Language.Length + 1 + 1 + Me.ContentDescription.Length + 1
For Each T As SyncText In Me.SyncTextChunks
Me.Header.DataSize += T.Text.Length + 1 + 4
Next
End Sub
Public Overrides Function Read(ByVal OpenStream As System.IO.BinaryReader) As Boolean
Try
'Codifica
OpenStream.ReadByte()
Me.Language = OpenStream.ReadChars(3)
Me.TimeStamp = OpenStream.ReadByte
Me.ContentType = OpenStream.ReadByte
Me.ContentDescription = Functions.ReadString(OpenStream)
Dim ChunkSize As Int32 = Me.Header.DataSize - 6 - (Me.ContentDescription.Length + 1)
Dim Start As Int32 = OpenStream.BaseStream.Position
Me.SyncTextChunks.Clear()
Do While OpenStream.BaseStream.Position < Start + ChunkSize
Dim T As New SyncText
T.Text = Functions.ReadString(OpenStream)
T.Time = OpenStream.ReadInt32
Me.SyncTextChunks.Add(T)
Loop
Return True
Catch ex As Exception
Return False
End Try
End Function
Public Overrides Sub Write(ByVal OpenStream As System.IO.BinaryWriter)
Me.CalculateSize()
Me.Header.Write(OpenStream)
'Codifica
OpenStream.Write(Null)
Functions.WriteString(OpenStream, Me.Language, False)
OpenStream.Write(Me.TimeStamp)
OpenStream.Write(Me.ContentType)
Functions.WriteString(OpenStream, Me.ContentDescription)
For Each T As SyncText In Me.SyncTextChunks
Functions.WriteString(OpenStream, T.Text)
OpenStream.Write(T.Time)
Next
End Sub
End Class
Public Class CommentFrame
Inherits Frame
<VBFixedString(3)> _
Private _Language As String
Private _Text As String
Private _ContentDescription As String
Public Property Language() As String
Get
Return _Language
End Get
Set(ByVal Value As String)
_Language = Value
End Set
End Property
Public Property Text() As String
Get
Return _Text
End Get
Set(ByVal Value As String)
_Text = Value
End Set
End Property
Public Property ContentDescription() As String
Get
Return _ContentDescription
End Get
Set(ByVal Value As String)
_ContentDescription = Value
End Set
End Property
Public Shared ReadOnly Property DefaultID() As String
Get
Return "COMM"
End Get
End Property
Sub New(ByVal Header As FrameHeader)
Me.Header = Header
Me.SetDescription()
Me.Language = "ITA"
Me.Text = ""
Me.ContentDescription = ""
End Sub
Sub New(ByVal ID As String)
Me.New(New FrameHeader(ID))
End Sub
Sub New()
Me.New(DefaultID)
End Sub
Protected Overrides Sub CalculateSize()
Me.Header.DataSize = 1 + 3 + Me.Text.Length + 1 + Me.ContentDescription.Length + 1
End Sub
Public Overrides Function Read(ByVal OpenStream As System.IO.BinaryReader) As Boolean
Try
'Salta il byte di codifica
OpenStream.ReadByte()
Me.Language = OpenStream.ReadChars(3)
Me.ContentDescription = Functions.ReadString(OpenStream)
Me.Text = Functions.ReadString(OpenStream)
Return True
Catch ex As Exception
Return False
End Try
End Function
Public Overrides Sub Write(ByVal OpenStream As System.IO.BinaryWriter)
Me.CalculateSize()
Me.Header.Write(OpenStream)
OpenStream.Write(Null)
Functions.WriteString(OpenStream, Me.Language, False)
Functions.WriteString(OpenStream, Me.ContentDescription)
Functions.WriteString(OpenStream, Me.Text)
End Sub
End Class
Public Class AttachedImageFrame
Inherits Frame
Public Enum ImagePurpose As Byte
Other
Icon32x32
Icon
CoverFront
CoverBack
Depliant
CdLabel
MainArtist
Artists
Conductor
Band
Composer
TextAuthor
RegistrationPlace
RegistrationImages
ConcertImages
Screenshot
Illustration = 18
ArtistLogo
PublisherLogo
End Enum
Private _MimeType As String
Private _ImageType As ImagePurpose
Private _ImageDescription As String
Private _ImageData As Byte()
Public Property MimeType() As String
Get
Return _MimeType
End Get
Set(ByVal Value As String)
_MimeType = Value
End Set
End Property
Public Property ImageType() As ImagePurpose
Get
Return _ImageType
End Get
Set(ByVal Value As ImagePurpose)
_ImageType = Value
End Set
End Property
Public Property ImageDescription() As String
Get
Return _ImageDescription
End Get
Set(ByVal Value As String)
_ImageDescription = Value
End Set
End Property
Public Property ImageData() As Byte()
Get
Return _ImageData
End Get
Set(ByVal Value As Byte())
_ImageData = Value
End Set
End Property
Public Shared ReadOnly Property DefaultID() As String
Get
Return "APIC"
End Get
End Property
Sub New(ByVal Header As FrameHeader)
Me.Header = Header
Me.SetDescription()
Me.MimeType = ""
Me.ImageDescription = ""
Me.ImageData = New Byte() {}
End Sub
Sub New(ByVal ID As String)
Me.New(New FrameHeader(ID))
End Sub
Sub New()
Me.New(DefaultID)
End Sub
Protected Overrides Sub CalculateSize()
Me.Header.DataSize = 1 + Me.MimeType.Length + 1 + 1 + Me.ImageDescription.Length + 1 + Me.ImageData.Length
End Sub
Public Overrides Function Read(ByVal OpenStream As System.IO.BinaryReader) As Boolean
Try
'Salta il byte di codifica
OpenStream.ReadByte()
Me.MimeType = Functions.ReadString(OpenStream)
Me.ImageType = OpenStream.ReadByte
Me.ImageDescription = Functions.ReadString(OpenStream)
Me.ImageData = OpenStream.ReadBytes(Me.Header.DataSize - 1 - Me.MimeType.Length - 1 - 1 - Me.ImageDescription.Length - 1)
Return True
Catch ex As Exception
Return False
End Try
End Function
Public Overrides Sub Write(ByVal OpenStream As System.IO.BinaryWriter)
Me.CalculateSize()
Me.Header.Write(OpenStream)
With OpenStream
.Write(Null)
Functions.WriteString(OpenStream, Me.MimeType)
.Write(Me.ImageType)
Functions.WriteString(OpenStream, Me.ImageDescription)
.Write(Me.ImageData)
End With
End Sub
Public Function GetImage() As Image
Dim Mem As New IO.MemoryStream(Me.ImageData)
Dim Result As Image
Result = Image.FromStream(Mem)
Mem.Close()
Return Result
End Function
Public Sub SetImage(ByVal Img As Image)
Dim Mem As New IO.MemoryStream
Img.Save(Mem, Img.RawFormat)
Mem.Position = 0
ReDim Me.ImageData(Mem.Length - 1)
Mem.Read(Me.ImageData, 0, Mem.Length)
Mem.Close()
End Sub
End Class
Public Class GeneralObjectFrame
Inherits Frame
Private _MimeType As String
Private _FileName As String
Private _ContentDescription As String
Private _ObjectData() As Byte
Public Property MimeType() As String
Get
Return _MimeType
End Get
Set(ByVal Value As String)
_MimeType = Value
End Set
End Property
Public Property FileName() As String
Get
Return _FileName
End Get
Set(ByVal Value As String)
_FileName = Value
End Set
End Property
Public Property ContentDescription() As String
Get
Return _ContentDescription
End Get
Set(ByVal Value As String)
_ContentDescription = Value
End Set
End Property
Public Property ObjectData() As Byte()
Get
Return _ObjectData
End Get
Set(ByVal value As Byte())
_ObjectData = value
End Set
End Property
Public Shared ReadOnly Property DefaultId() As String
Get
Return "GEOB"
End Get
End Property
Sub New(ByVal Header As FrameHeader)
Me.Header = Header
Me.SetDescription()
Me.MimeType = ""
Me.FileName = ""
Me.ContentDescription = ""
Me.ObjectData = New Byte() {}
End Sub
Sub New(ByVal ID As String)
Me.New(New FrameHeader(ID))
End Sub
Sub New()
Me.New(DefaultId)
End Sub
Protected Overrides Sub CalculateSize()
Me.Header.DataSize = 1 + Me.MimeType.Length + 1 + Me.FileName.Length + 1 + Me.ContentDescription.Length + 1 + Me.ObjectData.Length
End Sub
Public Overrides Function Read(ByVal OpenStream As System.IO.BinaryReader) As Boolean
Try
OpenStream.ReadByte()
Me.MimeType = Functions.ReadString(OpenStream)
Me.FileName = Functions.ReadString(OpenStream)
Me.ContentDescription = Functions.ReadString(OpenStream)
Me.ObjectData = OpenStream.ReadBytes(Me.Header.DataSize - 1 - Me.MimeType.Length - 1 - Me.FileName.Length - 1 - Me.ContentDescription.Length - 1)
Return True
Catch ex As Exception
Return False
End Try
End Function
Public Overrides Sub Write(ByVal OpenStream As System.IO.BinaryWriter)
Me.CalculateSize()
Me.Header.Write(OpenStream)
With OpenStream
.Write(Null)
Functions.WriteString(OpenStream, Me.MimeType)
Functions.WriteString(OpenStream, Me.FileName)
Functions.WriteString(OpenStream, Me.ContentDescription)
.Write(Me.ObjectData)
End With
End Sub
Public Sub SetObject(Of T)(ByVal Obj As T)
Dim Serializer As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()
Dim Mem As New IO.MemoryStream
Serializer.Serialize(Mem, Obj)
Mem.Position = 0
ReDim Me.ObjectData(Mem.Length - 1)
Mem.Read(Me.ObjectData, 0, Mem.Length)
Mem.Close()
End Sub
Public Function GetObject(Of T)() As T
Dim Mem As New IO.MemoryStream(Me.ObjectData)
Try
Dim Serializer As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()
Dim Result As T = Serializer.Deserialize(Mem)
Return Result
Catch ex As Exception
Mem.Close()
Return Nothing
End Try
End Function
End Class
Public Class PopularimeterFrame
Inherits Frame
Private _EMail As String
Private _Value As Byte
Private _Counter As Int32
Public Property EMail() As String
Get
Return _EMail
End Get
Set(ByVal Value As String)
_EMail = Value
End Set
End Property
Public Property Value() As Byte
Get
Return _Value
End Get
Set(ByVal Value As Byte)
_Value = Value
End Set
End Property
Public Property Counter() As Int32
Get
Return _Counter
End Get
Set(ByVal Value As Int32)
_Counter = Value
End Set
End Property
Public Shared ReadOnly Property DefaultID() As String
Get
Return "POPM"
End Get
End Property
Sub New(ByVal Header As FrameHeader)
Me.Header = Header
Me.SetDescription()
Me.EMail = ""
Me.Value = 0
Me.Counter = 0
End Sub
Sub New(ByVal ID As String)
Me.New(New FrameHeader(ID))
End Sub
Sub New()
Me.New(DefaultID)
End Sub
Protected Overrides Sub CalculateSize()
Me.Header.DataSize = Me.EMail.Length + 1 + 1 + 4
End Sub
Public Overrides Function Read(ByVal OpenStream As System.IO.BinaryReader) As Boolean
Try
Me.EMail = Functions.ReadString(OpenStream)
Me.Value = OpenStream.ReadByte
Me.Counter = OpenStream.ReadInt32
Return True
Catch ex As Exception
Return False
End Try
End Function
Public Overrides Sub Write(ByVal OpenStream As System.IO.BinaryWriter)
Me.CalculateSize()
Me.Header.Write(OpenStream)
Functions.WriteString(OpenStream, Me.EMail)
OpenStream.Write(Me.Value)
OpenStream.Write(Me.Counter)
End Sub
End Class
Public Class CommercialFrame
Inherits Frame
Public Enum GetMode As Byte
Other
CD
CompressCD
Download
Streaming
AttachToMusicSheet
AttachToMusicBook
Other2
NonMusic
End Enum
Private _Price As String
Private _ExpireDate As Date
Private _PublisherUrl As String
Private _BuyMode As GetMode
Private _SellerName As String
Private _ProductDescription As String
Private _MimeType As String
Private _PublisherLogoData As Byte()
Public Property Price() As String
Get
Return _Price
End Get
Set(ByVal Value As String)
_Price = Value
End Set
End Property
Public Property ExpireDate() As Date
Get
Return _ExpireDate
End Get
Set(ByVal Value As Date)
_ExpireDate = Value
End Set
End Property
Public Property PublisherUrl() As String
Get
Return _PublisherUrl
End Get
Set(ByVal Value As String)
_PublisherUrl = Value
End Set
End Property
Public Property BuyMode() As GetMode
Get
Return _BuyMode
End Get
Set(ByVal Value As GetMode)
_BuyMode = Value
End Set
End Property
Public Property SellerName() As String
Get
Return _SellerName
End Get
Set(ByVal Value As String)
_SellerName = Value
End Set
End Property
Public Property ProductDescription() As String
Get
Return _ProductDescription
End Get
Set(ByVal Value As String)
_ProductDescription = Value
End Set
End Property
Public Property MimeType() As String
Get
Return _MimeType
End Get
Set(ByVal Value As String)
_MimeType = Value
End Set
End Property
Public Property PublisherLogoData() As Byte()
Get
Return _PublisherLogoData
End Get
Set(ByVal Value As Byte())
_PublisherLogoData = Value
End Set
End Property
Public Shared ReadOnly Property DefaultID() As String
Get
Return "COMR"
End Get
End Property
Sub New(ByVal Header As FrameHeader)
Me.Header = Header
Me.SetDescription()
Me.Price = ""
Me.ExpireDate = New Date(1, 1, 1)
Me.PublisherUrl = ""
Me.SellerName = ""
Me.ProductDescription = ""
Me.MimeType = ""
Me.PublisherLogoData = New Byte() {}
End Sub
Sub New(ByVal ID As String)
Me.New(New FrameHeader(ID))
End Sub
Sub New()
Me.New(DefaultID)
End Sub
Protected Overrides Sub CalculateSize()
Dim LogoLen As Int32
If Me.PublisherLogoData Is Nothing Then
LogoLen = 0
Else
LogoLen = Me.PublisherLogoData.Length
End If
Me.Header.DataSize = 1 + Me.Price.Length + 1 + 8 + Me.PublisherUrl.Length + 1 + 1 + Me.SellerName.Length + 1 + Me.ProductDescription.Length + 1 + Me.MimeType.Length + 1 + LogoLen
End Sub
Public Overrides Function Read(ByVal OpenStream As System.IO.BinaryReader) As Boolean
Try
OpenStream.ReadByte()
Me.Price = Functions.ReadString(OpenStream)
Dim Buffer As String = OpenStream.ReadChars(8)
Dim Year As String = Buffer.Substring(0, 4)
Dim Month As String = Buffer.Substring(4, 2)
Dim Day As String = Buffer.Substring(6, 2)
Try
Me.ExpireDate = New Date(CInt(Year), CInt(Month), CInt(Day))
Catch Ex As Exception
Me.ExpireDate = New Date(1, 1, 1)
End Try
Me.PublisherUrl = Functions.ReadString(OpenStream)
Me.BuyMode = OpenStream.ReadByte
Me.SellerName = Functions.ReadString(OpenStream)
Me.ProductDescription = Functions.ReadString(OpenStream)
Me.MimeType = Functions.ReadString(OpenStream)
Me.PublisherLogoData = OpenStream.ReadBytes(Me.Header.DataSize - 1 - Me.Price.Length - 1 - 8 - Me.PublisherUrl.Length - 1 - 1 - Me.SellerName.Length - 1 - Me.ProductDescription.Length - 1 - Me.MimeType.Length - 1)
Return True
Catch ex As Exception
Return False
End Try
End Function
Public Overrides Sub Write(ByVal OpenStream As System.IO.BinaryWriter)
Me.CalculateSize()
Me.Header.Write(OpenStream)
OpenStream.Write(Null)
Functions.WriteString(OpenStream, Me.Price)
Functions.WriteString(OpenStream, CStr(Me.ExpireDate.Year) & CStr(Me.ExpireDate.Month).PadRight(2, "0") & CStr(Me.ExpireDate.Day).PadRight(2, "0"), False)
Functions.WriteString(OpenStream, Me.PublisherUrl)
OpenStream.Write(Me.BuyMode)
Functions.WriteString(OpenStream, Me.SellerName)
Functions.WriteString(OpenStream, Me.ProductDescription)
Functions.WriteString(OpenStream, Me.MimeType)
OpenStream.Write(Me.PublisherLogoData)
End Sub
Public Function GetPublisherLogo() As Image
Dim Mem As New IO.MemoryStream(Me.PublisherLogoData)
Dim Result As Image
Result = Image.FromStream(Mem)
Mem.Close()
Return Result
End Function
Public Sub SetPublicherLogo(ByVal Img As Image)
Dim Mem As New IO.MemoryStream
Img.Save(Mem, Img.RawFormat)
Mem.Position = 0
ReDim Me.PublisherLogoData(Mem.Length - 1)
Mem.Read(Me.PublisherLogoData, 0, Mem.Length)
Mem.Close()
End Sub
End Class
Public Class PrivateFrame
Inherits Frame
Private _OwnerIdentifier As String
Private _Data() As Byte
Public Property OwnerIdentifier() As String
Get
Return _OwnerIdentifier
End Get
Set(ByVal value As String)
_OwnerIdentifier = value
End Set
End Property
Public Property Data() As Byte()
Get
Return _Data
End Get
Set(ByVal value As Byte())
_Data = value
End Set
End Property
Public Shared ReadOnly Property DefaultID() As String
Get
Return "PRIV"
End Get
End Property
Sub New(ByVal Header As FrameHeader)
Me.Header = Header
Me.SetDescription()
Me.OwnerIdentifier = ""
Me.Data = New Byte() {}
End Sub
Sub New(ByVal ID As String)
Me.New(New FrameHeader(ID))
End Sub
Sub New()
Me.New(DefaultID)
End Sub
Protected Overrides Sub CalculateSize()
Me.Header.DataSize = Me.OwnerIdentifier.Length + 1 + Me.Data.Length
End Sub
Public Overrides Function Read(ByVal OpenStream As System.IO.BinaryReader) As Boolean
Try
Me.OwnerIdentifier = Functions.ReadString(OpenStream)
Me.Data = OpenStream.ReadBytes(Me.Header.DataSize - Me.OwnerIdentifier.Length - 1)
Return True
Catch ex As Exception
Return False
End Try
End Function
Public Overrides Sub Write(ByVal OpenStream As System.IO.BinaryWriter)
Me.CalculateSize()
Me.Header.Write(OpenStream)
Functions.WriteString(OpenStream, Me.OwnerIdentifier)
OpenStream.Write(Me.Data)
End Sub
End Class
Public Class ID3TagV2
<Flags()> _
Public Enum MainHeaderFlags
Desynchronization = 0
ExtendedHeader = 1
Experimental = 2
End Enum
Public Enum ReadResult
Failure
HeaderOnly
TagOnly
Success
End Enum
Private _Frames As New List(Of Frame)
Private _Flags As MainHeaderFlags
Private _Version As Version
Private _Size As Int32
Private Mp3Data() As Byte
Public ReadOnly Property Frames() As List(Of Frame)
Get
Return _Frames
End Get
End Property
Public Property Version() As Version
Get
Return _Version
End Get
Set(ByVal value As Version)
_Version = value
End Set
End Property
Public Property Flags() As MainHeaderFlags
Get
Return _Flags
End Get
Set(ByVal value As MainHeaderFlags)
_Flags = value
End Set
End Property
Public Property Size() As Int32
Get
Return _Size
End Get
Set(ByVal value As Int32)
_Size = value
End Set
End Property
Protected Sub QuickAdd(Of FrameType As {New, Frame})(ByVal H As FrameHeader, ByVal Reader As IO.BinaryReader)
Dim AFrame As New FrameType
AFrame.Initialize(H)
If AFrame.Read(Reader) Then
Me.Frames.Add(AFrame)
End If
End Sub
Public Function Read
(ByVal File As String) As ReadResult
Dim Reader
As New IO.
BinaryReader(New IO.
FileStream(File, IO.
FileMode.
Open))
Dim ID3 As String
ID3 = Reader.ReadChars(3)
If ID3 <> "ID3" Then
Reader.Close()
Return ReadResult.Failure
End If
Me.Version = New Version(Reader.ReadByte, Reader.ReadByte)
Dim Buffer As Byte = Reader.ReadByte
If (Buffer And 128) = 128 Then
Me.Flags = Me.Flags Or MainHeaderFlags.Desynchronization
End If
If (Buffer And 64) = 64 Then
Me.Flags = Me.Flags Or MainHeaderFlags.ExtendedHeader
End If
If (Buffer And 32) = 32 Then
Me.Flags = Me.Flags Or MainHeaderFlags.Experimental
End If
Me.Size = Functions.BytesToSize(Reader.ReadBytes(4))
If Me.Size = 0 Then
Reader.Close()
Return ReadResult.HeaderOnly
End If
Do While Reader.BaseStream.Position < Me.Size + 10
Dim Header As New FrameHeader
Dim p As Int32 = Reader.BaseStream.Position
If p > 2000 Then
End If
If Header.Read(Reader) Then
If Header.Identifier.StartsWith("T") Or Header.Identifier.StartsWith("W") Then
Me.QuickAdd(Of TextFrame)(Header, Reader)
ElseIf Header.Identifier = InvolvedPeopleFrame.DefaultID Then
Me.QuickAdd(Of InvolvedPeopleFrame)(Header, Reader)
ElseIf Header.Identifier = SynchronizedLyricTextFrame.DefaultID Then
Me.QuickAdd(Of SynchronizedLyricTextFrame)(Header, Reader)
ElseIf Header.Identifier = CommentFrame.DefaultID Then
Me.QuickAdd(Of CommentFrame)(Header, Reader)
ElseIf Header.Identifier = AttachedImageFrame.DefaultID Then
Me.QuickAdd(Of AttachedImageFrame)(Header, Reader)
ElseIf Header.Identifier = GeneralObjectFrame.DefaultId Then
Me.QuickAdd(Of GeneralObjectFrame)(Header, Reader)
ElseIf Header.Identifier = PopularimeterFrame.DefaultID Then
Me.QuickAdd(Of PopularimeterFrame)(Header, Reader)
ElseIf Header.Identifier = CommercialFrame.DefaultID Then
Me.QuickAdd(Of CommercialFrame)(Header, Reader)
Else
Reader.ReadBytes(Header.DataSize)
End If
Else
Reader.Close()
Return ReadResult.TagOnly
End If
Loop
ReDim Mp3Data(Reader.BaseStream.Length - Me.Size - 11)
Reader.BaseStream.Position = 0
Reader.BaseStream.Seek(Me.Size + 10, IO.SeekOrigin.Begin)
Reader.Read(Mp3Data, 0, Mp3Data.Length)
Reader.Close()
Return ReadResult.Success
End Function
Private Sub CalculateSize()
Me.Size = 0
For Each F As Frame In Me.Frames
Me.Size += F.Size
Next
End Sub
Public Sub Write(ByVal File As String)
If (Mp3Data Is Nothing) OrElse (Mp3Data.Length = 0) Then
Throw New IO.
FileNotFoundException(File & " non esiste!")
End If
Dim Reader
As New IO.
BinaryReader(New IO.
FileStream(File, IO.
FileMode.
Open))
Dim ID3 As String
Dim TempSize As Int32
ID3 = Reader.ReadChars(3)
If ID3 <> "ID3" Then
Reader.Close()
System.Threading.Thread.Sleep(10)
Else
Reader.ReadBytes(3)
TempSize = Functions.BytesToSize(Reader.ReadBytes(4))
If TempSize = 0 Then
ReDim Mp3Data(Reader.BaseStream.Length - 11)
Reader.Read(Mp3Data, 0, Mp3Data.Length)
Reader.Close()
Else
Reader.ReadBytes(TempSize)
ReDim Mp3Data(Reader.BaseStream.Length - 11 - TempSize)
Reader.Read(Mp3Data, 0, Mp3Data.Length)
Reader.Close()
End If
End If
System.Threading.Thread.Sleep(10)
End If
Dim Writer
As New IO.
BinaryWriter(New IO.
FileStream(File, IO.
FileMode.
Create))
Functions.WriteString(Writer, "ID3", False)
Writer.Write(CByte(3))
Writer.Write(CByte(0))
Dim Buffer As Byte
If (Me.Flags And MainHeaderFlags.Desynchronization) = MainHeaderFlags.Desynchronization Then
Buffer += 128
End If
If (Me.Flags And MainHeaderFlags.ExtendedHeader) = MainHeaderFlags.ExtendedHeader Then
Buffer += 64
End If
If (Me.Flags And MainHeaderFlags.Experimental) = MainHeaderFlags.Experimental Then
Buffer += 32
End If
Writer.Write(Buffer)
Me.CalculateSize()
Writer.Write(Functions.SizeToBytes(Me.Size))
For Each F As Frame In Me.Frames
F.Write(Writer)
Next
Writer.Write(Mp3Data)
Writer.Close()
End Sub
End Class
End Namespace
End Namespace