I posted iTunes to Rhythmbox on Monday, 27 July, 2015

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

Post itunes ruby music

iTunes to Rhythmbox

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.


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

# 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?

The song pie for July
Figure 1. The song pie for July

I’ve made progress since March. It looks less like Pac Man now.

Indieweb Social

Did you mention this somewhere? I'd love it if you sent me the link!

disclaimer about timing

Mentions are sent to webmention.io. I fetch the latest mentions when building the site, so I may not see your feedback right away. Especially if my site's broken, which is often the case.

Public replies and mentions might be shared on the site, but I try to do a little quality check first.

Site Links