【问题标题】:iTunes AppleScript: query all playlists that contain a certain trackiTunes AppleScript:查询包含某个曲目的所有播放列表
【发布时间】:2014-12-11 02:14:36
【问题描述】:

为 iTunes 处理复杂的 AppleScript。一项任务是累积包含给定曲目的所有播放列表的列表。我从其他地方(选择或其他)获得了这个轨道对象。

目前,我有一个类似这样的 sn-p:

on containingPlaylists(theTrack)
    tell application "iTunes"
        set librarySource to the source named "Library"
        set candidateLists to every user playlist in librarySource
        set candidateId to (get id of theTrack)
        set matchLists to {}
        repeat with candidateList in candidateLists
                set matchTracks to (file tracks in candidateList whose id = candidateId)
                if (count of matchTracks) > 0 then
                        copy candidateList to end of matchLists
                end if
        end repeat
        return matchLists
    end tell
end containingPlaylists

这可行,但循环中每个播放列表都需要一个 Apple Event,这很昂贵(性能)并且会丢弃中间结果。我宁愿做的是一个查询:

set matchLists to every playlist in librarySource whose file tracks contain theTrack 

但这当然不起作用(特定错误是“处理程序只处理单个对象。”但不确定这是否有见地)。我真的不确定语言/应用是否支持这样的查询。

任何人都可以确认/否认/提供任何见解吗?谢谢!

【问题讨论】:

  • 你的单行查询逻辑错误:你需要使用database ID of <track[s]>来检查两个track reference的数据是否相同。不过从结构上来说还不错;只是 iTunes 脚本模型陈旧而粗糙,在处理更复杂的查询时有点垃圾。不过,我不会太担心发送几十个 AE,因为这没什么。当发送数以万计的 AE 开销时。如果您不需要曲目引用列表,请使用 exists 而不是 get 以减少工作量,但 iTunes 的性能在解决大型库(50K+ 曲目?)上的查询时总是会下降。
  • @foo:谢谢。你能帮我构建这样一个查询吗? (在这种情况下,只需替换“theTrack 的数据库 ID”也有同样的问题。)我正在寻找包含曲目的播放列表列表(不需要返回曲目引用,只需列表引用) .我正在建立一个庞大的批量工作,其中 AE 开销将是一个大问题,我很乐意尽可能避免它。再次感谢!
  • 我试过了,但 iTunes 每次都会出错;正如我所说,它解析多项目说明符的能力很差。为了最大限度地减少 AE 负载,您可以使用tell app "iTunes" to get {database ID, id of container} of every track,它将为您提供所有曲目的数据 ID 以及包含它们的播放列表的 ID。使用 NS[Counted]Set 魔法有效地过滤重复的数据库 ID,使用 NSDictionary 将它们映射到播放列表 ID,然后使用另一个 NSSet 去除重复的 ID,最后从剩下的内容中构建新的 playlist id <ID> 引用。
  • 我应该说:在您真正编写一些代码并对其进行分析之前,没有必要推测关键瓶颈might actually lie 在哪里。此外,没有足够的一般信息来了解程序的其余部分是否适用于整个解决方案,更不用说它的性能是否会对整体运行时产生显着影响。
  • 谢谢@foo。有用的想法。不太担心过早的优化,主要是把它当作学习 AS/iTunes 工作方式(和不工作方式)的机会。

标签: macos applescript itunes


【解决方案1】:

您可以使用它(在 iTunes 11 和 12 上工作):

tell application "iTunes"
    set theTrack to item 1 of (get selection)
    return user playlists of theTrack
end tell

更新--

AppleScript 字典中:

艺术品 n [inh. item] : 曲目中的一件艺术品 | 元素:包含在tracks中。所以artworks of thisTrack 有效

track n [inh. item] : 可播放的音源 | 元素:包含艺术品;包含在播放列表中。所以playlists of thisTrack 有效,你可以使用user playlists of thisTrack

iTunes.h(ObjC 脚本桥)中:

@interface iTunesTrack : iTunesItem - (SBElementArray *) 艺术品; 这是不可能的,因为播放列表不在 SBElementArray 的列表中。

但我不知道为什么AppleScript字典和iTunes.h文件有区别。

【讨论】:

  • 太棒了,谢谢!这似乎不在字典中——您是否通过任何有用的、可共享的方式在界面上系统地进行刺激发现了这一点? (因为它不在字典中,我也无法通过 ObjC 脚本桥访问它,或者认为我不能。那里有更好的字典文件吗?)
【解决方案2】:

我也希望可以使用这样的 who 子句。可惜。其他人可能会想出更好的计划,但我很确定这就是我找到包含所选曲目的播放列表的方式(这可能是最有效的):

set persisID to persistent ID of selection
set pp to playlists
set playListsWithIt to {}
repeat with p in pp
    set tt to (tracks of p whose persistent ID is persisID)
    if tt ≠ {} then set playListsWithIt to (playListsWithIt & (id of p))
end repeat

然后我可以将这些 ID 用于下一步。当然,这包括像“最近添加”这样的播放列表,它可能是也可能不是你想要的;您必须在其中添加另一个步骤才能“过滤”掉这样的结果。

【讨论】:

  • 谢谢。这似乎是相同的执行大纲 - 播放列表数量为 O(n) 往返。我会在你的语法中偷一些我不知道的技巧。
  • 注意:如果您想为 iTunes 库中的每个曲目对象设置一个唯一标识符,该标识符在库的生命周期内永远不会改变,请使用 persistent ID。如果您想确定哪些轨道对象指向相同的曲调,请使用database ID。当您想要一些可以用来构建新的按 ID 引用的东西时,请使用 id,例如playlist id <ID>.
  • 另外,将重复循环更改为使用if exists (tracks of p whose database ID is dbID) then set end of playListsWithIt to (id of p)。那应该会更有效率。如果您不希望结果列表包含重复的播放列表 ID,那么也将 and id of p is not in playListsWithIt 添加到条件测试中。
猜你喜欢
  • 2023-03-08
  • 1970-01-01
  • 2010-11-03
  • 1970-01-01
  • 2012-07-21
  • 1970-01-01
  • 2011-06-04
  • 2013-09-11
  • 2010-12-28
相关资源
最近更新 更多