使用ScriptingBridge获取当前歌曲的iTunes封面艺术品

7

我一直在尝试使用脚本桥获取当前正在播放的歌曲的iTunes艺术品。 我已经得到了一些歌曲的艺术品,但对于其他歌曲,我会收到SIGABRT错误。 我不确定问题可能是什么,所以非常需要帮助。以下是我目前的进展:

iTunesApplication * iTunes = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"];
NSImage *songArtwork;
iTunesTrack *current = [iTunes currentTrack];
iTunesArtwork *artwork = (iTunesArtwork *)[[[current artworks] get] lastObject];
if(artwork != nil)
  songArtwork = [artwork data];
else
  songArtwork = [NSImage imageNamed:@"Image.tiff"];

NSMenuItem *artworkMenuItem = [[NSMenuItem alloc] initWithTitle:@"" action:NULL keyEquivalent:@""];
[songArtwork setSize:NSMakeSize(128, 128)];
[artworkMenuItem setImage:songArtwork];
[Menu insertItem:artworkMenuItem atIndex:0];

对于一些歌曲,它可以正常工作并在菜单项中显示艺术品,但对于另一些歌曲,我会在以下行上收到SIGABRT错误:

[songArtwork setSize:NSMakeSize(128, 128)];

控制台的输出如下所示:
2011-08-12 23:13:20.094 SongViewer[2146:707] -[NSAppleEventDescriptor setSize:]:     unrecognized selector sent to instance 0x102827f70
2011-08-12 23:13:20.095 SongViewer[2146:707] An uncaught exception was raised
2011-08-12 23:13:20.096 SongViewer[2146:707] -[NSAppleEventDescriptor setSize:]: unrecognized selector sent to instance 0x102827f70
2011-08-12 23:13:20.097 SongViewer[2146:707] (
0   CoreFoundation                      0x00007fff86f11986 __exceptionPreprocess + 198
1   libobjc.A.dylib                     0x00007fff8b04cd5e objc_exception_throw + 43
2   CoreFoundation                      0x00007fff86f9d5ae -[NSObject doesNotRecognizeSelector:] + 190
3   CoreFoundation                      0x00007fff86efe803 ___forwarding___ + 371
4   CoreFoundation                      0x00007fff86efe618 _CF_forwarding_prep_0 + 232
5   SongViewer                          0x0000000100002a83 -[IPMenulet awakeFromNib] + 4483
6   CoreFoundation                      0x00007fff86f089e1 -[NSObject performSelector:] + 49
7   CoreFoundation                      0x00007fff86f08962 -[NSSet makeObjectsPerformSelector:] + 274
8   AppKit                              0x00007fff8d9d9c27 -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:] + 1245
9   AppKit                              0x00007fff8d9d01b9 loadNib + 322
10  AppKit                              0x00007fff8d9cf6b6 +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:ownerBundle:] + 217
11  AppKit                              0x00007fff8d9cf5d1 +[NSBundle(NSNibLoading) loadNibFile:externalNameTable:withZone:] + 141
12  AppKit                              0x00007fff8d9cf514 +[NSBundle(NSNibLoading) loadNibNamed:owner:] + 364
13  AppKit                              0x00007fff8dc42355 NSApplicationMain + 398
14  SongViewer                          0x0000000100001882 main + 34
15  SongViewer                          0x0000000100001854 start + 52
)
2011-08-12 23:13:20.098 SongViewer[2146:707] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSAppleEventDescriptor setSize:]: unrecognized selector sent to instance 0x102827f70'
*** First throw call stack:
(
0   CoreFoundation                      0x00007fff86f11986 __exceptionPreprocess + 198
1   libobjc.A.dylib                     0x00007fff8b04cd5e objc_exception_throw + 43
2   CoreFoundation                      0x00007fff86f9d5ae -[NSObject doesNotRecognizeSelector:] + 190
3   CoreFoundation                      0x00007fff86efe803 ___forwarding___ + 371
4   CoreFoundation                      0x00007fff86efe618 _CF_forwarding_prep_0 + 232
5   SongViewer                          0x0000000100002a83 -[IPMenulet awakeFromNib] + 4483
6   CoreFoundation                      0x00007fff86f089e1 -[NSObject performSelector:] + 49
7   CoreFoundation                      0x00007fff86f08962 -[NSSet makeObjectsPerformSelector:] + 274
8   AppKit                              0x00007fff8d9d9c27 -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:] + 1245
9   AppKit                              0x00007fff8d9d01b9 loadNib + 322
10  AppKit                              0x00007fff8d9cf6b6 +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:ownerBundle:] + 217
11  AppKit                              0x00007fff8d9cf5d1 +[NSBundle(NSNibLoading) loadNibFile:externalNameTable:withZone:] + 141
12  AppKit                              0x00007fff8d9cf514 +[NSBundle(NSNibLoading) loadNibNamed:owner:] + 364
13  AppKit                              0x00007fff8dc42355 NSApplicationMain + 398
14  SongViewer                          0x0000000100001882 main + 34
15  SongViewer                          0x0000000100001854 start + 52
)
terminate called throwing an exception(gdb) 

如果有人知道可能出了什么问题,请告诉我!

你看到了哪些其他的控制台输出? - jtbandes
嗨jtbandes,感谢您的回复。我已经将控制台输出添加到上面的问题中。在我看来,由于某种原因,NSImage *artwork为nil(或NULL?),这就可以解释分段错误了。奇怪的是,我认为检查它是否为nil会检查那个...我想不是...我真的不知道该怎么继续了。从iTunes的角度来看,我播放的两首歌曲在艺术品方面似乎是相同的。一个有效,另一个无效。感谢您能给我的任何帮助! :) - alwaysapple
好的,我已经缩小到实际的iTunesArtwork *artwork无效。但它不是nil。有没有办法检查这个艺术品是否有效? - alwaysapple
2个回答

12

好的,所以我找到了解决办法。方法是使用API提供的NSData原始数据而不是NSImage。所以我使用了:

NSImage *songArtwork = [[NSImage alloc] initWithData:[artwork rawData]];

而不是

songArtwork = [artwork data];

这真的很有帮助,谢谢!你也可以接受自己的答案。 - ySgPjx

0

我需要从iTunes获取一批音轨艺术品并使用‘rawData’。但这种方式效率很低。我找到了一个更好的方法(实际上,它将“fetch”时间减少了约2倍,在获取许多使用‘valueForKey:’的音轨艺术品时非常显著,参见“提高Scripting Bridge代码性能”)。

所以我决定弄清楚iTunesArtwork的"data"属性出了什么问题。 根据iTunes.h,我们期望得到一个NSImage对象,但实际上得到的是一种'NSAppleEventDescriptor'。很容易猜到,这个对象包含了我们需要的图像。因此,我们可以使用"data"属性来获取图像数据。这比从iTunesArtwork获取"rawData"要快得多。 但有时iTunes会返回NSImage对象而不是NSAppleEventDescriptor。这是一种奇怪的行为,但仍然比使用rawData更快。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接