CUFP
OzzyOsbourne
<p>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?</p>
<p>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:<ul><li>fade in/out,</li><li>toggle the shuffle,</li><li>toggle the repeat,</li><li>raise the volume, and</li><li>change the balance</li></ul>, but it will also <b><i>speak the title of the song and the time remaining over your speakers via the Microsoft TTS engine</i></b> (which I find really useful when listening to unknown artists on internet radio while in different room from the PC).</p>
<p>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.</p>
<code>
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: Winamp 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 serial 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$serial_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 seconds";
$voice->Speak($info, 1);
while ($voice->IsSpeaking()) {
sleep 1;
}
return;
}
</code>
<p><B>Update (7/26/04):</b> This code also works with MediaMonkey.
<p>-<a href="/index.pl?node=OzzyOsbourne&lastnode_id=1072">OzzyOsbourne</a></p>