use DBI;
use Getopt::Long;
use IO::Async::Signal;
+use IO::Async::Timer::Periodic;
use Log::Any qw($log);
use Net::Async::MPD;
use Object::Pad;
has $db :reader;
has $db_needs_update :writer = 1;
has $mpd :reader;
+ has $idler;
use constant DEFAULT_CONFIG_FILE => '/etc/mpd-feeder/mpd-feeder.conf';
$mpd = Net::Async::MPD->new(%conn);
+ $mpd->on(
+ close => sub {
+ die "Connection to MPD lost";
+ }
+ );
+
my $int_signal_handler = sub {
state $signal_count = 0;
$signal_count++;
my $rows = $mpd->send('listallinfo')->get;
+ $log->trace('got all songs from MPD');
+
$db->start_update;
try {
my $song_count;
$self->db->store_song( $entry->{file},
$entry->{AlbumArtist} // $entry->{Artist},
$entry->{Album} );
+
$song_count++;
}
- $log->info("Updated data about $song_count songs");
+ my ($total_songs, $total_artists, $total_albums,
+ $new_songs, $new_artists, $new_albums
+ ) = $self->db->finish_update;
- $self->db->remove_stale_entries;
+ $log->info(
+ "Updated data about $song_count songs (including $new_songs new), "
+ . "$total_artists artists (including $new_artists new) "
- $self->db->finish_update;
+ . "and $total_albums albums (including $new_albums new)"
+ );
$db_needs_update = 0;
}
$self->connect_mpd;
$mpd->send('playlist')->on_done(
sub {
- my $present = scalar @{ $_[0] };
+ my $present = scalar @{ $_[0] // [] };
$log->notice( "Playlist contains $present songs. Wanted: "
. $opt->target_queue_length );
method prepare_to_wait_idle {
$log->trace('declaring idle mode');
- $mpd->send('idle database playlist')->on_done(
+ $idler = $mpd->send('idle database playlist')->on_done(
sub {
my $result = shift;
- if ( $result->{changed} eq 'database' ) {
+ undef $idler;
+
+ my $changed = $result->{changed} // '';
+
+ if ( $changed eq 'database' ) {
$db_needs_update = 1;
$self->prepare_to_wait_idle;
}
- elsif ( $result->{changed} eq 'playlist' ) {
+ elsif ( $changed eq 'playlist' ) {
$self->queue_songs( undef,
sub { $self->prepare_to_wait_idle } );
}
+ elsif ( $changed eq '' ) {
+ $log->debug("got no changes from idle");
+ $self->prepare_to_wait_idle;
+ }
else {
use JSON;
$log->warn(
);
}
- method run {
- $mpd->on(
- close => sub {
- die "Connection to MPD lost";
- }
- );
-
- $self->prepare_to_wait_idle;
- }
-
method stop {
undef $mpd;
}
method run_loop {
+ $self->connect_mpd;
$self->connect_db;
+ $mpd->loop->add(
+ IO::Async::Timer::Periodic->new(
+ interval => 300,
+ on_tick => sub {
+ if ($idler) {
+ $log->trace('breaking idle to see if MPD is there');
+ undef $idler;
+ $log->trace("> noidle (direct)");
+ $mpd->{mpd_handle}->write("noidle\n");
+ }
+ },
+ )->start
+ );
+
for ( ;; ) {
- $self->queue_songs( undef, sub { $self->run } );
+ $self->queue_songs( undef, sub { $self->prepare_to_wait_idle } );
$log->debug("Entering event loop. PID=$$");