Gtkticker 001 #!/usr/bin/perl 002 ############################# 003 # gtkticker 004 # Mike Schilli, 2004 005 # (m@perlmeister.com) 006 ############################# 007 use warnings; 008 use strict; 009 010 my $YHOO_URL = 011 "http://quote.yahoo.com/d?". 012 "f=sl1c1&s="; 013 my $RCFILE = 014 "$ENV{HOME}/.gtkticker"; 015 my @LABELS = (); 016 my $UPD_INTERVAL = 60; 017 my @SYMBOLS; 018 019 use Gtk; 020 use POE qw( 021 Component::Client::HTTP); 022 use HTTP::Request; 023 use Log::Log4perl qw(:easy); 024 use Data::Dumper; 025 026 Log::Log4perl->easy_init( 027 $DEBUG); 028 029 # Read config file 030 open FILE, "<$RCFILE" or 031 die "Cannot open $RCFILE"; 032 while() { 033 next if /^\s*#/; 034 push @SYMBOLS, $_ 035 for /(\S+)/g; 036 } 037 close FILE; 038 039 POE::Session->create( 040 inline_states => { 041 _start => \&start, 042 _stop => sub { 043 INFO "Shutdown" }, 044 yhoo_response => 045 \&resp_handler, 046 wake_up => 047 \&wake_up_handler, 048 } 049 ); 050 051 my $STATUS; 052 053 $poe_kernel->post( 054 "ticker", "wake_up"); 055 $poe_kernel->run(); 056 057 ############################# 058 sub start { 059 ############################# 060 061 DEBUG "Starting up"; 062 063 $poe_kernel->alias_set( 064 'ticker'); 065 my_gtk_init(); 066 067 $STATUS->set("Startup"); 068 069 POE::Component::Client::HTTP 070 ->spawn( 071 Agent => 072 'gtkticker/0.01', 073 Alias => 'useragent', 074 Timeout => 60, 075 ); 076 } 077 078 ############################# 079 sub upd_quotes { 080 ############################# 081 082 my $request = 083 HTTP::Request->new( 084 GET => $YHOO_URL . 085 join ",", @SYMBOLS); 086 087 $STATUS->set( 088 "Fetching quotes"); 089 090 $poe_kernel->post( 091 'useragent', 092 'request', 093 'yhoo_response', 094 $request); 095 } 096 097 ############################# 098 sub my_gtk_init { 099 ############################# 100 101 my $w = Gtk::Window->new(); 102 $w->set_default_size( 103 150,200); 104 105 # Create Menu 106 my $accel = 107 Gtk::AccelGroup->new(); 108 $accel->attach($w); 109 my $factory = 110 Gtk::ItemFactory->new( 111 'Gtk::MenuBar', 112 "
", $accel); 113 114 $factory->create_items( 115 { path => '/_File', 116 type => '', 117 }, 118 { path => 119 '/_File/_Quit', 120 accelerator => 121 'Q', 122 callback => 123 [sub { Gtk->exit(0) }], 124 }); 125 126 my $vb = Gtk::VBox->new( 127 0,0); 128 my $upd = Gtk::Button->new( 129 'Update'); 130 131 $vb->pack_start( 132 $factory->get_widget( 133 '
'), 0, 0, 0); 134 135 # Button at bottom 136 $vb->pack_end($upd, 137 0, 0, 0); 138 139 # Status line on top 140 # of buttons 141 $STATUS= Gtk::Label->new(); 142 $STATUS->set_alignment( 143 0.5, 0.5); 144 $vb->pack_end($STATUS, 145 0, 0, 0); 146 my $table = 147 Gtk::Table->new( 148 scalar @SYMBOLS, 3); 149 150 $vb->pack_start($table, 151 1, 1, 0); 152 153 for my $row (0.. 154 @SYMBOLS-1) { 155 for my $col (0..2) { 156 my $label = 157 Gtk::Label->new(); 158 $label->set_alignment( 159 0.0, 0.5); 160 push @{$LABELS[$row]}, 161 $label; 162 163 $table->attach_defaults( 164 $label, $col, $col+1, 165 $row, $row+1); 166 } 167 } 168 169 $w->add($vb); 170 171 # Destroying window 172 $w->signal_connect( 173 'destroy', sub { 174 Gtk->exit(0)}); 175 176 # Pressing update button 177 $upd->signal_connect( 178 'clicked', sub { 179 DEBUG "Sending wakeup"; 180 $poe_kernel->post( 181 'ticker', 'wake_up')} 182 ); 183 $w->show_all(); 184 } 185 186 ############################# 187 sub resp_handler { 188 ############################# 189 my ($req, $resp) = 190 map { $_->[0] } 191 @_[ARG0, ARG1]; 192 193 if($resp->is_error()) { 194 ERROR $resp->message(); 195 $STATUS->set( 196 $resp->message()); 197 return 1; 198 } 199 200 DEBUG "Response: ", 201 $resp->content(); 202 203 my $count = 0; 204 205 for(split /\n/, 206 $resp->content()) { 207 208 my($symbol, $price, 209 $change) = 210 split /,/, $_; 211 212 chop $change; 213 $change = "" if 214 $change =~ /^0/; 215 216 $symbol =~ s/"//g; 217 $LABELS[$count][0]-> 218 set($symbol); 219 $LABELS[$count][1]-> 220 set($price); 221 $LABELS[$count][2]-> 222 set($change); 223 $count++; 224 } 225 226 $STATUS->set(""); 227 228 1; 229 } 230 231 ############################# 232 sub wake_up_handler { 233 ############################# 234 DEBUG("waking up"); 235 236 # Initiate update 237 upd_quotes(); 238 239 # Re-enable timer 240 $poe_kernel->delay( 241 'wake_up', $UPD_INTERVAL); 242 } @KE: