OSDN Git Service

Bump version.
[mutilities/MUtilities.git] / src / Sound_Win32.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // MuldeR's Utilities for Qt
3 // Copyright (C) 2004-2019 LoRd_MuldeR <MuldeR2@GMX.de>
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18 //
19 // http://www.gnu.org/licenses/lgpl-2.1.txt
20 //////////////////////////////////////////////////////////////////////////////////
21
22 //Win32 API
23 #define WIN32_LEAN_AND_MEAN 1
24 #include <Windows.h>
25 #include <MMSystem.h>
26
27 //MUtils
28 #include <MUtils/Sound.h>
29 #include <MUtils/OSSupport.h>
30
31 //Qt
32 #include <QReadWriteLock>
33 #include <QHash>
34 #include <QResource>
35 #include <QFileInfo>
36 #include <QDir>
37
38 ///////////////////////////////////////////////////////////////////////////////
39 // BEEP
40 ///////////////////////////////////////////////////////////////////////////////
41
42 bool MUtils::Sound::beep(const MUtils::Sound::beep_t &beepType)
43 {
44         switch(beepType)
45         {
46                 case BEEP_NFO: return MessageBeep(MB_ICONASTERISK)    == TRUE; break;
47                 case BEEP_WRN: return MessageBeep(MB_ICONEXCLAMATION) == TRUE; break;
48                 case BEEP_ERR: return MessageBeep(MB_ICONHAND)        == TRUE; break;
49                 default: return false;
50         }
51 }
52
53 ///////////////////////////////////////////////////////////////////////////////
54 // PLAY SOUND
55 ///////////////////////////////////////////////////////////////////////////////
56
57 typedef QHash<const QString, const unsigned char*> SoundDB;
58
59 static QReadWriteLock g_sound_lock;
60 static QScopedPointer<SoundDB> g_sound_db;
61
62 static const unsigned char *get_sound_from_cache(const QString &name)
63 {
64         //Try to look-up the sound in the cache first
65         QReadLocker readLock(&g_sound_lock);
66         if((!g_sound_db.isNull()) && g_sound_db->contains(name))
67         {
68                 return g_sound_db->value(name);
69         }
70
71         //Get the write lock now
72         readLock.unlock();
73         QWriteLocker writeLock(&g_sound_lock);
74
75         //Is sound still not in cache?
76         if((!g_sound_db.isNull()) && g_sound_db->contains(name))
77         {
78                 return g_sound_db->value(name);
79         }
80
81         //If data not found in cache, try to load from resource!
82         QResource resource(QString(":/sounds/%1.wav").arg(name));
83         if(resource.isValid())
84         {
85                 if(const unsigned char *data = resource.data())
86                 {
87                         if(g_sound_db.isNull())
88                         {
89                                 g_sound_db.reset(new SoundDB());
90                         }
91                         g_sound_db->insert(name, data);
92                         return data;
93                 }
94         }
95
96         qWarning("Sound effect \"%s\" not found!", MUTILS_UTF8(name));
97         return NULL;
98 }
99
100 bool MUtils::Sound::play_sound(const QString &name, const bool &bAsync)
101 {
102         if(!name.isEmpty())
103         {
104                 if(const unsigned char *data = get_sound_from_cache(name))
105                 {
106                         return PlaySound(LPCWSTR(data), NULL, (SND_MEMORY | (bAsync ? SND_ASYNC : SND_SYNC))) != FALSE;
107                 }
108         }
109         
110         return false;
111 }
112
113 bool MUtils::Sound::play_system_sound(const QString &alias, const bool &bAsync)
114 {
115         return PlaySound(MUTILS_WCHR(alias), GetModuleHandle(NULL), (SND_ALIAS | (bAsync ? SND_ASYNC : SND_SYNC))) != FALSE;
116 }
117
118 bool MUtils::Sound::play_sound_file(const QString &library, const unsigned short uiSoundIdx, const bool &bAsync)
119 {
120         bool result = false;
121
122         QFileInfo libraryFile(library);
123         if(!libraryFile.isAbsolute())
124         {
125                 const QString &systemDir = MUtils::OS::known_folder(MUtils::OS::FOLDER_SYSTEM_DEF);
126                 if(!systemDir.isEmpty())
127                 {
128                         libraryFile.setFile(QDir(systemDir), libraryFile.fileName());
129                 }
130         }
131
132         if(libraryFile.exists() && libraryFile.isFile())
133         {
134                 if(const HMODULE module = GetModuleHandleW(MUTILS_WCHR(QDir::toNativeSeparators(libraryFile.canonicalFilePath()))))
135                 {
136                         result = (PlaySound(MAKEINTRESOURCE(uiSoundIdx), module, (SND_RESOURCE | (bAsync ? SND_ASYNC : SND_SYNC))) != FALSE);
137                 }
138                 else if(const HMODULE module = LoadLibraryW(MUTILS_WCHR(QDir::toNativeSeparators(libraryFile.canonicalFilePath()))))
139                 {
140                         result = (PlaySound(MAKEINTRESOURCE(uiSoundIdx), module, (SND_RESOURCE | (bAsync ? SND_ASYNC : SND_SYNC))) != FALSE);
141                         FreeLibrary(module);
142                 }
143         }
144         else
145         {
146                 qWarning("PlaySound: File \"%s\" could not be found!", MUTILS_UTF8(libraryFile.absoluteFilePath()));
147         }
148
149         return result;
150 }
151
152 ///////////////////////////////////////////////////////////////////////////////