chiark / gitweb /
bin/disorder-notify: Use `select' to read the log in non-blocking mode.
authorMark Wooding <mdw@distorted.org.uk>
Tue, 2 Jun 2020 10:06:44 +0000 (11:06 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Tue, 2 Jun 2020 16:20:38 +0000 (17:20 +0100)
This involves handling the line splitting ourselves, but this is quite
straightforward in Perl.

bin/disorder-notify

index c68e50c9fd7240bd8ccfa70421699d16b718d98e..3c570734a10df8d1658adb06a082992d1c934ed9 100755 (executable)
@@ -187,36 +187,56 @@ sub watch_and_notify0 ($) {
     notify "$TITLE: Now playing", format_now_playing %$info;
   }
 
-  while (my $line = readline $sk_log) {
-    my @f = split_fields $line;
-
-    if ($f[1] eq "state") {
-      my $msg = undef;
-      if ($f[2] eq "disable_random") { $msg = "Random play disabled"; }
-      elsif ($f[2] eq "enable_random") { $msg = "Random play enabled"; }
-      elsif ($f[2] eq "disable_play") { $msg = "Playing disabled"; }
-      elsif ($f[2] eq "enable_play") { $msg = "Playing enabled"; }
-      elsif ($f[2] eq "pause") { $msg = "Paused"; }
-      elsif ($f[2] eq "resume") { $msg = "Playing"; }
-      notify "$TITLE state", $msg if defined $msg;
-    } elsif ($f[1] eq "playing") {
-      my %info;
-      $info{track} = $f[2];
-      $info{submitter} = $f[3] if @f > 3;
-      decode_track_name $sk, %info;
-      notify "$TITLE: Now playing", format_now_playing %info;
-    } elsif ($f[1] eq "scratched") {
-      my %info;
-      $info{track} = $f[2];
-      decode_track_name $sk, %info;
-      notify "$TITLE: Scratched by $f[3]", format_now_playing %info;
+  fcntl $sk_log, F_SETFL, (fcntl $sk_log, F_GETFL, 0) | O_NONBLOCK;
+  my $buffer = "";
+  my @lines = ();
+  my $rdin = ""; vec($rdin, (fileno $sk_log), 1) = 1;
+
+  WATCH: for (;;) {
+    for my $line (@lines) {
+      my @f = split_fields $line;
+      if ($f[1] eq "state") {
+       my $msg = undef;
+       if ($f[2] eq "disable_random") { $msg = "Random play disabled"; }
+       elsif ($f[2] eq "enable_random") { $msg = "Random play enabled"; }
+       elsif ($f[2] eq "disable_play") { $msg = "Playing disabled"; }
+       elsif ($f[2] eq "enable_play") { $msg = "Playing enabled"; }
+       elsif ($f[2] eq "pause") { $msg = "Paused"; }
+       elsif ($f[2] eq "resume") { $msg = "Playing"; }
+       notify "$TITLE state", $msg if defined $msg;
+      } elsif ($f[1] eq "playing") {
+       my %info;
+       $info{track} = $f[2];
+       $info{submitter} = $f[3] if @f > 3;
+       decode_track_name $sk, %info;
+       notify "$TITLE: Now playing", format_now_playing %info;
+      } elsif ($f[1] eq "scratched") {
+       my %info;
+       $info{track} = $f[2];
+       decode_track_name $sk, %info;
+       notify "$TITLE: Scratched by $f[3]", format_now_playing %info;
+      }
     }
+
+    last WATCH unless $sk_log;
+    select my $rdout = $rdin, undef, undef, undef;
+    READ: for (;;) {
+      my ($b, $n);
+      eval { $n = sysread $sk_log, $b, 4096; };
+      if ($@ && $@->errno == EAGAIN) { last READ; }
+      elsif ($@) { die $@; }
+      elsif (!$n) { close $sk_log; $sk_log = undef; }
+      else { $buffer .= $b; }
+    }
+
+    @lines = split /\n/, $buffer, -1;
+    $buffer = pop @lines;
   }
 
   notify "$TITLE state", "Lost connection";
 
   close $sk;
-  close $sk_log;
+  close $sk_log if defined $sk_log;
 }
 
 sub watch_and_notify ($) {