Cookie Notice

As far as I know, and as far as I remember, nothing in this page does anything with Cookies.

2010/01/30

NGD -- Headphones!

A mere 8 feet from where I sit at work, that's where the main gathering and reception area for the lab is. This is a problem. So, I listen to music. I try to go for audio wallpaper, things like Monolake or Mogwai or Pell Mell. (Bands must have a capital M in the name. B) ) But last year, my work headphones lost an ear. Which makes things not work.

I picked up Sony MDR V150 headphones. $20 at Wal-Mart. Cost $15 on Amazon, but factor in shipping and it's a wash, plus I can bring 'em to work tomorrow. I'm liking the bass response, which is much better than what I normally hear at work, so I'm happy.

This always brings up the "programming music" question. My go-to these days is post-rock. I'm in to lots of other stuff, but I'm into it because it engages me, and when you program, you don't want to be engaged by your audio filter, you want to be engaged by the task on hand. Here's a LifeHacker post that starts with classical music and Brian Eno. I don't want to reject centuries of music for stupid reasons, but there's absolutely no swing in that genre. It was before the invention of swing, and I find the lack of swing really pulls me out of my tasks.

Any suggestions from the peanut gallery? What's good programming music?

2010/01/29

On Voice Messaging



This from Gizmodo came across my Google Reader, and I can only say "yeah!" I hate the whole process. I liked Vonage when we had it, and I like the office voice mail, because it gets sent to me when it comes, so I can play it like a WAV file.

The ultimate, of course, is Google Voice, which runs voice recognition on it, so that they leave the message with voice but you just have to read it.

Charting the Descent into Madness

A friend is getting XMPP to work on a private network, mixing XP, Linux and Solaris. So private, only he's on it. Madness after the cut.


2010/01/28

Solutions to my Remedial Perl Module Problems

Thanks to Stack Overflow, I can move forward. Stupid examples below.

test.pl

#!/usr/bin/perl
use 5.010 ;
use strict ;
use warnings ;

#use Dumb::Database ':all' ;
use Dumb ':all' ;

my_dumb_function() ;


Dumb.pm

package Dumb ;
use 5.010 ;
use strict;
use warnings;
use Exporter qw(import);
use lib '/home/jacoby/lib' ;
use Dumb::Database ':all' ;

our %EXPORT_TAGS = ('all' => [ qw(
my_dumb_function
) ],
);
our @EXPORT_OK = ( @{$EXPORT_TAGS{'all'}} );
our $VERSION = 0.0.1;

1;


Dumb/Database.pm

package Dumb::Database ;
use 5.010 ;
use strict;
use warnings;

use Exporter qw(import);
our %EXPORT_TAGS = ('all' => [ qw(
my_dumb_function
) ],
);
our @EXPORT_OK = ( @{$EXPORT_TAGS{'all'}} );

sub my_dumb_function {
say 'dumb' ;
}
1;

Perl Module Design For Dummies, or "I didn't know any better"

I have a 2 KLOC monster. I started writing it and it just grew and grew and grew. Now I hate it, which is sad, because I wrote every [REDACTED] word. Before I started working on it, I hadn't done much with Perl's DBI module and I hadn't written much with modules.

jacoby@oz:~/lib$ ls -l SecGenTools.pm
-rw------- 1 jacoby jacoby 60575 2010-01-26 15:25 SecGenTools.pm
jacoby@oz:~/lib$ wc SecGenTools.pm
2175 8253 60575 SecGenTools.pm
jacoby@oz:~/lib$ grep 'sub ' SecGenTools.pm | wc -l
96
jacoby@oz:~/lib$


Now, I'd love to refactor, break it apart into little pieces, but I'm at a loss about how.

It would be fairly easy to break out SecGenTools::FormTools and SecGenTools::RequestTools and the like. That makes seven kinds of sense. The problem is that I don't have use SecGenTools::FormTools ; in the existing code, I just have use SecGenTools::FormTools ; I could imagine line after line like this.

package Dumb ;
use strict ;
use warnings ;
use Dumb::Dumber ;
use Exporter qw(import) ;
our %EXPORT_TAGS = (
'all' => [ qw( my_function ) ] ,
) ;

sub dumb_function {
return Dumb::Dumber::dumb_function( @_ ) ;
}

1 ;

But that seems fragile and quite stupid.

Is there any way to seemlessly export the functions of Dumb::Dumber from Dumb without explicitly writing wrapper functions within Dumb? Or am I doomed?

2010/01/26

TV Workflow Considerations

I have a Vista machine with a 300GB drive and a TV tuner.

I have an XP machine with a 40GB drive that's connected to a TV.

I have a Linux box that has an out-facing SSH connection.

I record a few sets of shows.
  • Things the family would like
  • Things that I'd like to share with friends
  • Things I want for myself
Things in the first set, I'd like to have on or at least accessible to the laptop. Having 40GB, it won't have much if any room for files, and the dvr-ms format means a file could be up to 1.5GB. I would like to down-convert the shows for my friend and place them in a directory where my friend can get them.

Problem is, the Linux machine cannot see the Vista machine. Well, yeah via Gnome but not via fusesmb, so I can't really make a crontab. So, if I really want to do this, I have to learn how to do scheduled tasks on Vista Home Edition.

And ffmpeg seems to be hit-and-miss with opening the videos. Don't know what to do about that.

2010/01/22

gcalcli - command-line interface to Google Calendars

The coolest of all things about Google Calendar is how you can just put anything into the field and it'll interpret it. Most calendar programs have involved configurations, which are available if you need to fine-tune your gCal events, but being able to type in "LUG meeting 7pm in ECE" and having it know what you mean? That's good.

But it means having Google Calendar open. Which, honestly, I don't often do. With alerts, I have Evolution keeping track, I have some code that checks my calendar and sends me IMs to warn me, and there's what Google does automatically with SMS and email. If I have to go, I don't need Google Calendar open to remind me. So, like with Twitter and other things I've coded, what I need is a way to use Google Calendar without really using Google Calendar.

And gcalcli is that. It's a snazzy command line interface to Google. For Ubuntu folks, installation is as easy as sudo apt-get install gcalcli, and it shouldn't be much harder for the rest of you. All you need to do is type:

gcalcli quick '7pm Pick up Windows7 at Best Buy '

And there it is.

But I can't leave it there.


I've come to liking this kind of form for more social and less structured commands

program Long line of words that is a sentence, not an array of commands


So, I have a wrapper for the quick function here.


#!/usr/bin/perl

use strict ;
use warnings ;
use 5.010 ;
use subs qw{ set_status } ;

my $args = join ' ', @ARGV ;
if ( $args eq '' ) {
while ( ) {
$args .= $_;
}
}
create_event( $args ) ;

exit ;

########## ########## ########## ########## ########## ########## ##########
sub create_event {
my ( $msg ) = @_ ;
qx{/usr/bin/gcalcli quick '$msg' } ;
say $msg ;
}
########## ########## ########## ########## ########## ########## ##########


The thing I like most about this is how I don't have to worry about handling passwords. It's in the .gcalcli config itself. More on other uses later.

2010/01/14

Making Pretty Pictures

GD::Graph


R


Chart::Clicker
This should have times across the bottom. It doesn't. I don't know why.

These three images are of the same thing, graphed with different tools. I start by getting the data for these arrays out of the database:






















@number #temp_f @date
1 33 14:20
2 35 15:00
3 36 16:00
4 37 17:00
5 37 18:00
6 35 19:00
7 33 20:00
8 32 21:00
9 33 22:00
10 32 23:00
11 32 00:00
12 32 01:00
13 32 02:00
14 32 03:00
15 30 04:00
16 30 05:00
17 30 06:00
18 29 07:00
19 30 08:00
20 32 09:00


These three examples use the same basic information to draw the graph.

The database code



#!/usr/bin/perl

####################################
###### Draw Weather Graph ######
####################################

use 5.010 ;
use strict ;
use warnings ;

use Chart::Clicker;
use Chart::Clicker::Context;
use Chart::Clicker::Data::DataSet;
use Chart::Clicker::Data::Marker;
use Chart::Clicker::Data::Series;
use Chart::Clicker::Renderer::Area;
use Chart::Clicker::Renderer::Point;
use Chart::Clicker::Renderer::StackedArea;
use Geometry::Primitive::Rectangle;
use Geometry::Primitive::Circle;
use Graphics::Color::RGB;
use Graphics::Primitive::Font;
use Graphics::Primitive::Brush;

use Data::Dumper ;
use DBI ;
use Getopt::Long ;
use IO::Interactive qw{ interactive } ;

use lib '/home/jacoby/lib' ;
use MyDB 'db_connect' ;
use subs qw{
high low mean median mode range
} ;

my $dbh = db_connect() ;
my $sql ;

$sql .= 'SELECT ' ;
$sql .= 'time , ' ;
$sql .= 'temp_f ' ;
$sql .= 'FROM weather WHERE zip = "47909" ' ;
$sql .= 'AND HOUR( TIMEDIFF( SYSDATE() , time ) ) < 25 ' ;
$sql .= 'GROUP BY HOUR(time)' ;
$sql .= 'ORDER BY time' ;

my $hr = $dbh->selectall_arrayref( $sql ) or croak $dbh->errstr ;
my %tg ;

my @temp_f ;
my @date ;
my @number ;
my $count = 1 ;

for my $a ( @$hr ) {
$$a[0] = join ':' , ( split m{:} , ( split m{\s}mx , $$a[0] )[1] )[0..1];
push @date , $$a[0] ;
push @temp_f , $$a[1] ;
push @number , $count++ ;
}


Making the GD PNG



my @data = (
[@date] ,
[@temp_f]
) ;

my $graph = new GD::Graph::lines( 500,200 ) or die;
$graph->set(
x_label => 'Temperature',
y_label => 'Time',
bgclr => 'white' ,
transparent => 0 ,
title => 'Lafayette,IN Temperatures in F for the last 24 Hours',
) or die $graph->error;
$graph->set_title_font( '/home/jacoby/.fonts/trebuc.ttf' , 12 ) or die $graph->error;
$graph->set_legend_font( '/home/jacoby/.fonts/trebuc.ttf' , 8 ) or die $graph->error;
$graph->set_x_label_font( '/home/jacoby/.fonts/trebuc.ttf' , 10 ) or die $graph->error;
$graph->set_y_label_font( '/home/jacoby/.fonts/trebuc.ttf' , 10 ) or die $graph->error;
my $gd = $graph->plot(\@data) or die $graph->error;

open(IMG, '>' , '/home/jacoby/Desktop/24gd.png') or die $!;
binmode IMG;
print IMG $gd->png;




Making the R output



my $number = join ',' , @number;
my $temp_f = join ',' , @temp_f ;
my $date = join ' , ' , ( map { qq("$_") } @date );

my $r = <<"R" ;
#x <- (1:24)
x <- c( $number )
#x <- c( $date )
data <- c( $temp_f )
png(filename='/home/jacoby/Desktop/24r.png', width=500 ,height=200 )
plot(
x ,
data ,
type='l',
main='Lafayette,IN Temperatures in F for the last 24 Hours',
xlab='Time' ,
ylab='Temperature (f)'
)
#axis( 1 , at=1:48 )
dev.off()
R

open my $rh , '>' , '/home/jacoby/Desktop/24r.R' ;
say $rh $r ;

Which then has R CMD BATCH filename.R run on it to plot the graph. I could put that in as a qx{} bit, but I didn't here. Normally, yes, I would and in fact we have several that do.


Making the Chart::Clicker PNG




my $cc = Chart::Clicker->new(width => 500, height => 200, format => 'png');
my $series1 = Chart::Clicker::Data::Series->new(
keys => \@number ,
values => \@temp_f ,
);
my $dataset = Chart::Clicker::Data::DataSet->new(
series => [ $series1 ] ,
);

$cc->title->text('Lafayette,IN Temperatures in F for the last 24 Hours');
$cc->add_to_datasets($dataset);

$cc->get_context('default')->domain_axis->tick_values($series1->keys);
$cc->get_context('default')->domain_axis->tick_labels(\@date);
$cc->get_context('default')->domain_axis->tick_label_angle(1);

$cc->get_context('default')->domain_axis->fudge_amount( 0.05 );
$cc->get_context('default')->range_axis->fudge_amount( 0.1 );

my $defctx = $cc->get_context('default');
$defctx->range_axis->label( ' Temperature ' );
$defctx->domain_axis->label('Time');
$defctx->renderer->brush->width(2);
$cc->write_output('/home/jacoby/Desktop/24cc.png');

The big win is that it's graphed right. The next win is that it's all Perl, so I don't need to go back and run a plotter on the output. The last win is that it looks good.

BTW, I find it interesting that, at least on Jan 14 2010, when I do an image search on Chart::Clicker, this blog gets the top spot.

2010/01/07

San Francisco jails for proper system administration

By and large, I see no indefensible actions on the part of Terry Childs. I do see indefensible actions on the part of Herb Tong. If you're in computing, I would strongly suggest you avoid working for the city of San Francisco.

Free Terry Childs.