明确Resource的定义,不允许从本地文件创建Resource
This commit is contained in:
parent
a394eb0595
commit
00a2b9ebac
|
|
@ -2,7 +2,7 @@
|
||||||
#include "..\e2dbase.h"
|
#include "..\e2dbase.h"
|
||||||
#include "..\e2dtool.h"
|
#include "..\e2dtool.h"
|
||||||
|
|
||||||
std::map<e2d::Resource, ID2D1Bitmap*> e2d::Image::_bitmapCache;
|
std::map<size_t, ID2D1Bitmap*> e2d::Image::_bitmapCache;
|
||||||
|
|
||||||
e2d::Image::Image()
|
e2d::Image::Image()
|
||||||
: _bitmap(nullptr)
|
: _bitmap(nullptr)
|
||||||
|
|
@ -29,14 +29,14 @@ e2d::Image::Image(const String & fileName)
|
||||||
: _bitmap(nullptr)
|
: _bitmap(nullptr)
|
||||||
, _cropRect()
|
, _cropRect()
|
||||||
{
|
{
|
||||||
this->open(Resource(fileName));
|
this->open(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
e2d::Image::Image(const String & fileName, const Rect & cropRect)
|
e2d::Image::Image(const String & fileName, const Rect & cropRect)
|
||||||
: _bitmap(nullptr)
|
: _bitmap(nullptr)
|
||||||
, _cropRect()
|
, _cropRect()
|
||||||
{
|
{
|
||||||
this->open(Resource(fileName));
|
this->open(fileName);
|
||||||
this->crop(cropRect);
|
this->crop(cropRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -46,27 +46,31 @@ e2d::Image::~Image()
|
||||||
|
|
||||||
bool e2d::Image::open(const Resource& res)
|
bool e2d::Image::open(const Resource& res)
|
||||||
{
|
{
|
||||||
if (res.isFile())
|
|
||||||
{
|
|
||||||
WARN_IF(res.getFileName().isEmpty(), "Image open failed! Invalid file name.");
|
|
||||||
|
|
||||||
if (res.getFileName().isEmpty())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Image::preload(res))
|
if (!Image::preload(res))
|
||||||
{
|
{
|
||||||
WARN("Load Image from file failed!");
|
WARN("Load Image from file failed!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->_setBitmap(_bitmapCache.at(res));
|
this->_setBitmap(_bitmapCache.at(res.resNameId));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool e2d::Image::open(const String & fileName)
|
bool e2d::Image::open(const String & fileName)
|
||||||
{
|
{
|
||||||
return open(Resource(fileName));
|
WARN_IF(fileName.isEmpty(), "Image open failed! Invalid file name.");
|
||||||
|
|
||||||
|
if (fileName.isEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!Image::preload(fileName))
|
||||||
|
{
|
||||||
|
WARN("Load Image from file failed!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->_setBitmap(_bitmapCache.at(fileName.hash()));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void e2d::Image::crop(const Rect& cropRect)
|
void e2d::Image::crop(const Rect& cropRect)
|
||||||
|
|
@ -148,22 +152,19 @@ e2d::Point e2d::Image::getCropPos() const
|
||||||
|
|
||||||
bool e2d::Image::preload(const Resource& res)
|
bool e2d::Image::preload(const Resource& res)
|
||||||
{
|
{
|
||||||
if (_bitmapCache.find(res) != _bitmapCache.end())
|
if (_bitmapCache.find(res.resNameId) != _bitmapCache.end())
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT hr = S_OK;
|
Renderer* renderer = Game::getInstance()->getRenderer();
|
||||||
|
ID2D1HwndRenderTarget* pRenderTarget = renderer->getRenderTarget();
|
||||||
|
IWICImagingFactory *pImagingFactory = renderer->getImagingFactory();
|
||||||
IWICBitmapDecoder *pDecoder = nullptr;
|
IWICBitmapDecoder *pDecoder = nullptr;
|
||||||
IWICBitmapFrameDecode *pSource = nullptr;
|
IWICBitmapFrameDecode *pSource = nullptr;
|
||||||
IWICStream *pStream = nullptr;
|
IWICStream *pStream = nullptr;
|
||||||
IWICFormatConverter *pConverter = nullptr;
|
IWICFormatConverter *pConverter = nullptr;
|
||||||
ID2D1Bitmap *pBitmap = nullptr;
|
ID2D1Bitmap *pBitmap = nullptr;
|
||||||
IWICImagingFactory *pImagingFactory = Game::getInstance()->getRenderer()->getImagingFactory();
|
|
||||||
|
|
||||||
if (!res.isFile())
|
|
||||||
{
|
|
||||||
HRSRC imageResHandle = nullptr;
|
HRSRC imageResHandle = nullptr;
|
||||||
HGLOBAL imageResDataHandle = nullptr;
|
HGLOBAL imageResDataHandle = nullptr;
|
||||||
void *pImageFile = nullptr;
|
void *pImageFile = nullptr;
|
||||||
|
|
@ -172,11 +173,11 @@ bool e2d::Image::preload(const Resource& res)
|
||||||
// 定位资源
|
// 定位资源
|
||||||
imageResHandle = ::FindResourceW(
|
imageResHandle = ::FindResourceW(
|
||||||
HINST_THISCOMPONENT,
|
HINST_THISCOMPONENT,
|
||||||
MAKEINTRESOURCE(res.getResNameId()),
|
MAKEINTRESOURCE(res.resNameId),
|
||||||
(LPCWSTR)res.getResType()
|
(LPCWSTR)res.resType
|
||||||
);
|
);
|
||||||
|
|
||||||
hr = imageResHandle ? S_OK : E_FAIL;
|
HRESULT hr = imageResHandle ? S_OK : E_FAIL;
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
// 加载资源
|
// 加载资源
|
||||||
|
|
@ -226,24 +227,6 @@ bool e2d::Image::preload(const Resource& res)
|
||||||
&pDecoder
|
&pDecoder
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
String actualFilePath = File(res.getFileName()).getFilePath();
|
|
||||||
if (actualFilePath.isEmpty())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ´´½¨½âÂëÆ÷
|
|
||||||
hr = pImagingFactory->CreateDecoderFromFilename(
|
|
||||||
(LPCWSTR)actualFilePath,
|
|
||||||
nullptr,
|
|
||||||
GENERIC_READ,
|
|
||||||
WICDecodeMetadataCacheOnLoad,
|
|
||||||
&pDecoder
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
|
|
@ -273,7 +256,7 @@ bool e2d::Image::preload(const Resource& res)
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
// 从 WIC 位图创建一个 Direct2D 位图
|
// 从 WIC 位图创建一个 Direct2D 位图
|
||||||
hr = Game::getInstance()->getRenderer()->getRenderTarget()->CreateBitmapFromWicBitmap(
|
hr = pRenderTarget->CreateBitmapFromWicBitmap(
|
||||||
pConverter,
|
pConverter,
|
||||||
nullptr,
|
nullptr,
|
||||||
&pBitmap
|
&pBitmap
|
||||||
|
|
@ -282,7 +265,84 @@ bool e2d::Image::preload(const Resource& res)
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
_bitmapCache.insert(std::make_pair(res, pBitmap));
|
_bitmapCache.insert(std::make_pair(res.resNameId, pBitmap));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 释放相关资源
|
||||||
|
SafeRelease(pDecoder);
|
||||||
|
SafeRelease(pSource);
|
||||||
|
SafeRelease(pStream);
|
||||||
|
SafeRelease(pConverter);
|
||||||
|
|
||||||
|
return SUCCEEDED(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool e2d::Image::preload(const String & fileName)
|
||||||
|
{
|
||||||
|
String actualFilePath = File(fileName).getFilePath();
|
||||||
|
if (actualFilePath.isEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
size_t hash = actualFilePath.hash();
|
||||||
|
if (_bitmapCache.find(hash) != _bitmapCache.end())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
Renderer* renderer = Game::getInstance()->getRenderer();
|
||||||
|
ID2D1HwndRenderTarget* pRenderTarget = renderer->getRenderTarget();
|
||||||
|
IWICImagingFactory *pImagingFactory = renderer->getImagingFactory();
|
||||||
|
IWICBitmapDecoder *pDecoder = nullptr;
|
||||||
|
IWICBitmapFrameDecode *pSource = nullptr;
|
||||||
|
IWICStream *pStream = nullptr;
|
||||||
|
IWICFormatConverter *pConverter = nullptr;
|
||||||
|
ID2D1Bitmap *pBitmap = nullptr;
|
||||||
|
|
||||||
|
// 创建解码器
|
||||||
|
HRESULT hr = pImagingFactory->CreateDecoderFromFilename(
|
||||||
|
(LPCWSTR)actualFilePath,
|
||||||
|
nullptr,
|
||||||
|
GENERIC_READ,
|
||||||
|
WICDecodeMetadataCacheOnLoad,
|
||||||
|
&pDecoder
|
||||||
|
);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
// 创建初始化框架
|
||||||
|
hr = pDecoder->GetFrame(0, &pSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
// 创建图片格式转换器
|
||||||
|
hr = pImagingFactory->CreateFormatConverter(&pConverter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
// 图片格式转换成 32bppPBGRA
|
||||||
|
hr = pConverter->Initialize(
|
||||||
|
pSource,
|
||||||
|
GUID_WICPixelFormat32bppPBGRA,
|
||||||
|
WICBitmapDitherTypeNone,
|
||||||
|
nullptr,
|
||||||
|
0.f,
|
||||||
|
WICBitmapPaletteTypeMedianCut
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
// 从 WIC 位图创建一个 Direct2D 位图
|
||||||
|
hr = pRenderTarget->CreateBitmapFromWicBitmap(
|
||||||
|
pConverter,
|
||||||
|
nullptr,
|
||||||
|
&pBitmap
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
_bitmapCache.insert(std::make_pair(hash, pBitmap));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 释放相关资源
|
// 释放相关资源
|
||||||
|
|
|
||||||
|
|
@ -1,62 +1,8 @@
|
||||||
#include "..\e2dtool.h"
|
#include "..\e2dtool.h"
|
||||||
|
|
||||||
e2d::Resource::Resource(const String & fileName)
|
|
||||||
: _isFile(true)
|
|
||||||
, _fileName(fileName)
|
|
||||||
, _resNameId(0)
|
|
||||||
, _resType()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
e2d::Resource::Resource(size_t resNameId, const String & resType)
|
e2d::Resource::Resource(size_t resNameId, const String & resType)
|
||||||
: _isFile(false)
|
: resNameId(resNameId)
|
||||||
, _fileName()
|
, resType(resType)
|
||||||
, _resNameId(resNameId)
|
|
||||||
, _resType(resType)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool e2d::Resource::isFile() const
|
|
||||||
{
|
|
||||||
return _isFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
const e2d::String & e2d::Resource::getFileName() const
|
|
||||||
{
|
|
||||||
return _fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t e2d::Resource::getResNameId() const
|
|
||||||
{
|
|
||||||
return _resNameId;
|
|
||||||
}
|
|
||||||
|
|
||||||
const e2d::String & e2d::Resource::getResType() const
|
|
||||||
{
|
|
||||||
return _resType;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t e2d::Resource::getKey() const
|
|
||||||
{
|
|
||||||
return _isFile ? _fileName.hash() : _resNameId;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool e2d::Resource::operator>(const Resource &res) const
|
|
||||||
{
|
|
||||||
return this->getKey() > res.getKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool e2d::Resource::operator>=(const Resource &res) const
|
|
||||||
{
|
|
||||||
return this->getKey() >= res.getKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool e2d::Resource::operator<(const Resource &res) const
|
|
||||||
{
|
|
||||||
return this->getKey() < res.getKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool e2d::Resource::operator<=(const Resource &res) const
|
|
||||||
{
|
|
||||||
return this->getKey() <= res.getKey();
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,18 @@ bool e2d::Sprite::open(const Resource& res)
|
||||||
|
|
||||||
bool e2d::Sprite::open(const String & fileName)
|
bool e2d::Sprite::open(const String & fileName)
|
||||||
{
|
{
|
||||||
return open(Resource(fileName));
|
if (!_image)
|
||||||
|
{
|
||||||
|
_image = new (e2d::autorelease) Image();
|
||||||
|
_image->retain();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_image->open(fileName))
|
||||||
|
{
|
||||||
|
Node::setSize(_image->getWidth(), _image->getHeight());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void e2d::Sprite::crop(const Rect& cropRect)
|
void e2d::Sprite::crop(const Rect& cropRect)
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,44 @@ inline bool TraceError(wchar_t* sPrompt, HRESULT hr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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::getInstance()
|
||||||
|
{
|
||||||
|
static XAudio2Tool instance;
|
||||||
|
return &instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
IXAudio2 * e2d::Music::XAudio2Tool::getXAudio2()
|
||||||
|
{
|
||||||
|
return _xAudio2;
|
||||||
|
}
|
||||||
|
|
||||||
|
IXAudio2MasteringVoice * e2d::Music::XAudio2Tool::getMasteringVoice()
|
||||||
|
{
|
||||||
|
return _masteringVoice;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
e2d::Music::Music()
|
e2d::Music::Music()
|
||||||
: _opened(false)
|
: _opened(false)
|
||||||
, _playing(false)
|
, _playing(false)
|
||||||
|
|
@ -32,10 +70,26 @@ e2d::Music::Music()
|
||||||
, _dwSize(0)
|
, _dwSize(0)
|
||||||
, _voice(nullptr)
|
, _voice(nullptr)
|
||||||
, _voiceCallback(this)
|
, _voiceCallback(this)
|
||||||
, _xAudio2(nullptr)
|
|
||||||
, _masteringVoice(nullptr)
|
|
||||||
{
|
{
|
||||||
CoInitialize(nullptr);
|
auto xAudio2 = XAudio2Tool::getInstance()->getXAudio2();
|
||||||
|
xAudio2->AddRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
e2d::Music::Music(const e2d::String & filePath)
|
||||||
|
: _opened(false)
|
||||||
|
, _playing(false)
|
||||||
|
, _wfx(nullptr)
|
||||||
|
, _hmmio(nullptr)
|
||||||
|
, _resBuffer(nullptr)
|
||||||
|
, _waveData(nullptr)
|
||||||
|
, _dwSize(0)
|
||||||
|
, _voice(nullptr)
|
||||||
|
, _voiceCallback(this)
|
||||||
|
{
|
||||||
|
auto xAudio2 = XAudio2Tool::getInstance()->getXAudio2();
|
||||||
|
xAudio2->AddRef();
|
||||||
|
|
||||||
|
this->open(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
e2d::Music::Music(const Resource& res)
|
e2d::Music::Music(const Resource& res)
|
||||||
|
|
@ -48,105 +102,28 @@ e2d::Music::Music(const Resource& res)
|
||||||
, _dwSize(0)
|
, _dwSize(0)
|
||||||
, _voice(nullptr)
|
, _voice(nullptr)
|
||||||
, _voiceCallback(this)
|
, _voiceCallback(this)
|
||||||
, _xAudio2(nullptr)
|
|
||||||
, _masteringVoice(nullptr)
|
|
||||||
{
|
{
|
||||||
CoInitialize(nullptr);
|
auto xAudio2 = XAudio2Tool::getInstance()->getXAudio2();
|
||||||
|
xAudio2->AddRef();
|
||||||
|
|
||||||
this->open(res);
|
this->open(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
e2d::Music::Music(IXAudio2 * xAudio2)
|
|
||||||
: _opened(false)
|
|
||||||
, _playing(false)
|
|
||||||
, _wfx(nullptr)
|
|
||||||
, _hmmio(nullptr)
|
|
||||||
, _resBuffer(nullptr)
|
|
||||||
, _waveData(nullptr)
|
|
||||||
, _dwSize(0)
|
|
||||||
, _voice(nullptr)
|
|
||||||
, _voiceCallback(this)
|
|
||||||
, _xAudio2(xAudio2)
|
|
||||||
, _masteringVoice(nullptr)
|
|
||||||
{
|
|
||||||
CoInitialize(nullptr);
|
|
||||||
|
|
||||||
if (_xAudio2)
|
|
||||||
{
|
|
||||||
_xAudio2->AddRef();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
e2d::Music::~Music()
|
e2d::Music::~Music()
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
|
|
||||||
if (_masteringVoice)
|
auto xAudio2 = XAudio2Tool::getInstance()->getXAudio2();
|
||||||
{
|
xAudio2->Release();
|
||||||
_masteringVoice->DestroyVoice();
|
|
||||||
_masteringVoice = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SafeRelease(_xAudio2);
|
bool e2d::Music::open(const e2d::String & filePath)
|
||||||
|
|
||||||
CoUninitialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool e2d::Music::open(const Resource& res)
|
|
||||||
{
|
{
|
||||||
if (_opened)
|
if (_opened)
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_xAudio2)
|
|
||||||
{
|
|
||||||
if (FAILED(XAudio2Create(&_xAudio2, 0)))
|
|
||||||
{
|
|
||||||
TraceError(L"Create IXAudio2 error");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(_xAudio2->CreateMasteringVoice(&_masteringVoice)))
|
|
||||||
{
|
|
||||||
TraceError(L"Create IXAudio2MasteringVoice error");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!res.isFile())
|
|
||||||
{
|
|
||||||
HRSRC hResInfo;
|
|
||||||
HGLOBAL hResData;
|
|
||||||
DWORD dwSize;
|
|
||||||
void* pvRes;
|
|
||||||
|
|
||||||
if (nullptr == (hResInfo = FindResourceW(HINST_THISCOMPONENT, MAKEINTRESOURCE(res.getResNameId()), (LPCWSTR)res.getResType())))
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
String filePath = res.getFileName();
|
|
||||||
if (filePath.isEmpty())
|
if (filePath.isEmpty())
|
||||||
{
|
{
|
||||||
WARN("MusicInfo::open Invalid file name.");
|
WARN("MusicInfo::open Invalid file name.");
|
||||||
|
|
@ -169,7 +146,6 @@ bool e2d::Music::open(const Resource& res)
|
||||||
}
|
}
|
||||||
|
|
||||||
_hmmio = mmioOpen(pFilePath, nullptr, MMIO_ALLOCBUF | MMIO_READ);
|
_hmmio = mmioOpen(pFilePath, nullptr, MMIO_ALLOCBUF | MMIO_READ);
|
||||||
}
|
|
||||||
|
|
||||||
if (nullptr == _hmmio)
|
if (nullptr == _hmmio)
|
||||||
{
|
{
|
||||||
|
|
@ -200,7 +176,87 @@ bool e2d::Music::open(const Resource& res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ´´½¨ÒôÔ´
|
// ´´½¨ÒôÔ´
|
||||||
HRESULT hr = _xAudio2->CreateSourceVoice(&_voice, _wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO, &_voiceCallback);
|
auto xAudio2 = XAudio2Tool::getInstance()->getXAudio2();
|
||||||
|
HRESULT hr = xAudio2->CreateSourceVoice(&_voice, _wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO, &_voiceCallback);
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
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())
|
||||||
|
{
|
||||||
|
// 读取非 wave 文件时 ReadMMIO 调用失败
|
||||||
|
mmioClose(_hmmio, 0);
|
||||||
|
return TraceError(L"ReadMMIO");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_resetFile())
|
||||||
|
return TraceError(L"ResetFile");
|
||||||
|
|
||||||
|
// 重置文件后,wave 文件的大小是 _ck.cksize
|
||||||
|
_dwSize = _ck.cksize;
|
||||||
|
|
||||||
|
// 将样本数据读取到内存中
|
||||||
|
_waveData = new BYTE[_dwSize];
|
||||||
|
|
||||||
|
if (!_read(_waveData, _dwSize))
|
||||||
|
{
|
||||||
|
TraceError(L"Failed to read WAV data");
|
||||||
|
SAFE_DELETE_ARRAY(_waveData);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建音源
|
||||||
|
auto xAudio2 = XAudio2Tool::getInstance()->getXAudio2();
|
||||||
|
HRESULT hr = xAudio2->CreateSourceVoice(&_voice, _wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO, &_voiceCallback);
|
||||||
|
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3,21 +3,7 @@
|
||||||
|
|
||||||
e2d::Player::Player()
|
e2d::Player::Player()
|
||||||
: _volume(1.f)
|
: _volume(1.f)
|
||||||
, _enabled(true)
|
|
||||||
, _xAudio2(nullptr)
|
|
||||||
, _masteringVoice(nullptr)
|
|
||||||
{
|
{
|
||||||
CoInitialize(nullptr);
|
|
||||||
|
|
||||||
if (FAILED(XAudio2Create(&_xAudio2, 0)))
|
|
||||||
{
|
|
||||||
WARN("初始化 XAudio2 组件失败");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(_xAudio2->CreateMasteringVoice(&_masteringVoice)))
|
|
||||||
{
|
|
||||||
WARN("初始化 MasteringVoice 组件失败");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
e2d::Player::~Player()
|
e2d::Player::~Player()
|
||||||
|
|
@ -30,30 +16,85 @@ e2d::Player::~Player()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_masteringVoice)
|
|
||||||
{
|
|
||||||
_masteringVoice->DestroyVoice();
|
|
||||||
_masteringVoice = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeRelease(_xAudio2);
|
|
||||||
|
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
IXAudio2 * e2d::Player::getXAudio2()
|
bool e2d::Player::preload(const String & filePath)
|
||||||
{
|
{
|
||||||
return _xAudio2;
|
if (filePath.isEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Music * music = new (std::nothrow) Music();
|
||||||
|
|
||||||
|
if (music && music->open(filePath))
|
||||||
|
{
|
||||||
|
music->setVolume(_volume);
|
||||||
|
_musicList.insert(std::make_pair(filePath.hash(), music));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
IXAudio2MasteringVoice * e2d::Player::getMasteringVoice()
|
bool e2d::Player::play(const String & filePath, int nLoopCount)
|
||||||
{
|
{
|
||||||
return _masteringVoice;
|
if (filePath.isEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (Player::preload(filePath))
|
||||||
|
{
|
||||||
|
auto music = _musicList[filePath.hash()];
|
||||||
|
if (music->play(nLoopCount))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void e2d::Player::pause(const String & filePath)
|
||||||
|
{
|
||||||
|
if (filePath.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
size_t hash = filePath.hash();
|
||||||
|
if (_musicList.end() != _musicList.find(hash))
|
||||||
|
_musicList[hash]->pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
void e2d::Player::resume(const String & filePath)
|
||||||
|
{
|
||||||
|
if (filePath.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
size_t hash = filePath.hash();
|
||||||
|
if (_musicList.end() != _musicList.find(hash))
|
||||||
|
_musicList[hash]->resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
void e2d::Player::stop(const String & filePath)
|
||||||
|
{
|
||||||
|
if (filePath.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
size_t hash = filePath.hash();
|
||||||
|
if (_musicList.end() != _musicList.find(hash))
|
||||||
|
_musicList[hash]->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool e2d::Player::isPlaying(const String & filePath)
|
||||||
|
{
|
||||||
|
if (filePath.isEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
size_t hash = filePath.hash();
|
||||||
|
if (_musicList.end() != _musicList.find(hash))
|
||||||
|
return _musicList[hash]->isPlaying();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool e2d::Player::preload(const Resource& res)
|
bool e2d::Player::preload(const Resource& res)
|
||||||
{
|
{
|
||||||
if (_musicList.end() != _musicList.find(res))
|
if (_musicList.end() != _musicList.find(res.resNameId))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
Music * music = new (std::nothrow) Music();
|
Music * music = new (std::nothrow) Music();
|
||||||
|
|
@ -61,7 +102,7 @@ bool e2d::Player::preload(const Resource& res)
|
||||||
if (music && music->open(res))
|
if (music && music->open(res))
|
||||||
{
|
{
|
||||||
music->setVolume(_volume);
|
music->setVolume(_volume);
|
||||||
_musicList.insert(std::make_pair(res, music));
|
_musicList.insert(std::make_pair(res.resNameId, music));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -71,7 +112,7 @@ bool e2d::Player::play(const Resource& res, int nLoopCount)
|
||||||
{
|
{
|
||||||
if (Player::preload(res))
|
if (Player::preload(res))
|
||||||
{
|
{
|
||||||
auto music = _musicList[res];
|
auto music = _musicList[res.resNameId];
|
||||||
if (music->play(nLoopCount))
|
if (music->play(nLoopCount))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -82,26 +123,26 @@ bool e2d::Player::play(const Resource& res, int nLoopCount)
|
||||||
|
|
||||||
void e2d::Player::pause(const Resource& res)
|
void e2d::Player::pause(const Resource& res)
|
||||||
{
|
{
|
||||||
if (_musicList.end() != _musicList.find(res))
|
if (_musicList.end() != _musicList.find(res.resNameId))
|
||||||
_musicList[res]->pause();
|
_musicList[res.resNameId]->pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
void e2d::Player::resume(const Resource& res)
|
void e2d::Player::resume(const Resource& res)
|
||||||
{
|
{
|
||||||
if (_musicList.end() != _musicList.find(res))
|
if (_musicList.end() != _musicList.find(res.resNameId))
|
||||||
_musicList[res]->pause();
|
_musicList[res.resNameId]->resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
void e2d::Player::stop(const Resource& res)
|
void e2d::Player::stop(const Resource& res)
|
||||||
{
|
{
|
||||||
if (_musicList.end() != _musicList.find(res))
|
if (_musicList.end() != _musicList.find(res.resNameId))
|
||||||
_musicList[res]->stop();
|
_musicList[res.resNameId]->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool e2d::Player::isPlaying(const Resource& res)
|
bool e2d::Player::isPlaying(const Resource& res)
|
||||||
{
|
{
|
||||||
if (_musicList.end() != _musicList.find(res))
|
if (_musicList.end() != _musicList.find(res.resNameId))
|
||||||
return _musicList[res]->isPlaying();
|
return _musicList[res.resNameId]->isPlaying();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -143,15 +184,6 @@ void e2d::Player::stopAll()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void e2d::Player::setEnabled(bool enabled)
|
|
||||||
{
|
|
||||||
if (_enabled == enabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_enabled = enabled;
|
|
||||||
_enabled ? _xAudio2->StartEngine() : _xAudio2->StopEngine();
|
|
||||||
}
|
|
||||||
|
|
||||||
void e2d::Player::clearCache()
|
void e2d::Player::clearCache()
|
||||||
{
|
{
|
||||||
for (const auto& pair : _musicList)
|
for (const auto& pair : _musicList)
|
||||||
|
|
|
||||||
|
|
@ -679,37 +679,14 @@ protected:
|
||||||
class Resource
|
class Resource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Resource(
|
|
||||||
const String& fileName /* 文件路径 */
|
|
||||||
);
|
|
||||||
|
|
||||||
Resource(
|
Resource(
|
||||||
size_t resNameId, /* 资源名称 */
|
size_t resNameId, /* 资源名称 */
|
||||||
const String& resType /* 资源类型 */
|
const String& resType /* 资源类型 */
|
||||||
);
|
);
|
||||||
|
|
||||||
// 是否是本地文件
|
public:
|
||||||
bool isFile() const;
|
size_t resNameId;
|
||||||
|
String resType;
|
||||||
const String& getFileName() const;
|
|
||||||
|
|
||||||
size_t getResNameId() const;
|
|
||||||
|
|
||||||
const String& getResType() const;
|
|
||||||
|
|
||||||
size_t getKey() const;
|
|
||||||
|
|
||||||
// 比较运算符
|
|
||||||
bool operator> (const Resource &) const;
|
|
||||||
bool operator>= (const Resource &) const;
|
|
||||||
bool operator< (const Resource &) const;
|
|
||||||
bool operator<= (const Resource &) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool _isFile;
|
|
||||||
size_t _resNameId;
|
|
||||||
String _resType;
|
|
||||||
String _fileName;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -810,6 +787,11 @@ public:
|
||||||
// 获取 ID2D1Bitmap 对象
|
// 获取 ID2D1Bitmap 对象
|
||||||
ID2D1Bitmap * getBitmap();
|
ID2D1Bitmap * getBitmap();
|
||||||
|
|
||||||
|
// Ô¤¼ÓÔØÍ¼Æ¬×ÊÔ´
|
||||||
|
static bool preload(
|
||||||
|
const String& fileName
|
||||||
|
);
|
||||||
|
|
||||||
// 预加载图片资源
|
// 预加载图片资源
|
||||||
static bool preload(
|
static bool preload(
|
||||||
const Resource& res
|
const Resource& res
|
||||||
|
|
@ -830,7 +812,7 @@ protected:
|
||||||
Rect _cropRect;
|
Rect _cropRect;
|
||||||
ID2D1Bitmap * _bitmap;
|
ID2D1Bitmap * _bitmap;
|
||||||
|
|
||||||
static std::map<Resource, ID2D1Bitmap*> _bitmapCache;
|
static std::map<size_t, ID2D1Bitmap*> _bitmapCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,15 +58,20 @@ public:
|
||||||
Music();
|
Music();
|
||||||
|
|
||||||
explicit Music(
|
explicit Music(
|
||||||
const Resource& res /* 音乐资源 */
|
const e2d::String& filePath /* 音乐文件路径 */
|
||||||
);
|
);
|
||||||
|
|
||||||
explicit Music(
|
explicit Music(
|
||||||
IXAudio2* xAudio2
|
const Resource& res /* 音乐资源 */
|
||||||
);
|
);
|
||||||
|
|
||||||
virtual ~Music();
|
virtual ~Music();
|
||||||
|
|
||||||
|
// 打开音乐文件
|
||||||
|
bool open(
|
||||||
|
const e2d::String& filePath /* 音乐文件路径 */
|
||||||
|
);
|
||||||
|
|
||||||
// 댔역稜있栗都
|
// 댔역稜있栗都
|
||||||
bool open(
|
bool open(
|
||||||
const Resource& res
|
const Resource& res
|
||||||
|
|
@ -110,6 +115,27 @@ public:
|
||||||
// 삿혤 IXAudio2SourceVoice 뚤蹶
|
// 삿혤 IXAudio2SourceVoice 뚤蹶
|
||||||
IXAudio2SourceVoice * getIXAudio2SourceVoice() const;
|
IXAudio2SourceVoice * getIXAudio2SourceVoice() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
class XAudio2Tool
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
XAudio2Tool();
|
||||||
|
|
||||||
|
~XAudio2Tool();
|
||||||
|
|
||||||
|
static XAudio2Tool* getInstance();
|
||||||
|
|
||||||
|
// 获取 XAudio2 实例对象
|
||||||
|
IXAudio2 * getXAudio2();
|
||||||
|
|
||||||
|
// 获取 MasteringVoice 实例对象
|
||||||
|
IXAudio2MasteringVoice* getMasteringVoice();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
IXAudio2 * _xAudio2;
|
||||||
|
IXAudio2MasteringVoice* _masteringVoice;
|
||||||
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool _readMMIO();
|
bool _readMMIO();
|
||||||
|
|
||||||
|
|
@ -137,9 +163,7 @@ protected:
|
||||||
MMCKINFO _ckRiff;
|
MMCKINFO _ckRiff;
|
||||||
WAVEFORMATEX* _wfx;
|
WAVEFORMATEX* _wfx;
|
||||||
VoiceCallback _voiceCallback;
|
VoiceCallback _voiceCallback;
|
||||||
IXAudio2* _xAudio2;
|
|
||||||
IXAudio2SourceVoice* _voice;
|
IXAudio2SourceVoice* _voice;
|
||||||
IXAudio2MasteringVoice* _masteringVoice;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -153,6 +177,37 @@ public:
|
||||||
|
|
||||||
~Player();
|
~Player();
|
||||||
|
|
||||||
|
// 预加载音乐资源
|
||||||
|
bool preload(
|
||||||
|
const String& filePath /* 音乐文件路径 */
|
||||||
|
);
|
||||||
|
|
||||||
|
// 播放音乐
|
||||||
|
bool play(
|
||||||
|
const String& filePath, /* 音乐文件路径 */
|
||||||
|
int nLoopCount = 0 /* 重复播放次数,设置 -1 为循环播放 */
|
||||||
|
);
|
||||||
|
|
||||||
|
// 暂停音乐
|
||||||
|
void pause(
|
||||||
|
const String& filePath /* 音乐文件路径 */
|
||||||
|
);
|
||||||
|
|
||||||
|
// 继续播放音乐
|
||||||
|
void resume(
|
||||||
|
const String& filePath /* 音乐文件路径 */
|
||||||
|
);
|
||||||
|
|
||||||
|
// 停止音乐
|
||||||
|
void stop(
|
||||||
|
const String& filePath /* 音乐文件路径 */
|
||||||
|
);
|
||||||
|
|
||||||
|
// 获取音乐播放状态
|
||||||
|
bool isPlaying(
|
||||||
|
const String& filePath /* 音乐文件路径 */
|
||||||
|
);
|
||||||
|
|
||||||
// 渡속潼稜있栗都
|
// 渡속潼稜있栗都
|
||||||
bool preload(
|
bool preload(
|
||||||
const Resource& res /* 稜있栗都 */
|
const Resource& res /* 稜있栗都 */
|
||||||
|
|
@ -201,26 +256,12 @@ public:
|
||||||
// 界岺杰唐稜있
|
// 界岺杰唐稜있
|
||||||
void stopAll();
|
void stopAll();
|
||||||
|
|
||||||
// 打开或关闭播放器
|
|
||||||
void setEnabled(
|
|
||||||
bool enabled
|
|
||||||
);
|
|
||||||
|
|
||||||
// 헌왕稜있뻠닸
|
// 헌왕稜있뻠닸
|
||||||
void clearCache();
|
void clearCache();
|
||||||
|
|
||||||
// 获取 XAudio2 实例对象
|
|
||||||
IXAudio2 * getXAudio2();
|
|
||||||
|
|
||||||
// 获取 MasteringVoice 实例对象
|
|
||||||
IXAudio2MasteringVoice* getMasteringVoice();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _enabled;
|
|
||||||
float _volume;
|
float _volume;
|
||||||
IXAudio2* _xAudio2;
|
std::map<size_t, Music*> _musicList;
|
||||||
IXAudio2MasteringVoice* _masteringVoice;
|
|
||||||
std::map<Resource, Music*> _musicList;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue