#!/usr/bin/perl # vim: set ai noet ts=8 sw=8 sts=8 ft=perl : # set username # set uptime # set time # set xtitle of focused window # set list of windows for current tag # set list of windows for all tags # set la # set current language # set battery charge # main loop impl. : # save cur. str and compare it with prev. if it differs - update # proposed: 3 types of loop: # slow loop for batt charge, la # 1 second loop for time, uptime - generally, it looks like we do not need poll every second # timers if clock granularity set to 1 minute or even coarse # main (fast) loop for window name, language, it looks like we have some room here for greater # improvement, when it'll be more clear how get info directly from x server use strict; use warnings "all"; use Fcntl qw(:seek); use Net::DBus; binmode STDOUT; binmode STDERR; sub onesec_cron(); sub slow_cron(); sub gettimestr(); sub getfocusedwidowtitlestr(); sub getlangstr(); sub getuptimestr(); sub getlastr(); sub getbatterychargestr1(); sub getbatterychargestr2(); sub getbatterychargestr3(); sub meminfo(); sub to_hours($); # translates seconds to HH:MM format my $slow_timer = 360; # 0.333 * 360 ~= 2 min my $onesec_timer = 3; # 0.333 * 3 ~= 1 sec my @months = ('Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'); my @wdays = ('Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'); my $pstr = ''; my $charge; my $la; my $uptime; my $time; my $mem; my $bus = Net::DBus->system; my $upower = $bus->get_service("org.freedesktop.UPower"); my $properties = $upower->get_object("/org/freedesktop/UPower/devices/battery_BAT0", "org.freedesktop.DBus.Properties"); my $UPTIMEHANDLE; my $LAHANDLE; my $MEMINFOHANDLE; sleep 1; while (1) { if ($onesec_timer >= 3) { onesec_cron(); $onesec_timer = 0; } if ($slow_timer >= 360) { slow_cron(); $slow_timer = 0; } my $str = ''; # $str .= getfocusedwidowtitlestr(); # $str .= "$ENV{'USER'}"; $str .= getlangstr(); $str .= $uptime; $str .= $la; $str .= $mem; $str .= $charge; $str .= $time; if ($pstr ne $str) { syswrite STDOUT, "$str\n"; $pstr = $str; } # tick timers $slow_timer++; $onesec_timer++; # sleep for 0.333 second; select(undef, undef, undef, 0.333); } sub slow_cron() { $charge = getbatterychargestr3(); $la = getlastr(); } sub onesec_cron() { $uptime = getuptimestr(); $time = gettimestr(); # as we report time with precision of 1 minute, update 1/60 seconds $mem = meminfo(); } sub gettimestr() { my ($sec, $min, $hour, $mday, $mon, $year, $wday) = (localtime)[0,1,2,3,4,5,6]; $year = $year + 1900; my $str .= sprintf(" | %s, %s %s %s %02s:%02s ", $wdays[$wday], $mday, $months[$mon], $year, $hour, $min); return $str; } sub getfocusedwidowtitlestr() { my $str; if (-x '/usr/bin/xdotool') { $str = `xdotool getactivewindow getwindowname`; } elsif (-x '/usr/bin/xprop') { $str = (split( / = /, `xprop -id \$(xprop -root _NET_ACTIVE_WINDOW | cut -d ' ' -f 5) _NET_WM_NAME`))[1]; chop $str; chop $str; } chomp($str); if (length($str) != 0) { if (length($str) > 64){ $str = '...' . substr($str, 0, -61); } $str = '['. $str .'] | '; } else { $str = '| '; } return $str; } sub getuptimestr() { if (defined($UPTIMEHANDLE)) { open $UPTIMEHANDLE, "/proc/uptime" if (tell($UPTIMEHANDLE) == -1); } else { open $UPTIMEHANDLE, "/proc/uptime"; } my $u = <$UPTIMEHANDLE>; seek $UPTIMEHANDLE, SEEK_SET, 0; $u = (split(/ /, $u, 2))[0]; my $days = int($u / 86400); # 86400 = 1 day my $hours = int(($u - (86400 * $days)) / 3600); # 3600 = 1 hour my $minutes = int(($u - (86400 * $days) - (3600 * $hours)) / 60); my $seconds = int($u - (86400 * $days) - (3600 * $hours) - (60 * $minutes)); my $str = sprintf(" | up: %sd,%02sh,%02sm ", $days, $hours, $minutes); return $str; } sub getlastr() { if (defined($LAHANDLE)) { open $LAHANDLE, "/proc/loadavg" if (tell($LAHANDLE) == -1); } else { open $LAHANDLE, "/proc/loadavg"; } my $la = <$LAHANDLE>; seek $LAHANDLE, SEEK_SET, 0; $la = (split(/ /, $la, 2))[0]; return (" | LA: $la "); } sub getbatterychargestr1() { my $str = ''; if (-f "/sys/class/power_supply/BAT0/present") { open A, "/sys/class/power_supply/BAT0/present"; my $P = ; close A; chomp($P); if ($P eq '1') { open A, "/sys/class/power_supply/BAT0/energy_full"; my $full_charge = ; close A; chomp($full_charge); open A, "/sys/class/power_supply/BAT0/energy_now"; my $current_charge = ; close A; chomp($current_charge); $str .= sprintf(" | Bat: %03d%% ", int(($current_charge / $full_charge) * 100) ); undef $current_charge; undef $full_charge; } } return $str; } sub getbatterychargestr2() { my $str .= " | Power: "; open AC,"/sys/class/power_supply/ADP1/online"; if ( == 1) { $str .= "AC"; } else { $str .= "DC"; } close AC; # display % charge only if possible if (open DC,"/sys/class/power_supply/BAT0/capacity") { $str .= ' '. ; close DC; chomp $str; $str .= '%'; } return $str; } sub getbatterychargestr3() { my $capacity = $properties->Get('org.freedesktop.UPower.Device', 'Percentage'); my $state = $properties->Get('org.freedesktop.UPower.Device', 'State'); my $time = "?"; if ($state == 2) { # discharging $time = $properties->Get('org.freedesktop.UPower.Device', 'TimeToEmpty'); # time in seconds, let's translate it to hours:minutes $state = '▼'; } elsif ($state == 1) { # charging $time = $properties->Get('org.freedesktop.UPower.Device', 'TimeToFull'); $state = '▲'; } else { # already charged $time = 0; $state = '•'; } $time = to_hours ($time); return sprintf(" | %s%% %s %s", $capacity, $state, $time); } sub getlangstr() { my $str .= " | Lang: "; if (`xset -q` =~ /Group 2: on /o) { $str .= "RU"; } else { $str .= "EN"; } return $str; } sub meminfo() { if (defined($MEMINFOHANDLE)) { open ($MEMINFOHANDLE, "/proc/meminfo") if (tell($MEMINFOHANDLE) == -1); } else { open ($MEMINFOHANDLE, "/proc/meminfo"); } my @mem = <$MEMINFOHANDLE>; seek $MEMINFOHANDLE, SEEK_SET, 0; @mem = map { substr($_, 0, -4) } @mem; my $memavail = (split(/\s+/, $mem[2]))[1]; my $swaptotal = (split(/\s+/, $mem[14]))[1]; my $swapfree = (split(/\s+/, $mem[15]))[1]; return sprintf ( " | mem: %s M | sw: %s M", int($memavail / 1024), int(($swaptotal - $swapfree) / 1024) ); } sub to_hours ($) { my $sec = shift; my $hrs = $sec / (60 * 60); $hrs = 0 if ( $hrs < 1 ); my $min = ($sec - ($hrs * 60 * 60)) / 60; $min = 0 if ( $min < 1 ); return sprintf("%02d:%02d", $hrs, $min); }