XcodeとScripting BridgeでiTunesを使いこなす。

去年の夏、ひどいことが起こりました...私のMacBookにねじが入りました。 すべての重要なデータは簡単に回復されました。 タイムマシンに栄光を! しかし、私が長年苦心して培ってきた音楽コレクションは幸運ではありませんでした。 音楽自体を復元することは問題ではありませんが、レーティングと再生回数は、WindowsでのiTunesの外観にまでさかのぼります。 音楽ライブラリは、WindowsからHackintoshへ、そしてMacBookへの移行を含め、多く生き残りました。

幸いなことに、メディアライブラリのすべてが失われたわけではありません-角と足が残っていたか、むしろ大切なiTunes Librar yファイルが残っていました 。 先日、私は彼を蘇生することにしました。

Mac OSソリューション


画像 明らかな解決策はAppleScriptを使用することです。 これにより、Mac OS上のほとんどすべてのアプリケーションを自動化できます。 この言語は英語に非常に近く、他のプログラミング言語とはかけ離れているので、私はst迷に陥りました。 私は彼にどちらの側に近づくべきか知りませんでした。
Xcodeと少し馴染みのあるObjective-Cを使用する必要がありました。 XMLを使用しても、ほとんど問題は発生しませんでした。 NSXML ...とMSXMLは、名前だけでなく、非常によく似たAPIであることが判明しました。

iTunesでは、事態はさらに複雑になります。 Xcodeプロジェクトで使用できる実際のAppleScriptに加えて、2つの方法しか見つかりませんでした。 どちらも、本質的にAppleScriptのラッパーです。


1. AppScriptフレームワーク
サードパーティ開発者によるオープンソースプロジェクト。 10.3.9以降のMac OS Xに適しています。 Objective-CRubyPythonをサポートします。 構文は複雑に見え、正しくコンパイルできなかったため、理解できませんでした。

2. スクリプティングブリッジフレームワーク
Mac OS 10.5でのみリリースされたApple 独自のソリューション。 その名前が示すように、Scripting Bridgeは「Objective-CとAppleScript対応アプリケーション間のブリッジを動的に実装します。Objective-Cクラスは、スクリプトインターフェイスの記述に基づいて生成されます。プロパティ、要素、コマンドなどを表すオブジェクトとメソッドが含まれます。 」
2番目のオプションでは、停止しました。
最初にすることは、プロジェクトに/System/Library/Frameworks/ScriptingBridge.frameworkを追加することです。 次に、カスタムヘッダーファイルを作成して、特定のActionScript対応アプリケーションにアクセスする方法を確認します。
これは、ターミナルのコマンドによって実行されます。
sdef /Applications/iTunes.app | sdp -fh --basename iTunes

iTunes.hファイルが現在のフォルダーに表示されます。これはXcodeプロジェクトに追加する必要があり、iTunesにアクセスできます。
AppleScriptをサポートするどのアプリケーションでも同じことができます。

通信例


たとえば、歌のリスト、評価、およびパフォーマンスの数を保存するコード:

- ( void ) ExportLibrary
{
Boolean shouldExportTrack = NO;
// iTunes
iTunesApplication *iTunes = [SBApplication applicationWithBundleIdentifier: @"com.apple.iTunes" ];

// iTunes ( , )
iTunesLibraryPlaylist *library = [[[[iTunes sources] objectAtIndex:0] playlists] objectAtIndex:0];
iTunesTrack *track;

// XML
NSXMLDocument *xmlNew = [[NSXMLDocument alloc] initWithXMLString: @"<?xml version=\"1.0\"?><LIBRARY/>" options:0 error:NULL];
NSXMLElement *rootNode = [xmlNew rootElement], *curNode;

//
NSInteger curLibTrack = 0, nLibTracks = [[library tracks] count];
NSLog( @"%i" , nLibTracks);

//
for (curLibTrack = 0; curLibTrack < nLibTracks; curLibTrack++)
{
track = [[library tracks] objectAtIndex:curLibTrack];
shouldExportTrack = (track.rating > 0 || track.playedCount > 0); //
if (shouldExportTrack)
{
// XML
curNode = [[NSXMLElement alloc] initWithXMLString: @"<TRACK n=\"\" name=\"\" played=\"\" rating=\"\" />" error:NULL];
[[curNode attributeForName: @"n" ] setStringValue:[NSString stringWithFormat: @"%i" , curLibTrack]];
// getTrackMetaName, ,
// , , ( Beyoncé Anggun)
[[curNode attributeForName: @"name" ] setStringValue:[self getTrackMetaName:track]];
[[curNode attributeForName: @"played" ] setStringValue:[NSString stringWithFormat: @"%i" , track.playedCount]];
[[curNode attributeForName: @"rating" ] setStringValue:[NSString stringWithFormat: @"%i" , track.rating]];
[rootNode addChild:curNode];
[curNode release];
}

}

//
[[xmlNew XMLData] writeToFile:( @"/Users/max/Desktop/old-library.xml" ) atomically:NO];
[xmlNew release];

}


* This source code was highlighted with Source Code Highlighter .


おわりに


苦しんでいる図書館の修復作業はまだ完了していません。 MetaNameのハッシュによるトラックのソートと、一致の効果的な検索に対処する必要があります。 何時間も解決するよりも、すべてを手動で修正する方が速いと思われました =)
すべてがうまく機能します。 しかし、半自動モードでは、さらに調整する必要はありませんでした。

一方、私はそのようなルーチンに従事する代わりに多くを学びました。

何かを自動化する機会がある場合は、定期的に手作業に時間を費やすよりも、1回行うほうがよいでしょう。

Source: https://habr.com/ru/post/J52137/


All Articles