[APORTE] Multimedia Playlist Editor (M3U y PLS)

Iniciado por Eleкtro, 22 Julio 2014, 02:04 AM

0 Miembros y 1 Visitante están viendo este tema.

Eleкtro

Hola

Comparto esta Class cuya finalidad es la de administrar las pistas de una lista multimedia.

Para quien no sepa lo que es una lista multimedia, son unos archivos de texto plano que utilizan los reproductores de archivos multimedia (Video/Audio) para crear listas de reproducción.

Estas son ejemplos de los tipos de listas que soporta mi Class:

M3U:
#EXTM3U

#EXTINF:330,Track1 Title
C:\Track1.avi

C:\Track2.mp4

#EXTINF:5720,Track3 Title
C:\Track3.mp3


PLS:
[playlist]
NumberOfEntries=3
Version=2

File1=C:/Track1.avi

File2=C:/Track2.mp4
Title2=My Track2 Title!
Length2=5720

File3=C:/Track3.mp3
Title3=My Track3 Title!
Length3=330


Características del código:
· Se puede trabajar con dos tipos de listas, M3U y PLS.
· Se puede añadir entradas de pistas con o sin información extendida, así como editar una entrada, eliminar, determinar si existe, o buscar para obtener la información extendida de una pista.
· La mayoría de los métodos que desarrollé tienen overloads para trabajar pasandole o bien la ruta de la pista, o el índice de la pista (primero hay que conocer el índice, claro).

El código en general no creo que me haya quedado muy optimizado, de echo tengo que evitar la recursividad de algún que otro método, pero por el momento está bien y hace su función, aunque si encuentran cualquier fallo o cualquier sugerencia que quieran hacer entonces porfavor comenten.

PD: No he añadido muchos controles de errores, ya que he supuesto que si se le da el uso correcto no debería dar errores (más hallá de los que sí están controlados).

PD2: Al principio me propuse hacerlo todo mediante FileStreams y manteniendo el archivo abierto para denegar el acceso manual al archivo, pero el formato PLS me lo puso muy complicado porque hay que hacer operaciones constantes de búsqueda y modificar un valor tras cada operación así que para no comerme mucho más la cabeza decidí usar un StringBuilder y también listas de Strings, sin más, dejando un poco de lado los permisos de lectura/escritura del archivo del playlist y tambien el rendimiento en general ...los tiempos de ejecución, pero de todas formas recordemos que se trataría de un simple archivo de texto que no debería tener muchas lineas, aunque se optimizase el código no creo que se apreciase la diferencia (en milisegundos xD)...






Estos son algunos ejemplos de uso:

Código (vbnet) [Seleccionar]
       ' **********************************
       ' Instance the PlaylistEditor Class
       ' **********************************
       Dim Playlist As New PlaylistEditor(PlaylistFile:="C:\Playlist.m3u",
                                          PlaylistType:=PlaylistEditor.PlaylistType.M3U,
                                          Append:=False,
                                          FileEncoding:=System.Text.Encoding.Default)

       ' ************************************
       ' Retrieve the instanced object info
       ' ************************************
       MessageBox.Show(Playlist.FilePath)
       MessageBox.Show(Playlist.Type.ToString)
       MessageBox.Show(CStr(Playlist.Append))
       MessageBox.Show(String.Format("Encoding: {0}, CodePage: {1}",
                                     Playlist.FileEncoding.BodyName,
                                     Playlist.FileEncoding.CodePage))

       ' ***************************
       ' Instance a TrackInfo Class
       ' ***************************
       Dim TInfo As New PlaylistEditor.TrackInfo
       With TInfo
           .Path = "C:\Track1.ext"
           .Title = "Track1 Title"
           .Length = TimeSpan.Parse("00:05:30")
       End With

       ' ***************
       ' Add a new track
       ' ***************
       Playlist.Add(TrackInfo:=TInfo)
       Playlist.Add(Path:="C:\Track2.ext", AllowDuplicate:=False)
       Playlist.Add(Path:="C:\Track3.ext", Title:="Track3 Title", Length:=TimeSpan.Parse("01:35:20"))

       ' *************************************************
       ' Sets the extended track info of an existing track
       ' *************************************************
       Dim OldTrackPath As String = "C:\Track3.ext"

       Dim TInfoSet As New PlaylistEditor.TrackInfo
       With TInfoSet
           .Path = "C:\Modified Track3.ext"
           .Title = "My modified Track3 title"
           .Length = Playlist.GetTrack(OldTrackPath).Length
       End With

       Playlist.Set(Path:=OldTrackPath, TrackInfo:=TInfoSet)

       ' ************************
       ' Remove an existing track
       ' ************************
       Playlist.Remove(Path:="C:\Track3.ext")
       Playlist.Remove(TrackIndex:=2I)

       ' ********************************
       ' Determine whether a track exists
       ' ********************************
       MessageBox.Show(Playlist.Exist(Path:="C:\Track3.ext"))
       MessageBox.Show(Playlist.Exist(TrackIndex:=3I))

       ' ************************************************
       ' Count the total amount of tracks in the playlist
       ' ************************************************
       MessageBox.Show(Playlist.Count)

       ' ************************************
       ' Get extended track info from a track
       ' ************************************
       Dim TrackInfo1 As PlaylistEditor.TrackInfo = Playlist.GetTrack(Path:="C:\Track1.ext")
       Dim TrackInfo2 As PlaylistEditor.TrackInfo = Playlist.GetTrack(TrackIndex:=2I)

       ' ******************************************
       ' Get all tracks and its extended track info
       ' ******************************************
       Dim sb As New System.Text.StringBuilder
       Dim Tracks As List(Of PlaylistEditor.TrackInfo) = Playlist.GetTracks()

       For Each Track As PlaylistEditor.TrackInfo In Tracks

           With sb
               .Clear()
               .AppendLine(String.Format("Track Index : {0}", CStr(Track.Index)))
               .AppendLine(String.Format("Track Path  : {0}", Track.Path))
               .AppendLine(String.Format("Track Title : {0}", Track.Title))
               .AppendLine(String.Format("Track Length: {0}", Convert.ToString(Track.Length)))
           End With

           MessageBox.Show(sb.ToString)

       Next Track









Eleкtro

#1
Aquí tienen la Class:

Código (vbnet) [Seleccionar]
' ***********************************************************************
' Author   : Elektro
' Modified : 07-21-2014
' ***********************************************************************
' <copyright file="PlaylistEditor.vb" company="Elektro Studios">
'     Copyright (c) Elektro Studios. All rights reserved.
' </copyright>
' ***********************************************************************

#Region " Imports "

Imports System.ComponentModel
Imports System.IO
Imports System.Text

#End Region

#Region " PlaylistEditor "

''' <summary>
''' Contains methods to manage the contents of a multimedia playlist file.
''' This class cannot be inherited.
''' </summary>
Public NotInheritable Class PlaylistEditor

#Region " Properties "

    ''' <summary>
    ''' Gets the playlist filepath.
    ''' </summary>
    ''' <value>The playlist filepath.</value>
    Public ReadOnly Property FilePath As String
        Get
            Return Me._FilePath
        End Get
    End Property
    Private _FilePath As String

    ''' <summary>
    ''' Gets the playlist type.
    ''' </summary>
    ''' <value>The playlist type.</value>
    Public ReadOnly Property Type
        Get
            Return Me._Type
        End Get
    End Property
    Private _Type As PlaylistType

    ''' <summary>
    ''' Gets the playlist file encoding.
    ''' </summary>
    ''' <value>The playlist file encoding.</value>
    Public ReadOnly Property FileEncoding As Encoding
        Get
            Return Me._Encoding
        End Get
    End Property
    Private _Encoding As Encoding

    ''' <summary>
    ''' Gets a value indicating whether the append mode is activated.
    ''' </summary>
    ''' <value><c>true</c> if append mode is activated; otherwise, <c>false</c>.</value>
    Public ReadOnly Property Append As Boolean
        Get
            Return Me._Append
        End Get
    End Property
    Private _Append As Boolean

#End Region

#Region " Enumerations "

    ''' <summary>
    ''' Indicates the type of a playlist.
    ''' </summary>
    <Description("Enumeration used as 'PlaylistType' parameter of 'New' constructor.")>
    Public Enum PlaylistType As Integer

        ''' <summary>
        ''' M3U Playlist.
        ''' Documentation: http://en.wikipedia.org/wiki/M3U
        ''' </summary>
        M3U = 0I

        ''' <summary>
        ''' PLS Playlist.
        ''' Documentation: http://en.wikipedia.org/wiki/PLS_%28file_format%29
        ''' </summary>
        PLS = 1I

    End Enum

#End Region

#Region " Types "

    ''' <summary>
    ''' Contains extended info of a playlist track.
    ''' </summary>
    Public Class TrackInfo

#Region " Properties "

        ''' <summary>
        ''' Gets the track index.
        ''' Don't set this value manually.
        ''' This value is automatically set by some of the <see cref="PlaylistEditor"/> methods,
        ''' and has any effect for other purposes.
        ''' </summary>
        ''' <value>The track index.</value>
        Public Property Index As Integer

        ''' <summary>
        ''' Gets or sets the track filepath.
        ''' </summary>
        ''' <value>The track filepath.</value>
        Public Property Path As String

        ''' <summary>
        ''' Gets or sets the track title.
        ''' </summary>
        ''' <value>The track title.</value>
        Public Property Title As String

        ''' <summary>
        ''' Gets or sets the track length.
        ''' </summary>
        ''' <value>The track length.</value>
        Public Property Length As TimeSpan

#End Region

#Region " Hidden Methods "

        ''' <summary>
        ''' Serves as a hash function for a particular type.
        ''' </summary>
        <EditorBrowsable(EditorBrowsableState.Never)>
        Public Shadows Sub GetHashCode()
        End Sub

        ''' <summary>
        ''' Determines whether the specified System.Object instances are considered equal.
        ''' </summary>
        <EditorBrowsable(EditorBrowsableState.Never)>
        Public Shadows Sub Equals()
        End Sub

        ''' <summary>
        ''' Determines whether the specified System.Object instances are the same instance.
        ''' </summary>
        <EditorBrowsable(EditorBrowsableState.Never)>
        Private Shadows Sub ReferenceEquals()
        End Sub

        ''' <summary>
        ''' Returns a String that represents the current object.
        ''' </summary>
        <EditorBrowsable(EditorBrowsableState.Never)>
        Public Shadows Sub ToString()
        End Sub

#End Region

    End Class

#End Region

#Region " Constructors "

    ''' <summary>
    ''' Prevents a default instance of the <see cref="PlaylistEditor"/> class from being created.
    ''' </summary>
    Private Sub New()
    End Sub

    ''' <summary>
    ''' Initializes a new instance of the <see cref="PlaylistEditor"/> class.
    ''' </summary>
    ''' <param name="PlaylistFile">Indicates the playlist filepath.</param>
    ''' <param name="PlaylistType">Indicates the type of the playlist.</param>
    ''' <param name="Append">
    ''' If set to <c>true</c> the <see cref="PlaylistEditor"/> instance will assume that the playlist file already exist,
    ''' and will append any new entries in the existing file.
    ''' If set to <c>false</c> the <see cref="PlaylistEditor"/> instance will assume that the playlist file does not exist,
    ''' and will create the file.
    ''' </param>
    ''' <param name="FileEncoding">
    ''' Optionally indicates the file encoding to write/read the playlist content.
    ''' The default value is <see cref="Encoding.Default"/>
    ''' </param>
    Public Sub New(ByVal PlaylistFile As String,
                   ByVal PlaylistType As PlaylistType,
                   ByVal Append As Boolean,
                   Optional ByVal FileEncoding As Encoding = Nothing)

        Me._FilePath = PlaylistFile
        Me._Type = PlaylistType
        Me._Encoding = If(FileEncoding IsNot Nothing, FileEncoding, Encoding.Default)
        Me._Append = Append

        If Not _Append Then
            Me.AddHeaders()
        End If

    End Sub

#End Region

#Region " Hidden Methods "

    ''' <summary>
    ''' Serves as a hash function for a particular type.
    ''' </summary>
    <EditorBrowsable(EditorBrowsableState.Never)>
    Public Shadows Sub GetHashCode()
    End Sub

    ''' <summary>
    ''' Determines whether the specified System.Object instances are considered equal.
    ''' </summary>
    <EditorBrowsable(EditorBrowsableState.Never)>
    Public Shadows Sub Equals()
    End Sub

    ''' <summary>
    ''' Determines whether the specified System.Object instances are the same instance.
    ''' </summary>
    <EditorBrowsable(EditorBrowsableState.Never)>
    Private Shadows Sub ReferenceEquals()
    End Sub

    ''' <summary>
    ''' Returns a String that represents the current object.
    ''' </summary>
    <EditorBrowsable(EditorBrowsableState.Never)>
    Public Shadows Sub ToString()
    End Sub

#End Region

#Region " Private Methods "

    ''' <summary>
    ''' Adds the playlist headers in the playlist file.
    ''' This method should be called first before add any entry in the playlist.
    ''' </summary>
    Private Sub AddHeaders()

        Dim sb As New StringBuilder

        Select Case Me._Type

            Case PlaylistType.M3U
                sb.AppendLine("#EXTM3U")

            Case PlaylistType.PLS
                With sb
                    .AppendLine("[playlist]")
                    .AppendLine("NumberOfEntries=0")
                    .AppendLine("Version=2")
                End With

        End Select

        File.WriteAllText(Me._FilePath, sb.ToString, Me._Encoding)
        sb.Clear()

    End Sub

    ''' <summary>
    ''' Gets the amount of total entries of a PLS playlist file.
    ''' </summary>
    ''' <returns>The current number of total entries.</returns>
    Private Function GetPLSNumberOfEntries() As Integer

        Dim PlaylistContent As String = File.ReadAllText(Me._FilePath, Me._Encoding)

        Dim StartIndex As Integer =
            PlaylistContent.IndexOf("=") + 1I

        Dim EndIndex As Integer =
            PlaylistContent.IndexOf(ControlChars.NewLine, StartIndex) - StartIndex

        Return PlaylistContent.Substring(StartIndex, PlaylistContent.IndexOf(String.Empty, EndIndex))

    End Function

    ''' <summary>
    ''' Fixes the track index count of a PLS playlist file.
    ''' This method shoould be called after remove a track from the playlist.
    ''' </summary>
    Private Sub FixPLSTrackIndex()

        Dim PlaylistContent As List(Of String) = File.ReadAllLines(Me._FilePath, Me._Encoding).ToList
        Dim TrackCount As Integer = 0I

        For Index As Integer = 0 To (PlaylistContent.Count - 1I)

            If PlaylistContent(Index).StartsWith("File", StringComparison.OrdinalIgnoreCase) Then

                TrackCount += 1I

                PlaylistContent(Index) = String.Format("File{0}={1}",
                                                       CStr(TrackCount),
                                                       PlaylistContent(Index).Substring(PlaylistContent(Index).IndexOf("="c) + 1I))

            ElseIf PlaylistContent(Index).StartsWith("Title", StringComparison.OrdinalIgnoreCase) Then
                PlaylistContent(Index) = String.Format("Title{0}={1}",
                                                       CStr(TrackCount),
                                                       PlaylistContent(Index).Substring(PlaylistContent(Index).IndexOf("="c) + 1I))

            ElseIf PlaylistContent(Index).StartsWith("Length", StringComparison.OrdinalIgnoreCase) Then
                PlaylistContent(Index) = String.Format("Length{0}={1}",
                                                       CStr(TrackCount),
                                                       PlaylistContent(Index).Substring(PlaylistContent(Index).IndexOf("="c) + 1I))

            End If

        Next Index

        Dim NumberOfEntriesEntryIndex As Integer =
            PlaylistContent.FindIndex(Function(Item As String)
                                          Return Item.ToLower Like "numberofentries=#*"
                                      End Function)

        PlaylistContent(NumberOfEntriesEntryIndex) =
            String.Format("NumberOfEntries={0}", CStr(TrackCount))

        File.WriteAllLines(Me._FilePath, PlaylistContent, Me._Encoding)

    End Sub

#End Region

#Region " Public Methods "

    ''' <summary>
    ''' Adds a new track entry in the playlist.
    ''' </summary>
    ''' <param name="Path">Indicates the track path to add.</param>
    ''' <param name="AllowDuplicate">
    ''' If set to <c>true</c> an exception will be thrown if the track already exists in the playlist.
    ''' </param>
    ''' <exception cref="System.Exception">The TrackPath already exist in the playlist.</exception>
    Public Sub Add(ByVal [Path] As String,
                   Optional ByVal AllowDuplicate As Boolean = False)

        If Not AllowDuplicate AndAlso Me.Exist([Path]) Then
            Throw New Exception("The TrackPath already exist in the playlist.") With {.Source = [Path]}
        End If

        Dim sb As New StringBuilder

        Select Case Me._Type

            Case PlaylistType.M3U

                With sb
                    .AppendLine()
                    .AppendLine([Path])
                    File.AppendAllText(Me._FilePath, .ToString, Me._Encoding)
                    .Clear()

                End With

            Case PlaylistType.PLS

                Dim EntryCount As Integer = Me.GetPLSNumberOfEntries()

                With sb

                    .AppendLine(File.ReadAllText(Me._FilePath, Me._Encoding).
                                     Replace("NumberOfEntries=" & CStr(EntryCount),
                                             "NumberOfEntries=" & CStr(EntryCount + 1I)))

                    .AppendLine(String.Format("File{0}={1}", CStr(EntryCount + 1I), [Path].Replace("\", "/")))

                    File.WriteAllText(Me._FilePath, .ToString, Me._Encoding)
                    .Clear()

                End With

        End Select

    End Sub

    ''' <summary>
    ''' Adds a new track entry in the playlist, with extended track information.
    ''' </summary>
    ''' <param name="Path">Indicates the track to add.</param>
    ''' <param name="Title">Indicates the track title.</param>
    ''' <param name="Length">Indicates the track length.</param>
    Public Sub Add(ByVal [Path] As String,
                   ByVal Title As String,
                   ByVal Length As TimeSpan,
                   Optional ByVal AllowDuplicate As Boolean = False)

        If Not AllowDuplicate AndAlso Me.Exist([Path]) Then
            Throw New Exception("The TrackPath already exist in the playlist.") With {.Source = [Path]}
        End If

        Dim sb As New StringBuilder

        Select Case Me._Type

            Case PlaylistType.M3U

                With sb

                    .AppendLine()
                    .AppendLine(String.Format("#EXTINF:{0},{1}",
                                                CStr(Math.Truncate(Length.TotalSeconds)),
                                                Title))
                    .AppendLine([Path])

                    File.AppendAllText(Me._FilePath, .ToString, Me._Encoding)
                    .Clear()

                End With

            Case PlaylistType.PLS

                Dim EntryCount As Integer = Me.GetPLSNumberOfEntries()

                With sb

                    .AppendLine(File.ReadAllText(Me._FilePath, Me._Encoding).
                                     Replace("NumberOfEntries=" & CStr(EntryCount),
                                             "NumberOfEntries=" & CStr(EntryCount + 1I)))

                    .AppendLine(String.Format("File{0}={1}", CStr(EntryCount + 1I), [Path].Replace("\", "/")))
                    .AppendLine(String.Format("Title{0}={1}", CStr(EntryCount + 1I), Title))
                    .AppendLine(String.Format("Length{0}={1}", CStr(EntryCount + 1I), CStr(Math.Truncate(Length.TotalSeconds))))

                    File.WriteAllText(Me._FilePath, .ToString, Me._Encoding)
                    .Clear()

                End With

        End Select

    End Sub

    ''' <summary>
    ''' Adds a new track entry in the playlist, with extended track information.
    ''' </summary>
    ''' <param name="TrackInfo">A <see cref="TrackInfo"/> instance containing the extended track information.</param>
    Public Sub Add(ByVal TrackInfo As TrackInfo,
                   Optional ByVal AllowDuplicate As Boolean = False)

        Me.Add(TrackInfo.Path, TrackInfo.Title, TrackInfo.Length, AllowDuplicate)

    End Sub

    ''' <summary>
    ''' Removes the specified track entry from the playlist.
    ''' </summary>
    ''' <param name="Path">Indicates the track path to remove it's entry.</param>
    ''' <exception cref="System.Exception">The TrackPath was not found in the playlist.</exception>
    Public Sub Remove(ByVal [Path] As String)

        If Not Me.Exist([Path]) Then
            Throw New Exception("The TrackPath was not found in the playlist.") With {.Source = [Path]}
        End If

        Dim PlaylistContent As List(Of String) = File.ReadAllLines(Me._FilePath, Me._Encoding).ToList

        Select Case Me._Type

            Case PlaylistType.M3U

                Dim EntryIndex As Integer =
                    PlaylistContent.FindIndex(Function(Item As String)
                                                  Return Item.Equals([Path], StringComparison.OrdinalIgnoreCase)
                                              End Function)

                PlaylistContent.RemoveAt(EntryIndex)

                If PlaylistContent(EntryIndex - 1).StartsWith("#EXTINF", StringComparison.OrdinalIgnoreCase) Then
                    PlaylistContent.RemoveAt(EntryIndex - 1)
                End If

                File.WriteAllLines(Me._FilePath, PlaylistContent, Me._Encoding)

            Case PlaylistType.PLS

                Dim EntryIndex As Integer =
                    PlaylistContent.FindIndex(Function(Item As String)
                                                  Return Item.ToLower Like "file#*" & [Path].Replace("\", "/").ToLower
                                              End Function)

                Dim TrackIndexDelimStartIndex As Integer =
                    PlaylistContent(EntryIndex).IndexOf("e", StringComparison.OrdinalIgnoreCase) + 1I

                Dim TrackIndexDelimEndIndex As Integer =
                    PlaylistContent(EntryIndex).IndexOf("=", StringComparison.OrdinalIgnoreCase)

                Dim TrackIndex As Integer =
                    PlaylistContent(EntryIndex).Substring(TrackIndexDelimStartIndex,
                                                          TrackIndexDelimEndIndex - TrackIndexDelimStartIndex)

                PlaylistContent.RemoveAt(EntryIndex)

                Dim TitleEntryIndex As Integer =
                    PlaylistContent.FindIndex(Function(Item As String)
                                                  Return Item.ToLower Like String.Format("title{0}=*", CStr(TrackIndex))
                                              End Function)

                If TitleEntryIndex <> -1I Then
                    PlaylistContent.RemoveAt(TitleEntryIndex)
                End If

                Dim LengthEntryIndex As Integer =
                    PlaylistContent.FindIndex(Function(Item As String)
                                                  Return Item.ToLower Like String.Format("length{0}=*", CStr(TrackIndex))
                                              End Function)

                If LengthEntryIndex <> -1I Then
                    PlaylistContent.RemoveAt(LengthEntryIndex)
                End If

                Dim NumberOfEntriesEntryIndex As Integer =
                    PlaylistContent.FindIndex(Function(Item As String)
                                                  Return Item.ToLower Like "numberofentries=#*"
                                              End Function)

                PlaylistContent(NumberOfEntriesEntryIndex) =
                    String.Format("NumberOfEntries={0}", CStr(Me.GetPLSNumberOfEntries() - 1I))

                File.WriteAllLines(Me._FilePath, PlaylistContent, Me._Encoding)

                Me.FixPLSTrackIndex()

        End Select

    End Sub

    ''' <summary>
    ''' Removes the specified track entry from the playlist.
    ''' </summary>
    ''' <param name="TrackIndex">Indicates the track index to remove it's entry.</param>
    ''' <exception cref="System.IndexOutOfRangeException">TrackIndex is out of range</exception>
    Public Sub Remove(ByVal TrackIndex As Integer)

        Dim Track = Me.GetTrack(TrackIndex)

        If Track IsNot Nothing Then
            Me.Remove(Track.Path)
        Else
            Throw New IndexOutOfRangeException("TrackIndex is out of range") With {.Source = TrackIndex}
        End If

    End Sub

    ''' <summary>
    ''' Sets the extended track info of the specified track.
    ''' </summary>
    ''' <param name="Path">Indicates the track path to set its extended track info.</param>
    ''' <param name="TrackInfo">A <see cref="TrackInfo" /> instance containing the extended info to set.</param>
    ''' <exception cref="System.Exception">The TrackPath was not found in the playlist.</exception>
    Public Sub [Set](ByVal [Path] As String,
                     ByVal TrackInfo As TrackInfo)

        If Not Me.Exist([Path]) Then
            Throw New Exception("The TrackPath was not found in the playlist.") With {.Source = [Path]}
        End If

        Dim Track As TrackInfo = Me.GetTrack([Path])
        With Track
            .Path = TrackInfo.Path
            .Title = TrackInfo.Title
            .Length = TrackInfo.Length
        End With

        Dim PlaylistContent As List(Of String) = File.ReadAllLines(Me._FilePath, Me._Encoding).ToList

        Select Case Me._Type

            Case PlaylistType.M3U

                Dim EntryIndex As Integer =
                    PlaylistContent.FindIndex(Function(Item As String)
                                                  Return Item.Equals([Path], StringComparison.OrdinalIgnoreCase)
                                              End Function)

                PlaylistContent(EntryIndex) = String.Format("#EXTINF:{0},{1}",
                                                            CStr(Math.Truncate(Track.Length.TotalSeconds)),
                                                            Track.Title) & Environment.NewLine & Track.Path

                If PlaylistContent(EntryIndex - 1I).StartsWith("#EXTINF", StringComparison.OrdinalIgnoreCase) Then
                    PlaylistContent.RemoveAt(EntryIndex - 1I)
                End If

                File.WriteAllLines(Me._FilePath, PlaylistContent, Me._Encoding)

            Case PlaylistType.PLS

                Track.Path = Track.Path.Replace("\", "/")

                Dim EntryIndex As Integer =
                    PlaylistContent.FindIndex(Function(Item As String)
                                                  Return Item.ToLower Like "file#*" & [Path].Replace("\", "/").ToLower
                                              End Function)

                PlaylistContent(EntryIndex) = String.Format("File{0}={1}", CStr(Track.Index), Track.Path) & Environment.NewLine &
                                              String.Format("Title{0}={1}", CStr(Track.Index), Track.Title) & Environment.NewLine &
                                              String.Format("Length{0}={1}", CStr(Track.Index), CStr(Math.Truncate(Track.Length.TotalSeconds)))

                If PlaylistContent.Count > (EntryIndex + 1) Then

                    If PlaylistContent(EntryIndex + 2I).StartsWith("Title", StringComparison.OrdinalIgnoreCase) _
                    OrElse PlaylistContent(EntryIndex + 2I).StartsWith("Length", StringComparison.OrdinalIgnoreCase) Then

                        PlaylistContent.RemoveAt(EntryIndex + 2I)

                    End If

                End If

                If PlaylistContent.Count > EntryIndex Then

                    If PlaylistContent(EntryIndex + 1I).StartsWith("Title", StringComparison.OrdinalIgnoreCase) _
                    OrElse PlaylistContent(EntryIndex + 1I).StartsWith("Length", StringComparison.OrdinalIgnoreCase) Then

                        PlaylistContent.RemoveAt(EntryIndex + 1I)

                    End If

                End If

                File.WriteAllLines(Me._FilePath, PlaylistContent, Me._Encoding)

        End Select

    End Sub

    ''' <summary>
    ''' Sets the extended track info of the specified track.
    ''' </summary>
    ''' <param name="TrackIndex">Indicates the track index to set its extended track info.</param>
    ''' <param name="TrackInfo">A <see cref="TrackInfo" /> instance containing the extended info to set.</param>
    ''' <exception cref="System.IndexOutOfRangeException">TrackIndex is out of range</exception>
    Public Sub [Set](ByVal TrackIndex As Integer,
                     ByVal TrackInfo As TrackInfo)

        If Not Me.Exist(TrackIndex) Then
            Throw New IndexOutOfRangeException("TrackIndex is out of range") With {.Source = TrackIndex}
        End If

        Me.[Set](Me.GetTrack(TrackIndex).Path, TrackInfo)

    End Sub

    ''' <summary>
    ''' Gets the extended track information (if any) of the specified track in the playlist.
    ''' </summary>
    ''' <param name="Path">Indicates the track path.</param>
    ''' <returns>
    ''' If the track contains extended iformation,
    ''' the return value is a <see cref="TrackInfo"/> instance containing the track info.
    ''' Otherwise, the return value is an emptiness <see cref="TrackInfo"/> instance.
    ''' </returns>
    Public Function GetTrack(ByVal Path As String) As TrackInfo

        Dim PlaylistContent As List(Of String) = File.ReadAllLines(Me._FilePath, Me._Encoding).ToList
        Dim TInfo As New TrackInfo

        Select Case Me._Type

            Case PlaylistType.M3U

                Dim EntryIndex As Integer = PlaylistContent.FindIndex(Function(Item As String)
                                                                          Return Item.Equals([Path], StringComparison.OrdinalIgnoreCase)
                                                                      End Function) - 1I

                If PlaylistContent(EntryIndex).StartsWith("#EXTINF", StringComparison.OrdinalIgnoreCase) Then

                    Dim TitleDelimIndex As Integer = PlaylistContent(EntryIndex).IndexOf(","c) + 1I
                    Dim LengthDelimIndex As Integer = PlaylistContent(EntryIndex).IndexOf(":"c) + 1I

                    With TInfo

                        '.Index = EntryIndex
                        .Path = [Path]
                        .Title = PlaylistContent(EntryIndex).Substring(TitleDelimIndex)
                        .Length = TimeSpan.FromSeconds(PlaylistContent(EntryIndex).Substring(LengthDelimIndex,
                                                                                             (TitleDelimIndex - LengthDelimIndex)))
                    End With

                End If

            Case PlaylistType.PLS

                [Path] = [Path].Replace("\", "/")

                Dim Entry As String = (From Item As String In PlaylistContent
                                       Where Item.ToLower Like String.Format("file#*={0}", [Path].ToLower)).FirstOrDefault

                If Not String.IsNullOrEmpty(Entry) Then

                    Dim IndexDelimStartIndex As Integer =
                        Entry.IndexOf("e", StringComparison.OrdinalIgnoreCase) + 1I

                    Dim IndexDelimEndIndex As Integer =
                        Entry.IndexOf("=", StringComparison.OrdinalIgnoreCase)

                    Dim EntryIndex As Integer = Entry.Substring(IndexDelimStartIndex,
                                                                IndexDelimEndIndex - IndexDelimStartIndex)

                    Dim TitleEntry As String = (From Item As String In PlaylistContent
                                                Where Item.StartsWith(String.Format("Title{0}=", CStr(EntryIndex)), StringComparison.OrdinalIgnoreCase)).
                                                FirstOrDefault

                    Dim LengthEntry As String = (From Item As String In PlaylistContent
                                                 Where Item.StartsWith(String.Format("Length{0}=", CStr(EntryIndex)), StringComparison.OrdinalIgnoreCase)).
                                                 FirstOrDefault

                    With TInfo

                        .Index = EntryIndex

                        .Path = [Path]

                        .Title = If(Not String.IsNullOrEmpty(TitleEntry),
                                    TitleEntry.Substring(TitleEntry.IndexOf("=") + 1I),
                                    Nothing)

                        .Length = If(Not String.IsNullOrEmpty(TitleEntry),
                                     TimeSpan.FromSeconds(LengthEntry.Split("=").LastOrDefault),
                                     Nothing)

                    End With

                End If

        End Select

        Return TInfo

    End Function

    ''' <summary>
    ''' Gets the track path and its extended track information (if any) of the specified track index in the playlist.
    ''' </summary>
    ''' <param name="TrackIndex">Indicates the track index.</param>
    ''' <returns>
    ''' If the track index exist,
    ''' the return value is a <see cref="TrackInfo"/> instance containing the track path and its extended info (if any).
    ''' Otherwise, the return value is <c>Nothing</c>.
    ''' </returns>
    Public Function GetTrack(ByVal TrackIndex As Integer) As TrackInfo

        Dim PlaylistContent As List(Of String) = File.ReadAllLines(Me._FilePath, Me._Encoding).ToList

        Select Case Me._Type

            Case PlaylistType.M3U

                Dim TrackCount As Integer = 0I

                For Index As Integer = 0I To (PlaylistContent.Count - 1I)

                    If Not String.IsNullOrEmpty(PlaylistContent(Index)) _
                       AndAlso Not PlaylistContent(Index).StartsWith("#EXT", StringComparison.OrdinalIgnoreCase) Then

                        TrackCount += 1I

                        If TrackCount = TrackIndex Then

                            Dim TInfo As TrackInfo = Me.GetTrack(PlaylistContent(Index))
                            With TInfo
                                .Index = TrackIndex
                                .Path = PlaylistContent(Index)
                            End With

                            Return TInfo

                        End If

                    End If

                Next Index

            Case PlaylistType.PLS

                For Index As Integer = 0I To (PlaylistContent.Count - 1I)

                    If PlaylistContent(Index).StartsWith(String.Format("File{0}=", CStr(TrackIndex)),
                                                         StringComparison.OrdinalIgnoreCase) Then

                        Return Me.GetTrack(PlaylistContent(Index).Substring(PlaylistContent(Index).IndexOf("="c) + 1I))

                    End If

                Next Index

        End Select

        Return Nothing

    End Function

    ''' <summary>
    ''' Gets all the tracks and its extended track information (if any) in the playlist.
    ''' </summary>
    ''' <returns>
    ''' A <see cref="List(Of TrackInfo)"/> object containing the track entries and its extended info (if any).
    ''' </returns>
    Public Function GetTracks() As List(Of TrackInfo)

        Dim PlaylistContent As List(Of String) = File.ReadAllLines(Me._FilePath, Me._Encoding).ToList
        Dim TInfo As New List(Of TrackInfo)
        Dim TrackCount As Integer = 0I

        Select Case Me._Type

            Case PlaylistType.M3U

                For Index As Integer = 0I To (PlaylistContent.Count - 1I)

                    If Not String.IsNullOrEmpty(PlaylistContent(Index)) _
                       AndAlso Not PlaylistContent(Index).StartsWith("#EXT", StringComparison.OrdinalIgnoreCase) Then

                        TrackCount += 1
                        TInfo.Add(Me.GetTrack(TrackCount))

                    End If

                Next

            Case PlaylistType.PLS

                For Index As Integer = 0I To (PlaylistContent.Count - 1I)

                    If PlaylistContent(Index).StartsWith("File", StringComparison.OrdinalIgnoreCase) Then

                        TrackCount += 1I
                        TInfo.Add(Me.GetTrack(TrackCount))

                    End If

                Next Index

        End Select

        Return TInfo

    End Function

    ''' <summary>
    ''' Determines whether the specified track exists in the playlist.
    ''' </summary>
    ''' <param name="Path">Indicates the track path.</param>
    ''' <returns>
    ''' <c>true</c> if the track already exists in the playlist, <c>false</c> otherwise.
    ''' </returns>
    Public Function Exist(ByVal [Path] As String) As Boolean

        Dim ReturnValue As Boolean = False

        Select Case Me._Type

            Case PlaylistType.M3U

                ReturnValue = (From Item As String In File.ReadAllLines(Me._FilePath, Me._Encoding)
                               Where Item.StartsWith([Path], StringComparison.OrdinalIgnoreCase)).
                               Any()

            Case PlaylistType.PLS

                ReturnValue = (From Item As String In File.ReadAllLines(Me._FilePath, Me._Encoding)
                               Where Item.ToLower Like "file#*" & [Path].Replace("\", "/").ToLower).
                               Any()

        End Select

        Return ReturnValue

    End Function

    ''' <summary>
    ''' Determines whether the specified track exists in the playlist.
    ''' </summary>
    ''' <param name="TrackIndex">Indicates the track index.</param>
    ''' <returns><c>true</c> if the track already exists in the playlist, <c>false</c> otherwise.</returns>
    ''' <exception cref="System.IndexOutOfRangeException">TrackIndex should be greater than 0.</exception>
    Public Function Exist(ByVal TrackIndex As Integer) As Boolean

        If TrackIndex <= 0 Then
            Throw New IndexOutOfRangeException("TrackIndex should be greater than 0.") With {.Source = TrackIndex}
        End If

        Return (Me.Count >= TrackIndex)

    End Function

    ''' <summary>
    ''' Counts the amount of track entries in the playlist.
    ''' </summary>
    ''' <returns>
    ''' The amount of track entries in the playlist.
    ''' </returns>
    Public Function Count() As Integer

        Return Me.GetTracks.Count

    End Function

#End Region

End Class

#End Region








XresH

Se ve bastante completo, aunque creo que hay cosas que podrias reducir, hace años hice un reproductor y me hubiera venido bien este code, gracias por el aporte.

Saludos.
[ - Si eres programador y quieres que tus proyectos esten en mi blog(con o sin source), consúltame! - ]
Entra A Mi Blog De Programación | | Dudas en este post :| | >>Clic para ir al Post<<