Colaboraciones en el Guille

Reproductor aleatorio de MP3

[Usando el OCX de Windows Media Player 10]

 

Fecha: 21/Abr/2006 (20 de Abril de 2006)
Autor: Miliuco

 


Introducción

En agosto de 2003 publiqué un artículo sobre un reproductor de archivos MP3 realizado en Visual basic .NET 2003 utilizando el OCX de Windows Media Player 9. Retomando ese ejercicio, he añadido la funcionalidad de reproducir los archivos de forma aleatoria. El programa crea un Array con todas las canciones existentes en una determinada carpeta y, mediante las funciones Randomize() y Rnd(), genera un índice aleatorio que asigna al reproductor. En este artículo comentaré los aspectos que difieran del artículo anteriormente publicado para evitar repeticiones innecesarias.

Requisito imprescindible: tener instalado Windows Media Player 10 y añadir su control OCX al proyecto (explicado en el artículo anterior).

Variables globales

Se crean unas variables con visibilidad a nivel de clase para poder utilizarlas en cualquier procedimiento:

' para el nombre y la ruta de los archivos
Private strFilename, strPath As String
' el evento WMPLib.WMPPlayState.wmppsTransitioning se produce
' cuando Windows Media Player está preparando un nuevo ítem
' pero sólo ha de suceder cuando la variable blShuffle sea True
Private blShuffle As Boolean = False
' para el tiempo de reproducción transcurrido
Private dtTime As DateTime
' Array para contener los nombres de los archivos MP3
Private strLista(), strArchivo As String
' para el índice de las canciones
Private intCancion As Integer
Private a As Integer = 1
'
' para escribir en un archivo de texto el índice de los archivos reproducidos
Private objEscritor As StreamWriter

Posición del formulario

Para centrar el formulario en la pantalla por código:

' posición x.y del formulario: centrado en la pantalla
Me.Left = (Screen.PrimaryScreen.WorkingArea.Width - Me.Width) \ 2
Me.Top = (Screen.PrimaryScreen.WorkingArea.Height - Me.Height) \ 2

Procedimiento para abrir un archivo

El procedimiento abrirArchivo() presenta al usuario un cuadro de diálogo para elegir entre archivos MP3, WPL y WAV. El resultado de la elección se pasa al reproductor. La variable strPath guarda la ruta a la carpeta que contiene la canción que suena y la variable strLista una matriz con los archivos contenidos en esa carpeta.

' PROCEDIMIENTO PARA ABRIR ARCHIVOS
Private Sub abrirArchivo() ' procedimiento para buscar y abrir un archivo
   ' limpiar variables y parar el reproductor
   ocxPlayer.Ctlcontrols.stop()
   ocxPlayer.URL = ""
   strPath = ""
   lbIndex.Text = ""
   ' presentar al usuario un cuadro de diálogo
   Dim openFile As New OpenFileDialog
   ' mostrar solamente archivos MP3, WAV y WPL
   openFile.Filter = "Canciones (*.mp3; *.wav; *.wpl)|*.mp3; *.wav; *.wpl"
   ' si elegimos algún archivo
   If openFile.ShowDialog() = Windows.Forms.DialogResult.OK Then
     ' abrir el archivo elegido en el reproductor
     ocxPlayer.URL = openFile.FileName
     ' strPath -> ruta a la carpeta que contiene el archivo MP3
     ' quitamos "\nombre_de_archivo" de strPath
     Dim i As Integer
     i = openFile.FileName.LastIndexOf("\")
     strPath = openFile.FileName.Remove(i, openFile.FileName.Length - i)
     '
     ' COMPROBACIÓN: diálogo con la ruta a la carpeta
     'MsgBox(strPath)
     ' FIN DE LA COMPROBACIÓN
     '
     ' Array de string para los archivos MP3 que contenga la carpeta Canciones
     strLista = System.IO.Directory.GetFiles(strPath)
     '
     ' para poder llamar al método Aleatorio() en el evento wmppsTransitioning
     '
     ' si es una lista de reproducción
     If ocxPlayer.URL.EndsWith("wpl") Then
       blShuffle = False
       lbIndex.Text = "Lista en reproducción"
       ' si no es una lista de reproducción
     Else
       blShuffle = True
       lbIndex.Text = "Carpeta con " & strLista.Length & " canciones"
     End If
   End If
End Sub

Estado del reproductor

El procedimiento ocxPlayer_PlayStateChange() detecta los cambios en el estado del reproductor (reproduciendo, detenido...) para mostrar información de la canción al cambiar el estado del reproductor (PlayStateChange). Como el OCX tiene configurado su inicio automático, simplemente con elegir un archivo ya cambia el estado de reproducción y comienza a tocar. De este procedimiento, existente en el artículo anterior, sólo comentaré la inclusión de un nuevo estado wmppsTransitioning que tiene lugar cada vez que el reproductor está preparando un nuevo ítem; pero en algunas ocasiones no debe ser detectado por lo que se crea una variable booleana blShuffle que dice al programa cuándo detectar wmppsTransitioning y cuándo no hacerlo.

Private Sub ocxPlayer_PlayStateChange(ByVal sender As Object, ByVal e As AxWMPLib._WMPOCXEvents_PlayStateChangeEvent) _
Handles ocxPlayer.PlayStateChange
   '
   ' dependiendo del estado del reproductor
   Select Case e.newState
     	'
     	' REPRODUCIENDO
     	Case WMPLib.WMPPlayState.wmppsPlaying
       	'
       	' mostrar el título de la canción que suena, en la barra de título
       	Me.Text = ocxPlayer.currentMedia.getItemInfobyType("title", "", 0) ' título
       	lbTituloa.Text = "Reproducción en curso:"
       	lbTitulo.Text = ocxPlayer.currentMedia.getItemInfobyType("title", "", 0) ' título
       	lbAutora.Text = "Intérprete:"
       	lbAutor.Text = ocxPlayer.currentMedia.getItemInfobyType("author", "", 0) ' autor
       	'
       	btAbrir.Enabled = False ' desactivar el botón Abrir
       	btStop.Enabled = True ' activar el botón Abrir
       	btPlay.Enabled = False ' desactivar el botón Play
       	' botones Prev y Next activos sólo si reproduce una lista
      	If ocxPlayer.URL.EndsWith("wpl") Then
        	btPrev.Enabled = True ' activar el botón Prev
        	btNext.Enabled = True ' activar el botón Next 
        	' si es una lista, no se muestra información con el nº de archivos en la carpeta
        	lbIndex.Text = "Lista en reproducción"
      	Else
       		btPrev.Enabled = False ' desactivar el botón Prev
     		btNext.Enabled = False ' desactivar el botón Next
     		btSaltar.Enabled = True ' activar el botón Saltar 
     		' si no es una lista, se muestra información con el nº de archivos en la carpeta
     		lbIndex.Text = "Carpeta con " & strLista.Length & " canciones"
     	End If
     	'
   	' DETENIDO
	Case WMPLib.WMPPlayState.wmppsStopped
   	btAbrir.Enabled = True ' activar el botón Abrir
   	btStop.Enabled = False ' desactivar botón Stop
   	btPlay.Enabled = True ' activar botón Play
   	btPrev.Enabled = False ' desactivar botón Prev
	btNext.Enabled = False ' desactivar botón Next
	btSaltar.Enabled = False ' desactivar botón Saltar
	' barra de título de la ventana vacía
	Me.Text = "Mp3"
	' desactivar reproducción aleatoria
	If blShuffle = True Then
   		blShuffle = False
	End If
        '
   	' PREPARANDO UN NUEVO ITEM
   	Case WMPLib.WMPPlayState.wmppsTransitioning
   	' actuar en el evento wmppsTransitioning sólo si blShuffle es True
   	If blShuffle = True Then
      		Call Aleatorio()
   	End If
   End Select
End Sub

Reproducción aleatoria

El procedimiento Aleatorio() se encarga de generar un número aleatorio entre 1 y el número de elementos que componen la matriz de canciones (es decir, entre 1 y el número total de canciones en la carpeta).

La función Randomize() sin argumento arranca el generador de números aleatorios con un valor de inicialización basado en el temporizador del sistema.

La función Rnd() devuelve un número aleatorio de tipo Single (devuelve un valor menor que 1 pero mayor o igual que cero). Para producir enteros aleatorios en un intervalo dado, se utiliza la siguiente fórmula:

aleatorio = CInt(Int((límite_superior - límite_inferior + 1) * Rnd() + límite_inferior))

En el siguiente ejemplo se genera un entero aleatorio en el intervalo entre 1 y 6:

Dim value As Integer = CInt(Int((6 * Rnd()) + 1))

Como comprobación accesoria y para repasar cómo escribir en un archivo de texto con la clase StreamWriter, cada vez que arranca el programa se crea un archivo de texto en el que se van anotando los índices de las canciones según van siendo reproducidas. El archivo se llama Lista.txt y se crea en el directorio temporal. Si se reproduce una lista (WPL) solamente escribe el título y hora de comienzo.
El constructor de StreamWriter lleva un 2 parámetros:
- la ruta al archivo en que se va a escribir
- un parámetro booleano que puede ser False (lo que se escribe substituye a lo que ya está escrito) o True (lo que se escribe se añade al final de lo que ya está escrito).

Private Sub Aleatorio()
   Try
     ' ejecutar este método cuando blShuffle es True
     If blShuffle = True Then
       ' para que no llame al método Aleatorio() en el evento wmppsTransitioning
       ' hasta que termine el propio método Aleatorio()
       blShuffle = False
       '
       Randomize()
       '
       ' saber el número de archivos MP3 -> límite superior para usar con Rnd()
       Dim n As Integer
       n = strLista.Length - 1
       ' obtener un índice aleatorio
       ' (se usa -1 porque el índice del array empieza en cero)
       intCancion = CInt(n * Rnd() + 1) - 1
       strArchivo = strLista(intCancion)
       '
       ' utilizar solamente archivos MP3, WAV y WPL
       If strArchivo.EndsWith("mp3") Or strArchivo.EndsWith("wav") Or strArchivo.EndsWith("wpl") Then
         ocxPlayer.URL = strArchivo
       Else
         ' si tiene otra extensión diferente, volver a generar un índice aleatorio
         blShuffle = True ' para que se pueda ejecutar Aleatorio()
         Call Aleatorio()
       End If
       ' 
       objEscritor = New StreamWriter(Environment.GetEnvironmentVariable("TEMP") & "\Lista.txt", True)
       objEscritor.WriteLine(a & " - strLista[" & intCancion & "]")
       a = a + 1
       objEscritor.Close()
       '
       ' para poder llamar al método Aleatorio() en el evento wmppsTransitioning
       blShuffle = True
     End If
     '
   Catch pollo2 As Exception
     MsgBox("Error en el índice: " & intCancion & "." & vbCrLf & pollo2.Message)
   End Try
   '
End Sub


Imagen del programa en funcionamiento

Imagen del programa en funcionamiento


Espacios de nombres usados en el código de este artículo:

System.IO
System.WMPLib


Fichero con el código de ejemplo: miliuco_aleatorio.zip - 136 KB

(MD5 checksum: [4826FD5691566DE472357F6D8E31B484])


ir al índice principal del Guille