Comments

  1. Eirik says

    On Lion running the sudo gem commands gives me an error;

    ERROR: Error installing json:
    ERROR: Failed to build gem native extension.

    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby extconf.rb
    mkmf.rb can’t find header files for ruby at /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/ruby.h

    Any idea? I saw somewhere suggested to install Xcode; but I don’t feel like installing a 1,3GB program to run a short script…

    • Beau Giles says

      Hey Elrik – you can try the other application mentioned at the end of the post – else unfortunately you may be required to download XCode.

      • Eirik says

        Ok. Thanks. I tried that other mac program, but it also didn’t work on my computer…

    • Brian says

      Probably because you have to install the Command Line Tools with XCode. With OSX Lion they disabled a lot of commands in terminal unless you install the Command Line Tools for developers.

  2. Christian says

    This didn´t work on my Mac. I installed XCode but this didn´t help. I got that message:

    Building native extensions. This could take a while…
    ERROR: Error installing json:
    ERROR: Failed to build gem native extension.

    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby extconf.rb
    mkmf.rb can’t find header files for ruby at /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/ruby.h

    Gem files will remain installed in /Library/Ruby/Gems/1.8/gems/json-1.7.3 for inspection.
    Results logged to /Library/Ruby/Gems/1.8/gems/json-1.7.3/ext/json/ext/parser/gem_make.out

  3. says

    Hmm, terminal throws me this error:

    method_missing’: Unknown property, element or command: ‘selection’ (RuntimeError)
    from iTunesMatchMetadata.rb:54

    • Stephen says

      I also get the error: method missing'. The complete error that was returned is:

      /Library/Ruby/Gems/1.8/gems/rb-appscript-0.6.1/lib/appscript.rb:676:in method_missing’: Unknown property, element or command: ‘selection’ (RuntimeError)
      from iTunesMatchMetadata.rb:54

      Any suggestions? I would love to update my metadata!

      Please. And thank you.

  4. Christian says

    What would it take to make this work on 10.6? I’m stuck on a 64bit iMac that cannot be upgraded. Thanks!

    • Christian says

      Can’t edit posts, disregard the previous post. What I meant to ask is why I am getting this error after installing ruby and running the script:

      /Library/Ruby/Gems/1.8/gems/rb-appscript-0.6.1/lib/_aem/connect.rb:89:in launch_application': The Classic emulation environment was required but is not available. (-10828) (Connect::CantLaunchApplicationError)
      from /Library/Ruby/Gems/1.8/gems/rb-appscript-0.6.1/lib/_aem/connect.rb:182:in
      local_app’
      from /Library/Ruby/Gems/1.8/gems/rb-appscript-0.6.1/lib/aem.rb:146:in by_path'
      from /Library/Ruby/Gems/1.8/gems/rb-appscript-0.6.1/lib/appscript.rb:57:in
      send’
      from /Library/Ruby/Gems/1.8/gems/rb-appscript-0.6.1/lib/appscript.rb:57:in connect'
      from /Library/Ruby/Gems/1.8/gems/rb-appscript-0.6.1/lib/appscript.rb:159:in
      reference_by_name’
      from /Library/Ruby/Gems/1.8/gems/rb-appscript-0.6.1/lib/appscript.rb:633:in `method_missing’
      from meta.rb:55

  5. Appleman says

    You need to install the command line tools for Xcode too…

    You can get Xcode from the Mac App Store. You’ll need at least version 4.4 of Xcode for it to work with OS X Mountain Lion. After the installation, open up Xcode in your /Applications folder. You’d want to go to Xcode -> Preferences -> Downloads tab then install the “Command Line Tools.” After you’re done, quit Xcode and fire up Terminal and follow the steps mentioned prior.

    Good Luck!

  6. says

    For italian users, you can change code on line 63 with this:

    if iTunes_track.kind.get == ‘File audio AAC corrispondente’

    It will works fine!

  7. Gabriel says

    Worked fine (also in iTunes 11). However I needed to change the language of my system preferences to english.

  8. George says

    Thank you for the post!
    I’m getting this error:

    Found 1793 matched tracks
    Querying AU store for 1793 tracks */Library/Ruby/Gems/1.8/gems/rb-appscript-0.6.1/lib/appscript.rb:542:in _send_command': CommandError (Appscript::CommandError)
    OSERROR: -1700
    MESSAGE: Can't make some data into the expected type.
    COMMAND: app("/Applications/iTunes.app").sources.ID(73).user_playlists.ID(18643).file_tracks.ID(18652).album.set(nil)
    from /Library/Ruby/Gems/1.8/gems/rb-appscript-0.6.1/lib/appscript.rb:642:in
    method_missing’
    from iTunesMatchMetadata.rb:38:in update_track'
    from iTunesMatchMetadata.rb:92
    from iTunesMatchMetadata.rb:90:in
    each’
    from iTunesMatchMetadata.rb:90
    from iTunesMatchMetadata.rb:88:in each'
    from iTunesMatchMetadata.rb:88
    from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/delegate.rb:137:in
    each_slice’
    from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/delegate.rb:137:in each'
    from iTunesMatchMetadata.rb:84:in
    each_slice’
    from iTunesMatchMetadata.rb:84
    from iTunesMatchMetadata.rb:81:in `each’
    from iTunesMatchMetadata.rb:81

    Any idea?

  9. Mark says

    Hello,

    I’m getting the same error as George. What goes wrong?

    MacBook-Pro-van-Mark-Ramaekers:desktop Mark$ ruby iTunesMatchMetadata.rb
    Reading 8077 tracks ********************************************************************************
    Found 8077 matched tracks
    Querying AU store for 8077 tracks */Library/Ruby/Gems/1.8/gems/rb-appscript-0.6.1/lib/appscript.rb:542:in _send_command': CommandError (Appscript::CommandError)
    OSERROR: -1700
    MESSAGE: Can't make some data into the expected type.
    COMMAND: app("/Applications/iTunes.app").sources.ID(72).user_playlists.ID(100410).file_tracks.ID(100430).album.set(nil)
    from /Library/Ruby/Gems/1.8/gems/rb-appscript-0.6.1/lib/appscript.rb:642:in
    method_missing’
    from iTunesMatchMetadata.rb:38:in update_track'
    from iTunesMatchMetadata.rb:92
    from iTunesMatchMetadata.rb:90:in
    each’
    from iTunesMatchMetadata.rb:90
    from iTunesMatchMetadata.rb:88:in each'
    from iTunesMatchMetadata.rb:88
    from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/delegate.rb:137:in
    each_slice’
    from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/delegate.rb:137:in each'
    from iTunesMatchMetadata.rb:84:in
    each_slice’
    from iTunesMatchMetadata.rb:84
    from iTunesMatchMetadata.rb:81:in `each’
    from iTunesMatchMetadata.rb:81

  10. Bo says

    Hi Mark and George,
    Issue seems to be when iTunes store doesn’t have an album associated with the song. The code can’t handle an empty album name.

    Just place a little if statement in the “update_track” method.
    It should look like this now (minus the line numbers of course, also line 36 was only for debugging):

    35 def update_track(result)
    36 puts “Track Id= #{result[‘trackId’]} | Artist Name= #{result[‘artistName’]} | Album Name= #{result[‘collectionName’]} | Track Name= #{result[‘trackName’]}”
    37 @iTunes_track.name.set(result[‘trackName’])
    38 if !result[‘collectionName’].nil?
    39 @iTunes_track.album.set(result[‘collectionName’])
    40 end
    41 @iTunes_track.artist.set(result[‘artistName’])
    42 @iTunes_track.track_count.set(result[‘trackCount’])
    43 @iTunes_track.track_number.set(result[‘trackNumber’])
    44 @iTunes_track.genre.set(result[‘primaryGenreName’])
    45 @iTunes_track.disc_count.set(result[‘discCount’])
    46 @iTunes_track.disc_number.set(result[‘discNumber’])
    47 end

    • Mark says

      Hi Bo,

      I’m a total nitwit. My script now looks like below.
      I’m getting the message:

      MacBook-Pro-van-Mark-Ramaekers:desktop Mark$ ruby iTunesMatchMetadata.rb
      iTunesMatchMetadata.rb:37: Invalid char \342' in expression
      iTunesMatchMetadata.rb:37: Invalid char
      \200′ in expression
      iTunesMatchMetadata.rb:37: Invalid char `\234′ in expression
      iTunesMatchMetadata.rb:37: dynamic constant assignment
      puts “Track Id= #{result[‘trackId’]} | Artist…

      What am I doing wrong?

      #!/usr/bin/env ruby
      # by @tapbot_paul
      # Don’t blame me if this nukes your metadata, formats your drive, kills your kids
      # This script goes through any iCloud Matched songs in your iTunes library and tries to update the
      # metadata from the iTunes Store
      # Will run against selected tracks or if nothing selected entire library
      # install the required gems with the following commands
      # sudo gem install json
      # sudo gem install rb-appscript
      # then run the script with “ruby meta.rb”
      require ‘rubygems’
      require ‘appscript’
      require ‘json’
      require ‘open-uri’
      require(“~/Library/iTunes/tunes.rb”)

      class Track
      attr_reader :iTunes_id
      attr_reader :iTunes_track
      def initialize(iTunes_track)
      @iTunes_track = iTunes_track
      path = @iTunes_track.location.get.path
      file_string = File.open(path, ‘r’).read(1024) # data always seems to be around 600-700 bytes in
      index = file_string.index(‘song’)
      if index
      @iTunes_id = file_string[index+4,4].unpack(‘N’)[0]
      else
      puts “Couldn’t find @iTunes_track id #{track.name.get}”
      end
      end

      def valid?
      @iTunes_id.nil?
      end

      def update_track(result)
      puts “Track Id= #{result[‘trackId’]} | Artist Name= #{result[‘artistName’]} | Album Name= #{result[‘collectionName’]} | Track Name= #{result[‘trackName’]}”
      @iTunes_track.name.set(result[‘trackName’])
      if !result[‘collectionName’].nil?
      @iTunes_track.album.set(result[‘collectionName’])
      end
      @iTunes_track.artist.set(result[‘artistName’])
      @iTunes_track.track_count.set(result[‘trackCount’])
      @iTunes_track.track_number.set(result[‘trackNumber’])
      @iTunes_track.genre.set(result[‘primaryGenreName’])
      @iTunes_track.disc_count.set(result[‘discCount’])
      @iTunes_track.disc_number.set(result[‘discNumber’])
      end

      end

      WORK_SIZE = 100
      STDOUT.sync = true
      tracks = []

      app = Appscript.app.by_name(“iTunes”, Tunes)

      iTunes_tracks = app.selection.get
      if iTunes_tracks.count == 0
      iTunes_tracks = app.library_playlists[1].tracks.get
      end

      print “Reading #{iTunes_tracks.count} tracks ”
      iTunes_tracks.each do | iTunes_track |
      begin
      if iTunes_track.kind.get == ‘Gematcht AAC-audiobestand’
      track = Track.new(iTunes_track)
      unless track.valid?
      tracks < e
      puts e
      end
      end
      puts ”

      # all 2 char countries codes lots currently not valid %w(AF AX AL DZ AS AD AO AI AQ AG AR AM AW AU AT AZ BS BH BD BB BY BE BZ BJ BM BT BO BQ BA BW BV BR IO BN BG BF BI KH CM CA CV KY CF TD CL CN CX CC CO KM CG CD CK CR CI HR CU CW CY CZ DK DJ DM DO EC EG SV GQ ER EE ET FK FO FJ FI FR GF PF TF GA GM GE DE GH GI GR GL GD GP GU GT GG GN GW GY HT HM VA HN HK HU IS IN ID IR IQ IE IM IL IT JM JP JE JO KZ KE KI KP KR KW KG LA LV LB LS LR LY LI LT LU MO MK MG MW MY MV ML MT MH MQ MR MU YT MX FM MD MC MN ME MS MA MZ MM NA NR NP NL NC NZ NI NE NG NU NF MP NO OM PK PW PS PA PG PY PE PH PN PL PT PR QA RE RO RU RW BL SH KN LC MF PM VC WS SM ST SA SN RS SC SL SG SX SK SI SB SO ZA GS SS ES LK SD SR SJ SZ SE CH SY TW TJ TZ TH TL TG TK TO TT TN TR TM TC TV UG UA AE GB US UM UY UZ VU VE VN VG VI WF EH YE ZM ZW)

      countries = %w(NL US GB FR DE CA IT JP DZ AO AI AG AR AM AT AZ BS BH BD BB BY BE BZ BM BO BW BR BN BG CM KY CL CN CO CR CI HR CY CZ DK DM DO EC EG SV EE ET FI GH GR GD GT GY HN HK HU IS IN ID IE IL JM JO KZ KE KR KW LV LB LY LI LT LU MO MK MG MY MV ML MT MU MX MD MS MM NP AU NZ NI NE NG NO OM PK PA PY PE PH PL PT QA RO RU KN LC VC SA SN RS SG SK SI ZA ES LK SR SE CH TW TZ TH TT TN TR TC UG UA AE UY UZ VE VN VG YE)

      puts “Found #{tracks.count} matched tracks”
      countries.each do | country |
      print “Querying #{country} store for #{tracks.count} tracks ”
      counter = 0
      tracks.dup.each.each_slice(WORK_SIZE) do | subtracks |
      ids = subtracks.map { | track | track.iTunes_id }
      iTunesHash = JSON.parse(open(“http://itunes.apple.com/lookup?id=#{ids.join(‘,’)}&country=#{country}”).read)
      print ‘*’
      iTunesHash[‘results’].each do | result |
      result_id = result[‘trackId’]
      subtracks.each do | track |
      if result_id == track.iTunes_id
      track.update_track(result)
      tracks.delete(track)
      counter += 1
      break
      end
      end
      end
      end
      puts ” #{counter} updated”
      break if tracks.empty?
      end

      puts “Couldn’t find meatadata for #{tracks.count} tracks” if tracks.count != 0

    • says

      Hey Lala,
      Could you please explain what you mean by ‘copyright’ tag?
      This script should only change the title, album and artist fields, without touching anything else.

      • Lala says

        By copyright tag I mean the record label field that appears under the title, album and artist tags when clicking on “Get Info” on iTunes. Thank you for the reply in advance.

  11. Anthony says

    I absolutely loved this post, and I had no problems running the script. Thanks so much!

    The only question I have is if there is any way to make this script gather and replace any other information, like genre, year, explicit/clean, etc? Or is that related to a limitation of the API?

  12. Ludovic Salmeron says

    Hey sorry for my bad english i’m french, I don’t know why :

    new-host:Desktop ludovicsalmeron$ ruby iTunesMatchMetadata.rb
    Reading 1003 tracks
    Found 0 matched tracks
    Querying AU store for 0 tracks 0 updated

    Only AU store and no others. Can U help me ?

  13. Brad says

    Have you found a workaround for tracks that are not found in any of the stores? Seems odd to me that ANY would be skipped if they are still available on iTunes.

    Awesome script! I can’t thank you enough.

  14. David says

    Thanks! This works like a charm. I fixed up a couple hundred tunes tonight that had been resisting everything else.

  15. Zee says

    This was working fine on my iMac with OS 10.8 today I updated to OS 10.9 and now it’s not working.

    what do you think changed on 10.9 ?

  16. Gert-Jan says

    Hey Guys,
    I got some problems with getting updated tracks, this is what termanl said:

    Reading 1119 tracks
    Found 0 matched tracks
    Querying AU store for 0 tracks 0 updated
    MacBook-Pro-van-Gert-Jan:Desktop GertJan$
    MacBook-Pro-van-Gert-Jan:Desktop GertJan$
    MacBook-Pro-van-Gert-Jan:Desktop GertJan$
    MacBook-Pro-van-Gert-Jan:Desktop GertJan$ ruby iTunesMatchMetadata.rb

    Can anyone see whats the problem of not getting any updated tracks?

    Thanks in advance!

    Gert-Jan

  17. Connor says

    This is working quite well, however I have the same question as some of the guys above, i.e. Lala and Anthony. Is there a way to edit the script so that it adds other metadata, e.g. Copyright information and explicit/clean tags? I have tried adding to the script myself (although I really am no expert) but I can never get it to work.

    Replies would be much appreciated (either from the author or someone who knows how to do this).

    Thanks