Click here to Skip to main content
15,881,882 members
Articles / Multimedia / DirectX

XML Writer for MP3 Tags, with XSD Validation Using LINQ to XML

Rate me:
Please Sign up or sign in to vote.
4.38/5 (5 votes)
26 Nov 2008CPOL5 min read 30K   294   13  
Creates MP3 tag XML files and validates them
Imports System.Xml
Imports System.Xml.Schema
Imports System
Imports System.IO
Imports System.IO.Path
Imports Microsoft.VisualBasic

Public Class frmXMLWriter
    '// variables, constants and Events //
    Public WithEvents MMedia As clsDirectXAudio
    Dim errors As Boolean = False
    Dim strPath As String = "C:\Users\" & GetUserName() & "\Music\"
    Dim path As String = "C:\Users\" & GetUserName() & "\Documents\"
    Dim audioFiles As String = "Audio Files (*.mp3)|*.mp3"
    Dim strFile As String = String.Empty
    Dim strFileShow As String = String.Empty
    Dim strFilePath As String = String.Empty
    Dim currentMP3 As String = String.Empty
    Dim isValid As Boolean = False

    'GetUserName is also from ms-help
    Function GetUserName() As String
        If TypeOf My.User.CurrentPrincipal Is  _
        Security.Principal.WindowsPrincipal Then
            Dim parts() As String = Split(My.User.Name, "\")
            Dim username As String = parts(1)
            Return username
        Else
            Return My.User.Name
        End If
    End Function

    'From ms-help
    Private Sub XSDErrors(ByVal o As Object, ByVal e As ValidationEventArgs)
        MessageBox.Show(e.Message)
        errors = True
    End Sub

    Private Sub txtFileXML_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtFileXML.TextChanged
        buttonAccept.Enabled = True
    End Sub

    Private Sub frmXMLWriter_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim mediaObj As New clsDirectXAudio
        MMedia = mediaObj
        ResetAll()
    End Sub

    Private Sub ResetAll()
        lblStatus.Text = "waiting..."
        isValid = False
        errors = False
        buttonAccept.Enabled = False
        buttonSelect.Enabled = False
        buttonValidate.Enabled = False
        buttonReset.Enabled = False
        buttonOpen.Enabled = False
        txtFileXML.Text = "*.xml"
        lstActions.Items.Clear()
        lstMP3.Items.Clear()
    End Sub

    Private Sub buttonAccept_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles buttonAccept.Click
        If txtFileXML.Text = "" Or GetExtension(txtFileXML.Text) <> ".xml" Then
            MessageBox.Show("File Name is not valid.", "Error creating file!", MessageBoxButtons.OK, MessageBoxIcon.Error)
            isValid = False
            txtFileXML.Text = "*.xml"
            txtFileXML.Focus()
            ResetAll()
            Exit Sub
        Else
            isValid = True
            lstActions.Items.Add("File Name is Valid")
            lblStatus.Text = "Valid"
            strFile = Trim(txtFileXML.Text)
            buttonSelect.Enabled = True
        End If
    End Sub

    Private Sub buttonSelect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles buttonSelect.Click
        LoadFiles("Audio")
    End Sub

    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 'OpenFileDialog Control
            .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("<?xml version=""1.0""?>")
                sw.WriteLine("<MP3Info>") 'Opening Tag for 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("<MP3Info>") 'Opening Tag for MP3Info
                    sw.WriteLine("    <TrackTitle>" & fileInfo.TrackTitle & "</TrackTitle>")
                    sw.WriteLine("    <Artist>" & fileInfo.Artist & "</Artist>")

                    'Lets get the time length of the mp3 file.
                    Dim secx, minx, mediaTotal As String
                    Dim mediaTimes As String
                    mediaTotal = CStr(Int(MMedia.MediaDuration))
                    'If mediaTotal < 1 Then mediaTotal = 1
                    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("    <Title>" & strFileShow & "</Title>")
                    sw.WriteLine("    <Genre>" & GetGenre(currentMP3) & "</Genre>")
                    'sw.WriteLine("</MP3Info>") 'Closing Tag for MP3Info
                    sw.WriteLine()
                Next

                sw.WriteLine("</MP3Info>") 'Closing Tag for MP3Info

                'Lets close the writer.
                sw.Close()

            End Using
        End If

        'Display again what we are doing for the user...
        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"

        'Make unenabled, Enabled.
        buttonValidate.Enabled = True
    End Sub

    Public Function GetGenre(ByVal strGenre As String) As String
        'This function takes the enum value from the
        'clsID3v1Reader and changes it back so we can 
        'understand it more clearly.
        Dim fileInfo As New clsID3v1Reader(strFilePath)
        Select Case fileInfo.Genre
            Case 0
                strGenre = "Blues"
            Case 1
                strGenre = "Classic Rock"
            Case 2
                strGenre = "Country"
            Case 3
                strGenre = "Dance"
            Case 4
                strGenre = "Disco"
            Case 5
                strGenre = "Funk"
            Case 6
                strGenre = "Grundge"
            Case 7
                strGenre = "HipHop"
            Case 8
                strGenre = "Jazz"
            Case 9
                strGenre = "Metal"
            Case 10
                strGenre = "NewAge"
            Case 11
                strGenre = "Oldies"
            Case 12
                strGenre = "Other"
            Case 13
                strGenre = "Pop"
            Case 14
                strGenre = "RnB"
            Case 15
                strGenre = "Rap"
            Case 16
                strGenre = "Reggae"
            Case 17
                strGenre = "Rock"
            Case 18
                strGenre = "Techno"
            Case 19
                strGenre = "Industrial"
            Case 20
                strGenre = "Alternative"
            Case 21
                strGenre = "Ska"
            Case 22
                strGenre = "Death Metal"
            Case 23
                strGenre = "Pranks"
            Case 24
                strGenre = "Soundtrack"
            Case 25
                strGenre = "EuroTechno"
            Case 26
                strGenre = "Ambient"
            Case 27
                strGenre = "Triphop"
            Case 28
                strGenre = "Vocal"
            Case 29
                strGenre = "JazzFunk"
            Case 30
                strGenre = "Fusion"
            Case 31
                strGenre = "Trance"
            Case 32
                strGenre = "Classical"
            Case 33
                strGenre = "Instrumental"
            Case 34
                strGenre = "Acid"
            Case 35
                strGenre = "House"
            Case 36
                strGenre = "Game"
            Case 37
                strGenre = "Sound Clip"
            Case 38
                strGenre = "Gospel"
            Case 39
                strGenre = "Noise"
            Case 40
                strGenre = "AlternRock"
            Case 41
                strGenre = "Bass"
            Case 42
                strGenre = "Soul"
            Case 43
                strGenre = "Punk"
            Case 44
                strGenre = "Space"
            Case 45
                strGenre = "Meditative"
            Case 46
                strGenre = "InstrumentalPop"
            Case 47
                strGenre = "InstrumentalRock"
            Case 48
                strGenre = "Ethnic"
            Case 49
                strGenre = "Gothic"
            Case 50
                strGenre = "Darkwave"
            Case 51
                strGenre = "TechnoIndustrial"
            Case 52
                strGenre = "Electronic"
            Case 53
                strGenre = "PopFolk"
            Case 54
                strGenre = "Eurodance"
            Case 55
                strGenre = "Dream"
            Case 56
                strGenre = "SouthernRock"
            Case 57
                strGenre = "Comedy"
            Case 58
                strGenre = "Cult"
            Case 59
                strGenre = "Gangsta"
            Case 60
                strGenre = "Top 40"
            Case 61
                strGenre = "ChristainRap"
            Case 62
                strGenre = "PopFunk"
            Case 63
                strGenre = "Jungle"
            Case 64
                strGenre = "NativeAmerican"
            Case 65
                strGenre = "Cabaret"
            Case 66
                strGenre = "NewWave"
            Case 67
                strGenre = "Psychadelic"
            Case 68
                strGenre = "Rave"
            Case 69
                strGenre = "Showtunes"
            Case 70
                strGenre = "Trailer"
            Case 71
                strGenre = "LoFi"
            Case 72
                strGenre = "Tribal"
            Case 73
                strGenre = "AcidPunk"
            Case 74
                strGenre = "AcidJazz"
            Case 75
                strGenre = "Polka"
            Case 76
                strGenre = "Retro"
            Case 77
                strGenre = "Musical"
            Case 78
                strGenre = "RocknRoll"
            Case 79
                strGenre = "Hardrock"
            Case 255
                strGenre = "None"
        End Select
        Return strGenre
    End Function

    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)")
        'XSD code was in ms-help
        'I re-edited it to fit the output in the xml file
        Dim xsdMarkup As XElement = _
        <xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
            <xsd:element name='MP3Info'>
                <xsd:complexType>
                    <xsd:sequence maxOccurs="unbounded">
                        <xsd:element name="TrackTitle" type="xsd:string"/>
                        <xsd:element name="Artist" type="xsd:string"/>
                        <xsd:element name="Length" type="xsd:string"/>
                        <xsd:element name="Title" type="xsd:string"/>
                        <xsd:element name="Genre" type="xsd:string"/>
                    </xsd:sequence>
                </xsd:complexType>
            </xsd:element>
        </xsd: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

    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

    Private Sub buttonReset_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles buttonReset.Click
        ResetAll()
    End Sub
End Class

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Retired
United States United States
I am currently retired.
I have no degree but I have some programming experience
when I was in college(Cobol, Pascal).

My accomplishments thus far are;
Best VB.Net article for January(2009)
Best VB.Net article for July(2009)

Comments and Discussions