Archive for 4月, 2015

2015/04/23 Macのモデル名を返す

Macのモデル名を返すAppleScriptです。Mac Pro/Mac mini/iMac/MacBook Pro/MacBook Air/MacBook などのざっくりしたモデル名(マシン種別)です。

AppleScript名:Macのモデル名を返す
–By Christopher Stone <listmeister@thestoneforge.com>
–2011/09/15

set aModelName to getModelName()
–> "MacBook Pro"

on getModelName()
  # Keeping the hardware data record:
  
set hardwareData to do shell script "system_profiler SPHardwareDataType" without altering line endings
  
set cmd to "sed -nE ’/Model Name/p’ <<< " & quoted form of hardwareData & " | sed -E ’s/^ +//’"
  
set macModel to do shell script cmd
  
  
# One-liner:
  
set macModel to do shell script "system_profiler SPHardwareDataType | sed -nE ’/Model Name/p’| sed -E ’s/^ +//’"
  
  
return (text 13 thru -1 of macModel) –Skip "Model Name: " strings
  
end getModelName

★Click Here to Open This Script 

2015/04/22 Spotlight検索インデックスを再生成

起動ディスクのSpotlight検索インデックスを再生成するAppleScriptです。ふつうに、スクリプトエディタ上で実行するものです。実行時に管理者パスワードの入力を求められます。

さまざまなマシン環境を見たときに、Spotlightの検索インデックスが「壊れている」マシンを見かけることがあります。こうなると、mdfindコマンドでspotlightの機能を呼び出して、指定のファイルを見つけ出す処理が有効に機能しません。このような場合には、インデックスの再生成が必要になります。

Spotlightのインデックス再生成は、システム環境設定で行うようになっており、そのものズバリの名前がついていないため、ひじょうに分かりにくくなっています。

そのため、説明を省くことを目的にAppleScriptで書いておきました。Terminalが使えないユーザーでも、スクリプトを実行するだけなら可能でしょう。

ただし、Spotlight復旧のためにはSpotlightのインデックス再生成のほか、ディスクユーティリティーで「ユーザー権限の修復」を行う必要があったり、そもそも起動ディスクの一部のセクタが損傷しているケースなどもあり、「万能薬」ではないことに注意が必要です。

AppleScript名:Spotlight検索インデックスを再生成
do shell script “mdutil -E /” with administrator privileges

★Click Here to Open This Script 

2015/04/18 「戦場の絆ポータブル」の対戦ステージと対戦日時のデータを取り出す

PSPのゲーム「戦場の絆ポータブル」のリプレイデータから、対戦ステージと対戦日時を取り出すAppleScriptです。

リプレイデータにはタイムスタンプがついているので、日時については取り出すことが可能です。

psp10.png

しかし、どこのステージで対戦したかについては、とくに見分けるための情報が用意されていないため・・・すべてのリプレイデータに入っている、ステージのサムネイル画像(ICON0.PNG)に注目。

icon0.PNG

これらサムネイル画像は、すべてのステージにおいて同一のファイル名で記録されるため、ファイル名では見分けられませんが、画像データ内容は明らかに異なっています。

そこで、各画像のsha-1のハッシュ値をあらかじめ計算(別に明確に見分けるための値ならなんでもいいので、とくにsha-1の選択は根拠レス)しておき、指定フォルダ以下の「ICON0.PNG」ファイルのハッシュ値を計算して、それぞれのステージ画像のハッシュ値と比較。ハッシュ値が同じかどうかで判定を行っています。

保存されているパラメータデータらしきものをバイナリレベルで解析すれば、もう少し詳しい情報が出てくると思いますが、リバースエンジニアリングするほどの暇はなかったので、とりあえずこのレベルで満足しています(数十分で書いたし)。

とりあえず、かんたんなエラー報告(ログ出力)をつけておきましたが、判定でミスが起こったことはないようです。

yeyayay.PNG
▲ニューヤーク:ハッシュ値=dbb9e8e26e96dbb4dd3198e55b6cde41aba8e0a8

yuyye.PNG
▲サイド7:ハッシュ値=be22fa949bfd78b0cd97596929f07ce4ec501d7b

uaoo.PNG
▲鉱山都市:ハッシュ値=72f35456504b1957ec85fb6a1597ac1a2baa2ee9

yeyeyoyeyo.PNG
▲トリントン:ハッシュ値=9f080853dac45ecaf1672ff2230f2b9a80a00eb4

yyiyeyyayeyyo.PNG
▲グレートキャニオン:ハッシュ値=9de93e8b853fe153bc73066fb07481c774499960

yyayoyiai.PNG
▲ジャブロー地下:ハッシュ値=a93550099419f52444cf77366773192d0bf5f848

yoythyeya.PNG
▲ヒマラヤ:ハッシュ値=877f998d608dd267c380e59a17b2a95a139baef5

yyyeythyyocu.PNG
▲タクラマカン砂漠:ハッシュ値=5284dc5f0f7a53ee5677908f66da1e00b80f76b6

yyayoyiaia.PNG
▲ジャブロー地上:ハッシュ値=8c4ee44e8f2fbcbf061e6d5ea2b202b08f42c59a

imgphp.jpeg
▲取得したデータから、ステージごとの対戦割合をグラフ化してみた

AppleScript名:チェックサム値から、メモリースティックに保存されたReplay Dataのステージ名とプレイ日時を求める
– Created 2015-04-17 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

–New Yark
set sha1 to “dbb9e8e26e96dbb4dd3198e55b6cde41aba8e0a8″
–鉱山都市
set sha2 to “72f35456504b1957ec85fb6a1597ac1a2baa2ee9″
–グレートキャニオン
set sha3 to “9de93e8b853fe153bc73066fb07481c774499960″
–サイド 7
set sha4 to “be22fa949bfd78b0cd97596929f07ce4ec501d7b”
–タクラマカン砂漠
set sha5 to “5284dc5f0f7a53ee5677908f66da1e00b80f76b6″
–トリントン・タワー
set sha6 to “9f080853dac45ecaf1672ff2230f2b9a80a00eb4″
–ジャブロー地下
set sha7 to “a93550099419f52444cf77366773192d0bf5f848″
–ヒマラヤ
set sha8 to “877f998d608dd267c380e59a17b2a95a139baef5″
–ジャブロー地上
set sha9 to “8c4ee44e8f2fbcbf061e6d5ea2b202b08f42c59a”

set shaList to {sha1, sha2, sha3, sha4, sha5, sha6, sha7, sha8, sha9} –Hash List
set stageList to {“ニューヤーク”, “鉱山都市”, “グレートキャニオン”, “サイド 7″, “タクラマカン砂漠”, “トリントン・タワー”, “ジャブロー地下”, “ヒマラヤ”, “ジャブロー地上”} –Stage Name List

set apPath1 to choose folder with prompt “リプレイデータが入っているフォルダを選択してください”
set findName to “ICON0.PNG”
set aRes to getFileListWithSpotLight(“kMDItemFSName”, findName, apPath1) of me

set outList to {}
repeat with i in aRes
  set j to contents of i
  
set sumRes to calcSHA1(j) of me
  
  
–チェックサムからステージ名を検索する
  
set hitF to false
  
set aCounter to 1
  
repeat with ii in shaList
    set jj to contents of ii
    
if sumRes = jj then
      set hitF to true
      
exit repeat
    end if
    
set aCounter to aCounter + 1
  end repeat
  
  
if hitF = true then
    tell application “Finder”
      set cDat to (creation date of j) as string
    end tell
    
set tmpList to {contents of item aCounter of stageList, cDat}
    
    
if tmpList is not in outList then
      set the end of outList to tmpList
    end if
  else
    log sumRes
  end if
  
end repeat

set out2List to shellSortListAscending(outList, 2) of me

set aText to retItemDelimedAndParagraphDelimedText(out2List, tab, return) of me

–mdfindで指定フォルダ以下にあるすべての指定名称の書類を取得
on findAdocFromAfolder(aPath, findName)
  set origList to getFileListWithSpotLight(“kMDItemFSName”, findName, aPath) of me
  
if length of origList = 1 then return contents of first item of origList
  
return length of origList
end findAdocFromAfolder

–指定階層下で、指定メタデータが指定パラメータであるファイルを取得(alias list)
on getFileListWithSpotLight(aMetaDataItem, aParam, startDir)
  
  
set sDirText to quoted form of POSIX path of startDir
  
set shellText to “mdfind ’” & aMetaDataItem & ” == \”" & aParam & “\”’ -onlyin “ & sDirText
  
try
    set aRes to do shell script shellText
  on error
    return {}
  end try
  
set pList to paragraphs of aRes
  
set aList to {}
  
repeat with i in pList
    set aPath to POSIX file i
    
set aPath to aPath as alias
    
set the end of aList to aPath
  end repeat
  
return aList
end getFileListWithSpotLight

–SHA-1 digestを求める
on calcSHA1(aFile)
  set aRes to do shell script “/usr/bin/openssl sha1 “ & quoted form of the POSIX path of the aFile
  
set anOffset to offset of “)= “ in aRes
  
if anOffset = 0 then return false –エラー時
  
set bRes to text (anOffset + 3) thru -1 of aRes
  
return bRes
end calcSHA1

–シェルソートで入れ子のリストを昇順ソート
on shellSortListAscending(a, keyItem)
  set n to length of a
  
set cols to {1391376, 463792, 198768, 86961, 33936, 13776, 4592, 1968, 861, 336, 112, 48, 21, 7, 3, 1}
  
repeat with h in cols
    if (h (n - 1)) then
      repeat with i from h to (n - 1)
        set v to item (i + 1) of a
        
set j to i
        
repeat while (j h) and ((contents of item keyItem of item (j - h + 1) of a) > (item keyItem of v))
          set (item (j + 1) of a) to (item (j - h + 1) of a)
          
set j to j - h
        end repeat
        
set item (j + 1) of a to v
      end repeat
    end if
  end repeat
  
return a
end shellSortListAscending

–シェルソートで入れ子のリストを降順ソート
on shellSortListDecending(a, keyItem)
  set n to length of a
  
set cols to {1391376, 463792, 198768, 86961, 33936, 13776, 4592, 1968, 861, 336, 112, 48, 21, 7, 3, 1}
  
repeat with h in cols
    if (h (n - 1)) then
      repeat with i from h to (n - 1)
        set v to item (i + 1) of a
        
set j to i
        
repeat while (j h) and ((contents of item keyItem of item (j - h + 1) of a) < (item keyItem of v))
          set (item (j + 1) of a) to (item (j - h + 1) of a)
          
set j to j - h
        end repeat
        
set item (j + 1) of a to v
      end repeat
    end if
  end repeat
  
return a
end shellSortListDecending

–CSV書き出し
–ただし、データ内にダブルクォートが入っていた場合に備えてのサニタイズ処理は行っていない
on saveAsCSV(aList, aPath)
  set crlfChar to (ASCII character 13) & (ASCII character 10)
  
set LF to (ASCII character 10)
  
set wholeText to “”
  
repeat with i in aList
    set aLineText to “”
    
set curDelim to AppleScript’s text item delimiters
    
set AppleScript’s text item delimiters to “\”,\”"
    
set aLineList to i as text
    
set AppleScript’s text item delimiters to curDelim
    
    
set aLineText to repChar(aLineList, return, “”) of me –データの途中に改行が入っていた場合には削除する
    
set aLineText to repChar(aLineText, LF, “”) of me –データの途中に改行が入っていた場合には削除する
    
    
set wholeText to wholeText & “\”" & aLineText & “\”" & crlfChar –行ターミネータはCR+LF
  end repeat
  
  
if (aPath as string) does not end with “.csv” then
    set bPath to aPath & “.csv” as Unicode text
  else
    set bPath to aPath as Unicode text
  end if
  
  
write_to_file(wholeText, bPath, false) of me
  
end saveAsCSV

–入れ子のリストを、アイテム間のデリミタとパラグラフ間のデリミタを指定してテキスト化
–というか、入れ子のリストをタブ区切りテキストにするのが目的
on retItemDelimedAndParagraphDelimedText(aList, itemDelim, paragraphDelim)
  set aText to “”
  
  
repeat with i in aList
    set aStr to retDelimedText(i, itemDelim) of me
    
set aText to aText & aStr & paragraphDelim
  end repeat
  
  
return aText
end retItemDelimedAndParagraphDelimedText

on retDelimedText(aList, aDelim)
  set aText to “”
  
set curDelim to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to aDelim
  
set aText to aList as text
  
set AppleScript’s text item delimiters to curDelim
  
return aText
end retDelimedText

★Click Here to Open This Script 

2015/04/18 PSPのメモリースティックに保存されたリプレイデータをアーカイブ

PSPのゲーム(戦場の絆ポータブル)で毎週週末にオンライン対戦しており、毎回リプレイデータを保存していますが・・・さすがに毎度毎度のことなので、AppleScriptで自動化してみました。

実行すると、メモリースティック上のフォルダ(どこでもよい)を指定するダイアログが出るので、指定すると、PSP:SAVEDATA:フォルダ内の「oldData」フォルダ内に、「oldXXX」(XXXの部分が数字)の連番のフォルダの数字を+1したものを作成し、そこにリプレイデータを移動させ、メモリースティックをイジェクトします。

プログラム的には、「ありもののルーチンをかき集めて、なるべく楽をして早く作る」ことを目的としたため、新規に書いた部分はサブルーチン以外の部分のみです。

img_2879.jpg
▲PSP

img_2880.jpg
▲メモリースティックをイジェクト

img_2882.jpg
▲メモリースティック

img_2883.jpg
▲USBメモリーリーダーに入れて・・・

img_2885.jpg
▲MacのUSB端子に挿すと、デスクトップ上にマウントされる

psp1.png
▲マウントされたメモリースティック

psp2.png
▲リプレイデータはPSPから16個以上保存できないので、別フォルダに移動・・・

psp3.png
▲いいかげん、たまってきてフォルダを作成してリプレイデータを移動させるのが面倒に

AppleScript名:メモリースティックのリプレイSaveDataを最新のフォルダを掘って移動
– Created 2015-04-17 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "ASObjCExtras"

set a to choose folder with prompt "Select Memory Strick"

tell application "Finder"
  set aDisk to disk of a –Driveを求める
  
set diskPath to properties of aDisk
  
set driveRoot to displayed name of aDisk
end tell

set savedData to driveRoot & ":PSP:SAVEDATA:"
tell application "Finder"
  tell folder savedData
    set repList to (every folder whose name contains "REPLAY_") as alias list
  end tell
end tell

–> {alias "PSP_DATA:PSP:SAVEDATA:ULJS00181REPLAY_0000:", alias "PSP_DATA:PSP:SAVEDATA:ULJS00181REPLAY_0001:", alias "PSP_DATA:PSP:SAVEDATA:ULJS00181REPLAY_0002:", alias "PSP_DATA:PSP:SAVEDATA:ULJS00181REPLAY_0003:", alias "PSP_DATA:PSP:SAVEDATA:ULJS00181REPLAY_0004:", alias "PSP_DATA:PSP:SAVEDATA:ULJS00181REPLAY_0005:", alias "PSP_DATA:PSP:SAVEDATA:ULJS00181REPLAY_0006:", alias "PSP_DATA:PSP:SAVEDATA:ULJS00181REPLAY_0007:", alias "PSP_DATA:PSP:SAVEDATA:ULJS00181REPLAY_0008:", alias "PSP_DATA:PSP:SAVEDATA:ULJS00181REPLAY_0009:", alias "PSP_DATA:PSP:SAVEDATA:ULJS00181REPLAY_0010:", alias "PSP_DATA:PSP:SAVEDATA:ULJS00181REPLAY_0011:", alias "PSP_DATA:PSP:SAVEDATA:ULJS00181REPLAY_0012:", alias "PSP_DATA:PSP:SAVEDATA:ULJS00181REPLAY_0013:", alias "PSP_DATA:PSP:SAVEDATA:ULJS00181REPLAY_0014:", alias "PSP_DATA:PSP:SAVEDATA:ULJS00181REPLAY_0015:"}

if length of repList = 0 then
  tell current application
    display dialog "メモリースティック内にはリプレイデータが存在していないようです。" buttons {"OK"} default button 1
    
return
  end tell
end if

set oldFol to driveRoot & ":PSP:SAVEDATA:oldData:" –Path to Replay Data archive folder
tell application "Finder"
  tell folder oldFol
    set dList to (every folder whose name starts with "old") as alias list
  end tell
end tell

set newSortedList to sortAliasByCreationDate(dList) –sort by creation date
set newestFol to contents of first item of newSortedList –Newer -> Older , Get Newest One
tell application "Finder"
  set newestFolName to name of newestFol
end tell

log {"newestFolName", newestFolName}

set numPart to contents of first item of (retNumCharOnly(newestFolName) of me)

log {"numPart", numPart}

try
  set alphaPart to repChar(newestFolName, numPart, "")
on error erN
  –エラー時の処理
  
tell current application
    display dialog "メモリースティック内のフォルダの命名規則にイレギュラーがあったようです" & return & return & erN buttons {"OK"} default button 1
    
return
  end tell
end try

–新規名称のフォルダを作成する
set newIncrementedName to alphaPart & ((numPart as integer) + 1) as string
tell application "Finder"
  set nFol to make new folder with properties {name:newIncrementedName} at folder oldFol
  
set nnFol to nFol as alias
end tell

do shell script "sync"

–リプレイデータを移動する
with timeout of 3600 seconds
  tell application "Finder"
    move repList to nnFol
    
eject aDisk –イジェクトする
  end tell
  
end timeout

display notification "Memory Stick Update OK."

on sortAliasByCreationDate(aliasList)
  
  
tell application "Finder"
    set aList to {}
    
    
repeat with i in aliasList
      set j to contents of i
      
set the end of aList to {j, creation date of j}
    end repeat
    
    
–set cList to shellSortListAscending(aList, 2) of me –で作成日時でソート
    
set cList to shellSortListDecending(aList, 2) of me –で作成日時でソート
    
    
set aliasList to {}
    
set fnCount to 1
    
repeat with i in cList
      set j to contents of (item 1 of i)
      
      
set the end of aliasList to j
    end repeat
  end tell
  
  
return aliasList
  
end sortAliasByCreationDate

–シェルソートで入れ子のリストを昇順ソート
on shellSortListAscending(a, keyItem)
  set n to length of a
  
set cols to {1391376, 463792, 198768, 86961, 33936, 13776, 4592, 1968, 861, 336, 112, 48, 21, 7, 3, 1}
  
repeat with h in cols
    if (h (n - 1)) then
      repeat with i from h to (n - 1)
        set v to item (i + 1) of a
        
set j to i
        
repeat while (j h) and ((contents of item keyItem of item (j - h + 1) of a) > (item keyItem of v))
          set (item (j + 1) of a) to (item (j - h + 1) of a)
          
set j to j - h
        end repeat
        
set item (j + 1) of a to v
      end repeat
    end if
  end repeat
  
return a
end shellSortListAscending

–シェルソートで入れ子のリストを降順ソート
on shellSortListDecending(a, keyItem)
  set n to length of a
  
set cols to {1391376, 463792, 198768, 86961, 33936, 13776, 4592, 1968, 861, 336, 112, 48, 21, 7, 3, 1}
  
repeat with h in cols
    if (h (n - 1)) then
      repeat with i from h to (n - 1)
        set v to item (i + 1) of a
        
set j to i
        
repeat while (j h) and ((contents of item keyItem of item (j - h + 1) of a) < (item keyItem of v))
          set (item (j + 1) of a) to (item (j - h + 1) of a)
          
set j to j - h
        end repeat
        
set item (j + 1) of a to v
      end repeat
    end if
  end repeat
  
return a
end shellSortListDecending

–与えられた文字列から、数字部分だけを返す
on retNumCharOnly(a)
  set aList to characters of a
  
  
set aResList to {}
  
  
set inF to false –アイテムへの取り込みフラグ:初期値=false(取り込まない)
  
set oneItem to ""
  
  
repeat with i in aList
    set j to contents of i
    
set aF to detectOutNumChar(j) of me –aF:現在のキャラクタがNumericかどうかの判定フラグ
    
    
if aF = true and inF = false then
      set inF to true
      
set oneItem to oneItem & j
      
    else if aF = true and inF = true then
      set oneItem to oneItem & j
      
    else if aF = false and inF = true then
      set the end of aResList to oneItem
      
set oneItem to ""
      
set inF to false
      
    else if aF = false and inF = false then
      –なにもしない
      
    end if
  end repeat
  
  
if oneItem is not equal to "" then
    set the end of aResList to oneItem
  end if
  
  
return aResList
  
–> {"100", "12", "88"}
end retNumCharOnly

–数字範囲外の文字があるかどうかをテストする
–数字の文字以外のものが入っていたらfalse
on detectOutNumChar(testText)
  –ANK文字列(大文字小文字は問わない)
  
set ankChar to {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "."}
  
  
set _testChar to testText as Unicode text
  
  
ignoring case
    repeat with i in _testChar
      set j to contents of i
      
if j is not in ankChar then
        return false
      end if
    end repeat
  end ignoring
  
  
return true
end detectOutNumChar

–文字置換
on repChar(aStr, targStr, repStr)
  set aString to current application’s NSString’s stringWithString:aStr
  
set bString to aString’s stringByReplacingOccurrencesOfString:targStr withString:repStr
  
set cString to (bString’s ASify()) as string
  
return cString
end repChar

★Click Here to Open This Script 

2015/04/12 OS X 10.10.3のdelayに(新たな)バグ? マウスカーソルの移動でdelayがキャンセルされる

Twitterへの@fixdotさんの投稿についてやりとりしつつ検証したところ、OS X 10.10.3の新たなバグらしきものが明らかになりました(以前からあったものかは不明)。@fixdotさんの(この)投稿内容が正しいことが証明されました。

step1:以下のScriptをアプリケーション形式で保存

AppleScript名:delayTest
display dialog “test1″ giving up after 1
delay 10
display dialog “test2″ giving up after 1

★Click Here to Open This Script 

step2: 保存したアプリケーション(アプレット)を実行
step3: (実行中に)マウスカーソルを移動させる

・・・アプレットをの実行中にマウスカーソルを移動させると、delayの待ち時間が無視されます(ーー;

とりあえず、広く言われている対策をスマートに実装するとこんな感じです。do shell script “sleep”に置き換えろ、というのが解決策なんですが、プログラムの書き換えを最低限にとどめるために、on delayでdelay命令そのものをのっとってdo shell scriptコマンドを実行します。

AppleScript名:delayTest_対策
display dialog “test1″ giving up after 1
delay 10
display dialog “test2″ giving up after 1

on delay aParam
  do shell script “sleep “ & aParam
end delay

★Click Here to Open This Script 

2015/04/12 指定のPOSIX pathがFolder (Directory)かどうかを返す。実在しないpathならerrorを返す

This ASOC script detect the specified path is whether directory or not. Detect directory is important with NSPathControl. So, I wrote this.

特定のパスがディレクトリ(フォルダ)かどうかを判定するASOCのscriptです。

ディレクトリ検出は、NSPathControlをASOCアプリで使うときに、ドラッグ&ドロップされたfile pathがフォルダの時には処理し、フォルダでなければ処理しないといった条件分岐を書くために作りました。

AppleScript名:指定のPOSIX pathがFolder (Directory)かどうかを返す。実在しないpathならerrorを返す
– Created 2015-04-12 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aa to POSIX path of (choose folder)
set ab to isDir(aa)
–> true

set bb to POSIX path of (choose file)
set bc to isDir(bb)
–> false

–指定のPOSIX pathがFolder (Directory)かどうかを返す。実在しないpathならerrorを返す。
on isDir(aa)
  set {aRes, dirF} to current application’s NSFileManager’s defaultManager()’s fileExistsAtPath:aa isDirectory:(reference)
  
set aRes to aRes as boolean
  
set dirF to dirF as boolean
  
  
if aRes = true then
    return dirF
  else
    error
  end if
end isDir

★Click Here to Open This Script 

2015/04/09 写真.app(Photos.app)のScript対応機能は未完成

OS X 10.10.3がリリースされ、山のように報告していたバグの一部が修正され・・・Message経由での画面共有あたりはまともになりました。

スタイル付きテキストのコピー&ペーストでダブルクォート2個が1個に化けるとか、ファイル共有しようとしてもホスト名が勝手にMac(26)とかの変な名前になってPeer To Peerのファイル共有ができないといった深刻なバグは手付かずです、、、(ーー;

photosicon.pngそんなOS X 10.10.3の新アプリ「写真.app」(Photos.app)バージョン1.0。

ph1.jpg
▲OS X 10.10.3に新登場の「写真.app」(Photos.app)/ 各人物の顔へのモザイクは自作アプリ「Photo Face Masker」にて一括実行(顔認識しなかった若干名は手作業)

β版の頃からAppleScript用語辞書がついていてAppleScriptから機能を呼び出せることは確認していたのですが、いかんせん未完成のβ版なので「見ても仕方がない」レベルだと思っていました。

ほぼ初見のPhotos.appのAppleScript対応機能の充実度はどんなもんでしょうか?

Applicationのpropertiesがとれる

AppleScript名:Photosのプロパティを取得
tell application “Photos”
  properties
  
–> {recently deleted album:recently deleted album id “trashAlbum” of application “Photos”, last import album:container id “lastImportAlbum” of application “Photos”, selection:{}, name:”Photos”, frontmost:false, favorites album:container id “favoritesAlbum” of application “Photos”, version:”1.0″, slideshow running:false, class:application}
  
end tell

★Click Here to Open This Script 

selectionがapplicationの直下にありますね。selectionは機能しています(詳細は後述)。

selectionの内容から、写真1枚1枚は「media item」という名称でアクセスされることがわかります。ただし、media itemに直接アクセスしようとするとエラーに(汗)

アルバムへのアクセスも可能

アルバムはcontainerというオブジェクトで表現されています。container “フラグ付き”といった名称でアクセスすることも可能です。

AppleScript名:Photosで全アルバム名を取得
tell application “Photos”
  set aList to name of every container –Every Album Name
  
–> {”フラグ付き”, “iPhoto イベント”, “MobileMe から”, “ともぞうさん2010″, “あいかちゃん2010″, “かいちゃん2010″, “けいこ2010″, “ムービー”, “こうじ2010″, “名称未設定アルバム 2″, “iPhone4″, “あいかちゃん2011″, “大きすぎ”, “うどん”,……….}
end tell

★Click Here to Open This Script 

AppleScript名:Photosで指定のアルバムにアクセス
tell application “Photos”
  tell container “フラグ付き” –Album
    properties
    
–> {id:”yFpznZXFQo2IyXJqLjlAtQ”, class:album, name:”フラグ付き”, parent:missing value}
    
    
set aList to every media item
    
–> {media item id “Alt+61wVTkGVnhSsyfrayg” of container id “yFpznZXFQo2IyXJqLjlAtQ” of application “Photos”, media item id “pWF6W56sRXaswwvao6UJpw” of container id “yFpznZXFQo2IyXJqLjlAtQ” of application “Photos”,………….}
  end tell
end tell

★Click Here to Open This Script 

AppleScript名:Photosでアルバム内のmedia item一覧を取得
tell application “Photos”
  tell container “フラグ付き”
    set aList to every media item
  end tell
end tell

–> {media item id “Alt+61wVTkGVnhSsyfrayg” of container id “yFpznZXFQo2IyXJqLjlAtQ” of application “Photos”, media item id “pWF6W56sRXaswwvao6UJpw” of container id “yFpznZXFQo2IyXJqLjlAtQ” of application “Photos”……….}

★Click Here to Open This Script 

「人々」の各人物を選択してselectionを取得すると、media itemのlistが返ってきます。containerとかfolderではないようです。

「最後の読み込み」アルバムにアクセスして、その中に入っているmedia itemへのpropertiesは取得できます。selectionから取得した各media itemのpropertiesはエラーになるのに、container内のmedia itemにはpropertiesの取得が効きます。このあたりで、まだまだ未完成な印象を受けます(ーー;;

AppleScript名:Photosで「最後に読み込み」アルバム内のmedia itemのプロパティにアクセス
tell application “Photos”
  set aProp to properties
  
set aLast to last import album of aProp
  
  
tell aLast
    set aPhotos to every media item
    
repeat with i in aPhotos
      
      
properties of i
      
–> {favorite:false, id:”2np1X29yQrOm0lV7xlOFBA”, class:media item, filename:”DSCF3559.JPG”, width:1920, location:{missing value, missing value}, keywords:missing value, date:date “2010年1月1日金曜日 0:06:55″, height:1080, description:missing value, altitude:missing value, name:missing value}
      
    end repeat
  end tell
  
end tell

★Click Here to Open This Script 

AppleScript名:Photosで直接selection内のmedia itemのpropertiesを取得するとエラーに
tell application “Photos”
  set aProp to properties
  
  
set aSel to selection of aProp
  
–> {media item id “5hwoENYJSP6JRutP8n9Miw” of application “Photos”}
  
  
repeat with i in aSel
    set j to contents of i
    
set aCon to filename of j
    
–> error “Photos でエラーが起きました:AppleEvent のハンドラで誤りが起きました。” number -10000
  end repeat
end tell

★Click Here to Open This Script 

全体の印象は悪くないが、未完成であることは事実

KeynoteがiOS版と足並みをそろえるために機能ダウンしてフォントパネルが使えないとかいろいろ不満な点が出て「残念な出来」になってしまったのにくらべ、iPhotoからの機能ダウンはそれほど感じられず、「悪くない」印象です。

AppleScript対応機能については、まだ触りだしたばかりですが……selectionからmedia itemにアクセスできないというのは、おっとっと、という感じです。「人々」と連絡先.app(Contacts.app)との連携なども期待していたのですが、そこまでも行っていない感じです。

Keynote 6.xのAppleScript対応機能の残念さにくらべれば、まだ望みがあるように見えます。

ちなみにPhotos.appのsdefファイル(Script用語辞書書類)は、読みやすいように空行が入れてあり、きちんとメンテナンスするぞという(生きているという)印象を受けます。改行を全部とっぱらって、メンテナンスもなにものぞめないような「死んだ」辞書ではない、という印象を受けます。

ph2.png

ありもののアプリの再構築についてはiPhoto→Photosで経験を積んで、次は本丸の「iTunes」を作り直したいといったところでしょうか、アップル的には。

2015/04/02 CocoaでDisk Free Space (Bytes) を求める

Shane wrote me various methods to get free space in Cocoa way. NSByteCountFormatter seems very useful.

“usedSpaceLongString” is good because they take the user’s number formatting and language into account (Shane said).

ShaneがCocoaでDiskの空き容量を(Byte単位で)返すscriptを書いてくれました(Thanks!)。NSByteCountFormatterが非常に使い勝手がありそうです。

“usedSpaceLongString”は実行時のユーザー環境の数値フォーマット形式と言語設定を反映させるため有用です(Shane談)。

あれ??? このScript、使用率が%で返ってきているものをただ文字フォーマットしているだけかも、、、

AppleScript名:CocoaでDiskSpace(Bytes)を求める
– Created 2015-04-02 by Shane Stanley
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

usedSpace(“/”)
–>  4.5772857344E+10

usedSpace2(“/”)
–>  4.5772857344E+10

usedSpaceString(“/”)
–>  ”45.77 GB”

usedSpaceLongString(“/”)
–>  ”45.77 GB (45,772,857,344 bytes)”–English user environment
–>  ”45.77 GB (45,772,857,344 バイト)”–Japanese user environment

tell application “Finder”
  free space of startup disk
end tell
–>  4.5784592712E+10

on usedSpace(volumePath)
  set theNSURL to current application’s class “NSURL”’s fileURLWithPath:volumePath –considering “ASOC in Xcode”
  
set {theResult, theSize} to theNSURL’s getResourceValue:(reference) forKey:(current application’s NSURLVolumeAvailableCapacityKey) |error|:(missing value)
  
  
return theSize as real – integer may be too big for AS
end usedSpace

on usedSpace2(volumePath)
  set fileAttr to current application’s NSFileManager’s defaultManager()’s attributesOfFileSystemForPath:volumePath |error|:(missing value)
  
  
return (fileAttr’s objectForKey:(current application’s NSFileSystemFreeSize)) as real – integer may be too big for AS
end usedSpace2

on usedSpaceString(volumePath)
  set fileAttr to current application’s NSFileManager’s defaultManager()’s attributesOfFileSystemForPath:volumePath |error|:(missing value)
  
set fRes to fileAttr’s objectForKey:(current application’s NSFileSystemFreeSize)
  
  
–Formatting
  
set sizeString to current application’s NSByteCountFormatter’s stringFromByteCount:fRes countStyle:(current application’s NSByteCountFormatterCountStyleDecimal)
  
  
return sizeString as text
end usedSpaceString

on usedSpaceLongString(volumePath)
  set fileAttr to current application’s NSFileManager’s defaultManager()’s attributesOfFileSystemForPath:volumePath |error|:(missing value)
  
set fRes to fileAttr’s objectForKey:(current application’s NSFileSystemFreeSize)
  
  
–Formatting
  
set theFormatter to current application’s NSByteCountFormatter’s alloc()’s init()
  
theFormatter’s setCountStyle:(current application’s NSByteCountFormatterCountStyleDecimal)
  
theFormatter’s setIncludesActualByteCount:true
  
set sizeString to theFormatter’s stringFromByteCount:fRes
  
  
return sizeString as text
end usedSpaceLongString

★Click Here to Open This Script 

2015/04/01 DiskSpaceを求める

These scripts get free space of storage. Finder’s “free space” command returns specified disk’s free space by bytes. Cocoa’s NSFileSystemFreeSize return percentage of used space. I like the former. But ASOC in Xcode, sometimes we can not use Finder command. So I checked the cocoa way.

通常のAppleScriptとASOCのscriptでディスクの空きを求めるものです。Finderの「free space」コマンドは指定ディスクの空き容量をバイト単位で返します。CocoaのNSFileSystemFreeSizeは使用ずみ容量をパーセントで返します。どちらかといえば、前者の方が好みですが・・・ASOC in XcodeではFinderのコマンドが通じないケースが出てくるため、Cocoa風のやり方を調べておきました。

AppleScript名:Pure ASでDiskSpace(GBytes)を求める
– Created 2015-04-01 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions

tell application “Finder”
  set aFree to (free space of startup disk) / 1.0E+9
end tell
–>  102.829194753

★Click Here to Open This Script 

AppleScript名:CocoaでDiskSpace(%)を求める
– Created 2015-04-01 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

set aPath to current application’s NSString’s stringWithString:“/”
set fileAttr to current application’s NSFileManager’s defaultManager()’s attributesOfFileSystemForPath:aPath |error|:(missing value)
set fRes to (fileAttr’s objectForKey:(current application’s NSFileSystemFreeSize)) as string

set aDecNum to current application’s NSDecimalNumber’s decimalNumberWithString:fRes
set aFreeNum to aDecNum’s decimalNumberByDividingBy:(current application’s NSDecimalNumber’s decimalNumberWithString:“1000000000″) –”G” Bytes for Storage
set bFreeNum to aFreeNum as real
–> 84.058387756348

★Click Here to Open This Script