From 73521c7f980117233633d8ccd6b0afd8d7fce6d6 Mon Sep 17 00:00:00 2001 From: LoRd_MuldeR Date: Fri, 5 Dec 2014 21:07:06 +0100 Subject: [PATCH] Moved all the Sound-specific functions into MUtilities library. --- MUtilities_VS2013.vcxproj | 6 +- MUtilities_VS2013.vcxproj.filters | 6 ++ include/MUtils/Global.h | 4 + include/MUtils/Sound.h | 54 +++++++++++ src/Global.cpp | 52 +++++++++++ src/Sound_Win32.cpp | 148 ++++++++++++++++++++++++++++++ 6 files changed, 268 insertions(+), 2 deletions(-) create mode 100644 include/MUtils/Sound.h create mode 100644 src/Sound_Win32.cpp diff --git a/MUtilities_VS2013.vcxproj b/MUtilities_VS2013.vcxproj index 4c86384..16a7da4 100644 --- a/MUtilities_VS2013.vcxproj +++ b/MUtilities_VS2013.vcxproj @@ -25,6 +25,7 @@ + @@ -38,6 +39,7 @@ + @@ -143,7 +145,7 @@ Windows true $(QTDIR)\lib;$(SolutionDir)\..\Prerequisites\VisualLeakDetector\lib\Win32 - QtCored4.lib;QtGuid4.lib;Psapi.lib;Sensapi.lib;PowrProf.lib;%(AdditionalDependencies) + QtCored4.lib;QtGuid4.lib;Winmm.lib;Psapi.lib;Sensapi.lib;PowrProf.lib;%(AdditionalDependencies) @@ -172,7 +174,7 @@ true true $(QTDIR)\lib;$(SolutionDir)\..\Prerequisites\VisualLeakDetector\lib\Win32 - QtCore4.lib;QtGui4.lib;Psapi.lib;Sensapi.lib;PowrProf.lib;%(AdditionalDependencies) + QtCore4.lib;QtGui4.lib;Winmm.lib;Psapi.lib;Sensapi.lib;PowrProf.lib;%(AdditionalDependencies) false diff --git a/MUtilities_VS2013.vcxproj.filters b/MUtilities_VS2013.vcxproj.filters index 17a0908..d4318a0 100644 --- a/MUtilities_VS2013.vcxproj.filters +++ b/MUtilities_VS2013.vcxproj.filters @@ -69,6 +69,9 @@ Source Files\Generated + + Source Files + @@ -116,6 +119,9 @@ Header Files\3rd Party + + Public Headers + diff --git a/include/MUtils/Global.h b/include/MUtils/Global.h index 16029ca..07750a7 100644 --- a/include/MUtils/Global.h +++ b/include/MUtils/Global.h @@ -91,6 +91,10 @@ namespace MUtils //String sorting MUTILS_API void natural_string_sort(QStringList &list, const bool bIgnoreCase); + //Clean file path + MUTILS_API QString clean_file_name(const QString &name); + MUTILS_API QString clean_file_path(const QString &path); + //Internal namespace Internal { diff --git a/include/MUtils/Sound.h b/include/MUtils/Sound.h new file mode 100644 index 0000000..7895d11 --- /dev/null +++ b/include/MUtils/Sound.h @@ -0,0 +1,54 @@ +/////////////////////////////////////////////////////////////////////////////// +// MuldeR's Utilities for Qt +// Copyright (C) 2004-2014 LoRd_MuldeR +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// http://www.gnu.org/licenses/lgpl-2.1.txt +////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +//MUtils +#include + +/////////////////////////////////////////////////////////////////////////////// + +namespace MUtils +{ + namespace Sound + { + enum beep_t + { + BEEP_NFO = 0, + BEEP_WRN = 1, + BEEP_ERR = 2 + }; + + //Simple beep + MUTILS_API bool beep(beep_t beepType); + + //Play built-in sound by name + MUTILS_API bool play_sound(const QString &name, const bool bAsync); + + //Play system sound by name + MUTILS_API bool play_system_sound(const QString &alias, const bool bAsync); + + //Play sound from file + MUTILS_API bool play_sound_file(const QString &library, const unsigned short uiSoundIdx); + } +} + +/////////////////////////////////////////////////////////////////////////////// diff --git a/src/Global.cpp b/src/Global.cpp index 7206d77..984b56d 100644 --- a/src/Global.cpp +++ b/src/Global.cpp @@ -326,6 +326,58 @@ void MUtils::natural_string_sort(QStringList &list, const bool bIgnoreCase) qSort(list.begin(), list.end(), bIgnoreCase ? natural_string_sort_helper_fold_case : natural_string_sort_helper); } +/////////////////////////////////////////////////////////////////////////////// +// CLEAN FILE PATH +/////////////////////////////////////////////////////////////////////////////// + +static const struct +{ + const char *const search; + const char *const replace; +} +CLEAN_FILE_NAME[] = +{ + { "\\", "-" }, + { " / ", ", " }, + { "/", "," }, + { ":", "-" }, + { "*", "x" }, + { "?", "!" }, + { "<", "[" }, + { ">", "]" }, + { "|", "!" }, + { "\"", "'" }, + { NULL, NULL } +}; + +QString MUtils::clean_file_name(const QString &name) +{ + QString str = name.simplified(); + + for(size_t i = 0; CLEAN_FILE_NAME[i].search; i++) + { + str.replace(CLEAN_FILE_NAME[i].search, CLEAN_FILE_NAME[i].replace); + } + + QRegExp regExp("\"(.+)\""); + regExp.setMinimal(true); + str.replace(regExp, "`\\1´"); + + return str.simplified(); +} + +QString MUtils::clean_file_path(const QString &path) +{ + QStringList parts = path.simplified().replace("\\", "/").split("/", QString::SkipEmptyParts); + + for(int i = 0; i < parts.count(); i++) + { + parts[i] = MUtils::clean_file_name(parts[i]); + } + + return parts.join("/"); +} + /////////////////////////////////////////////////////////////////////////////// // SELF-TEST /////////////////////////////////////////////////////////////////////////////// diff --git a/src/Sound_Win32.cpp b/src/Sound_Win32.cpp new file mode 100644 index 0000000..ba6b798 --- /dev/null +++ b/src/Sound_Win32.cpp @@ -0,0 +1,148 @@ +/////////////////////////////////////////////////////////////////////////////// +// MuldeR's Utilities for Qt +// Copyright (C) 2004-2014 LoRd_MuldeR +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// http://www.gnu.org/licenses/lgpl-2.1.txt +////////////////////////////////////////////////////////////////////////////////// + +//Win32 API +#define WIN32_LEAN_AND_MEAN 1 +#include +#include + +//MUtils +#include +#include + +//Qt +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////////// +// BEEP +/////////////////////////////////////////////////////////////////////////////// + +bool MUtils::Sound::beep(MUtils::Sound::beep_t beepType) +{ + switch(beepType) + { + case BEEP_NFO: return MessageBeep(MB_ICONASTERISK) == TRUE; break; + case BEEP_WRN: return MessageBeep(MB_ICONEXCLAMATION) == TRUE; break; + case BEEP_ERR: return MessageBeep(MB_ICONHAND) == TRUE; break; + default: return false; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// PLAY SOUND +/////////////////////////////////////////////////////////////////////////////// + +typedef QHash SoundDB; + +static QReadWriteLock g_sound_lock; +static QScopedPointer g_sound_db; + +static const unsigned char *get_sound_from_cache(const QString &name) +{ + //Try to look-up the sound in the cache first + QReadLocker readLock(&g_sound_lock); + if((!g_sound_db.isNull()) && g_sound_db->contains(name)) + { + return g_sound_db->value(name); + } + + //Get the write lock now + readLock.unlock(); + QWriteLocker writeLock(&g_sound_lock); + + //Is sound still not in cache? + if((!g_sound_db.isNull()) && g_sound_db->contains(name)) + { + return g_sound_db->value(name); + } + + //If data not found in cache, try to load from resource! + QResource resource(QString(":/sounds/%1.wav").arg(name)); + if(resource.isValid()) + { + if(const unsigned char *data = resource.data()) + { + if(g_sound_db.isNull()) + { + g_sound_db.reset(new SoundDB()); + } + g_sound_db->insert(name, data); + return data; + } + } + + qWarning("Sound effect \"%s\" not found!", MUTILS_UTF8(name)); + return NULL; +} + +bool MUtils::Sound::play_sound(const QString &name, const bool bAsync) +{ + if(!name.isEmpty()) + { + if(const unsigned char *data = get_sound_from_cache(name)) + { + return PlaySound(LPCWSTR(data), NULL, (SND_MEMORY | (bAsync ? SND_ASYNC : SND_SYNC))) != FALSE; + } + } + + return false; +} + +bool MUtils::Sound::play_system_sound(const QString &alias, const bool bAsync) +{ + return PlaySound(MUTILS_WCHR(alias), GetModuleHandle(NULL), (SND_ALIAS | (bAsync ? SND_ASYNC : SND_SYNC))) != FALSE; +} + +bool MUtils::Sound::play_sound_file(const QString &library, const unsigned short uiSoundIdx) +{ + bool result = false; + + QFileInfo libraryFile(library); + if(!libraryFile.isAbsolute()) + { + const QString &systemDir = MUtils::OS::known_folder(MUtils::OS::FOLDER_SYSTEMFOLDER); + if(!systemDir.isEmpty()) + { + libraryFile.setFile(QDir(systemDir), libraryFile.fileName()); + } + } + + if(libraryFile.exists() && libraryFile.isFile()) + { + if(const HMODULE module = LoadLibraryW(MUTILS_WCHR(QDir::toNativeSeparators(libraryFile.canonicalFilePath())))) + { + result = (PlaySound(MAKEINTRESOURCE(uiSoundIdx), module, (SND_RESOURCE | SND_SYNC)) != FALSE); + FreeLibrary(module); + } + } + else + { + qWarning("PlaySound: File \"%s\" could not be found!", MUTILS_UTF8(libraryFile.absoluteFilePath())); + } + + return result; +} + +///////////////////////////////////////////////////////////////////////////////