From 68ff3ebd0073097de84fc55b22047cb5b9d98db7 Mon Sep 17 00:00:00 2001
From: "Jan \"Yenya\" Kasprzak" <kas@fi.muni.cz>
Date: Thu, 2 Dec 2010 01:59:11 +0100
Subject: [PATCH] Proof-of-concept GUI

---
 SCX/Reader.pm    |  20 +-
 gui.pl           | 122 ++++++++++
 slotcarman.glade | 600 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 737 insertions(+), 5 deletions(-)
 create mode 100755 gui.pl
 create mode 100644 slotcarman.glade

diff --git a/SCX/Reader.pm b/SCX/Reader.pm
index 1b7c44f..5a98a6d 100644
--- a/SCX/Reader.pm
+++ b/SCX/Reader.pm
@@ -82,13 +82,23 @@ sub read {
 
 	my @bad_bytes;
 
-	while (@bytes >= $PACKET_SIZE) {
-		if ($bytes[0] != 0x55 || $bytes[9] != 0x05
-			|| SCX::CRC::digest(@bytes[0..7]) != $bytes[8]) {
+	while (@bytes >= 2) {
+		if ($bytes[0] != 0x55) {
 			push @bad_bytes, shift @bytes;
 			next;
 		}
+		my $cmd = $bytes[1];
 
+		my $packet_size = $cmd >= 0x40 && $cmd <= 0x46 ? 4 : 9;
+		last if @bytes <= $packet_size;
+
+		if ($bytes[$packet_size] != 0x05
+			|| SCX::CRC::digest(@bytes[0..$packet_size-2])
+				!= $bytes[$packet_size-1]) {
+			push @bad_bytes, shift @bytes;
+			next;
+		}
+		
 		if (@bad_bytes) {
 			$self->{logfh}->print("Cannot parse bytes",
 				(map { sprintf(' %02x', $_) } @bad_bytes),
@@ -97,8 +107,8 @@ sub read {
 		}
 
 		$self->{logfh}->print("Callback\n");
-		&{ $self->{callback} }(@bytes[1..7]);
-		splice @bytes, 0, 10;
+		&{ $self->{callback} }(@bytes[1..$packet_size]);
+		splice @bytes, 0, $packet_size+1;
 	}
 	if (@bad_bytes) {
 		$self->{logfh}->print("Cannot parse bytes",
diff --git a/gui.pl b/gui.pl
new file mode 100755
index 0000000..5e1411a
--- /dev/null
+++ b/gui.pl
@@ -0,0 +1,122 @@
+#!/usr/bin/perl -w
+
+use strict;
+use utf8;
+
+use Gtk2 '-init';
+use Glib qw(TRUE FALSE);
+
+use SCX::Reader;
+
+my @controllers = (0, 0, 0, 0, 0, 0);
+
+my $builder = Gtk2::Builder->new;
+$builder->add_from_file('slotcarman.glade');
+
+my $window = $builder->get_object('slotcarman');
+
+$builder->connect_signals(undef);
+$window->show();
+
+sub quit {
+	Gtk2->main_quit;
+	return FALSE;
+}
+
+my $reader = SCX::Reader->new({
+	portname   => '/dev/ttyUSB0',
+	logfile    => 'log',
+	callback   => \&do_packet,
+});
+
+sub scx_read {
+	my $event = shift;
+
+	$reader->read();
+	return TRUE;
+}
+
+Glib::IO->add_watch(fileno($reader->fh), 'in', \&scx_read, 1);
+
+Gtk2->main();
+
+sub do_packet {
+	my (@data) = @_;
+
+	if ($data[0] == 0xff) { # controller status
+		for my $controller (1..6) {
+			my $byte = $data[$controller];
+			next if defined $controllers[$controller-1]
+				&& $controllers[$controller-1] == $byte;
+			$controllers[$controller-1] = $byte;
+
+			my $progressbar = $builder->get_object(
+				'progressbar_controller'.$controller);
+			if ($byte == 0xaa) {
+				$progressbar->set_text('inactive');
+				$progressbar->set_fraction(0);
+				next;
+			}
+			my $light = !($byte & 0x20);
+			my $backbutton = !($byte & 0x10);
+			my $speed = $byte & 0x0f;
+
+			my $text = ($backbutton ? '+' : '') . $speed;
+			$progressbar->set_text($text);
+			$progressbar->set_fraction($speed / 12);
+		}
+	} elsif ($data[0] == 0xd6) { # fuel status
+		my @fuel = (0,
+			$data[1] >> 4, $data[1] & 0x0f,
+			$data[2] >> 4, $data[2] & 0x0f,
+			$data[3] >> 4, $data[3] & 0x0f,
+		);
+		for my $car (1..6) {
+			next if defined $controllers[$car-1]
+				&&$controllers[$car-1] == $fuel[$car];
+			
+			my $progressbar = $builder->get_object(
+				'progressbar_fuel'.$car);
+			$progressbar->set_fraction($fuel[$car]/8);
+		}
+	} else {
+		print "Unknown packet",
+			(map { sprintf(" %02x", $_) } @data), "\n";
+	}
+}
+			
+__END__
+use Gtk2 '-init';
+
+my $window = Gtk2::Window->new('toplevel');
+$window->signal_connect(delete_event => sub { Gtk2->main_quit; return FALSE });
+$window->set_title("Slot Cars Manager");
+
+$window->set_border_width(10);
+
+my $button = Gtk2::Button->new("Button 1");
+$button->signal_connect(clicked => \&callback, 'button 1');
+
+my $box1 = Gtk2::HBox->new(FALSE, 0);
+$window->add($box1);
+$box1->pack_start($button, TRUE, TRUE, 0);
+
+$button->show;
+$button = Gtk2::Button->new("Button 2");
+$button->signal_connect(clicked => \&callback, 'button 2');
+$box1->pack_start($button, TRUE, TRUE, 0);
+
+$button->show;
+$box1->show;
+$window->show;
+
+Gtk2->main();
+
+
+sub callback
+{
+	my ($button, $data) = @_;
+	
+	print "Hello again - $data was pressed\n";
+}
+
diff --git a/slotcarman.glade b/slotcarman.glade
new file mode 100644
index 0000000..45c33e0
--- /dev/null
+++ b/slotcarman.glade
@@ -0,0 +1,600 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="2.20"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkWindow" id="slotcarman">
+    <property name="title" translatable="yes">Slot Cars Race Manager</property>
+    <child>
+      <object class="GtkVBox" id="vbox1">
+        <property name="visible">True</property>
+        <child>
+          <object class="GtkMenuBar" id="menubar1">
+            <property name="visible">True</property>
+            <child>
+              <object class="GtkMenuItem" id="menuitem1">
+                <property name="visible">True</property>
+                <property name="use_action_appearance">False</property>
+                <property name="label" translatable="yes">_File</property>
+                <property name="use_underline">True</property>
+                <child type="submenu">
+                  <object class="GtkMenu" id="menu1">
+                    <property name="visible">True</property>
+                    <child>
+                      <object class="GtkImageMenuItem" id="imagemenuitem1">
+                        <property name="label">gtk-new</property>
+                        <property name="visible">True</property>
+                        <property name="use_action_appearance">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkImageMenuItem" id="imagemenuitem2">
+                        <property name="label">gtk-open</property>
+                        <property name="visible">True</property>
+                        <property name="use_action_appearance">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkImageMenuItem" id="imagemenuitem3">
+                        <property name="label">gtk-save</property>
+                        <property name="visible">True</property>
+                        <property name="use_action_appearance">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkImageMenuItem" id="imagemenuitem4">
+                        <property name="label">gtk-save-as</property>
+                        <property name="visible">True</property>
+                        <property name="use_action_appearance">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkSeparatorMenuItem" id="separatormenuitem1">
+                        <property name="visible">True</property>
+                        <property name="use_action_appearance">False</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkImageMenuItem" id="imagemenuitem5">
+                        <property name="label">gtk-quit</property>
+                        <property name="visible">True</property>
+                        <property name="use_action_appearance">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                        <signal name="activate" handler="quit" swapped="no"/>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkMenuItem" id="menuitem2">
+                <property name="visible">True</property>
+                <property name="use_action_appearance">False</property>
+                <property name="label" translatable="yes">_Edit</property>
+                <property name="use_underline">True</property>
+                <child type="submenu">
+                  <object class="GtkMenu" id="menu2">
+                    <property name="visible">True</property>
+                    <child>
+                      <object class="GtkImageMenuItem" id="imagemenuitem6">
+                        <property name="label">gtk-cut</property>
+                        <property name="visible">True</property>
+                        <property name="use_action_appearance">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkImageMenuItem" id="imagemenuitem7">
+                        <property name="label">gtk-copy</property>
+                        <property name="visible">True</property>
+                        <property name="use_action_appearance">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkImageMenuItem" id="imagemenuitem8">
+                        <property name="label">gtk-paste</property>
+                        <property name="visible">True</property>
+                        <property name="use_action_appearance">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkImageMenuItem" id="imagemenuitem9">
+                        <property name="label">gtk-delete</property>
+                        <property name="visible">True</property>
+                        <property name="use_action_appearance">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkMenuItem" id="menuitem3">
+                <property name="visible">True</property>
+                <property name="use_action_appearance">False</property>
+                <property name="label" translatable="yes">_View</property>
+                <property name="use_underline">True</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkMenuItem" id="menuitem4">
+                <property name="visible">True</property>
+                <property name="use_action_appearance">False</property>
+                <property name="label" translatable="yes">_Help</property>
+                <property name="use_underline">True</property>
+                <child type="submenu">
+                  <object class="GtkMenu" id="menu3">
+                    <property name="visible">True</property>
+                    <child>
+                      <object class="GtkImageMenuItem" id="imagemenuitem10">
+                        <property name="label">gtk-about</property>
+                        <property name="visible">True</property>
+                        <property name="use_action_appearance">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                        <signal name="activate" handler="about" swapped="no"/>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkTable" id="table1">
+            <property name="visible">True</property>
+            <property name="n_rows">7</property>
+            <property name="n_columns">11</property>
+            <child>
+              <object class="GtkLabel" id="label_pos1">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">&lt;span weight="ultrabold" size="large"&gt;1&lt;/span&gt;</property>
+                <property name="use_markup">True</property>
+                <property name="justify">right</property>
+                <property name="width_chars">1</property>
+                <property name="single_line_mode">True</property>
+              </object>
+              <packing>
+                <property name="top_attach">1</property>
+                <property name="bottom_attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label_pos2">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">&lt;span weight="ultrabold" size="large"&gt;2&lt;/span&gt;</property>
+                <property name="use_markup">True</property>
+                <property name="justify">right</property>
+                <property name="width_chars">1</property>
+                <property name="single_line_mode">True</property>
+              </object>
+              <packing>
+                <property name="top_attach">2</property>
+                <property name="bottom_attach">3</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label_pos3">
+                <property name="visible">True</property>
+                <property name="yalign">0.50999999046325684</property>
+                <property name="label" translatable="yes">&lt;span weight="ultrabold" size="large"&gt;3&lt;/span&gt;</property>
+                <property name="use_markup">True</property>
+                <property name="justify">right</property>
+                <property name="width_chars">1</property>
+                <property name="single_line_mode">True</property>
+              </object>
+              <packing>
+                <property name="top_attach">3</property>
+                <property name="bottom_attach">4</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label_pos4">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">&lt;span weight="ultrabold" size="large"&gt;4&lt;/span&gt;</property>
+                <property name="use_markup">True</property>
+                <property name="justify">right</property>
+                <property name="width_chars">1</property>
+                <property name="single_line_mode">True</property>
+              </object>
+              <packing>
+                <property name="top_attach">4</property>
+                <property name="bottom_attach">5</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label_pos5">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">&lt;span weight="ultrabold" size="large"&gt;5&lt;/span&gt;</property>
+                <property name="use_markup">True</property>
+                <property name="justify">right</property>
+                <property name="width_chars">1</property>
+                <property name="single_line_mode">True</property>
+              </object>
+              <packing>
+                <property name="top_attach">5</property>
+                <property name="bottom_attach">6</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label_pos6">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">&lt;span weight="ultrabold" size="large"&gt;6&lt;/span&gt;</property>
+                <property name="use_markup">True</property>
+                <property name="justify">right</property>
+                <property name="width_chars">1</property>
+                <property name="single_line_mode">True</property>
+              </object>
+              <packing>
+                <property name="top_attach">6</property>
+                <property name="bottom_attach">7</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label_name1">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Ivi</property>
+                <property name="ellipsize">end</property>
+                <property name="width_chars">25</property>
+                <property name="single_line_mode">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="right_attach">2</property>
+                <property name="top_attach">1</property>
+                <property name="bottom_attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <object class="GtkProgressBar" id="progressbar_fuel1">
+                <property name="visible">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">10</property>
+                <property name="right_attach">11</property>
+                <property name="top_attach">1</property>
+                <property name="bottom_attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkProgressBar" id="progressbar_fuel2">
+                <property name="visible">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">10</property>
+                <property name="right_attach">11</property>
+                <property name="top_attach">2</property>
+                <property name="bottom_attach">3</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkProgressBar" id="progressbar_fuel3">
+                <property name="visible">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">10</property>
+                <property name="right_attach">11</property>
+                <property name="top_attach">3</property>
+                <property name="bottom_attach">4</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkProgressBar" id="progressbar_fuel4">
+                <property name="visible">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">10</property>
+                <property name="right_attach">11</property>
+                <property name="top_attach">4</property>
+                <property name="bottom_attach">5</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkProgressBar" id="progressbar_fuel5">
+                <property name="visible">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">10</property>
+                <property name="right_attach">11</property>
+                <property name="top_attach">5</property>
+                <property name="bottom_attach">6</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkProgressBar" id="progressbar_fuel6">
+                <property name="visible">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">10</property>
+                <property name="right_attach">11</property>
+                <property name="top_attach">6</property>
+                <property name="bottom_attach">7</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkProgressBar" id="progressbar_controller1">
+                <property name="visible">True</property>
+                <property name="orientation">bottom-to-top</property>
+              </object>
+              <packing>
+                <property name="left_attach">8</property>
+                <property name="right_attach">9</property>
+                <property name="top_attach">1</property>
+                <property name="bottom_attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkProgressBar" id="progressbar_controller2">
+                <property name="visible">True</property>
+                <property name="orientation">bottom-to-top</property>
+              </object>
+              <packing>
+                <property name="left_attach">8</property>
+                <property name="right_attach">9</property>
+                <property name="top_attach">2</property>
+                <property name="bottom_attach">3</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkProgressBar" id="progressbar_controller3">
+                <property name="visible">True</property>
+                <property name="orientation">bottom-to-top</property>
+              </object>
+              <packing>
+                <property name="left_attach">8</property>
+                <property name="right_attach">9</property>
+                <property name="top_attach">3</property>
+                <property name="bottom_attach">4</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkProgressBar" id="progressbar_controller4">
+                <property name="visible">True</property>
+                <property name="orientation">bottom-to-top</property>
+              </object>
+              <packing>
+                <property name="left_attach">8</property>
+                <property name="right_attach">9</property>
+                <property name="top_attach">4</property>
+                <property name="bottom_attach">5</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkProgressBar" id="progressbar_controller5">
+                <property name="visible">True</property>
+                <property name="orientation">bottom-to-top</property>
+              </object>
+              <packing>
+                <property name="left_attach">8</property>
+                <property name="right_attach">9</property>
+                <property name="top_attach">5</property>
+                <property name="bottom_attach">6</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkProgressBar" id="progressbar_controller6">
+                <property name="visible">True</property>
+                <property name="orientation">bottom-to-top</property>
+              </object>
+              <packing>
+                <property name="left_attach">8</property>
+                <property name="right_attach">9</property>
+                <property name="top_attach">6</property>
+                <property name="bottom_attach">7</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkStatusbar" id="statusbar1">
+            <property name="visible">True</property>
+            <property name="spacing">2</property>
+            <property name="has_resize_grip">False</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
-- 
2.43.5