197 lines
7.8 KiB
Perl
Executable File
197 lines
7.8 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
|
|
my $debug = 0; # Set to 1 to put the script in debug mode
|
|
|
|
use POSIX;
|
|
use DBI;
|
|
use DBD::mysql;
|
|
use Config::INI::Reader;
|
|
|
|
my $confcontents = Config::INI::Reader->read_file('/etc/homeaudio.ini');
|
|
my $Config = $confcontents->{_};
|
|
|
|
$dsn = "DBI:mysql:" . $Config->{DBNAME} . ":" . $Config->{DBHOST};
|
|
$dbh = DBI->connect($dsn, $Config->{DBUSER}, $Config->{DBPASS}, {RaiseError=>1});
|
|
|
|
sub getNextSong() {
|
|
# Set up our variables
|
|
my $songid = 0;
|
|
my $song = "";
|
|
my $qid = 0;
|
|
|
|
# If Christmas is active we should always make sure that a
|
|
# Christmas song has played within the last frequency interval.
|
|
$sth = $dbh->prepare("SELECT value FROM settings WHERE parameter='CHRISTMAS'");
|
|
$sth->execute();
|
|
@row = $sth->fetchrow_array();
|
|
$sth->finish();
|
|
$christmasactive = $row[0] eq "true" ? 1 : 0;
|
|
$forcechristmas = 0;
|
|
if ( $christmasactive ) {
|
|
if ( $debug ) { print "Christmas is active.\n"; }
|
|
$sth = $dbh->prepare("SELECT value FROM settings WHERE parameter='CHRISTMASFREQ'");
|
|
$sth->execute();
|
|
@row = $sth->fetchrow_array();
|
|
my $christmasfreq = $row[0];
|
|
$sth->finish();
|
|
if ( $debug ) { print "Christmas frequency is (${christmasfreq}). Checking if Christmas song was played recently.\n"; }
|
|
$sth = $dbh->prepare("SELECT COUNT(songid) FROM (SELECT songid FROM recently ORDER BY timeplayed DESC LIMIT ?) AS counter LEFT JOIN songs ON songid=id WHERE genre=?");
|
|
$sth->execute($christmasfreq - 1, $Config->{CHRISTMASGENRE});
|
|
@row = $sth->fetchrow_array();
|
|
$sth->finish();
|
|
if ( $row[0] == 0 ) {
|
|
$forcechristmas = 1;
|
|
}
|
|
}
|
|
if ( $forcechristmas ) {
|
|
if ( $debug ) { print "No Christmas songs found in the last ${christmasfreq}. Forcing one to play.\n"; }
|
|
$queueselect = "SELECT id FROM queues WHERE name='" . $Config->{CHRISTMASGENRE} . "'";
|
|
$sth_first = $dbh->prepare("SELECT qid, songid, CONCAT(path, song) FROM queuecontents AS qc LEFT JOIN songs ON songid=id WHERE qc.timesplayed=0 AND qid=(${queueselect}) ORDER BY RAND() LIMIT 1");
|
|
$sth_first->execute();
|
|
$numsongs = $sth_first->rows;
|
|
if ( $sth_first->rows == 0 ) {
|
|
$sth = $dbh->prepare("UPDATE queuecontents SET timesplayed=0 WHERE qid=(${queueselect})");
|
|
$sth->execute();
|
|
$sth->finish();
|
|
$sth_second = $dbh->prepare("SELECT qid, songid, CONCAT(path, song) FROM queuecontents AS qc LEFT JOIN songs ON songid=id WHERE qc.timesplayed=0 AND qid=(${queueselect}) ORDER BY RAND() LIMIT 1");
|
|
$sth_second->execute();
|
|
if ( $sth->rows == 1 ) {
|
|
@row = $sth_second->fetchrow_array();
|
|
$qid = $row[0];
|
|
$songid = $row[1];
|
|
$song = $row[2];
|
|
}
|
|
$sth_second->finish();
|
|
} else {
|
|
@row = $sth_first->fetchrow_array();
|
|
$sth_first->finish();
|
|
$qid = $row[0];
|
|
$songid = $row[1];
|
|
$song = $row[2];
|
|
}
|
|
}
|
|
|
|
# Only try to pull from the instantq if we don't have a song yet
|
|
if ( $songid == 0 ) {
|
|
# if there is anything in the instantq, get the list of songs
|
|
# (sorted by "id"), delete the most recent one and return
|
|
# the full path to the song
|
|
my $sth = $dbh->prepare("SELECT instantq.id, songid, CONCAT(path, song) AS songpath FROM instantq LEFT JOIN songs ON songid=songs.id ORDER BY id");
|
|
$sth->execute();
|
|
if ( $sth->rows > 0 ) {
|
|
@result = $sth->fetchrow_array();
|
|
$sth->finish();
|
|
$id = $result[0];
|
|
$songid = $result[1];
|
|
$songpath = $result[2];
|
|
$dbh->do("DELETE FROM instantq WHERE id=$id");
|
|
$sth->finish();
|
|
return ($songid, $songpath);
|
|
}
|
|
$sth->finish();
|
|
}
|
|
|
|
# Only try to grab the next song in the active queue if we don't have a song yet
|
|
if ( $songid == 0 ) {
|
|
# We wouldn't be here if there was anything in the instant queue
|
|
# so let's find out the default queue and randomly select a song
|
|
# from that queue which is in the group of lowest "timesplayed".
|
|
# Basically, when a song in a queue is played by the autoplayer
|
|
# its "timesplayed" is incremented. Each queue should have "timesplayed"
|
|
# values of only two distinct numbers since each queue starts at 0 (zero),
|
|
# gets incremented only when autoplayed, and won't get autoplayed again
|
|
# until after all other lower number "timesplayed" have been played.
|
|
if ( $debug ) { print "Trying to pull a song from the active queue.\n"; }
|
|
$queueselect = "SELECT id FROM queues WHERE active='true'";
|
|
$sth_first = $dbh->prepare("SELECT qid, songid, CONCAT(path, song) FROM queuecontents AS qc LEFT JOIN songs ON songid=id WHERE qc.timesplayed=0 AND qid=(${queueselect}) ORDER BY RAND() LIMIT 1");
|
|
$sth_first->execute();
|
|
$numsongs = $sth->rows;
|
|
# if there are no songs returned then reset the played count to zero and try again
|
|
if ( $sth_first->rows == 0 ) {
|
|
if ( $debug ) { print "Found no songs. Resetting timesplayed and trying again.\n"; }
|
|
$sth = $dbh->prepare("UPDATE queuecontents SET timesplayed=0 WHERE qid=(${queueselect})");
|
|
$sth->execute();
|
|
$sth->finish();
|
|
$sth_second = $dbh->prepare("SELECT qid, songid, CONCAT(path, song) FROM queuecontents AS qc LEFT JOIN songs ON songid=id WHERE qc.timesplayed=0 AND qid=(${queueselect}) ORDER BY RAND() LIMIT 1");
|
|
$sth_second->execute();
|
|
if ( $sth_second->rows == 0 ) {
|
|
if ( $debug ) { print "Found no songs after resetting timesplayed. Queue must be empty. Returning empty song.\n"; }
|
|
return (0, "");
|
|
}
|
|
@result = $sth_second->fetchrow_array();
|
|
$sth_second->finish();
|
|
} else {
|
|
@result = $sth_first->fetchrow_array();
|
|
$sth_first->finish();
|
|
}
|
|
$qid = $result[0];
|
|
$songid = $result[1];
|
|
$song = $result[2];
|
|
}
|
|
|
|
# Increment the timesplayed for this song if a song was found
|
|
$sound = `/usr/bin/amixer sget Master`;
|
|
@mixer = split(/\n/, $sound);
|
|
$muted = 1;
|
|
if ( index($mixer[@mixer-1], "[on]") > 0 ) { $muted = 0; }
|
|
if ( ($muted == 0) && ($songid > 0) ) {
|
|
$sth = $dbh->prepare("UPDATE queuecontents SET timesplayed=1 WHERE qid=? AND songid=?");
|
|
$sth->execute($qid, $songid);
|
|
$sth->finish();
|
|
}
|
|
|
|
# return the song ID and the relative path
|
|
return ($songid, $song);
|
|
}
|
|
|
|
while ( 1 ) {
|
|
if ( -e "/tmp/homeaudio.stop" ) {
|
|
sleep 10;
|
|
next;
|
|
}
|
|
my ($songid, $song) = getNextSong();
|
|
# if the song is blank, sleep for 60 seconds and try again
|
|
# the song might be blank if the active queue is empty
|
|
# or there is no active queue and the instantq is empty
|
|
# or the song that was found in the DB doesn't exist on
|
|
# the hard drive
|
|
if ( $song eq "" ) {
|
|
if ( $debug ) { print "Found no songs to play. Sleeping for 60 seconds.\n"; }
|
|
sleep 60;
|
|
next;
|
|
}
|
|
$songcmd = $Config->{MP3DIR} . $song;
|
|
$songcmd =~ s/ /\\ /g;
|
|
$songcmd =~ s/&/\\&/g;
|
|
$songcmd =~ s/\(/\\\(/g;
|
|
$songcmd =~ s/\)/\\\)/g;
|
|
$songcmd =~ s/\[/\\\[/g;
|
|
$songcmd =~ s/\]/\\\]/g;
|
|
$songcmd =~ s/'/\\'/g;
|
|
$songcmd =~ s/"/\\"/g;
|
|
$songcmd =~ s/\$/\\\$/g;
|
|
$songdb = $song;
|
|
$songdb =~ s/'/\\'/g;
|
|
$sth = $dbh->prepare("INSERT INTO recently (songid, timeplayed) VALUES(?, NOW())");
|
|
$sth->execute($songid);
|
|
$sth->finish();
|
|
$sth = $dbh->prepare("SELECT timeplayed FROM recently ORDER BY timeplayed DESC limit 1 OFFSET 1000");
|
|
$sth->execute();
|
|
if ( $sth->rows == 1 ) {
|
|
@row = $sth->fetchrow_array();
|
|
$sth->finish();
|
|
$sth = $dbh->prepare("DELETE FROM recently WHERE timeplayed <= ?");
|
|
$sth->execute($row[0]);
|
|
}
|
|
$sth->finish();
|
|
$songcmd = "/usr/bin/mpg321 -q " . $songcmd;
|
|
if ( $debug ) {
|
|
print("Next: " . $songcmd . "\n"); $dbh->disconnect(); exit();
|
|
} else {
|
|
system($songcmd);
|
|
}
|
|
}
|
|
|
|
# Close the DB connection
|
|
$dbh->disconnect();
|