php怎么控制mp3播放器,简单的C++ MP3播放器类

作者:Wong Shao Voon

如果你需要的只是在你的应用程序中播放MP3(例如,在应用程序启动画面播放很短的MP3),对于这样简单的需求,可以使用C++ MP3/WMA DirectShow播放MP3封装类。源代码来自Flipcode Alan Kemp的贡献。源代码需要一些调整,包含必要的头文件和导入库,这样它才可以在Visual Studio 2010中编译。由于该类依赖DirectShow,你需要下载Windows SDK来构建它。如果您正在使用Visual Studio 2010,它本身就带有Windows SDK,包含了DirectShow库的一个子集,所以你不用下载任何东西就可以编译它。在加载MP3文件前你必须调用COM的CoInitialize来初始化COM,在应用程序结束前你还需要调用CoUninitialize来清理。头文件mp3.h列在下面。

af666ffc33453e1d30f30249983813af.png

图1:cppmp3player

#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers

// Windows Header Files:

#include

#include

#include

#include

#pragma comment(lib, "strmiids.lib")

class Mp3

{

public:

Mp3();

~Mp3();

bool Load(LPCWSTR filename);

void Cleanup();

bool Play();

bool Pause();

bool Stop();

// Poll this function with msTimeout = 0, so that it return immediately.

// If the mp3 finished playing, WaitForCompletion will return true;

bool WaitForCompletion(long msTimeout, long* EvCode);

// -10000 is lowest volume and 0 is highest volume, positive value > 0 will fail

bool SetVolume(long vol);

// -10000 is lowest volume and 0 is highest volume

long GetVolume();

// Returns the duration in 1/10 millionth of a second,

// meaning 10,000,000 == 1 second

// You have to divide the result by 10,000,000

// to get the duration in seconds.

__int64 GetDuration();

// Returns the current playing position

// in 1/10 millionth of a second,

// meaning 10,000,000 == 1 second

// You have to divide the result by 10,000,000

// to get the duration in seconds.

__int64 GetCurrentPosition();

// Seek to position with pCurrent and pStop

// bAbsolutePositioning specifies absolute or relative positioning.

// If pCurrent and pStop have the same value, the player will seek to the position

// and stop playing. Note: Even if pCurrent and pStop have the same value,

// avoid putting the same pointer into both of them, meaning put different

// pointers with the same dereferenced value.

bool SetPositions(__int64* pCurrent, __int64* pStop, bool bAbsolutePositioning);

private:

IGraphBuilder * pigb;

IMediaControl * pimc;

IMediaEventEx * pimex;

IBasicAudio * piba;

IMediaSeeking * pims;

bool ready;

// Duration of the MP3.

__int64 duration;

};

原始版本只有播放,暂停和停止功能。在调用Pause暂停后,你必须调用Play来恢复播放。因为我需要循环播放音乐,所以我需要知道什么时候我的MP3已经结束,所以我加入了一个方法,用WaitForCompletion来定期轮询演奏是否结束,并再次重播。原始的代码中总以最大音量播放,我也添加了一个方法,GetVolume得到音量,SetVolume设置音量。注:-10000是最小音量,0是最大音量。如果设置的音量大于0,你会得到一个错误。这两个方法返回是以1千万分之一秒为单位(1/10000000秒),我没有按秒为单位返回,因为秒的时间实在是太长了。

#include "Mp3.h"

#include

Mp3::Mp3()

{

pigb = NULL;

pimc = NULL;

pimex = NULL;

piba = NULL;

pims = NULL;

ready = false;

duration = 0;

}

Mp3::~Mp3()

{

Cleanup();

}

void Mp3::Cleanup()

{

if (pimc)

pimc->Stop();

if(pigb)

{

pigb->Release();

pigb = NULL;

}

if(pimc)

{

pimc->Release();

pimc = NULL;

}

if(pimex)

{

pimex->Release();

pimex = NULL;

}

if(piba)

{

piba->Release();

piba = NULL;

}

if(pims)

{

pims->Release();

pims = NULL;

}

ready = false;

}

bool Mp3::Load(LPCWSTR szFile)

{

Cleanup();

ready = false;

if (SUCCEEDED(CoCreateInstance( CLSID_FilterGraph,

NULL,

CLSCTX_INPROC_SERVER,

IID_IGraphBuilder,

(void **)&this->pigb)))

{

pigb->QueryInterface(IID_IMediaControl, (void **)&pimc);

pigb->QueryInterface(IID_IMediaEventEx, (void **)&pimex);

pigb->QueryInterface(IID_IBasicAudio, (void**)&piba);

pigb->QueryInterface(IID_IMediaSeeking, (void**)&pims);

HRESULT hr = pigb->RenderFile(szFile, NULL);

if (SUCCEEDED(hr))

{

ready = true;

if(pims)

{

pims->SetTimeFormat(&TIME_FORMAT_MEDIA_TIME);

pims->GetDuration(&duration); // returns 10,000,000 for a second.

duration = duration;

}

}

}

return ready;

}

bool Mp3::Play()

{

if (ready&&pimc)

{

HRESULT hr = pimc->Run();

return SUCCEEDED(hr);

}

return false;

}

bool Mp3::Pause()

{

if (ready&&pimc)

{

HRESULT hr = pimc->Pause();

return SUCCEEDED(hr);

}

return false;

}

bool Mp3::Stop()

{

if (ready&&pimc)

{

HRESULT hr = pimc->Stop();

return SUCCEEDED(hr);

}

return false;

}

bool Mp3::WaitForCompletion(long msTimeout, long* EvCode)

{

if (ready&&pimex)

{

HRESULT hr = pimex->WaitForCompletion(msTimeout, EvCode);

return *EvCode > 0;

}

return false;

}

bool Mp3::SetVolume(long vol)

{

if (ready&&piba)

{

HRESULT hr = piba->put_Volume(vol);

return SUCCEEDED(hr);

}

return false;

}

long Mp3::GetVolume()

{

if (ready&&piba)

{

long vol = -1;

HRESULT hr = piba->get_Volume(&vol);

if(SUCCEEDED(hr))

return vol;

}

return -1;

}

__int64 Mp3::GetDuration()

{

return duration;

}

__int64 Mp3::GetCurrentPosition()

{

if (ready&&pims)

{

__int64 curpos = -1;

HRESULT hr = pims->GetCurrentPosition(&curpos);

if(SUCCEEDED(hr))

return curpos;

}

return -1;

}

bool Mp3::SetPositions(__int64* pCurrent, __int64* pStop, bool bAbsolutePositioning)

{

if (ready&&pims)

{

DWORD flags = 0;

if(bAbsolutePositioning)

flags = AM_SEEKING_AbsolutePositioning | AM_SEEKING_SeekToKeyFrame;

else

flags = AM_SEEKING_RelativePositioning | AM_SEEKING_SeekToKeyFrame;

HRESULT hr = pims->SetPositions(pCurrent, flags, pStop, flags);

if(SUCCEEDED(hr))

return true;

}

return false;

}

源代码包含一个静态库项目和DLL项目以及一个DEMO项目,PlayMp3,包含一个有用类的MP3播放器,CLibMP3DLL,运行时加载LibMP3DLL.dll。CLibMP3DLL的使用方法类似于Mp3类,用LoadDLL和UnloadDLL来加载/释放动态库。以下是CLibMP3DLL的头文件。

class CLibMP3DLL

{

public:

CLibMP3DLL(void);

~CLibMP3DLL(void);

bool LoadDLL(LPCWSTR dll);

void UnloadDLL();

bool Load(LPCWSTR filename);

bool Cleanup();

bool Play();

bool Pause();

bool Stop();

bool WaitForCompletion(long msTimeout, long* EvCode);

bool SetVolume(long vol);

long GetVolume();

__int64 GetDuration();

__int64 GetCurrentPosition();

bool SetPositions(__int64* pCurrent, __int64* pStop, bool bAbsolutePositioning);

private:

HMODULE m_Mod;

};

我往这个MP3类添加许多方法,花了相当多的努力并让他们正确运行,我希望其他程序员可以通过这些代码方便地播放MP3文件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值