HDMIctrl.pl 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use IPC::System::Simple qw( system capture );
  5. use Time::HiRes qw( usleep sleep time );
  6. # Local modules
  7. use Cwd qw(abs_path);
  8. use File::Basename qw(dirname);
  9. use lib dirname(abs_path($0));
  10. use DMX;
  11. # Prototypes
  12. sub sendCmd($$);
  13. # App config
  14. my $DATA_DIR = DMX::dataDir();
  15. my $STATE_SOCK = 'HDMI_CTRL';
  16. my $HDMI_SOCK = 'HDMI';
  17. my $OUTPUT_FILE = $DATA_DIR . $STATE_SOCK;
  18. my $PUSH_TIMEOUT = 10;
  19. my $PULL_TIMEOUT = 60;
  20. my $DELAY = $PULL_TIMEOUT / 2;
  21. my $CMD_DELAY = 1.0;
  22. my @INIT_CMDS = ('POD_OFF');
  23. # Debug
  24. my $DEBUG = 0;
  25. if ($ENV{'DEBUG'}) {
  26. $DEBUG = 1;
  27. }
  28. # Sockets
  29. DMX::stateSocket($STATE_SOCK);
  30. DMX::stateSubscribe($STATE_SOCK);
  31. my $hdmi = DMX::clientSock($HDMI_SOCK);
  32. # State
  33. my $state = 'PLEX';
  34. my $stateLast = $state;
  35. my %exists = ();
  36. my $pushLast = 0;
  37. my $pullLast = time();
  38. my $update = 0;
  39. # Init
  40. foreach my $cmd (@INIT_CMDS) {
  41. $hdmi->send($cmd)
  42. or die('Unable to write command to HDMI socket: ' . $cmd . ": ${!}\n");
  43. }
  44. # Loop forever
  45. while (1) {
  46. # State is calculated; use newState to gather data
  47. my $newState = $state;
  48. # Wait for state updates
  49. my $cmdState = DMX::readState($DELAY, \%exists, undef(), undef());
  50. # Avoid repeated calls to time()
  51. my $now = time();
  52. # Record only valid states
  53. if (defined($cmdState)) {
  54. $newState = $cmdState;
  55. $pullLast = time();
  56. }
  57. # Die if we don't see regular updates
  58. if ($now - $pullLast > $PULL_TIMEOUT) {
  59. die('No update on state socket in past ' . $PULL_TIMEOUT . " seconds. Exiting...\n");
  60. }
  61. # Calculate the new state
  62. $stateLast = $state;
  63. if ($exists{'GAME'}) {
  64. $state = 'GAME';
  65. } else {
  66. $state = 'PLEX';
  67. }
  68. # Force updates on a periodic basis
  69. if (!$update && $now - $pushLast > $PUSH_TIMEOUT) {
  70. if ($DEBUG) {
  71. print STDERR "Forcing periodic update\n";
  72. }
  73. $update = 1;
  74. }
  75. # Force updates on any state change
  76. if (!$update && $stateLast ne $state) {
  77. if ($DEBUG) {
  78. print STDERR 'State change: ' . $stateLast . ' => ' . $state . "\n";
  79. }
  80. $update = 1;
  81. }
  82. # Rate-limit commands, in case we go dumb somewhere in the chain
  83. if ($update && $now < $pushLast + $CMD_DELAY) {
  84. if ($DEBUG) {
  85. print STDERR 'Ignoring overrate update: ' . $state . "\n";
  86. }
  87. $update = 0;
  88. }
  89. # Update the switch
  90. if ($update) {
  91. # Extra debugging to record pushes
  92. if ($DEBUG) {
  93. print STDERR 'State: ' . $state . "\n";
  94. }
  95. # Send state
  96. $hdmi->send($state)
  97. or die('Unable to write command to HDMI socket: ' . $state . ": ${!}\n");
  98. # Update the push time
  99. $pushLast = $now;
  100. # Clear the update flag
  101. $update = 0;
  102. }
  103. }