From 47bdf8536586ec1cc408c785f582817d01867ffc Mon Sep 17 00:00:00 2001 From: Perry Butler Date: Tue, 10 Sep 2013 01:50:07 -0700 Subject: [PATCH] First Local Commit v0.4 --- Perry's ID3 Tag Library.sln | 20 + Perry's ID3 Tag Library/BitManipulator.vb | 39 + Perry's ID3 Tag Library/ComParser.vb | 40 + Perry's ID3 Tag Library/Documentation.doc | Bin 0 -> 37376 bytes Perry's ID3 Tag Library/Globals.vb | 180 +++++ Perry's ID3 Tag Library/ID3LibraryKeyFile.snk | Bin 0 -> 596 bytes Perry's ID3 Tag Library/ID3v1Tag.vb | 63 ++ Perry's ID3 Tag Library/ID3v2Tag.vb | 751 ++++++++++++++++++ Perry's ID3 Tag Library/MP3File.vb | 148 ++++ .../My Project/Application.Designer.vb | 13 + .../My Project/Application.myapp | 10 + .../My Project/AssemblyInfo.vb | 35 + .../My Project/Resources.Designer.vb | 77 ++ .../My Project/Resources.resx | 147 ++++ .../My Project/Settings.Designer.vb | 73 ++ .../My Project/Settings.settings | 7 + .../Perry's ID3 Tag Library.vbproj | 123 +++ 17 files changed, 1726 insertions(+) create mode 100644 Perry's ID3 Tag Library.sln create mode 100644 Perry's ID3 Tag Library/BitManipulator.vb create mode 100644 Perry's ID3 Tag Library/ComParser.vb create mode 100644 Perry's ID3 Tag Library/Documentation.doc create mode 100644 Perry's ID3 Tag Library/Globals.vb create mode 100644 Perry's ID3 Tag Library/ID3LibraryKeyFile.snk create mode 100644 Perry's ID3 Tag Library/ID3v1Tag.vb create mode 100644 Perry's ID3 Tag Library/ID3v2Tag.vb create mode 100644 Perry's ID3 Tag Library/MP3File.vb create mode 100644 Perry's ID3 Tag Library/My Project/Application.Designer.vb create mode 100644 Perry's ID3 Tag Library/My Project/Application.myapp create mode 100644 Perry's ID3 Tag Library/My Project/AssemblyInfo.vb create mode 100644 Perry's ID3 Tag Library/My Project/Resources.Designer.vb create mode 100644 Perry's ID3 Tag Library/My Project/Resources.resx create mode 100644 Perry's ID3 Tag Library/My Project/Settings.Designer.vb create mode 100644 Perry's ID3 Tag Library/My Project/Settings.settings create mode 100644 Perry's ID3 Tag Library/Perry's ID3 Tag Library.vbproj 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 0000000000000000000000000000000000000000..5f06c9cb956da59da7227504a525d176da9079e3 GIT binary patch literal 37376 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 ATmS$7 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..9618e7c2f9b702f3298d377391b9c6c52927445b GIT binary patch literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098q%ILSz3N9(r&`VN%CdoVi$uxI;ua(P= zgunIb=lXqWW$j=_oIQ7sEGli6&M-pQq*WkeXo7C67$H6Se~o_mq*6BO`6q;gh0rQf z&Y<5Ta=O<;MqOF2mqAU^%5~Cy6m1>0_vtVQK%X2t{1o75dV9VFTAvZzSp_AchhCnk z?WQh7*5}wbX;4!DGJF^RRtLE1@omBs<3ZmX+rXUGm-SBD-R0$evpl>+3nlmTj0XWv zO^#J74EABYK0eJAY}9D-KPi4{FW5(4<5IXxSO&@x`p-pSqzENGjpt5#-(5542}Ve; zP6}JfelsVn+GE=u$!-!uy@Da~y@qZ$*3JbYu1CFiRJQXys~yEgPKClmjXK-~gh z;4F$~Y2VO~LU5BjK{T`|Rvox`5NZwjoiy^jX{$X`zjrJ(%{*yZK!`*ngD9{>oZh!g zGIEn=`*=8i)d?x>J4N=ohm^*`vR&D?;3RAJGI36`CQ4egA8nXpv(rlAT3>e5st(z1BT#K|?B*LAAxh>}N%UAHzPqcu#AGqQdcI@9MF85F>y?0uag~=9kQ 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