X-Git-Url: https://git.distorted.org.uk/~mdw/profile/blobdiff_plain/f6ef7584f281ba1335958bdc79186fc4400adc7a..fbc10dba9a1ff359cf6f3774a240189e4cd25512:/bin/disorder-notify diff --git a/bin/disorder-notify b/bin/disorder-notify index 3c57073..2b0d5e8 100755 --- a/bin/disorder-notify +++ b/bin/disorder-notify @@ -5,6 +5,8 @@ use strict; use DisOrder; use File::FcntlLock; +use Getopt::Long qw{:config gnu_compat bundling + require_order no_getopt_compat}; use POSIX qw{:errno_h :fcntl_h}; ###-------------------------------------------------------------------------- @@ -14,6 +16,7 @@ my %C = (config => "$ENV{HOME}/.disorder/passwd", lockdir => "$ENV{HOME}/.disorder/", mixer => "Master,0"); +(my $PROG = $0) =~ s:^.*/::; my $TITLE = "DisOrder"; my $VARIANT = "default"; if (-l $C{config} && (my $t = readlink $C{config}) =~ /^passwd\.(.*)$/) @@ -124,8 +127,16 @@ sub get_state0 ($) { return \%st; } +my $CONF = undef; + +sub configured_connection (;$) { + my ($quietp) = @_; + $CONF //= load_config $C{config}; + return connect_to_server %$CONF, $quietp // 0; +} + sub get_state () { - my $sk = connect_to_server $C{config}; + my $sk = configured_connection; send_command0 $sk, "log"; my $st = get_state0 $sk; close $sk; @@ -147,18 +158,6 @@ sub fmt_duration ($) { return sprintf "%d:%02d", int $n/60, $n%60; } -sub format_now_playing (\%) { - my ($info) = @_; - exists $info->{track} or return "Nothing."; - my $r = "$info->{artist}: ‘$info->{title}’"; - $r .= ", from ‘$info->{album}’" if $info->{album}; - exists $info->{sofar} && exists $info->{length} and - $r .= sprintf " (%s/%s)", - fmt_duration $info->{sofar}, fmt_duration $info->{length}; - $r .= "\n(chosen by $info->{submitter})" if exists $info->{submitter}; - return $r; -} - sub get_now_playing ($) { my ($sk) = @_; my $r = send_command $sk, "playing"; @@ -170,11 +169,28 @@ sub get_now_playing ($) { return \%info; } +sub format_now_playing (;\%) { + my ($info) = @_; + unless (defined $info) { + my $sk = configured_connection; + $info = get_now_playing $sk; + close $sk; + } + exists $info->{track} or return "Nothing."; + my $r = "$info->{artist}: ‘$info->{title}’"; + $r .= ", from ‘$info->{album}’" if $info->{album}; + exists $info->{sofar} && exists $info->{length} and + $r .= sprintf " (%s/%s)", + fmt_duration $info->{sofar}, fmt_duration $info->{length}; + $r .= "\n(chosen by $info->{submitter})" if exists $info->{submitter}; + return $r; +} + sub watch_and_notify0 ($) { my ($now_playing) = @_; - my $sk = connect_to_server $C{config}, 1; - my $sk_log = connect_to_server $C{config}, 1; + my $sk = configured_connection 1; + my $sk_log = configured_connection 1; send_command0 $sk_log, "log"; my $st = get_state0 $sk_log; @@ -191,18 +207,25 @@ sub watch_and_notify0 ($) { my $buffer = ""; my @lines = (); my $rdin = ""; vec($rdin, (fileno $sk_log), 1) = 1; + my $loss; 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"; } + if ($f[2] eq "disable_random") + { $st->{random} = 0; $msg = "Random play disabled"; } + elsif ($f[2] eq "enable_random") + { $st->{random} = 1; $msg = "Random play enabled"; } + elsif ($f[2] eq "disable_play") + { $st->{play} = 0; $msg = "Playing disabled"; } + elsif ($f[2] eq "enable_play") + { $st->{play} = 1; $msg = "Playing enabled"; } + elsif ($f[2] eq "pause") + { $st->{pause} = 1; $msg = "Paused"; } + elsif ($f[2] eq "resume") + { $st->{pause} = 0; $msg = "Playing"; } notify "$TITLE state", $msg if defined $msg; } elsif ($f[1] eq "playing") { my %info; @@ -215,25 +238,33 @@ sub watch_and_notify0 ($) { $info{track} = $f[2]; decode_track_name $sk, %info; notify "$TITLE: Scratched by $f[3]", format_now_playing %info; + } elsif ($f[1] eq "completed" && !$st->{play}) { + notify "$TITLE state", "Stopped"; } } - 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; } - } + if (!$sk_log) { $loss = "EOF from server"; last WATCH; } + my $nfd = select my $rdout = $rdin, undef, undef, 60; + if (!$nfd) { + eval { print $sk_log "."; flush $sk_log; }; + if ($@) { $loss = "error from write: " . $@->errno; last WATCH; } + @lines = (); + } else { + READ: for (;;) { + my ($b, $n); + eval { $n = sysread $sk_log, $b, 4096; }; + if ($@ && $@->errno == EAGAIN) { last READ; } + elsif ($@) { $loss = "error from read: " . $@->errno; last WATCH; } + elsif (!$n) { close $sk_log; $sk_log = undef; last READ; } + else { $buffer .= $b; } + } - @lines = split /\n/, $buffer, -1; - $buffer = pop @lines; + @lines = split /\n/, $buffer, -1; + $buffer = pop @lines; + } } - notify "$TITLE state", "Lost connection"; + notify "$TITLE state", "Lost connection: $loss"; close $sk; close $sk_log if defined $sk_log; @@ -262,14 +293,14 @@ $OP{"volume-down"} = sub { run_discard_output "amixer", "sset", $C{mixer}, "5\%-"; }; $OP{"scratch"} = sub { - my $sk = connect_to_server $C{config}; + my $sk = configured_connection; send_command $sk, "scratch"; close $sk; }; $OP{"enable/disable"} = sub { my $st = get_state; - my $sk = connect_to_server $C{config}; + my $sk = configured_connection; if ($st->{play}) { send_command $sk, "disable"; } else { send_command $sk, "enable"; } close $sk; @@ -277,7 +308,7 @@ $OP{"enable/disable"} = sub { $OP{"play/pause"} = sub { my $st = get_state; - my $sk = connect_to_server $C{config}; + my $sk = configured_connection; if (!$st->{play}) { send_command $sk, "enable"; if ($st->{pause}) { send_command $sk, "resume"; } @@ -297,7 +328,7 @@ $OP{"watch"} = sub { }; $OP{"now-playing"} = sub { - my $sk = connect_to_server $C{config}; + my $sk = configured_connection; my $info = get_now_playing $sk; close $sk; print format_now_playing %$info; @@ -305,7 +336,7 @@ $OP{"now-playing"} = sub { }; $OP{"notify-now-playing"} = sub { - my $sk = connect_to_server $C{config}; + my $sk = configured_connection; my $info = get_now_playing $sk; close $sk; notify "$TITLE: Now playing", format_now_playing %$info; @@ -343,7 +374,39 @@ $OP{"next-config"} = sub { ###-------------------------------------------------------------------------- ### Main program. -if (@ARGV != 1) { print STDERR "usage: $0 OP\n"; exit 2; } +sub usage (\*) { + my ($fh) = @_; + print $fh "usage: $PROG [-u CONFIG] COMMAND\n"; +} + +sub help () { + usage *STDOUT; + print < sub { help; exit 0; }, + "u|user-config=s" => \$C{config} + or $bad = 1; +@ARGV == 1 or $bad = 1; +if ($bad) { usage *STDERR; exit 2; } my $op = $ARGV[0]; if (!exists $OP{$op}) { print STDERR "$0: unknown op `$op'\n"; exit 2; } $OP{$op}();