Magic_Game/core/Tool/Music.cpp

619 lines
12 KiB
C++
Raw Normal View History

2018-04-21 21:24:46 +08:00
#include "..\e2dtool.h"
2018-02-01 22:07:44 +08:00
#ifndef SAFE_DELETE
#define SAFE_DELETE(p) { if (p) { delete (p); (p)=nullptr; } }
2018-02-01 22:07:44 +08:00
#endif
2018-02-01 22:07:44 +08:00
#ifndef SAFE_DELETE_ARRAY
#define SAFE_DELETE_ARRAY(p) { if (p) { delete[] (p); (p)=nullptr; } }
2018-02-01 22:07:44 +08:00
#endif
2018-02-28 19:17:15 +08:00
inline bool TraceError(wchar_t* sPrompt)
2018-02-01 22:07:44 +08:00
{
2018-05-24 12:24:39 +08:00
WARN("MusicInfo error: %s failed!", sPrompt);
2018-02-01 22:07:44 +08:00
return false;
}
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-05-24 12:24:39 +08:00
WARN("MusicInfo error: %s (%#X)", sPrompt, hr);
2018-02-01 22:07:44 +08:00
return false;
}
2018-05-17 23:53:27 +08:00
e2d::Music::XAudio2Tool::XAudio2Tool()
{
CoInitialize(nullptr);
ThrowIfFailed(
XAudio2Create(&_xAudio2, 0)
);
ThrowIfFailed(
_xAudio2->CreateMasteringVoice(&_masteringVoice)
);
}
e2d::Music::XAudio2Tool::~XAudio2Tool()
{
_masteringVoice->DestroyVoice();
_xAudio2->Release();
CoUninitialize();
}
e2d::Music::XAudio2Tool* e2d::Music::XAudio2Tool::instance()
{
static XAudio2Tool instance;
return &instance;
}
IXAudio2 * e2d::Music::XAudio2Tool::xAudio2()
{
return _xAudio2;
}
IXAudio2MasteringVoice * e2d::Music::XAudio2Tool::masteringVoice()
{
return _masteringVoice;
}
2018-05-17 23:53:27 +08:00
e2d::Music::Music()
: _opened(false)
, _playing(false)
, _wfx(nullptr)
, _hmmio(nullptr)
, _resBuffer(nullptr)
, _waveData(nullptr)
, _dwSize(0)
, _voice(nullptr)
, _voiceCallback(this)
, _volume(1.f)
{
auto xAudio2 = XAudio2Tool::instance()->xAudio2();
xAudio2->AddRef();
2018-05-17 23:53:27 +08:00
}
2018-04-27 17:07:47 +08:00
e2d::Music::Music(const e2d::String & filePath)
2018-05-17 23:53:27 +08:00
: _opened(false)
, _playing(false)
, _wfx(nullptr)
, _hmmio(nullptr)
, _resBuffer(nullptr)
, _waveData(nullptr)
, _dwSize(0)
, _voice(nullptr)
, _voiceCallback(this)
, _volume(1.f)
2018-05-17 23:53:27 +08:00
{
auto xAudio2 = XAudio2Tool::instance()->xAudio2();
xAudio2->AddRef();
2018-08-12 12:06:06 +08:00
this->open(filePath);
2018-05-17 23:53:27 +08:00
}
2018-04-27 17:07:47 +08:00
e2d::Music::Music(const Resource& res)
2018-05-17 23:53:27 +08:00
: _opened(false)
, _playing(false)
, _wfx(nullptr)
, _hmmio(nullptr)
, _resBuffer(nullptr)
, _waveData(nullptr)
, _dwSize(0)
, _voice(nullptr)
, _voiceCallback(this)
, _volume(1.f)
2018-05-17 23:53:27 +08:00
{
auto xAudio2 = XAudio2Tool::instance()->xAudio2();
xAudio2->AddRef();
2018-08-12 12:06:06 +08:00
this->open(res);
2018-05-17 23:53:27 +08:00
}
2018-04-27 17:07:47 +08:00
2018-05-17 23:53:27 +08:00
e2d::Music::~Music()
{
2018-05-17 23:53:27 +08:00
close();
auto xAudio2 = XAudio2Tool::instance()->xAudio2();
xAudio2->Release();
}
bool e2d::Music::open(const e2d::String & filePath)
{
2018-05-17 23:53:27 +08:00
if (_opened)
2018-02-01 22:07:44 +08:00
{
2018-08-12 12:06:06 +08:00
close();
}
if (filePath.empty())
2018-08-12 12:06:06 +08:00
{
WARN("MusicInfo::open Invalid file name.");
return false;
2018-02-01 22:07:44 +08:00
}
String actualFilePath = File(filePath).path();
if (actualFilePath.empty())
{
WARN("MusicInfo::open File not found.");
return false;
}
// <20><>λ wave <20>ļ<EFBFBD>
wchar_t pFilePath[MAX_PATH];
if (!_findMediaFileCch(pFilePath, MAX_PATH, (const wchar_t *)actualFilePath))
{
WARN("Failed to find media file: %s", pFilePath);
return false;
}
2018-05-24 15:47:38 +08:00
_hmmio = mmioOpen(pFilePath, nullptr, MMIO_ALLOCBUF | MMIO_READ);
if (nullptr == _hmmio)
{
return TraceError(L"mmioOpen");
}
if (!_readMMIO())
{
// <20><>ȡ<EFBFBD><C8A1> wave <20>ļ<EFBFBD>ʱ ReadMMIO <20><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>
mmioClose(_hmmio, 0);
return TraceError(L"ReadMMIO");
}
if (!_resetFile())
return TraceError(L"ResetFile");
// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>wave <20>ļ<EFBFBD><C4BC>Ĵ<EFBFBD>С<EFBFBD><D0A1> _ck.cksize
_dwSize = _ck.cksize;
2018-02-01 22:07:44 +08:00
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݶ<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD>
_waveData = new BYTE[_dwSize];
if (!_read(_waveData, _dwSize))
{
TraceError(L"Failed to read WAV data");
SAFE_DELETE_ARRAY(_waveData);
return false;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
auto xAudio2 = XAudio2Tool::instance()->xAudio2();
HRESULT hr = xAudio2->CreateSourceVoice(&_voice, _wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO, &_voiceCallback);
if (FAILED(hr))
2018-02-01 22:07:44 +08:00
{
TraceError(L"Create source voice error", hr);
SAFE_DELETE_ARRAY(_waveData);
return false;
}
_opened = true;
_playing = false;
return true;
}
bool e2d::Music::open(const Resource& res)
{
if (_opened)
{
close();
2018-02-01 22:07:44 +08:00
}
HRSRC hResInfo;
HGLOBAL hResData;
DWORD dwSize;
void* pvRes;
if (nullptr == (hResInfo = FindResourceW(HINST_THISCOMPONENT, MAKEINTRESOURCE(res.resNameId), (LPCWSTR)res.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");
_resBuffer = new CHAR[dwSize];
memcpy(_resBuffer, pvRes, dwSize);
MMIOINFO mmioInfo;
ZeroMemory(&mmioInfo, sizeof(mmioInfo));
mmioInfo.fccIOProc = FOURCC_MEM;
mmioInfo.cchBuffer = dwSize;
mmioInfo.pchBuffer = (CHAR*)_resBuffer;
_hmmio = mmioOpen(nullptr, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ);
if (nullptr == _hmmio)
{
return TraceError(L"mmioOpen");
}
if (!_readMMIO())
{
2018-05-17 23:53:27 +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);
return TraceError(L"ReadMMIO");
}
if (!_resetFile())
return TraceError(L"ResetFile");
2018-05-17 23:53:27 +08:00
// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>wave <20>ļ<EFBFBD><C4BC>Ĵ<EFBFBD>С<EFBFBD><D0A1> _ck.cksize
2018-05-08 17:40:36 +08:00
_dwSize = _ck.cksize;
2018-05-17 23:53:27 +08:00
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݶ<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD>
_waveData = new BYTE[_dwSize];
2018-05-17 23:53:27 +08:00
if (!_read(_waveData, _dwSize))
{
TraceError(L"Failed to read WAV data");
2018-05-17 23:53:27 +08:00
SAFE_DELETE_ARRAY(_waveData);
return false;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
auto xAudio2 = XAudio2Tool::instance()->xAudio2();
HRESULT hr = xAudio2->CreateSourceVoice(&_voice, _wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO, &_voiceCallback);
if (FAILED(hr))
{
TraceError(L"Create source voice error", hr);
2018-05-17 23:53:27 +08:00
SAFE_DELETE_ARRAY(_waveData);
return false;
}
2018-05-17 23:53:27 +08:00
_opened = true;
_playing = false;
return true;
}
2018-05-17 23:53:27 +08:00
bool e2d::Music::play(int nLoopCount)
{
2018-05-17 23:53:27 +08:00
if (!_opened)
2018-03-02 23:49:57 +08:00
{
2018-08-12 12:06:06 +08:00
WARN("Music::play Failed: Music must be opened first!");
2018-03-02 23:49:57 +08:00
return false;
}
2018-05-17 23:53:27 +08:00
if (_voice == nullptr)
2018-03-02 23:49:57 +08:00
{
2018-08-12 12:06:06 +08:00
WARN("Music::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-17 23:53:27 +08:00
if (_playing)
{
stop();
}
2018-07-04 12:49:05 +08:00
nLoopCount = std::min(nLoopCount, XAUDIO2_LOOP_INFINITE - 1);
2018-02-06 21:11:54 +08:00
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-17 23:53:27 +08:00
buffer.pAudioData = _waveData;
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-17 23:53:27 +08:00
if (FAILED(hr = _voice->SubmitSourceBuffer(&buffer)))
{
2018-04-23 00:05:57 +08:00
TraceError(L"Submitting source buffer error", hr);
2018-05-17 23:53:27 +08:00
_voice->DestroyVoice();
SAFE_DELETE_ARRAY(_waveData);
2018-02-01 22:07:44 +08:00
return false;
}
2018-05-17 23:53:27 +08:00
if (SUCCEEDED(hr = _voice->Start(0)))
2018-02-01 22:07:44 +08:00
{
2018-05-17 23:53:27 +08:00
_playing = true;
2018-02-01 22:07:44 +08:00
}
2018-05-17 23:53:27 +08:00
2018-02-01 22:07:44 +08:00
return SUCCEEDED(hr);
}
2018-05-17 23:53:27 +08:00
void e2d::Music::pause()
{
2018-05-17 23:53:27 +08:00
if (_voice)
2018-02-01 22:07:44 +08:00
{
2018-05-17 23:53:27 +08:00
if (SUCCEEDED(_voice->Stop()))
2018-02-01 22:07:44 +08:00
{
2018-05-17 23:53:27 +08:00
_playing = false;
2018-02-01 22:07:44 +08:00
}
}
}
2018-05-17 23:53:27 +08:00
void e2d::Music::resume()
{
2018-05-17 23:53:27 +08:00
if (_voice)
2018-02-01 22:07:44 +08:00
{
2018-05-17 23:53:27 +08:00
if (SUCCEEDED(_voice->Start()))
2018-02-01 22:07:44 +08:00
{
2018-05-17 23:53:27 +08:00
_playing = true;
2018-02-01 22:07:44 +08:00
}
}
}
2018-05-17 23:53:27 +08:00
void e2d::Music::stop()
{
2018-05-17 23:53:27 +08:00
if (_voice)
2018-02-01 22:07:44 +08:00
{
2018-05-17 23:53:27 +08:00
if (SUCCEEDED(_voice->Stop()))
2018-02-01 22:07:44 +08:00
{
2018-05-17 23:53:27 +08:00
_voice->ExitLoop();
_voice->FlushSourceBuffers();
_playing = false;
2018-02-01 22:07:44 +08:00
}
}
}
2018-05-17 23:53:27 +08:00
void e2d::Music::close()
{
2018-05-17 23:53:27 +08:00
if (_voice)
2018-03-02 23:49:57 +08:00
{
2018-05-17 23:53:27 +08:00
_voice->Stop();
_voice->FlushSourceBuffers();
_voice->DestroyVoice();
_voice = 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-17 23:53:27 +08:00
SAFE_DELETE_ARRAY(_resBuffer);
SAFE_DELETE_ARRAY(_waveData);
SAFE_DELETE_ARRAY(_wfx);
2018-03-02 23:49:57 +08:00
2018-05-17 23:53:27 +08:00
_opened = false;
_playing = false;
2018-03-02 23:49:57 +08:00
}
bool e2d::Music::playing() const
2018-03-02 23:49:57 +08:00
{
2018-05-17 23:53:27 +08:00
if (_opened && _voice)
{
2018-05-17 23:53:27 +08:00
return _playing;
2018-02-01 22:07:44 +08:00
}
else
{
return false;
}
}
float e2d::Music::volume() const
{
return _volume;
}
IXAudio2SourceVoice * e2d::Music::sourceVoice() const
{
2018-05-17 23:53:27 +08:00
return _voice;
}
bool e2d::Music::volume(float volume)
2018-05-17 23:53:27 +08:00
{
_volume = volume;
2018-05-17 23:53:27 +08:00
if (_voice)
2018-02-01 22:07:44 +08:00
{
2018-07-28 20:06:27 +08:00
return SUCCEEDED(_voice->SetVolume(volume));
2018-02-01 22:07:44 +08:00
}
return false;
}
void e2d::Music::callbackOnEnd(const Function & func)
{
_voiceCallback.SetCallbackOnStreamEnd(func);
}
void e2d::Music::callbackOnLoopEnd(const Function & func)
{
_voiceCallback.SetCallbackOnLoopEnd(func);
}
2018-05-17 23:53:27 +08:00
bool e2d::Music::_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-17 23:53:27 +08:00
_wfx = 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
{
_wfx = (WAVEFORMATEX*) new CHAR[sizeof(WAVEFORMATEX)];
2018-02-01 22:07:44 +08:00
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
2018-05-17 23:53:27 +08:00
memcpy(_wfx, &pcmWaveFormat, sizeof(pcmWaveFormat));
_wfx->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
_wfx = (WAVEFORMATEX*) new CHAR[sizeof(WAVEFORMATEX) + cbExtraBytes];
2018-02-01 22:07:44 +08:00
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
2018-05-17 23:53:27 +08:00
memcpy(_wfx, &pcmWaveFormat, sizeof(pcmWaveFormat));
_wfx->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-17 23:53:27 +08:00
if (mmioRead(_hmmio, (CHAR*)(((BYTE*)&(_wfx->cbSize)) + sizeof(WORD)),
2018-02-01 22:07:44 +08:00
cbExtraBytes) != cbExtraBytes)
{
2018-05-17 23:53:27 +08:00
SAFE_DELETE(_wfx);
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-17 23:53:27 +08:00
SAFE_DELETE(_wfx);
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-05-17 23:53:27 +08:00
bool e2d::Music::_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-05-17 23:53:27 +08:00
bool e2d::Music::_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-05-14 22:51:40 +08:00
for (DWORD cT = 0; cT < cbDataIn; ++cT)
2018-02-01 22:07:44 +08:00
{
// 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);
2018-05-14 22:51:40 +08:00
++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-05-17 23:53:27 +08:00
bool e2d::Music::_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 };
2018-02-01 22:07:44 +08:00
GetModuleFileName(HINST_THISCOMPONENT, strExePath, MAX_PATH);
strExePath[MAX_PATH - 1] = 0;
2018-07-25 16:44:22 +08:00
wchar_t* strLastSlash = wcsrchr(strExePath, TEXT('\\'));
2018-02-01 22:07:44 +08:00
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
// Chop the exe _name from the exe path
2018-02-01 22:07:44 +08:00
*strLastSlash = 0;
2018-01-30 16:45:38 +08:00
// Chop the .exe from the exe _name
2018-02-01 22:07:44 +08:00
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
// 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
}