Posted by Larry Karnowski
Fri, 28 Mar 2008 00:26:00 GMT
Took me a bit to figure this out (big thanks to Sam U!), but it's actually pretty easy.
Install id3lib using MacPorts like so:
$ sudo port install id3lib
Then the harder part, install the id3lib-ruby gem as so:
$ sudo env ARCHFLAGS="-arch i386" gem install id3lib-ruby -- --build-flags --with-opt-dir=/opt/local
Note that you change the ARCHFLAGS to "-arch ppc" if you're using an older PowerPC Macintosh. Using the "/opt/local" build flag tells RubyGems to look in the MacPorts include directory for necessary headers (like id3.h).
2 comments
Posted by Larry Karnowski
Fri, 14 Mar 2008 20:00:00 GMT
What began as my "learn to write Ruby" project almost a year ago is finally taking shape thanks to Open Source Fridays at my new place of gainful employment -- Relevance!
iCalendar is the open standard for those ubiquitous *.ics files. These are the files we read and write with Apple's iCal, Google Calendars, and other standards-based calendaring programs. (Read that as "all calendars except Outlook.")
Ruby has a partial implementation of the specification at the Rubyforge iCalendar project. However, it's missing one important feature -- recurring dates.
For example, that 1pm Monday meeting that you have every week? The Ruby iCalendar project doesn't support it. Now, don't give the iCalendar folks a hard time -- recurring rules are damn hard to implement, and they've spent their time doing the most important stuff -- reading and writing the *.ics files. Also, since most webapps nowadays just export important dates as one-off dates anyway -- the Ruby implementation of iCalendar just hasn't really needed a recurring date implementation. (But we really want one!)
I started by brute forcing my way through the massive list of examples in the RFC 2445. I foolishly thought it was just a matter of hacking out an example using TDD and then refactoring all previous examples. No... I've found out it's just not that simple. (And let's face it, if that's all it took then the Ruby iCalendar folks would've added it ages ago! Poor, naive Larry.)
Then at one of the Raleigh.rb hack nights, Nathaniel Talbott recommended that I look at a little-known Ruby toolkit called Runt. This toolkit implements something called temporal expressions. You remember that weekly 1pm Monday meeting you have? Come to find out that with Runt they look like this:
DIWeek.new(Mon) & REDay.new(13, 00,14, 00)
You read this as: "day in week: Monday, and range each day: from 1pm to 2pm". You can use this temporal expression either to generate a list of matching DateTimes or to check if a given DateTime matches. Very powerful stuff, incredibly powerful. (By the way, this all comes from an idea by Martin Fowler and implemented by Matthew Lipper.)
So, now my problem looks like this:
- Take the iCalendar recurring rule (called a RRULE) syntax and convert it into an appropriate Runt temporal expression.
- Let Runt do all the work.
I'm home free! Or... well, I'm not. Come to find out, Runt only implemented about 60% of what I needed to implement the full iCalendar spec. The biggest missing piece was the ability to handle dates at a "week precision". That is, I need to be able to know if a given day and another given day are in the same week. I finally got that feature in today!
So now with the weekly precision and a few other temporal expressions I added, I now have all but 14 of the 41 examples working as Test::Unit tests in Runt! That 65% may sound a little low, but it is actually something like 80% of the total iCalendar functionality. It's definitely all the key features. It definitely supports recurring rules based on a given day and month (mark November 15th on your calendar! it's my birthday!), and it definitely supports week-based recurring rules like the 1pm Monday meeting above. What else do you need?
Here's the patch for Runt's current Subversion trunk. I'm now working on my old iCalendar code. I'm going to do the same trick of using the RFC examples as Test::Unit tests.
I'm hoping to have more next week!
Tags calendar, ical, icalendar, patch, ruby, runt, temporal_expressions | 2 comments
Posted by Larry Karnowski
Fri, 07 Mar 2008 14:55:00 GMT
So you want to play MP3s from your web application? The best tool I've found for that is Scott Schill's SoundManager2 Javascript API. It invisibly uses a very small Flash object to play the MP3s, and the whole thing is very scriptable through Javascript. Getting it set up is not difficult, but it's a little bit of a pain -- so I wrote a Rails plugin!
Here's what you do:
Install the Rails plugin like this:
./script/plugin install http://soundmanager2.rubyforge.org/svn/soundmanager2
Then run the generator to get the SoundManager2 files in your app:
./script/generate sound_manager2
You'll notice the following files are created:
public/soundmanager2.swf
public/javascripts/soundmanager2.js
public/javascripts/soundmanager2-jsmin.js
public/javascripts/soundmanager2-rails.js
public/images/SoundManager2/pause-control.gif
public/images/SoundManager2/play-control.gif
Then, to add basic play/stop functionality to your view, add the following to your ERB file:
<%= javascript_include_tag :defaults %>
<%=
sounds = [
["sound1", "http://url/to/sound1.mp3"],
["sound2", url_for(:controller => "sounds", :action => "listen", :id => "2")],
]
%>
<%= initialize_sounds(sounds) %>
<div>Play sound 1: <%= toggle_sound "sound1" %></div>
<div>Play sound 2: <%= toggle_sound "sound2" %></div>
- Or, if you want more functionality, start calling the SoundManager2 Javascript APIs directly.
Here are some screenshots of this plugin in action. Here you're looking at part of a table with MP3s ready to play...

And then here you've clicked on the middle song. Note the MP3 will start playing immediately, even while it's downloading!

Clicking the "pause" button will stop the playback.
Here are the project links:
Oh, and by the way, both the Javascript API and Rails plugins are released with BSD/MIT licenses!
I'm definitely wanting to put more "off-the-shelf" behavior in this plugin, but for now the simple play/stop behavior is all my application needs. If you need something else, or want to send me some patches, please shoot me an email!
Tags mp3, plugin, rails, ruby, rubyforge, soundmanager2 | 1 comment
Posted by Larry Karnowski
Mon, 03 Mar 2008 16:45:00 GMT
My name is Larry Karnowski, and I've been blogging about twangy and traditional music over at Hickory Wind for over five years now. Hickory Wind has been a great outlet for my musical passion, and I've met some of my best friends through that site. (You can also indirectly trace my meeting of my fiancé-soon-wife through that site too, so it's been a great experience!) However, Hickory Wind has a music audience, not a technical one. I've never been able to wax geek over there, talking about how tired I was of Java, how cool Ruby and Rails are, etc.
Now I'm making a change in my career. Instead of being at a product-based company like I have for the past eight years, I'm starting at a contract-based custom software company called Relevance next Monday. I'm crazy excited about it, and I can't wait to immerse myself into their geeky, open-source-heavy culture!
As part of this change in my career, job, and geeky culture, I've decided it's definitely time to launch this geeky blog to service my other passion -- technology. Here I'll talk about software development, user interface design, and other geeky tangents like Tolkien books, World of Warcraft, and an occasional D&D analogy.
Hickory Wind will be my manic music side, and Hickory Tech will be my manic geek side. (Here's a tip -- I'm all Hulk and no Bruce Banner, baby.)
So, if you're interested in talking Typo versus Mephisto, MovableType versus WordPress, Rails versus Spring, anything versus Java, Rogues vs Bards, and phat l00tz versus role-playing, well then you're probably at the right place.
Welcome!
Tags blog, geek, technology | 8 comments