Develop and Download Open Source Software

Browse Subversion Repository

Contents of /sound/MusicManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 365 - (show annotations) (download) (as text)
Tue Apr 22 21:52:39 2008 UTC (15 years, 11 months ago) by satofumi
File MIME type: text/x-c++src
File size: 7675 byte(s)
fix nowPlaying
1 /*!
2 \file
3 \brief ”wŒi‹Č‚ĚŠÇ—
4
5 \author Satofumi KAMIMURA
6
7 $Id$
8 */
9
10 #include "MusicManager.h"
11 #include "MixerInit.h"
12 #include "ThreadCreator.h"
13 #include "LockGuard.h"
14 #include "ExistFile.h"
15 #include "Delay.h"
16 #include <SDL_mixer.h>
17 #include <string>
18 #include <deque>
19 #include <map>
20
21 using namespace beego;
22
23
24 struct MusicManager::pImpl : private MixerInit {
25
26 bool initialized;
27 size_t fade_in_msec;
28 size_t fade_out_msec;
29 static bool now_playing;
30 int current_music_id;
31
32 class MusicInfo {
33 public:
34 std::string file_path;
35 Mix_Music* music;
36
37 MusicInfo(void) : file_path(""), music(NULL) {
38 }
39 };
40 typedef std::map<int,MusicInfo> MusicMap;
41 MusicMap music_map;
42
43 SDL_mutex* mutex;
44
45 class ChangeOrder {
46 public:
47 int next_music_id;
48 int play_times;
49
50 ChangeOrder(int next_id, int times)
51 : next_music_id(next_id), play_times(times) {
52 }
53 };
54 typedef std::deque<ChangeOrder> ChangeOrderList;
55 ChangeOrderList change_order;
56
57 class ThreadArgs {
58 public:
59 pImpl* own_obj;
60 ThreadArgs(pImpl* obj) : own_obj(obj) {
61 }
62 };
63 ThreadArgs thread_args;
64 ThreadCreator thread;
65
66 pImpl(void) : initialized(false), fade_in_msec(0), fade_out_msec(0),
67 current_music_id(0), mutex(SDL_CreateMutex()),
68 thread_args(this), thread(change_thread, &thread_args) {
69
70 if (! isInitialized()) {
71 return;
72 }
73 initialized = true;
74 }
75
76 ~pImpl(void) {
77
78 // ÄśƒXƒŒƒbƒh‚ĚŠŽ—š‘Ň‚ż
79 thread.wait();
80
81 // ‰šŠyŽ‘Œš‚̉đ•ú
82 // !!! freeMusResource() ‚đŽg‚¤‚悤‚É•ĎX‚ˇ‚ׂŤ‚Š‚ŕ
83 for (MusicMap::iterator it = music_map.begin();
84 it != music_map.end(); ++it) {
85 if (it->second.music) {
86 Mix_FreeMusic(it->second.music);
87 }
88 }
89
90 // ƒXƒŒƒbƒh‚̏I—š‘Ň‚ż
91 thread.wait();
92
93 SDL_DestroyMutex(mutex);
94 }
95
96 static pImpl* getObject(void) {
97 static pImpl obj;
98 return &obj;
99 }
100
101 static int change_thread(void* args) {
102 ThreadArgs* info = static_cast<ThreadArgs*>(args);
103 SDL_mutex* mutex = info->own_obj->mutex;
104 ChangeOrderList& change_order = info->own_obj->change_order;
105 MusicMap& music_map = info->own_obj->music_map;
106 size_t& fade_in_msec = info->own_obj->fade_in_msec;
107 size_t& fade_out_msec = info->own_obj->fade_out_msec;
108 bool& now_playing = info->own_obj->now_playing;
109 int& current_music_id = info->own_obj->current_music_id;
110
111 while (true) {
112 LockMutex(mutex);
113 if (change_order.empty()) {
114 UnlockMutex(mutex);
115 return 0;
116 }
117
118 // Žw—߂̎󂯎ć‚čBĹŒă‚ĚŽw—ß‚Ě‚Ýˆľ‚¤
119 ChangeOrder order = change_order.back();
120 int play_times = order.play_times;
121 int next_music_id = order.next_music_id;
122 change_order.clear();
123
124 pImpl::MusicMap::iterator p;
125 if (play_times != 0) {
126 p = music_map.find(next_music_id);
127 if (p == music_map.end()) {
128 // ‹Č‚ŞŒŠ‚Â‚Š‚ç‚Č‚˘
129 // !!! ƒGƒ‰[o—Í
130 now_playing = false;
131 UnlockMutex(mutex);
132 return -1;
133 }
134 }
135
136 // ƒtƒF[ƒhƒCƒ“‚ŞŠŽ—š‚ˇ‚é‚Ě‚đ‘Ň‚Â
137 // Mix_FadeInMusic() ‚Ě“Žě’†‚É Mix_FadeOutMusic() ‚Ş“Žě‚ľ‚Č‚˘‚˝‚ß
138 // !!! Œľ–§‚ɂ́Afade_out_msec == 0 ‚Č‚ç‚Î‘ŚŔ‚É’âŽ~‚ł‚š‚é‚ׂŤ‚ž‚ށA•Ű—Ż
139 UnlockMutex(mutex);
140
141 while (Mix_FadingMusic() != MIX_NO_FADING) {
142 delay(10);
143 }
144 LockMutex(mutex);
145 Mix_FadeOutMusic(fade_out_msec);
146 UnlockMutex(mutex);
147
148 // ƒtƒF[ƒhƒAƒEƒg‚ĚŠŽ—š‚đ‘Ň‚Á‚āAŽŸ‚ĚƒtƒF[ƒh‚đŽn‚ß‚é
149 while (Mix_PlayingMusic()) {
150 delay(10);
151 }
152
153 LockMutex(mutex);
154 if (current_music_id != next_music_id) {
155 pImpl::freeMusResource(music_map, current_music_id);
156 }
157 if (play_times == 0) {
158 // ‹Č‚Ě’âŽ~‚đs‚˘A–ß‚é
159 now_playing = false;
160 UnlockMutex(mutex);
161 continue;
162 }
163
164 // ‰šŠyƒtƒ@ƒCƒ‹‚Ě“Ç‚Ýo‚ľ
165 p = music_map.find(next_music_id);
166 if (p == music_map.end()) {
167 // !!! ƒtƒF[ƒh’†‚É‹Č‚Ş‰đ•ú‚ł‚ę‚˝ę‡H
168 continue;
169 }
170 pImpl::MusicInfo& music_info = p->second;
171 if (music_info.music == NULL) {
172 music_info.music = Mix_LoadMUS(music_info.file_path.c_str());
173 if (music_info.music == NULL) {
174 // !!! ƒGƒ‰[o—Í
175 now_playing = false;
176 UnlockMutex(mutex);
177 continue;
178 }
179 }
180
181 // ŽŸ‚̋ȂđÄś
182 now_playing = true;
183 Mix_HookMusicFinished(pImpl::playFinished);
184 Mix_FadeInMusic(music_info.music, play_times, fade_in_msec);
185 current_music_id = next_music_id;
186 UnlockMutex(mutex);
187 }
188 }
189
190 static void playFinished(void) {
191 now_playing = false;
192 }
193
194 static void freeMusResource(MusicMap& music_maps, int music_id,
195 bool erase = false) {
196 MusicMap::iterator p = music_maps.find(music_id);
197 if (p != music_maps.end()) {
198 if (p->second.music) {
199 Mix_FreeMusic(p->second.music);
200 p->second.music = NULL;
201 }
202 if (erase) {
203 music_maps.erase(p);
204 }
205 }
206 }
207 };
208 bool MusicManager::pImpl::now_playing = false;
209
210
211 MusicManager::MusicManager(void) : pimpl(pImpl::getObject()) {
212 }
213
214
215 MusicManager::~MusicManager(void) {
216 }
217
218
219 bool MusicManager::isInitialized(void) {
220 if (pimpl) {
221 return pimpl->initialized;
222 } else {
223 return false;
224 }
225 }
226
227
228 bool MusicManager::registerMusic(int music_id, const char* file_path) {
229 if (! isInitialized()) {
230 return false;
231 }
232
233 // ƒtƒ@ƒCƒ‹‚Ě‘śÝƒ`ƒFƒbƒN
234 if (! existFile(file_path)) {
235 return false;
236 }
237
238 pImpl::MusicInfo music_info;
239 music_info.file_path = file_path;
240
241 // Šů‘ś‚Ě‚ŕ‚Ě‚Ć“Ż‚ś ID ‚ŞŽw’肳‚ę‚˝ę‡AŠů‘śƒŠƒ\[ƒX‚đíœ‚ˇ‚é
242 LockGuard guard(pimpl->mutex);
243 pImpl::freeMusResource(pimpl->music_map, music_id);
244
245 // ‹ČŽ‘Œš‚Ě‚ ‚éęŠ‚݂̂đ“o˜^‚ľAƒ[ƒh‚ÍŽŔŰ‚̍ĐśŽž‚ɍs‚¤
246 pimpl->music_map[music_id] = music_info;
247
248 return true;
249 }
250
251
252 void MusicManager::unregisterMusic(int music_id) {
253 if (! isInitialized()) {
254 return;
255 }
256
257 LockGuard guard(pimpl->mutex);
258 pImpl::freeMusResource(pimpl->music_map, music_id, true);
259 }
260
261
262 void MusicManager::updateVolume(size_t percent) {
263 if (! isInitialized()) {
264 return;
265 }
266
267 if (percent > 100) {
268 percent = 100;
269 } else if (percent < 0) {
270 percent = 0;
271 }
272 Mix_VolumeMusic(MIX_MAX_VOLUME * percent / 100);
273 }
274
275
276 void MusicManager::setNextMusic(int next_music_id, int play_times) {
277 if (! isInitialized()) {
278 return;
279 }
280
281 LockGuard guard(pimpl->mutex);
282
283 // –‚čŽn‚ß‚˝‚ĆŒŠ‚Č‚ˇ
284 pImpl::now_playing = true;
285
286 pimpl->change_order.push_back(pImpl::ChangeOrder(next_music_id, play_times));
287 pimpl->thread.run(1);
288 }
289
290
291 void MusicManager::stop(size_t fade_out_msec) {
292 if (! isInitialized()) {
293 return;
294 }
295
296 setFadeOutEffect(fade_out_msec);
297 setNextMusic(0, 0);
298 }
299
300
301 void MusicManager::halt(void) {
302 if (! isInitialized()) {
303 return;
304 }
305
306 Mix_HaltMusic();
307 LockGuard guard(pimpl->mutex);
308 pImpl::now_playing = false;
309 }
310
311
312 void MusicManager::setFadeInEffect(size_t effect_msec) {
313 if (! isInitialized()) {
314 // !!!
315 return;
316 }
317
318 LockGuard guard(pimpl->mutex);
319 pimpl->fade_in_msec = effect_msec;
320 }
321
322
323 void MusicManager::setFadeOutEffect(size_t effect_msec) {
324 if (! isInitialized()) {
325 return;
326 }
327
328 LockGuard guard(pimpl->mutex);
329 pimpl->fade_out_msec = effect_msec;
330 }
331
332
333 int MusicManager::getCurrentMusicId(void) {
334 if (! isInitialized()) {
335 return -1;
336 }
337
338 LockGuard guard(pimpl->mutex);
339 return pimpl->current_music_id;
340 }
341
342
343 bool MusicManager::nowPlaying(void) {
344 if (! isInitialized()) {
345 fprintf(stderr, "not initialized.\n");
346 return false;
347 }
348
349 LockGuard guard(pimpl->mutex);
350 return ((Mix_PlayingMusic() != 0) || pImpl::now_playing) ? true : false;
351 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26