利用DirectShow开发C#版的MP3播放器(一)

    因工作需要,近期开始接触DirectShow开发的相关技术,由于本人较青睐于C#,因此从网上找了一些关于.NET版的DirectShow库及实例,之后参考相关源码编写了一个用于测试的MP3播放器,源码主要参考了SourceForge(http://sourceforge.net/)上的一份关于DirectShow的源码实例。

    这篇文章展示的是一个初步的不完善的MP3播放器Demo,包括两部分:播放控制部分和播放列表部分。其中播放控制部分的基本功能包括:播放/暂停、停止、上一曲、下一曲、播放进度条、当前播放时间、播放时长、播放标题。播放列表部分包括:播放列表、添加、删除。此外,还增加了顺序播放和随机播放两种播放模式,默认为顺序播放模式。
    因无法上传图片,这里贴出主要代码:

using System;
using System.Windows.Forms;
using System.IO;

using QuartzTypeLib;

namespace MyMp3Player
{
    public partial class FrmPlayer : Form
    {
        private const int WM_APP = 0x8000;
        private const int WM_GRAPHNOTIFY = WM_APP + 1;
        private const int EC_COMPLETE = 0x01;
        private const int WS_CHILD = 0x40000000;
        private const int WS_CLIPCHILDREN = 0x2000000;

 

        private FilgraphManager m_objFilterGraph = null;
        private IBasicAudio m_objBasicAudio = null;
        private IVideoWindow m_objVideoWindow = null;
        private IMediaEvent m_objMediaEvent = null;
        private IMediaEventEx m_objMediaEventEx = null;
        private IMediaPosition m_objMediaPosition = null;
        private IMediaControl m_objMediaControl = null;

 

        enum MediaStatus { None, Stopped, Paused, Running };

        private MediaStatus m_CurrentStatus = MediaStatus.None;

 

        private string m_strFilePath;  // 文件路径
        private bool m_blnRandomPlay = false;  // 随机播放模式

        public FrmPlayer()
        {
            InitializeComponent();

            this.UpdatePlayTime();
            this.UpdatePlayList();
            this.UpdateButtonStatus();
        }

        private void FrmPlayer_Load(object sender, EventArgs e)
        {

        }

        private void FrmPlayer_FormClosing(object sender, FormClosingEventArgs e)
        {
            this.CleanUp();
        }

        ///


        /// 播放/暂停
        ///

        ///
        ///
        private void btnPlayPause_Click(object sender, EventArgs e)
        {
            if (m_CurrentStatus == MediaStatus.Running)
            {
                this.Pause();
            }
            else
            {
                this.Play();
            }
        }

        ///


        /// 停止
        ///

        ///
        ///
        private void btnStop_Click(object sender, EventArgs e)
        {
            this.Stop();
        }

        ///


        /// 上一曲
        ///

        ///
        ///
        private void btnPrevious_Click(object sender, EventArgs e)
        {
            this.Previous();
        }

        ///


        /// 下一曲
        ///

        ///
        ///
        private void btnNext_Click(object sender, EventArgs e)
        {
            this.Next();
        }

        ///


        /// 定时器
        ///

        ///
        ///
        private void timer1_Tick(object sender, EventArgs e)
        {
            if (m_CurrentStatus == MediaStatus.Running)
            {
                this.UpdatePlayTime();
            }
        }

        ///


        /// 播放进度条控制
        ///

        ///
        ///
        private void trackBarPlay_Scroll(object sender, EventArgs e)
        {
            if (m_CurrentStatus != MediaStatus.None)
            {
                m_objMediaPosition.CurrentPosition = m_objMediaPosition.Duration * trackBarPlay.Value / 100;
            }
        }

        ///


        /// 添加播放文件
        ///

        ///
        ///
        private void btnAdd_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();

            openFileDialog.Filter = "MP3文件(*.mp3)|*.mp3";
            openFileDialog.Multiselect = true;

            if (DialogResult.OK == openFileDialog.ShowDialog())
            {
                string[] fileNames = openFileDialog.FileNames;

                if (fileNames != null)
                {
                    foreach (string fileName in fileNames)
                    {
                        lstPlayList.Items.Add(fileName);
                    }

                    if (lstPlayList.SelectedIndex < 0) // 当前播放列表为空
                    {
                        // 选中第一个文件并进行播放
                        lstPlayList.SelectedIndex = 0;
                        this.InitPlayer();
                        this.Play();
                    }

                    this.UpdatePlayList();
                }
            }
        }

        ///


        /// 双击选中文件并播放
        ///

        ///
        ///
        private void lstPlayList_DoubleClick(object sender, EventArgs e)
        {
            if (lstPlayList.Items.Count > 0)
            {
                this.InitPlayer();
                this.Play();
            }
        }

        ///


        /// 随机播放模式
        ///

        ///
        ///
        private void btnPlayRandom_Click(object sender, EventArgs e)
        {
            m_blnRandomPlay = true;
            btnPlayOrder.Enabled = true;
            btnPlayRandom.Enabled = false;
        }

        ///


        /// 顺序播放模式
        ///

        ///
        ///
        private void btnPlayOrder_Click(object sender, EventArgs e)
        {
            m_blnRandomPlay = false;
            btnPlayOrder.Enabled = false;
            btnPlayRandom.Enabled = true;
        }

        ///


        /// 清空播放列表
        ///

        ///
        ///
        private void btnClear_Click(object sender, EventArgs e)
        {
            lstPlayList.Items.Clear();
            btnPlayOrder.Enabled = false;
            btnPlayRandom.Enabled = false;
            btnClear.Enabled = false;
        }

        #region private methods
        ///


        /// 更新播放时间及播放进度
        ///

        private void UpdatePlayTime()
        {
            if (m_objMediaPosition != null)
            {
                int s = (int)m_objMediaPosition.Duration;
                int h = s / 3600;
                int m = (s - (h * 3600)) / 60;
                s = s - (h * 3600 + m * 60);

                lblTotalTime.Text = String.Format("{0:D2}:{1:D2}", m, s);

                s = (int)m_objMediaPosition.CurrentPosition;
                h = s / 3600;
                m = (s - (h * 3600)) / 60;
                s = s - (h * 3600 + m * 60);

                lblCurrentTime.Text = String.Format("{0:D2}:{1:D2}", m, s);

                trackBarPlay.Value = (int)(100 * (m_objMediaPosition.CurrentPosition / m_objMediaPosition.Duration));
            }
            else
            {
                lblTotalTime.Text = "00:00";
                lblCurrentTime.Text = "00:00";
            }
        }

        ///


        /// 根据播放列表状态更新相应按钮状态
        ///

        private void UpdatePlayList()
        {
            if (lstPlayList.Items.Count > 0)
            {
                btnPrevious.Enabled = true;
                btnNext.Enabled = true;
                btnClear.Enabled = true;
                btnPlayRandom.Enabled = true;
            }
            else
            {
                btnPrevious.Enabled = false;
                btnNext.Enabled = false;
                btnClear.Enabled = false;
                btnPlayRandom.Enabled = false;
            }
        }

        ///


        /// 更新播放按钮状态
        ///

        private void UpdateButtonStatus()
        {
            switch (m_CurrentStatus)
            {
                case MediaStatus.None:
                    btnPlayPause.Enabled = false;
                    btnStop.Enabled = false;
                    break;

                case MediaStatus.Paused:
                case MediaStatus.Running:
                    btnPlayPause.Enabled = true;
                    btnStop.Enabled = true;
                    break;

                case MediaStatus.Stopped:
                    btnPlayPause.Enabled = true;
                    btnStop.Enabled = false;
                    lblCurrentTime.Text = "00:00";
                    lblTotalTime.Text = "00:00";
                    trackBarPlay.Value = 0;
                    break;
            }
        }

        ///


        /// 初始化播放
        ///

        private void InitPlayer()
        {
            this.CleanUp();

            m_strFilePath = lstPlayList.SelectedItem.ToString();

            m_objFilterGraph = new FilgraphManager();
            m_objFilterGraph.RenderFile(m_strFilePath);

            m_objBasicAudio = m_objFilterGraph as IBasicAudio;
            m_objMediaEvent = m_objFilterGraph as IMediaEvent;

            m_objMediaEventEx = m_objFilterGraph as IMediaEventEx;
            m_objMediaEventEx.SetNotifyWindow((int)this.Handle, WM_GRAPHNOTIFY, 0);

            m_objMediaPosition = m_objFilterGraph as IMediaPosition;

            m_objMediaControl = m_objFilterGraph as IMediaControl;
        }

        ///


        /// 播放
        ///

        private void Play()
        {
            FileInfo fi = new FileInfo(m_strFilePath);
            string fileName = fi.Name;
            fileName = fileName.Substring(0, fileName.Length - 4);
            if (fileName.IndexOf("&") > 0)
            {
                fileName = fileName.Replace("&", "&&");
            }
            lblTitle.Text = fileName;

            m_objMediaControl.Run();
            m_CurrentStatus = MediaStatus.Running;
            btnPlayPause.Text = "暂停";
            this.UpdatePlayTime();
            this.UpdateButtonStatus();
        }

        ///


        /// 暂停
        ///

        private void Pause()
        {
            m_objMediaControl.Pause();
            m_CurrentStatus = MediaStatus.Paused;
            btnPlayPause.Text = "播放";
            this.UpdatePlayTime();
            this.UpdateButtonStatus();
        }

        ///


        /// 停止
        ///

        private void Stop()
        {
            m_objMediaControl.Stop();
            m_objMediaPosition.CurrentPosition = 0;
            m_CurrentStatus = MediaStatus.Stopped;
            btnPlayPause.Text = "播放";
            this.UpdateButtonStatus();
        }

        ///


        /// 上一曲
        ///

        private void Previous()
        {
            if (m_blnRandomPlay)  // 随机播放模式
            {
                Random random = new Random();
                lstPlayList.SelectedIndex = random.Next(lstPlayList.Items.Count);
            }
            else  // 顺序播放模式
            {
                if (lstPlayList.SelectedIndex == 0)
                {
                    // 已移到最前面,不做任何事情
                }
                else
                {
                    lstPlayList.SelectedIndex -= 1;
                }
            }

            this.InitPlayer();
            this.Play();
        }

        ///


        /// 下一曲
        ///

        private void Next()
        {
            if (m_blnRandomPlay)  // 随机播放模式
            {
                Random random = new Random();
                lstPlayList.SelectedIndex = random.Next(lstPlayList.Items.Count);
            }
            else  // 顺序播放模式
            {
                if (lstPlayList.SelectedIndex == lstPlayList.Items.Count - 1)
                {
                    // 已移到最后面,不做任何事情
                }
                else
                {
                    lstPlayList.SelectedIndex += 1;
                }
            }

            this.InitPlayer();
            this.Play();
        }

        ///


        /// 清理
        ///

        private void CleanUp()
        {
            if (m_objMediaControl != null)
                m_objMediaControl.Stop();

            m_CurrentStatus = MediaStatus.Stopped;

            if (m_objMediaEventEx != null)
                m_objMediaEventEx.SetNotifyWindow(0, 0, 0);

            if (m_objVideoWindow != null)
            {
                m_objVideoWindow.Visible = 0;
                m_objVideoWindow.Owner = 0;
            }

            if (m_objMediaControl != null) m_objMediaControl = null;
            if (m_objMediaPosition != null) m_objMediaPosition = null;
            if (m_objMediaEventEx != null) m_objMediaEventEx = null;
            if (m_objMediaEvent != null) m_objMediaEvent = null;
            if (m_objVideoWindow != null) m_objVideoWindow = null;
            if (m_objBasicAudio != null) m_objBasicAudio = null;
            if (m_objFilterGraph != null) m_objFilterGraph = null;
        }

        ///


        /// 重写WndProc
        ///

        ///
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_GRAPHNOTIFY)
            {
                int lEventCode;
                int lParam1, lParam2;

                while (true)
                {
                    try
                    {
                        m_objMediaEventEx.GetEvent(out lEventCode, out lParam1, out lParam2, 0);
                        m_objMediaEventEx.FreeEventParams(lEventCode, lParam1, lParam2);

                        if (lEventCode == EC_COMPLETE)
                        {
                            this.Next(); // 自动切换到下一曲
                        }
                    }
                    catch (Exception)
                    {
                        break;
                    }
                }
            }

            base.WndProc(ref m);
        }

        #endregion
    }
}

    上面实例使用到了Interop.QuartzTypeLib.dll,并没有完全使用DirectShow的一些内部机制,仅仅是一个简单例子,在后面如有时间将会对该播放器进行逐步完善。

你可能感兴趣的:(程序开发)