So you have a universal RF X10 remote (UR47A - comes with activehome and other starter kits) and a firecracker serial receiver on your PC, and you know that the Boom2000 software to control Winamp, well, bites. What can you do?
Run the following script. It stays open as you issue commands. It not only will do the typical play, stop, FF, rew, thing, but it can:
- fade in/out,
- toggle the shuffle,
- toggle the repeat,
- raise the volume, and
- change the balance
, but it will also
speak the title of the song and the time remaining over your speakers via the Microsoft TTS engine (which I find really useful when listening to unknown artists on internet radio while in different room from the PC).
If you want to change the button asignments, you will need a serial port watching program like SerialWatcher to read the codes that come in. Then just make changes to the button_codes hash.
use strict;
use Win32::SerialPort qw(:STAT);
use Win32::GUI;
use Win32::OLE;
use constant WM_USER => 1024;
my ($count,$data,$Port,$serial_data);
my ($voice,$winampHandle);
my %button_codes=(
'1110111000111000'=>{
action=>'Previous',
type=>WM_COMMAND,
value1=>40044,
value2=>0,
},
'1110111010111000'=>{
action=>'Next',
type=>WM_COMMAND,
value1=>40048,
value2=>0,
},
'1110111010110000'=>{
action=>'Play',
type=>WM_COMMAND,
value1=>40045,
value2=>0,
},
'1110111001110010'=>{
action=>'Pause',
type=>WM_COMMAND,
value1=>40046,
value2=>0,
},
'1110111001110000'=>{
action=>'Stop',
type=>WM_COMMAND,
value1=>40047,
value2=>0,
},
'1110111011001001'=>{
action=>'Fadeout',
type=>WM_COMMAND,
value1=>40147,
value2=>0,
},
'1110111001000000'=>{
action=>'Fast_for5',
type=>WM_COMMAND,
value1=>40148,
value2=>0,
},
'1110111011000000'=>{
action=>'Fast_rewind5',
type=>WM_COMMAND,
value1=>40144,
value2=>0,
},
'1110111011010101'=>{
action=>'Raise_vol',
type=>WM_COMMAND,
value1=>40058,
value2=>0,
},
'1110111011010011'=>{
action=>'Lower_vol',
type=>WM_COMMAND,
value1=>40059,
value2=>0,
},
'1110111011110010'=>{
action=>'Toggle_Repeat',
type=>WM_COMMAND,
value1=>40022,
value2=>0,
},
'1110111010111010'=>{
action=>'Toggle_Shuffle',
type=>WM_COMMAND,
value1=>40023,
value2=>0,
},
'1110111010100000'=>{
action=>'Mute',
type=>WM_USER,
value1=>0,
value2=>122,
},
'1110111001010010'=>{
action=>'Balance_Ctr',
type=>WM_USER,
value1=>0,
value2=>123,
},
'1110111011010001'=>{
action=>'Balance_Rt',
type=>WM_USER,
value1=>127,
value2=>123,
},
'1110111011010010'=>{
action=>'Balance_Lt',
type=>WM_USER,
value1=>-127,
value2=>123,
},
'1110111011010110'=>{
action=>'Get_Info',
type=>'',
value1=>'',
value2=>'',
}
);
##### MAIN SUBS #####
&Init_Voice()
&Call_WAmp();
&Open_Serial();
&Get_Data();
&Close_Serial();
##### MAIN SUBS #####
sub Call_WAmp(){
$winampHandle = Win32::GUI::FindWindow("Winamp v1.x", "");
if ($winampHandle){return $winampHandle;}else{die "Stopping: Winam
+p Not running\n";}
return $winampHandle;
}
sub Open_Serial{ # Prep and open the serial port
$Port = new Win32::SerialPort("COM2");
$Port->baudrate(9600);
$Port->parity("none");
$Port->databits(8);
$Port->stopbits(1);
$Port->handshake("none");
$Port->rts_active(1);
$Port->binary(1);
$Port->write_settings || undef $Port;
die "Can't change Device_Control_Block: $^E\n" unless ($Port);
}
sub Get_Data{ # Gets the data bits from the serial port and puts into
+$data
do{
my $serial_data;
($count, $serial_data) = $Port->read( 40 );#read data from ser
+ial port
if ( $count>4 and defined $serial_data ) {
my @bytes= split(//, $serial_data);
my $header=unpack("B16",join('',$bytes[0],$bytes[1]));
$data=unpack("B16",join('',$bytes[2],$bytes[3]));
if ($button_codes{$data}{type}=='Get_Info'){
&Talk();
}
Win32::GUI::SendMessage($winampHandle,$button_codes{$data}
+{type},$button_codes{$data}{value1},$button_codes{$data}{value2});
my $footer=unpack("B8",$bytes[4]);
print "code:\t $button_codes{$data}{type}, $button_codes{$
+data}{value1},$button_codes{$data}{value2}\ncount:\t$count\ndata:\t$s
+erial_data\nheader:\t$header\ndata:\t$data\nfooter:\t$footer\n";
#select(undef, undef, undef, 1);
}else{
select(undef, undef, undef, 1);#Wait 1 seconds
}
}until($data==1110111011110000);
}
sub Close_Serial{
$Port->close || die "failed to close";
undef $Port;
print "bye";
}
sub Init_Voice{
$voice = Win32::OLE->new("Speech.VoiceText") or die("TTS failed");
$voice->Register("", "$0");
$voice->{Enabled} = 1; # optional
$voice->{Speed}=150;
return $voice;
}
sub Talk{
my $windowname=Win32::GUI::Text($winampHandle);
$windowname=~s/\s+//g;
$windowname=~s/\d+.//g;
my ($artist,$title)=split(/-/,$windowname);
my $totaltime=Win32::GUI::SendMessage( $winampHandle, WM_USER, 1,
+105 );
my $minutes=int($totaltime/60);
my $seconds=($totaltime-((int($totaltime/60))*60));
my $info = "$title by $artist, $minutes minutes and $seconds secon
+ds";
$voice->Speak($info, 1);
while ($voice->IsSpeaking()) {
sleep 1;
}
return;
}
Update (7/26/04): This code also works with MediaMonkey.
-OzzyOsbourne