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 = $Config->{MP3PLAYER} . " -q " . $songcmd;
 | 
						|
   if ( $debug ) {
 | 
						|
      print("Next: " . $songcmd . "\n"); $dbh->disconnect(); exit();
 | 
						|
   } else {
 | 
						|
      system($songcmd);
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
# Close the DB connection
 | 
						|
$dbh->disconnect();
 |