#!/usr/bin/perl ########################################### # gtkticker # Mike Schilli, 2004 (m@perlmeister.com) ########################################### use warnings; use strict; my $YHOO_URL = "http://quote.yahoo.com/d?". "f=sl1c1&s="; my $RCFILE = "$ENV{HOME}/.gtkticker"; my @LABELS = (); my $UPD_INTERVAL = 60; my @SYMBOLS; use Gtk; use POE qw(Component::Client::HTTP); use HTTP::Request; use Log::Log4perl qw(:easy); use Data::Dumper; Log::Log4perl->easy_init($DEBUG); # Read config file open FILE, "<$RCFILE" or die "Cannot open $RCFILE"; while() { next if /^\s*#/; push @SYMBOLS, $_ for /(\S+)/g; } close FILE; POE::Session->create( inline_states => { _start => \&start, _stop => sub { INFO "Shutdown" }, yhoo_response => \&resp_handler, wake_up => \&wake_up_handler, } ); my $STATUS; $poe_kernel->post("ticker", "wake_up"); $poe_kernel->run(); ########################################### sub start { ########################################### DEBUG "Starting up"; $poe_kernel->alias_set( 'ticker' ); my_gtk_init(); $STATUS->set("Starting up"); POE::Component::Client::HTTP->spawn( Agent => 'gtkticker/0.01', Alias => 'useragent', Timeout => 60, ); } ########################################### sub upd_quotes { ########################################### my $request = HTTP::Request->new( GET => $YHOO_URL . join ",", @SYMBOLS); $STATUS->set("Fetching quotes"); $poe_kernel->post('useragent', 'request', 'yhoo_response', $request); } ######################################### sub my_gtk_init { ######################################### my $w = Gtk::Window->new(); $w->set_default_size(150,200); # Create Menu my $accel = Gtk::AccelGroup->new(); $accel->attach($w); my $factory = Gtk::ItemFactory->new( 'Gtk::MenuBar', "
", $accel); $factory->create_items( { path => '/_File', type => '', }, { path => '/_File/_Quit', accelerator => 'Q', callback => [sub { Gtk->exit(0) }], }); my $vb = Gtk::VBox->new(0, 0); my $upd = Gtk::Button->new( 'Update'); $vb->pack_start($factory->get_widget( '
'), 0, 0, 0); # Button at bottom $vb->pack_end($upd, 0, 0, 0); # Status line on top of buttons $STATUS = Gtk::Label->new(); $STATUS->set_alignment(0.5, 0.5); $vb->pack_end($STATUS, 0, 0, 0); my $table = Gtk::Table->new( scalar @SYMBOLS, 3); $vb->pack_start($table, 1, 1, 0); for my $row (0..@SYMBOLS-1) { for my $col (0..2) { my $label = Gtk::Label->new(); $label->set_alignment(0.0, 0.5); push @{$LABELS[$row]}, $label; $table->attach_defaults($label, $col, $col+1, $row, $row+1); } } $w->add($vb); # Destroying window $w->signal_connect('destroy', sub {Gtk->exit(0)}); # Pressing update button $upd->signal_connect('clicked', sub { DEBUG "Sending wake_up"; $poe_kernel->post( 'ticker', 'wake_up')} ); $w->show_all(); } ########################################### sub resp_handler { ########################################### my ($req, $resp) = map { $_->[0] } @_[ARG0, ARG1]; if($resp->is_error()) { ERROR $resp->message(); $STATUS->set($resp->message()); return 1; } DEBUG "Response: ", $resp->content(); my $count = 0; for(split /\n/, $resp->content()) { my($symbol, $price, $change) = split /,/, $_; chop $change; $change = "" if $change =~ /^0/; $symbol =~ s/"//g; $LABELS[$count][0]->set($symbol); $LABELS[$count][1]->set($price); $LABELS[$count][2]->set($change); $count++; } $STATUS->set(""); 1; } ########################################### sub wake_up_handler { ########################################### DEBUG("waking up"); # Initiate update upd_quotes(); # Re-enable timer $poe_kernel->delay('wake_up', $UPD_INTERVAL); }