

I shall make music play
I shall make it sunny outside
I shall make this page magically change
I wrote a script which calls on Device::Ericsson::AccessoryMenu to allow me to trigger things from my phone.

Images stolen from http://www.linuxbrit.net/bluexmms/
Mac OS X applications

You write your actions in applescript
try
tell application "iTunes"
try
set the current_track to get current track
on error
error "No current track."
end try
set the track_count to (the count of tracks of the current playlist) as string
next track
try
set this_track to get current track
on error
play current_track
set this_track to the current_track
play track 1 of current playlist
set this_track to get current track
end try
set the track_index to (the index of this_track) as string
set this_title to the name of this_track as string
return (track_index & "/" & track_count & " " & this_title)
end tell
on error error_message
return error_message
end try
That's how you tell iTunes to play the next track
Ruby program that remote controls XMMS
Grokable, but very entwined code
So for the first version of my code I stole mostly from that, splitting up the AT-slinging code from the actions
#!/usr/local/bin/perl -w
use strict;
use Device::Ericsson::AccessoryMenu;
use Device::SerialPort;
use Xmms::Remote;
my $xmms = Xmms::Remote->new;
my $menu = Device::Ericsson::AccessoryMenu->new(
port => Device::SerialPort->new( '/dev/rfcomm0' ) || die,
menu => [ XMMS => [
"Play/Pause" => sub {
$xmms->is_playing ? $xmms->pause : $xmms->play;
},
Back => sub { $xmms->playlist_prev },
Next => sub { $xmms->playlist_next },
Stop => sub { $xmms->stop },
],
],
);
$menu->register_menu;
$menu->control while 1;
$music_player, kindly play the next track.
try
tell application "iTunes"
try
set the current_track to get current track
on error
error "No current track."
end try
set the track_count to (the count of tracks of the current playlist) as string
next track
try
set this_track to get current track
on error
play current_track
set this_track to the current_track
play track 1 of current playlist
set this_track to get current track
end try
set the track_index to (the index of this_track) as string
set this_title to the name of this_track as string
return (track_index & "/" & track_count & " " & this_title)
end tell
on error error_message
return error_message
end try
use Xmms::Remote; my $xmms = Xmms::Remote->new; $xmms->playlist_next;
We can invoke other kinds of widgets too, like this volume slider

Volume => sub {
my $r = shift;
$r->percent_slider(
title => 'Volume',
value => $xmms->get_main_volume,
steps => 10,
callback => sub {
$xmms->set_main_volume( shift )
},
);
return;
},

As a lowly utility module we want to stay out of the way of those, and not trap the user into a(nother) busy loop.

Since we expect the phone to send different messages when it's
displaying a Slider than when it's displaying a Menu we can either:
Continue to kludge tests into a really big if/then/else statement. Eventually go insane.
Do something stateful.

I also like state machines
enter_state we push a new state onto the stack, and call its
on_enter method
exit_state - we pop the top, call it's on_exit method, and the
new tops on_enter
in control we call the topmost states handle method
Text is probably the simplest state:
Set up the parentage, and add some accessors
use strict; package Device::Ericsson::AccessoryMenu::Text; use base 'Device::Ericsson::AccessoryMenu::State'; __PACKAGE__->mk_accessors( qw( title lines ) );
on_enter we just send the dialog over
sub on_enter {
my $self = shift;
my $title = $self->title;
$self->send( join ',',
qq{AT*EAID=14,2,"$title"},
map { qq{"$_"} } @{ $self->lines }
);
$self->expect( 'OK' );
}
And whatever value our handler gets, it means leave this state
sub handle {
my $self = shift;
$self->exit_state;
}
1;
That's all there is to it.
Xmms::Remote is your underdocumented friend.
You just write bookmarklets and invoke them via system
Well, anything you can write Perl for at least.
Check out examples/remote in the Device::Ericsson::AccessoryMenu distribution. It's the remote I'm using for this presentation, and already includes XMMS and Galeon menus.
It's fairly straightforward to use the Mouse state and remap the
events into X11 keypresses.
#!/usr/local/bin/perl -w use lib qw(lib); use strict; use Device::Ericsson::AccessoryMenu; use Device::SerialPort; use X11::GUITest qw(PressKey ReleaseKey);
my $port = shift || '/dev/rfcomm0';
my %keymap1 = ( ... ); my %keymap2 = ( ... );
sub translate_keys {
my $remote = shift;
my %keymap = @_;
$remote->mouse_mode( callback => sub {
my ($key, $updown) = @_;
return unless exists $keymap{$key};
$updown ? PressKey($keymap{$key})
: ReleaseKey($keymap{$key});
});
}
my $menu = Device::Ericsson::AccessoryMenu->new(
port => Device::SerialPort->new( $port ) || die,
menu => [ XKeys => [
Map1 => sub { translate_keys( shift, %keymap1 ) },
Map2 => sub { translate_keys( shift, %keymap2 ) },
],
],
);
Being Perl this naturally has a real and practical application.
Couple more dialog types to add, if they're useful.
With luck someone will write a nice frontend for building menus, possibly shipping a bunch of precanned menus
More pie
