#!/usr/bin/perl
##########################################################################
#
# This script is to be used with a Toyota Prius 2004,2005 in conjunction
# with a CAN-view http://hybridinterfaces.ca/
#
# Will read in MFD touchscreen coordinates sent by the CAN-view and
# translate them into Apple Front Row AppleScript commands (key presses)
# to control FrontRow
# email: Jeremy Kusnetz jeremy@kusnetz.net for details or see
# http://www.kusnetz.net/prius/
#
# This script requires Mac::AppleScript::Glue,Device::SerialPort,Time::HiRes
# Use CPAN to download and install these modules.
#
# This script will need tweaking to work on your own system.  
# If your Mac spontaneously combusts after running this scrip I am not responsible!
# Be sure the serial port is pointing to your serial port.


use Device::SerialPort;
use POSIX qw(strftime);
use Time::HiRes qw(usleep);
use strict;
use Mac::AppleScript::Glue;

my $progname = $0;
my $version = '2006.02.18,01';
my $DEBUG = 0;

daemonize() if (!$DEBUG);

my $systemevents = new Mac::AppleScript::Glue::Application('System Events');
my $frontrow = new Mac::AppleScript::Glue::Application('Front Row');

# Set to your serial port number
#my $port = "/dev/tty.KeySerial1";
my $port = "/dev/tty.USA19QW191P1.1";
my $baud = "115200";

print "Setting up $port\n" if ($DEBUG);
my $ob;
$ob = Device::SerialPort->new ($port,1) || die "Can't open $port: $!";
$ob->baudrate($baud)       || die "fail setting baudrate";
$ob->parity("none")       || die "fail setting parity";
$ob->databits(8)   || die "fail setting databits";
$ob->stopbits(1)   || die "fail setting stopbits";
$ob->handshake("none") || die "fail setting handshake";
# timeouts
#$ob->read_char_time(5);     # time between chars
#$ob->read_const_time(50); # timeout after n
$ob->write_settings || die "no settings";
print "Finished setting up $port\n" if ($DEBUG);

my $quit = 0;
my $inputData = 1;

my $downScroll = 0;
my $upScroll = 0;
while (!$quit) {
	my ($grabbed, $datagrabbed) = $ob->read($inputData);

	if ($grabbed == $inputData) {
		my @data = unpack('C*', $datagrabbed);
		&touchscreen(@data);
	} else {
           print "NO DATA\n" if ($DEBUG == 2);
           fr_downScroll($downScroll) if ($downScroll);
           fr_upScroll($upScroll) if ($upScroll);
        }
}
undef $ob;
exit;


sub touchscreen {
   my @data = @_;
   my $BYTE = 0;
   foreach (@data) {
      next if ($_[0] == 0);
      $BYTE = sprintf("%02X ", $data[0]);
      my ($x, $y) = split(//,$BYTE);
      $x = hex($x);
      $y = hex($y);
      print "$BYTE: $x,$y: " if ($DEBUG);
      fr_right() if (($x > 10) && ($y>5) && ($y<=10));
      fr_left() if (($x <= 5) && ($y>5) && ($y<=10));
      fr_down() if (($y <= 5) && ($x>5) && ($x<=10));
      fr_up() if (($y > 10) && ($x>5) && ($x<=10));
      fr_enter() if (($y <= 10) && ($y > 5) && ($x > 5) && ($x <=10)); 
      fr_esc() if (($y > 10) && ($x < 5));
      fr_start() if (($y <= 5) && ($x < 5));
      fr_downScroll(0) if (($y <= 5) && ($x > 10));
      fr_upScroll(0) if (($y > 10) && ($x > 10));
   }
}

sub fr_right {
   print "FrontRow Right\n" if ($DEBUG);
   $upScroll = 0; $downScroll = 0;
   $systemevents->key_code(124);
}

sub fr_left {
   print "FrontRow Left\n" if ($DEBUG);
   $upScroll = 0; $downScroll = 0;
   $systemevents->key_code(123);
}

sub fr_up {
   print "FrontRow Up\n" if ($DEBUG);
   $upScroll = 0; $downScroll = 0;
   $systemevents->key_code(126);
}

sub fr_down {
   print "FrontRow Down\n" if ($DEBUG);
   $upScroll = 0; $downScroll = 0;
   $systemevents->key_code(125);
}

sub fr_enter {
   print "FrontRow Enter\n" if ($DEBUG);
   $upScroll = 0; $downScroll = 0;
   $systemevents->key_code(36);
}

sub fr_esc {
   print "FrontRow Escape\n" if ($DEBUG);
   $frontrow->activate;
   $upScroll = 0; $downScroll = 0;
   $systemevents->key_code(53);
}

sub fr_start {
   print "FrontRow Start\n" if ($DEBUG);
   $frontrow->activate;
   $upScroll = 0; $downScroll = 0;
   $systemevents->key_code(53);
   usleep(5);
   $systemevents->key_code(53);
}

sub fr_downScroll {
   my $continue = shift;
   $upScroll = 0;
   if (($downScroll) && (!$continue)) {
      $downScroll = 0;
      print "FrontRow Down Scroll - Stop\n" if ($DEBUG);
   } else {
      $downScroll = 1;
      print "FrontRow Down Scroll - Start\n" if ($DEBUG);
      $systemevents->key_code(125);
   }
}

sub fr_upScroll {
   my $continue = shift;
   $downScroll = 0;
   if (($upScroll) && (!$continue)){
      $upScroll = 0;
      print "FrontRow Up Scroll - Stop\n" if ($DEBUG);
   } else {
      $upScroll = 1;
      print "FrontRow Up Scroll - Start\n" if ($DEBUG);
      $systemevents->key_code(126);
   }
}

############################################
### BEGIN DAEMON FUNCTIONS

sub daemonize {
  ##### Daemonize

  #open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
  #open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!";
  #open STDERR, '>&STDOUT' or die "Can't dup stdout: $!";

  # Fork
  my $pid = fork;
  exit if $pid;
  die "Couldn't fork: $!" unless defined($pid);

  POSIX::setsid() or die "Can't start new session: $!";

  $SIG{INT} = $SIG{TERM} = \&sig_handler;
  $SIG{PIPE} = 'IGNORE';
  $SIG{HUP} = \&hup_handler;

  ##### End daemonize
}

sub sig_handler {
        exit;
}

sub hup_handler {
        exec($progname,'');
        exit;
}

