Is this your first visit? You may want to subscribe to the feed.

Bending iTunes to my will with RubyOSA: take 1

A couple months ago I expressed my frustration about iTunes not letting me move podcast files into my library. Several people commented with suggestions, such as converting the ID3 tag to an older version, re-importing the track, and then converting the ID3 tag back to 2.4. This is definitely better than the solution I had found, but still a pain.

I tried to find a scriptable solution, but iTunes doesn’t expose, though AppleScript, the ability to change the ID3 tag version or the mystical ID3 tag attribute that tells iTunes that it’s a podcast.

So, I’ve turned to Ruby. Though a little introspection and experimentation with ID3lib-ruby, I’ve figured out that it is the CTO (Content Type) ID3v2 tag set to “Podcast” that iTunes is using to put the files in the Podcasts folder. Clearing the CTO tag and readding the track in iTunes will move it into the Library.

So, with RubyOSA, I’ve written a little script that will loop through the selected tracks in iTunes and clear the CTO ID3 tag.

require 'rubygems'
require 'rbosa'
require 'ID3lib'

itunes = OSA.app('itunes')
itunes.selection.get.each do |track|
  if track.is_a?(OSA::Itunes::Track)
    location = URI.decode(URI.parse(track.location.__data__('furl')).path)
    tag = ID3Lib::Tag.new(location)
    tag.content_type = nil
    tag.update!
  end
end

There are a few remaining problems that I would like to tackle:

  1. I can’t figure out how to delete and add the track through RubyOSA. There is a delete method on the track, but doesn’t appear to do anything.
  2. I want the script to display a dialog confirming the actions about to take place.
  3. I want to be able to execute the script from the Scripts menu in iTunes, which appears to involve installing OSA Components.

Overall, this has been a fun experiment (and a reason to play with RubyOSA). I’m looking forward to Leopard when this is all built in!

Code: applescript, id3, itunes, mac, osa, podcast, ruby Jun 30, 2007 ● updated Jun 30, 2007 3 comments

3 comments

  1. I think the reason you can’t delete the track is because you do a get

    itunes.selection.get.each do |track|

    This converts the specifier list object (i.e. reference to the tune in iTunes) to an actual MP3, which I think is no longer connected to iTunes.

    If you did

    itunes.selection.each do |track|

    then I think you would be able to do itunes.delete(track) BUT I think you might then have problem with the ID3 tags :-)

    There is some info on this sort of thing here

    http://rubyosa.rubyforge.org/guide/object-specifiers.html

    Conrad Conrad July 01, 2007 at 02:28 AM
  2. “1. I can’t figure out how to delete and add the track through RubyOSA. There is a delete method on the track, but doesn’t appear to do anything.”

    I don’t know about RubyOSA, but to add a file to iTunes using rb-appscript (example code):

    require 'appscript'
    include Appscript
    
    Itunes = app('iTunes')
    
    Itunes.add(MacTypes::Alias.path('/Users/foo/lizard scum.mp3'))
    

    That’ll add it to your main library only. If you want to add it to a user playlist as well, specify that playlist via the optional ‘to’ parameter:

    Itunes.add(MacTypes::Alias.path('/Users/foo/lizard scum.mp3'), :to=>app.playlists['MyList'])
    

    To delete a track from a user playlist (example code):

    track_ref = Itunes.playlists['MyList'].tracks['Goodbye you lizard scum']
    track_ref.delete
    

    If you want to delete the track completely from your library, you’ll need to reference it there:

     
    Itunes.library_playlists[1].tracks['Goodbye you lizard scum'].delete
    

    BTW, if you want to delete a track completely but all you’ve got is a reference to it in a user playlist, get its database ID and then use a ‘whose’ clause to locate that track in the main library:

    user_playlist_track_ref = Itunes.playlists['MyList'].tracks['Goodbye you lizard scum']
    
    db_id = user_playlist_track_ref.database_ID.get
    library_track_ref = Itunes.library_playlists[1].tracks[its.database_ID.eq(db_id)].first.get

    You can then call #delete on that reference to delete the track completely.

    “2. I want the script to display a dialog confirming the actions about to take place.”

    In appscript:

    #!/usr/local/bin/ruby
    
    require 'osax'
    
    standard_additions = OSAX.osax
    
    standard_additions.display_dialog('Hello world!')
    

    If you want the dialog to appear in a specific application, e.g. iTunes:

    standard_additions = OSAX.osax.by_name('iTunes')
    
    standard_additions.activate
    standard_additions.display_dialog('Hello world!')
    

    “3. I want to be able to execute the script from the Scripts menu in iTunes, which appears to involve installing OSA Components.”

    I don’t think that’ll work – in order to send Apple events to the host application, you need an OSA component that provides integrated support for this, which the RubyOSA component (no relation to the RubyOSA Apple event bridge) doesn’t. The only third-party components that currently do this are JavaScriptOSA (although it has a number of other flaws that limit its usefulness) and PyOSA (which is still under development and not quite ready for general use).

    The simplest solution would be to put your script into the system-wide Script Menu (which accepts shell scripts as well as AppleScripts, so no need for an OSA component). Use /Applications/AppleScript/AppleScript Utility.app to enable it if you’ve not already done so, then put your .rb script in ~/Library/Scripts.

    Alternatively, write an AppleScript that uses ‘do shell script’ to start your .rb script and then detach the ruby process so that the ‘do shell script’ command returns immediately.

    HTH

    has

    http://appscript.sourceforge.net http://rb-appscript.rubyforge.org

    has has July 03, 2007 at 06:01 PM
  3. Hi,

    Just to let you know that you can also use CocoaDialog for displaying confirmations, this is what I use in tagloko1.

    [1] tagloko.rubyforge.org

    Bye, thanks for the info,

    Federico
    Federico Zagarzazú Federico Zagarzazú September 16, 2007 at 07:36 PM

Speak your mind:

*

*


* I hate spam and will never sell or publish your email address.

(You may use textile in your comments.)

Subscribe

Browse by Tag