#!/usr/bin/perl -w

###  Written by qbxk for perlmonks
###  It is provided as is with no warranties, express or implied, of any kind. Use posted code at your own risk.

$|++;
use warnings;
use strict;
use Net::HTTP;
use Data::Dumper;
use Carp::Assert;

use constant USER_AGENT => 'WinampMPEG/5.33';  # I got refused by some public servers unlessen i done it thar way

my %HOST = ( 
   host => 'rc.vc', port => 8000, mount => '/'
);

sub debug(@) { print STDERR "\n" . join("\n", @_) . "\n"; }
sub debug_raw(@) { print STDERR @_; }

sub open_connection {
   my %args = (
      host => undef,
      port => 80,
      mount => '',
      user_agent => USER_AGENT,
      @_
   );
   
   die "Need a host name" unless defined($args{host});
   
   $args{mount} =~ s/^\/+//g;

   my $sock = Net::HTTP->new(Host => $args{host}, PeerPort => $args{port} ) || die $@;
   $sock->write_request(GET => "/$args{mount}", 'User-Agent' => $args{user_agent}, 'Icy-MetaData' => 1) or die $@;
   
   # my ($code, $mess, %headers) = $sock->read_response_headers( laxed => 1 )

   my ($code, $mess, %headers);
   while( <$sock> ) {
      s/\s*$//g;
      last if /^\s*$/;
      
      if( /^(?:HTTP\/1\.[01]|ICY) ([0-9]+) (.+)$/ ) {
         ($code, $mess) = ($1 +0, $2);
      }
      else {
         my ($h, $v) = split(/:/);
         $headers{$h} = $v;
      }
   }
   return ($sock,$code,$mess,%headers);
}

main: {

   my ($s,$code, $mess, %headers) = open_connection( %HOST );
  
#   debug "$code|$mess\n" . Dumper(\%headers);
 
   # TODO: timeout on $s.

   exit if( $code != 200 ); # scream and shout

   my ($metaint) = map { (/^icy-metaint$/i && $headers{$_}) or () } keys %headers;
      assert( $metaint > 0 );

   while( 1 ) {   
      my $buf;
      $s->read($buf, $metaint);
      
      my ($metadata, $metalen, $metabyte);
      
      $s->read($metabyte, 1);
      $metalen = unpack("C",$metabyte) * 16;

      if( $metalen > 0) {
         #We have NEW metadata! JOY
         $s->read($metadata, $metalen);
         $metadata = unpack("A$metalen", $metadata);
         assert( $metadata =~ /Stream/, "Not good metadata!" ); #don't dump a lot of BS (binary *#$!), just die.
         
         #debug "$metalen - [$metadata]";
         my ($title) = $metadata =~ /StreamTitle='(.*?)';StreamUrl/i;
         print "$title";
         exit(0);
      }
      else {
         $metadata = '';
         debug_raw "-";
      }
   }
}
