--- deliantra/Deliantra-Client/bin/cfplus 2007/07/13 05:31:32 1.167 +++ deliantra/Deliantra-Client/bin/cfplus 2007/07/14 12:05:53 1.168 @@ -163,8 +163,10 @@ our $SDL_MIXER; our $MUSIC_DEFAULT = "in_a_heartbeat.ogg"; our @MUSIC_WANT; +our $MUSIC_START; our $MUSIC_PLAYING; our $MUSIC_PLAYER; +our $MUSIC_RESUME = 30; # resume music when players less than these many seconds before our @SOUNDS; # event => file mapping our %AUDIO_CHUNKS; # audio files @@ -2019,26 +2021,41 @@ sub audio_music_set { my ($songs) = @_; - my $count = @$songs; - my @meta; + my @want = + grep $_, + map $CONN->{music_meta}{$_}, + @$songs; + + if (@want) { + @MUSIC_WANT = @want; + &audio_music_changed (); + } +} - for my $name (@$songs) { - CFPlus::DB::get "res-metadata" => $name, sub { - my ($data) = @_; - - if ($data) { - $data = JSON::XS->new->utf8->decode ($data); - $data->{path} = CFPlus::DB::path_of $name; - push @meta, $data; - } +sub audio_music_start { + my $path = $MUSIC_PLAYING->{path} + or return; + + CFPlus::DB::prefetch_file $path, 1024_000, sub { + # music might have changed... + $path eq $MUSIC_PLAYING->{path} + or return &audio_music_start (); + + $MUSIC_PLAYER = new_from_file CFPlus::MixMusic $path; + + my $NOW = time; + + if ($MUSIC_PLAYING->{stop_time} > $NOW - $MUSIC_RESUME) { + my $pos = $MUSIC_PLAYING->{stop_pos}; + $MUSIC_PLAYER->fade_in_pos (0, 1000, $pos); + $MUSIC_START = time - $pos; + } else { + $MUSIC_PLAYER->play (0); + $MUSIC_START = time; + } - unless (--$count) { - if (@meta) { - @MUSIC_WANT = @meta; - &audio_music_changed (); - } - } - }; + delete $MUSIC_PLAYING->{stop_time}; + delete $MUSIC_PLAYING->{stop_pos}; } } @@ -2052,15 +2069,24 @@ return if $MUSIC_PLAYING && grep $MUSIC_PLAYING->{path} eq $_->{path}, @MUSIC_WANT; + my $NOW = time; + if ($MUSIC_PLAYING) { + $MUSIC_PLAYING->{stop_time} = $NOW; + $MUSIC_PLAYING->{stop_pos} = $NOW - $MUSIC_START; CFPlus::MixMusic::fade_out 1000; } else { - my $music = $MUSIC_WANT [rand @MUSIC_WANT]; + # sort by stop time, oldest first + @MUSIC_WANT = sort { $a->{stop_time} <=> $b->{stop_time} } @MUSIC_WANT; - $MUSIC_PLAYING = $music; + # if the most recently-played piece played very recently, + # resume it, else choose the oldest piece for rotation. + $MUSIC_PLAYING = + $MUSIC_WANT[-1]{stop_time} > $NOW - $MUSIC_RESUME + ? $MUSIC_WANT[-1] + : $MUSIC_WANT[0]; - $MUSIC_PLAYER = new_from_file CFPlus::MixMusic $music->{path}; - $MUSIC_PLAYER->play (0); + audio_music_start; } }