| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- #!/usr/bin/perl
- use strict;
- use warnings;
- use POSIX;
- use File::Touch;
- use File::Basename;
- use Time::HiRes qw( usleep sleep time );
- use IPC::System::Simple;
- # Package name
- package Audio;
- # Config
- my $MEDIA_PATH = `~/bin/video/mediaPath`;
- my %FILES = ();
- # Debug
- my $DEBUG = 0;
- if ($ENV{'DEBUG'}) {
- $DEBUG = 1;
- }
- sub runApplescript($) {
- my ($script) = @_;
- if ($DEBUG) {
- print STDERR 'AppleScript: ' . $script . "\n";
- }
- my $retval = IPC::System::Simple::capture('osascript', '-e', $script);
- if ($DEBUG) {
- print STDERR "\tAppleScript result: " . $retval . "\n";
- }
- return $retval;
- }
- sub add($$) {
- my ($name, $path) = @_;
- if ($DEBUG) {
- print STDERR 'Audio::add(): ' . $name . "\n";
- }
- # Construct an absolute file path
- if (!($path =~ /^\//)) {
- $path = $MEDIA_PATH . '/' . $path;
- }
- # Validate
- if (!-r $path) {
- die('Invalid audio path: ' . $path . "\n");
- }
- # We only support one document per name
- drop($name);
- # Append the array
- my %tmp = ('path' => $path);
- $FILES{$name} = \%tmp;
- }
- sub drop($) {
- my ($name) = @_;
- if ($DEBUG) {
- print STDERR 'Audio::drop(): ' . $name . "\n";
- }
- # Unload as necessary
- if (loaded($name)) {
- stop($name);
- unload($name);
- }
- # Drop as necessary
- if (available($name)) {
- delete($FILES{$name});
- }
- }
- sub loaded($) {
- my ($name) = @_;
- if ($DEBUG) {
- print STDERR 'Audio::loaded(): ' . $name . "\n";
- }
- if (available($name) && defined($FILES{$name}->{'name'})) {
- return 1;
- }
- return 0;
- }
- sub available($) {
- my ($name) = @_;
- if ($DEBUG) {
- print STDERR 'Audio::available(): ' . $name . "\n";
- }
- if (defined($name) && defined($FILES{$name})) {
- return 1;
- }
- return 0;
- }
- sub play($) {
- my ($name) = @_;
- if ($DEBUG) {
- print STDERR 'Audio::play(): ' . $name . "\n";
- }
- # Start playback
- background($name);
- # Wait for it to complete
- my @cmd = ('tell application "QuickTime Player"');
- push(@cmd, 'repeat while playing of document ' . $FILES{$name}->{'name'} . ' = true');
- push(@cmd, 'delay 0.1');
- push(@cmd, 'end repeat');
- push(@cmd, 'end tell');
- runApplescript(join("\n", @cmd));
- }
- sub background($) {
- my ($name) = @_;
- if ($DEBUG) {
- print STDERR 'Audio::background(): ' . $name . "\n";
- }
- if (!loaded($name)) {
- die('Invalid QT document: ' . $name . "\n");
- }
- # Start playback
- my @cmd = ('tell application "QuickTime Player"');
- push(@cmd, 'set current time of document ' . $FILES{$name}->{'name'} . ' to 0');
- push(@cmd, 'play document ' . $FILES{$name}->{'name'});
- push(@cmd, 'end tell');
- runApplescript(join("\n", @cmd));
- }
- sub playing($) {
- my ($name) = @_;
- if ($DEBUG) {
- print STDERR 'Audio::playing(): ' . $name . "\n";
- }
- if (!loaded($name)) {
- die('Invalid QT document: ' . $name . "\n");
- }
- # Ask QT if the document is playing
- my $result = runApplescript('tell application "QuickTime Player" to get playing of document ' . $FILES{$name}->{'name'});
- if ($result =~ /true/i) {
- return 1;
- }
- return 0;
- }
- sub position($$) {
- my ($name, $new) = @_;
- if ($DEBUG) {
- print STDERR 'Audio::position(): ' . $name . "\n";
- }
- if (!loaded($name)) {
- die('Invalid QT document: ' . $name . "\n");
- }
- # Optionally set the audio position
- if ($new) {
- runApplescript('tell application "QuickTime Player" to set current time of document ' . $FILES{$name}->{'name'} . ' to ' . $new);
- }
- # Get the current playback position from QT
- return runApplescript('tell application "QuickTime Player" to get current time of document ' . $FILES{$name}->{'name'});
- }
- sub rate($$) {
- my ($name, $new) = @_;
- if ($DEBUG) {
- print STDERR 'Audio::rate(): ' . $name . "\n";
- }
- if (!loaded($name)) {
- die('Invalid QT document: ' . $name . "\n");
- }
- # Optionally set the playback rate
- if ($new) {
- runApplescript('tell application "QuickTime Player" to set rate of document ' . $FILES{$name}->{'name'} . ' to ' . $new);
- }
- # Get the current playback position from QT
- return runApplescript('tell application "QuickTime Player" to get rate of document ' . $FILES{$name}->{'name'});
- }
- sub stop($) {
- my ($name) = @_;
- if ($DEBUG) {
- print STDERR "Audio::stopAudio()\n";
- }
- # Allow control of all documents or a specific document
- my $doc = 'every document';
- if (!loaded($name)) {
- $doc = 'document ' . $FILES{$name}->{'name'};
- }
- # Stop and rewind all QT documents
- runApplescript('tell application "QuickTime Player" to stop ' . $doc);
- runApplescript('tell application "QuickTime Player" to set current time of ' . $doc . ' to 0');
- # Bring Plex back to the front
- runApplescript('tell application "Plex" to activate');
- }
- sub unload($) {
- my ($name) = @_;
- if ($DEBUG) {
- print STDERR 'Audio::loadAudio(): ' . $name . "\n";
- }
- if (!available($name)) {
- die('Invalid QT document: ' . $name . "\n");
- }
- # Nothing to do if the file isn't loaded
- if (!loaded($name)) {
- return;
- }
- # Close to document
- runApplescript('tell application "QuickTime Player" to close document ' . $FILES{$name}->{'name'});
- # Delete our local handle
- delete($FILES{$name}->{'name'});
- }
- sub load($) {
- my ($name) = @_;
- if ($DEBUG) {
- print STDERR 'Audio::loadAudio(): ' . $name . "\n";
- }
- if (!available($name)) {
- die('Invalid QT document: ' . $name . "\n");
- }
- # Unload first, if we're already loaded
- if (loaded($name)) {
- unload($name);
- }
- # Find out how many files are already open
- my $count = runApplescript('tell application "QuickTime Player" to count items of every document');
- # Open the file
- IPC::System::Simple::system('open', '-a', 'QuickTime Player', $FILES{$name}->{'path'});
- # Wait for QT to load the new file
- my @cmd = ('tell application "QuickTime Player"');
- push(@cmd, 'repeat while (count items of every document) <= ' . $count);
- push(@cmd, 'delay 0.1');
- push(@cmd, 'end repeat');
- push(@cmd, 'get document 1');
- push(@cmd, 'end tell');
- my $doc = runApplescript(join("\n", @cmd));
- # Clean up the document name
- $doc =~ s/^\s*document //;
- $doc =~ s/\s+$//;
- $doc =~ s/\"/\\\"/g;
- $doc = '"' . $doc . '"';
- # Save the document handle
- $FILES{$name}->{'name'} = $doc;
- # Bring Plex back to the front
- runApplescript('tell application "Plex" to activate');
- }
- sub init() {
- if ($DEBUG) {
- print STDERR "Audio::init()\n";
- }
- # Close all QT documents and relaunch QT Player
- runApplescript('tell application "QuickTime Player" to close every document');
- runApplescript('tell application "QuickTime Player" to quit');
- sleep(1);
- IPC::System::Simple::system('open', '-a', 'QuickTime Player');
- # Always load and play the SILENCE file (for sanity and general init)
- add('SILENCE', 'DMX/Silence.wav');
- load('SILENCE');
- play('SILENCE');
- }
- # Always return true
- 1;
|