diff --git a/Perry's ID3 Tag Library.sln b/Perry's ID3 Tag Library.sln new file mode 100644 index 0000000..3d0f194 --- /dev/null +++ b/Perry's ID3 Tag Library.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Perry's ID3 Tag Library", "Perry's ID3 Tag Library\Perry's ID3 Tag Library.vbproj", "{0AAD4FAD-D851-4A41-A299-B6728F05AA28}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0AAD4FAD-D851-4A41-A299-B6728F05AA28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0AAD4FAD-D851-4A41-A299-B6728F05AA28}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0AAD4FAD-D851-4A41-A299-B6728F05AA28}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0AAD4FAD-D851-4A41-A299-B6728F05AA28}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Perry's ID3 Tag Library/BitManipulator.vb b/Perry's ID3 Tag Library/BitManipulator.vb new file mode 100644 index 0000000..876529b --- /dev/null +++ b/Perry's ID3 Tag Library/BitManipulator.vb @@ -0,0 +1,39 @@ +Public Class BitManipulator + + ' The ClearBit Sub clears the 1 based, nth bit + ' (MyBit) of an integer (MyByte). + Shared Sub ClearBit(ByRef MyByte, ByVal MyBit) + Dim BitMask As Int16 + ' Create a bitmask with the 2 to the nth power bit set: + BitMask = 2 ^ (MyBit - 1) + ' Clear the nth Bit: + MyByte = MyByte And Not BitMask + End Sub + + ' The ExamineBit function will return True or False + ' depending on the value of the 1 based, nth bit (MyBit) + ' of an integer (MyByte). + Shared Function ExamineBit(ByVal MyByte, ByVal MyBit) As Boolean + Dim BitMask As Int16 + BitMask = 2 ^ (MyBit - 1) + ExamineBit = ((MyByte And BitMask) > 0) + End Function + + ' The SetBit Sub will set the 1 based, nth bit + ' (MyBit) of an integer (MyByte). + Shared Sub SetBit(ByRef MyByte, ByVal MyBit) + Dim BitMask As Int16 + BitMask = 2 ^ (MyBit - 1) + MyByte = MyByte Or BitMask + End Sub + + ' The ToggleBit Sub will change the state + ' of the 1 based, nth bit (MyBit) + ' of an integer (MyByte). + Shared Sub ToggleBit(ByRef MyByte, ByVal MyBit) + Dim BitMask As Int16 + BitMask = 2 ^ (MyBit - 1) + MyByte = MyByte Xor BitMask + End Sub + +End Class diff --git a/Perry's ID3 Tag Library/ComParser.vb b/Perry's ID3 Tag Library/ComParser.vb new file mode 100644 index 0000000..0807a18 --- /dev/null +++ b/Perry's ID3 Tag Library/ComParser.vb @@ -0,0 +1,40 @@ + _ +Public Class ComParser + +#Region "COM GUIDs" + ' These GUIDs provide the COM identity for this class + ' and its COM interfaces. If you change them, existing + ' clients will no longer be able to access the class. + Public Const ClassId As String = "2a314524-a053-4dc4-87dc-ffe55d8efdc8" + Public Const InterfaceId As String = "70c601e7-841d-4a50-b7e7-4e69665a2783" + Public Const EventsId As String = "d969b307-6f11-47f1-97b2-9d540b069f4a" +#End Region + + ' A creatable COM class must have a Public Sub New() + ' with no parameters, otherwise, the class will not be + ' registered in the COM registry and cannot be created + ' via CreateObject. + Public Sub New() + MyBase.New() + End Sub + + ''' + ''' Parses an MP3 file whose result is accessible through COM. + ''' + ''' + ''' + ''' + Public Function ParseMP3(ByVal argFilePath As String) As MP3File + Return New ComMP3File(argFilePath) + End Function + + Public Class ComMP3File + Inherits ID3TagLibrary.MP3File + Sub New(ByVal argFilePath As String) + MyBase.new(argFilePath) + End Sub + End Class + +End Class + + diff --git a/Perry's ID3 Tag Library/Documentation.doc b/Perry's ID3 Tag Library/Documentation.doc new file mode 100644 index 0000000..5f06c9c Binary files /dev/null and b/Perry's ID3 Tag Library/Documentation.doc differ diff --git a/Perry's ID3 Tag Library/Globals.vb b/Perry's ID3 Tag Library/Globals.vb new file mode 100644 index 0000000..1a6e686 --- /dev/null +++ b/Perry's ID3 Tag Library/Globals.vb @@ -0,0 +1,180 @@ +Public Module Globals + + ''' + ''' Gets the encoded size in bytes of an ID3v2.2 tag. + ''' + ''' + ''' + ''' + Function GetID3EncodedSizeV2(ByVal argBytes() As Byte) As Integer + Dim encodedSize As Integer + 'encodedSize = argBytes(0) + argBytes(1) + argBytes(2) + encodedSize = (argBytes(0) * 256 * 256) + (argBytes(1) * 256) + argBytes(2) + Return encodedSize + End Function + + ''' + ''' Gets the encoded size in bytes of an ID3v2.3 tag. + ''' + ''' + ''' + ''' + Function GetID3EncodedSizeV3(ByVal argBytes() As Byte) As Integer + Dim encodedSize As Integer + 'encodedSize = (65536 * (argBytes(0) * 256 + argBytes(1))) + (argBytes(2) * 256 + argBytes(3)) + 'encodedSize = (argBytes(0) * 128 * 128 * 128) + (argBytes(1) * 128 * 128) + (argBytes(2) * 128) + argBytes(3) + encodedSize = (argBytes(0) * 256 * 256 * 256) + (argBytes(1) * 256 * 256) + (argBytes(2) * 256) + argBytes(3) + Return encodedSize + End Function + + ''' + ''' Gets the encoded size in bytes of the ID3v2.4 tag. + ''' + ''' + ''' + ''' + Function GetID3EncodedSizeV4(ByVal argBytes() As Byte) As String + + ' According to ID3v2 spec, the encoded size is contained by 4 bytes. Each + ' byte has it's MSB set to zero. The NORMAL CHART and UNSYNCHED CHART + ' show this difference. + + ' NORMAL CHART (last 2 bytes) + ' 16 15 14 13 12 11 10 9 | 8 7 6 5 4 3 2 1 + ' 32768 16384 8192 4096 2048 1024 512 256 | 128 64 32 16 8 4 2 1 + + ' UNSYNCHED CHART (last 2 bytes) + ' 16 15 14 13 12 11 10 9 | 8 7 6 5 4 3 2 1 + ' 0 8192 4096 2048 1024 512 256 128 | 0 64 32 16 8 4 2 1 + + 'Dim encodedSize As Integer + + '' check the value of each bit in the fourth byte and increment the encoded size + 'If BitManipulator.ExamineBit(argBytes(3), 1) = True Then encodedSize += 1 + 'If BitManipulator.ExamineBit(argBytes(3), 2) = True Then encodedSize += 2 + 'If BitManipulator.ExamineBit(argBytes(3), 3) = True Then encodedSize += 4 + 'If BitManipulator.ExamineBit(argBytes(3), 4) = True Then encodedSize += 8 + 'If BitManipulator.ExamineBit(argBytes(3), 5) = True Then encodedSize += 16 + 'If BitManipulator.ExamineBit(argBytes(3), 6) = True Then encodedSize += 32 + 'If BitManipulator.ExamineBit(argBytes(3), 7) = True Then encodedSize += 64 + + '' check the value of each bit in the third byte and increment the encoded size + 'If BitManipulator.ExamineBit(argBytes(2), 1) = True Then encodedSize += 128 + 'If BitManipulator.ExamineBit(argBytes(2), 2) = True Then encodedSize += 256 + 'If BitManipulator.ExamineBit(argBytes(2), 3) = True Then encodedSize += 512 + 'If BitManipulator.ExamineBit(argBytes(2), 4) = True Then encodedSize += 1024 + 'If BitManipulator.ExamineBit(argBytes(2), 5) = True Then encodedSize += 2048 + 'If BitManipulator.ExamineBit(argBytes(2), 6) = True Then encodedSize += 4096 + 'If BitManipulator.ExamineBit(argBytes(2), 7) = True Then encodedSize += 8192 + + '' check the value of each bit in the second byte and increment the encoded size + 'If BitManipulator.ExamineBit(argBytes(1), 1) = True Then encodedSize += 16384 + 'If BitManipulator.ExamineBit(argBytes(1), 2) = True Then encodedSize += 32768 + 'If BitManipulator.ExamineBit(argBytes(1), 3) = True Then encodedSize += 65536 + 'If BitManipulator.ExamineBit(argBytes(1), 4) = True Then encodedSize += 131072 + 'If BitManipulator.ExamineBit(argBytes(1), 5) = True Then encodedSize += 262144 + 'If BitManipulator.ExamineBit(argBytes(1), 6) = True Then encodedSize += 524288 + 'If BitManipulator.ExamineBit(argBytes(1), 7) = True Then encodedSize += 1048576 + + '' check the value of each bit in the first byte and increment the encoded size + 'If BitManipulator.ExamineBit(argBytes(0), 1) = True Then encodedSize += 2097152 + 'If BitManipulator.ExamineBit(argBytes(0), 2) = True Then encodedSize += 4194304 + 'If BitManipulator.ExamineBit(argBytes(0), 3) = True Then encodedSize += 8388608 + 'If BitManipulator.ExamineBit(argBytes(0), 4) = True Then encodedSize += 16777216 + 'If BitManipulator.ExamineBit(argBytes(0), 5) = True Then encodedSize += 33554432 + 'If BitManipulator.ExamineBit(argBytes(0), 6) = True Then encodedSize += 67108864 + 'If BitManipulator.ExamineBit(argBytes(0), 7) = True Then encodedSize += 134217728 + + '' subtract the tag header size (which is always 10 bytes according to ID3v2 spec) from the encodedSize to get the final tag size in bytes + 'Return encodedSize - 10 '50934 + + Dim encodedSize As Integer + 'encodedSize = (argBytes(0) * 256 * 256 * 256) + (argBytes(1) * 256 * 256) + (argBytes(2) * 256) + argBytes(3) + encodedSize = (argBytes(0) * 128 * 128 * 128) + (argBytes(1) * 128 * 128) + (argBytes(2) * 128) + argBytes(3) + Return encodedSize + + End Function + + ''' + ''' Converts an array of Bytes to a String, optionally removing non-alphanumeric characters. + ''' + ''' + ''' + ''' + ''' + Function BytesToText(ByVal argBytes() As Byte, ByVal argRemoveNonAlphanumeric As Boolean) As String + Dim mText As String = "" + + ' new method + Dim lst As New ArrayList(argBytes) + Dim x() As Byte + x = Array.FindAll(argBytes, AddressOf isAlphaNumeric) + mText = Text.Encoding.ASCII.GetString(x) + + ' old method + 'For Each b As Byte In argBytes + ' Dim mCharacter As String + ' If argRemoveNonAlphanumeric = True Then + ' Select Case b + ' Case Is < 32 + ' Case Else + ' mCharacter = Convert.ToChar(b) + ' mText &= mCharacter + ' End Select + ' Else + ' mCharacter = Convert.ToChar(b) + ' mText &= mCharacter + ' End If + 'Next + + Return mText + End Function + + ''' + ''' Checks whether a byte is an alphanumeric character in the ASCII table. + ''' + ''' + ''' + ''' + Public Function isAlphaNumeric(ByVal b As Byte) As Boolean + If b > 31 And b < 128 Then + Return True + Else + Return False + End If + End Function + + ''' + ''' Converts a Byte array to a String of comma-delimited numeric ASCII codes. + ''' + ''' + ''' + ''' + Function BytesToAsciiCodes(ByVal argBytes() As Byte) As String + Dim mText As String = "" + For Each b As Byte In argBytes + If mText = "" Then + mText = b + Else + mText &= ", " & b + End If + Next + Return mText + End Function + + ''' + ''' Removes one or more characters from a string. + ''' + ''' The string that should have one or more characters removed. + ''' An array of integer ASCII codes. Hint: New Integer() {1, 5, 23} + ''' + ''' + Function RemoveChars(ByVal argString As String, ByVal argRemove() As Integer) + For i As Integer = 0 To argRemove.Length - 1 + argString = argString.Replace(Chr(argRemove(i)), "") + Next + Return argString + End Function + +End Module + diff --git a/Perry's ID3 Tag Library/ID3LibraryKeyFile.snk b/Perry's ID3 Tag Library/ID3LibraryKeyFile.snk new file mode 100644 index 0000000..9618e7c Binary files /dev/null and b/Perry's ID3 Tag Library/ID3LibraryKeyFile.snk differ diff --git a/Perry's ID3 Tag Library/ID3v1Tag.vb b/Perry's ID3 Tag Library/ID3v1Tag.vb new file mode 100644 index 0000000..50e27de --- /dev/null +++ b/Perry's ID3 Tag Library/ID3v1Tag.vb @@ -0,0 +1,63 @@ +Public Class ID3v1Tag + + Public FileIdentifier As String + Public Title As String + Public Artist As String + Public Album As String + Public Year As String + Public Comment As String + Public Genre As String + Public TagVersion As String + + Sub New(ByVal argFileInfo As IO.FileInfo) + + Dim mReader As IO.FileStream = argFileInfo.OpenRead + + Dim mFileIdentifier(2) As Byte + Dim mTitle(29) As Byte + Dim mArtist(29) As Byte + Dim mAlbum(29) As Byte + Dim mYear(3) As Byte + Dim mComment(29) As Byte + Dim mGenre(0) As Byte + + ' start at the last 128 bytes of the file, which is where an ID3v1 tag is supposed to be + mReader.Position = mReader.Length - 128 + + ' read the file identifier and make sure the value equals "TAG" which indicates an ID3v1 tag + mReader.Read(mFileIdentifier, 0, 3) + Me.FileIdentifier = BytesToText(mFileIdentifier, True).Trim + + ' read the rest of the tag if it is an ID3v1 tag + If Me.FileIdentifier = "TAG" Then + + Me.TagVersion = "1.0" + + mReader.Read(mTitle, 0, 30) + mReader.Read(mArtist, 0, 30) + mReader.Read(mAlbum, 0, 30) + mReader.Read(mYear, 0, 4) + mReader.Read(mComment, 0, 30) + mReader.Read(mGenre, 0, 1) + + Me.Title = BytesToText(mTitle, True).Trim + Me.Artist = BytesToText(mArtist, True).Trim + Me.Album = BytesToText(mAlbum, True).Trim + Me.Year = BytesToText(mYear, True).Trim + Me.Comment = BytesToText(mComment, True).Trim + 'Me.Comment = RemoveChars(Me.Comment, New Integer() {0, 1, 32}) + Me.Genre = mGenre(0) + + Else + + 'MsgBox("Could not find an ID3v1 tag!") + + End If + + ' close the file handle (remove the lock) + mReader.Close() + mReader.Dispose() + + End Sub + +End Class \ No newline at end of file diff --git a/Perry's ID3 Tag Library/ID3v2Tag.vb b/Perry's ID3 Tag Library/ID3v2Tag.vb new file mode 100644 index 0000000..4075005 --- /dev/null +++ b/Perry's ID3 Tag Library/ID3v2Tag.vb @@ -0,0 +1,751 @@ +Public Class ID3v2Tag + + Public gTagReader As IO.FileStream + Public gTagString As String + + ' TODO: + Class HeaderFlagsClass + Public UnsynchronizationFlag As Boolean + Public ExtendedHeaderFlag As Boolean + Public ExperimentalIndicatorFlag As Boolean + End Class + + Class FrameFlagsClass + Public TagAlterPreservationFlag As Boolean + Public FileAlterPreservationFlag As Boolean + Public ReadOnlyFlag As Boolean + Public CompressionFlag As Boolean + Public EncryptionFlag As Boolean + Public GroupingIdentityFlag As Boolean + End Class + + Class FrameCollection + Inherits Hashtable + + Sub AddFrame(ByVal argFrame As FrameBase) + If Me.ContainsKey(argFrame.ID) = True Then + Dim mFrameList As ArrayList + mFrameList = Me.Values(argFrame.ID) + mFrameList.Add(argFrame) + Else + Dim mFrameList As New ArrayList + mFrameList.Add(argFrame) + Me.Add(argFrame.ID, mFrameList) + End If + End Sub + End Class + + Public Class FrameBase + Public ID As String + Public Size As Integer + Public Flags As String + Public ValueBytes() As Byte + + Public Function Value() As String + Return BytesToText(ValueBytes, True) + End Function + + End Class + + ' define tag header variables + Public FileIdentifier As String + Public TagVersion As String + Public TagSize As String + Public HeaderFlags As String + + Public Frames As New ArrayList + Public RawAscii As String + Public RawBytes As String + + 'TODO: these functions don't work for ID3v2.2.0 because those frame id's are 3 characters instead of 4 + Public Function Artwork(ByVal argFrameSize As Integer) As Drawing.Image + Dim img As Drawing.Image = Nothing + For Each mFrame As FrameBase In Me.Frames + 'If mFrame.ID = "APIC" And mFrame.Size = argFrameSize Then + If mFrame.ID = "APIC" Or mFrame.ID = "PIC" Then + + ' TODO: + ' read the text encoding (1 byte) + ' read the mime type (variable length, terminated with 0) + ' read the picture type (1 byte) + ' read the description (variable length, terminated with 0) + ' remaining data is image data + ' currently, a fixed APIC header size of 14 is always assumed + + Dim mApicTextEncoding As Byte + Dim mApicMimeType As New ArrayList + Dim mApicPictureType As Byte + Dim mApicDescription As String = "" + Dim mApicDataStart As Integer = 7 '14 + + Dim c As String = "" + Dim i As Integer = 0 + + mApicTextEncoding = mFrame.ValueBytes(i) + i += 1 + + c = "" + Do Until c = "0" + c = mFrame.ValueBytes(i).ToString + mApicMimeType.Add(c) + i = i + 1 + Loop + + mApicPictureType = mFrame.ValueBytes(i).ToString + i += 1 + + c = "" + Do Until c = "0" + c = mFrame.ValueBytes(i).ToString + mApicDescription &= c.ToString + i = i + 1 + Loop + + mApicDataStart = i + + Dim ms As IO.MemoryStream + ms = New IO.MemoryStream(mFrame.ValueBytes, mApicDataStart, mFrame.ValueBytes.Length - mApicDataStart) + + img = Drawing.Image.FromStream(ms) + + End If + Next + Return img + End Function + + Public Function Title() As String + Return GetFrameValue("TIT2") + End Function + + Public Function Album() As String + Dim val As String + val = GetFrameValue("TALB") + If val = "" Then val = GetFrameValue("TAL") + Return val + End Function + + Public Function Artist() As String + Dim val As String + val = GetFrameValue("TPE1") + If val = "" Then val = GetFrameValue("TP1") + Return val + End Function + + Public Function Year() As String + Dim val As String + val = GetFrameValue("TDRC") + If val = "" Then val = GetFrameValue("TRD") + Return val + End Function + + Public Function Comment() As String + Dim val As String + val = GetFrameValue("COMM") + If val = "" Then val = GetFrameValue("COM") + Return val + End Function + + Public Function Genre() As String + Dim val As String + val = GetFrameValue("TCON") + If val = "" Then val = GetFrameValue("TCO") + Return val + End Function + + Public Function TrackNumber() As String + Dim val As String + val = GetFrameValue("TRCK") + If val = "" Then val = GetFrameValue("TRK") + Return val + End Function + + Public Function Length() As String + Dim val As String + val = GetFrameValue("TLEN") + If val = "" Then val = GetFrameValue("TLE") + Return val + End Function + + Function GetFrameValue(ByVal argFrameName As String) As String + For i As Integer = 0 To Me.Frames.Count - 1 + Dim mFrame As FrameBase + mFrame = Me.Frames(i) + If mFrame.ID = argFrameName Then Return mFrame.Value + Next + Return Nothing + End Function + + Sub New(ByVal argFileInfo As IO.FileInfo) + ParseTag(argFileInfo) + End Sub + + 'Sub New(ByVal argFileInfo As IO.FileInfo) + + ' ParseTag(argFileInfo) + ' Exit Sub + + ' Dim mReader As IO.FileStream = argFileInfo.OpenRead + + ' Dim mFileIdentifier(2) As Byte + ' Dim mTagVersion(1) As Byte + ' Dim mTagSize(3) As Byte + ' Dim mHeaderFlags(0) As Byte + + ' ' start at the beginning of the file + ' mReader.Position = 0 + + ' ' read the file identifier and make sure the value equals "ID3" which indicates an ID3v2 tag + ' mReader.Read(mFileIdentifier, 0, 3) + ' Me.FileIdentifier = BytesToText(mFileIdentifier, True) + + ' If Me.FileIdentifier = "ID3" Then + + ' ' 1) get the tag version from the tag header + + ' ' read the 2 bytes where the tag version is stored + ' mReader.Read(mTagVersion, 0, 2) + + ' ' set the MP3 Tag Version + ' Me.TagVersion = mTagVersion(0) & "." & mTagVersion(1) + + ' ' 2) get the header flags from the tag header + ' 'TODO: handle multiple versions here, e.g. v2.4.0 has 4 header flags where v.2.3.0 only has 3 + + ' ' read the 1 byte where the header flags are stored + ' mReader.Read(mHeaderFlags, 0, 1) + + ' ' set the MP3 Header Flags + ' If BitManipulator.ExamineBit(mHeaderFlags(0), 8) = True Then Me.HeaderFlags = "Unsynchronization" + ' If BitManipulator.ExamineBit(mHeaderFlags(0), 7) = True Then Me.HeaderFlags &= ", " & "Extended Header" + ' If BitManipulator.ExamineBit(mHeaderFlags(0), 6) = True Then Me.HeaderFlags &= ", " & "Experimental Indicator" + + ' ' 3) get the tag size from the tag header + + ' ' read the 4 bytes where the tag size is stored + ' mReader.Read(mTagSize, 0, 4) + + ' ' set the MP3 Tag Size + ' Me.TagSize = GetID3EncodedSize(mTagSize) + + ' ' read the entire tag, minus the header + + ' Dim mEntireTag(Me.TagSize - 1) As Byte + ' mReader.Read(mEntireTag, 0, Me.TagSize) + + ' ' increment by 1 char + ' ' if char = 0 then end current find + ' Dim val As String = "" + ' For i As Integer = 0 To mEntireTag.Length - 1 + + ' Dim mNextByte As Byte = mEntireTag(i) + ' Dim mNextChar As String + + ' If mNextByte > 31 And mNextByte < 127 Then + ' mNextChar = Chr(mNextByte) + ' val &= mNextChar + ' Else + ' ' stop here and find the next valid char + ' End If + + ' Next + + ' 'Exit Sub + + ' mReader.Position = 10 + + + ' ' 4) get the frames and parse them + + ' Do Until mReader.Position >= Me.TagSize ' TODO change 800 + + ' ' 1) get the next frame + + ' Dim mFrame As New FrameBase + + ' Dim mFrameIDBytes() As Byte + ' Dim mFrameSizeBytes() As Byte + ' Dim mFrameFlagsBytes(1) As Byte + ' Dim mFrameValueBytes() As Byte + + ' ' TODO: Me.TagVersion contains the ID3v2 version, so 2.0 denotes ID3v2.2.0 + ' Select Case Me.TagVersion + + ' Case "2.0" + + ' ReDim mFrameIDBytes(2) + ' ReDim mFrameSizeBytes(2) + + ' mReader.Read(mFrameIDBytes, 0, 3) + ' mReader.Read(mFrameSizeBytes, 0, 3) + + ' mFrame.ID = BytesToText(mFrameIDBytes, False) + ' mFrame.Size = GetID3EncodedSize(mFrameSizeBytes) + + ' Case Else + + ' ReDim mFrameIDBytes(3) + ' ReDim mFrameSizeBytes(3) + + ' ' read the frame header + ' mReader.Read(mFrameIDBytes, 0, 4) + ' mReader.Read(mFrameSizeBytes, 0, 4) + ' mReader.Read(mFrameFlagsBytes, 0, 2) + + ' ' get the frame id, which indicates the type of frame + ' mFrame.ID = BytesToText(mFrameIDBytes, False) + + ' ' get the frame size by reading the next four bytes and converting those bytes from HEX to DEC + ' 'mFrame.Size = mFrameSizeBytes(0) + mFrameSizeBytes(1) + mFrameSizeBytes(2) + mFrameSizeBytes(3) + ' mFrame.Size = GetID3EncodedSize(mFrameSizeBytes) + 10 + + ' ' get the frame flags which will not be used + ' 'mFrame.Flags = BytesToText(mFrameFlagsBytes, False) + + ' If BitManipulator.ExamineBit(mFrameFlagsBytes(0), 8) = True Then mFrame.Flags &= "Tag Alter Preservation, " + ' If BitManipulator.ExamineBit(mFrameFlagsBytes(0), 7) = True Then mFrame.Flags &= "File Alter Preservation, " + ' If BitManipulator.ExamineBit(mFrameFlagsBytes(0), 6) = True Then mFrame.Flags &= "Read Only, " + + ' If BitManipulator.ExamineBit(mFrameFlagsBytes(1), 8) = True Then mFrame.Flags &= "Compression, " + ' If BitManipulator.ExamineBit(mFrameFlagsBytes(1), 7) = True Then mFrame.Flags &= "Encryption, " + ' If BitManipulator.ExamineBit(mFrameFlagsBytes(1), 6) = True Then mFrame.Flags &= "Group Identity" + + ' End Select + + ' ' get the frame value + ' ReDim mFrameValueBytes(mFrame.Size - 1) + ' mReader.Read(mFrameValueBytes, 0, mFrame.Size) + ' 'mFrame.Value = BytesToText(mFrameValueBytes, True) + ' mFrame.ValueBytes = mFrameValueBytes + + ' ' add the frame to the collection + ' Me.Frames.Add(mFrame) + + ' '' determine what to do with the frame + ' 'Select Case mFrameID + ' ' Case "TIT2" ' Title + ' ' Me.Title = mFrame + ' ' Case "TPE1" ' Artist + ' ' Me.Artist = mFrame + ' ' Case "TALB" ' Album + ' ' Me.Album = mFrame + ' ' Case "TRCK" ' Track number + ' ' Me.TrackNumber = mFrame + ' ' Case "TLEN" ' Length of song in milliseconds + + ' ' Case "COMM" ' Comments + ' ' Me.Comments = mFrame + ' ' Case "TCON" ' Content Type (aka Genre) + ' ' Me.Genre = mFrame + ' ' Case "TDAT", "TDRC" ' Date (aka Year) + ' ' Me.Year = mFrame + ' 'End Select + + ' Loop + + ' Else + + ' MsgBox("Could not find an ID3v2 tag!") + + ' End If + + ' mReader.Close() + + ' ' get the raw info + ' mReader = argFileInfo.OpenRead + ' mReader.Position = 0 + ' Dim mRawInfo(4999) As Byte ' get the first megabyte of raw data as ASCII + ' mReader.Position = 0 + ' mReader.Read(mRawInfo, 0, 5000) + ' Me.RawAscii = BytesToText(mRawInfo, False) + ' Me.RawBytes = BytesToAsciiCodes(mRawInfo) + + 'End Sub + + 'TODO: Descriptor 3bytes -> Tag Version 2bytes -> Header Flags 1byte -> Size 4bytes -> Frames Nbytes + Sub ParseTag(ByVal argFileInfo As IO.FileInfo) + + ' create a file reader to read the tag data + gTagReader = argFileInfo.OpenRead + + ' parse the tag version + ParseTagVersion() + + ' parse the tag header and frames according to version + Select Case Me.TagVersion + Case "2.0" + ParseHeaderV2() + ParseFramesV2() ' FrameID 3bytes FrameSize 3bytes FrameData Nbytes + Case "3.0" + ParseHeaderV4() + ParseFramesV3() + Case "4.0" + ParseHeaderV4() + ParseFramesV4() + Case "Unknown Descriptor" + + End Select + + ' close the file handle (remove the lock) + gTagReader.Close() + gTagReader.Dispose() + + End Sub + + Sub ParseTagVersion() + + Dim mTagDescriptor(2) As Byte + Dim mTagVersionBytes(1) As Byte + + ' read the tag info + gTagReader.Read(mTagDescriptor, 0, 3) + gTagReader.Read(mTagVersionBytes, 0, 2) + + If BytesToText(mTagDescriptor, False) = "ID3" Then + Me.FileIdentifier = "ID3" + Me.TagVersion = mTagVersionBytes(0) & "." & mTagVersionBytes(1) + Else + Me.TagVersion = "" + End If + + End Sub + + Sub ParseFramesV2() + + ' write the tag data to file for analysis + 'Dim mPos As Integer = gTagReader.Position + 'Dim b(Me.TagSize - mPos) As Byte + 'gTagReader.Read(b, 0, Me.TagSize - mPos) + 'Dim f As New IO.StreamWriter("C:\tag.txt") + 'For i As Integer = 0 To b.Length - 1 + ' f.Write(Chr(b(i))) + 'Next + 'f.WriteLine("-----") + 'For i As Integer = 0 To b.Length - 1 + ' f.WriteLine(b(i) & vbTab & vbTab & Chr(b(i))) + 'Next + 'f.Dispose() + + 'gTagReader.Position = mPos + + gTagReader.Position = 10 + + Do Until gTagReader.Position >= Me.TagSize + + Dim mFrame As New FrameBase + Dim mFrameIdBytes(2) As Byte + Dim mFrameSizeBytes(2) As Byte + + ' read the FrameID, FrameSize and FrameFlags + gTagReader.Read(mFrameIdBytes, 0, 3) + gTagReader.Read(mFrameSizeBytes, 0, 3) + + ' exit out if padding found (byte = 0) + If mFrameIdBytes(0) = 0 Then + Exit Do + End If + + ' parse the Frame ID + mFrame.ID = BytesToText(mFrameIdBytes, False) + + ' parse the Frame Size (4 bytes) + ' TODO: GetID3EncodedSize does not seem to work for frame size, only for tag size, fix it + 'mFrame.Size = GetID3EncodedSize(mFrameSizeBytes) + 10 + 'Return CByte(argBytes(0)) Or (CInt(argBytes(1)) << 8) Or (CInt(argBytes(2)) << 16) Or (CInt(argBytes(3)) << 24) + 'mFrame.Size = (65536 * (mFrameSizeBytes(0) * 256 + mFrameSizeBytes(1))) + (mFrameSizeBytes(2) * 256 + mFrameSizeBytes(3)) + 'mFrame.Size = mFrameSizeBytes(0) + mFrameSizeBytes(1) + mFrameSizeBytes(2) + + Dim mSizeV2 As Integer = GetID3EncodedSizeV2(mFrameSizeBytes) '+ 10 + 'Dim mSizeV3 As Integer = GetID3EncodedSizeV3(mFrameSizeBytes) + 'Dim mSizeV4 As Integer = GetID3EncodedSizeV4(mFrameSizeBytes) '+ 10 + + mFrame.Size = mSizeV2 + + ' read the Frame Data (mFrame.Size - 10 bytes) + ReDim mFrame.ValueBytes(mFrame.Size) + gTagReader.Read(mFrame.ValueBytes, 0, mFrame.Size) + + ' check the Frame Data + Dim mVal As String = mFrame.Value + + ' add the frame to the collection + Me.Frames.Add(mFrame) + + Loop + + End Sub + + Sub ParseFramesV3() + + '' write the tag data to file for analysis + 'Dim mPos As Integer = gTagReader.Position + 'Dim b(Me.TagSize - mPos) As Byte + 'gTagReader.Read(b, 0, Me.TagSize - mPos) + 'Dim f As New IO.StreamWriter("C:\tag.txt") + 'For i As Integer = 0 To b.Length - 1 + ' If b(i) > 32 And b(i) < 128 Then + ' f.Write(Chr(b(i))) + ' Else + ' f.Write("?") + ' End If + 'Next + 'f.WriteLine("-----") + 'For i As Integer = 0 To b.Length - 1 + ' f.WriteLine(b(i) & vbTab & vbTab & Chr(b(i))) + 'Next + 'f.Dispose() + + gTagReader.Position = 10 + + Do Until gTagReader.Position >= Me.TagSize + + Dim mFrame As New FrameBase + Dim mFrameIdBytes(3) As Byte + Dim mFrameSizeBytes(3) As Byte + Dim mFrameFlagsBytes(1) As Byte + + ' read the FrameID, FrameSize and FrameFlags + gTagReader.Read(mFrameIdBytes, 0, 4) + gTagReader.Read(mFrameSizeBytes, 0, 4) + gTagReader.Read(mFrameFlagsBytes, 0, 2) + + ' exit out if padding (bytes = 0) + If mFrameIdBytes(0) = 0 Then + Exit Do + End If + + ' parse the Frame ID (4 bytes) + Dim mFrameID As String = BytesToText(mFrameIdBytes, False) + mFrame.ID = mFrameID + + ' parse the Frame Size (4 bytes) + ' TODO: GetID3EncodedSize does not seem to work for frame size, only for tag size, fix it + 'mFrame.Size = GetID3EncodedSize(mFrameSizeBytes) + 10 + 'Return CByte(argBytes(0)) Or (CInt(argBytes(1)) << 8) Or (CInt(argBytes(2)) << 16) Or (CInt(argBytes(3)) << 24) + 'mFrame.Size = (65536 * (mFrameSizeBytes(0) * 256 + mFrameSizeBytes(1))) + (mFrameSizeBytes(2) * 256 + mFrameSizeBytes(3)) + + 'Dim mSizeV2 As Integer = GetID3EncodedSizeV2(mFrameSizeBytes) '+ 10 + Dim mSizeV3 As Integer = GetID3EncodedSizeV3(mFrameSizeBytes) + 'Dim mSizeV4 As Integer = GetID3EncodedSizeV4(mFrameSizeBytes) '+ 10 + + mFrame.Size = mSizeV3 + + ' preview the flags as a string for debug + Dim flags As String = GetBitString(mFrameFlagsBytes) + + ' parse the Frame Flags (2 bytes) + If BitManipulator.ExamineBit(mFrameFlagsBytes(1), 8) = True Then mFrame.Flags &= "Tag Alter Preservation, " + If BitManipulator.ExamineBit(mFrameFlagsBytes(1), 7) = True Then mFrame.Flags &= "File Alter Preservation, " + If BitManipulator.ExamineBit(mFrameFlagsBytes(1), 6) = True Then mFrame.Flags &= "Read Only, " + + If BitManipulator.ExamineBit(mFrameFlagsBytes(0), 8) = True Then mFrame.Flags &= "Compression, " + If BitManipulator.ExamineBit(mFrameFlagsBytes(0), 7) = True Then mFrame.Flags &= "Encryption, " + If BitManipulator.ExamineBit(mFrameFlagsBytes(0), 6) = True Then mFrame.Flags &= "Group Identity" + + ' read the Frame Data (mFrame.Size - 10 bytes) + ReDim mFrame.ValueBytes(mFrame.Size) + gTagReader.Read(mFrame.ValueBytes, 0, mFrame.Size) + + ' check the Frame Data + Dim mVal As String = mFrame.Value + + ' add the frame to the collection + Me.Frames.Add(mFrame) + + Loop + + End Sub + + Sub ParseFramesV4() + + '' write the tag data to file for analysis + 'Dim mPos As Integer = gTagReader.Position + 'Dim b(Me.TagSize - mPos) As Byte + 'gTagReader.Read(b, 0, Me.TagSize - mPos) + 'Dim f As New IO.StreamWriter("C:\tag.txt") + 'For i As Integer = 0 To b.Length - 1 + ' If b(i) > 32 And b(i) < 128 Then + ' f.Write(Chr(b(i))) + ' Else + ' f.Write("?") + ' End If + 'Next + 'f.WriteLine("-----") + 'For i As Integer = 0 To b.Length - 1 + ' f.WriteLine(b(i) & vbTab & vbTab & Chr(b(i))) + 'Next + 'f.Dispose() + + gTagReader.Position = 10 + + Do Until gTagReader.Position >= Me.TagSize + + Dim mFrame As New FrameBase + Dim mFrameIdBytes(3) As Byte + Dim mFrameSizeBytes(3) As Byte + Dim mFrameFlagsBytes(1) As Byte + + ' read the FrameID, FrameSize and FrameFlags + gTagReader.Read(mFrameIdBytes, 0, 4) + gTagReader.Read(mFrameSizeBytes, 0, 4) + gTagReader.Read(mFrameFlagsBytes, 0, 2) + + ' exit out if padding (bytes = 0) + If mFrameIdBytes(0) = 0 Then + Exit Do + End If + + ' parse the Frame ID (4 bytes) + Dim mFrameID As String = BytesToText(mFrameIdBytes, False) + mFrame.ID = mFrameID + + ' parse the Frame Size (4 bytes) + ' TODO: GetID3EncodedSize does not seem to work for frame size, only for tag size, fix it + 'mFrame.Size = GetID3EncodedSize(mFrameSizeBytes) + 10 + 'Return CByte(argBytes(0)) Or (CInt(argBytes(1)) << 8) Or (CInt(argBytes(2)) << 16) Or (CInt(argBytes(3)) << 24) + 'mFrame.Size = (65536 * (mFrameSizeBytes(0) * 256 + mFrameSizeBytes(1))) + (mFrameSizeBytes(2) * 256 + mFrameSizeBytes(3)) + + Dim mSizeV2 As Integer = GetID3EncodedSizeV2(mFrameSizeBytes) '+ 10 + Dim mSizeV3 As Integer = GetID3EncodedSizeV3(mFrameSizeBytes) + Dim mSizeV4 As Integer = GetID3EncodedSizeV4(mFrameSizeBytes) '+ 10 + + mFrame.Size = mSizeV4 + + ' preview the flags as a string for debug + Dim flags As String = GetBitString(mFrameFlagsBytes) + + ' parse the Frame Flags (2 bytes) + If BitManipulator.ExamineBit(mFrameFlagsBytes(1), 7) = True Then mFrame.Flags &= "Tag Alter Preservation, " + If BitManipulator.ExamineBit(mFrameFlagsBytes(1), 6) = True Then mFrame.Flags &= "File Alter Preservation, " + If BitManipulator.ExamineBit(mFrameFlagsBytes(1), 5) = True Then mFrame.Flags &= "Read Only, " + + If BitManipulator.ExamineBit(mFrameFlagsBytes(0), 7) = True Then mFrame.Flags &= "Group Identity, " + If BitManipulator.ExamineBit(mFrameFlagsBytes(0), 4) = True Then mFrame.Flags &= "Compression, " + If BitManipulator.ExamineBit(mFrameFlagsBytes(0), 3) = True Then mFrame.Flags &= "Encryption" + If BitManipulator.ExamineBit(mFrameFlagsBytes(0), 2) = True Then mFrame.Flags &= "Unsynchronization" + If BitManipulator.ExamineBit(mFrameFlagsBytes(0), 1) = True Then mFrame.Flags &= "Data Length Indicator" + + ' read the Frame Data (mFrame.Size - 10 bytes) + ReDim mFrame.ValueBytes(mFrame.Size) + gTagReader.Read(mFrame.ValueBytes, 0, mFrame.Size) + + ' check the Frame Data + Dim mVal As String = mFrame.Value + + ' add the frame to the collection + Me.Frames.Add(mFrame) + + Loop + + End Sub + + Function GetBitString(ByVal argBytes() As Byte) As String + Dim s As String = "" + For i As Integer = 0 To argBytes.Length - 1 + s &= BitManipulator.ExamineBit(argBytes(i), 0) + s &= BitManipulator.ExamineBit(argBytes(i), 1) + s &= BitManipulator.ExamineBit(argBytes(i), 2) + s &= BitManipulator.ExamineBit(argBytes(i), 3) + s &= BitManipulator.ExamineBit(argBytes(i), 4) + s &= BitManipulator.ExamineBit(argBytes(i), 5) + s &= BitManipulator.ExamineBit(argBytes(i), 6) + s &= BitManipulator.ExamineBit(argBytes(i), 7) + s &= BitManipulator.ExamineBit(argBytes(i), 8) + Next + Return s + End Function + + Sub ParseHeaderV2() + + Dim mHeaderFlags(1) As Byte + Dim mTagSize(3) As Byte + + ' read the 1 byte where the header flags are stored + gTagReader.Read(mHeaderFlags, 0, 1) + + ' set the MP3 Header Flags + If BitManipulator.ExamineBit(mHeaderFlags(0), 8) = True Then Me.HeaderFlags = "Unsynchronization" + If BitManipulator.ExamineBit(mHeaderFlags(0), 7) = True Then Me.HeaderFlags &= ", " & "Extended Header" + If BitManipulator.ExamineBit(mHeaderFlags(0), 6) = True Then Me.HeaderFlags &= ", " & "Experimental Indicator" + + ' 3) get the tag size from the tag header + + ' read the 4 bytes where the tag size is stored + gTagReader.Read(mTagSize, 0, 4) + + ' set the MP3 Tag Size + Me.TagSize = GetID3EncodedSizeV4(mTagSize) + + ' read the entire tag, minus the header + 'Dim mEntireTag(Me.TagSize - 1) As Byte + 'gTagReader.Read(mEntireTag, 0, Me.TagSize) + + '' increment by 1 char + '' if char = 0 then end current find + 'Dim val As String = "" + 'For i As Integer = 0 To mEntireTag.Length - 1 + + ' Dim mNextByte As Byte = mEntireTag(i) + ' Dim mNextChar As String + + ' If mNextByte > 31 And mNextByte < 127 Then + ' mNextChar = Chr(mNextByte) + ' val &= mNextChar + ' Else + ' ' stop here and find the next valid char + ' End If + + 'Next + + 'gTagString = val + + End Sub + + Sub ParseHeaderV4() + + Dim mHeaderFlags(1) As Byte + Dim mTagSize(3) As Byte + + ' read the 1 byte where the header flags are stored + gTagReader.Read(mHeaderFlags, 0, 1) + + ' set the MP3 Header Flags + If BitManipulator.ExamineBit(mHeaderFlags(0), 8) = True Then Me.HeaderFlags = "Unsynchronization" + If BitManipulator.ExamineBit(mHeaderFlags(0), 7) = True Then Me.HeaderFlags &= ", " & "Extended Header" + If BitManipulator.ExamineBit(mHeaderFlags(0), 6) = True Then Me.HeaderFlags &= ", " & "Experimental Indicator" + If BitManipulator.ExamineBit(mHeaderFlags(0), 5) = True Then Me.HeaderFlags &= ", " & "Footer" + + ' 3) get the tag size from the tag header + + ' read the 4 bytes where the tag size is stored + gTagReader.Read(mTagSize, 0, 4) + + ' set the MP3 Tag Size + Me.TagSize = GetID3EncodedSizeV4(mTagSize) + + '' read the entire tag, minus the header + + 'Dim mEntireTag(Me.TagSize - 1) As Byte + 'gTagReader.Read(mEntireTag, 0, Me.TagSize) + + '' increment by 1 char + '' if char = 0 then end current find + 'Dim val As String = "" + 'For i As Integer = 0 To mEntireTag.Length - 1 + + ' Dim mNextByte As Byte = mEntireTag(i) + ' Dim mNextChar As String + + ' If mNextByte > 31 And mNextByte < 127 Then + ' mNextChar = Chr(mNextByte) + ' val &= mNextChar + ' Else + ' ' stop here and find the next valid char + ' End If + + 'Next + + 'gTagString = val + + End Sub + +End Class \ No newline at end of file diff --git a/Perry's ID3 Tag Library/MP3File.vb b/Perry's ID3 Tag Library/MP3File.vb new file mode 100644 index 0000000..a3e3731 --- /dev/null +++ b/Perry's ID3 Tag Library/MP3File.vb @@ -0,0 +1,148 @@ +Public Class MP3File + + Public FileInfo As IO.FileInfo + Public Tag1 As ID3v1Tag + Public Tag2 As ID3v2Tag + + ''' + ''' Retrieves the ID3 tag version. + ''' + ''' + ''' + ''' + Property TagVersion() As String + Get + Dim val As String = "" + If Me.Tag1.TagVersion <> "" Then val = Me.Tag1.TagVersion + If Me.Tag2.TagVersion <> "" Then val = Me.Tag2.TagVersion + Return val + End Get + Set(ByVal value As String) + + End Set + End Property + + ''' + ''' Retrieves the most accurate Artist associated with this MP3 file (preferring ID3v2 info over ID3v1 info). + ''' + ''' + ''' + ''' + Property Artist() As String + Get + Dim val As String = "" + If Me.Tag1.Artist <> "" Then val = Me.Tag1.Artist + If Me.Tag2.Artist <> "" Then val = Me.Tag2.Artist + Return val + End Get + Set(ByVal value As String) + + End Set + End Property + + ''' + ''' Retrieves the most accurate Album title associated with this MP3 file (preferring ID3v2 info over ID3v1 info). + ''' + ''' + ''' + ''' + Property Album() As String + Get + Dim val As String = "" + If Me.Tag1.Album <> "" Then val = Me.Tag1.Album + If Me.Tag2.Album <> "" Then val = Me.Tag2.Album + Return val + End Get + Set(ByVal value As String) + + End Set + End Property + + ''' + ''' Retrieves the most accurate track Title associated with this MP3 file (preferring ID3v2 info over ID3v1 info). + ''' + ''' + ''' + ''' + Property Title() As String + Get + Dim val As String = "" + If Me.Tag1.Title <> "" Then val = Me.Tag1.Title + If Me.Tag2.Title <> "" Then val = Me.Tag2.Title + Return val + End Get + Set(ByVal value As String) + + End Set + End Property + + ''' + ''' Retrieves the most accurate Year associated with this MP3 file (preferring ID3v2 info over ID3v1 info). + ''' + ''' + ''' + ''' + Property Year() As String + Get + Dim val As String = "" + If Me.Tag1.Year <> "" Then val = Me.Tag1.Year + If Me.Tag2.Year <> "" Then val = Me.Tag2.Year + Return val + End Get + Set(ByVal value As String) + + End Set + End Property + + ''' + ''' Retrieves the most accurate Comment associated with this MP3 file (preferring ID3v2 info over ID3v1 info). + ''' + ''' + ''' + ''' + Property Comment() As String + Get + Dim val As String = "" + If Me.Tag1.Comment <> "" Then val = Me.Tag1.Comment + If Me.Tag2.Comment <> "" Then val = Me.Tag2.Comment + Return val + End Get + Set(ByVal value As String) + + End Set + End Property + + ''' + ''' Retrieves the most accurate Genre associated with this MP3 file (preferring ID3v2 info over ID3v1 info). + ''' + ''' + ''' + ''' + Property Genre() As String + Get + Dim val As String = "" + If Me.Tag1.Genre <> "" Then val = Me.Tag1.Genre + If Me.Tag2.Genre <> "" Then val = Me.Tag2.Genre + Return val + End Get + Set(ByVal value As String) + + End Set + End Property + + ''' + ''' When instantiating a new instance of this class, the MP3 file is parsed immediately and the Tag1/Tag2 properties are populated. + ''' + ''' Path to the MP3 file we wish to parse. + ''' + Sub New(ByVal argFilePath As String) + + Me.FileInfo = New IO.FileInfo(argFilePath) + + ' TODO: file lock happens here, remove the lock after loading the file data: + Me.Tag1 = New ID3v1Tag(Me.FileInfo) + Me.Tag2 = New ID3v2Tag(Me.FileInfo) + + End Sub + +End Class \ No newline at end of file diff --git a/Perry's ID3 Tag Library/My Project/Application.Designer.vb b/Perry's ID3 Tag Library/My Project/Application.Designer.vb new file mode 100644 index 0000000..6d7ac5e --- /dev/null +++ b/Perry's ID3 Tag Library/My Project/Application.Designer.vb @@ -0,0 +1,13 @@ +'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:2.0.50727.4959 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + diff --git a/Perry's ID3 Tag Library/My Project/Application.myapp b/Perry's ID3 Tag Library/My Project/Application.myapp new file mode 100644 index 0000000..758895d --- /dev/null +++ b/Perry's ID3 Tag Library/My Project/Application.myapp @@ -0,0 +1,10 @@ + + + false + false + 0 + true + 0 + 1 + true + diff --git a/Perry's ID3 Tag Library/My Project/AssemblyInfo.vb b/Perry's ID3 Tag Library/My Project/AssemblyInfo.vb new file mode 100644 index 0000000..2e438f5 --- /dev/null +++ b/Perry's ID3 Tag Library/My Project/AssemblyInfo.vb @@ -0,0 +1,35 @@ +Imports System +Imports System.Reflection +Imports System.Runtime.InteropServices + +' General Information about an assembly is controlled through the following +' set of attributes. Change these attribute values to modify the information +' associated with an assembly. + +' Review the values of the assembly attributes + + + + + + + + + + +'The following GUID is for the ID of the typelib if this project is exposed to COM + + +' Version information for an assembly consists of the following four values: +' +' Major Version +' Minor Version +' Build Number +' Revision +' +' You can specify all the values or you can default the Build and Revision Numbers +' by using the '*' as shown below: +' + + + diff --git a/Perry's ID3 Tag Library/My Project/Resources.Designer.vb b/Perry's ID3 Tag Library/My Project/Resources.Designer.vb new file mode 100644 index 0000000..b577dbf --- /dev/null +++ b/Perry's ID3 Tag Library/My Project/Resources.Designer.vb @@ -0,0 +1,77 @@ +'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:2.0.50727.4959 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + +Imports System + +Namespace My.Resources + + 'This class was auto-generated by the StronglyTypedResourceBuilder + 'class via a tool like ResGen or Visual Studio. + 'To add or remove a member, edit your .ResX file then rerun ResGen + 'with the /str option, or rebuild your VS project. + ''' + ''' A strongly-typed resource class, for looking up localized strings, etc. + ''' + _ + Friend Module Resources + + Private resourceMan As Global.System.Resources.ResourceManager + + Private resourceCulture As Global.System.Globalization.CultureInfo + + ''' + ''' Returns the cached ResourceManager instance used by this class. + ''' + _ + Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager + Get + If Object.ReferenceEquals(resourceMan, Nothing) Then + Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("ID3TagLibrary.Resources", GetType(Resources).Assembly) + resourceMan = temp + End If + Return resourceMan + End Get + End Property + + ''' + ''' Overrides the current thread's CurrentUICulture property for all + ''' resource lookups using this strongly typed resource class. + ''' + _ + Friend Property Culture() As Global.System.Globalization.CultureInfo + Get + Return resourceCulture + End Get + Set + resourceCulture = value + End Set + End Property + + Friend ReadOnly Property picture() As System.Drawing.Bitmap + Get + Dim obj As Object = ResourceManager.GetObject("picture", resourceCulture) + Return CType(obj,System.Drawing.Bitmap) + End Get + End Property + + Friend ReadOnly Property textfield_rename() As System.Drawing.Bitmap + Get + Dim obj As Object = ResourceManager.GetObject("textfield_rename", resourceCulture) + Return CType(obj,System.Drawing.Bitmap) + End Get + End Property + End Module +End Namespace diff --git a/Perry's ID3 Tag Library/My Project/Resources.resx b/Perry's ID3 Tag Library/My Project/Resources.resx new file mode 100644 index 0000000..510a9ad --- /dev/null +++ b/Perry's ID3 Tag Library/My Project/Resources.resx @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAjxJREFUOE+lk+9P + EnEcx+uP6lnrx9aj1mqz5uxBtkbMRa3WcukwE9F5JvFDTwFBusgChZISRZOwglEy5VduOZu1msWPAd4B + J+ej3n2PBwTCaqvbXrfv/Xp93vt8P3cQwIH/OkSB1R1RMy+iqTFnmNPYG2Aj96qgHWHO7Apry8XFEzMb + TWey2Z9Fnge/K/yRbFFAmi3A8CzCVgRi5UKRx9jcNtRzMSjmp2Fdo+GI98MWU2LUr8KVBybcsgTQYfmI + TEHAqDPKVQRaElusbJjfBrWwCOsqjakP7TCvtsGwIoExJIPK2wfZ+BPImQ2kuQaCAhGML3yHwjMJO6lq + DEkx/O4CVP7zoN62QOO/iYsj99H9aBMprkQSRGoTcERgXvyBHrcVD8Pd0AVbQb1pRu9yE+6+agLlu4ZW + 3T30Pv6EJLtbL2B5AZaXCVBuD2j/ILRBCRTLZyFfOoMeXwvuPO+ETD+JfvsWkjsNEuyQ7jLeJGhPHJ0O + BtTsDQz5pKC8l9DlvIrL9DCJH8Tg9Od6gbj3OdJZqy9Vloy4Y7itbMWA5gQo1XEo+pqhtL2HZuYrVE+/ + ILE/gSjI5gXIHafRMXUK7baTMHUdwjpzDnGCa+Ao2kzHIDUegUR/uF6gtq1xOSLwb72uEFx3IbQygbjr + OgKbSzXPErkSaEfVLmjKglLNS9Wy/etETqgV6J3hbzk2jzxpZJ7fA1dGAEeu2Tr2kCmPcvT3KE+4IkOm + mWhAHA4x2t8g/wFHvtFVRllc/Cu/AAZ/6ElKbpVOAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAALJJREFUOE/FkkEK + wjAQRfWq2SZGbY0g3iFWS0ApIh7F1k0uEO0NcojANwniqoSWLAx8spj5bz7DzAHMsl4A5CjLHNPnTI8A + rTVSopRCSgkhxGBfBDjnkmKMDdattfgB6KEDq55g/l9UXscO3CvACSHjAMW5R3F5Y9MY7G4vLE/tNEDZ + 9Ci9eXs12N8NVvUEQIz+jR0mB/O6foxPkFpkcgdhkykFs1IKnPPBvvxDyr7EvwM+s0MMBk9Z0EoAAAAA + SUVORK5CYII= + + + \ No newline at end of file diff --git a/Perry's ID3 Tag Library/My Project/Settings.Designer.vb b/Perry's ID3 Tag Library/My Project/Settings.Designer.vb new file mode 100644 index 0000000..47c3509 --- /dev/null +++ b/Perry's ID3 Tag Library/My Project/Settings.Designer.vb @@ -0,0 +1,73 @@ +'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:2.0.50727.4959 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + + +Namespace My + + _ + Partial Friend NotInheritable Class MySettings + Inherits Global.System.Configuration.ApplicationSettingsBase + + Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings),MySettings) + +#Region "My.Settings Auto-Save Functionality" +#If _MyType = "WindowsForms" Then + Private Shared addedHandler As Boolean + + Private Shared addedHandlerLockObject As New Object + + _ + Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs) + If My.Application.SaveMySettingsOnExit Then + My.Settings.Save() + End If + End Sub +#End If +#End Region + + Public Shared ReadOnly Property [Default]() As MySettings + Get + +#If _MyType = "WindowsForms" Then + If Not addedHandler Then + SyncLock addedHandlerLockObject + If Not addedHandler Then + AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings + addedHandler = True + End If + End SyncLock + End If +#End If + Return defaultInstance + End Get + End Property + End Class +End Namespace + +Namespace My + + _ + Friend Module MySettingsProperty + + _ + Friend ReadOnly Property Settings() As Global.ID3TagLibrary.My.MySettings + Get + Return Global.ID3TagLibrary.My.MySettings.Default + End Get + End Property + End Module +End Namespace diff --git a/Perry's ID3 Tag Library/My Project/Settings.settings b/Perry's ID3 Tag Library/My Project/Settings.settings new file mode 100644 index 0000000..85b890b --- /dev/null +++ b/Perry's ID3 Tag Library/My Project/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Perry's ID3 Tag Library/Perry's ID3 Tag Library.vbproj b/Perry's ID3 Tag Library/Perry's ID3 Tag Library.vbproj new file mode 100644 index 0000000..6ddb8f7 --- /dev/null +++ b/Perry's ID3 Tag Library/Perry's ID3 Tag Library.vbproj @@ -0,0 +1,123 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {0AAD4FAD-D851-4A41-A299-B6728F05AA28} + Library + ID3TagLibrary + ID3TagLibrary + 512 + Windows + v3.5 + On + Binary + Off + On + true + ID3LibraryKeyFile.snk + + + true + full + true + true + bin\Debug\ + ID3TagLibrary.xml + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + true + + + pdbonly + false + true + true + bin\Release\ + ID3TagLibrary.xml + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + true + + + + + + + + 3.5 + + + 3.5 + + + 3.5 + + + + + + + + + + + + + + + + + + + + + + True + Application.myapp + + + True + True + Resources.resx + + + True + Settings.settings + True + + + + + VbMyResourcesResXFileCodeGenerator + Resources.Designer.vb + My.Resources + Designer + + + + + + + MyApplicationCodeGenerator + Application.Designer.vb + + + SettingsSingleFileGenerator + My + Settings.Designer.vb + + + + + + + + + \ No newline at end of file