+#! /usr/bin/perl -w
+
+use autodie qw{:all};
+use strict;
+
+use DisOrder;
+
+(my $PROG = $0) =~ s:.*/::;
+
+sub grobble_dir (\@$$$);
+
+sub grobble_dir (\@$$$) {
+ my ($list, $sk, $root, $dir) = @_;
+ my @d;
+
+ for my $f (send_command $sk, "files", "$root$dir") {
+ my ($tail) = $f =~ /\Q$root\E(.*)$/;
+ die "`$f' not under root `$root'" unless $tail;
+ push @$list, $tail;
+ }
+
+ for my $d (send_command $sk, "dirs", "$root$dir") {
+ my ($tail) = $d =~ /\Q$root\E(.*)$/;
+ die "`$d' not under root `$root'" unless $tail;
+ push @d, $tail;
+ }
+ for my $d (@d) { grobble_dir @$list, $sk, $root, $d; }
+}
+
+sub grobble_root ($) {
+ my ($sk) = @_;
+ my $root = undef;
+ my @list = ();
+
+ for my $d (send_command $sk, "dirs", "") {
+ my ($pre, $tail) = $d =~ m{^(.*/)([^/]*)$};
+ die "no root in `$_'?" unless $pre;
+ if (!defined $root) { $root = $pre; }
+ elsif ($root ne $pre) { die "root was `$root'; now it's `$pre'"; }
+ grobble_dir @list, $sk, $root, $tail;
+ }
+ return $root, \@list;
+}
+
+sub trim_extension ($) {
+ my ($f) = @_;
+ $f =~ s/\.(flac|mp[23]|ogg|wav)$//;
+ return $f;
+}
+
+sub die_usage () {
+ print STDERR <<EOF;
+usage:
+ $PROG get CONFIG
+ $PROG set CONFIG [LIST]
+EOF
+ exit 2;
+}
+
+defined (my $op = shift @ARGV) or die_usage;
+if ($op eq "get") {
+ defined (my $conf = shift @ARGV) or die_usage;
+ !@ARGV or die_usage;
+ my $sk = connect_to_server $conf;
+ my ($root, $list) = grobble_root $sk;
+
+ for my $f (sort @$list) {
+ my $pick = send_command $sk, "get", "$root$f", "pick_at_random";
+ if (($pick // 1) eq "0") { print trim_extension $f, "\n"; }
+ }
+ close $sk;
+} else {
+ defined (my $conf = shift @ARGV) or die_usage;
+ my $fh;
+ if (defined (my $list = shift @ARGV)) { open $fh, "<", $list; }
+ else { $fh = \*STDIN; }
+ my %black = ();
+ while (<$fh>) { chomp; $black{$_} = 1; }
+ my $sk = connect_to_server $conf;
+ my ($root, $list) = grobble_root $sk;
+
+ FILE: for my $f (sort @$list) {
+ my $pick = send_command $sk, "get", "$root$f", "pick_at_random";
+ if (($pick // 1) eq "0") {
+ next FILE if $black{trim_extension $f};
+ send_command $sk, "unset", "$root$f", "pick_at_random";
+ print STDERR ";; reinstate <$f>\n";
+ } else {
+ next FILE unless $black{trim_extension $f};
+ send_command $sk, "set", "$root$f", "pick_at_random", 0;
+ print STDERR ";; blacklist <$f>\n";
+ }
+ }
+ close $sk;
+}