hmmm....

Alfred 2 Workflow for Audio Device Selection

Alfred V2 has a great new feature called workflows. I’ve been playing with a few others wrote and had ported my old custom commands to workflows but was looking for something to really make use of their power.

Changing OSX Audio device from menubar Changing the selected audio output device was just the thing to implement as a workflow. OS X has a nice shortcut for doing this without heading to system preferences. Option clicking the speaker in the menu bar well let you change the input or output device, but I wanted to do it easily from the keyboard.

The ‘Script Filter’ option under the input menu is the magic for this workflow. It allows a script to output a list of items for display and selection in the Alfred GUI. You get Alfred’s great predictive auto complete which makes selecting a device a breeze.

Selecting output audio device in Alfred

Output via Growl or Notification Center provides feedback of the completed action.

Growl confirmation

The workflow is pretty simple in Alfred’s workflow editor, it ends up looking like this:

Alfred work flow

Alfred makes sharing workflows insanely easy by throwing all the necessary files for each workflow in a dedicated directory. Right clicking a workflow in Alfred gives an export workflow option which creates a zip file of this directory with the ‘.alfredworkflow’ extension.

Grab SwitchAudio.alfredworkflow

The heavy lifting is done by switchaudio-osx by deweller on GitHub with a simple perl glue script to pass data back and forth between Alfred and switchaudio-osx.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#!/usr/bin/env perl

use strict;
use warnings;

use FindBin;

my $action = shift || 'list';
my $direction = shift || 'output';

if ($action eq 'list') {
    my $devices = get_possibilities($direction);
    print qq{<?xml version="1.0"?>\n<items>\n};
    print output_device($_) for @$devices;
    print "</items>\n";
}

if ( $action eq 'set' ) {
    my $device = shift;
    print set_device($direction, $device) . "\n";
}

sub get_possibilities {
    my $direction = shift;
    my @devices;
    open( my $fh, '-|', $FindBin::Bin . '/SwitchAudioSource',
        '-at', $direction );
    while ( my $line = <$fh> ) {
        chomp $line;
        $line =~ s/ \(\Q$direction\E\)$//;
        push @devices, $line;
    }
    close $fh;
    return \@devices;
}

sub set_device {
    my ( $direction, $device ) = @_;
    open( my $fh, '-|', $FindBin::Bin . '/SwitchAudioSource',
        '-t', $direction, '-s', $device );
    my $output = join "\n", <$fh>;
    close $fh;
    return $output;
}

sub output_device {
    my $device = shift;
    ( my $device_no_space = $device ) =~ tr/ /_/;
    return qq{<item arg="$device" uid="$device_no_space"><title>$device</title><subtitle/><icon>icon.png</icon></item>\n};
}

Fair Trade Coffee Price Premium

Galloway Township considered a resolution last week that would support fair trade practices. The resolution was tabled after some brief discussion. The cost difference between fair trade and non fair trade items was brought up and I was curious how much of a difference there was.

The town currently gets most office supplies from WB Mason. I do not know if this includes coffee but at work we get our coffee from WB Mason so as any Geek would do, I made a spread sheet.

Direct Link to Google Docs Spreadsheet

There are only two fair trade items in this category but they are right in line with prices for non fair trade varieties. If you are already using one of the non fair trade blends from the two companies with a fair trade blend, there is 0 price difference.

This lack of price difference surprised me.

ZSH Completion Waiting Dots

ZSH has some pretty nice tab completion but some of the completion modules can make things slow when you have a high latency conection. This can be extra harsh for me as I have failure to complete beeps turned off so I’m not sure if it’s still trying to complete or if there were no matches. When reading some zshrc snippts on Stack Overflow I came accross my favorite new snippit.

This snippet from a paid nerd adds ‘…’ output during completion that is replaced with the completion or removed once the completion engine is finished.

Here’s the snippet:

1
2
3
4
5
6
7
8
# http://stackoverflow.com/a/844299
expand-or-complete-with-dots() {
  echo -n "\e[31m...\e[0m"
  zle expand-or-complete
  zle redisplay
}
zle -N expand-or-complete-with-dots
bindkey "^I" expand-or-complete-with-dots

Also, get yourself in the habbit of including a comment with a url for stuff like this. I once wanted to write a blog post about something I found somewhere and couldn’t remember where I found it online! I’ll never make that mistake again.

Syncing Zsh Named Directories

One of my most used features of zsh is named directories. I keep my dotfiles synced across multiple machines via Dropbox (referral link) and a Makefile that creates symlinks automagically.

My named directories start with ~ for my home directory so they need to exist for expansion to work properly and not output errors when I log in. When I first implemented syncing I added this check with a very simple test:

DHS NOC MNC Poor Security Examples

The Media Monitoring Capability of the The Department of Homeland Security’s National Operations Center is tasked with keeping existing situation summaries for both domestic and international events up to date with open source media information. Their second mission is “to constantly monitor all available open source information with the goal of expeditiously alerting the NOC Watch Team and other key Department personnel of emergent situations”. This means monitoring both various online news sites as well as social networking.

Through a Freedom of Information Act request their Analyst’s Desktop Binder (4.4 MB PDF) was made publicly available. This is essentially the employee manual for MMC analysts, describing how to preform their job. There are quite a few very interesting tid bits in it such as the list of keywords and search terms used when searching social media sites.

Tweeting Thermostat

I recently replaced the thermostat in our new house with a Filtrete 3M-50. This thermostat has a wifi module and is available at your local Home Depot for $99. I’d been aware of it for a while but had planned on purchasing the $250 nest. The turning point for me came one even as I was going to bed. I was hot, the heat was running and I chose to turn the fan on instead of going downstairs and adjusting the thermostat. In my defense, I knew the thermostat would switch to night mode in another 45 minutes and reduce the set point but I was still wasting energy.

Comparing the Filtrete to the nest the main features you are missing out on are:

Migrating Post Tags From Wordpress to Octopress

I’ve migrated from Wordpress to Octopress and used the Jekyll wordpress migrator to move my posts over. Unfortunately, this doesn’t preserve post tags. The output looks like this:

1
2
3
4
5
6
7
8
---
layout: post
title: Devops w/ Perl @ Linode PPW Talk Slides
wordpress_id: 330
wordpress_url: http://michael.thegrebs.com/?p=330
date: 2011-10-27 14:46:31 -04:00
---
Earlier this month I gave a talk about...

Having the wordpress post id means extracting the post tags from the db should be quite easy. First we define our desired output:

1
2
3
4
5
6
7
8
9
---
layout: post
title: Devops w/ Perl @ Linode PPW Talk Slides
wordpress_id: 330
wordpress_url: http://michael.thegrebs.com/?p=330
date: 2011-10-27 14:46:31 -04:00
tags: geek perl slides
---
Earlier this month I gave a talk about ...

The tags field really can appear anywhere in this YAML fragment but I chose to throw it at the end. With 103 posts to loop over, run a query and insert a new line a short script makes sense. The real win for our script though is using the Tie::File module which presents each file as an array with an element for each line.

Local Growl Notifications From Remote Irssi

What I’ve tried, What I want

Skip to the next section if you just care about the end result. In the past, I’ve had my remote Irssi client send UDP Growl packets to my static home IP that were then forwarded to the broadcast address on the local network. This worked great and allowed me to get Growl notifications on which ever computer I happened to be sitting at. These days, I’m always on my laptop, even when sitting at another computer (Teleport for the mega win).

I wanted a solution that would allow me to receive Growl notifications without having to forward any ports and no matter what the public IP for my laptop may be. I use App::PersistentSSH to maintain a persistent SSH control master connection to my Linode so the ideal solution uses a reverse tunnel over this connection to get the notifications too my laptop.

My Current Solution

  • Added --ssh_opts -R 127.0.0.1:22992:127.0.0.1:22 to my App::PersistentSSH command line. This connects localhost:22992 on my Linode to port 22 on my laptop.
  • local-growl.pl – an Irssi script that uses growlnotify to send growl notifications
  • growlnotify.pl – an ssh proxy for growlnotify, passes it’s arguments to growlnotify on a remote system via ssh

Simple push growl notifications from my Linode –> my MacBook Air whenever it is online. The scripts and an irssi.png to use in the notifications are available on GitHub.

Configuration for local-growl.pl is via Irssi’s in built settings, type /set growl to see a list of possibilites:

1
2
3
4
5
6
7
[local-growl]
growl_enabled = ON
growl_growlnotifypath = /home/michael/bin/growlnotify
growl_image_path = /Users/mgreb/Documents/irssi.png
growl_show_hilights = ON
growl_show_private_messages = ON
growl_sticky = OFF

Configuration for growlnotify.pl is via a set of config variables near the top:

1
2
3
4
my $ssh_host    = 'localhost';
my $ssh_port    = 22992;
my $ssh_user    = 'mgreb';
my $growlnotify = '/usr/local/bin/growlnotify';

Hopefully you will find this useful.