addd code to BackMusic.cpp. not tested.
@@ -8,25 +8,64 @@ | ||
8 | 8 | */ |
9 | 9 | |
10 | 10 | #include "BackMusic.h" |
11 | +#include <SDL_mixer.h> | |
12 | +#include <map> | |
13 | +#include <string> | |
11 | 14 | |
15 | +#include <cstdio> | |
16 | + | |
12 | 17 | using namespace qrk; |
18 | +using namespace std; | |
13 | 19 | |
14 | 20 | |
15 | 21 | struct BackMusic::pImpl |
16 | 22 | { |
17 | - // !!! | |
23 | + typedef map<string, Mix_Music*> Musics; | |
18 | 24 | |
25 | + bool is_playing_; | |
26 | + Musics musics_; | |
19 | 27 | |
20 | - pImpl(void) | |
28 | + | |
29 | + pImpl(void) : is_playing_(false) | |
21 | 30 | { |
22 | 31 | } |
23 | 32 | |
24 | 33 | |
34 | +#if 0 | |
35 | + // !!! 必要ならば musics_ を解放する | |
36 | + // !!! valgrind で警告がでなかったら、解放しなくてもよいことにしたい | |
37 | + ~pImpl(void) | |
38 | + { | |
39 | + } | |
40 | +#endif | |
41 | + | |
42 | + | |
25 | 43 | static pImpl* object(void) |
26 | 44 | { |
27 | 45 | static pImpl singleton_object; |
28 | 46 | return &singleton_object; |
29 | 47 | } |
48 | + | |
49 | + | |
50 | + Mix_Music* find_music(const char* file_path) | |
51 | + { | |
52 | + // Load に失敗した場合には musics_ に NULL を格納し、 | |
53 | + // 成功した場合にはリソースのポインタを格納する | |
54 | + Musics::iterator it = musics_.find(file_path); | |
55 | + if (it != musics_.end()) { | |
56 | + return it->second; | |
57 | + } | |
58 | + | |
59 | + Mix_Music* music = Mix_LoadMUS(file_path); | |
60 | + musics_[file_path] = music; | |
61 | + return music; | |
62 | + } | |
63 | + | |
64 | + | |
65 | + void free_music(const char* file_path) | |
66 | + { | |
67 | + musics_.erase(file_path); | |
68 | + } | |
30 | 69 | }; |
31 | 70 | |
32 | 71 |
@@ -40,10 +79,22 @@ | ||
40 | 79 | } |
41 | 80 | |
42 | 81 | |
82 | +void BackMusic::free_music_resource(const char* file_path) | |
83 | +{ | |
84 | + Mix_Music* music = pimpl->find_music(file_path); | |
85 | + if (music) { | |
86 | + Mix_FreeMusic(music); | |
87 | + pimpl->free_music(file_path); | |
88 | + } | |
89 | +} | |
90 | + | |
91 | + | |
43 | 92 | void BackMusic::setVolume(size_t percent) |
44 | 93 | { |
45 | - (void)percent; | |
46 | - // !!! | |
94 | + fprintf(stderr, "BackMusic::setVolume: %d\n", percent); | |
95 | + | |
96 | + int mix_volume = static_cast<int>(MIX_MAX_VOLUME * 100.0 / percent); | |
97 | + Mix_VolumeMusic(mix_volume); | |
47 | 98 | } |
48 | 99 | |
49 | 100 |
@@ -50,24 +101,39 @@ | ||
50 | 101 | bool BackMusic::play(const char* file_path, int fade_in_msec, |
51 | 102 | int play_times, int fade_out_msec) |
52 | 103 | { |
53 | - (void)file_path; | |
54 | - (void)fade_in_msec; | |
55 | - (void)play_times; | |
104 | + fprintf(stderr, "play %s\n", file_path); | |
105 | + | |
106 | + Mix_Music* music = pimpl->find_music(file_path); | |
107 | + if (!music) { | |
108 | + return false; | |
109 | + } | |
110 | + | |
111 | + // !!! 現在再生中の music の fade out を待ってから、 | |
112 | + // !!! 指定された music を再生するように実装を変更する | |
56 | 113 | (void)fade_out_msec; |
57 | - // !!! | |
58 | - return false; | |
114 | + | |
115 | + int ret = Mix_FadeInMusic(music, play_times, fade_in_msec); | |
116 | + if (ret == -1) { | |
117 | + return false; | |
118 | + } | |
119 | + | |
120 | + pimpl->is_playing_ = true; | |
121 | + return true; | |
59 | 122 | } |
60 | 123 | |
61 | 124 | |
62 | 125 | void BackMusic::stop(int fade_out_msec) |
63 | 126 | { |
64 | - (void)fade_out_msec; | |
65 | - // !!! | |
127 | + fprintf(stderr, "stop\n"); | |
128 | + | |
129 | + Mix_FadeOutMusic(fade_out_msec); | |
130 | + pimpl->is_playing_ = false; | |
66 | 131 | } |
67 | 132 | |
68 | 133 | |
69 | 134 | bool BackMusic::isPlaying(void) const |
70 | 135 | { |
71 | - // !!! | |
72 | - return false; | |
136 | + // !!! 終了を監視するスレッドにて is_playing_ フラグを監視する | |
137 | + | |
138 | + return pimpl->is_playing_; | |
73 | 139 | } |
@@ -22,6 +22,11 @@ | ||
22 | 22 | } |
23 | 23 | |
24 | 24 | |
25 | +enum { | |
26 | + DefaultVolumePercent = 30, | |
27 | +}; | |
28 | + | |
29 | + | |
25 | 30 | struct SoundEffect::pImpl |
26 | 31 | { |
27 | 32 | static bool initialized_; |
@@ -30,14 +35,18 @@ | ||
30 | 35 | int channel_id_; |
31 | 36 | Mix_Chunk* chunk_; |
32 | 37 | |
38 | + size_t master_percent_; | |
33 | 39 | |
40 | + | |
34 | 41 | pImpl(const char* play_file) |
35 | - : channel_id_(-1), chunk_(Mix_LoadWAV(play_file)) | |
42 | + : channel_id_(-1), chunk_(Mix_LoadWAV(play_file)), | |
43 | + master_percent_(DefaultVolumePercent) | |
36 | 44 | { |
37 | 45 | if (! initialized_) { |
38 | 46 | Mix_ChannelFinished(finished); |
39 | 47 | initialized_ = true; |
40 | 48 | } |
49 | + fprintf(stderr, "SoundEffect:play_file: %s)\n", play_file); | |
41 | 50 | } |
42 | 51 | |
43 | 52 |
@@ -89,10 +98,15 @@ | ||
89 | 98 | } |
90 | 99 | |
91 | 100 | |
92 | -void SoundEffect::setDefaultVolume(size_t percent) | |
101 | +void SoundEffect::setMasterVolume(size_t percent) | |
93 | 102 | { |
94 | - (void)percent; | |
103 | + fprintf(stderr, "SoundEffect::setMasterVolume: %d\n", percent); | |
104 | + static_cast<void>(percent); | |
105 | + | |
106 | + // Mix_Volume() を用いる | |
107 | + | |
95 | 108 | // !!! |
109 | + //pimpl->master_percent_ = max(percent, static_cast<size_t>(100)); | |
96 | 110 | } |
97 | 111 | |
98 | 112 |
@@ -130,6 +144,8 @@ | ||
130 | 144 | static_cast<void>(y); |
131 | 145 | static_cast<void>(z); |
132 | 146 | |
147 | + // !!! SDL_Mixer の Effect を利用すると再生位置の表現ができるかもしれない | |
148 | + | |
133 | 149 | // 実装しない |
134 | 150 | } |
135 | 151 |