This article is currently in the process of being translated into Spanish (~99% done).
Playing audio
WPF viene con un excelente soporte incorporado para sonido y video, como podrás ver en el siguiente par de ejemplos de este tutorial. En este artículo en particular, nosotros abordaremos la habilidad para reproducir sonido, procedente de ficheros de audio, p.ej: en formato MP3, pero primero, veamos un par de aproximaciones más simples.
Sonidos del sistema y la clase SoundPlayer
WPF tiene una clase llamada SoundPlayer, que reproduce contenido de audio basado en el formato WAV. El formato WAV hoy ya no es ampliamente utilizado, principalmente porque no es comprimido y por lo tanto ocupa MUCHO espacio.
Así, mientras la clase SoundPlayer es fácil de usar, no es demasiado útil. En su lugar, nos centraremos en las clases MediaPlayer y MediaElement , que permiten la reproducción de ficheros MP3, pero primero, echemos un vistazo a la forma más simple de producir un sonido en su aplicación WPF: la clase SystemSounds.
La clase SystemSounds ofrece varios sonidos diferentes, que corresponden al sonido definido para cada evento en Windows, como Exclamation (exclamación) y Question (pregunta). Puede probar estos sonidos y reproducirlos con una simple linea de código:
SystemSounds.Beep.Play();
Aquí hay un ejemplo completo, donde usamos todos los sonidos actualmente disponibles:
<Window x:Class="WpfTutorialSamples.Audio_and_Video.SystemSoundsSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="SystemSoundsSample" Height="200" Width="150">
<StackPanel Margin="10" HorizontalAlignment="Center" VerticalAlignment="Center">
<Button Name="btnAsterisk" Click="btnAsterisk_Click">Asterisk</Button>
<Button Name="btnBeep" Margin="0,5" Click="btnBeep_Click">Beep</Button>
<Button Name="btnExclamation" Click="btnExclamation_Click">Exclamation</Button>
<Button Name="btnHand" Margin="0,5" Click="btnHand_Click">Hand</Button>
<Button Name="btnQuestion" Click="btnQuestion_Click">Question</Button>
</StackPanel>
</Window>
using System;
using System.Media;
using System.Windows;
namespace WpfTutorialSamples.Audio_and_Video
{
public partial class SystemSoundsSample : Window
{
public SystemSoundsSample()
{
InitializeComponent();
}
private void btnAsterisk_Click(object sender, RoutedEventArgs e)
{
SystemSounds.Asterisk.Play();
}
private void btnBeep_Click(object sender, RoutedEventArgs e)
{
SystemSounds.Beep.Play();
}
private void btnExclamation_Click(object sender, RoutedEventArgs e)
{
SystemSounds.Exclamation.Play();
}
private void btnHand_Click(object sender, RoutedEventArgs e)
{
SystemSounds.Hand.Play();
}
private void btnQuestion_Click(object sender, RoutedEventArgs e)
{
SystemSounds.Question.Play();
}
}
}
Hay, por supuesto, varias limitaciones utilizando esta via. Lo primero de todo, sólo tendrá acceso a estos cinco sonidos, y lo segundo, el usuario puede haberlos desactivado en Windows, en cuyo caso el sonido esperado será sustituido por un silencio. Por otro lado, si sólo quiere usar estos sonidos de la misma forma en que Windows lo hace, resulta extremadamente fácil producir un sonido para avisos, preguntas, etc. En ese caso, es bueno que su aplicación respete la opción del usuario a estar en silencio.
La clase MediaPlayer
La clase MediaPlayer usa la tecnología de Windows Media Player para reproducir tanto sonido como video en varios formatos modernos, p.ej: MP3 y MPEG. En este artículo, estaremos usándolo para reproducir sólamente audio, y después nos centraremos en video en el siguiente artículo.
Reproducir un fichero MP3 con la clase MediaPlayer es muy simple, como veremos en el siguiente ejemplo:
<Window x:Class="WpfTutorialSamples.Audio_and_Video.MediaPlayerAudioSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MediaPlayerAudioSample" Height="100" Width="200">
<Grid VerticalAlignment="Center" HorizontalAlignment="Center">
<Button Name="btnOpenAudioFile" Click="btnOpenAudioFile_Click">Open Audio file</Button>
</Grid>
</Window>
using System;
using System.Windows;
using System.Windows.Media;
using Microsoft.Win32;
namespace WpfTutorialSamples.Audio_and_Video
{
public partial class MediaPlayerAudioSample : Window
{
private MediaPlayer mediaPlayer = new MediaPlayer();
public MediaPlayerAudioSample()
{
InitializeComponent();
}
private void btnOpenAudioFile_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "MP3 files (*.mp3)|*.mp3|All files (*.*)|*.*";
if(openFileDialog.ShowDialog() == true)
{
mediaPlayer.Open(new Uri(openFileDialog.FileName));
mediaPlayer.Play();
}
}
}
}
En este ejemplo, tenemos únicamente un botón, que mostrará un OpenFileDialog (diálogo para abrir un fichero) para seleccionar un fichero MP3. Una vez que esté hecho, se usará la instancia previamente creada de la clase MediaPlayer para abrir y reproducir ese fichero. Nótese que el objeto MediaPlayer es creado fuera del manejador de eventos. Esto asegura que el objeto no sea descartado prematuramente por el recolector de basura porque salga fuera de ámbito una vez que el manejador de eventos finaliza, lo que podría resultar en que se detuviera la reproducción.
Por favor, ten en cuenta que no se ha realizado ningún mecanismo de manejo de excepciones para este ejemplo, como es habitual para mantener el ejemplo lo más compacto posible, pero en este caso también porque los métodos Open() y Play() no lanzan ninguna excepción en realidad. En su lugar, puedes usar los eventos MediaOpened y MediaFailed para intervenir cuando las cosas vayan bien o mal.
Controlando la clase MediaPlayer
En nuestro primer ejemplo con MediaPlayer, sólo abrimos y automáticamente iniciamos la reproducción del fichero, sin dar al usuario una opción para controlar el proceso de reproducción, pero obviamente, el control MediaPlayer le ofrece pleno control sobre la reproducción. Aquí hay un ejemplo que muestra las funciones más importantes:
<Window x:Class="WpfTutorialSamples.Audio_and_Video.MediaPlayerAudioControlSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MediaPlayerAudioControlSample" Height="120" Width="300">
<StackPanel Margin="10">
<Label Name="lblStatus" Content="Not playing..." HorizontalContentAlignment="Center" Margin="5" />
<WrapPanel HorizontalAlignment="Center">
<Button Name="btnPlay" Click="btnPlay_Click">Play</Button>
<Button Name="btnPause" Margin="5,0" Click="btnPause_Click">Pause</Button>
<Button Name="btnStop" Click="btnStop_Click">Stop</Button>
</WrapPanel>
</StackPanel>
</Window>
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;
using Microsoft.Win32;
namespace WpfTutorialSamples.Audio_and_Video
{
public partial class MediaPlayerAudioControlSample : Window
{
private MediaPlayer mediaPlayer = new MediaPlayer();
public MediaPlayerAudioControlSample()
{
InitializeComponent();
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "MP3 files (*.mp3)|*.mp3|All files (*.*)|*.*";
if(openFileDialog.ShowDialog() == true)
mediaPlayer.Open(new Uri(openFileDialog.FileName));
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += timer_Tick;
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
if(mediaPlayer.Source != null)
lblStatus.Content = String.Format("{0} / {1}", mediaPlayer.Position.ToString(@"mm\:ss"), mediaPlayer.NaturalDuration.TimeSpan.ToString(@"mm\:ss"));
else
lblStatus.Content = "No file selected...";
}
private void btnPlay_Click(object sender, RoutedEventArgs e)
{
mediaPlayer.Play();
}
private void btnPause_Click(object sender, RoutedEventArgs e)
{
mediaPlayer.Pause();
}
private void btnStop_Click(object sender, RoutedEventArgs e)
{
mediaPlayer.Stop();
}
}
}
En este ejemplo, hemos ampliado nuestro reproductor un poco, de modo que ahora contiene los botones Play (reproducir), Pause (pausa) y Stop (detener), así como una etiqueta para mostrar el estado actual de la reproducción. El fichero MP3 a reproducir es cargado del mismo modo, pero lo hacemos tan pronto como la aplicación se inicia, para mantener el ejemplo sencillo.
Inmediatamente después de cargar el fichero MP3, iniciamos un temporizador que se activa cada segundo. Usamos este evento para actualizar la etiqueta de estado, que mostrará el progreso actual, así como la longitud completa del fichero cargado.
Cada uno de los tres botones, simplemente llaman al método correspondiente del objeto MediaPlayer: Play, Pause y Stop.
Resumen
Existen bastantes más opciones que puede ofrecer a su control de usuario, pero quiero reservar eso para cuando hayamos hablado sobre los aspectos de video de la clase MediaPlayer. En ese momento, haré un ejemplo más completo de un reproductor capaz de ejecutar ambos, ficheros de sonido y video, con más opciones.