近來閑來有事,便想到用自己這段時間學習的知識寫一個音樂播放器。提前聲明,我不擅長界面,因此做出來的界面的卻有些次,但不是本系列文章的重點。
先講下我們開發此音樂播放器所用到的技術:數據綁定、Xml、MediaPlayer類、數據模板等,將在之后陸續講解。
來闡述下播放器開發的整體思路:構建音樂播放類用於播放音樂,用兩個控件分別作為播放列表和播放控制,並且利用控件模板改變它們的界面,利用Xml數據讀取類XmlListsReader來讀取位於存放列表的xml,將歌曲名稱、文件路徑、持續時間歌手等信息讀取到Product類中,並設置ListBox的ItemSouse為此類,采用數據模板顯示數據。
好了,開始我們第一部分的教程--音樂播放類的構建。
話說利用WPF播放音樂有多種方法:MediaPlayer類,SoundPlayer類,以及使用DirectX Sound等。若要選擇一種功能較多,方便易用的方法,定要屬MediaPlayer類了,唯一的限制就是需要依賴Windows Media Player(WMP)。不過在Windows環境下,這一限制可以忽略不計,都是系統自帶的,不是嗎?
當然,我們可以直接在窗口中防置MediaPlayer的操作代碼,但是為了更正規化和可維護性,我們將它封裝進MusicPlayer類中。
在類的開頭,先來定義幾個私有變量和公有的枚舉(表示播放器的狀態):
public enum PlayState : int { stoped = 0, playing = 1, paused = 2 } private MediaPlayer player = null; private Uri musicfile; private PlayState state; public Uri MusicFile { set { musicfile = value; } get { return musicfile; } }
接下來寫構造函數,一個帶參數(音樂文件路徑),一個不帶參數的:
public MusicPlay() { player = new MediaPlayer(); } public MusicPlay(Uri file) { Load(file); }
構造函數將傳入的文件路徑傳到Load方法中處理,以下是Load方法的代碼:
public void Load(Uri file) { player = new MediaPlayer(); MusicFile = file; player.Open(musicfile); }
Load方法中設置了MusicFile(公有變量,指示文件路徑),用MediaPlayer的Open方法加載了音樂文件。
接下來是播放、暫停、停止的代碼:
public void Play() { player.Play(); state = PlayState.playing; } public void Pause() { player.Pause(); state = PlayState.paused; } public void Stop() { player.Stop(); state = PlayState.stoped; }
以上三個方法的第一句代碼分別是設置播放、暫停、停止,第二句代碼是設置播放器當前的狀態。
然后是獲取音樂文件的自然持續時間:
public TimeSpan GetMusicDurationTime() { while (!player.NaturalDuration.HasTimeSpan) { if (player.NaturalDuration.HasTimeSpan) { return player.NaturalDuration.TimeSpan; } } return new TimeSpan(); }
這里用了MediaPlayer的NaturalDuration.HasTimeSpan檢查是否可以讀取音樂的自然持續時間,還用了While循環避免了讀取到空值或讀取不到的情況。
這是設置和獲取當前進度的方法:
public void SetPosition(TimeSpan tp) { player.Position = tp; } public TimeSpan GetPosition() { return player.Position; }
設置音量和讀取音量,傳入參數為0即是靜音:
public void SetVolume(double volume) { player.Volume = volume; } public double GetVolume(double volume) { return player.Volume; }
獲取和設置當前播放器的狀態,這里只是三種狀態,但實際可能會更多:
public PlayState GetPlayState() { return state; } public void SetPlayState(PlayState state) { if (state == PlayState.playing) { this.Play(); } else if (state == PlayState.paused) { this.Pause(); } else if (state == PlayState.stoped) { this.Stop(); } }
再加個根據文件路徑獲取音樂名字的方法:
public string GetMusicTitle() { string title=player.Source.ToString(); return title.Substring(title.LastIndexOf("/")+1, title.Length - title.LastIndexOf("/")-1); }
這個方法的第二句代碼就是截取字符串最后一個"/"后邊的部分。
還有我在這里還定義了個 DispatcherTimer,用來更新音樂的位置,完全可以用更改通知來完成相同的任務,但我沒有用到,大家可以嘗試下。
以下是完整代碼,沒寫注釋,湊合看吧,應該不難:
using System; using System.Collections.Generic; using System.Linq; using System.Media; using System.Text; using System.Threading; using System.Windows; using System.Windows.Media; using System.Windows.Threading; namespace WpfApplication10 { public class MusicPlay { public enum PlayState : int { stoped = 0, playing = 1, paused = 2 } private MediaPlayer player = null; private Uri musicfile; private PlayState state; public Uri MusicFile { set { musicfile = value; } get { return musicfile; } } public DispatcherTimer dt = null; public MusicPlay() { player = new MediaPlayer(); } public MusicPlay(Uri file) { Load(file); } public void Load(Uri file) { player = new MediaPlayer(); MusicFile = file; player.Open(musicfile); } public void Play() { player.Play(); dt.Start(); state = PlayState.playing; } public void Pause() { player.Pause(); state = PlayState.paused; } public void Stop() { player.Stop(); state = PlayState.stoped; } public string GetMusicTitle() { string title=player.Source.ToString(); return title.Substring(title.LastIndexOf("/")+1, title.Length - title.LastIndexOf("/")-1); //return ""; } public TimeSpan GetMusicDuringTime() { while (!player.NaturalDuration.HasTimeSpan) { if (player.NaturalDuration.HasTimeSpan) { return player.NaturalDuration.TimeSpan; } } return new TimeSpan(); } public void SetPosition(TimeSpan tp) { player.Position = tp; } public TimeSpan GetPosition() { return player.Position; } public void SetVolume(double volume) { player.Volume = volume; } public double GetVolume(double volume) { return player.Volume; } public PlayState GetPlayState() { return state; } public void SetPlayState(PlayState state) { if (state == PlayState.playing) { this.Play(); } else if (state == PlayState.paused) { this.Pause(); } else if (state == PlayState.stoped) { this.Stop(); } } } }
可別急着構建界面。。。在下篇文章中我們將構建Xml讀取類,敬請期待,同時期待拍磚者的到來。。。。。。。