Silverlight製作音樂播放器

 Silverlight提供了MediaElement控件方便開發者製作音樂或媒體播放器, 它可以提供流暢的音樂播放和高清晰度的視頻效果. 這裏我們來介紹一下如何利用MediaElement控件製作簡單的網頁音樂播放器. 在這裏示例中, 在網頁中你可以看到一個MediaElement控件, 3個Slider控件, 一個DataGrid和若干個Button控件. MediaElement用於綁定音樂文件和播放, Slider控件用於綁定音樂的進度過程, 平衡度和音量, 你可以通過拖拽Slider來控制音樂文件的效果.

綁定平衡度和音量時比較簡單的, 你可以直接通過Binding方法設置ElementName, path和UpdateSourceTrigger屬性, 或者通過ValueChange事件來綁定. 對於進度條的綁定就稍微要麻煩一點, 一般我們有兩種方式來實現, 第一個是採用Timer控件, 定期的去追蹤音樂文件的播放事件, 並且改變Slider的Value值, 還有一種方式是通過創建一個繼承IValueConvert接口的類返回Time的秒數, 綁定給Slider控件. 用戶可以觀察音樂的播放進度, 並且允許拖拽光標來實現快進或者倒退.

好了, 現在來看一下這個簡單的媒體的播放器是怎麼實現的, 首先, 確認一個你的電腦是夠安裝了Silverlight 4 SDK和SIlverlight 4 Toolkit. 運行Silverlight示例一般需要這兩個基本程序, 它們的下載地址如下:

http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=7335

http://www.microsoft.com/download/en/details.aspx?id=18149

 

[本示例完整源碼下載(0分)] http://download.csdn.net/source/3448102 

基本準備工作結束了, 首先在Visual Studio裏面創建一個Silverlight程序, 爲了更貼近現在的開發環境, 在創建Silverlight程序時包括它寄宿的Web應用程序. 因爲通常網絡音樂播放器的音樂文件和播放列表是存在於Web服務器上的, 那麼在默認存在的Web應用程序中的ClientBin文件夾中放入你的音樂文件(如a.mp3), 接着我們放入一個XML文件作爲音樂播放列表, XML文件示例如下, 爲了方便於測試, 這裏我們只放進了兩個音樂文件:

MusicList.xml

<root>
  <music open="1" path="ClientBin/Mp3/Buddy Joe.mp3" name="Buddy Joe">Buddy Joe</music>
  <music open="1" path="ClientBin/Mp3/Complicated.mp3" name="Complicated">Complicated</music>
</root>


接着, 在SIlverlight項目中創建一個DataItem實體類作爲音樂文件的實體類, 包括音樂文件的名稱和路徑:

DataItem.cs

public class DataItem
    {
        private string nameItem;
        private string pathItem;

        public string NameItem
        {
            get
            {
                return nameItem;
            }
            set
            {
                nameItem = value;
            }
        }

        public string PathItem
        {
            get
            {
                return pathItem;
            }
            set
            {
                pathItem = value;
            }
        }
    }


創建一個類繼承IValueConvert接口, 用於綁定Process Slider的控件值Value,使得用戶能過觀測到音樂文件的播放進度, 它必須實現兩個方法Convert和ConvertBack:

 ProgressConverter.cs

    public class ProgressConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return ((TimeSpan)value).TotalSeconds;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return TimeSpan.FromSeconds((double)value);
        }
    }

接着修改MainPage.xaml文件, 添加必要的MediaElement, Slider, DataGrid等控件, DataGrid用於綁定XML文件的數據, 這裏需要在XAML文件中引入ProcessConverter, 這需要在UserControl頭文件中加入註冊信息 xmlns:yw="clr-namespace:CSSL4MediaPlayer" 並且在Grid容器外引入UserControl的Resource文件  <UserControl.Resources> <yw:ProgressConverter x:Key="progress"></yw:ProgressConverter></UserControl.Resources>   全部代碼如下:

MainPage.xaml

<UserControl xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" 
             x:Class="CSSL4MediaPlayer.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:yw="clr-namespace:CSSL4MediaPlayer"
    mc:Ignorable="d"
    d:DesignHeight="478" d:DesignWidth="604">
    <UserControl.Resources>
        <yw:ProgressConverter x:Key="progress"></yw:ProgressConverter>
    </UserControl.Resources>
        <Grid x:Name="LayoutRoot" HorizontalAlignment="Left" Width="599" Height="474"    ShowGridLines="False" VerticalAlignment="Top" Margin="5,5,5,5">
        <Grid.RowDefinitions>
            <RowDefinition Height="68"/>
            <RowDefinition Height="53"/>
            <RowDefinition Height="71"/>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="282*" />
        </Grid.RowDefinitions>
        <MediaElement x:Name="mediaElement" Width="300" Grid.Row="1" AutoPlay="True" 
                      IsMuted="False" Stretch="Fill" Volume="0.5" 
                      CurrentStateChanged="mediaElement_CurrentStateChanged" MediaEnded="mediaElement_MediaEnded" MediaOpened="mediaElement_MediaOpened" Margin="44,0,44,147"></MediaElement>
        <Button x:Name="btnStop" Content="stop" Grid.Row="2" Width="70" Height="25" Click="btnStop_Click" Margin="30,25,499,21"></Button>
        <Button x:Name="btnPlay" Content="play" Grid.Row="2" Width="70" Height="25" Click="btnPlay_Click" Margin="0,25,430,21" HorizontalAlignment="Right"></Button>
        <Button x:Name="btnPause" Content="pause" Grid.Row="2" Width="70" Height="25" Click="btnPause_Click" Margin="168,25,361,21"></Button>
        <Button x:Name="btnMuted" Content="muted" Grid.Row="2" Width="70" Height="25" Click="btnMuted_Click" Margin="236,25,293,21"></Button>
        <Button x:Name="btnFullScreen" Content="full screen" Grid.Row="2" Height="25" Click="btnFullScreen_Click" Margin="305,25,210,21"></Button>
        <TextBlock Grid.Row="4" Height="23" HorizontalAlignment="Left" Margin="255,9,0,0" Name="textBlock1" Text="Music Play List" VerticalAlignment="Top" />
        <sdk:DataGrid AutoGenerateColumns="False" ItemsSource="{Binding}" Grid.Row="4" Height="196" HorizontalAlignment="Left" Margin="196,36,0,50" Name="girdList" VerticalAlignment="Center" Width="206" SelectionChanged="girdList_SelectionChanged">
            <sdk:DataGrid.Columns >
                <sdk:DataGridTextColumn Header="name" Binding="{Binding NameItem}" Width="204" IsReadOnly="True"></sdk:DataGridTextColumn>
            </sdk:DataGrid.Columns>
        </sdk:DataGrid>
        <TextBlock Height="34" Margin="200,18,197,0" Name="tbTitle" Text="Silverlight Media" VerticalAlignment="Top" FontSize="24" Width="200" />
        <Slider x:Name="sliderProcess" Grid.Row="1" Minimum="0" Value="{Binding ElementName=mediaElement, Path=Position, Mode=TwoWay, Converter={StaticResource progress}}" Maximum="230"  Margin="96,0,78,0" IsEnabled="False" />
        <TextBlock Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="22,17,0,0" Name="textBlock2" Text="Process:" VerticalAlignment="Top" />
        <Slider LargeChange="0.1" Margin="466,3,39,46" Maximum="1" SmallChange="0.01" Value="{Binding Volume, ElementName=mediaElement, Mode=TwoWay, UpdateSourceTrigger=Default}" Grid.Row="2" />
        <TextBlock Height="23" HorizontalAlignment="Left" Margin="413,5,0,0" Name="tbTag1" Text="Volumn:" VerticalAlignment="Top" Grid.Row="2" />
        <Slider LargeChange="0.1" Margin="466,43,39,6"  Minimum="-1" Maximum="1" Grid.Row="2" ValueChanged="Slider_ValueChanged" Name="sliderBalance" />
        <TextBlock Height="23" HorizontalAlignment="Left" Margin="413,45,0,0" Name="tbTag2" Text="Balance:" VerticalAlignment="Top" Grid.Row="2" />
        <TextBlock Grid.Row="1" Height="16" HorizontalAlignment="Left" Margin="536,6,0,0" Name="tbTag" Text="Status:" VerticalAlignment="Top" />
        <TextBlock Grid.Row="1" Height="19" HorizontalAlignment="Left" Margin="532,30,0,0" Name="tbStatus" Text="" VerticalAlignment="Top" />
    </Grid>
</UserControl>


最後添加播放器的基本功能, 比如建立播放器的播放, 暫停, 停止, 靜音, 全屏等功能, 實現異步的方法讀取XML文件, 並且追蹤MediaElement播放器的狀態並且顯示出來:

MainPage.xaml.cs

public partial class MainPage : UserControl
    {
        // Define some public properties of application, include data items, 
        // some signal variables, a TimeSpan class and a timer. 
        public List<DataItem> DataItems;
        public bool blnIsMuted = false;
        public bool blnIsFull = false;
        private TimeSpan timeDuration;

        public MainPage()
        {
            InitializeComponent();
            this.XmlProcessMethod(); 
        }

        /// <summary>
        /// This method used to asynchronous loading data from xml file and 
        /// adds DownLoadXmlComplete method with WebCient, it will add other 
        /// methods to timer and media element.
        /// </summary>
        private void XmlProcessMethod()
        {
            WebClient webClient = new WebClient();
            webClient.DownloadStringAsync(new Uri(HtmlPage.Document.DocumentUri, "ClientBin/MusicList.xml"));
            webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(this.DownLoadXmlComplete);
            mediaElement.MediaEnded += new RoutedEventHandler(mediaElement_MediaEnded);
        }

        private void mediaElement_CurrentStateChanged(object sender, RoutedEventArgs e)
        {
            tbStatus.Text = mediaElement.CurrentState.ToString();
            if (mediaElement.CurrentState != MediaElementState.Playing)
            {
                this.sliderProcess.IsEnabled = false;
            }
            else
            {
                this.sliderProcess.IsEnabled = true;
            }
        }

        private void mediaElement_MediaEnded(object sender, RoutedEventArgs e)
        {
            tbStatus.Text = "complete";
            mediaElement.Stop();
            mediaElement.Position = TimeSpan.Zero;
        }

        private void mediaElement_MediaOpened(object sender, RoutedEventArgs e)
        {
            tbStatus.Text = "start";
            // Retrieve music's total time.
            timeDuration = mediaElement.NaturalDuration.HasTimeSpan ? mediaElement.NaturalDuration.TimeSpan : TimeSpan.FromMilliseconds(0);
            sliderProcess.Maximum = timeDuration.TotalSeconds;
        }

        private void btnStop_Click(object sender, RoutedEventArgs e)
        {
            mediaElement.Pause();
            mediaElement.Position = TimeSpan.Zero;
        }

        private void btnPlay_Click(object sender, RoutedEventArgs e)
        {
            mediaElement.Play();
        }

        private void btnPause_Click(object sender, RoutedEventArgs e)
        {
            mediaElement.Pause();
        }

        /// <summary>
        /// Muted method
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnMuted_Click(object sender, RoutedEventArgs e)
        {
            if (!blnIsMuted)
            {
                btnMuted.Content = "Unmute";
                mediaElement.IsMuted = true;
                blnIsMuted = true;
            }
            else
            {
                btnMuted.Content = "Muted";
                mediaElement.IsMuted = false;
                blnIsMuted = false;
            }
        }

        /// <summary>
        /// Full screen method
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnFullScreen_Click(object sender, RoutedEventArgs e)
        {
            if (!blnIsFull)
            {
                btnFullScreen.Content = "Small Screen";
                Application.Current.Host.Content.IsFullScreen = true;
                blnIsFull = true;
            }
            else
            {
                btnFullScreen.Content = "Full Screen";
                Application.Current.Host.Content.IsFullScreen = false;
                blnIsFull = false;
            }
        }

        /// <summary>
        /// Load music data from xml file and convert data to a List of DataItem
        /// instances. Bind DataGrid control's ItemSource with it.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DownLoadXmlComplete(object sender, DownloadStringCompletedEventArgs e)
        {
            using (XmlReader reader = XmlReader.Create(new StringReader(e.Result)))
            {
                DataItems = new List<DataItem>();
                while (reader.Read())
                {
                    if (reader.IsStartElement() && reader.GetAttribute("open") == "1")
                    {
                        string pathMusic = reader.GetAttribute("path").ToString();
                        string nameMusic = reader.GetAttribute("name").ToString();
                        DataItem dataItem = new DataItem();
                        dataItem.NameItem = nameMusic;
                        dataItem.PathItem = pathMusic;
                        DataItems.Add(dataItem);
                    }
                }
                this.DataContext = DataItems;
            }
        }

        /// <summary>
        /// Allow user to change another song.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void girdList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            sliderProcess.IsEnabled = true;
            mediaElement.Position = new TimeSpan(0);
            sliderProcess.Value = 0;
            DataItem selectItem = (DataItem)girdList.SelectedItem;
            mediaElement.Source = new Uri(HtmlPage.Document.DocumentUri, selectItem.PathItem);
            mediaElement.Play();
        }

        /// <summary>
        /// Go back to the beginning of slider control when music plays complete
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void mdeMusic_MediaEnded(object sender, RoutedEventArgs e)
        {
            sliderProcess.Value = 0;
        }

        /// <summary>
        /// Balance slider
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            mediaElement.Balance = sliderBalance.Value;
        }
       
    }

那麼這個簡單的播放器算是製作完成的, 你需要設置Silverlight.Web應用程序爲啓動項(注意不是Silverlight), 如果你從Silverlight程序進入, 那麼你會在加載Xml文件時收到一個TargetInvocationException錯誤, 這是因爲你的Silverlight無法讀取Web應用程序中的xml導致的, 你當然也可以把XML文件置於Silverlight程序集中.

運行成功後, 你可以點擊歌曲名稱播放它, 進行測試.

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章