Archive for the 'iTunes' Category

2017/09/13 macOS 10.13, High Sierra 9/26リリース、iTunes 12.7

macOS 10.13, High Sierraが日本時間で2017/9/26にリリースされることが発表されました。巨大なバグはバグではなく仕様として開き直って、リリース後のアップデートでなんとかしようという話のようです(日本語音声読み上げバグは直らないことが決定)。

リリース日が予想よりも1か月早いですが、これには9〜10月に新ハードウェア(iMac Proとか)をリリースするための措置でしょう。あるいは、iOSデバイスをTouch bar化するApple純正アプリケーション(サードパーティ製は1年前から存在していた)をiOS11用に提供し、macOSのアップデートとタイミングを揃える必要があったとか(願望をこめた予想)。

一方で、本日iTunes 12.7がリリースされました。High Sierraよりもこちらの変更のほうが変動幅が大きいかもしれません。

 ・着信音(ringtone)をMac上のiTunes上で扱わなくなった
 ・ポップアップメニューから「iTunes U」が削除された
 ・iOSデバイスのモバイルアプリストアが削除された

iTunes 12.7でAppleScript用語辞書の変更はありません(用語辞書だけで比較)。画面上で削除された機能について、iTunes 12.7のAppleScript用語内には、

media kind alert tone / audiobook / book / home video / iTunesU / movie / song / music video / podcast / ringtone / TV show / voice memo / unknown — the media kind of the track

と、定義が残ったままです(このあたりいつものApple仕事。善意に解釈できないこともないものの、善意に解釈するとバカを見るところ)。

iPhoneの発表会で噂どおりの顔認識機能(Face ID)を搭載したiPhone Xが登場しました。予想どおり赤外線カメラを搭載し(可視光線からの画像だけでは顔認識の精度を上げられないので)ドットプロジェクタを併用しているため、OSレベルでのソフトウェアによる顔認識能力が上がったわけではなさそうです。

2017/09/08 iTunes Library上のsongでライブラリへの追加年を集計してKeynote書類上にグラフ作成

iTunesのMusic Libraryで楽曲のライブラリへの追加年で集計を行ってKeynote上にグラフを作成するAppleScriptです。6,775曲が登録されている自分のライブラリで集計→グラフ作成で3秒程度です。

itunes_usic.png

iTunes LibraryへのアクセスをiTunesLibrary framework経由で行い、NSCountedSetで集計を行うことで高速に処理を行ないます。

iTunesの基礎的な操作については電子書籍「iTunes Control」にて、Keynoteのグラフ作成については、電子書籍「Keynote Control with AppleScript」 △脳楮戮望匆陲靴討い泙后6縮がある方はぜひお買い求めください。

年々、楽曲を聴かない&買わなくなっている様子が見てとれますが、ほかの人はどんなもんなのか興味があります。

AppleScript名:iTunes Library上のsongでライブラリへの追加年で集計してKeynote書類上にグラフ作成
– Created 2017-09-06 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “iTunesLibrary”
–http://piyocast.com/as/archives/4816

property NSString : a reference to current application’s NSString
property NSArray : a reference to current application’s NSArray
property NSSortDescriptor : a reference to current application’s NSSortDescriptor
property NSDictionary : a reference to current application’s NSDictionary
property NSCountedSet : a reference to current application’s NSCountedSet
property ITLibrary : a reference to current application’s ITLibrary
property NSMutableArray : a reference to current application’s NSMutableArray

set yRec to retSongAddedYear() of me
–>  {{theName:2005, numberOfTimes:1907}….}

–楽曲のiTunesライブラリへの追加「年」のみ抽出
set yList to ((NSArray’s arrayWithArray:yRec)’s valueForKeyPath:“theName”) as list
–>  {2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017}

–楽曲のiTunesライブラリへの追加「年」ごとのカウントを抽出
set vList to ((NSArray’s arrayWithArray:yRec)’s valueForKeyPath:“numberOfTimes”) as list
–>  {1907, 1125, 853, 319, 638, 353, 351, 241, 605, 344, 71, 76, 28}

tell application “Keynote”
  set adoc to (make new document with properties {document theme:theme “ホワイト”, height:768, width:1024}) –Caution: theme name is **localized** (”White”)
  
tell front document
    set base slide of current slide to master slide “空白” –Caution: master slide name is **localized** (”Blank”)
    
tell current slide
      add chart row names {“ライブラリ追加年”} column names yList data {vList} type vertical_bar_2d group by chart row –row name is “iTunes Library Added Year”
    end tell
  end tell
  
activate
end tell

on retSongAddedYear()
  set library to ITLibrary’s libraryWithAPIVersion:“1.0″ |error|:(missing value)
  
if library is equal to missing value then return {}
  
  
set allTracks to library’s allMediaItems()
  
set allCount to allTracks’s |count|()
  
  
set anEnu to allTracks’s objectEnumerator()
  
set newArray to NSMutableArray’s alloc()’s init()
  
  
repeat
    set aPL to anEnu’s nextObject()
    
if aPL = missing value then exit repeat
    
try
      set aKind to (aPL’s mediaKind) as integer
      
if (aKind as integer) is equal to 2 then –Music, Song
        set pMonth to ((aPL’s addedDate() as date)’s year) as integer
        
newArray’s addObject:(pMonth)
      end if
    on error
      set aLoc to (aPL’s location’s |path|()) as string
    end try
  end repeat
  
  
return countItemsByItsAppearance(newArray) of me
end retSongAddedYear

–出現回数で集計
on countItemsByItsAppearance(aList)
  set aSet to NSCountedSet’s alloc()’s initWithArray:aList
  
set bArray to NSMutableArray’s array()
  
set theEnumerator to aSet’s objectEnumerator()
  
  
repeat
    set aValue to theEnumerator’s nextObject()
    
if aValue is missing value then exit repeat
    
bArray’s addObject:(NSDictionary’s dictionaryWithObjects:{aValue, (aSet’s countForObject:aValue)} forKeys:{“theName”, “numberOfTimes”})
  end repeat
  
  
–出現回数(numberOfTimes)で降順ソート
  
set theDesc to NSSortDescriptor’s sortDescriptorWithKey:“theName” ascending:true
  
bArray’s sortUsingDescriptors:{theDesc}
  
  
return bArray as list
end countItemsByItsAppearance

★Click Here to Open This Script 

2017/02/25 技術書典2で新刊書籍「iTunes Control」を頒布します

ぴよまるソフトウェアは、4月9日に秋葉原アキバ・スクウェアで開催される「技術書典2」(え-11)に出展。新刊電子書籍を販売します。

tbf2.png

新刊のタイトルは「iTunes Control」。iTunes+AppleScriptにおける「Hello World」体験を提供する本で、誰にでもわかり、誰にでもその実態を経験できるというもの。難易度も急に上がったりしません(Hop, Step, Jumpの3段階)。

book2.png

book3.png

book4.png

edama2さんに1か月前ぐらいに見せたら「前作からかわりすぎ!!!」と驚かれたので、「頭どうかしちゃったの?」「別人か?!」とかいうショックをやわらげるためにここに表紙その他を掲載しておきます(^ー^;;。

ブースではQRコードで書籍の販売を行い、販売したQRコードをスマホで読み取って販売元にメール送信すると、クラウドストレージにアップロードされた書籍のURLがメールで返送されてきます。

そして、この販売システム自体がAppleScriptで作ってあり、Mac上で稼働しているのです。

2017/01/07 iTunesライブラリの曲のアーティスト名を集計

iTunesライブラリ中に入っている「曲」(song)のアーティスト名を集計するAppleScriptです。

iTunesLibraryフレームワークを用いてライブラリにアクセスしているので、iTunes.appが起動している必要はありません。

アーティスト名については、ライブラリ中にかなりイレギュラーなデータが存在しているため、対策が必要でした。

・初期のiTunesで、CDからリッピングしたものの、CDDBに登録がなかったため、アーティスト名などが登録されていない→ エラートラップで対処

・アーティスト名で姓(last name)と名(first name)の間に空白が入っていたりいなかったりするなど、表記ゆらぎが存在していたため、ゆらぎを吸収

もう少し高速に実行できてもよさそうですが、ライブラリ中のtrackが8,100程度のときに、10回実行時の平均は2.8秒程度です(MacBook Pro Retina 2012)。

AppleScript名:iTunesライブラリの曲のアーティスト名を集計
– Created 2017-01-07 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “iTunesLibrary”
–http://piyocast.com/as/archives/4379

set library to current application’s ITLibrary’s libraryWithAPIVersion:“1.0″ |error|:(missing value)
if library is equal to missing value then return

set allTracks to library’s allMediaItems()
set allCount to allTracks’s |count|()

set anEnu to allTracks’s objectEnumerator()
set newArray to current application’s NSMutableArray’s alloc()’s init()

repeat
  set aPL to anEnu’s nextObject()
  
if aPL = missing value then exit repeat
  
try
    set aKind to (aPL’s mediaKind) as integer
    
    
if (aKind as integer) is equal to 2 then –Music, Song
      set plName to aPL’s artist’s |name| as string
      
set pl2Name to (my changeThis:” “ toThat:“” inString:plName) –日本語アーティスト名で姓と名の間にスペースが入っているものがある(表記ゆらぎ)ので対策
      
newArray’s addObject:(pl2Name)
    end if
  on error
    set aLoc to (aPL’s location’s |path|()) as string
    
log aLoc
  end try
end repeat

set aRes to countItemsByItsAppearance(newArray) of me
–>  {{theName:”浜田省吾”, numberOfTimes:442}, {theName:”B’z”, numberOfTimes:379}, {theName:”渡辺岳夫・松山祐士”, numberOfTimes:199}, {theName:”VariousArtists”, numberOfTimes:192}, {theName:”菅野よう子”, numberOfTimes:108}, {theName:”布袋寅泰”, numberOfTimes:100}, {theName:”三枝成彰”, numberOfTimes:95}, {theName:”宇多田ヒカル”, numberOfTimes:94}, {theName:”宮川泰”, numberOfTimes:81}, {theName:”MichaelJackson”, numberOfTimes:78}, {theName:”稲葉浩志”, numberOfTimes:73}, …

–出現回数で集計
on countItemsByItsAppearance(aList)
  set aSet to current application’s NSCountedSet’s alloc()’s initWithArray:aList
  
set bArray to current application’s NSMutableArray’s array()
  
set theEnumerator to aSet’s objectEnumerator()
  
  
repeat
    set aValue to theEnumerator’s nextObject()
    
if aValue is missing value then exit repeat
    
bArray’s addObject:(current application’s NSDictionary’s dictionaryWithObjects:{aValue, (aSet’s countForObject:aValue)} forKeys:{“theName”, “numberOfTimes”})
  end repeat
  
  
–出現回数(numberOfTimes)で降順ソート
  
set theDesc to current application’s NSSortDescriptor’s sortDescriptorWithKey:“numberOfTimes” ascending:false
  
bArray’s sortUsingDescriptors:{theDesc}
  
  
return bArray as list
end countItemsByItsAppearance

on changeThis:findString toThat:repString inString:someText
  set theString to current application’s NSString’s stringWithString:someText
  
set theString to theString’s stringByReplacingOccurrencesOfString:findString withString:repString options:(current application’s NSRegularExpressionSearch) range:{location:0, |length|:length of someText}
  
return theString as text
end changeThis:toThat:inString:

★Click Here to Open This Script 

2016/11/02 iTunesライブラリ中の楽曲のジャンルを集計して多い順にソートして出力

iTunesライブラリ中の楽曲のジャンルを集計して多い順にソートして返すAppleScriptです。

集計部分をCocoaで行っているので、集計部分自体が相当に高速なのですが、手元のMacBook Pro Retina 2012(Core i7 2.6GHz)で音声データが6,861件iTunesに登録されている環境で処理したところ、

  アプリケーション(iTunes)を直接呼び出し:3.5秒
  すべてフレームワーク経由で処理:0.03秒

と、アプリケーションを直接操作しないでフレームワーク経由で楽曲の情報を取得して処理するとアプリケーションへの問い合わせを行うよりも100倍以上高速です。

iTunes Music Library.xmlを読み取って処理してもだいたいフレームワーク経由の処理と同じかやや高速なぐらいに落ち着くと思われます。
補足:XML経由の処理はAppleScriptだと(Cocoaの機能を使っても)ムチャクチャ時間がかかりました。参考までに

ただ、処理結果が方法によってほんの微妙に変わるのはジャンル判定処理が異なるためでしょうか。やや、気になります。

GUIアプリ経由で情報を取得するのと、フレームワークを呼び出して情報を取得するのと、XMLを自力で解析するのとでは、提供してくれる機能が違うので、用途に応じて適切なものを取捨選択することになります。「現在再生中の曲」「曲リスト中で選択中のもの」といった情報が必要な場合にはGUIアプリ(iTunes)に問い合わせるのが正解です。

AppleScript名:iTunesライブラリ中の楽曲のジャンルを集計して多い順にソートして出力(アプリケーション呼び出し)
– Created 2016-10-30 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4301

tell application “iTunes”
  –set aList to genre of (every file track whose media kind is equal to song and genre is not equal to “”)
  
set aList to genre of every file track
end tell

set aRes to countItemsByItsAppearance(aList) of me
return aRes
–> {{theName:”サウンドトラック”, numberOfTimes:1721}, {theName:”ロック”, numberOfTimes:942}, {theName:”クラシック”, numberOfTimes:539},

–ジャンルのリストを出現回数で集計
on countItemsByItsAppearance(aList)
  set aSet to current application’s NSCountedSet’s alloc()’s initWithArray:aList
  
set bArray to current application’s NSMutableArray’s array()
  
set theEnumerator to aSet’s objectEnumerator()
  
  
repeat
    set aValue to theEnumerator’s nextObject()
    
if aValue is missing value then exit repeat
    
bArray’s addObject:(current application’s NSDictionary’s dictionaryWithObjects:{aValue, (aSet’s countForObject:aValue)} forKeys:{“theName”, “numberOfTimes”})
  end repeat
  
  
–出現回数(numberOfTimes)で降順ソート
  
set theDesc to current application’s NSSortDescriptor’s sortDescriptorWithKey:“numberOfTimes” ascending:false
  
bArray’s sortUsingDescriptors:{theDesc}
  
  
return bArray as list
end countItemsByItsAppearance

★Click Here to Open This Script 

AppleScript名:iTunesライブラリ中の楽曲のジャンルを集計して多い順にソートして出力(フレームワーク呼び出し)
– Created 2016-11-02 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “iTunesLibrary”
–http://piyocast.com/as/archives/4301

set library to current application’s ITLibrary’s libraryWithAPIVersion:“1.0″ |error|:(missing value)
if library is equal to missing value then return

set playLists to library’s allPlaylists()
set gArray to library’s allMediaItems()’s genre
set aRes to countItemsByItsAppearance(gArray) of me
–> {{theName:”サウンドトラック”, numberOfTimes:1722}, {theName:”ロック”, numberOfTimes:956}, {theName:”Podcast”, numberOfTimes:755},

–ジャンルのリストを出現回数で集計
on countItemsByItsAppearance(aList)
  set aSet to current application’s NSCountedSet’s alloc()’s initWithArray:aList
  
set bArray to current application’s NSMutableArray’s array()
  
set theEnumerator to aSet’s objectEnumerator()
  
  
repeat
    set aValue to theEnumerator’s nextObject()
    
if aValue is missing value then exit repeat
    
bArray’s addObject:(current application’s NSDictionary’s dictionaryWithObjects:{aValue, (aSet’s countForObject:aValue)} forKeys:{“theName”, “numberOfTimes”})
  end repeat
  
  
–出現回数(numberOfTimes)で降順ソート
  
set theDesc to current application’s NSSortDescriptor’s sortDescriptorWithKey:“numberOfTimes” ascending:false
  
bArray’s sortUsingDescriptors:{theDesc}
  
  
return bArray as list
end countItemsByItsAppearance

★Click Here to Open This Script 

2016/02/10 iTunesライブラリ内のメディアへのアクセス

iTunesのライブラリにアクセスして情報を取得するAppleScriptです。

AppleScriptでは一般的にiTunesに対して直接命令を実行して、選択中のトラックの情報を取得したり、さまざまな処理を行います。これが最も一般的です。

ただし、これだとスピードを稼げないため、外部にXML形式で保存されているiTunes Library(iTunes Music Library.xml)ファイルに直接アクセスして、一般的なXMLを扱うように処理する方法も存在しています。これも実際にASOCで試してみました。

iTunes 11以降がインストールされた環境では、iTunes Libraryへのアクセスフレームワーク「iTunesLibrary.framework」が利用でき、これを経由して間接的にiTunes Music Library.xmlにアクセスして情報の取得が行えます。本AppleScriptはこの方法を試してみたものです。

たいてい、AppleScriptでiTunesにアクセスして遅いのなんのと言われている場合には,力辰任△蝓iTunes登場直後から外部にXMLベースのライブラリ情報が書き出されていたことからも、大量のデータ取得には△諒法が推奨されてきたことが伺い知れます。それにもかかわらず、「わざわざ遅い方法を使って大量のデータを取得すると時間がかかる」というのは至極当然のことです。

ユーザーが選択したトラックの情報を取得するのであれば,鮖箸Δ里得策ですが、スピードを重視するのであれば△筬が、iTunes上でCD取り込みやMusic Storeからの楽曲購入に伴うデータ更新を考慮するのであればが適しているのではないかと思うものです。

AppleScript名:iTunesライブラリ内のメディアへのアクセス
– Created 2016-02-10 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “iTunesLibrary”

set library to current application’s ITLibrary’s libraryWithAPIVersion:“1.0″ |error|:(missing value)
if library is equal to missing value then return

set playLists to library’s allPlaylists()
set tracks to library’s allMediaItems()

set tracksTotal to tracks’s |count|()
log tracksTotal

repeat with i in tracks
  set j to contents of i
  
  set aTitle to j’s title()
  
set anArtist to j’s playCount()
  
end repeat

★Click Here to Open This Script 

2015/07/01 iTunes, iBooks Author, XcodeなどOS X 10.10.4に合わせてアップデート

OS X 10.10.4が公開され、同時にiTunes 12.2.0、iBooks Author 2.3、GarageBand 10.1、Xcode 6.4なども公開されました。

OS X 10.10.4では、既存のバグのうち直ったものもあれば直っていないものもあり・・・かつ長期的にテストするとやっぱり動いていないようなもの(Message.appのメッセージ受信などのイベントハンドラで実行するAppleScriptについては、長期間テストしてみると動かないケースもあったりで)もあり、10.10.x系列のバグ取りに協力すべきなのか10.11系列のテストに移行すべきなのかいまひとつはっきりしません。

とりあえず、AppleScript的に見た各アプリケーションの対応度の変化を調べてみました。用語辞書レベルではとくに変化はないように見えます(すべて前バージョンとdiffで比較してみました)。

iTunes 12.2

AppleScript用語辞書の内容について、前バージョンからの変化はありません。

iBooks Author 2.3

用語辞書はついているものの、アプリケーションの機能をほとんどサポートしておらず、「仕事しているフリ」というレベルです。前バージョンと変化はありません。現状では本アプリで行う仕事を自動化するのに役立つ機能はAppleScriptなどのOSA言語からは一切利用できません(書類のオープンとクローズができる程度)。

GarageBand 10.1

ものすごく割り切ったAppleScript用語辞書がついています。renderPreviewという1つの命令のみ実装されており、

renderPreview v : Render an iLife Preview for a project
 renderPreview [file] : Reference to the project

という内容のようですが、これが本当に役立つものかどうかは不明です。あと、説明がそっけなさすぎて「iLife Preview」の指すものが、GarageBandのファイルなのか、iPhoto/Photos、iTunesなどのiLife Applicationのデータなのかがよくわかりません。

Xcode 6.4

前バージョンからの変更点はAppleScript用語辞書的にはありません。Xcodeによる開発作業やプロジェクトの自動解析などに役立つレベルの実装にはなっていません。

2014/05/17 /Usersが消えなくな「らない」iTunes 11.2.1リリース

「Macを探す」をオンにしてあると/Usersディレクトリを不可視にするという謎のiTunes 11.2のリリースから1日、異例の早さでiTunes 11.2.1がリリースされました。

iTunes 11.2からAppleScript用語辞書の変更はありません。

OS X 10.9.3関連では……GUI Scriptingのclick at命令が(構文確認時に)エラーにならなくなりましたね。まだ、実行がきちんとできているのかは確認が必要ですが、構文確認時に「エラーにならなくなった」ということは確認できています。

2014/05/16 iTunes 11.2で用語辞書に微妙な変更

OS X 10.9.3とiTunes 11.2のアップデートがリリースされ、ひととおり(ざっくりレベルで)調べています。

「システムの時計が狂いまくる」という致命的かつ巨大な問題点が直ったのか直っていないのか、なかなか判断が難しいところですが、ntpへの問い合わせ自体はうまく動作しているように見えますし、いまのところNICTのホームページで調べても時間は合っているように見えます。

カレンダー.app(旧称iCal)とリマインダー.appの間でカレンダーが両方とも見境なく見えてしまうのは、もはや仕様ということなんだか……直す気も説明する気もないようです。

iTunes 11.2では、AppleScript用語辞書に不思議な属性値が新設されました。Applicationの属性値として、「iAd identifier」というread onlyの属性値が。

複数台のMacで同じiTunes Storeのアカウントでログインした状態でこの「iAd identifier」を比較してみたところ、同じ内容にはなりませんでした。個別のマシンを追跡するための属性値なのか、いまひとつ存在意義が分らないというか、エンドユーザーがそれを知ったところでメリットがなさそうなので、何かの「手違い」で用語辞書に載ったのではないかと推測しています。不思議ですね。

10.9.3については、/Usersディレクトリが不可視に設定されるという意味不明なバグがあったりと……βの時には起こっていなかったことがなぜリリース時に起こるのか、理解に苦しみます。

スクリプト名:iTunes 11.2でiAd Identifierが追加された
tell application “iTunes”
  properties
  
–> {class:application, name:”iTunes”, player state:playing, version:”11.2″, frontmost:false, sound volume:84, mute:false, visuals enabled:false, full screen:false, visual size:large, EQ enabled:false, fixed indexing:false, player position:547.338012695312, converting:false, current stream title:missing value, current stream URL:missing value, AirPlay enabled:false, current AirPlay devices:{AirPlay device id 26 of application “iTunes”}, iAd identifier:”XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX”}
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2013/05/19 iTunes 11.0.2〜11.0.3 AppleScript系変更点まとめ

iTunes史上最大のAppleScript系機能の変更・拡充が行われた、iTunes 11.0.3およびその1つ前のバージョンである11.0.2の変更点をまとめてみました。

■iTunes 11.0.2
device playlistが廃止された

■iTunes 11.0.3
propertiesで各種オブジェクトの属性情報をまとめて取得できるようになった。

AirPlayの制御のためのオブジェクトと属性情報が用意された。
AirPlay enabled:アプリケーションの属性。AirPlayが使用可能だとtrue
current AirPlay devices:AirPlayで使用中のデバイスを示すアプリケーションの属性。
AirPlay device:AirPlayデバイス。nameやindexで識別可。各種属性値を持つ。

player position:現在再生中のTrackの再生位置(秒)。従来はintegerでしか取得/指定できなかったものが、小数点以下の情報まで扱えるようになった

special kind:playlistのspecial kindから、 「Party Shuffle」が削除された

device:sourceのkindから「device」が削除された

device playlist:sourceに含まれるplaylistの中から「deveice playlist」が削除された

device track:playlistに含まれるtrackから「device track」が削除された

iTunes U:trackに属性値「iTunes U」が追加された(read only)

home video:trackの属性値にvideo kindに「home video」が追加された

2013/05/17 iTunes 11.0.3で出力可能なすべてのAirPlay Deviceに同時出力する

iTunes 11.0.3以降で、現在出力可能なAirPlay Deviceすべてを出力先に指定し、音声の同時出力を行うAppleScriptです。

airplay2.png

MacBook Pro Retina本体と、無線LAN経由でつながっている居間のApple TVに同時に出力を行わせて……もちろん、無線LAN経由なので、出力デバイスごとに若干のディレイは発生しますが、ちょっと面白い感じ(エコー?)がしていいと思います。

スクリプト名:iTunes 11.0.3で出力可能なすべてのAirPlay Deviceに同時出力する
tell application “iTunes”
  set dList to every AirPlay device
  
set current AirPlay devices to dList
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2013/05/17 iTunes 11.0.3でアプリケーションの状態を取得する

iTunes 11.0.3がリリースされ、AppleScript関連で大幅な改修が行われました。iTunesのAppleScript系の機能においては、過去最大の改修といってもよいかもしれません。

iTunes 11.0.2まではずーーーーーーっとできなかった、各種属性を「properties」でまとめて取得する記法を受け付けるようになりました。

スクリプト名:iTunes 11.0.3でアプリケーションの状態を取得する
tell application “iTunes”
  properties
end tell

–> {class:application, name:”iTunes”, player state:stopped, version:”11.0.3″, frontmost:false, sound volume:100, mute:false, visuals enabled:false, full screen:false, visual size:large, EQ enabled:false, fixed indexing:false, player position:missing value, converting:false, current stream title:missing value, current stream URL:missing value, AirPlay enabled:false, current AirPlay devices:{AirPlay device id 26 of application “iTunes”}}

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

もちろん、Trackのpropertiesなども取れます。いままでの、かったるいiTunes Scriptingとは雲泥の差です。

さらに、AirPlayの状態取得や設定が行えるようになりました。

スクリプト名:iTunes 11.0.3でAirPlay Deviceすべての詳細情報を取得する
tell application “iTunes”
  set dList to every AirPlay device
  
–> {AirPlay device id 26, AirPlay device id 88476}
  
  
repeat with i in dList
    set j to contents of i
    
    
properties of j
    
    
–> {class:AirPlay device, id:26, index:1, name:”コンピュータ”, persistent ID:”0000000000000000″, active:false, available:true, kind:computer, network address:missing value, protected:false, selected:true, supports audio:true, supports video:true, sound volume:100}
    
    
–> {class:AirPlay device, id:88476, index:2, name:”Apple TV”, persistent ID:”00005855CA413D01″, active:false, available:true, kind:Apple TV, network address:”58:55:ca:41:3d:01″, protected:false, selected:false, supports audio:true, supports video:true, sound volume:100}
    
  end repeat
  
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

airplay1.png

スクリプト名:iTunes 11.0.3で指定可能なAirPlay Deviceから選択して、AirPlay出力先を指定する
tell application “iTunes”
  
  
set dList to every AirPlay device
  
set nList to name of every AirPlay device
  
  
set aSel to choose from list nList
  
set aaSel to first item of aSel
  
  
set current AirPlay devices to AirPlay device aaSel
  
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

AirPlayの状態も取得できます。ただし、この「AirPlay Enabled」というアプリケーションの属性値がRead Onlyなので、AirPlayの状態を解除する方法の模索が必要です。

スクリプト名:iTunes 11.0.3でAirPlayの状態を取得する
tell application “iTunes”
  set airPF to AirPlay enabled
  
–> false
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

一応、AirPlay Deviceを「コンピュータ」にすればAirPlay Offと似た状態になるようなので、そこから先に何かをすべきなのかもしれません。

AirPlayの出力先デバイスの変更は、再生中にも行うことができました。

スクリプト名:iTunes 11.0.3で現在利用可能なAirPlayデバイス一覧を取得する
tell application “iTunes”
  set curAirPlay to current AirPlay devices
  
–> {AirPlay device id 26 of application “iTunes”}
  
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2012/06/20 Sandbox対応したiTunes 10.6.3の挙動の変化

iTunes 10.6.3はこれまでにリリースされたiTunesとは若干挙動が変わっていることを確認していました。どこが違うのかといえば、Mac OS X 10.6.8および10.7.4上でASDictionaryを使ってAppleScript用語辞書をHTMLに書き出すことができないという点です。

もともとASDictionaryは、「appscript」ベースのscript開発のために、AppleScript用語辞書を異なる言語(RubyとかPythonとか)のフォーマットでHTML書き出しすることを目的として作成されたものでした。OSやアプリケーションのバージョン間のAppleScript用語辞書差分検出のために使うというのは、本来のASDictionaryの目的とは異なる用途といえます(すごく役立っています)。

asdic.png

appscriptとは、アプリケーションの操作をRubyやPythonなどの言語処理系に提供するためのもので、AppleScriptの枠組みとは異なる仕組みでAppleScriptと同様の機能を他の言語処理系に提供するためのもの。同じ処理を行うにしても「AppleScript上で処理するよりも速い」といった評判がありました。また、AppleScript自体を習得しなくても、RubyやPythonの知識があればアプリケーションのコントロールが行えるという、RubyやPython系開発者にとってのメリットも存在しました。

appscript自体の将来性について多角的に考察・検討した時期もあったのですが、これがApple純正の枠組みではないため、「将来のOSアップデート時に動かなくなる可能性が高い」と考えられたのと、あくまで極地的な動きでありApple内部やアプリ開発者全体に波及するものではない、という結論に。

国内のScripterとの間で議論も行ったのですが、やはり「すべてを置き換えるためのコストが大きすぎる」点が懸念されました。日本国内はともかく、海外ではAppleScriptに慣れ親しんでいるユーザーやソリューションデベロッパーが大量に存在しているため、いまさらゼロから教育を行うための膨大なコストをAppleが支払うことはしないだろうというのが理由の1つ。

また、アプリケーションを外部からコントロールするタイプの一般的なAppleScriptは言うに及ばず、アプリケーション内に埋め込んで使っているAppleScriptや、アプリケーション独自のScript Menu内から呼び出すタイプのAppleScriptなどなど、OS・アプリケーション内のいたるところに存在しているために、それらをすべて移行させるのは無理(コストに見合わない)だろうという話になりました。

実際、appscriptの仕組み自体がCarbon Apple Event Managerという古いOSのAPIを利用したものであったため、Carbon Apple Event ManagerがMac OS X 10.6以降でサポートされないことがAppleによって表明されると、appscriptの開発およびサポートは中止となりました

appscript1.png

先日、「iTunes 10.6.3 changes AppleScript interface?」と題した海外のBBSの投稿があり、appscript経由でiTunes 10.6.3上の選択状態にあるトラックの情報(AppleScriptでいうところのselection)の取得が行えないという話が出ていました(iTunes 10.6.3上のselectionの取得はAppleScriptからは問題なく行えます)。

このケースでは、すでにサポート外になったCarbon Apple Event Managerを呼んでいるappscriptを利用していること自体が問題ですし、そういう問題が発生しても文句を言えた種類のものではないでしょう。

一方で、ASDictionaryがCarbon Apple Event Managerを用いてAppleScript用語辞書にアクセスしているのか、あるいはSandboxの仕組み上、アプリケーションファイルへのアクセスが限定されたためにHTML書き出しが(Mac OS X 10.6および10.7上で)できないのか、そのあたりははっきりとはしませんが……これから登場してくる「Sandbox化されたアプリケーション」の挙動が、ターゲットOS(Mac OS X 10.8, Mountain Lion)上とそれ以前のOS(10.7, 10.6)上で異なってくる可能性があることを意識する必要があることでしょう。

2012/04/21 iPhoto, iTunes, Safariアップデートについて

iPhoto 9.2.3、iTunes 10.6.1、Safari 5.1.5の各アップデートが提供されていますが、これらのアプリケーションのAppleScript用語辞書に変更はありません。

2012/03/07 InDesign CS3で指定のオプジェクトを、JPEG書き出ししてiPhoneへ

InDesign CS3上で指定したオブジェクトをJPEG書き出ししてiPhoneに転送するAppleScriptです。

ことのはじまりは、目下開発中のiPhoneアプリ(私はプロジェクト管理やら仕様書書きやらを)で、Welcome画面の表示を行うのに「文字詰めや行送りをいろいろ指定できないと!」という話になったこと。

……そもそも、iPhoneの文字表示部品に、そんな気の利いたものはありません。そこで、InDesignやらIllustrator上で気の済むまで行間や文字間にこだわっていただいて、それをそのまま「画像」として書き出して表示しようではないか、と。

ただし、その指定内容をすぐにiPhoneの実機で見たいという話に。

その場で10分もかけずにInDesign書類上の指定レイヤー(「コンテンツ」)上に存在する指定名称(スクリプトラベル「screen」)のグループをJPEG書き出しして、書き出したJPEG書類をiPhotoにインポートして、iTunesに命令して接続しているすべてのiOSデバイスにシンクロを行うようAppleScriptで指令を出すようにしてみました。

できた瞬間はかなりガッツポーズでしたが、冷静に考えるとInDesignから書き出されるJPEG画像のクオリティが「残念なレベル」です。また、シンクロが終わるまでにちょっと時間がかかるので、実用性がいまひとつ。

結局、Good Reader for iPhoneをインストールして、iTunes経由でGood Readerに対してInDesignから書き出したPDFを渡す、という方法に落ち着きました。本Scriptは何らかの「可能性」を感じさせてくれはしたのですが、結局おクラ入りに。

スクリプト名:InDesign CS3で指定のオプジェクトを、JPEG書き出ししてiPhoneへ
–v1 InDesign CS3から直接JPEG書き出し。画像クオリティが低くて難あり

set dtPath to (path to desktop) as string
set fName to do shell script “date +%Y%m%d%H%M%S”

set fullPath to dtPath & fName & “.jpg”
set fullPathPOSIX to POSIX path of fullPath

tell application “Adobe InDesign CS3″
  tell document 1
    tell layer “コンテンツ”
      set aList to every group whose label is equal to “screen”
    end tell
    
    
set expItem to contents of first item of aList
    
export expItem format JPG to fullPath without with grids
    
  end tell
end tell

–iPhotoに書き出したJPEGファイルをインポートする
tell application “iPhoto”
  import from fullPathPOSIX
end tell

–アップデート可能なiOSデバイスをアップデートする
tell application “iTunes”
  repeat with i in sources
    if (kind of i is iPod) then update i
  end repeat
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2011/11/20 Xcode 4.2.1、iTunes 10.5.1登場。AS用語辞書に変更なし

Xcodeのバージョン4.2.1、およびiTunesのバージョン10.5.1が登場しています。
ともにAppleScript用語辞書の内容に変更はありません。

2011/10/18 指定アプリの指定タグの文字列をアプリ内のLocalizableStringsから取得する v3

バンドルIDを指定してアプリケーションのパスを求め、その中のローカライズ文字列テーブルから指定ラベルに該当する文字を取り出すAppleScriptの改良版です。

プロセスを確認して、起動中であればプロセスから情報を取得。起動中ではない場合には、Finder経由で実行ファイルのパスを求めるようにしています。

スクリプト名:指定アプリの指定タグの文字列をアプリ内のLocalizableStringsから取得する v3

set aRes to retLocalizedStringFromApp("135.006", "com.apple.itunes") of me
–> "ライブラリ"–Japanese
–> "LIBRARY"–English
–> "BIBLIOTHÈQUE"–French
–> ""–Simply Chinese
–> "資料庫"–Traditional Chinese
–> "MEDIATHEK"–Deutsch

–指定バンドルIDのアプリケーション内のResourcesフォルダの中の現在のロケールのフォルダ内のLocalizable.strings内の指定タグに対応する値を取得
–iTunesのような「不適切なローカライズ」に対応するために、リソース内のローカライズデータからオブジェクト名を取得
on retLocalizedStringFromApp(locLabel, bundleID)
  
  
set pRes to retExistenceOfProcessByBundleID(bundleID) of me
  
  
if pRes is not equal to false then
    –指定Bundle IDのプロセスが起動していた場合
    
tell application "System Events"
      tell pRes
        set appFile to application file
      end tell
    end tell
    
  else
    –指定Bundle IDのプロセスが起動していなかった場合
    
tell application "Finder"
      try
        set appFile to application file id bundleID
      on error
        return
      end try
    end tell
    
    
set appFile to appFile as alias
  end if
  
  
  
set aStr to localized string locLabel in bundle appFile
  
end retLocalizedStringFromApp

–指定のバンドルIDのプロセスが起動していればプロセスへの参照を返す、なければfalseを返す
on retExistenceOfProcessByBundleID(bundleID)
  tell application "System Events"
    set aProc to every process whose bundle identifier is equal to bundleID
    
if aProc = {} then return false
    
    
set aProc to contents of first item of aProc
    
return aProc
  end tell
end retExistenceOfProcessByBundleID

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

本ルーチンを使って、iTunesの「ライブラリ」に該当する文字列を取り出すテストを行い、実際に使用ユーザー環境の言語を変更してログインし直し、各言語で動作確認を行ってみました。

スクリプト名:iTunes_control_Japanese
tell application “iTunes”
  tell source “ライブラリ”
    tell playlist “ライブラリ”
      count every track
    end tell
  end tell
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

スクリプト名:iTunes_control_English
tell application “iTunes”
  tell source “LIBRARY”
    tell playlist “LIBRARY”
      count every track
    end tell
  end tell
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

スクリプト名:iTunes_control_Deteuch
tell application “iTunes”
  tell source “MEDIATHEK”
    tell playlist “MEDIATHEK”
      count every track
    end tell
  end tell
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

スクリプト名:iTunes_control_French
tell application “iTunes”
  tell source “BIBLIOTHÈQUE”
    tell playlist “BIBLIOTHÈQUE”
      count every track
    end tell
  end tell
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

スクリプト名:iTunes_control_Chinese (simplified)
tell application “iTunes”
  tell source
    tell playlist
      count every track
    end tell
  end tell
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

スクリプト名:iTunes_control_Chinese (traditional)
tell application “iTunes”
  tell source “資料庫”
    tell playlist “資料庫”
      count every track
    end tell
  end tell
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

……で、冒頭のScriptを使うと、これらの各言語環境ごとにバラバラのオブジェクト名を記述しなければならなかった部分が、1本のScriptでカバーできるはずです。

スクリプト名:指定アプリの指定タグの文字列をアプリ内のLocalizableStringsから取得する v3.1
–すべての言語環境でこのプログラムに統一できるはず
set aRes to retLocalizedStringFromApp(“135.006″, “com.apple.itunes”) of me

tell application “iTunes”
  tell source aRes
    tell playlist aRes
      count every track
    end tell
  end tell
end tell

–指定バンドルIDのアプリケーション内のResourcesフォルダの中の現在のロケールのフォルダ内のLocalizable.strings内の指定タグに対応する値を取得
–iTunesのような「不適切なローカライズ」に対応するために、リソース内のローカライズデータからオブジェクト名を取得
on retLocalizedStringFromApp(locLabel, bundleID)
  
  
set pRes to retExistenceOfProcessByBundleID(bundleID) of me
  
  
if pRes is not equal to false then
    –指定Bundle IDのプロセスが起動していた場合
    
tell application “System Events”
      tell pRes
        set appFile to application file
      end tell
    end tell
    
  else
    –指定Bundle IDのプロセスが起動していなかった場合
    
tell application “Finder”
      try
        set appFile to application file id bundleID
      on error
        return
      end try
    end tell
    
    
set appFile to appFile as alias
  end if
  
  
  
set aStr to localized string locLabel in bundle appFile
  
end retLocalizedStringFromApp

–指定のバンドルIDのプロセスが起動していればプロセスへの参照を返す、なければfalseを返す
on retExistenceOfProcessByBundleID(bundleID)
  tell application “System Events”
    set aProc to every process whose bundle identifier is equal to bundleID
    
if aProc = {} then return false
    
    
set aProc to contents of first item of aProc
    
return aProc
  end tell
end retExistenceOfProcessByBundleID

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2011/10/18 指定アプリの指定タグの文字列をアプリ内のLocalizableStringsから取得する

Amazonダウンローダー内でAppleScriptを使っている箇所があり、案の定、オブジェクト名までローカライズされているiTunesの特性を理解せずに作られているために、日本語環境ではまともに動かなくて大笑いしましたが……このような悲劇が起こらないように、いろいろ考えておりました。

結局のところ、アプリケーションのバンドル内のResourcesフォルダの各言語フォルダの中に入っているLocalizable.stringsファイル内から該当するデータを取り出せればよいのだろうか、と考えました。

locali.jpg

そこで、実際にLocalizable.stringsを調査して、実際にオブジェクト名に該当するものを探しだし、ラベルを指定して取り出せるようにしてみました。

Localizable.stringsには文字定数とか画面に表示する文字列なんかを入れておくわけで、このケースでも画面上に「ライブラリ」と表示するためのデータが格納されているわけですが、それがAppleScriptのオブジェクト名と同じであるために、結果オーライで取り出してみることにしました。

本バージョンでは、アプリケーション名とLocalizable.strings内のラベルを指定します。対象のアプリケーションが起動していることが実行条件です。

スクリプト名:指定アプリの指定タグの文字列をアプリ内のLocalizableStringsから取得する

set aRes to retLocalizedStringFromApp(“135.006″, “iTunes”) of me

on retLocalizedStringFromApp(locLabel, appName)
  
  
launchAnApp(appName) of me
  
  
tell application “System Events”
    set aProc to process appName
    
if aProc = “” then return
    
    
tell aProc
      set appPath to application file
    end tell
  end tell
  
  
set aStr to localized string locLabel in bundle appPath –ライブラリ
  
end retLocalizedStringFromApp

on launchAnApp(appName)
  tell application appName to launch
end launchAnApp

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2011/10/12 iTunes10.5が登場。AppleScript用語辞書に変更なし

iCloudへの対応など新機能を盛り込んだiTunes 10.5が公開されました。さっそく、AppleScript用語辞書を前バージョンのiTunes 10.4.1と比較してみたところ、差異はとくにありませんでした。

2011/06/07 iTunes 10.3β AppleScript用語辞書に変更なし

本日、β版が公開されたiTunes 10.3のAppleScript用語辞書を現行のiTunes 10.2.2と比較してみたところ、変更点がないことを確認しました。

いろんな意味で、ドキドキさせられます。

追記:
iTunes 10.3.1βでもAppleScript用語辞書には変更はありませんでした。

2010/11/13 iTunes 10.1アップデート、AppleScript用語辞書に変更なし

ソフトウェア・アップデート経由でiTunes 10.1アップデートがリリースされました。早速、AppleScript用語辞書をHTMLに書き出して前バージョンとのdiffを取ってみたところ、とくに変更はありませんでした。

最近では、iTunes 7.6.2と9.1で変更(追加)があったぐらいで、用語辞書にはほとんど変更はありません。

2010/11/10 選択中のtrackのうち再生済みのものを削除する

iTunesで選択中のtrackのうち、再生済みのものを削除するAppleScriptです。

Podcastで、ダウンロード先が変更になって……それを知らずにすべてのエピソードをダウンロードしてしまった場合、すべてのエピソードが2つ存在してしまいます。

itunes.jpg

こういうケースでは、旧ダウンロード先から落としてきたエピソード(再生ずみ)を削除し、新ダウンロード先のtrackを残しておくことになるわけで……そのために、再生ずみのtrackのみ削除するAppleScriptを作成したものです。

iTunesといえば、Amazonダウンローダー内でAppleScriptによりtrackの追加を行っているものの、ライブラリ名を英語で書いてしまったため日本語環境でうまく動いていないという悲劇がそこかしこで報告されています。日本語環境できちんと動作検証しないでリリースしてしまったAmazonに合掌(iTunes上でのオブジェクト名を日本語環境に合わせて書き直さないといけない、という間抜けな仕様を作ったAppleにも合掌)。

amazon_bug.jpg

スクリプト名:選択中のtrackのうち再生済みのものを削除する
tell application “iTunes”
  set aList to selection
  
  
repeat with i in aList
    set aP to unplayed of i
    
if aP = false then
      ignoring application responses
        delete i
      end ignoring
    end if
  end repeat
  
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2010/09/02 iTunes 10でAppleScript用語辞書に変更なし

9/1の発表会で紹介され、その日……のうちギリギリで? ダウンロード可能になったiTunes 10。インストールして真っ先に行うのはAppleScript用語辞書が変更されているかのチェック。大規模な変更があった場合には、さまざまなプログラムを山ほど書き直さなくてはなりません。

it10_1.jpg

it10_2.jpg

HTMLに書き出して比較してみたところ、前バージョンからとくに変更点はない(0箇所)ということが分りました。

とりあえず、辞書上では変更がないということであり、挙動が変わっていないかどうかはこれからじっくり調べることになるでしょう。

2010/03/31 iTunes 9.1で用語辞書に変更アリ

iTunes 9.1がリリースされました。iPadのサポートが主な内容とのことですが、AppleScript用語辞書にも一部(だけ)変更が加わっています。

playlistのspecial kind属性の値が、

 Audiobooks → Books
 Videos → TV Shows

にそれぞれ変更されました。また、Genius、iTunes U、Libraryといった属性値が追加されています。

itunes91.jpg