tech

Quod Libet plugins on Ubuntu

I've moved back to Quod Libet from Rhythmbox this week (the only thing I miss is Rhythmbox's "Recently Added" category). One gotcha which took me a while to work out: to use Quod Libet plugins, they have to go into ~/.quodlibet/plugins. Copy them from /usr/share/quodlibet/plugins (which is where they are installed by default, on Ubuntu at least) to that directory and you should be fine.

I also installed some binaries of the new version, even though I am on Ubuntu Breezy: see http://www.ubuntuforums.org/showthread.php?t=131304&page=3 for Ubuntu packages.

Linux Desktop Architecture Meeting (I didn't attend, by the way)

I was really heartened by this article which outlines the recent Desktop Architecture Meeting 3 in Portland, where a bunch of Linux desktop folk got together to discuss how to move Linux on the desktop forward. This is an issue which is dear to my heart, as I use Linux exclusively, both at work and home. Particularly important to me is what was called "sound suckage", something which desperately needs fixing. I have a few issues with sound myself on my Ubuntu (still Breezy, need to upgrade to Edgy soon):

  • Some sound program on my computer initialises esd (the e-sound daemon). Once this is running, it means I can't listen to sound from any Flash movies inside my browser. I use the command line to kill esd, restart Firefox, and everything is alright with the world. Don't imagine my dad could do this, though.
  • For some reason, when I rip to ogg with Grip, the mime type in the properties dialogue for the resulting file in Nautilus reports "audio/mpeg" (even though the file name suffix is .ogg and I thought I was ripping an ogg). If I change the suffix to .mp3, Nautilus goes crazy and plays a stuttering first few seconds of the track. I've switched to ripping to mp3, as oggs were driving me mad. Not sure if the problem is with Nautilus or Grip, here.
  • It's still a pain to get all the decoders working to play mp3s, wmas and all those other hateful formats. Is there any way to make this easier without sacrificing the pure, free OS for the people who want it? I'd be prepared to pay some cash to Ubuntu every year if they could make this simple for me.
  • Just this week, Rhythmbox decided to seg fault every time I tried to play a track. I reinstalled Rhythmbox, cleaned out my settings, fsck'd the external hard drive with my audio on it (in case that was causing the problem), but still the problem. Does Rhythmbox have problems when you have over 5500 tracks? I actually had to switch back to Quod Libet so I can listen to music at all.

Aside from this (which, as you can see, is very important to me), it's also interesting to read about plans to make hardware for support more comprehensive. It still pains me that my laptop internal wireless is not working (though that may be fixed in Edgy - we'll see). Until hardware manufacturers buy in, and you can buy a computer with Linux in PC World, Linux on the desktop will stay grounded. (Though I noticed a PC in Woolworths had StarOffice on it the other day, which I suppose is a start of sorts.)

I'd also like to reiterate a point made elsewhere: why is it I can get 3D spinning windows on my screen, but my wireless doesn't work, external projectors work sometimes and not others, and I have to manually stop sound daemons to use Flash? Although those issues are dull, they are the real barriers to the uptake of Linux on the desktop; not the fact it doesn't look like the Mac UI.

Ruby Tuesday: RSS feeds in Rails

Yesterday, I mentioned I have added RSS feed capabilities to FlickrLilli. I thought it might be worth sharing my experiences of this, as it took me a good couple of hours to iron out the wrinkles and get a valid feed.

Update: Thanks to Thomas Hurst (see comments) for pointing out that I can just use the output from the existing partial and escape it again.

Existing components

I had a lot of code for fetching photos from Flickr and displaying them as HTML: I wanted to reuse these as much as possible. The examples below simplify, as FlickrLilli is a special case and doesn't have a database back-end; for the example, I have assumed a photo database which stores Flickr-like photo objects.

The model

FlickrLilli doesn't use ActiveRecord, but has objects corresponding to photos from Flickr. For the purposes of this example, let's assume a photo actually corresponds to a table in the database called photos, and has a model that looks like this:

class Photo < ActiveRecord::Base
  has_and_belongs_to_many :tags
  belongs_to :owner
  
  # Show tag names in a human-readable string.
  # (Thanks to Tim [see comments] for reminding me of this syntax.)
  def tag_str
    tags.map(&:name).join(", ")
  end
end

And that the model supplies these attributes (which mirrors Flickr metadata on a photo):

  • title
  • description
  • date_taken
  • image_url (the URL to the actual photo graphic file)
  • tags (returns an array of Tag model objects)
  • licence
  • owner (an instance of an Owner model object, with a username and homepage URL)

The standard partial for rendering a photo

FlickrLilli uses a single partial to render a photo as HTML in different contexts (app/views/main/_metadata.rhtml). Paraphrasing a bit, this looks like:

<h2><%=h photo.title %></h2>
<p><%= image_tag(photo.image_url) %></p>
<p><strong>Tags:</strong> <%=h photo.tag_str %></p>
<div class="photo_details">
<p><strong>Licence:</strong> <%= photo.licence %></p>
<p><strong>Date and time taken:</strong> <%= photo.date_taken %></p>
<p><strong>Owner:</strong> <%= link_to photo.owner.username, photo.owner.homepage %></p>
<p><strong>Description:</strong><br/>
<%=h photo.description %>
</p>

The RSS feed generator

Given these two existing components (a model and an HTML partial for a photo), I set about writing my feed generator. It needed:

  1. A controller action to manage the feed
  2. An RXML template for rendering it (RXML uses Builder to generate XML output for controller actions)
  3. A route which makes it convenient to download the raw feed XML as an XML file with a .xml suffix

The controller action for the RSS feed

This was pretty quick to write. Again, using a simplified version for the purposes of exposition, I added the action to my MainController class (in app/controllers/main_controller.rb):

def rss
  # Get the 10 most recent photos
  @photos = Photo.find :all, :limit => 10, :order => 'date_taken DESC'
  # Title for the RSS feed
  @feed_title = "10 most recent photos"
  # Get the absolute URL which produces the feed
  @feed_url = "http://" + request.host_with_port + request.request_uri
  # Description of the feed as a whole
  @feed_description = "10 most recent photos"
  # Set the content type to the standard one for RSS
  response.headers['Content-Type'] = 'application/rss+xml'
  # Render the feed using an RXML template
  render :action => 'rss', :layout => false
end

There are a couple of key things to note here:

  1. The Content-Type header should be set properly for the response.
  2. The RXML template needs to be rendered without a layout, otherwise you get XML wrapped in the controller's layout.

The feed XML template

This uses the RXML template provided by Rails to generate the XML document. There is an example in the Rails documentation, but as far as I can see it doesn't produce a properly-valid feed, as it lacks an <?xml version="1.0"?> declaration. Here's my template, which went into app/views/main/rss.rxml:

xml.instruct!
xml.rss("version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/") do
  xml.channel do
    xml.title @feed_title
    xml.link @feed_url
    xml.description @feed_description
    xml.language "en-gb"

    for photo in @photos
      xml.item do
        xml.pubDate photo.date_taken.rfc822
        xml.title h(photo.title)
        xml.link photo.image_url
        xml.guid photo.image_url
        xml.description do
          xml << h(render(:partial => 'metadata', :locals => {:photo => photo}))
        end
      end
    end
  end
end

Things of note:

  • A guid element is added for each item. This enables blog readers to uniquely identify items, meaning it can detect which items in a feed are new and which have already been seen. In this case, I'm just using the image URL; in the case of FlickrLilli, I use the URL of the photo detail page on FlickrLilli, which ensures the feed only shows items which are new, not updates to existing items.
  • The Time class in Ruby provides a handy instance method called rfc822, which returns a string suitable for use inside the <pubDate> element of an RSS feed.
  • The xml << h(...) syntax directly appends some content to the XML output, attaching it to the currently active element (in this case, the <description>).
  • The partial is rendered using the standard render method, passing the photo in as a local. The whole lot is then filtered through the h method to escape all the HTML. This will result in some parts of the HTML being "double escaped"; however, when decoded by the reader at the other end, it should be proper single-escaped HTML again.

A nice route

Applications like Firefox look at the filename suffix of a downloaded file to determine how to handle it. If we make the RSS feed available at a URL like http://localhost/rss, the downloaded file will be called rss, and some applications won't be able to work out what to do with it.

So it gets properly treated as an XML file, I add a custom route to config/routes.rb:

map.connect '/rss.xml', :controller => 'main', :action => 'rss'

And that's it!

Bonus sample code

Because I'm feeling generous, and because I wanted to check all the above actually worked, I put together a really simple Rails application which fleshes this out and includes a sample SQLite database and migrations. It's attached below. To run it, just use script/server, then browse to http://localhost:3000/rss.xml. When I tested it, it produced a valid RSS feed.

RSS feeds of Flickr Creative Commons material now in FlickrLilli

I tend to use FlickrLilli to do the same search over and over (I use open as this provides good material for presentations on open source, naturally). I decided to hack a quick RSS feed facility into FlickrLilli to support this mode of working. It's just a link added to the search results page, but it means you can get a feed of the Creative Commons images in Flickr matching your query. This is updated in real time (it should be cached really, but like I say, it's a quick hack at the moment). Give it a spin and let me know how it performs. It would probably be best if you didn't batter it every 5 seconds, as it does a live search for every query at the moment. By the way, I am quite surprised that Flickr doesn't provide this facility on general searches, though it does seem to provide feeds for groups and pools (I think).

New version of FlickrLilli

FlickrLilli is a project I've been working on/off with for about a year now. The idea is that it provides a search interface across Flickr's Creative Commons content; I use it myself to source royalty-free images for presentations. It was a really early Rails project of mine, so the code was a bit ropey in places; and I've had many problems hosting it, as it used to be a bit "bursty" and create dozens of HTTP requests very close together (AJAX, don't you know), which made all the hosting I've tried break. I spent a lot of time rewriting the XML parsing to make it more efficient, but still problems.

A couple of months ago I embarked on a major rewrite. This time I decided to remove a lot of the AJAX request load by rejigging the interface, so details for pictures are loaded on request; I also rewrote all the AJAX stuff so it degrades gracefully and works on more browsers (including IE, which was a problem before), using Unobtrusive Javascript. This was the biggest challenge. And I redid much of the CSS so it resizes better (still problematic on really small screens, but I'm no CSS expert); it should also work with all the CSS off in ancient browsers. I've retained the login feature, which enables you to login to your Flickr account and make comments/add favourites from inside FlickrLilli. There are still issues with the Javascript on browsers other than Firefox, but at least it all works with Javascript turned off if necessary.

I've now completed all this, and you can see the results at http://flickrlilli.org.uk/. Enjoy! Let me know if it breaks! (It's only on cheap shared hosting and I had to revert it to REXML, so more than likely it will fall over within a few minutes of me posting this.)

Early day motion on software in schools

I would encourage you to write to your local MP (e.g. via TheyWorkForYou.com) and encourage them to sign this Early Day Motion:

http://edmi.parliament.uk/EDMi/EDMDetails.aspx?EDMID=31752

Here's the full text of the motion:

That this House congratulates the Open University and other schools, colleges and universities for utilising free and open source software to deliver cost-effective educational benefit not just for their own institutions but also the wider community; and expresses concern that Becta and the Department for Education and Skills, through the use of outdated purchasing frameworks, are effectively denying schools the option of benefiting from both free and open source software and the value and experience small and medium ICT companies could bring to the schools market.

Fashion and intellectual property

An interesting paper about the "piracy paradox" of the fashion industry: despite a lack of protection for fashion designs and rampant copying in cheap knock-offs (though with IP still invested in brands), the fashion industry innovates at a rapid click and attracts enormous investment. I haven't the time or skill to read all 94 pages, but the introduction, conclusion and some of body of the text are interesting (open source gets a footnote). From my skim, it looks like the authors largely attribute the paradox to the positional ("this year's look") and ephemeral nature of fashion. They go so far as to say that copying is actually beneficial to the industry and accelerates innovation. I think there's a case for saying IT is "positional", in the sense that there are trends and people gain recognition for being "on the bleeding edge" in adopting new technologies; so some of the arguments are adaptable. There are good arguments made here against the assumption that IP protectionism leads to innovation.

Via http://arjen-lentz.livejournal.com/84301.html

Ruby and S3: Molina trumps Smith

Update: Mr. Molina's S3 library is available at http://amazon.rubyforge.org/. I've downloaded it. I had a sinking feeling (all my hard work...),combined with a feeling of relief (no more hard work!), as I looked through it. It looks very good. Clearly the work of a super Ruby programmer (my library is very verbose by comparison, though in its defence is a bit easier to follow). The usage patterns are nice and clean. Plus it has an interactive shell, which is nice. I think I would probably use it in preference to my library. So I have the feeling I won't be doing much more work on s33r for now... (but see the comments for a very nice vote of confidence).



Not sure how I missed this, but it looks like Marcel Molina has been working on an Amazon S3 library for Ruby. Looks like my own Ruby S3 project could be consigned to the dump bin before too long (I'm just not famous enough). Mr. Molina's library is going to be released on Friday, as part of Peter Cooper's Ruby Advent Calendar; Peter has a preview of the API on his blog.

By the way, here's code for doing the same thing as Peter's example, but using my s33r library:

#!/usr/bin/env ruby
require 'rubygems'
require 's33r'

local_file = ARGV[0]
base_name = File.basename(local_file)
bucket = ARGV[1]

puts "Uploading #{local_file} as '#{base_name}' to '#{bucket}'"

S33r::NamedBucket.new('accesskeyhere', 'secretaccesskeyhere', 
:default_bucket => bucket) do |client|
  client.put_file(local_file, base_name)
end

puts "Uploaded!"

None of that messing about with mimetypes or reading in files: put_file does that for you :). Plus there's a sample (and simple) Rails app. called fors33r bundled with it, which displays all your buckets and enables you to upload files into them. s33r can be installed as a gem, by the way...

Web 2 point 0 report

Not much content in there, but here's a short report on the recent Web 2 point 0 seminar I presented.

Relative search popularity of open source CMSs

I noticed someone else using Google Trends to demonstrate the falling volume of "Linux" as a search term, which they take to mean that interest in Linux is falling and Linux itself is being marginalised. An interesting debate, but one which is difficult to come up with good evidence for. Based purely on the interest in OpenAdvantage Linux training, I'd say people still have a healthy interest, but that's hardly good statistics.

Anyway, that's beside the point. I thought it would be interesting to look at the relative popularity of 4 of the big open source CMSs, with respect to how often they turn up in Google searches, using the aforementioned Google Trends.

What I found interesting here was that, according to Google, searches for Mambo have dropped off a fair bit, while Joomla! is on the ascendant; also, Drupal has overtaken Plone in terms of search volumes. Also looks like Drupal is very popular in Hungary and Canada. Probably nothing in it, but I think it could be an indicator that the Mambo Foundation probably wasn't a great idea, in terms of making a product ubiquitous. Also interesting that Joomla! is now winning awards, which Mambo was doing last year; and Mambo seems to have faded from the limelight somewhat.

Syndicate content