Introduction
I have been using Notepad for sometime now, and use it for creating all types of files. I recently wanted to create an XML file for my MP3 collection and found that writing 5 to 8 tags for 350+ MP3s was going to be a task (for me, typing is a task). So, I decided to create a program that did just that, with validation as an added extra.
When I was in college (20 or so years ago), our professor always made us use some sort of pseudo-code to follow while we were creating our programs, which I totally forgot about until I decided to make this program.
Here is the Pseudo... Short Version
- Design the UI (using the pseudo that follows)
- Create a filename with the XML extension
- Validate, then accept the filename if it is good
- Select the MP3s and add them to a list box
- Create and write the tags to the file
- Display to the user what we have done so far (in a list box)
- Validate the file using XSD (LINQ to XML)
- After validating, open the file to see our handiwork
- Finally... reset, and repeat if required
Starting Point
The XML writer starts with all the buttons in the disabled state. You must complete the first task before continuing on to the next task. After creating the filename, validating it, selecting the MP3s, and writing tags, we are now at the validation part. We can now validate the file that we just created.
Private Sub buttonValidate_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles buttonValidate.Click
lstActions.Items.Add("Linking (LINQ to XML using XSD)")
Dim xsdMarkup As XElement = _
<schema xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" />
<element name=""MP3Info"" />
<complextype />
<sequence maxoccurs=""unbounded"" />
<element name=""TrackTitle"" type=""xsd:string"" />
<element name=""Artist"" type=""xsd:string"" />
<element name=""Length"" type=""xsd:string"" />
<element name=""Title"" type=""xsd:string"" />
<element name=""Genre"" type=""xsd:string"" />
</sequence />
</complextype />
</element />
</schema />
Dim schemas As XmlSchemaSet = New XmlSchemaSet()
schemas.Add("", xsdMarkup.CreateReader)
lstActions.Items.Add("Attempting to Validate")
Dim myDoc As XDocument = XDocument.Load(path & Trim(txtFileXML.Text))
errors = False
myDoc.Validate(schemas, AddressOf XSDErrors)
If errors = True Then
isValid = False
lstActions.Items.Add("File is InValid")
lblStatus.Text = "Invalid..."
buttonOpen.Enabled = True
Exit Sub
Else
isValid = True
lstActions.Items.Add("File is Valid")
lblStatus.Text = "Valid..."
End If
buttonOpen.Enabled = True
End Sub
I searched for code in MS-Help, and got nothing but old code that did not fare well with .NET v. 3.5. Most of the code was for .NET v. 1.1, which I later discovered due to errors in my code. I also found that errors were unacceptable when using XML. If you have errors, your program will crap out on you. So, you have to write error-free code, which I have finally accomplished through trial and error using all sorts of tidbits that I found in MS-Help.
Private Sub loadFiles(ByVal mediaType As String)
Dim supportedFiles As String
Select Case mediaType
Case "Audio"
supportedFiles = audioFiles
Case Else
supportedFiles = audioFiles
End Select
lstActions.Items.Add("Please wait...Creating File")
With ofd
.InitialDirectory = strPath
.Filter = supportedFiles
.CheckFileExists = True
.Multiselect = True
.RestoreDirectory = True
End With
If ofd.ShowDialog = Windows.Forms.DialogResult.OK Then
Using sw As StreamWriter = File.CreateText(path & Trim(txtFileXML.Text))
sw.WriteLine("")
sw.WriteLine("<mp3info />")
For Each Me.strFilePath In ofd.FileNames
strFileShow = GetFileName(strFilePath)
lstMP3.Items.Add(strFilePath)
MMedia.LoadMedia(strFilePath)
Dim fileInfo As New clsID3v1Reader(strFilePath)
sw.WriteLine(" <tracktitle />" & fileInfo.TrackTitle & _
"</tracktitle />")
sw.WriteLine(" <artist />" & fileInfo.Artist & "</artist />")
Dim secx, minx, mediaTotal As String
Dim mediaTimes As String
mediaTotal = CStr(Int(MMedia.MediaDuration))
secx = CStr(CDbl(mediaTotal) - (Int(CDbl(mediaTotal) / 60) * 60))
minx = CStr(Int((CDbl(mediaTotal) -
Int(CDbl(mediaTotal) / 3600) * 3600) / 60))
mediaTimes = minx.ToString() & ":" & secx.ToString
sw.WriteLine(" <length />" & mediaTimes & "</length />")
MMedia.UnLoadMedia(strFilePath)
sw.WriteLine(" ")
sw.WriteLine(" <genre />" & GetGenre(currentMP3) & "</genre />")
sw.WriteLine()
Next
sw.WriteLine("</mp3info />")
sw.Close()
End Using
End If
lstActions.Items.Add("File created - " & Trim(txtFileXML.Text))
lstActions.Items.Add("# of files selected..." & (lstMP3.Items.Count).ToString)
lblStatus.Text = (lstMP3.Items.Count).ToString & " files selected"
buttonValidate.Enabled = True
End Sub
Next... we can open the new file that we just created to see the results of our handiwork. I used the Process
class to open Notepad and display our file.
Private Sub buttonOpen_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles buttonOpen.Click
ProcessNotepad.StartInfo.FileName = path & Trim(txtFileXML.Text)
ProcessNotepad.Start()
ProcessNotepad.WaitForExit()
buttonReset.Enabled = True
End Sub
Using the Code
The XML writer creates mp3tag.xml files that can be used in WPF or Blend as a data source or as a play list, or whatever else XML files are used for. I believe it to be a good utility, but that's just me wishing.
The classes that I used in this program are re-edited classes that were found on this site and MS-Help. clsDirectXAudio.vb is from MMPlayer which can be found on this site, and clsID3TagReader.vb I believe was in 'Managing a MP3 Collection" which was on MS-Help as an MS-Word doc file. One last thing, the program cannot be run inside the IDE, it throws a Managed Code Exception. Make a .exe file and run it outside the IDE, it works fine.
Points of Interest
When I first started this program, I knew nothing about LINQ, XSD, or XML, now I know more than what I started with (which was a thimble full of nothing).
Please do not download this until I fix some bugs. I totally forgot about the apostrophies, ampersand, and the less-than and greater-than signs. I do not know how to read a character in a string
, and if I do find out, I do not know how to replace them using code, preferably VB.NET. Thank you for your patience on this matter. If someone could point me in the right direction on how to do this, I would greatly appreciate it!
Update
In the original, XMLWriter
, there were design flaws that created some nasty exceptions. It would throw an exception when it came across an ampersand or an apostrophy. I fixed it with a few replace statements in the correct spots. I also re-did the psuedo which is in the program disguised as labels. See the picture below.
Using the Code
After the program starts (intro picture), you will enter a filename with an XML extension and press the accept button (pictured above). Next...
Enter any or all your mp3 files, the program will then create your XML file and display it to you in the listbox
. Picture above. Next...
We validate our newly created XML file. With the use of a few replace statements in the right area, this took care of the exceptions that would occur when you picked an mp3 file with ampersands or apostrophies in the tracktitle, title or artist (example: Brooks & Dunn - She's not the cheatin' Kind). This would make the program crap out on you. This has been fixed. Picture above. Next... just hit the reset button and you are ready to do it all over again. Doing this multiple times would be useful as playlists in WPF® or Blend®. Picture below.
Apologies All Around
If you downloaded the original XMLWriter
, please delete it and use this updated version. It works so much better and the results are better also. I apologize for any inconvienience that this little mental mistake of mine may have cost you. Once again...apologies all around.
To the Authors…
To all the authors of code that I used (all names are in comments throughout the program), I thank you all very much. Special thanks go to MS-Help for having such a vast library of knowledge.