#!/usr/bin/perl

# mountmv: Moves listeners from one mountpoint to another on an Icecast server,
#          and also aliases the first mountpoint to the second so that new listeners
#          get the stream on the second mountpoint


# Copyright (c) 2002, Fat Freddy <ff@squat.net> and his cat 
# All rights reserved.

use strict;
use IO::Socket;
use IO::Select;

$| = 1;

my $DEBUG = 0;

# Set the icecast passwords here
my $admin_pw = 'XXXXXX';
my $oper_pw = 'XXXXXX';

my $server_ip = '194.109.209.34'; #freeteam.xs4all.nl
my $server_port = '8000'; # freeteam.xs4all.nl

#my $server_ip = '192.87.116.7'; # live.waag.org
#my $server_port = 7800; # live.waag.org


unless ($ARGV[1]) {
	print STDERR ("ARGUMENTS: source-mountpoint target-mountpoint (Example: ./mountmv ascii keyser)\n");
	exit;
}

my $source = shift @ARGV;
$source = '/'.$source
	unless $source =~ m#^/#;
my $target = shift @ARGV;
$target = '/'.$target
	unless $target =~ m#^/#;

			my ($resp,$buf);
			&_debug("*** ABOUT TO OPEN SOCKET TO ADMIN INTERFACE");
			my $socket = IO::Socket::INET->new(	Proto => 'tcp', 
								PeerAddr => "$server_ip:$server_port",
								Type => SOCK_STREAM,
								Timeout => 5 )
				or do {
					print STDERR ("Could not open socket to $server_ip:$server_port",$!,"\n");
					exit;
				};

			my $select = IO::Select->new($socket);
			&_debug("*** OPENED SOCKET, ABOUT TO LOG IN AS ADMIN");
			$socket->send("ADMIN $admin_pw\n\n");
			&_debug("*** SENT REQUEST");

			$resp = '';
                        &_debug("*** WAITING FOR OK");
			sleep 1;
			&_debug("*** ABOUT TO TRY RECEIVING 1000 BYTES");
			&_can_read($select)
				or do {
					print STDERR "Could not read from socket to $server_ip:$server_port",$!,"\n";
					exit;
				};
                	$socket->recv($resp,1000);
			if ($resp =~ /OK/) {
				&_debug("*** RECEIVE SUCCEEDED");
			} else { print STDERR ("*** DID NOT GET OK IN RESPONSE TO ADMIN LOGIN: $resp\n"); exit; }

			my $dout = $resp;
			$dout =~ s/\n/\n# /g;
			&_debug("# $dout");

			my $line = "status off\noper $oper_pw\nsources\n";
			$socket->send($line);
			$dout = $line;
			$dout =~ s/\n/\n#> /g;
			&_debug("#> $dout");
			sleep 3;

			&_debug("*** ABOUT TO TRY RECEIVING 10000 BYTES");
			&_can_read($select)
				or do {
					print STDERR "Could not read from socket to $server_ip:$server_port",$!,"\n";
					exit;
				};
                	$socket->recv($resp,10000);
			&_debug("*** RECEIVE SUCCEEDED");

			$dout = $resp;
			$dout =~ s/\n/\n# /g;
			&_debug("# $dout");

			my @lines = split /[\r\n]+/,$resp;
			@lines = grep {/^\[Id:/} @lines;
			my %ids;

			LINE: while (@lines) {
				$line = shift @lines;
				my @data = split /\] \[/, $line;
				# print "\&" . join "\n\&", @data;
				my %data;

				map { 
					my ($label,$value) = split /: /, $_, 2;
					$label =~ s/^\[//;
					$value =~ s/\]$//;
					$data{$label} = $value;
				} @data;

				next LINE
					unless $data{'Id'} && $data{'Mountpoint'};
				my $id = $data{'Id'};
			 	my $mp = $data{'Mountpoint'};
				$ids{$mp} = $mp;
			}
			&_debug("*** Source on mountpoint $source has ID $ids{$source}");
			&_debug("*** Source on mountpoint $target has ID $ids{$target}");
			do {
				print STDERR  ("ID for $source not found\n");
				exit;
			}
				unless $ids{$source};
			do {
				print STDERR ("ID for $target not found\n");
				exit;
			}
				unless $ids{$target};
			$socket->send("select -a $ids{$source} $ids{$target}\n");
			sleep 1;
			$socket->send("alias del $source\nalias del $target\nalias add $source $target\n");
			sleep 1;
			$socket->send("quit\n");
			print STDERR "Moved listeners from $source to $target\n";
			sleep 1;
			exit;

sub _debug {
	my $msg = shift;
	print STDERR "$msg\n" if $DEBUG;
}

sub _can_read {
	my $select = shift;
	if (my @ready = $select->can_read(5)) {
		&_debug("*** CAN READ FROM SOCKET");
		return 1;
	}
	else {
		&_debug("*** SOCKET TIMED OUT, EXITING");
		return 0;
	}
}

#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
