From 3f892d23a8870af6b73b0dc2a1a502f656c8848e Mon Sep 17 00:00:00 2001 From: Nomango <569629550@qq.com> Date: Wed, 25 Oct 2017 10:54:03 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0EMusicUtils=EF=BC=9B=E6=9B=B4?= =?UTF-8?q?=E6=96=B0EFuileUtils=E5=9C=A8=E6=8F=90=E5=8F=96=E5=92=8C?= =?UTF-8?q?=E4=BF=9D=E5=AD=98=E6=95=B0=E5=AD=97=E7=B1=BB=E5=9E=8B=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=97=B6=E7=9A=84=E8=BD=AC=E6=8D=A2=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Easy2D/Tool/EFileUtils.cpp | 36 +-- Easy2D/Tool/EMusicUtils.cpp | 509 ++++++++++++++++++++++++++++++++++++ Easy2D/etools.h | 154 ++++++++++- 3 files changed, 665 insertions(+), 34 deletions(-) diff --git a/Easy2D/Tool/EFileUtils.cpp b/Easy2D/Tool/EFileUtils.cpp index d53e4b45..6ef76160 100644 --- a/Easy2D/Tool/EFileUtils.cpp +++ b/Easy2D/Tool/EFileUtils.cpp @@ -53,21 +53,17 @@ e2d::EString e2d::EFileUtils::getDefaultSavePath() void e2d::EFileUtils::saveInt(LPCTSTR key, int value) { - std::wstringstream ss; - ss << value; - ::WritePrivateProfileString(L"Default", key, ss.str().c_str(), getDefaultSavePath().c_str()); + ::WritePrivateProfileString(L"Default", key, std::to_wstring(value).c_str(), getDefaultSavePath().c_str()); } -void e2d::EFileUtils::saveDouble(LPCTSTR key, double value) +void e2d::EFileUtils::saveFloat(LPCTSTR key, float value) { - std::wstringstream ss; - ss << value; - ::WritePrivateProfileString(L"Default", key, ss.str().c_str(), getDefaultSavePath().c_str()); + ::WritePrivateProfileString(L"Default", key, std::to_wstring(value).c_str(), getDefaultSavePath().c_str()); } -void e2d::EFileUtils::saveString(LPCTSTR key, EString value) +void e2d::EFileUtils::saveString(LPCTSTR key, LPCTSTR value) { - ::WritePrivateProfileString(L"Default", key, value.c_str(), getDefaultSavePath().c_str()); + ::WritePrivateProfileString(L"Default", key, value, getDefaultSavePath().c_str()); } int e2d::EFileUtils::getInt(LPCTSTR key, int default) @@ -75,25 +71,17 @@ int e2d::EFileUtils::getInt(LPCTSTR key, int default) return ::GetPrivateProfileInt(L"Default", key, default, getDefaultSavePath().c_str()); } -double e2d::EFileUtils::getDouble(LPCTSTR key, double default) +float e2d::EFileUtils::getFloat(LPCTSTR key, float default) { - // 将 default 参数转化为字符串 - std::wstringstream ss; - ss << default; - // 读取数据 - TCHAR temp[128] = { 0 }; - ::GetPrivateProfileString(L"Default", key, ss.str().c_str(), temp, 128, getDefaultSavePath().c_str()); - // 转换为字符串流 - ss.str(L""); - ss << temp; - // 将字符串转化为 double - return _wtof(ss.str().c_str()); + TCHAR temp[32] = { 0 }; + ::GetPrivateProfileString(L"Default", key, std::to_wstring(default).c_str(), temp, 31, getDefaultSavePath().c_str()); + return std::stof(temp); } -e2d::EString e2d::EFileUtils::geTString(LPCTSTR key, EString default) +e2d::EString e2d::EFileUtils::geTString(LPCTSTR key, LPCTSTR default) { - TCHAR temp[128] = { 0 }; - ::GetPrivateProfileString(L"Default", key, default.c_str(), temp, 128, getDefaultSavePath().c_str()); + TCHAR temp[256] = { 0 }; + ::GetPrivateProfileString(L"Default", key, default, temp, 255, getDefaultSavePath().c_str()); return EString(temp); } diff --git a/Easy2D/Tool/EMusicUtils.cpp b/Easy2D/Tool/EMusicUtils.cpp index 86aab8f7..a8b85517 100644 --- a/Easy2D/Tool/EMusicUtils.cpp +++ b/Easy2D/Tool/EMusicUtils.cpp @@ -1 +1,510 @@ #include "..\etools.h" +#include "..\Win\winbase.h" +#include +#pragma comment(lib , "winmm.lib") + +#include +#include + + +//////////////////////////////////////////////////////////////////// +// MciPlayer +//////////////////////////////////////////////////////////////////// + +class MciPlayer +{ +public: + MciPlayer(); + ~MciPlayer(); + + void close(); + void open(const e2d::EString & pFileName, UINT uId); + void open(const e2d::EString & pResouceName, const e2d::EString & pResouceType, const e2d::EString & musicExtension, UINT uId); + void play(bool bLoop = false); + void pause(); + void resume(); + void stop(); + void rewind(); + void setVolume(float volume); + bool isPlaying(); + UINT getSoundID(); + +private: + void _sendCommand(int nCommand, DWORD_PTR param1 = 0, DWORD_PTR parma2 = 0); + + MCIDEVICEID m_dev; + UINT m_nSoundID; + bool m_bPlaying; + bool m_bLoop; + e2d::EString m_sTmpFileName; +}; + + +MciPlayer::MciPlayer() : + m_dev(0L), + m_nSoundID(0), + m_bPlaying(false), + m_bLoop(false) +{ +} + +MciPlayer::~MciPlayer() +{ + close(); // 关闭播放器 +} + +void MciPlayer::open(const e2d::EString & pFileName, UINT uId) +{ + // 忽略不存在的文件 + if (pFileName.empty()) return; + // 停止当前音乐 + close(); + + // 设置 MCI_OPEN_PARMS 参数 + MCI_OPEN_PARMS mciOpen = { 0 }; + mciOpen.lpstrDeviceType = (LPCTSTR)-1; + mciOpen.lpstrElementName = pFileName.c_str(); + + // 打开这个文件 + MCIERROR mciError; + mciError = mciSendCommand(0, MCI_OPEN, MCI_OPEN_ELEMENT, reinterpret_cast(&mciOpen)); + // 出现错误时,忽略这次操作 + if (mciError) return; + + // 保存设备等信息 + m_dev = mciOpen.wDeviceID; + m_nSoundID = uId; + m_bPlaying = false; +} + +void MciPlayer::open(const e2d::EString & pResouceName, const e2d::EString & pResouceType, const e2d::EString & musicExtension, UINT uId) +{ + bool ExtractResource(LPCTSTR strDstFile, LPCTSTR strResType, LPCTSTR strResName); + + // 忽略不存在的文件 + if (pResouceName.empty() || pResouceType.empty()) return; + + // 获取临时文件目录 + TCHAR tmpFilePath[_MAX_PATH]; + ::GetTempPath(_MAX_PATH, tmpFilePath); + + // 创建临时文件目录 + e2d::EString tmpFileName = tmpFilePath + e2d::EApp::getAppName(); + if (_waccess(tmpFileName.c_str(), 0) == -1) + { + _wmkdir(tmpFileName.c_str()); + } + + // 产生临时文件的文件名 + tmpFileName.append(L"\\"); + tmpFileName.append(std::to_wstring(uId)); + tmpFileName.append(L"." + musicExtension); + + // 导出资源为临时文件 + if (ExtractResource(tmpFileName.c_str(), pResouceType.c_str(), pResouceName.c_str())) + { + // 停止当前音乐 + close(); + + // 设置 MCI_OPEN_PARMS 参数 + MCI_OPEN_PARMS mciOpen = { 0 }; + mciOpen.lpstrDeviceType = (LPCTSTR)-1; + mciOpen.lpstrElementName = tmpFileName.c_str(); + + // 打开这个文件 + MCIERROR mciError; + mciError = mciSendCommand(0, MCI_OPEN, MCI_OPEN_ELEMENT, reinterpret_cast(&mciOpen)); + // 出现错误时,忽略这次操作 + if (mciError) return; + + // 保存设备等信息 + m_dev = mciOpen.wDeviceID; + m_nSoundID = uId; + m_bPlaying = false; + m_sTmpFileName = tmpFileName; + } +} + +void MciPlayer::play(bool bLoop) +{ + // 设备为空时,忽略这次操作 + if (!m_dev) + { + return; + } + // 设置播放参数 + MCI_PLAY_PARMS mciPlay = { 0 }; + MCIERROR s_mciError; + // 播放声音 + s_mciError = mciSendCommand(m_dev, MCI_PLAY, MCI_FROM | (bLoop ? MCI_DGV_PLAY_REPEAT : 0), reinterpret_cast(&mciPlay)); + // 未出错时,置 m_bPlaying 为 true + if (!s_mciError) + { + m_bPlaying = true; + m_bLoop = bLoop; + } +} + +void MciPlayer::close() +{ + // 停止音乐 + if (m_bPlaying) + { + stop(); + } + // 关闭设备 + if (m_dev) + { + _sendCommand(MCI_CLOSE); + } + // 删除临时文件 + if (!m_sTmpFileName.empty()) + { + DeleteFile(m_sTmpFileName.c_str()); + m_sTmpFileName.clear(); + } + // 恢复默认属性 + 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 }; + m_bPlaying = mciSendCommand(m_dev, MCI_PLAY, (m_bLoop ? MCI_DGV_PLAY_REPEAT : 0), reinterpret_cast(&mciPlay)) ? false : true; +} + +void MciPlayer::setVolume(float volume) +{ + MCI_DGV_SETAUDIO_PARMS mciSetAudioPara = { 0 }; + mciSetAudioPara.dwItem = MCI_DGV_SETAUDIO_VOLUME; + mciSetAudioPara.dwValue = DWORD(1000 * min(max(volume, 0), 1)); + mciSendCommand(m_dev, MCI_SETAUDIO, MCI_DGV_SETAUDIO_VALUE | MCI_DGV_SETAUDIO_ITEM, (DWORD_PTR)&mciSetAudioPara); +} + +bool MciPlayer::isPlaying() +{ + return m_bPlaying; +} + +UINT MciPlayer::getSoundID() +{ + return m_nSoundID; +} + +void MciPlayer::_sendCommand(int nCommand, DWORD_PTR param1, DWORD_PTR parma2) +{ + // 空设备时忽略这次操作 + if (!m_dev) + { + return; + } + // 向当前设备发送操作 + mciSendCommand(m_dev, nCommand, param1, parma2); +} + + + + +//////////////////////////////////////////////////////////////////// +// e2d::EMusicUtils +//////////////////////////////////////////////////////////////////// + + +typedef std::map MusicList; +typedef std::pair Music; + +static size_t Hash(const e2d::EString & key); + + +static MusicList& getMciPlayerList() +{ + static MusicList s_List; + return s_List; +} + +static MciPlayer& getBgMciPlayer() +{ + static MciPlayer s_Music; + return s_Music; +} + +void e2d::EMusicUtils::end() +{ + // 停止背景音乐 + getBgMciPlayer().close(); + // 停止其他所有音乐 + for (auto& iter : getMciPlayerList()) + { + SafeDelete(&iter.second); + } + // 清空音乐列表 + getMciPlayerList().clear(); + return; +} + +void e2d::EMusicUtils::setVolume(float volume) +{ + // 设置背景音乐音量 + getBgMciPlayer().setVolume(volume); + // 设置其他音乐音量 + for (auto& iter : getMciPlayerList()) + { + iter.second->setVolume(volume); + } +} + +void e2d::EMusicUtils::setVolume(const EString & musicFilePath, float volume) +{ + unsigned int nRet = ::Hash(musicFilePath); + + MusicList::iterator p = getMciPlayerList().find(nRet); + if (p != getMciPlayerList().end()) + { + p->second->setVolume(volume); + } +} + +void e2d::EMusicUtils::playBackgroundMusic(const EString & musicFilePath, bool bLoop) +{ + if (musicFilePath.empty()) + { + return; + } + + getBgMciPlayer().open(musicFilePath, ::Hash(musicFilePath)); + getBgMciPlayer().play(bLoop); +} + +void e2d::EMusicUtils::playBackgroundMusic(const EString & musicResourceName, const EString & musicResourceType, const EString & musicExtension, bool loop) +{ + if (musicResourceName.empty() || musicResourceType.empty()) + { + return; + } + + getBgMciPlayer().open(musicResourceName, musicResourceType, musicExtension, ::Hash(musicResourceName)); + getBgMciPlayer().play(loop); +} + +void e2d::EMusicUtils::stopBackgroundMusic(bool bReleaseData) +{ + if (bReleaseData) + { + getBgMciPlayer().close(); + } + else + { + getBgMciPlayer().stop(); + } +} + +void e2d::EMusicUtils::pauseBackgroundMusic() +{ + getBgMciPlayer().pause(); +} + +void e2d::EMusicUtils::resumeBackgroundMusic() +{ + getBgMciPlayer().resume(); +} + +void e2d::EMusicUtils::rewindBackgroundMusic() +{ + getBgMciPlayer().rewind(); +} + +bool e2d::EMusicUtils::isBackgroundMusicPlaying() +{ + return getBgMciPlayer().isPlaying(); +} + +void e2d::EMusicUtils::setBackgroundMusicVolume(float volume) +{ + getBgMciPlayer().setVolume(volume); +} + +void e2d::EMusicUtils::playMusic(const EString & musicFilePath, bool bLoop) +{ + unsigned int nRet = ::Hash(musicFilePath); + + preloadMusic(musicFilePath); + + MusicList::iterator p = getMciPlayerList().find(nRet); + if (p != getMciPlayerList().end()) + { + p->second->play(bLoop); + } +} + +void e2d::EMusicUtils::playMusic(const EString & musicResourceName, const EString & musicResourceType, const EString & musicExtension, bool loop) +{ + unsigned int nRet = ::Hash(musicResourceName); + + preloadMusic(musicResourceName, musicResourceType, musicExtension); + + MusicList::iterator p = getMciPlayerList().find(nRet); + if (p != getMciPlayerList().end()) + { + p->second->play(loop); + } +} + +void e2d::EMusicUtils::_stopMusic(size_t nSoundId) +{ + MusicList::iterator p = getMciPlayerList().find(nSoundId); + if (p != getMciPlayerList().end()) + { + p->second->stop(); + } +} + +void e2d::EMusicUtils::preloadMusic(const EString & musicFilePath) +{ + if (musicFilePath.empty()) return; + + int nRet = ::Hash(musicFilePath); + + if (getMciPlayerList().end() != getMciPlayerList().find(nRet)) return; + + getMciPlayerList().insert(Music(nRet, new MciPlayer())); + MciPlayer * pPlayer = getMciPlayerList()[nRet]; + pPlayer->open(musicFilePath, nRet); + + if (nRet == pPlayer->getSoundID()) return; + + delete pPlayer; + getMciPlayerList().erase(nRet); + nRet = 0; +} + +void e2d::EMusicUtils::preloadMusic(const EString & musicResourceName, const EString & musicResourceType, const EString & musicExtension) +{ + if (musicResourceName.empty() || musicResourceType.empty()) return; + + int nRet = ::Hash(musicResourceName); + + if (getMciPlayerList().end() != getMciPlayerList().find(nRet)) return; + + getMciPlayerList().insert(Music(nRet, new MciPlayer())); + MciPlayer * pPlayer = getMciPlayerList()[nRet]; + pPlayer->open(musicResourceName, musicResourceType, musicExtension, nRet); + + if (nRet == pPlayer->getSoundID()) return; + + delete pPlayer; + getMciPlayerList().erase(nRet); + nRet = 0; +} + +void e2d::EMusicUtils::_pauseMusic(size_t nSoundId) +{ + MusicList::iterator p = getMciPlayerList().find(nSoundId); + if (p != getMciPlayerList().end()) + { + p->second->pause(); + } +} + +void e2d::EMusicUtils::pauseAllMusics() +{ + for (auto& iter : getMciPlayerList()) + { + iter.second->pause(); + } +} + +void e2d::EMusicUtils::_resumeMusic(size_t nSoundId) +{ + MusicList::iterator p = getMciPlayerList().find(nSoundId); + if (p != getMciPlayerList().end()) + { + p->second->resume(); + } +} + +void e2d::EMusicUtils::resumeAllMusics() +{ + for (auto& iter : getMciPlayerList()) + { + iter.second->resume(); + } +} + +void e2d::EMusicUtils::stopAllMusics() +{ + for (auto& iter : getMciPlayerList()) + { + iter.second->stop(); + } +} + +void e2d::EMusicUtils::unloadMusic(const EString & musicFilePath) +{ + unsigned int nID = ::Hash(musicFilePath); + + MusicList::iterator p = getMciPlayerList().find(nID); + if (p != getMciPlayerList().end()) + { + SafeDelete(&p->second); + getMciPlayerList().erase(nID); + } +} + + + + +size_t Hash(const e2d::EString & key) +{ + static std::hash h; + return h(key); +} + +bool ExtractResource(LPCTSTR strDstFile, LPCTSTR strResType, LPCTSTR strResName) +{ + // 创建文件 + HANDLE hFile = ::CreateFile(strDstFile, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL); + if (hFile == INVALID_HANDLE_VALUE) + return false; + + // 查找资源文件中、加载资源到内存、得到资源大小 + HRSRC hRes = ::FindResource(NULL, strResName, strResType); + HGLOBAL hMem = ::LoadResource(NULL, hRes); + DWORD dwSize = ::SizeofResource(NULL, hRes); + + // 写入文件 + DWORD dwWrite = 0; // 返回写入字节 + ::WriteFile(hFile, hMem, dwSize, &dwWrite, NULL); + ::CloseHandle(hFile); + + return true; +} \ No newline at end of file diff --git a/Easy2D/etools.h b/Easy2D/etools.h index 89685f10..e0ce187f 100644 --- a/Easy2D/etools.h +++ b/Easy2D/etools.h @@ -269,31 +269,54 @@ public: static EString getDefaultSavePath(); // 保存 int 型的值 - static void saveInt(LPCTSTR key, int value); + static void saveInt( + LPCTSTR key, + int value + ); - // 保存 double 型的值 - static void saveDouble(LPCTSTR key, double value); + // 保存 float 型的值 + static void saveFloat( + LPCTSTR key, + float value + ); // 保存 字符串 型的值(不要在 Unicode 字符集下保存中文字符) - static void saveString(LPCTSTR key, EString value); + static void saveString( + LPCTSTR key, + LPCTSTR value + ); // 获取 int 型的值(若不存在则返回 default 参数的值) - static int getInt(LPCTSTR key, int default); + static int getInt( + LPCTSTR key, + int default + ); - // 获取 double 型的值(若不存在则返回 default 参数的值) - static double getDouble(LPCTSTR key, double default); + // 获取 float 型的值(若不存在则返回 default 参数的值) + static float getFloat( + LPCTSTR key, + float default + ); // 获取 字符串 型的值(若不存在则返回 default 参数的值) - static EString geTString(LPCTSTR key, EString default); + static EString geTString( + LPCTSTR key, + LPCTSTR default + ); // 得到文件扩展名(小写) - static EString getFileExtension(const EString & filePath); + static EString getFileExtension( + const EString & filePath + ); /** * 打开保存文件对话框,得到有效保存路径返回 true * 参数:返回文件路径的字符串,窗口标题,设置扩展名过滤,设置默认扩展名 */ - static EString getSaveFilePath(LPCTSTR title = L"保存到", LPCTSTR defExt = NULL); + static EString getSaveFilePath( + LPCTSTR title = L"保存到", + LPCTSTR defExt = NULL + ); }; @@ -337,4 +360,115 @@ public: static std::default_random_engine &getEngine(); }; + +class EMusicUtils +{ +public: + // 播放背景音乐 + static void playBackgroundMusic( + const EString & musicFilePath, + bool loop = true + ); + + // 播放背景音乐 + static void playBackgroundMusic( + const EString & musicResourceName, /* 资源名称 */ + const EString & musicResourceType, /* 资源类别 */ + const EString & musicExtension, /* 指定资源的扩展名 */ + bool loop = true + ); + + // 停止背景音乐 + static void stopBackgroundMusic( + bool release = false + ); + + // 暂停背景音乐 + static void pauseBackgroundMusic(); + + // 继续播放背景音乐 + static void resumeBackgroundMusic(); + + // 从头播放背景音乐 + static void rewindBackgroundMusic(); + + // 背景音乐是否正在播放 + static bool isBackgroundMusicPlaying(); + + // 设置背景音乐音量,范围 [0 ~ 1.0] + static void setBackgroundMusicVolume( + float volume + ); + + // 播放音效 + static void playMusic( + const EString & musicFilePath, + bool loop = false + ); + + // 播放音效 + static void playMusic( + const EString & musicResourceName, /* 资源名称 */ + const EString & musicResourceType, /* 资源类别 */ + const EString & musicExtension, /* 指定资源的扩展名 */ + bool loop = false + ); + + // 预加载音效 + static void preloadMusic( + const EString & musicFilePath + ); + + // 预加载音效 + static void preloadMusic( + const EString & musicResourceName, /* 资源名称 */ + const EString & musicResourceType, /* 资源类别 */ + const EString & musicExtension /* 指定资源的扩展名 */ + ); + + // 卸载音效 + static void unloadMusic( + const EString & musicFilePath + ); + + // 设置特定音乐的音量,范围 [0 ~ 1.0] + static void setVolume( + const EString & musicFilePath, + float volume + ); + + // 暂停所有音乐 + static void pauseAllMusics(); + + // 继续播放所有音乐 + static void resumeAllMusics(); + + // 停止所有音乐 + static void stopAllMusics(); + + // 停止所有音乐,并释放内存 + static void end(); + + // 设置总音量,范围 [0 ~ 1.0] + static void setVolume( + float volume + ); + +protected: + // 暂停音效 + static void _pauseMusic( + size_t nSoundId + ); + + // 继续播放音效 + static void _resumeMusic( + size_t nSoundId + ); + + // 停止音效 + static void _stopMusic( + size_t nSoundId + ); +}; + } \ No newline at end of file