#!/usr/bin/env perl
#
# Copyright © 2012,2019 Nick Bowler
#
# Simple program to send a command to MPD.  Each command-line argument is
# quoted as necessary so it appears as a single argument at the protocol
# level.  The result is printed to standard output.
#
# License WTFPL2: Do What The Fuck You Want To Public License, version 2.
# This is free software: you are free to do what the fuck you want to.
# There is NO WARRANTY, to the extent permitted by law.

use strict;

use utf8;

use Encode::Locale qw(decode_argv);
decode_argv(Encode::FB_CROAK);

binmode(STDOUT, ":utf8");
binmode(STDIN, ":utf8");
use IO::Socket::INET6;

my $host = $ENV{MPD_HOST} // "localhost";
my $port = $ENV{MPD_PORT} // 6600;

my $sock = new IO::Socket::INET6(
	PeerAddr => $host,
	PeerPort => $port,
	Proto    => 'tcp',
) or die "failed to connect to MPD: $!";
binmode($sock, ":utf8");

if (!(<$sock> =~ /^OK MPD ([0-9]+)\.([0-9]+)\.([0-9]+)$/)) {
	die "MPD failed to announce version: $!";
}

sub mpd_escape {
	($_) = @_;

	# No way to encode literal newlines in the protocol, so we convert
	# any newlines in the arguments into a space, which can help with
	# shell quoting.
	s/\n/ /g;

	if (/[ \t\\"]/) {
		s/[\\"]/\\$&/g;
		return "\"$_\"";
	}
	return $_;
}

sub mpd_exec {
	print $sock join(' ', @_), "\n";
	while (<$sock>) {
		last if (/^OK/);
		print;
		exit 1 if (/^ACK/);
	}
}

if (@ARGV) {
	mpd_exec(map { mpd_escape($_) } @ARGV)
} else {
	while (<>) {
		chomp;
		mpd_exec($_);
	}
}

print $sock "close\n";
close $sock;
