3

如何使用 Python 和 Scripting Bridge 创建播放列表?

到目前为止,我有:

from Foundation import *
from ScriptingBridge import *

iTunes = SBApplication.applicationWithBundleIdentifier_("com.apple.iTunes")
newPlaylist = iTunes.iTunesPlaylist()

这显然是行不通的。

我见过 Ruby 和 Objective C 的东西,但我并不真正理解这门语言。

4

1 回答 1

6

这实际上是Scripting Bridge 文档中的一个示例。请参见清单 2,“在 PyObjC 代码中将对象添加到可编写脚本的应用程序”:

from Foundation import *
from ScriptingBridge import *

iTunes = SBApplication.applicationWithBundleIdentifier_("com.apple.iTunes")
p = {'name':'Testing'}
playlist = iTunes.classForScriptingClass_("playlist").alloc().initWithProperties_(p)
iTunes.sources()[0].playlists().insertObject_atIndex_(playlist, 0)

如果这对你没有意义,有一些不同的丑陋的事情需要解释......</p>

首先,SBApplication没有任何成员iTunesPlaylistSBObject. 如果你生成了静态胶水,ITApplication可能会有这样的东西……但你不想使用静态胶水。因此,您必须动态创建类对象iTunesPlaylist。有几种不同的方法可以做到这一点,但最简单的方法(假设你知道它playlist在 Applescript 中被调用)是使用classForScriptingClass_.

其次,ScriptingBridge 并不是真正的原生 Python 到 AE 的桥梁。它是通往 AE 的 ObjC 桥梁的 Python 桥梁。所以这iTunesPlaylist实际上是一个包装好的 ObjC 类,而不是 Python 类。这意味着您不能将其实例化为iTunesPlaylist(),您必须说iTunesPlaylist.alloc().init()

调用initWithProperties_(p)是在单独的步骤中初始化和设置属性的一个很好的快捷方式。

最后,AE对象模型的工作方式,你不能只是“创建一个对象”,你必须在某个位置创建一个对象。ScriptingBridge 试图对您隐藏这一点,但它做得不是很好。您创建的playlist对象实际上并不代表 iTunes 中的任何内容——事实上,如果您查看它的typeor repr,您会发现它是“未来的 iTunesPlaylist”。你需要找到一个合适SBElementArray的插入它,然后它就会成为一个真正的播放列表。

并非 ScriptingBridge 中的所有内容都如此可怕。但有些情况甚至更糟。等到您遇到 iTunes 脚本字典出错的地方之一……</p>

如果可以避免使用 ScriptingBridge,iTunes AE 界面本身就非常好。有三种方法可以解决这个问题,尽管它们可能对您没有帮助。

首先,有appscript此处的文档)。这是一个不同的 Python->AE 桥,比 SB 好得多。以下是相同的内容(依赖于 iTunes 具有播放列表默认位置的默认设置 - 在第一个库源中播放列表列表的末尾):

from appscript import *

iTunes = app('iTunes')
p = {'name':'Testing'}
playlist = iTunes.make(new=k.playlist, with_properties=p)

如果您不知道如何做您想做的事,但可以找到 AppleScript 示例代码(例如,在dougscripts),您可以使用 ASTranslate 工具编写等效的 appscript。

不幸的是,appscript 的作者已经取消了这个项目。并且有充分的理由——它依赖于 Apple 可以在 10.9 中删除的遗留 API(或引用拒绝你从 App Store 中)。目前,它仍然可以正常工作,并且有几个人在上面的 github repo 中保持它的活力,但总有一天,它会真的死掉。因此,除非这是个人、短期或学习项目,否则它可能不是一个好的解决方案。(此外,特定于 iTunes:10.6.3 有一个影响 appscript 的错误,但不会影响其他网桥,除非您远程使用它们。如果您需要使用该版本,请参阅itunesterms以获得一种解决方案。)

当然,总有一个显而易见的选择:在 AppleScript 中执行:

tell application "iTunes"
    make new playlist with properties {name:"Testing4"}
end tell

The problem with AppleScript is that it's a horrible language for everything except talking AEOM, and its equivalent of Python's standard library is about 5% as deep and wide. But you can always use a two-language solution, in two ways. You can connect from AppleScript to other Cocoa code (e.g., Python with PyObjC) via ASOC. Or, alternatively, you can use NSAppleScript and friends to run scripts from PyObjC/etc.

The latter may be the most painful answer, but it has one huge advantage: If you use the new APIs in Mountain Lion, and your use cases fall within a certain narrow band, you can write a sandboxed app that scripts iTunes without needing a temporary exception entitlement, meaning you can sell it in the App Store.

于 2012-10-18T22:55:41.903 回答