Просмотр исходного кода

Merge branch 'master' of github.com:profplump/UberZach-Integration

Zachary Kotlarek 13 лет назад
Родитель
Сommit
6faf916481
6 измененных файлов с 189 добавлено и 119 удалено
  1. 5 0
      dmx/garage.pl
  2. 1 1
      dmx/projectorPower.pl
  3. 12 11
      dmx/qt_player.pl
  4. 4 16
      dmx/rifftrax.pl
  5. 165 89
      dmx/state.pl
  6. 2 2
      pms/optimize.sh

+ 5 - 0
dmx/garage.pl

@@ -98,6 +98,11 @@ while (1) {
 	# Update the relay
 	if ($update) {
 
+		# Annouce the command
+		if ($exists{'GARAGE_CMD'}) {
+			DMX::say('Garage door activated by ' . $exists{'GARAGE_CMD'});
+		}
+
 		# Toggle
 		$state = 'ACTIVATE';
 		DMX::applyDataset($DIM{$state}, $state, $OUTPUT_FILE);

+ 1 - 1
dmx/projectorPower.pl

@@ -14,7 +14,7 @@ my $COUNTDOWN   = 300;
 my $OFF_DELAY   = 15;
 my $CMD_DELAY   = 20;
 my $COLOR_DELAY = 60;
-my $COLOR_HIGH  = 'THEATER';
+my $COLOR_HIGH  = 'THEATER_BLACK_1';
 my $COLOR_PLAY  = 'THEATER_BLACK_1';
 my $COLOR_LOW   = 'THEATER_BLACK_1';
 my $LAMP_LIFE   = 2000;

+ 12 - 11
dmx/qt_player.pl

@@ -21,7 +21,7 @@ sub load($$);
 sub unload($);
 sub stop();
 sub printFiles();
-sub dieUnloaded($);
+sub cmdApp($$);
 
 # App config
 my $DATA_DIR    = DMX::dataDir();
@@ -112,8 +112,8 @@ sub init() {
 	%FILES = ();
 
 	# Close all QT documents and relaunch QT Player
-	Audio::runApplescript('tell application "QuickTime Player" to close every document');
-	Audio::runApplescript('tell application "QuickTime Player" to quit');
+	cmdApp('QuickTime Player', 'close every document');
+	cmdApp('QuickTime Player', 'quit');
 	sleep(1);
 	IPC::System::Simple::system('open', '-a', 'QuickTime Player');
 
@@ -121,7 +121,7 @@ sub init() {
 	load('SILENCE', 'DMX/Silence.wav');
 
 	# Bring Plex back to the front
-	activatePlex();
+	cmdApp('Plex', 'activate');
 }
 
 # Open the named file and record the handle
@@ -177,7 +177,7 @@ sub load($$) {
 	printFiles();
 
 	# Bring Plex back to the front
-	activatePlex();
+	cmdApp('Plex', 'activate');
 }
 
 # Close the named file
@@ -217,12 +217,13 @@ sub printFiles() {
 	rename($tmp, $OUTPUT_FILE);
 }
 
-# Bring Plex to the front, if it's already running
-sub activatePlex() {
+# Request the specified action from the provided app, if it's already running
+sub cmdApp($$) {
+	my ($app, $cmd) = @_;
 	my @cmd = ('tell application "System Events"');
-	push(@cmd, 'if exists process "Plex" then');
-	push(@cmd, 'tell application "Plex" to activate');
+	push(@cmd, 'if exists process "' . $app . '" then');
+	push(@cmd, 'tell application "' . $app . '" to ' . $cmd);
 	push(@cmd, 'end if');
-	push(@cmd, 'end tell');	
+	push(@cmd, 'end tell');
 	Audio::runApplescript(join("\n", @cmd));
-}
+}

+ 4 - 16
dmx/rifftrax.pl

@@ -209,12 +209,11 @@ while (1) {
 		rename($tmp, $OUTPUT_FILE);
 	}
 
-	# Play/pause to match the video
-	# This assumes our local state is valid. We double-check that state tracking if the sync error is large enough to trigger a jump
-	if ($riff) {
-		if ($state eq 'PAUSE' && $playing) {
+	# Play/pause to match the video state
+	if ($riff && exists($exists{'PLAYING'})) {
+		if (!$exists{'PLAYING'} && $playing) {
 			pauseRiff();
-		} elsif ($state eq 'PLAY' && !$playing) {
+		} elsif ($exists{'PLAYING'} && !$playing) {
 			playRiff();
 		}
 	}
@@ -301,17 +300,6 @@ while (1) {
 					}
 					setRiffRate($newRate);
 				}
-
-				# Play/pause as needed, before we adjust
-				# The state-change detection should handle most of this
-				# But double-check while adjusting in case things get out-of-sync
-				if (exists($exists{'PLAYING'})) {
-					if ($exists{'PLAYING'} && !$playing) {
-						playRiff();
-					} elsif (!$exists{'PLAYING'} && $playing) {
-						pauseRiff();
-					}
-				}
 			}
 		} else {
 

+ 165 - 89
dmx/state.pl

@@ -4,6 +4,7 @@ use warnings;
 use IO::Select;
 use File::Basename;
 use File::Temp qw( tempfile );
+use Sys::Hostname;
 
 # Local modules
 use Cwd qw(abs_path);
@@ -17,19 +18,26 @@ sub mtime($);
 # User config
 my $MEDIA_PATH    = `~/bin/video/mediaPath`;
 my %DISPLAY_DEVS  = ('TV' => 1, 'PROJECTOR' => 1);
-my $DISPLAY       = '<NONE>';
+my $DISPLAY       = undef();
 my $STATE_TIMEOUT = 180;
 my %MON_FILES     = ();
 
+# Host-specific config
+# This is necessary to avoid contention on shared disks
+my $HOST = Sys::Hostname::hostname();
+if ($HOST =~ /loki/i) {
+	$MON_FILES{ $MEDIA_PATH . '/DMX/cmd/GARAGE_CMD' } = 'EXISTS-VALUE-CLEAR';
+}
+
 # Available state files
 {
 
 	# Plex
-	$MON_FILES{'GUI'}     = 'STATUS_GUI';
-	$MON_FILES{'PLAYING'} = 'STATUS_PLAYING';
+	$MON_FILES{'GUI'}     = 'GUI';
+	$MON_FILES{'PLAYING'} = 'PLAYING';
 
 	# RiffTrax
-	$MON_FILES{'RIFF'} = 'STATUS_VALUE';
+	$MON_FILES{'RIFF'} = 'VALUE';
 
 	# Motion detection
 	$MON_FILES{'MOTION'}    = 'MTIME';
@@ -37,35 +45,34 @@ my %MON_FILES     = ();
 
 	# Projector
 	$MON_FILES{'PROJECTOR'}       = 'STATUS';
-	$MON_FILES{'PROJECTOR_COLOR'} = 'STATUS_VALUE';
-	$MON_FILES{'PROJECTOR_INPUT'} = 'STATUS_VALUE';
-	$MON_FILES{'PROJECTOR_LAMP'}  = 'STATUS_VALUE';
+	$MON_FILES{'PROJECTOR_COLOR'} = 'VALUE';
+	$MON_FILES{'PROJECTOR_INPUT'} = 'VALUE';
+	$MON_FILES{'PROJECTOR_LAMP'}  = 'VALUE';
 
 	# Amplifier
 	$MON_FILES{'AMPLIFIER'}       = 'STATUS';
-	$MON_FILES{'AMPLIFIER_VOL'}   = 'STATUS_VALUE';
-	$MON_FILES{'AMPLIFIER_MODE'}  = 'STATUS_VALUE';
-	$MON_FILES{'AMPLIFIER_INPUT'} = 'STATUS_VALUE';
-	$MON_FILES{'AUDIO_AMP'}       = 'EXISTS_ON';
-	$MON_FILES{'STEREO_CMD'}      = 'EXISTS_ON';
+	$MON_FILES{'AMPLIFIER_VOL'}   = 'VALUE';
+	$MON_FILES{'AMPLIFIER_MODE'}  = 'VALUE';
+	$MON_FILES{'AMPLIFIER_INPUT'} = 'VALUE';
+	$MON_FILES{'AUDIO_AMP'}       = 'EXISTS-ON';
+	$MON_FILES{'STEREO_CMD'}      = 'EXISTS-ON';
 
 	# A/V Effects
-	$MON_FILES{'LIGHTS'} = 'EXISTS_ON';
+	$MON_FILES{'LIGHTS'} = 'EXISTS-ON';
 	$MON_FILES{'RAVE'}   = 'EXISTS';
 	$MON_FILES{'EFFECT'} = 'EXISTS';
 
 	# Equipment
-	$MON_FILES{'FAN_CMD'} = 'EXISTS_ON';
-	$MON_FILES{ $MEDIA_PATH . '/DMX/cmd/GARAGE_CMD' } = 'EXISTS_CLEAR';
+	$MON_FILES{'FAN_CMD'} = 'EXISTS-ON';
 
 	# OS State
-	$MON_FILES{'COLOR'}       = 'STATUS_VALUE';
-	$MON_FILES{'AUDIO'}       = 'STATUS_VALUE';
-	$MON_FILES{'AUDIO_STATE'} = 'STATUS_VALUE';
+	$MON_FILES{'COLOR'}       = 'VALUE';
+	$MON_FILES{'AUDIO'}       = 'VALUE';
+	$MON_FILES{'AUDIO_STATE'} = 'VALUE';
 
 	# TV
 	$MON_FILES{'TV'}     = 'STATUS';
-	$MON_FILES{'TV_VOL'} = 'STATUS_VALUE';
+	$MON_FILES{'TV_VOL'} = 'VALUE';
 }
 my %EXTRAS = (
 	'PLAYING' => {
@@ -116,27 +123,74 @@ foreach my $file (keys(%EXTRAS)) {
 
 # Init the file tracking structure
 my %files = ();
-foreach my $file (keys(%MON_FILES)) {
-	my %tmp = (
-		'name'      => basename($file),
-		'type'      => $MON_FILES{$file},
-		'path'      => $DATA_DIR . $file,
-		'update'    => 0,
-		'status'    => 0,
-		'last'      => 0,
-		'available' => 1,
+foreach my $name (keys(%MON_FILES)) {
+	my %file = (
+		'name'   => basename($name),
+		'type'   => $MON_FILES{$name},
+		'path'   => $DATA_DIR . $name,
+		'update' => 0,
+		'value'  => 0,
+		'last'   => 0,
 	);
 
 	# Allow absolute paths to override the $DATA_DIR path
-	if ($file =~ /^\//) {
-		$tmp{'path'} = $file;
+	if ($name =~ /^\//) {
+		$file{'path'} = $name;
 	}
 
 	# Record the directory name for folder monitoring
-	$tmp{'dir'} = dirname($tmp{'path'});
+	$file{'dir'} = dirname($file{'path'});
+
+	# Set the attribute bits, for use in later update handling logic
+	my %attr = (
+		'available' => 0,
+		'status'    => 0,
+		'exists'    => 0,
+		'value'     => 0,
+		'clear'     => 0,
+		'clear_off' => 0,
+		'mtime'     => 0,
+		'gui'       => 0,
+		'playing'   => 0,
+	);
+	if ($file{'type'} =~ /\bSTATUS\b/i) {
+		$attr{'status'} = 1;
+	}
+	if ($file{'type'} =~ /\bEXISTS\b/i) {
+		$attr{'exists'} = 1;
+	}
+	if ($file{'type'} =~ /\bVALUE\b/i) {
+		$attr{'value'} = 1;
+	}
+	if ($file{'type'} =~ /\bCLEAR\b/i) {
+		$attr{'clear'} = 1;
+	}
+	if ($file{'type'} =~ /\bON\b/i) {
+		$attr{'clear_off'} = 1;
+	}
+	if ($file{'type'} =~ /\bMTIME\b/i) {
+		$attr{'mtime'} = 1;
+	}
+	if ($file{'type'} =~ /\bGUI\b/i) {
+		$attr{'gui'} = 1;
+	}
+	if ($file{'type'} =~ /\bPLAYING\b/i) {
+		$attr{'playing'} = 1;
+	}
+
+	# Cross-match some data types for easy of use
+	if ($attr{'value'} || $attr{'gui'} || $attr{'playing'}) {
+		$attr{'status'} = 1;
+	}
+	if ($attr{'status'} || $attr{'exists'}) {
+		$attr{'mtime'} = 1;
+	}
+
+	# Push ATTR into the file hash
+	$file{'attr'} = \%attr;
 
-	# Push a hash ref
-	$files{$file} = \%tmp;
+	# Push FILE into the files hash
+	$files{$name} = \%file;
 }
 
 # Delete any existing input files, to ensure our state is reset
@@ -231,31 +285,34 @@ while (1) {
 		}
 
 		# Always record the previous status and clear the new one
-		$file->{'last'}   = $file->{'status'};
-		$file->{'status'} = 0;
+		$file->{'last'}  = $file->{'value'};
+		$file->{'value'} = 0;
 
-		# Track available/unavailable files
-		if (!($file->{'type'} =~ /^EXISTS/)) {
-			my $wasAvailable = $file->{'available'};
-			$file->{'available'} = -r $file->{'path'} ? 1 : 0;
-			if ($wasAvailable != $file->{'available'}) {
+		# Track available/unavailable status in each cycle
+		{
+			my $wasAvailable = $file->{'attr'}->{'available'};
+			$file->{'attr'}->{'available'} = -r $file->{'path'} ? 1 : 0;
+			if ($wasAvailable != $file->{'attr'}->{'available'}) {
 
 				# Reset and extras for this file
 				if (exists($EXTRAS{ $file->{'name'} })) {
 					foreach my $extra (keys(%{ $EXTRAS{ $file->{'name'} } })) {
 						my $name = $file->{'name'} . '_' . $extra;
-						$files{$name}{'last'}   = $files{$name}{'status'};
-						$files{$name}{'status'} = 0;
+						$files{$name}{'last'}  = $files{$name}{'value'};
+						$files{$name}{'value'} = 0;
 					}
 				}
 
 				# Determine which display device we have (if any)
 				if (exists($DISPLAY_DEVS{ $file->{'name'} })) {
 					$DISPLAY = $file->{'name'};
+					if ($DEBUG) {
+						print STDERR 'Selecting display device: ' . $DISPLAY . "\n";
+					}
 				}
 
 				if ($DEBUG) {
-					if ($file->{'available'}) {
+					if ($file->{'attr'}->{'available'}) {
 						print STDERR 'Added file ' . $file->{'name'} . ': ' . $file->{'path'} . "\n";
 					} else {
 						print STDERR 'Dropped file ' . $file->{'name'} . ': ' . $file->{'path'} . "\n";
@@ -265,20 +322,33 @@ while (1) {
 		}
 
 		# Skip unavailable files
-		if (!$file->{'available'}) {
+		if (!$file->{'attr'}->{'available'}) {
 			next;
 		}
 
-		# Record the last update for STATUS and MTIME files
-		if ($file->{'type'} =~ /^STATUS/ || $file->{'type'} =~ /^MTIME/) {
-			$file->{'update'} = mtime($file->{'path'});
+		# Record the last update for MTIME files
+		if ($file->{'attr'}->{'mtime'}) {
+			my $mtime = mtime($file->{'path'});
+
+			# All EXISTS files have MTIME set, and mtime returns 0 if the file does not exist, so we can overload this check
+			if ($file->{'attr'}->{'exists'}) {
+				if ($mtime > 0) {
+					$file->{'update'} = $mtime;
+					$file->{'value'}  = 1;
+				} elsif ($file->{'last'}) {
+					$file->{'update'} = time();
+				}
+			} else {
+				$file->{'update'} = $mtime;
+			}
+
 			if ($DEBUG) {
-				print STDERR 'Last change: ' . $file->{'name'} . ': ' . localtime($file->{'update'}) . "\n";
+				print STDERR 'Mtime: ' . $file->{'name'} . ': ' . $file->{'value'} . ':' . $file->{'update'} . "\n";
 			}
 		}
 
 		# Grab the state from STATUS files
-		if ($file->{'type'} =~ /^STATUS/) {
+		if ($file->{'attr'}->{'status'}) {
 			my $text = '';
 			{
 				if (!open(my $fh, $file->{'path'})) {
@@ -290,25 +360,25 @@ while (1) {
 				}
 			}
 
-			# Record the main status for the file
-			if ($file->{'type'} eq 'STATUS_PLAYING') {
+			# Parse the value for the file
+			if ($file->{'attr'}->{'value'}) {
+				$text =~ s/\n$//;
+				$file->{'value'} = $text;
+			} elsif ($file->{'attr'}->{'playing'}) {
 				if ($text =~ /PlayStatus\:Playing/) {
-					$file->{'status'} = 1;
+					$file->{'value'} = 1;
 				}
-			} elsif ($file->{'type'} eq 'STATUS_GUI') {
+			} elsif ($file->{'attr'}->{'gui'}) {
 				if (!($text =~ /ActiveWindowName\:Fullscreen video/)) {
-					$file->{'status'} = 1;
+					$file->{'value'} = 1;
 				}
-			} elsif ($file->{'type'} eq 'STATUS_VALUE') {
-				$text =~ s/\n$//;
-				$file->{'status'} = $text;
 			} else {
 				if ($text =~ /1/) {
-					$file->{'status'} = 1;
+					$file->{'value'} = 1;
 				}
 			}
 			if ($DEBUG) {
-				print STDERR 'Status: ' . $file->{'name'} . ': ' . $file->{'status'} . "\n";
+				print STDERR 'Status: ' . $file->{'name'} . ': ' . $file->{'value'} . "\n";
 			}
 
 			# Handle extras, if any
@@ -316,34 +386,20 @@ while (1) {
 				foreach my $extra (keys(%{ $EXTRAS{ $file->{'name'} } })) {
 
 					my $name = $file->{'name'} . '_' . $extra;
-					$files{$name}{'last'}   = $files{$name}{'status'};
-					$files{$name}{'status'} = 0;
+					$files{$name}{'last'}   = $files{$name}{'value'};
+					$files{$name}{'value'}  = 0;
 					$files{$name}{'update'} = $file->{'update'};
 
 					if ($text =~ $EXTRAS{ $file->{'name'} }{$extra}) {
-						$files{$name}{'status'} = $1;
+						$files{$name}{'value'} = $1;
 					}
 
 					if ($DEBUG) {
-						print STDERR 'Status (extra): ' . $name . ': ' . $files{$name}{'status'} . "\n";
+						print STDERR 'Status (extra): ' . $name . ': ' . $files{$name}{'value'} . "\n";
 					}
 				}
 			}
 		}
-
-		# Check for the presence of EXISTS files and record their last change
-		if ($file->{'type'} =~ /^EXISTS/) {
-			my $mtime = mtime($file->{'path'});
-			if ($mtime > 0) {
-				$file->{'status'} = 1;
-				$file->{'update'} = $mtime;
-			} elsif ($file->{'last'}) {
-				$file->{'update'} = time();
-			}
-			if ($DEBUG) {
-				print STDERR 'Exists: ' . $file->{'name'} . ': ' . $file->{'status'} . ':' . $file->{'update'} . "\n";
-			}
-		}
 	}
 
 	# Set the global update timestamp
@@ -353,15 +409,35 @@ while (1) {
 		}
 	}
 
+	# Determine some intermediate state data
+	my $playing = 0;
+	if (exists($files{'PLAYING'}) && $files{'PLAYING'}->{'value'}) {
+		$playing = 1;
+	}
+	my $video = 0;
+	if (exists($files{'PLAYING_TYPE'}) && $files{'PLAYING_TYPE'}->{'value'} ne 'Audio') {
+		$video = 1;
+	} elsif (!exists($files{'PLAYING_TYPE'})) {
+		$video = 1;
+	}
+
 	# Calculate the new state
 	$stateLast = $state;
-	if (exists($files{$DISPLAY}) && $files{$DISPLAY}->{'status'}) {
+	if (!defined($DISPLAY) || !exists($files{$DISPLAY})) {
 
-		# We are always either playing or paused if the display is on
-		# When we're playing "Audio" assume we are paused
-		if (   (exists($files{'PLAYING'}) && $files{'PLAYING'}->{'status'})
-			&& ((exists($files{'PLAYING_TYPE'}) && $files{'PLAYING_TYPE'}->{'status'} ne 'Audio') || !exists($files{'PLAYING_TYPE'})))
-		{
+		# If there's no display the state is always PLAY or PAUSE, as indicated by the master
+		if ($playing) {
+			$state = 'PLAY';
+		} else {
+			$state = 'PAUSE';
+		}
+
+	} elsif ($files{$DISPLAY}->{'value'}) {
+
+		# If a display exists and is on:
+		# PLAY when video is active and playing
+		# PAUSE any other time (including when audio is active)
+		if ($playing && $video) {
 			$state = 'PLAY';
 		} else {
 			$state = 'PAUSE';
@@ -369,12 +445,12 @@ while (1) {
 
 	} else {
 
-		# If the display is off, check the timeouts
+		# If the display exists but is off, check the timeouts to determine MOTION vs. OFF
 		my $timeSinceUpdate = time() - $updateLast;
 		if ($timeSinceUpdate > $STATE_TIMEOUT) {
 			$state = 'OFF';
 		} elsif ($timeSinceUpdate < $STATE_TIMEOUT) {
-			if (exists($files{'NO_MOTION'}) && $files{'NO_MOTION'}->{'status'}) {
+			if (exists($files{'NO_MOTION'}) && $files{'NO_MOTION'}->{'value'}) {
 				$state = 'OFF';
 			} else {
 				$state = 'MOTION';
@@ -387,7 +463,7 @@ while (1) {
 
 	# Clear EXISTS_ON files when the main state is "OFF" (and before we append their status)
 	foreach my $file (values(%files)) {
-		if ($file->{'type'} eq 'EXISTS_ON' && $file->{'status'} && $state eq 'OFF') {
+		if ($file->{'attr'}->{'clear_off'} && $file->{'value'} && $state eq 'OFF') {
 			unlink($file->{'path'});
 			$file->{'stauts'} = 0;
 			if ($DEBUG) {
@@ -401,7 +477,7 @@ while (1) {
 	{
 		my @statTime = ();
 		foreach my $file (values(%files)) {
-			my $text = $file->{'status'};
+			my $text = $file->{'value'};
 			$text =~ s/\s/ /g;
 			$text =~ s/\|/-/g;
 			push(@statTime, $file->{'name'} . '|' . $text . '|' . $file->{'update'});
@@ -411,7 +487,7 @@ while (1) {
 
 	# Clear EXISTS_CLEAR files immediately (but after we append their status)
 	foreach my $file (values(%files)) {
-		if ($file->{'type'} eq 'EXISTS_CLEAR' && $file->{'status'}) {
+		if ($file->{'attr'}->{'clear'} && $file->{'value'}) {
 			unlink($file->{'path'});
 			$file->{'stauts'} = 0;
 			if ($DEBUG) {
@@ -427,7 +503,7 @@ while (1) {
 
 	# Update on any status change
 	foreach my $file (values(%files)) {
-		if ($file->{'status'} ne $file->{'last'}) {
+		if ($file->{'value'} ne $file->{'last'}) {
 			$update = 1;
 			last;
 		}

+ 2 - 2
pms/optimize.sh

@@ -2,8 +2,8 @@
 
 # Delay if we are currently scanning
 WAIT=0
-DELAY=30
-MAX_WAIT=300
+DELAY=5
+MAX_WAIT=600
 while ~/bin/video/pms/isScanning.sh; do
 	sleep $DELAY
 	WAIT=$(( $WAIT + $DELAY ))