Ok, I’ve been a bit compulsive about having artwork for my movies and music in iTunes since we got our AppleTV. Ok, maybe more than a bit.
Even so, this little Rails application should give you some idea of how simple it is. It uses Amazon’s web service (which, it turns out, I misjudged), to look up candidate artwork for each album and displays them to you. You simply click on the desired image (higher resolution is typically better) and it will insert that artwork into iTunes for each track in your album.
I won’t pretend that this is the cleanest implementation but it gets the job done. If any of you watching at home want to play along, you will also need ruby/amazon installed.
FYI: Amazon’s search engine may not resolve all of your album names. You may want to manually search Amazon, in the case of stubborn albums, to determine what Amazon calls the album. However, more often than not, this shouldn’t be a problem if you ripped using iTunes.
Finally, this program could be easily adapted for hunting down artwork for your movie collection as well.
Code follows:
AlbumController.rb:
require 'win32ole'
require 'amazon/search'
class AlbumController < ApplicationController
def fetch_file_with_url(url, meta)
response = Net::HTTP.get_response(URI.parse(url))
title = meta.product_name
title.gsub! ':', '-'
title.gsub! '/', '-'
art_filename = ""
art_filename << session[:ART_PATH] << title
art_filename.gsub! ‘ ‘, ”
art_filename.gsub! ‘”‘, ”
art_filename.gsub! ‘\\”, ”
art_filename.gsub! ‘(’, ”
art_filename.gsub! ‘)’, ”
if art_filename.length > 60
# iTunes COM API seems to have issues with long file names
art_filename = art_filename[0,59]
puts art_filename
end
art_filename << “.jpg”
File.open( art_filename, ‘wb’) do |f|
f << response.body
f.flush
end
size = File.size(art_filename)
art_filename
end
def reset
session[:track_counter] = nil
session[:skip_hash] = {}
redirect_to ‘/album/iterate_through_coverless_albums’
end
def next
session[:skip_hash][session[:current_album]] = 1
session[:track_counter] += 1
redirect_to ‘/album/iterate_through_coverless_albums’
end
def process_input
album_candidates = lookup_album session[:current_album], session[:current_artist]
update_artwork_with params[:image_url], album_candidates[params[:idx].to_i]
self.next
end
def update_artwork_with(artwork_url, meta)
art_filename = fetch_file_with_url artwork_url, meta
return if art_filename.nil?
# Change path from Ruby to Winblows
art_filename.gsub! /\\//, ‘\\\\’
app = WIN32OLE.new ‘iTunes.Application’
music = app.LibrarySource.Playlists.ItemByName ‘Music’
tracks_in_album = music.Search session[:current_album], 0
i = 1
puts “==> #{art_filename}, #{tracks_in_album.Count}”
while i <= tracks_in_album.Count do
track = tracks_in_album.Item i
puts “#{track.Album} <=> #{session[:current_album]}”
if track.Album != session[:current_album]
i += 1
next
end
puts “*#{track.Name}”
track.AddArtworkFromFile art_filename
i += 1
end
end
def lookup_album(title, artist)
#puts title
begin
req = Amazon::Search::Request.new session[:AWS_KEY]
res = req.keyword_search(title + ” ” + artist, ‘music’)
return res.products.clone
rescue
puts “excepton”
nil
end
end
def iterate_through_coverless_albums
if session[:track_counter].nil?
# First time through. Setup.
session[:AWS_KEY] = ‘XXXXXXXXXXXXXXXXXXXXX’ # Go get your own AWS key
session[:ART_PATH] = ‘f:/music/artwork/’
session[:track_counter] = 1
session[:skip_hash] = {}
end
app = WIN32OLE.new ‘iTunes.Application’
music = app.LibrarySource.Playlists.ItemByName ‘Music’
total_count = music.Tracks.Count
while session[:track_counter] <= total_count do
track = music.Tracks.Item session[:track_counter]
if track.Artwork.Count == 0 and not session[:skip_hash].has_key? track.Album
@album_candidates = lookup_album track.Album, track.Artist
if not @album_candidates.nil?
# We have our next contestant. Let’s break
#puts “Got candidates: #{@album_candidates.length}”
@current_album = session[:current_album] = track.Album
@current_artist = session[:current_artist] = track.Artist
break
end
end
session[:track_counter] += 1
end
end
def index
iterate_through_coverless_albums
render :action => ‘iterate_through_coverless_albums’, :controller => ‘album’
end
end
iteratethroughcoverlessalbums.rhtml:
script type = "text/javascript">
function submitform(url, idx)
{
art.image_url.value = url;
art.idx.value = idx;
art.submit();
}
</script>
<% form_tag '/album/reset' do %><br />
<%= submit_tag 'Reset' %><br />
<% end %><br />
<% formtag ‘/album/next’ do %>
<%= submittag ‘Next’ %>
<% end %>
<h1><%= @currentartist %>, <%= @currentalbum %></h1>
<% formtag ‘/album/processinput’, {:name => “art”, :id => “art”} do%>
<%= hiddenfieldtag “imageurl” %>
<%= hiddenfieldtag “idx” %>
<% if not @albumcandidates.nil? %>
<table>
<th>Album Name</th>
<th>Small Art</th>
<th>Medium Art</th>
<th>Large Art</th>
<% idx = 0
@albumcandidates.each do |album| %>
<tr>
<td><%= album.productname %></td>
<td><%= imagetag album.imageurlsmall, :onclick => “submitform(’#{album.imageurlsmall}’, #{idx})” %></td>
<td><%= imagetag album.imageurlmedium, :onclick => “submitform(’#{album.imageurlmedium}’, #{idx})” %></td>
<td><%= imagetag album.imageurllarge, :onclick => “submitform(’#{album.imageurllarge}’, #{idx})” %></td>
</tr>
<% idx += 1
end %>
</table>
<% else %>
Done
<% end %>
<% end %>
<% formtag ‘/album/next’ do %>
<%= submittag ‘Next’ %>
<% end %>



1 comment so far ↓
this is cool. thanks for the idea.
Leave a Comment