Random Geekery

iTunes to Rhythmbox

Added by to Tools on

Tags · itunes · ruby · music ·

Pandoc Zentangle Doodle

I nearly wrote a script that transfers my iTunes ratings to Rhythmbox. Instead I used Edgar Salgado’s version of iTunesToRhythm.

See, I have been spending most of my time lately in GNOME 3 on openSUSE Linux. All of my music is copied over and loaded into Rhythmbox, but I wanted to continue my quest to rate all of my music. I spent roughly an hour starting my own solution before realizing that this was probably a solved problem.

Salgado’s code is a fork of another project, but he won my heart because he wrote how to use his version.

$ git clone git@github.com:esalgado/iTunesToRhythm.git
$ cd iTunesToRhythm
$ python iTunesToRhythm.py -w ~/Sync/iTunes\ Music\ Library.xml ~/.local/share/rhythmbox/rhythmdb.xml

Some things about the process annoyed me. For some strange reason, not every iTunes entry included a file location. I manually fixed those. More annoying: the iTunes XML showed roughly 7,000 tracks as rated even though the iTunes application showed over 10,000 as rated. I chose to live with that. It’s only 3,000 tracks that I need to rate again.

sigh

Hey, let’s make a pretty picture.

#!/usr/bin/env ruby

require 'nokogiri'
require 'gruff'

SOURCE = "/home/brian/.local/share/rhythmbox/rhythmdb.xml"

rhythmdb = Nokogiri::XML File.open SOURCE
songs = rhythmdb.xpath "/rhythmdb/entry[@type='song']"
ratings = {}

# Group the songs by rating.
songs.each do |song|
  rating = song.xpath("rating").text.to_i || 0
  total_time = song.xpath("duration").text.to_i || 0
  ratings[rating] ||= { songs: 0, time: 0 }
  ratings[rating][:songs] += 1
  ratings[rating][:time] += total_time
end

# Print it.
puts 'Rating Songs Percent Duration'

ratings.keys.sort.each do |rating|
  song_count = ratings[rating][:songs]
  total_seconds = ratings[rating][:time] #Rhythmbox uses seconds
  seconds = total_seconds % 60
  minutes = (total_seconds / 60) % 60
  hours = (total_seconds / (60 * 60)) % 24
  days = total_seconds / (60 * 60 * 24)

  percentage = song_count.to_f() / songs.count.to_f() * 100.0
  duration = format '%02d:%02d:%02d:%02d', days, hours, minutes, seconds
  description = format '%6d %5d %6.1f%% %s', rating, song_count, percentage, duration
  puts description

# Graph it.
data = ratings.map { |rating, info| [ rating, [ info[:songs]]] }

graph = Gruff::Pie.new
graph.title = "Songs Grouped By Rating"

ratings.keys.sort.each { |rating| graph.data rating, ratings[rating][:songs] }

graph.write "song-pie.png"

This calls for Nokogiri instead of plist, which gives me the opportunity to flex my amazing XPath skills. Nothing too complex. Thank goodness.

$ ruby graph-ratings.rb
Rating Songs Percent Duration
     0  8926   55.2% 24:13:00:24
     1   254    1.6% 00:19:49:30
     2   984    6.1% 02:21:42:54
     3  3932   24.3% 10:08:49:09
     4  1716   10.6% 04:10:50:01
     5   370    2.3% 00:23:16:01

How about that pretty picture?

July song rating chart
The song pie for July

I’ve made progress since graphing my iTunes ratings in July. It looks less like Pac Man now.