1

今天我发现,当我将专辑封面添加到 iTunes 时,它实际上只是将其添加到了每张专辑中的一些曲目中。所以我做了任何人都会做的事情,并尝试编写一个脚本来纠正它。

这是第一次尝试,经过大约 3 小时的修补。它假定您已选择专辑中的所有歌曲。

#! /usr/local/bin/macruby
framework 'Foundation'
framework 'ScriptingBridge'

itunes = SBApplication.applicationWithBundleIdentifier("com.apple.itunes")
tracks = itunes.selection.get

# Find some track with artwork
artwork = tracks.map { |track| track.artworks[0] }.find { |a| a }
raise "No selected song has artwork" if artwork.nil?

# I checked artwork.rawData and it is PNG wrapped in an NSConcreteData.
pngData = artwork.rawData

tracks.each do |track|
  if track.artworks[0]
    puts "[O] #{track.name}"
  else
    puts "[X] #{track.name}"
    # Adding the same artwork object is apparently NG so we get the data from it
    # and make a copy.
    # There is probably a more straight-forward way to clone an object but
    # artwork.copy raises an exception.
    # I have tried using the keys 'data' and 'raw data' instead - same results.
    dict = {rawData: pngData}
    artwork_copy = itunes.classForScriptingClass('artwork').alloc.initWithProperties(dict)

    track.artworks.addObject(artwork_copy)

    raise "Didn't actually add the artwork" if track.artworks.empty?
  end
end

对 addObject 的调用不会引发异常,但我注意到它实际上并没有将艺术品添加到轨道(因此检查下一行以加快脚本测试。)

我主要从 ScriptingBridge 的 Objective-C 示例中工作,也找不到其他人做过的任何地方。获得艺术品的例子很多,但设置它的例子却很少......

I did find an interesting mailing list thread from four years ago where someone else had a similar issue, but they never came to a solution either (or found it and didn't post it to the thread, which is worse and if they did that, they're a bad person and should feel bad.)

4

1 回答 1

1

Here is an example of Objective-C code that works for me. I don't know for macruby

iTunesApplication *iTunesApp = [SBApplication applicationWithBundleIdentifier: @"com.apple.iTunes"];
SBElementArray *tracks = [[iTunesApp selection] get];
NSArray *trackWithArt = [tracks filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"artworks[SIZE] > 0"]]; 
if ([trackWithArt count] > 0) {
    NSImage *tData = (NSImage*)[[[[trackWithArt objectAtIndex:0] artworks] objectAtIndex:0] data];
    for (iTunesTrack *tObj in [tracks filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"artworks[SIZE] = 0"]]) {
        [[[[tObj artworks] objectAtIndex:0] propertyWithCode:'pPCT'] setTo:tData];
    }
}

Here is another method that works:

Replace the line in the loop by the following:

iTunesArtwork *tArtw = [[tObj artworks] objectAtIndex:0];
tArtw.data = tData; // set the track's artwork

MacRuby equivalents of both of the above (I'm using the latter for obvious reasons):

    # 0x70504354 = 'pPCT'
    track.artworks.objectAtIndex(0).propertyWithCode(0x70504354).setTo(artwork.data)
    # or,
    track.artworks.objectAtIndex(0).data = artwork.data

-

An alternative: it's very simple to do with AppleScript.

于 2012-10-28T23:43:13.507 回答