3 # Copyright © 2012,2019-2020 Nick Bowler
5 # Send commands to MPD. Each command-line argument is quoted as necessary
6 # so it appears as a single argument at the protocol level. The result is
7 # printed to standard output.
9 # License GPLv3+: GNU General Public License version 3 or any later version.
10 # This is free software: you are free to change and redistribute it.
11 # There is NO WARRANTY, to the extent permitted by law.
17 use Encode qw(decode encode);
18 use Encode::Locale qw(decode_argv);
19 decode_argv(Encode::FB_CROAK);
21 binmode(STDOUT, ":utf8");
22 binmode(STDIN, ":utf8");
23 use IO::Socket::INET6;
25 use Getopt::Long qw(:config gnu_getopt);
28 use lib "$FindBin::Bin";
31 my $host = $ENV{MPD_HOST} // "localhost";
32 my $port = $ENV{MPD_PORT} // 6600;
33 my ($quiet, $binary, $ignore_errors, $download);
38 Copyright © 2019 Nick Bowler
39 License GPLv3+: GNU General Public License version 3 or any later version.
40 This is free software: you are free to change and redistribute it.
41 There is NO WARRANTY, to the extent permitted by law.
46 my $fh = $_[1] // *STDERR;
48 print $fh "Usage: $0 [options] [command ...]\n";
49 print "Try $0 --help for more information.\n" unless (@_ > 0);
55 This is "mpdexec": a tool to send simple commands to MPD.
58 -h, --host=HOST Connect to the MPD server on HOST, overriding defaults.
59 -p, --port=PORT Connect to the MPD server on PORT, overriding defaults.
60 -q, --quiet Do not output any response messages. Only errors (on
61 standard error) or binary data (if enabled) are output.
63 Output raw binary response data, which is normally not
64 written. If FILE is specified, the data is written there.
65 Otherwise, --quiet is automatically enabled and the data
66 goes to standard output.
67 --download Enable automatic sequencing of albumart commands; if this
68 option is specified, albumart commands without offsets will
69 be expanded into multiple commands in order to download the
71 --ignore-errors In batch mode, continue submitting commands after errors.
72 -V, --version Print a version message and then exit.
73 -H, --help Print this message and then exit.
75 Report bugs to <nbowler\@draconx.ca>.
84 'no-quiet' => sub { $quiet = 0; },
85 'binary|b:s' => \$binary,
86 'no-binary' => sub { $binary = undef; },
88 'download' => \$download,
89 'no-download' => sub { $download = 0; },
91 'ignore-errors' => \$ignore_errors,
92 'no-ignore-errors' => sub { $ignore_errors = 0; },
94 'V|version' => sub { print_version(); exit },
95 'H|help' => sub { print_help(); exit },
96 ) or do { print_usage; exit 1 };
98 my $binfile = *STDOUT;
100 if ($binary ne "-") {
101 open(my $fh, ">", $binary) or die "failed to open $binary: $!";
105 $quiet = 1 if (defined($binary) && $binary eq "");
107 my $sock = new IO::Socket::INET6(
111 ) or die "failed to connect to MPD: $!";
112 #binmode($sock, ":utf8");
115 if (!(<$sock> =~ /^OK MPD ([0-9]+)\.([0-9]+)\.([0-9]+)$/)) {
116 die "MPD failed to announce version: $!";
125 return 0 unless ($count);
126 my $rc = $sock->read($buf, $count) or die "$!";
127 if (defined($binary)) {
128 $binfile->write($buf) or die "$!";
137 # special case for "albumart"; if no offset is specified
138 # (invalid command) we synthesize a sequence of albumart
139 # commands to retrieve the entire file.
140 if ($download && $_[0] eq "albumart" && @_ == 2) {
145 print $sock encode('UTF-8', join(' ', @_), Encode::FB_QUIET), $/;
147 $_ = decode('UTF_8', $_, Encode::FB_QUIET);
150 last unless ($downloadseq);
151 print $sock encode('UTF-8',
153 Encode::FB_QUIET), $/;
157 if (/^binary: ([0-9]+)$/) {
158 print unless ($quiet);
162 $downloadseq = 0 unless ($1);
163 $_[$downloadseq] += $1;
168 last if ($ignore_errors);
171 print unless ($quiet);
177 mpd_exec(map { MPD::escape($_) } @ARGV)
185 print $sock "close\n";