… | |
… | |
164 | our $SDL_MIXER; |
164 | our $SDL_MIXER; |
165 | our $MUSIC_DEFAULT = "in_a_heartbeat.ogg"; |
165 | our $MUSIC_DEFAULT = "in_a_heartbeat.ogg"; |
166 | our $MUSIC_WANT; # arryref of ambient music |
166 | our $MUSIC_WANT; # arryref of ambient music |
167 | our @MUSIC_HAVE; # ambient music we want now |
167 | our @MUSIC_HAVE; # ambient music we want now |
168 | our $MUSIC_START; |
168 | our $MUSIC_START; |
|
|
169 | our @MUSIC_JINGLE; # which jingles to play |
169 | our $MUSIC_PLAYING_DATA; |
170 | our $MUSIC_PLAYING_DATA; |
170 | our $MUSIC_PLAYING_META; |
171 | our $MUSIC_PLAYING_META; |
171 | our $MUSIC_PLAYER; |
172 | our $MUSIC_PLAYER; |
172 | our $MUSIC_RESUME = 30; # resume music when players less than these many seconds before |
173 | our $MUSIC_RESUME = 30; # resume music when players less than these many seconds before |
173 | our @SOUNDS; # event => file mapping |
174 | our @SOUNDS; # event => file mapping |
… | |
… | |
216 | } else { |
217 | } else { |
217 | # sound_meta not set means data is in flight either way |
218 | # sound_meta not set means data is in flight either way |
218 | my $meta = $CONN->{sound_meta}{$face} |
219 | my $meta = $CONN->{sound_meta}{$face} |
219 | or return; |
220 | or return; |
220 | |
221 | |
|
|
222 | # if its a jingle, play it as ambient music |
|
|
223 | if ($meta->{meta}{jingle}) { |
|
|
224 | push @MUSIC_JINGLE, $meta; |
|
|
225 | delete $AUDIO_PLAY{$face}; |
|
|
226 | &audio_music_push ($face); |
|
|
227 | } else { |
221 | # fetch from database |
228 | # fetch from database |
222 | CFPlus::DB::get res_data => $meta->{name}, sub { |
229 | CFPlus::DB::get res_data => $meta->{name}, sub { |
223 | my $rwops = new CFPlus::RW $_[0]; |
230 | my $rwops = new CFPlus::RW $_[0]; |
224 | my $chunk = new CFPlus::MixChunk $rwops; |
231 | my $chunk = new CFPlus::MixChunk $rwops; |
225 | $chunk->volume (($meta->{meta}{volume} || 1) * 128); |
232 | $chunk->volume (($meta->{meta}{volume} || 1) * 128); |
226 | $AUDIO_CHUNK{$face} = $chunk; |
233 | $AUDIO_CHUNK{$face} = $chunk; |
227 | |
234 | |
228 | audio_sound_push ($face); |
235 | audio_sound_push ($face); |
|
|
236 | }; |
229 | }; |
237 | } |
230 | } |
238 | } |
231 | } |
239 | } |
232 | |
240 | |
233 | sub audio_sound_play { |
241 | sub audio_sound_play { |
234 | my ($face, $dx, $dy, $vol) = @_; |
242 | my ($face, $dx, $dy, $vol) = @_; |
… | |
… | |
243 | } |
251 | } |
244 | |
252 | |
245 | sub audio_music_update_volume { |
253 | sub audio_music_update_volume { |
246 | return unless $MUSIC_PLAYING_META; |
254 | return unless $MUSIC_PLAYING_META; |
247 | my $volume = $MUSIC_PLAYING_META->{meta}{volume} || 1; |
255 | my $volume = $MUSIC_PLAYING_META->{meta}{volume} || 1; |
248 | my $base = $CFG->{bgm_volume}; |
256 | my $base = $MUSIC_PLAYING_META->{meta}{jingle} ? 1 : $CFG->{bgm_volume}; |
249 | CFPlus::MixMusic::volume $base * $volume * 128; |
257 | CFPlus::MixMusic::volume $base * $volume * 128; |
250 | } |
|
|
251 | |
|
|
252 | sub audio_music_push { |
|
|
253 | my @have = |
|
|
254 | grep $_, |
|
|
255 | map $CONN->{music_meta}{$_}, |
|
|
256 | @$MUSIC_WANT; |
|
|
257 | |
|
|
258 | if (@have) { |
|
|
259 | @MUSIC_HAVE = @have; |
|
|
260 | &audio_music_changed (); |
|
|
261 | } |
|
|
262 | } |
|
|
263 | |
|
|
264 | sub audio_music_set_ambient { |
|
|
265 | my ($songs) = @_; |
|
|
266 | |
|
|
267 | $MUSIC_WANT = $songs; |
|
|
268 | |
|
|
269 | audio_music_push; |
|
|
270 | } |
258 | } |
271 | |
259 | |
272 | sub audio_music_start { |
260 | sub audio_music_start { |
273 | my $meta = $MUSIC_PLAYING_META; |
261 | my $meta = $MUSIC_PLAYING_META; |
274 | |
262 | |
… | |
… | |
304 | delete $MUSIC_PLAYING_META->{stop_time}; |
292 | delete $MUSIC_PLAYING_META->{stop_time}; |
305 | delete $MUSIC_PLAYING_META->{stop_pos}; |
293 | delete $MUSIC_PLAYING_META->{stop_pos}; |
306 | } |
294 | } |
307 | } |
295 | } |
308 | |
296 | |
309 | sub audio_music_changed { |
297 | sub audio_music_push { |
310 | return unless $CFG->{bgm_enable}; |
|
|
311 | return unless $SDL_MIXER; |
298 | return unless $SDL_MIXER; |
312 | |
299 | |
|
|
300 | my $fade_out; |
|
|
301 | |
|
|
302 | if (@MUSIC_JINGLE) { |
|
|
303 | @MUSIC_HAVE = $MUSIC_JINGLE[0]; |
|
|
304 | $fade_out = 333; |
|
|
305 | } else { |
|
|
306 | return unless $CFG->{bgm_enable}; |
|
|
307 | |
|
|
308 | my @have = |
|
|
309 | grep $_, |
|
|
310 | map $CONN->{music_meta}{$_}, |
|
|
311 | @$MUSIC_WANT; |
|
|
312 | |
|
|
313 | @MUSIC_HAVE = @have |
|
|
314 | if @have; |
|
|
315 | |
313 | # default MUSIC_HAVE == MUSIC_DEFAULT |
316 | # default MUSIC_HAVE == MUSIC_DEFAULT |
314 | @MUSIC_HAVE = { path => CFPlus::find_rcfile "music/$MUSIC_DEFAULT" } unless @MUSIC_HAVE; |
317 | @MUSIC_HAVE = { path => CFPlus::find_rcfile "music/$MUSIC_DEFAULT" } unless @MUSIC_HAVE; |
|
|
318 | $fade_out = 1000; |
|
|
319 | } |
315 | |
320 | |
316 | # if the currently playing song is acceptable, let it continue |
321 | # if the currently playing song is acceptable, let it continue |
317 | return if $MUSIC_PLAYING_META |
322 | return if $MUSIC_PLAYING_META |
318 | && grep $MUSIC_PLAYING_META == $_, @MUSIC_HAVE; |
323 | && grep $MUSIC_PLAYING_META == $_, @MUSIC_HAVE; |
319 | |
324 | |
320 | my $NOW = time; |
325 | my $NOW = time; |
321 | |
326 | |
322 | if ($MUSIC_PLAYING_META) { |
327 | if ($MUSIC_PLAYING_META) { |
323 | $MUSIC_PLAYING_META->{stop_time} = $NOW; |
328 | $MUSIC_PLAYING_META->{stop_time} = $NOW; |
324 | $MUSIC_PLAYING_META->{stop_pos} = $NOW - $MUSIC_START; |
329 | $MUSIC_PLAYING_META->{stop_pos} = $NOW - $MUSIC_START; |
325 | CFPlus::MixMusic::fade_out 1000; |
330 | CFPlus::MixMusic::fade_out $fade_out; |
326 | } else { |
331 | } else { |
327 | # sort by stop time, oldest first |
332 | # sort by stop time, oldest first |
328 | @MUSIC_HAVE = sort { $a->{stop_time} <=> $b->{stop_time} } @MUSIC_HAVE; |
333 | @MUSIC_HAVE = sort { $a->{stop_time} <=> $b->{stop_time} } @MUSIC_HAVE; |
329 | |
334 | |
330 | # if the most recently-played piece played very recently, |
335 | # if the most recently-played piece played very recently, |
… | |
… | |
336 | |
341 | |
337 | audio_music_start; |
342 | audio_music_start; |
338 | } |
343 | } |
339 | } |
344 | } |
340 | |
345 | |
|
|
346 | sub audio_music_set_ambient { |
|
|
347 | my ($songs) = @_; |
|
|
348 | |
|
|
349 | $MUSIC_WANT = $songs; |
|
|
350 | audio_music_push; |
|
|
351 | } |
|
|
352 | |
341 | sub audio_music_finished { |
353 | sub audio_music_finished { |
|
|
354 | shift @MUSIC_JINGLE |
|
|
355 | if $MUSIC_PLAYING_META == $MUSIC_JINGLE[0]; |
|
|
356 | |
342 | undef $MUSIC_PLAYER; |
357 | undef $MUSIC_PLAYER; |
343 | undef $MUSIC_PLAYING_META; |
358 | undef $MUSIC_PLAYING_META; |
344 | undef $MUSIC_PLAYING_DATA; |
359 | undef $MUSIC_PLAYING_DATA; |
345 | |
360 | |
346 | audio_music_changed; |
361 | audio_music_push; |
347 | } |
362 | } |
348 | |
363 | |
349 | ############################################################################# |
364 | ############################################################################# |
350 | |
365 | |
351 | sub status { |
366 | sub status { |