Parcourir la source

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

Zachary Kotlarek il y a 13 ans
Parent
commit
785a637b5c
2 fichiers modifiés avec 95 ajouts et 21 suppressions
  1. 14 1
      dmx/qt_player.pl
  2. 81 20
      dmx/rifftrax.pl

+ 14 - 1
dmx/qt_player.pl

@@ -96,6 +96,11 @@ while (1) {
 		}
 	}
 
+	# Ensure the output file always exists
+	if (!-r $OUTPUT_FILE) {
+		printFiles();
+	}
+
 	# Ensure "silence" is always available -- reset if it goes away
 	if (!exists($FILES{'SILENCE'})) {
 		die("We need only the SILENCE\n");
@@ -156,16 +161,24 @@ sub load($$) {
 	IPC::System::Simple::system('open', '-a', 'QuickTime Player', $path);
 
 	# Wait for QT to load the new file
-	# To avoid indefinate hangs this will give up after 5 seconds. When it does the results are undefined.
+	# To avoid indefinate hangs this will give up after 5 seconds
 	my @cmd = ('tell application "QuickTime Player"');
 	push(@cmd, 'set endDate to current date + (5/60 * minutes)');
 	push(@cmd, 'repeat while (count items of every document) <= ' . $count . ' and current date < endDate');
 	push(@cmd, 'delay 0.1');
 	push(@cmd, 'end repeat');
+	push(@cmd, 'if (count items of every document) > ' . $count . ' then');
 	push(@cmd, 'get document 1');
+	push(@cmd, 'end if');
 	push(@cmd, 'end tell');
 	my $doc = Audio::runApplescript(join("\n", @cmd));
 
+	# Reset if we cannot open -- something is out-of-sync
+	if (!$doc) {
+		init();
+		return;
+	}
+
 	# Clean up the document name
 	$doc =~ s/^\s*document //;
 	$doc =~ s/\s+$//;

+ 81 - 20
dmx/rifftrax.pl

@@ -17,6 +17,7 @@ my $MEDIA_PATH     = `~/bin/video/mediaPath`;
 my $CONFIG_PATH    = $MEDIA_PATH . '/DMX/RiffTrax';
 my $ACTION_DELAY   = 0.1;
 my $JUMP_THRESHOLD = 5;
+my $LEADIN_TIME    = 5;
 my $VOLUME_RIFF    = 65;
 my $VOLUME_STD     = 40;
 my $VOL_STEP       = 1 / 20;
@@ -28,6 +29,7 @@ sub pauseRiff();
 sub getRiffRate();
 sub setRiffRate($);
 sub parseConfig($$);
+sub playPausePlex();
 
 # App config
 my $DATA_DIR     = DMX::dataDir();
@@ -60,6 +62,7 @@ my $pullLast  = time();
 my $lastSync  = time();
 my $playing   = 0;
 my $delay     = $DELAY;
+my $leadin    = 0;
 
 # Read the config
 parseConfig($CONFIG_PATH, \%RIFFS);
@@ -138,6 +141,20 @@ while (1) {
 		$title     = $exists{'PLAYING_TITLE'};
 	}
 
+	# Convert the video timestamp to seconds
+	my $videoTime = 0;
+	if ($exists{'PLAYING_POSITION'}) {
+		my @parts = split(/\:/, $exists{'PLAYING_POSITION'});
+		$videoTime = 0;
+		if (scalar(@parts) == 3) {
+			$videoTime = ($parts[0] * 3600) + ($parts[1] * 60) + $parts[2];
+		} elsif (scalar(@parts) == 2) {
+			$videoTime = ($parts[0] * 60) + $parts[1];
+		} else {
+			$videoTime = $parts[0];
+		}
+	}
+
 	# Update our state when the PLAYING_TITLE changes
 	if ($title ne $titleLast) {
 
@@ -155,7 +172,8 @@ while (1) {
 
 			# Close the audio file
 			Audio::unload('RIFF');
-			$riff = 0;
+			$riff   = 0;
+			$leadin = 0;
 
 			# Warm fuzzies
 			DMX::say('RiffTrax complete');
@@ -185,6 +203,12 @@ while (1) {
 
 			# Reduce the delay while playing so we sync faster
 			$delay = 1;
+
+			# Enable LEADIN if we're near the beginning of the movie
+			if ($RIFFS{$riff}->{'offset'} > $LEADIN_TIME && $videoTime < $LEADIN_TIME) {
+				playPausePlex();
+				$leadin = 1;
+			}
 		}
 	}
 
@@ -209,15 +233,29 @@ while (1) {
 		rename($tmp, $OUTPUT_FILE);
 	}
 
-	# Play/pause to match the video state
-	if ($riff && exists($exists{'PLAYING'})) {
-		if (!$exists{'PLAYING'} && $playing) {
+	# Skip further processing if we don't have valid state data from Plex
+	if (!exists($exists{'PLAYING'})) {
+		next;
+	}
+
+	# Play/pause to match the video or LEADIN state
+	if ($riff) {
+		if ($leadin) {
+			if (!$playing) {
+				playRiff();
+			}
+		} elsif (!$exists{'PLAYING'} && $playing) {
 			pauseRiff();
 		} elsif ($exists{'PLAYING'} && !$playing) {
 			playRiff();
 		}
 	}
 
+	# Skip further processing if we don't have valid sync data from Plex
+	if (!$videoTime) {
+		next;
+	}
+
 	# Sync at most once per second
 	if ($riff && $lastSync < time()) {
 		if ($DEBUG) {
@@ -225,10 +263,9 @@ while (1) {
 		}
 		$lastSync = time();
 
-		# Get the video and riff playback positions
-		my $rate      = getRiffRate();
-		my $riffTime  = Audio::position('RIFF', undef());
-		my $videoTime = $exists{'PLAYING_POSITION'};
+		# Get the riff playback state
+		my $rate = getRiffRate();
+		my $riffTime = Audio::position('RIFF', undef());
 
 		# Update our local playing state tracker
 		# The rate is always 0 when paused (Audio::playing uses this same methodology)
@@ -238,17 +275,6 @@ while (1) {
 			$playing = 0;
 		}
 
-		# Convert the timestamp to seconds
-		my @parts = split(/\:/, $videoTime);
-		$videoTime = 0;
-		if (scalar(@parts) == 3) {
-			$videoTime = ($parts[0] * 3600) + ($parts[1] * 60) + $parts[2];
-		} elsif (scalar(@parts) == 2) {
-			$videoTime = ($parts[0] * 60) + $parts[1];
-		} else {
-			$videoTime = $parts[0];
-		}
-
 		# Calculate the adjusted riff time and the error between the riff and video times
 		my $riffAdjTime = $riffTime - $RIFFS{$riff}->{'offset'};
 		my $error       = $videoTime - $riffAdjTime;
@@ -262,9 +288,38 @@ while (1) {
 			print STDERR "\tVideo time: " . $videoTime . "\n";
 			print STDERR "\tAdjusted riff time: " . $riffAdjTime . "\n";
 			print STDERR "\tError: " . $error . "\n";
+			print STDERR "\tLeadin: " . $leadin . "\n";
 		}
 
-		# Adjust the riff position if we're off by 0.5 seconds or more
+		# If LEADIN is still active
+		if ($leadin) {
+
+			# Deactivate LEADIN if the movie advances outside the LEADIN_TIME window
+			if ($videoTime > $LEADIN_TIME) {
+				$leadin = 0;
+				if ($DEBUG) {
+					print STDERR "LEADIN canceled due to video time\n";
+				}
+			}
+
+			# Start the movie when we reach the sync point
+			if ($RIFFS{$riff}->{'offset'} <= $riffTime) {
+				if (!$exists{'PLAYING'}) {
+					playPausePlex();
+				}
+				$leadin = 0;
+				if ($DEBUG) {
+					print STDERR "LEADIN canceled due to synchronization\n";
+				}
+			}
+
+			# Skip normal syncing until LEADIN is cleared
+			if ($leadin) {
+				next;
+			}
+		}
+
+		# Adjust the riff rate/position if we're off by 0.5 seconds or more
 		if ($errorAbs > 0.5) {
 
 			# Calculate the new position, including an ACTION_DELAY adjustment to compensate for time elapsed in this process
@@ -425,3 +480,9 @@ sub parseConfig($$) {
 	# Record the last update time
 	$riffs->{'_LAST_CONFIG_UPDATE'} = time();
 }
+
+# The UDP listener would be more portable, but I already know how to do this
+# The PMS playback API would work too, but this script currently knows nothing of the PMS
+sub playPausePlex() {
+	Audio::runApplescript('tell application "System Events" to key code 49');
+}