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:
' **********************************
' 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
Aquí tienen la Class:
' ***********************************************************************
' 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
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.