Aug 25 2008

Filter stderr

I’ve been exploring D the language. I really do like it, but that’s another post. There are a couple of D compilers, but the only viable option on OS X seems to be gdc. I installed it via MacPorts. On Leopard, gdc generates assembly that makes the FSF gcc complain “indirect jmp without `*'” over and over. The bug is known, and other than being annoying it seems harmless.

So I decided what I needed was a script that would filter out these frivolous warnings without otherwise affecting stderr, and also without changing the exit status (so make can do the right thing). This turned out to be easier said than done. Finally I stumbled on the right incantation:

#! /bin/bash
gdc=/opt/local/bin/gdc
msg="indirect jmp without"
$gdc "$@" 2> >(grep -v "$msg" 1>&2)

We redirect stderr to the named pipe corresponding to that subshell (see “Process Substitution” in the bash manpage), then we redirect grep’s output to its stderr. Because grep is in a subshell, its exit status doesn’t mess up the exit status of the script, which is the exit status of gdc, as it should be.


Jun 24 2008

Pipe Dream

So I’ve been reading up on what makes organ pipes tick (ok, so they don’t tick). It’s very fascinating and yet very simple. It has surprised even me that it has made me think about making my own.

Now, I’m not crazy enough to build a large organ, at least not without gobs of time and money and the proper tools. I’m still nurturing the dream of building just a MIDI pedalboard, remember.

Still, there is a project that I can see myself taking on someday. I could build a positive organ. (”Positive” rhymes with “beef.”) It’s a little one-manual organ that has just a couple of stops. It’s portable like a dresser with wheels is.

But not just any positive organ. A crazy simple positive organ. I’m thinking PVC pipe, because working with metal and wood intimidates me (and I don’t have the tools). That may change before I actually build it. Who needs a case? If I’m going to build a pipe organ it’s going to be naked so that people can see how an organ works. So build it onto/into a simple push cart or something. As for wind, what good is a portable organ if you have a loud motor that needs electricity? If I had cash for a nice quiet blower that would be one thing, but since I don’t maybe I’ll go with a simple bellows like they did in the olde days. Keyboard? Tracker’s the only way to go on something like this, which means I’ll have to break my anti-woodworking pact. But on a positive organ where the pipes are right there, the action should be simple.

This is very early stages of the dream, but I’m imagining 8′, 4′, 2′, and 2 2/3′. 8′ and 4′ for sure. Probably 49 notes (4 octaves) on the manual. So that’s 100–200 pipes. I hope my attention span is that large. Of course I can always start with one stop and go from there.

You may wonder how I’m going to fit an 8′ stop in an organ I pretend will be portable. You can take a 4′ pipe and cover the end and it will resonate like an 8′ pipe (and though it’s not made of wood will hopefully sound not entirely unlike a Gedackt).

If none of that made any sense, just click on this link and say “that’d be cool!”


Aug 2 2007

Pipelining Processes in Ruby

I’ve occasionally needed to pipeline some processes in Ruby, especially when doing sysadmin-type tasks. You can always do:

system "foo | bar"

but that gets interpreted by the shell. That can be a problem when you need to
include filenames that could have all kinds of nastiness including spaces,
semicolons, exclamation points, etc. You should be shaking in your boots about
now.

Well, for single processes, it’s easy:

system "foo", arg1, arg2

But if you want to pipe them together it’s a bit more difficult. I came up with
this solution, and it seems to be working well in my “convert my cool music
collection into a lame (wink) format my car stereo can understand” script:

  def pipeline(*args)
    pids, r = args.inject([[],nil]) do |memo, cmd|
      pids, rr = memo
      r,w = IO.pipe
      if (pid = fork)
        pids.push pid
        rr.close if rr
        w.close
        [pids, r]
      else
        r.close
        $stdin.reopen rr if rr
        $stdout.reopen w
        cmd = [cmd] if String === cmd
        exec *cmd
      end
    end
    r.close
    pids.each {|p| Process.waitpid(p)}
  end

  pipeline ['oggdec','-o','-',oldpath],['lame','-',newpath]

Do take the time to figure out what’s going on, but don’t do it without a piece
of paper handy or you might sprain something.

Update

I had an error in the original post—if you don’t close rr in the parent of the fork you will end up with too many open files eventually.