2018-04-21 21:24:46 +08:00
|
|
|
|
#include "..\e2dtool.h"
|
|
|
|
|
|
#include "..\e2dmanager.h"
|
2018-04-27 17:07:47 +08:00
|
|
|
|
#include <map>
|
2017-12-08 15:37:52 +08:00
|
|
|
|
|
|
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
#ifndef SAFE_DELETE
|
|
|
|
|
|
#define SAFE_DELETE(p) { if (p) { delete (p); (p)=nullptr; } }
|
|
|
|
|
|
#endif
|
|
|
|
|
|
#ifndef SAFE_DELETE_ARRAY
|
|
|
|
|
|
#define SAFE_DELETE_ARRAY(p) { if (p) { delete[] (p); (p)=nullptr; } }
|
|
|
|
|
|
#endif
|
2017-12-08 15:37:52 +08:00
|
|
|
|
|
2018-02-28 19:17:15 +08:00
|
|
|
|
inline bool TraceError(wchar_t* sPrompt)
|
2018-02-01 22:07:44 +08:00
|
|
|
|
{
|
2018-04-27 17:07:47 +08:00
|
|
|
|
WARN_IF(true, "MusicInfo error: %s failed!", sPrompt);
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2017-12-08 15:37:52 +08:00
|
|
|
|
|
2018-02-28 19:17:15 +08:00
|
|
|
|
inline bool TraceError(wchar_t* sPrompt, HRESULT hr)
|
2018-01-30 16:45:38 +08:00
|
|
|
|
{
|
2018-04-27 17:07:47 +08:00
|
|
|
|
WARN_IF(true, "MusicInfo error: %s (%#X)", sPrompt, hr);
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-04-24 10:35:58 +08:00
|
|
|
|
static IXAudio2 * s_pXAudio2 = nullptr;
|
|
|
|
|
|
static IXAudio2MasteringVoice * s_pMasteringVoice = nullptr;
|
2018-04-27 17:07:47 +08:00
|
|
|
|
static float s_fMusicVolume = 1.0;
|
2018-04-24 10:35:58 +08:00
|
|
|
|
|
|
|
|
|
|
|
2018-04-27 17:07:47 +08:00
|
|
|
|
// <20><><EFBFBD>ֲ<EFBFBD><D6B2><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
class MusicPlayer
|
2018-04-24 10:35:58 +08:00
|
|
|
|
{
|
2018-04-27 17:07:47 +08:00
|
|
|
|
public:
|
|
|
|
|
|
MusicPlayer();
|
2018-04-24 10:35:58 +08:00
|
|
|
|
|
2018-04-27 17:07:47 +08:00
|
|
|
|
virtual ~MusicPlayer();
|
2018-04-24 10:35:58 +08:00
|
|
|
|
|
2018-04-27 17:07:47 +08:00
|
|
|
|
bool open(
|
2018-05-07 15:48:06 +08:00
|
|
|
|
const e2d::String& filePath
|
2018-04-27 17:27:05 +08:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
bool MusicPlayer::open(
|
|
|
|
|
|
int resNameId,
|
|
|
|
|
|
const e2d::String& resType
|
2018-04-27 17:07:47 +08:00
|
|
|
|
);
|
2018-04-24 10:35:58 +08:00
|
|
|
|
|
2018-04-27 17:07:47 +08:00
|
|
|
|
bool play(
|
|
|
|
|
|
int nLoopCount = 0
|
|
|
|
|
|
);
|
2018-04-24 10:35:58 +08:00
|
|
|
|
|
2018-04-27 17:07:47 +08:00
|
|
|
|
void pause();
|
2018-04-24 10:35:58 +08:00
|
|
|
|
|
2018-04-27 17:07:47 +08:00
|
|
|
|
void resume();
|
2018-02-01 22:07:44 +08:00
|
|
|
|
|
2018-04-27 17:07:47 +08:00
|
|
|
|
void stop();
|
|
|
|
|
|
|
|
|
|
|
|
void close();
|
|
|
|
|
|
|
|
|
|
|
|
bool setVolume(
|
|
|
|
|
|
float fVolume
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
bool isPlaying() const;
|
|
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
bool _readMMIO();
|
|
|
|
|
|
|
|
|
|
|
|
bool _resetFile();
|
|
|
|
|
|
|
|
|
|
|
|
bool _read(
|
|
|
|
|
|
BYTE* pBuffer,
|
|
|
|
|
|
DWORD dwSizeToRead
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
bool _findMediaFileCch(
|
|
|
|
|
|
wchar_t* strDestPath,
|
|
|
|
|
|
int cchDest,
|
|
|
|
|
|
const wchar_t * strFilename
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
protected:
|
2018-05-08 17:40:36 +08:00
|
|
|
|
bool _bOpened;
|
|
|
|
|
|
mutable bool _bPlaying;
|
|
|
|
|
|
DWORD _dwSize;
|
|
|
|
|
|
CHAR* _pResourceBuffer;
|
|
|
|
|
|
BYTE* _pbWaveData;
|
|
|
|
|
|
HMMIO _hmmio;
|
|
|
|
|
|
MMCKINFO _ck;
|
|
|
|
|
|
MMCKINFO _ckRiff;
|
|
|
|
|
|
WAVEFORMATEX* _pwfx;
|
|
|
|
|
|
IXAudio2SourceVoice* _pSourceVoice;
|
2018-04-27 17:07:47 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
typedef std::map<UINT, MusicPlayer *> MusicMap;
|
|
|
|
|
|
|
2018-04-27 17:27:05 +08:00
|
|
|
|
static MusicMap& GetMusicFileList()
|
2017-12-08 15:37:52 +08:00
|
|
|
|
{
|
2018-04-27 17:27:05 +08:00
|
|
|
|
static MusicMap s_MusicFileList;
|
|
|
|
|
|
return s_MusicFileList;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static MusicMap& GetMusicResList()
|
|
|
|
|
|
{
|
|
|
|
|
|
static MusicMap s_MusicResList;
|
|
|
|
|
|
return s_MusicResList;
|
2017-12-08 15:37:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-04-27 17:07:47 +08:00
|
|
|
|
MusicPlayer::MusicPlayer()
|
2018-05-08 17:40:36 +08:00
|
|
|
|
: _bOpened(false)
|
|
|
|
|
|
, _bPlaying(false)
|
|
|
|
|
|
, _pwfx(nullptr)
|
|
|
|
|
|
, _hmmio(nullptr)
|
|
|
|
|
|
, _pResourceBuffer(nullptr)
|
|
|
|
|
|
, _pbWaveData(nullptr)
|
|
|
|
|
|
, _dwSize(0)
|
|
|
|
|
|
, _pSourceVoice(nullptr)
|
2018-03-02 23:49:57 +08:00
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-04-27 17:07:47 +08:00
|
|
|
|
MusicPlayer::~MusicPlayer()
|
2017-12-08 15:37:52 +08:00
|
|
|
|
{
|
2018-03-02 23:49:57 +08:00
|
|
|
|
close();
|
2017-12-08 15:37:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-07 15:48:06 +08:00
|
|
|
|
bool MusicPlayer::open(const e2d::String& filePath)
|
2017-12-08 15:37:52 +08:00
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (_bOpened)
|
2018-02-01 22:07:44 +08:00
|
|
|
|
{
|
2018-04-27 17:07:47 +08:00
|
|
|
|
WARN_IF(true, "MusicInfo can be opened only once!");
|
2017-12-08 15:37:52 +08:00
|
|
|
|
return false;
|
2018-02-01 22:07:44 +08:00
|
|
|
|
}
|
2017-12-08 15:37:52 +08:00
|
|
|
|
|
2018-05-07 15:48:06 +08:00
|
|
|
|
if (filePath.isEmpty())
|
2017-12-08 15:37:52 +08:00
|
|
|
|
{
|
2018-04-27 17:07:47 +08:00
|
|
|
|
WARN_IF(true, "MusicInfo::open Invalid file name.");
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return false;
|
2017-12-08 15:37:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-04-24 10:35:58 +08:00
|
|
|
|
if (!s_pXAudio2)
|
2018-02-01 22:07:44 +08:00
|
|
|
|
{
|
2018-04-23 00:05:57 +08:00
|
|
|
|
WARN_IF(true, "IXAudio2 nullptr pointer error!");
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2017-12-08 15:37:52 +08:00
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
// <20><>λ wave <20>ļ<EFBFBD>
|
2018-05-07 15:48:06 +08:00
|
|
|
|
wchar_t pFilePath[MAX_PATH];
|
|
|
|
|
|
if (!_findMediaFileCch(pFilePath, MAX_PATH, filePath))
|
2018-02-01 22:07:44 +08:00
|
|
|
|
{
|
2018-05-07 15:48:06 +08:00
|
|
|
|
WARN_IF(true, "Failed to find media file: %s", pFilePath);
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2017-12-08 15:37:52 +08:00
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
_hmmio = mmioOpen(pFilePath, nullptr, MMIO_ALLOCBUF | MMIO_READ);
|
2017-12-08 15:37:52 +08:00
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (nullptr == _hmmio)
|
2017-12-08 15:37:52 +08:00
|
|
|
|
{
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return TraceError(L"mmioOpen");
|
2017-12-08 15:37:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
if (!_readMMIO())
|
2017-12-08 15:37:52 +08:00
|
|
|
|
{
|
2018-02-01 22:07:44 +08:00
|
|
|
|
// <20><>ȡ<EFBFBD><C8A1> wave <20>ļ<EFBFBD>ʱ ReadMMIO <20><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>
|
2018-05-08 17:40:36 +08:00
|
|
|
|
mmioClose(_hmmio, 0);
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return TraceError(L"_readMMIO");
|
2017-12-08 15:37:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
if (!_resetFile())
|
|
|
|
|
|
return TraceError(L"_resetFile");
|
2017-12-08 15:37:52 +08:00
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>wave <20>ļ<EFBFBD><C4BC>Ĵ<EFBFBD>С<EFBFBD><D0A1> _ck.cksize
|
|
|
|
|
|
_dwSize = _ck.cksize;
|
2017-12-08 15:37:52 +08:00
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݶ<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD>
|
2018-05-08 17:40:36 +08:00
|
|
|
|
_pbWaveData = new BYTE[_dwSize];
|
2018-02-01 22:07:44 +08:00
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (!_read(_pbWaveData, _dwSize))
|
2017-12-08 15:37:52 +08:00
|
|
|
|
{
|
2018-02-01 22:07:44 +08:00
|
|
|
|
TraceError(L"Failed to read WAV data");
|
2018-05-08 17:40:36 +08:00
|
|
|
|
SAFE_DELETE_ARRAY(_pbWaveData);
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return false;
|
2017-12-08 15:37:52 +08:00
|
|
|
|
}
|
2018-02-01 22:07:44 +08:00
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
|
|
|
|
|
|
HRESULT hr;
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (FAILED(hr = s_pXAudio2->CreateSourceVoice(&_pSourceVoice, _pwfx)))
|
2018-02-01 22:07:44 +08:00
|
|
|
|
{
|
2018-04-23 00:05:57 +08:00
|
|
|
|
TraceError(L"Create source voice error", hr);
|
2018-05-08 17:40:36 +08:00
|
|
|
|
SAFE_DELETE_ARRAY(_pbWaveData);
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
_bOpened = true;
|
|
|
|
|
|
_bPlaying = false;
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return true;
|
2017-12-08 15:37:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-04-27 17:27:05 +08:00
|
|
|
|
bool MusicPlayer::open(int resNameId, const e2d::String& resType)
|
|
|
|
|
|
{
|
|
|
|
|
|
HRSRC hResInfo;
|
|
|
|
|
|
HGLOBAL hResData;
|
|
|
|
|
|
DWORD dwSize;
|
|
|
|
|
|
void* pvRes;
|
|
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (_bOpened)
|
2018-04-27 17:27:05 +08:00
|
|
|
|
{
|
|
|
|
|
|
WARN_IF(true, "MusicInfo can be opened only once!");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!s_pXAudio2)
|
|
|
|
|
|
{
|
|
|
|
|
|
WARN_IF(true, "IXAudio2 nullptr pointer error!");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Loading it as a file failed, so try it as a resource
|
|
|
|
|
|
if (nullptr == (hResInfo = FindResourceW(HINST_THISCOMPONENT, MAKEINTRESOURCE(resNameId), resType)))
|
|
|
|
|
|
return TraceError(L"FindResource");
|
|
|
|
|
|
|
|
|
|
|
|
if (nullptr == (hResData = LoadResource(HINST_THISCOMPONENT, hResInfo)))
|
|
|
|
|
|
return TraceError(L"LoadResource");
|
|
|
|
|
|
|
|
|
|
|
|
if (0 == (dwSize = SizeofResource(HINST_THISCOMPONENT, hResInfo)))
|
|
|
|
|
|
return TraceError(L"SizeofResource");
|
|
|
|
|
|
|
|
|
|
|
|
if (nullptr == (pvRes = LockResource(hResData)))
|
|
|
|
|
|
return TraceError(L"LockResource");
|
|
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
_pResourceBuffer = new CHAR[dwSize];
|
|
|
|
|
|
memcpy(_pResourceBuffer, pvRes, dwSize);
|
2018-04-27 17:27:05 +08:00
|
|
|
|
|
|
|
|
|
|
MMIOINFO mmioInfo;
|
|
|
|
|
|
ZeroMemory(&mmioInfo, sizeof(mmioInfo));
|
|
|
|
|
|
mmioInfo.fccIOProc = FOURCC_MEM;
|
|
|
|
|
|
mmioInfo.cchBuffer = dwSize;
|
2018-05-08 17:40:36 +08:00
|
|
|
|
mmioInfo.pchBuffer = (CHAR*)_pResourceBuffer;
|
2018-04-27 17:27:05 +08:00
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
_hmmio = mmioOpen(nullptr, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ);
|
2018-04-27 17:27:05 +08:00
|
|
|
|
|
|
|
|
|
|
if (!_readMMIO())
|
|
|
|
|
|
{
|
|
|
|
|
|
// ReadMMIO will fail if its an not a wave file
|
2018-05-08 17:40:36 +08:00
|
|
|
|
mmioClose(_hmmio, 0);
|
2018-04-27 17:27:05 +08:00
|
|
|
|
return TraceError(L"ReadMMIO");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!_resetFile())
|
|
|
|
|
|
return TraceError(L"ResetFile");
|
|
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
// After the reset, the size of the wav file is _ck.cksize so store it now
|
|
|
|
|
|
_dwSize = _ck.cksize;
|
2018-04-27 17:27:05 +08:00
|
|
|
|
|
|
|
|
|
|
// Read the sample data into memory
|
2018-05-08 17:40:36 +08:00
|
|
|
|
_pbWaveData = new BYTE[_dwSize];
|
2018-04-27 17:27:05 +08:00
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (!_read(_pbWaveData, _dwSize))
|
2018-04-27 17:27:05 +08:00
|
|
|
|
{
|
|
|
|
|
|
TraceError(L"Failed to read WAV data");
|
2018-05-08 17:40:36 +08:00
|
|
|
|
SAFE_DELETE_ARRAY(_pbWaveData);
|
2018-04-27 17:27:05 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
|
|
|
|
|
|
HRESULT hr;
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (FAILED(hr = s_pXAudio2->CreateSourceVoice(&_pSourceVoice, _pwfx)))
|
2018-04-27 17:27:05 +08:00
|
|
|
|
{
|
|
|
|
|
|
TraceError(L"Create source voice error", hr);
|
2018-05-08 17:40:36 +08:00
|
|
|
|
SAFE_DELETE_ARRAY(_pbWaveData);
|
2018-04-27 17:27:05 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
_bOpened = true;
|
|
|
|
|
|
_bPlaying = false;
|
2018-04-27 17:27:05 +08:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-04-27 17:07:47 +08:00
|
|
|
|
bool MusicPlayer::play(int nLoopCount)
|
2017-12-08 15:37:52 +08:00
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (!_bOpened)
|
2018-03-02 23:49:57 +08:00
|
|
|
|
{
|
2018-04-27 17:07:47 +08:00
|
|
|
|
WARN_IF(true, "MusicInfo::play Failed: MusicInfo must be opened first!");
|
2018-03-02 23:49:57 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (_pSourceVoice == nullptr)
|
2018-03-02 23:49:57 +08:00
|
|
|
|
{
|
2018-04-27 17:07:47 +08:00
|
|
|
|
WARN_IF(true, "MusicInfo::play Failed: IXAudio2SourceVoice Null pointer exception!");
|
2018-03-02 23:49:57 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2018-02-01 22:07:44 +08:00
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (_bPlaying)
|
2017-12-08 15:37:52 +08:00
|
|
|
|
{
|
|
|
|
|
|
stop();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-02-06 21:11:54 +08:00
|
|
|
|
nLoopCount = min(nLoopCount, XAUDIO2_LOOP_INFINITE - 1);
|
|
|
|
|
|
nLoopCount = (nLoopCount < 0) ? XAUDIO2_LOOP_INFINITE : nLoopCount;
|
|
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
// <20>ύ wave <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
XAUDIO2_BUFFER buffer = { 0 };
|
2018-05-08 17:40:36 +08:00
|
|
|
|
buffer.pAudioData = _pbWaveData;
|
2018-02-01 22:07:44 +08:00
|
|
|
|
buffer.Flags = XAUDIO2_END_OF_STREAM;
|
2018-05-08 17:40:36 +08:00
|
|
|
|
buffer.AudioBytes = _dwSize;
|
2018-02-01 22:07:44 +08:00
|
|
|
|
buffer.LoopCount = nLoopCount;
|
|
|
|
|
|
|
2018-03-02 23:49:57 +08:00
|
|
|
|
HRESULT hr;
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (FAILED(hr = _pSourceVoice->SubmitSourceBuffer(&buffer)))
|
2017-12-08 15:37:52 +08:00
|
|
|
|
{
|
2018-04-23 00:05:57 +08:00
|
|
|
|
TraceError(L"Submitting source buffer error", hr);
|
2018-05-08 17:40:36 +08:00
|
|
|
|
_pSourceVoice->DestroyVoice();
|
|
|
|
|
|
SAFE_DELETE_ARRAY(_pbWaveData);
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return false;
|
2017-12-08 15:37:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (SUCCEEDED(hr = _pSourceVoice->Start(0)))
|
2018-02-01 22:07:44 +08:00
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
_bPlaying = true;
|
2018-02-01 22:07:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return SUCCEEDED(hr);
|
2017-12-08 15:37:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-04-27 17:07:47 +08:00
|
|
|
|
void MusicPlayer::pause()
|
2017-12-08 15:37:52 +08:00
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (_pSourceVoice)
|
2018-02-01 22:07:44 +08:00
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (SUCCEEDED(_pSourceVoice->Stop()))
|
2018-02-01 22:07:44 +08:00
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
_bPlaying = false;
|
2018-02-01 22:07:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2017-12-08 15:37:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-04-27 17:07:47 +08:00
|
|
|
|
void MusicPlayer::resume()
|
2017-12-08 15:37:52 +08:00
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (_pSourceVoice)
|
2018-02-01 22:07:44 +08:00
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (SUCCEEDED(_pSourceVoice->Start()))
|
2018-02-01 22:07:44 +08:00
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
_bPlaying = true;
|
2018-02-01 22:07:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2017-12-08 15:37:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-04-27 17:07:47 +08:00
|
|
|
|
void MusicPlayer::stop()
|
2017-12-08 15:37:52 +08:00
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (_pSourceVoice)
|
2018-02-01 22:07:44 +08:00
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (SUCCEEDED(_pSourceVoice->Stop()))
|
2018-02-01 22:07:44 +08:00
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
_pSourceVoice->ExitLoop();
|
|
|
|
|
|
_pSourceVoice->FlushSourceBuffers();
|
|
|
|
|
|
_bPlaying = false;
|
2018-02-01 22:07:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2017-12-08 15:37:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-04-27 17:07:47 +08:00
|
|
|
|
void MusicPlayer::close()
|
2017-12-08 15:37:52 +08:00
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (_pSourceVoice)
|
2018-03-02 23:49:57 +08:00
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
_pSourceVoice->Stop();
|
|
|
|
|
|
_pSourceVoice->FlushSourceBuffers();
|
|
|
|
|
|
_pSourceVoice->DestroyVoice();
|
|
|
|
|
|
_pSourceVoice = nullptr;
|
2018-03-02 23:49:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (_hmmio != nullptr)
|
2018-03-02 23:49:57 +08:00
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
mmioClose(_hmmio, 0);
|
|
|
|
|
|
_hmmio = nullptr;
|
2018-03-02 23:49:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
SAFE_DELETE_ARRAY(_pResourceBuffer);
|
|
|
|
|
|
SAFE_DELETE_ARRAY(_pbWaveData);
|
|
|
|
|
|
SAFE_DELETE_ARRAY(_pwfx);
|
2018-03-02 23:49:57 +08:00
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
_bOpened = false;
|
|
|
|
|
|
_bPlaying = false;
|
2018-03-02 23:49:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-04-27 17:07:47 +08:00
|
|
|
|
bool MusicPlayer::isPlaying() const
|
2018-03-02 23:49:57 +08:00
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (_bOpened && _pSourceVoice)
|
2017-12-08 15:37:52 +08:00
|
|
|
|
{
|
2018-02-01 22:07:44 +08:00
|
|
|
|
XAUDIO2_VOICE_STATE state;
|
2018-05-08 17:40:36 +08:00
|
|
|
|
_pSourceVoice->GetState(&state);
|
2017-12-08 15:37:52 +08:00
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
if (state.BuffersQueued == 0)
|
|
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
_bPlaying = false;
|
2018-02-01 22:07:44 +08:00
|
|
|
|
}
|
2018-05-08 17:40:36 +08:00
|
|
|
|
return _bPlaying;
|
2018-02-01 22:07:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2017-12-08 15:37:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-04-27 17:07:47 +08:00
|
|
|
|
bool MusicPlayer::setVolume(float fVolume)
|
2017-12-08 15:37:52 +08:00
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (_pSourceVoice)
|
2018-02-01 22:07:44 +08:00
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
return SUCCEEDED(_pSourceVoice->SetVolume(fVolume));
|
2018-02-01 22:07:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
return false;
|
2017-12-08 15:37:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-04-27 17:07:47 +08:00
|
|
|
|
bool MusicPlayer::_readMMIO()
|
2018-02-01 22:07:44 +08:00
|
|
|
|
{
|
|
|
|
|
|
MMCKINFO ckIn;
|
|
|
|
|
|
PCMWAVEFORMAT pcmWaveFormat;
|
2018-01-30 16:45:38 +08:00
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
memset(&ckIn, 0, sizeof(ckIn));
|
2018-01-30 16:45:38 +08:00
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
_pwfx = nullptr;
|
2018-01-30 16:45:38 +08:00
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if ((0 != mmioDescend(_hmmio, &_ckRiff, nullptr, 0)))
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return TraceError(L"mmioDescend");
|
2018-01-30 16:45:38 +08:00
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
// ȷ<><C8B7><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD> wave <20>ļ<EFBFBD>
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if ((_ckRiff.ckid != FOURCC_RIFF) ||
|
|
|
|
|
|
(_ckRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E')))
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return TraceError(L"mmioFOURCC");
|
2018-01-30 16:45:38 +08:00
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC>в<EFBFBD><D0B2><EFBFBD> 'fmt' <20><>
|
|
|
|
|
|
ckIn.ckid = mmioFOURCC('f', 'm', 't', ' ');
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (0 != mmioDescend(_hmmio, &ckIn, &_ckRiff, MMIO_FINDCHUNK))
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return TraceError(L"mmioDescend");
|
2018-01-30 16:45:38 +08:00
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
// 'fmt' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6> PCMWAVEFORMAT һ<><D2BB><EFBFBD><EFBFBD>
|
|
|
|
|
|
if (ckIn.cksize < (LONG)sizeof(PCMWAVEFORMAT))
|
|
|
|
|
|
return TraceError(L"sizeof(PCMWAVEFORMAT)");
|
|
|
|
|
|
|
|
|
|
|
|
// <20><> 'fmt' <20><><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1> pcmWaveFormat <20><>
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (mmioRead(_hmmio, (HPSTR)&pcmWaveFormat,
|
2018-02-01 22:07:44 +08:00
|
|
|
|
sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat))
|
|
|
|
|
|
return TraceError(L"mmioRead");
|
2018-01-30 16:45:38 +08:00
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
// <20><><EFBFBD><EFBFBD> WAVEFORMATEX<45><58><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> PCM <20><>ʽ<EFBFBD><CABD><EFBFBD>ٶ<EFBFBD>ȡһ<C8A1><D2BB> WORD <20><>С
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݾ<EFBFBD><DDBE>Ƕ<EFBFBD><C7B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD>С
|
|
|
|
|
|
if (pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM)
|
2018-01-30 16:45:38 +08:00
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
_pwfx = (WAVEFORMATEX*)new CHAR[sizeof(WAVEFORMATEX)];
|
2018-02-01 22:07:44 +08:00
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
2018-05-08 17:40:36 +08:00
|
|
|
|
memcpy(_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat));
|
|
|
|
|
|
_pwfx->cbSize = 0;
|
2018-01-30 16:45:38 +08:00
|
|
|
|
}
|
2018-02-01 22:07:44 +08:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵĴ<DDB5>С
|
|
|
|
|
|
WORD cbExtraBytes = 0L;
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (mmioRead(_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD))
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return TraceError(L"mmioRead");
|
2018-01-30 16:45:38 +08:00
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
_pwfx = (WAVEFORMATEX*)new CHAR[sizeof(WAVEFORMATEX) + cbExtraBytes];
|
2018-02-01 22:07:44 +08:00
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
2018-05-08 17:40:36 +08:00
|
|
|
|
memcpy(_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat));
|
|
|
|
|
|
_pwfx->cbSize = cbExtraBytes;
|
2018-01-30 16:45:38 +08:00
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (mmioRead(_hmmio, (CHAR*)(((BYTE*)&(_pwfx->cbSize)) + sizeof(WORD)),
|
2018-02-01 22:07:44 +08:00
|
|
|
|
cbExtraBytes) != cbExtraBytes)
|
|
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
SAFE_DELETE(_pwfx);
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return TraceError(L"mmioRead");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (0 != mmioAscend(_hmmio, &ckIn, 0))
|
2018-01-30 16:45:38 +08:00
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
SAFE_DELETE(_pwfx);
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return TraceError(L"mmioAscend");
|
2018-01-30 16:45:38 +08:00
|
|
|
|
}
|
2018-02-01 22:07:44 +08:00
|
|
|
|
|
|
|
|
|
|
return true;
|
2018-01-30 16:45:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-04-27 17:07:47 +08:00
|
|
|
|
bool MusicPlayer::_resetFile()
|
2018-01-30 16:45:38 +08:00
|
|
|
|
{
|
2018-02-01 22:07:44 +08:00
|
|
|
|
// Seek to the data
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (-1 == mmioSeek(_hmmio, _ckRiff.dwDataOffset + sizeof(FOURCC),
|
2018-02-01 22:07:44 +08:00
|
|
|
|
SEEK_SET))
|
|
|
|
|
|
return TraceError(L"mmioSeek");
|
2018-01-30 16:45:38 +08:00
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
// Search the input file for the 'data' chunk.
|
2018-05-08 17:40:36 +08:00
|
|
|
|
_ck.ckid = mmioFOURCC('d', 'a', 't', 'a');
|
|
|
|
|
|
if (0 != mmioDescend(_hmmio, &_ck, &_ckRiff, MMIO_FINDCHUNK))
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return TraceError(L"mmioDescend");
|
2018-01-30 16:45:38 +08:00
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return true;
|
2018-01-30 16:45:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-04-27 17:07:47 +08:00
|
|
|
|
bool MusicPlayer::_read(BYTE* pBuffer, DWORD dwSizeToRead)
|
2018-01-30 16:45:38 +08:00
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
MMIOINFO mmioinfoIn; // current status of _hmmio
|
2018-01-30 16:45:38 +08:00
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (0 != mmioGetInfo(_hmmio, &mmioinfoIn, 0))
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return TraceError(L"mmioGetInfo");
|
2018-01-30 16:45:38 +08:00
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
UINT cbDataIn = dwSizeToRead;
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (cbDataIn > _ck.cksize)
|
|
|
|
|
|
cbDataIn = _ck.cksize;
|
2018-01-30 16:45:38 +08:00
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
_ck.cksize -= cbDataIn;
|
2018-01-30 16:45:38 +08:00
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
for (DWORD cT = 0; cT < cbDataIn; cT++)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Copy the bytes from the io to the buffer.
|
|
|
|
|
|
if (mmioinfoIn.pchNext == mmioinfoIn.pchEndRead)
|
|
|
|
|
|
{
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (0 != mmioAdvance(_hmmio, &mmioinfoIn, MMIO_READ))
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return TraceError(L"mmioAdvance");
|
2018-01-30 16:45:38 +08:00
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
if (mmioinfoIn.pchNext == mmioinfoIn.pchEndRead)
|
|
|
|
|
|
return TraceError(L"mmioinfoIn.pchNext");
|
|
|
|
|
|
}
|
2018-01-30 16:45:38 +08:00
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
// Actual copy.
|
|
|
|
|
|
*((BYTE*)pBuffer + cT) = *((BYTE*)mmioinfoIn.pchNext);
|
|
|
|
|
|
mmioinfoIn.pchNext++;
|
2018-01-30 16:45:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-08 17:40:36 +08:00
|
|
|
|
if (0 != mmioSetInfo(_hmmio, &mmioinfoIn, 0))
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return TraceError(L"mmioSetInfo");
|
2018-01-30 16:45:38 +08:00
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return true;
|
2018-01-30 16:45:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-04-27 17:07:47 +08:00
|
|
|
|
bool MusicPlayer::_findMediaFileCch(wchar_t* strDestPath, int cchDest, const wchar_t * strFilename)
|
2018-01-30 16:45:38 +08:00
|
|
|
|
{
|
2018-02-01 22:07:44 +08:00
|
|
|
|
bool bFound = false;
|
2018-01-30 16:45:38 +08:00
|
|
|
|
|
2018-03-02 23:49:57 +08:00
|
|
|
|
if (nullptr == strFilename || nullptr == strDestPath || cchDest < 10)
|
2018-02-01 22:07:44 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
// Get the exe name, and exe path
|
2018-02-28 19:17:15 +08:00
|
|
|
|
wchar_t strExePath[MAX_PATH] = { 0 };
|
|
|
|
|
|
wchar_t strExeName[MAX_PATH] = { 0 };
|
|
|
|
|
|
wchar_t* strLastSlash = nullptr;
|
2018-02-01 22:07:44 +08:00
|
|
|
|
GetModuleFileName(HINST_THISCOMPONENT, strExePath, MAX_PATH);
|
|
|
|
|
|
strExePath[MAX_PATH - 1] = 0;
|
|
|
|
|
|
strLastSlash = wcsrchr(strExePath, TEXT('\\'));
|
|
|
|
|
|
if (strLastSlash)
|
2018-01-30 16:45:38 +08:00
|
|
|
|
{
|
2018-02-01 22:07:44 +08:00
|
|
|
|
wcscpy_s(strExeName, MAX_PATH, &strLastSlash[1]);
|
2018-01-30 16:45:38 +08:00
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
// Chop the exe name from the exe path
|
|
|
|
|
|
*strLastSlash = 0;
|
2018-01-30 16:45:38 +08:00
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
// Chop the .exe from the exe name
|
|
|
|
|
|
strLastSlash = wcsrchr(strExeName, TEXT('.'));
|
|
|
|
|
|
if (strLastSlash)
|
|
|
|
|
|
*strLastSlash = 0;
|
2018-01-30 16:45:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
wcscpy_s(strDestPath, cchDest, strFilename);
|
|
|
|
|
|
if (GetFileAttributes(strDestPath) != 0xFFFFFFFF)
|
|
|
|
|
|
return true;
|
2018-01-30 16:45:38 +08:00
|
|
|
|
|
2018-02-01 22:07:44 +08:00
|
|
|
|
// Search all parent directories starting at .\ and using strFilename as the leaf name
|
2018-02-28 19:17:15 +08:00
|
|
|
|
wchar_t strLeafName[MAX_PATH] = { 0 };
|
2018-02-01 22:07:44 +08:00
|
|
|
|
wcscpy_s(strLeafName, MAX_PATH, strFilename);
|
|
|
|
|
|
|
2018-02-28 19:17:15 +08:00
|
|
|
|
wchar_t strFullPath[MAX_PATH] = { 0 };
|
|
|
|
|
|
wchar_t strFullFileName[MAX_PATH] = { 0 };
|
|
|
|
|
|
wchar_t strSearch[MAX_PATH] = { 0 };
|
|
|
|
|
|
wchar_t* strFilePart = nullptr;
|
2018-02-01 22:07:44 +08:00
|
|
|
|
|
|
|
|
|
|
GetFullPathName(L".", MAX_PATH, strFullPath, &strFilePart);
|
|
|
|
|
|
if (strFilePart == nullptr)
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
while (strFilePart != nullptr && *strFilePart != '\0')
|
2018-01-30 16:45:38 +08:00
|
|
|
|
{
|
2018-02-01 22:07:44 +08:00
|
|
|
|
swprintf_s(strFullFileName, MAX_PATH, L"%s\\%s", strFullPath, strLeafName);
|
|
|
|
|
|
if (GetFileAttributes(strFullFileName) != 0xFFFFFFFF)
|
|
|
|
|
|
{
|
|
|
|
|
|
wcscpy_s(strDestPath, cchDest, strFullFileName);
|
|
|
|
|
|
bFound = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
swprintf_s(strFullFileName, MAX_PATH, L"%s\\%s\\%s", strFullPath, strExeName, strLeafName);
|
|
|
|
|
|
if (GetFileAttributes(strFullFileName) != 0xFFFFFFFF)
|
|
|
|
|
|
{
|
|
|
|
|
|
wcscpy_s(strDestPath, cchDest, strFullFileName);
|
|
|
|
|
|
bFound = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
swprintf_s(strSearch, MAX_PATH, L"%s\\..", strFullPath);
|
|
|
|
|
|
GetFullPathName(strSearch, MAX_PATH, strFullPath, &strFilePart);
|
2018-01-30 16:45:38 +08:00
|
|
|
|
}
|
2018-02-01 22:07:44 +08:00
|
|
|
|
if (bFound)
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
|
|
// ʧ<><CAA7>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>Ϊ·<CEAA><C2B7><EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD>ͬʱҲ<CAB1><D2B2><EFBFBD>ش<EFBFBD><D8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
wcscpy_s(strDestPath, cchDest, strFilename);
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
2018-01-30 16:45:38 +08:00
|
|
|
|
}
|
2018-04-01 23:08:11 +08:00
|
|
|
|
|
|
|
|
|
|
|
2018-05-07 15:48:06 +08:00
|
|
|
|
bool e2d::Music::preload(const String& filePath)
|
2018-04-27 17:07:47 +08:00
|
|
|
|
{
|
2018-05-07 15:48:06 +08:00
|
|
|
|
UINT nRet = filePath.getHashCode();
|
2018-04-27 17:07:47 +08:00
|
|
|
|
|
2018-04-27 17:27:05 +08:00
|
|
|
|
if (GetMusicFileList().end() != GetMusicFileList().find(nRet))
|
2018-04-27 17:07:47 +08:00
|
|
|
|
{
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
MusicPlayer * pPlayer = new (std::nothrow) MusicPlayer();
|
|
|
|
|
|
|
2018-05-07 15:48:06 +08:00
|
|
|
|
if (pPlayer->open(filePath))
|
2018-04-27 17:07:47 +08:00
|
|
|
|
{
|
|
|
|
|
|
pPlayer->setVolume(s_fMusicVolume);
|
2018-04-27 17:27:05 +08:00
|
|
|
|
GetMusicFileList().insert(std::pair<UINT, MusicPlayer *>(nRet, pPlayer));
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
delete pPlayer;
|
|
|
|
|
|
pPlayer = nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-07 15:48:06 +08:00
|
|
|
|
bool e2d::Music::preload(int resNameId, const String& resType)
|
2018-04-27 17:27:05 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (GetMusicResList().end() != GetMusicResList().find(resNameId))
|
|
|
|
|
|
{
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
MusicPlayer * pPlayer = new (std::nothrow) MusicPlayer();
|
|
|
|
|
|
|
|
|
|
|
|
if (pPlayer->open(resNameId, resType))
|
|
|
|
|
|
{
|
|
|
|
|
|
pPlayer->setVolume(s_fMusicVolume);
|
|
|
|
|
|
GetMusicResList().insert(std::pair<UINT, MusicPlayer *>(resNameId, pPlayer));
|
2018-04-27 17:07:47 +08:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
delete pPlayer;
|
|
|
|
|
|
pPlayer = nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-07 15:48:06 +08:00
|
|
|
|
bool e2d::Music::play(const String& filePath, int nLoopCount)
|
2018-04-27 17:07:47 +08:00
|
|
|
|
{
|
2018-05-07 15:48:06 +08:00
|
|
|
|
if (Music::preload(filePath))
|
2018-04-27 17:07:47 +08:00
|
|
|
|
{
|
2018-05-07 15:48:06 +08:00
|
|
|
|
UINT nRet = filePath.getHashCode();
|
2018-04-27 17:27:05 +08:00
|
|
|
|
auto pMusic = GetMusicFileList()[nRet];
|
|
|
|
|
|
if (pMusic->play(nLoopCount))
|
|
|
|
|
|
{
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-07 15:48:06 +08:00
|
|
|
|
bool e2d::Music::play(int resNameId, const String& resType, int nLoopCount)
|
2018-04-27 17:27:05 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (Music::preload(resNameId, resType))
|
|
|
|
|
|
{
|
|
|
|
|
|
auto pMusic = GetMusicResList()[resNameId];
|
2018-04-27 17:07:47 +08:00
|
|
|
|
if (pMusic->play(nLoopCount))
|
|
|
|
|
|
{
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-07 15:48:06 +08:00
|
|
|
|
void e2d::Music::pause(const String& filePath)
|
2018-04-27 17:07:47 +08:00
|
|
|
|
{
|
2018-05-07 15:48:06 +08:00
|
|
|
|
if (filePath.isEmpty())
|
2018-04-27 17:07:47 +08:00
|
|
|
|
return;
|
|
|
|
|
|
|
2018-05-07 15:48:06 +08:00
|
|
|
|
UINT nRet = filePath.getHashCode();
|
2018-04-27 17:07:47 +08:00
|
|
|
|
|
2018-04-27 17:27:05 +08:00
|
|
|
|
if (GetMusicFileList().end() != GetMusicFileList().find(nRet))
|
|
|
|
|
|
GetMusicFileList()[nRet]->pause();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-07 15:48:06 +08:00
|
|
|
|
void e2d::Music::pause(int resNameId, const String& resType)
|
2018-04-27 17:27:05 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (GetMusicResList().end() != GetMusicResList().find(resNameId))
|
|
|
|
|
|
GetMusicResList()[resNameId]->pause();
|
2018-04-27 17:07:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-07 15:48:06 +08:00
|
|
|
|
void e2d::Music::resume(const String& filePath)
|
2018-04-27 17:07:47 +08:00
|
|
|
|
{
|
2018-05-07 15:48:06 +08:00
|
|
|
|
if (filePath.isEmpty())
|
2018-04-27 17:07:47 +08:00
|
|
|
|
return;
|
|
|
|
|
|
|
2018-05-07 15:48:06 +08:00
|
|
|
|
UINT nRet = filePath.getHashCode();
|
2018-04-27 17:07:47 +08:00
|
|
|
|
|
2018-04-27 17:27:05 +08:00
|
|
|
|
if (GetMusicFileList().end() != GetMusicFileList().find(nRet))
|
|
|
|
|
|
GetMusicFileList()[nRet]->resume();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-07 15:48:06 +08:00
|
|
|
|
void e2d::Music::resume(int resNameId, const String& resType)
|
2018-04-27 17:27:05 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (GetMusicResList().end() != GetMusicResList().find(resNameId))
|
|
|
|
|
|
GetMusicResList()[resNameId]->pause();
|
2018-04-27 17:07:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-07 15:48:06 +08:00
|
|
|
|
void e2d::Music::stop(const String& filePath)
|
2018-04-27 17:07:47 +08:00
|
|
|
|
{
|
2018-05-07 15:48:06 +08:00
|
|
|
|
if (filePath.isEmpty())
|
2018-04-27 17:07:47 +08:00
|
|
|
|
return;
|
|
|
|
|
|
|
2018-05-07 15:48:06 +08:00
|
|
|
|
UINT nRet = filePath.getHashCode();
|
2018-04-27 17:07:47 +08:00
|
|
|
|
|
2018-04-27 17:27:05 +08:00
|
|
|
|
if (GetMusicFileList().end() != GetMusicFileList().find(nRet))
|
|
|
|
|
|
GetMusicFileList()[nRet]->stop();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-07 15:48:06 +08:00
|
|
|
|
void e2d::Music::stop(int resNameId, const String& resType)
|
2018-04-27 17:27:05 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (GetMusicResList().end() != GetMusicResList().find(resNameId))
|
|
|
|
|
|
GetMusicResList()[resNameId]->stop();
|
2018-04-27 17:07:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-07 15:48:06 +08:00
|
|
|
|
bool e2d::Music::isPlaying(const String& filePath)
|
2018-04-27 17:07:47 +08:00
|
|
|
|
{
|
2018-05-07 15:48:06 +08:00
|
|
|
|
if (filePath.isEmpty())
|
2018-04-27 17:07:47 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
|
2018-05-07 15:48:06 +08:00
|
|
|
|
UINT nRet = filePath.getHashCode();
|
2018-04-27 17:07:47 +08:00
|
|
|
|
|
2018-04-27 17:27:05 +08:00
|
|
|
|
if (GetMusicFileList().end() != GetMusicFileList().find(nRet))
|
|
|
|
|
|
return GetMusicFileList()[nRet]->isPlaying();
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2018-04-27 17:07:47 +08:00
|
|
|
|
|
2018-05-07 15:48:06 +08:00
|
|
|
|
bool e2d::Music::isPlaying(int resNameId, const String& resType)
|
2018-04-27 17:27:05 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (GetMusicResList().end() != GetMusicResList().find(resNameId))
|
|
|
|
|
|
return GetMusicResList()[resNameId]->isPlaying();
|
2018-04-27 17:07:47 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double e2d::Music::getVolume()
|
|
|
|
|
|
{
|
|
|
|
|
|
return s_fMusicVolume;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void e2d::Music::setVolume(double fVolume)
|
|
|
|
|
|
{
|
|
|
|
|
|
s_fMusicVolume = min(max(static_cast<float>(fVolume), -224), 224);
|
2018-04-27 17:27:05 +08:00
|
|
|
|
for (auto pair : GetMusicFileList())
|
2018-04-27 17:07:47 +08:00
|
|
|
|
{
|
|
|
|
|
|
pair.second->setVolume(s_fMusicVolume);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void e2d::Music::pauseAll()
|
|
|
|
|
|
{
|
2018-04-27 17:27:05 +08:00
|
|
|
|
for (auto pair : GetMusicFileList())
|
2018-04-27 17:07:47 +08:00
|
|
|
|
{
|
|
|
|
|
|
pair.second->pause();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void e2d::Music::resumeAll()
|
|
|
|
|
|
{
|
2018-04-27 17:27:05 +08:00
|
|
|
|
for (auto pair : GetMusicFileList())
|
2018-04-27 17:07:47 +08:00
|
|
|
|
{
|
|
|
|
|
|
pair.second->resume();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void e2d::Music::stopAll()
|
|
|
|
|
|
{
|
2018-04-27 17:27:05 +08:00
|
|
|
|
for (auto pair : GetMusicFileList())
|
2018-04-27 17:07:47 +08:00
|
|
|
|
{
|
|
|
|
|
|
pair.second->stop();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
IXAudio2 * e2d::Music::getIXAudio2()
|
|
|
|
|
|
{
|
|
|
|
|
|
return s_pXAudio2;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
IXAudio2MasteringVoice * e2d::Music::getIXAudio2MasteringVoice()
|
|
|
|
|
|
{
|
|
|
|
|
|
return s_pMasteringVoice;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool e2d::Music::__init()
|
|
|
|
|
|
{
|
|
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
|
|
|
|
if (FAILED(hr = XAudio2Create(&s_pXAudio2, 0)))
|
|
|
|
|
|
{
|
|
|
|
|
|
WARN_IF(true, "Failed to init XAudio2 engine");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (FAILED(hr = s_pXAudio2->CreateMasteringVoice(&s_pMasteringVoice)))
|
|
|
|
|
|
{
|
|
|
|
|
|
WARN_IF(true, "Failed creating mastering voice");
|
|
|
|
|
|
e2d::SafeReleaseInterface(&s_pXAudio2);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void e2d::Music::__uninit()
|
|
|
|
|
|
{
|
2018-04-27 17:27:05 +08:00
|
|
|
|
for (auto pair : GetMusicFileList())
|
2018-04-27 17:07:47 +08:00
|
|
|
|
{
|
|
|
|
|
|
pair.second->close();
|
|
|
|
|
|
delete pair.second;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-04-27 17:27:05 +08:00
|
|
|
|
GetMusicFileList().clear();
|
2018-04-27 17:07:47 +08:00
|
|
|
|
|
|
|
|
|
|
if (s_pMasteringVoice)
|
|
|
|
|
|
{
|
|
|
|
|
|
s_pMasteringVoice->DestroyVoice();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
e2d::SafeReleaseInterface(&s_pXAudio2);
|
|
|
|
|
|
}
|