Mac OS X Audio in node.js, and a Chromecast

| Comments

A few weeks ago, a simple idea formed: why can’t you easily stream system audio to a Chromecast? Sure, if your chosen listening application already supports it, you’re set. Otherwise you’re left out.

A solution seemed simple: node.js has streams, and they’re awesome! Take system audio, pipe it to an encoder, pipe that to an HTTP response, and tell the Chromecast where to look. Easy!

Except, there’s no node.js package that supports OS X audio input, except via bindings to another library. I wanted to write something that was only dependent on the OS X core frameworks.

Hello osx-audio

A few weeks later, and there’s a solution (writing your first node.js native binding is hard!). osx-audio will allow you to get a readable stream from your currently-selected OS X audio input. It only depends on the frameworks available in Mac OS X, so if you can compile any other native node.js extension, you should be able to install it!

You should check it out if audio input’s the thing you need. Output will be implemented in the future too!

How about the Chromecast?

Solved, but it still requires an additional piece of software. You see, OS X doesn’t provide native methods for accessing system audio (the output of the system mixer) so anything that’s not an input (like the microphone) is inaccessible. However, there’s a open source utility called Soundflower that solves this for you. If you’re unfamiliar with it, here’s a step by step to get it working:

  1. Install Soundflower. Reboot.
  2. Install chromecast-osx-audio globally, with an npm install -g chromecast-osx-audio
  3. Open your System Preferences -> Sound preference pane, and select “Soundflower (2ch)” as both your input and output.
  4. Run chromecast in your terminal. It will find the first-available Chromecast, and stream your system audio to it.
  5. Play your music/audio as normal. There is a 5–15 second delay due to how the Chromecast buffers.
  6. Enjoy

Ok, great. I don’t have a Chromecast

They are pretty cheap! But, I wrote a generic module that just exposes a live mp3 stream of your system audio. It’s called webcast-osx-audio, and it’s what chromecast-osx-audio relies on for it’s streaming component. You can install it just as above, and it exposes a webcast-audio command when installed globally. Connect to http://your_local_ip:3000/stream.mp3 and you’re good to go!

What’s next?

  • I still need to write the input-side output-side of osx-audio before I consider it complete. And tests!
  • chromecast-osx-audio will only stream to the first Chromecast it finds. I plan to implement an interface that allows you to select which you’d like to stream to if multiple are found. That’ll be in before v1.0.

Note that both modules command-line interfaces have usage information! Just run chromecast --help or webcast-audio --help to see what options are available!

Note: What we go through to solve problems, eh? All of this still assumes some familiarity with node.js—this is definitely not a solution for the non-technical. Maybe someday!

XKCD Password Generation for Node.js

| Comments

I created an XKCD-style password generator for Node.js (see this comic for reference). You can find it on my github or do an npm install -g xkcd-password to get it on your path.

There are others available, but most don’t include a CLI, or easily configurable options. Many use small word lists. So I made one that uses a sufficiently large list—113,809 words provided by the Moby Project—and both a simple commandline utility and a module that you can use in your Node.js apps. If you don’t like my wordlist, you can substitute your own easily. Everything is non-blocking, so you shouldn’t find it bogging down your stuff.

Send issues or pull requests!

1
2
3
4
5
6
7
8
9
Usage: xkcd-password [options]

Options:
   -n, --numWords    The number of words to generate for your password.  [4]
   -m, --minLength   Minimum lengh of words chosen for the generated password.  [5]
   -x, --maxLength   Maximum length of words chosen for the generated password.  [8]
   -f, --wordFile    The newline-delimited list of words to be used as the source.
   -s, --separator   The separator character to use between words when output to the console.  [ ]
   --version         print version and exit

Primes, a Twitter-backed Prime Number Generator

| Comments

_primes_ Twitter avatar

A few weeks ago I started primes, a Twitter-backed prime number generator. When I say “Twitter-backed”, I mean the bot that updates the account has very little idea of state: it only knows the last number it calculated because Twitter provides it. The program flow is this:

  1. Start up
  2. Fetch the most recently calculated prime from the Twitter feed.
  3. Calculate the next prime.
  4. Post if an hour has passed since the last posting. Wait if not, then post.
  5. Steps 2–4 forever.

Technically steps two and four are merged after the first posting, since Twitter returns your latest tweet as a response when you post it. You can view the code on Github. It’s written in CoffeeScript on Node.js, and uses node-fibers since I orginally built the prime number algorithm as a generator, but it’s unnecessary in this case.

The only state the application maintains is an internal “last posting” date, just as a fail-safe if the server it runs on spontaneously changed time: I didn’t want it accidentally posting too quickly.

You should give it a follow if you love primes! Or maybe fork the code and make some new Twitter bots? I’d love to see some.

An Addendum to “Fixing a Famicom Disk System”

| Comments

My old Sharp Twin Famicom threw the belt again, as they do. While replacing it, I wanted to make an update to my previous blog post about FDS belts, since my old article wasn’t as helpful as I’d have liked when I actually tried to use it.

First, there’s now a far better repair article available at the Famicom Disk System website. This goes through the whole process of belt replacement as well as aligning the spindle hub, which I had a lot of problems with this time.

I’d recommend following their article over mine; it does a far better job of explaining how to align the spindle hub. The only addition I would make is that I still had to make small 5–10° adjustments both forward and backward to the spindle hub before everything worked.

Getting WiFi on a Headless Raspberry Pi

| Comments

One of the final steps in a to-be-announced project involved getting a headless Raspberry Pi up on WiFi at boot time—which turned out to be a little more challenging that first expected. Not because it was particularly difficult, but because the documentation was poor.

Below are my full configuration files that were required. The WiFi USB dongle itself was an Adafruit USB WiFi with Antenna which is actually a B-LINK BBL-LW05-AR5; notable becuase of its sizeable antenna, and for working with the latest Raspbian Wheezy distribution.

Prior to getting started, make sure your Raspbian is up to date by issuing:

1
2
sudo apt-get update
sudo apt-get upgrade

At that point, reboot and connect your WiFi module to USB. Then, edit your config. It’s worth noting that I have an interface eth0 which is set to DHCP, and my wlan0 interface which has a static IP. This allows me to use ethernet as a failsafe if something goes wrong.

First, in the file /etc/network/interfaces:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
auto lo

iface lo inet loopback
iface eth0 inet dhcp

allow-hotplug wlan0
iface wlan0 inet manual
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf

iface YOUR_WIFI_ID inet static
address 192.168.1.5
netmask 255.255.255.0
gateway 192.168.1.1

# iface default inet dhcp

This is setting up your ethernet to dhcp, your wifi to manual, sourcing the wpa_supplicant.conf file, and then assigning your named Wireless connection to a static IP. Note that YOUR_WIFI_ID above should be an identifier you make up yourself. For example, mine is NORTH_WPA.

Now, configure the network information in /etc/wpa_supplicant/wpa_supplicant.conf:

1
2
3
4
5
6
7
8
9
10
11
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
# update_config=1
network={
  ssid="Your SSID Name"
  proto=RSN
  key_mgmt=WPA-PSK
  pairwise=CCMP TKIP
  group=CCMP TKIP
  psk="Your WPA Password"
  id_str="YOUR_WIFI_ID"
}

Again, note that YOUR_WIFI_ID is present.

At that point, reboot. Assuming you’ve got all your information correct (and that your key management and etc. match mine) you’ll be connected automatically at boot!

Much of the information in this post was gleaned from this thread. The original poster’s information didn’t work for me, but I was able to assemble a working config from various commenters’ information.

UPDATE 2014-01-06

When I switched from the older-style Airport Extreme base stations to the new “tower”-shaped base stations, I was having issues with the WiFi disconnected and then not reconnecting without a reboot. To resolve this, I followed one of the answers in this stack exchange post, reproduced below for convenience. This is originally from the user AndaluZ:

Well, there is a very simple solution:

  1. Go to /etc/ifplugd/action.d/ and rename the ifupdown file to ifupdown.original
  2. Then do: cp /etc/wpa_supplicant/ifupdown.sh ./ifupdown
  3. Finally: sudo reboot

That’s all. Test this by turning off/on your AP; you should see that your Raspberry Pi properly reconnects.

Keeping Your Countdowns in Check

| Comments

Timer is a simple, multiple countdown timer web application. The iPhone lacks multiple timers, and what I found on the app store was poor. What I found online, also poor (and way too full of ads), so I built one. It’s pretty simple, and hopefully you’ll find it useful.

I’ve actually started some additional work on it—such as long-running timers that are remembered if you leave the site—but I’ll probably come back to those some other day. Also this includes my newest pre-deployment processing scripts, which perform automatic minification and building from jinja templates. They may be of interest to someone.

Timer’s source is available on my github. I would love to see some patches or improvements! Or, just enjoy as-is.

Vim, Fish Shell, and Vim-sensible

| Comments

Part of this evening was spent making vim workable for me, the first step was getting some sane defaults. vim-sensible was recommended in several places (as was Tim Pope’s also excellent pathogen), but immediately after installation I was getting an error:

1
2
3
4
Error detected while processing ~/.vim/bundle/vim-sensible/plugin/sensible.vim:
line   75:
E484: Can't open file /tmp/v1NmKg8/0
Press ENTER or type command to continue

Frustratingly, line 75 held no obvious suggestions. After some time troubleshooting, I found it worked fine if I wasn’t using fish shell.

I’m not positive why this is the case, but you can fix the error by adding the following line to your .vimrc.

1
set shell=/bin/sh

On next launch of vim, all is resolved.

The New Yorker and the Importance of Optimization

| Comments

Update 2013-03-07: Please see the correction at the bottom of this article.

I have a small obsession web platforms, and discovering what platform a site is using. There are some great tools that help, but nothing beats viewing the source. Recently I encountered the New Yorker

It’s a sight. I encourage you to check the source for yourself, but it’s a templating system gone wrong. The day I discovered it, I tweeted

in the midst of 90 new-lines, sits @NewYorker’s <html> tag. a scant 1006 lines later, the <body>.

—to no reply. It’s for real though: their homepage serves, of this writing, 16101 newlines. Many of their tags are surrounded by no less than 30 newlines each. Their <head> contains 998 alone. So this gets me thinking:

A newline character, usually represented as \n in many languages, but represented by the unicode U+000A tends to be represented as an 8-bit ASCII character, or one byte. For the purposes of this excercise we’ll assume exactly that.

In terms of websites:

Now lets talk bandwidth: 16101 bytes is 0.0153 MB—less than two-hundredths of a megabyte—it’s not much. Now traffic-wise: According to Compete, they see 1,103,088 unique visitors per month.

Or, if you prefer: 16.54 GB of newlines per month, strictly in unique visits to the homepage. Hey, Condé Nast: might be time to optimize?

Correction: Reddit has bested me on this one. As the commenters point out, my math is done assuming that the web server isn’t configured to compress with gzip—and it is. Since all major browsers support gzip, the actual impact of The New Yorker’s excessive newlines is minimal.

So, this is more or less an article about the comical result of a templating system than it is about performance. Thanks to those on Reddit that pointed out this error.

Using Caps-Lock as a Compose Key in XFCE4

| Comments

Why not take that useless key, and make it useful? The Compose Key—formerly present on many Unix keyboards of old—isn’t present on most modern laptops.

In XFCE, this is a little more cumbersome than Gnome, since there isn’t a graphical interface for setxkbmap, but these two commands will swap the Caps lock for a compose key:

1
2
setxkbmap -option ctrl:nocaps  # disables caps lock
setxkbmap -option compose:caps  # sets caps key to compose

To make this active at login, you can add two entries to your “Session and Startup” -> “Application Autostart” available under the Settings Manager. I’ve named mine “compose1” and “compose2”, each containing one of the above commands. Now enjoy all those en-dashes you’ll surely be typing.

Making Noise in Python

| Comments

I’ve been working with PyAudio lately, on a project to synchronize sound streams across multiple devices. Nothing to say on that front yet, but I do have a nice snippet for programatically generating a tone:

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
import math
import numpy
import pyaudio


def sine(frequency, length, rate):
    length = int(length * rate)
    factor = float(frequency) * (math.pi * 2) / rate
    return numpy.sin(numpy.arange(length) * factor)


def play_tone(stream, frequency=440, length=1, rate=44100):
    chunks = []
    chunks.append(sine(frequency, length, rate))

    chunk = numpy.concatenate(chunks) * 0.25

    stream.write(chunk.astype(numpy.float32).tostring())


if __name__ == '__main__':
    p = pyaudio.PyAudio()
    stream = p.open(format=pyaudio.paFloat32,
                    channels=1, rate=44100, output=1)

    play_tone(stream)

    stream.close()
    p.terminate()

This simply generates a sine wave of a specified frequency and length, and writes it out to an already open PyAudio stream. A pleasant tone is produced. It’s not too fancy, but it beats loading a wave file from disk.