269 lines
5.0 KiB
C++
269 lines
5.0 KiB
C++
|
|
#include "..\etools.h"
|
|||
|
|
#include <mmsystem.h>
|
|||
|
|
#include "winbase.h"
|
|||
|
|
#include "MciPlayer.h"
|
|||
|
|
#pragma comment(lib , "winmm.lib")
|
|||
|
|
|
|||
|
|
#define WIN_CLASS_NAME L"MciPlayerCallbackWnd"
|
|||
|
|
|
|||
|
|
static HINSTANCE s_hInstance = nullptr;
|
|||
|
|
|
|||
|
|
LRESULT WINAPI _MciPlayerProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
|
|||
|
|
static bool ExtractResource(LPCTSTR strDstFile, LPCTSTR strResType, LPCTSTR strResName);
|
|||
|
|
|
|||
|
|
|
|||
|
|
MciPlayer::MciPlayer()
|
|||
|
|
: m_wnd(NULL)
|
|||
|
|
, m_dev(0L)
|
|||
|
|
, m_nMusicID(0)
|
|||
|
|
, m_bPlaying(false)
|
|||
|
|
, m_nRepeatTimes(0)
|
|||
|
|
{
|
|||
|
|
if (!s_hInstance)
|
|||
|
|
{
|
|||
|
|
s_hInstance = HINST_THISCOMPONENT;
|
|||
|
|
|
|||
|
|
WNDCLASS wc;
|
|||
|
|
wc.style = 0;
|
|||
|
|
wc.lpfnWndProc = _MciPlayerProc;
|
|||
|
|
wc.cbClsExtra = 0;
|
|||
|
|
wc.cbWndExtra = 0;
|
|||
|
|
wc.hInstance = s_hInstance;
|
|||
|
|
wc.hIcon = 0;
|
|||
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|||
|
|
wc.hbrBackground = NULL;
|
|||
|
|
wc.lpszMenuName = NULL;
|
|||
|
|
wc.lpszClassName = WIN_CLASS_NAME;
|
|||
|
|
|
|||
|
|
if (!RegisterClass(&wc) && 1410 != GetLastError())
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
m_wnd = CreateWindowEx(
|
|||
|
|
WS_EX_APPWINDOW,
|
|||
|
|
WIN_CLASS_NAME,
|
|||
|
|
NULL,
|
|||
|
|
WS_POPUPWINDOW,
|
|||
|
|
0, 0, 0, 0,
|
|||
|
|
NULL,
|
|||
|
|
NULL,
|
|||
|
|
s_hInstance,
|
|||
|
|
NULL);
|
|||
|
|
|
|||
|
|
if (m_wnd)
|
|||
|
|
{
|
|||
|
|
SetWindowLongPtr(m_wnd, GWLP_USERDATA, (LONG_PTR)this);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
MciPlayer::~MciPlayer()
|
|||
|
|
{
|
|||
|
|
close();
|
|||
|
|
DestroyWindow(m_wnd);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool MciPlayer::open(const e2d::EString & pFileName, UINT uId)
|
|||
|
|
{
|
|||
|
|
if (pFileName.empty())
|
|||
|
|
return false;
|
|||
|
|
|
|||
|
|
close();
|
|||
|
|
|
|||
|
|
MCI_OPEN_PARMS mciOpen = { 0 };
|
|||
|
|
mciOpen.lpstrDeviceType = (LPCTSTR)MCI_ALL_DEVICE_ID;
|
|||
|
|
mciOpen.lpstrElementName = pFileName.c_str();
|
|||
|
|
|
|||
|
|
MCIERROR mciError;
|
|||
|
|
mciError = mciSendCommand(
|
|||
|
|
0,
|
|||
|
|
MCI_OPEN,
|
|||
|
|
MCI_OPEN_ELEMENT,
|
|||
|
|
reinterpret_cast<DWORD_PTR>(&mciOpen)
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
if (mciError == 0)
|
|||
|
|
{
|
|||
|
|
m_dev = mciOpen.wDeviceID;
|
|||
|
|
m_nMusicID = uId;
|
|||
|
|
m_bPlaying = false;
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool MciPlayer::open(const e2d::EString & pResouceName, const e2d::EString & pResouceType, const e2d::EString & musicExtension, UINT uId)
|
|||
|
|
{
|
|||
|
|
// <20><><EFBFBD>Բ<EFBFBD><D4B2><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5>ļ<EFBFBD>
|
|||
|
|
if (pResouceName.empty() || pResouceType.empty() || musicExtension.empty()) return false;
|
|||
|
|
|
|||
|
|
// <20><>ȡ<EFBFBD><C8A1>ʱ<EFBFBD>ļ<EFBFBD>Ŀ¼
|
|||
|
|
e2d::EString tempFileName = e2d::EFileUtils::getTempPath();
|
|||
|
|
|
|||
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>
|
|||
|
|
tempFileName.append(L"\\");
|
|||
|
|
tempFileName.append(std::to_wstring(uId));
|
|||
|
|
tempFileName.append(L"." + musicExtension);
|
|||
|
|
|
|||
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԴΪ<D4B4><CEAA>ʱ<EFBFBD>ļ<EFBFBD>
|
|||
|
|
if (ExtractResource(tempFileName.c_str(), pResouceType.c_str(), pResouceName.c_str()))
|
|||
|
|
{
|
|||
|
|
return open(tempFileName, uId);
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void MciPlayer::play(int repeatTimes)
|
|||
|
|
{
|
|||
|
|
if (!m_dev)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
MCI_PLAY_PARMS mciPlay = { 0 };
|
|||
|
|
mciPlay.dwCallback = reinterpret_cast<DWORD_PTR>(m_wnd);
|
|||
|
|
|
|||
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
MCIERROR mciError = mciSendCommand(
|
|||
|
|
m_dev,
|
|||
|
|
MCI_PLAY,
|
|||
|
|
MCI_FROM | MCI_NOTIFY,
|
|||
|
|
reinterpret_cast<DWORD_PTR>(&mciPlay)
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
if (!mciError)
|
|||
|
|
{
|
|||
|
|
m_bPlaying = true;
|
|||
|
|
m_nRepeatTimes = repeatTimes;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void MciPlayer::close()
|
|||
|
|
{
|
|||
|
|
if (m_bPlaying)
|
|||
|
|
{
|
|||
|
|
stop();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (m_dev)
|
|||
|
|
{
|
|||
|
|
_sendCommand(MCI_CLOSE);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
m_dev = 0;
|
|||
|
|
m_bPlaying = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void MciPlayer::pause()
|
|||
|
|
{
|
|||
|
|
_sendCommand(MCI_PAUSE);
|
|||
|
|
m_bPlaying = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void MciPlayer::resume()
|
|||
|
|
{
|
|||
|
|
_sendCommand(MCI_RESUME);
|
|||
|
|
m_bPlaying = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void MciPlayer::stop()
|
|||
|
|
{
|
|||
|
|
_sendCommand(MCI_STOP);
|
|||
|
|
m_bPlaying = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void MciPlayer::rewind()
|
|||
|
|
{
|
|||
|
|
if (!m_dev)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
mciSendCommand(m_dev, MCI_SEEK, MCI_SEEK_TO_START, 0);
|
|||
|
|
|
|||
|
|
MCI_PLAY_PARMS mciPlay = { 0 };
|
|||
|
|
mciPlay.dwCallback = reinterpret_cast<DWORD_PTR>(m_wnd);
|
|||
|
|
|
|||
|
|
MCIERROR mciError = mciSendCommand(
|
|||
|
|
m_dev,
|
|||
|
|
MCI_PLAY,
|
|||
|
|
MCI_NOTIFY,
|
|||
|
|
reinterpret_cast<DWORD_PTR>(&mciPlay)
|
|||
|
|
);
|
|||
|
|
m_bPlaying = mciError ? false : true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool MciPlayer::isPlaying()
|
|||
|
|
{
|
|||
|
|
return m_bPlaying;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
UINT MciPlayer::getMusicID()
|
|||
|
|
{
|
|||
|
|
return m_nMusicID;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void MciPlayer::_sendCommand(int nCommand, DWORD_PTR param1, DWORD_PTR parma2)
|
|||
|
|
{
|
|||
|
|
// <20><><EFBFBD>豸ʱ<E8B1B8><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>β<EFBFBD><CEB2><EFBFBD>
|
|||
|
|
if (!m_dev)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
// <20><><EFBFBD><EFBFBD>ǰ<EFBFBD>豸<EFBFBD><E8B1B8><EFBFBD>Ͳ<EFBFBD><CDB2><EFBFBD>
|
|||
|
|
mciSendCommand(m_dev, nCommand, param1, parma2);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
bool ExtractResource(LPCTSTR strDstFile, LPCTSTR strResType, LPCTSTR strResName)
|
|||
|
|
{
|
|||
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
|
|||
|
|
HANDLE hFile = ::CreateFile(strDstFile, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL);
|
|||
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|||
|
|
return false;
|
|||
|
|
|
|||
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD>ļ<EFBFBD><C4BC>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD>ڴ桢<DAB4>õ<EFBFBD><C3B5><EFBFBD>Դ<EFBFBD><D4B4>С
|
|||
|
|
HRSRC hRes = ::FindResource(NULL, strResName, strResType);
|
|||
|
|
HGLOBAL hMem = ::LoadResource(NULL, hRes);
|
|||
|
|
DWORD dwSize = ::SizeofResource(NULL, hRes);
|
|||
|
|
|
|||
|
|
// д<><D0B4><EFBFBD>ļ<EFBFBD>
|
|||
|
|
DWORD dwWrite = 0; // <20><><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD>ֽ<EFBFBD>
|
|||
|
|
::WriteFile(hFile, hMem, dwSize, &dwWrite, NULL);
|
|||
|
|
::CloseHandle(hFile);
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
LRESULT WINAPI _MciPlayerProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
|||
|
|
{
|
|||
|
|
MciPlayer * pPlayer = NULL;
|
|||
|
|
|
|||
|
|
if (Msg == MM_MCINOTIFY
|
|||
|
|
&& wParam == MCI_NOTIFY_SUCCESSFUL
|
|||
|
|
&& (pPlayer = (MciPlayer *)GetWindowLongPtr(hWnd, GWLP_USERDATA)))
|
|||
|
|
{
|
|||
|
|
if (pPlayer->m_nRepeatTimes > 0)
|
|||
|
|
{
|
|||
|
|
pPlayer->m_nRepeatTimes--;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (pPlayer->m_nRepeatTimes)
|
|||
|
|
{
|
|||
|
|
mciSendCommand(lParam, MCI_SEEK, MCI_SEEK_TO_START, 0);
|
|||
|
|
|
|||
|
|
MCI_PLAY_PARMS mciPlay = { 0 };
|
|||
|
|
mciPlay.dwCallback = reinterpret_cast<DWORD_PTR>(hWnd);
|
|||
|
|
mciSendCommand(lParam, MCI_PLAY, MCI_NOTIFY, reinterpret_cast<DWORD_PTR>(&mciPlay));
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
pPlayer->m_bPlaying = false;
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return DefWindowProc(hWnd, Msg, wParam, lParam);
|
|||
|
|
}
|