rope.pl 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use Time::HiRes qw( usleep );
  5. use File::Temp qw( tempfile );
  6. # Prototypes
  7. sub mtime($);
  8. # User config
  9. my %DIM = (
  10. 'OFF' => { 'value' => 0, 'time' => 10000 },
  11. 'PLAY' => { 'value' => 64, 'time' => 250 },
  12. 'PAUSE' => { 'value' => 192, 'time' => 1000 }
  13. );
  14. my $TIMEOUT = 600; # Seconds
  15. my $DELAY = 0.5 * 1000000; # Microseconds
  16. # App config
  17. my $TEMP_DIR = `getconf DARWIN_USER_TEMP_DIR`;
  18. chomp($TEMP_DIR);
  19. my $DATA_DIR = $TEMP_DIR . '/plexMonitor';
  20. my $EXEC_DIR = $ENV{'HOME'} . '/bin/video/dmx';
  21. # Ensure python can find its OLA imports
  22. my $PYTHON_PATH = "/opt/local/lib/python2.7/site-packages:/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages";
  23. if ($ENV{'PYTHONPATH'}) {
  24. $PYTHON_PATH = $ENV{'PYTHONPATH'} . ':' . $PYTHON_PATH;
  25. }
  26. $ENV{'PYTHONPATH'} = $PYTHON_PATH;
  27. # Debug
  28. my $DEBUG = 0;
  29. if ($ENV{'DEBUG'}) {
  30. $DEBUG = 1;
  31. }
  32. # Sanity check
  33. if (!-d $EXEC_DIR || !-d $DATA_DIR) {
  34. die("Bad config\n");
  35. }
  36. # Always force lights out at launch
  37. system($EXEC_DIR . '/setChannels.py', 0);
  38. # State
  39. my $state = 'INIT';
  40. my $stateLast = $state;
  41. my $playing = 0;
  42. my $playingLast = $playing;
  43. my $valueLast = $DIM{'OFF'}{'value'};
  44. my $updateLast = 0;
  45. # Loop forever
  46. while (1) {
  47. # Monitor the PLAY_STATUS file for changes and state
  48. $playingLast = $playing;
  49. {
  50. my $mtime = mtime($DATA_DIR . '/PLAY_STATUS');
  51. if ($mtime > $updateLast) {
  52. $updateLast = $mtime;
  53. # Grab the PLAY_STATUS value
  54. $playing = 0;
  55. my $fh;
  56. open($fh, $DATA_DIR . '/PLAY_STATUS')
  57. or die("Unable to open PLAY_STATUS\n");
  58. my $text = <$fh>;
  59. close($fh);
  60. if ($text =~ /1/) {
  61. $playing = 1;
  62. }
  63. }
  64. }
  65. # Monitor the GUI and PLAYING files for changes only
  66. {
  67. my $mtime = mtime($DATA_DIR . '/PLAYING');
  68. if ($mtime > $updateLast) {
  69. $updateLast = $mtime;
  70. }
  71. $mtime = mtime($DATA_DIR . '/GUI');
  72. if ($mtime > $updateLast) {
  73. $updateLast = $mtime;
  74. }
  75. }
  76. # Calculate the new state
  77. $stateLast = $state;
  78. if ($playing != $playingLast) {
  79. if ($DEBUG) {
  80. print STDERR "Play state changed\n";
  81. }
  82. # We always need to update when the play state changes
  83. if ($playing) {
  84. $state = 'PLAY';
  85. } else {
  86. $state = 'PAUSE';
  87. }
  88. } elsif (!$playing) {
  89. # If we're not playing, check the timeout
  90. my $timeSinceUpdate = time() - $updateLast;
  91. if ($state ne 'OFF' && $timeSinceUpdate > $TIMEOUT) {
  92. $state = 'OFF';
  93. } elsif ($state eq 'OFF' && $timeSinceUpdate < $TIMEOUT) {
  94. $state = 'PAUSE';
  95. }
  96. }
  97. # Update the lighting state
  98. if ($stateLast ne $state) {
  99. if ($DEBUG) {
  100. print STDERR 'New state: ' . $state . "\n";
  101. print STDERR "\tTime: " . $DIM{$state}{'time'} . "\n";
  102. print STDERR "\tFrom: " . $valueLast . "\n";
  103. print STDERR "\tTo: " . $DIM{$state}{'value'} . "\n";
  104. }
  105. if ($valueLast != $DIM{$state}{'value'}) {
  106. system($EXEC_DIR . '/dimChannels.py', $DIM{$state}{'time'}, $valueLast, $DIM{$state}{'value'});
  107. } elsif ($DEBUG) {
  108. print STDERR "Skipping noop dim request\n";
  109. }
  110. $valueLast = $DIM{$state}{'value'};
  111. # Save the state and value to disk
  112. my ($fh, $tmp) = tempfile($DATA_DIR . '/ROPE.XXXXXXXX', 'UNLINK' => 0);
  113. print $fh 'State: ' . $state . "\nValue: " . $valueLast . "\n";
  114. close($fh);
  115. rename($tmp, $DATA_DIR . '/ROPE');
  116. }
  117. # Wait and loop
  118. usleep($DELAY);
  119. }
  120. sub mtime($) {
  121. my ($file) = @_;
  122. my (undef(), undef(), undef(), undef(), undef(), undef(), undef(), undef(), undef(), $mtime, undef(), undef(), undef()) = stat($file);
  123. return $mtime;
  124. }