因工作需要,近期开始接触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();
}
///
///
///
///
///
///
///
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();
}
}
}
///
///
///
///
#region private methods
///
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";
}
}
///
///
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;
}
}
///
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;
}
///
m_objMediaControl.Run();
m_CurrentStatus = MediaStatus.Running;
btnPlayPause.Text = "暂停";
this.UpdatePlayTime();
this.UpdateButtonStatus();
}
///
///
///
this.InitPlayer();
this.Play();
}
///
this.InitPlayer();
this.Play();
}
///
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;
}
///
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的一些内部机制,仅仅是一个简单例子,在后面如有时间将会对该播放器进行逐步完善。