Archive for 10月, 2016

2016/10/31 指定ファイルをFinderで選択表示

指定のファイルをFinder上で選択状態で表示するAppleScriptです。

何か処理結果をファイルに書き出したような場合、どのファイルに出力したかを明示的に表現するために、Finder上で新規ウィンドウを作成して対象ファイルを選択状態にすることはよくあります。

そのためのAppleScriptで、Pure AppleScript版とCocoaの機能を用いたAppleScriptObjC版です。

見比べてみて、このぐらいの素朴な処理&用途ではASOCを使う意義が見出せないですね。

AppleScript名:指定ファイルをFinderで選択表示_pure_as
– Created 2016-10-31 by Takaaki Naganoya
– 2016 Piyomaru Software
–http://piyocast.com/as/archives/4297

set aFile to choose file
tell application “Finder”
  activate
  
reveal aFile
end tell

★Click Here to Open This Script 

AppleScript名:指定ファイルをFinderで選択表示_asoc
– Created 2016-10-31 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”
–http://piyocast.com/as/archives/4297

set aFile to POSIX path of (choose file)
set pathStr to current application’s NSString’s stringWithString:aFile
set parentPath to pathStr’s stringByDeletingLastPathComponent()
set aRes to current application’s NSWorkspace’s sharedWorkspace()’s selectFile:pathStr inFileViewerRootedAtPath:parentPath

★Click Here to Open This Script 

2016/10/31 listのrecordをplistにserializeして、plistをde-serializeする

Listでまとめたrecordをエンコーディングしてplist文字列にして(serialize)、さらにそれを元に戻す(deserialize)AppleScriptです。

本来、「エンコーダーとデコーダーは一緒に作る」はずのものですが、plistへのエンコードScriptしかできておらず、世の中に転がっているObjective-Cのサンプルとにらめっこしてもさっぱり分からなかったので、AppleScript Users MLに質問を投げてみたら、Shane Stanleyからあっさりと、

「これ、もうdeprecatedなmethodなんで使っちゃダメだよ。あと、deserializeするときには文字列をそのまま渡さないでね」

というアドバイスとコードそのものを教えてもらいました。というわけで、整理して掲載しておきます。

AppleScript名:listのrecordをplistにserializeして、plistをde-serializeする
– Created 2016-10-30 by Takaaki Naganoya
– Modified 2016-10-31 by Shane Stanley
– 2016 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4296

set aList to {{theName:“Sound Track”, numberOfTimes:1721}, {theName:“Rock”, numberOfTimes:942}}
set aRes to serializeToPlistString(aList) of me
set bRes to (deserializeToPlistString(aRes) of me) as list
–>  {{numberOfTimes:1721, theName:”Sound Track”}, {numberOfTimes:942, theName:”Rock”}}

–list or record –> XML-format plist string
on serializeToPlistString(aList as {list, record})
  set pListData to current application’s NSPropertyListSerialization’s dataWithPropertyList:aList |format|:(current application’s NSPropertyListXMLFormat_v1_0) options:0 |error|:(missing value)
  
set bStr to (current application’s NSString’s alloc()’s initWithData:pListData encoding:(current application’s NSUTF8StringEncoding)) as string
  
return bStr
end serializeToPlistString

–XML-format plist string–> list or record
on deserializeToPlistString(aStr as string)
  set deStr to current application’s NSString’s stringWithString:aStr
  
set theData to deStr’s dataUsingEncoding:(current application’s NSUTF8StringEncoding)
  
set aList to current application’s NSPropertyListSerialization’s propertyListWithData:theData options:(current application’s NSPropertyListMutableContainersAndLeaves) |format|:(missing value) |error|:(missing value)
  
return aList
end deserializeToPlistString

★Click Here to Open This Script 

2016/10/30 Listのrecordをエンコーディングしてplist文字列にする

Listでまとめたrecordをエンコーディングしてplist文字列にするAppleScriptです。

ただのrecordでもなんでもいいのですが、plistのファイルに書き込むのではなく、文字列として取得します。

AppleScriptをTerminal上で呼び出して、複数のAppleScript同士でデータをやりとりする場合に、リストやレコードをそのままやりとりすることは困難です。そこで、plistの文字列にして標準出力に出すことを検討してみました。

ご注意:本Scriptはdeprecatedなmethodを使っているため、アップデート版を利用してください。

AppleScript名:Listのrecordをエンコーディングしてplist文字列にする
– 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/4295

set aList to {{theName:“サウンドトラック”, numberOfTimes:1721}, {theName:“ロック”, numberOfTimes:942}}

–2D Arrayをplistの文字列にエンコードする
set anArray to current application’s NSArray’s arrayWithObject:aList
set pListData to current application’s NSPropertyListSerialization’s dataFromPropertyList:anArray |format|:(current application’s NSPropertyListXMLFormat_v1_0) errorDescription:(missing value)
set bStr to (current application’s NSString’s alloc()’s initWithData:pListData encoding:(current application’s NSUTF8StringEncoding)) as string

(*
–>  ”<?xml version=\”1.0\” encoding=\”UTF-8\”?>
<!DOCTYPE plist PUBLIC \”-//Apple//DTD PLIST 1.0//EN\” \”http://www.apple.com/DTDs/PropertyList-1.0.dtd\”>
<plist version=\”1.0\”>
<array>
  <array>
    <dict>
      <key>numberOfTimes</key>
      <integer>1721</integer>
      <key>theName</key>
      <string>サウンドトラック</string>
    </dict>
    <dict>
      <key>numberOfTimes</key>
      <integer>942</integer>
      <key>theName</key>
      <string>ロック</string>
    </dict>
  </array>
</array>
</plist>

*)

★Click Here to Open This Script 

2016/10/29 同義語辞書【新語対応】

Apitoreの「同義語辞書【新語対応】」APIを呼び出して、指定の日本語の単語の同義語(っぽいもの)を返すAppleScriptです。

実行前にapitoreにユーザー登録を行い(無料)、Web上でアクセストークンを取得。そのトークンをretAccessToken()内で返すように書いておく必要があります(掲載のリストのまま実行すると、エラーになります。かならずアクセストークンを取得してください)。

一般的なシソーラス的な動作を行うわけではなく、固有名詞に特化しているとのこと。そこで、「ガンダム」を渡してみたところ、

{input:”ガンダム”, endTime:”1477742279389″, processTime:”1019″, log:”Success.”, distances:{{word:”ζガンダム”, distance:0.819100677967}, {word:”rx-78″, distance:0.798426866531}, {word:”ζζガンダム”, distance:0.794555306435}, {word:”ザク”, distance:0.783695220947}, {word:”zガンダム”, distance:0.776543617249}, {word:”フルアーマー”, distance:0.757733106613}, {word:”gアーマー”, distance:0.75621265173}, {word:”νガンダム”, distance:0.754522383213}, {word:”ガンキャノン”, distance:0.752012193203}, {word:”モビルスーツ”, distance:0.744036734104}}, startTime:”1477742278370″, num:”10″}

やや、ゴミ(ζガンダム、ζζガンダム)が入っているようです。また、「グフ・カスタム」を入力してみると、

{input:”グフ・カスタム”, endTime:”1477742501687″, processTime:”934″, log:”Success.”, distances:{{word:”sideral”, distance:0.922877013683}, {word:”北海道道104号網走端野線”, distance:0.922159075737}, {word:”北海道道966号十勝岳温泉美瑛線”, distance:0.921318411827}, {word:”kuttner”, distance:0.916471898556}, {word:”北海道道102号網走川湯線”, distance:0.915675938129}, {word:”北海道道42号八雲北檜山線”, distance:0.915441274643}, {word:”三浦隆”, distance:0.914838135242}, {word:”桧山泰浩”, distance:0.914380848408}, {word:”北海道道120号美深中頓別線”, distance:0.914329528809}, {word:”knipex”, distance:0.913379848003}}, startTime:”1477742500753″, num:”10″}

と、関係ない言葉が返ってくるようです。Wikipediaに項目が単独で存在しているような単語と、その関連語では本サービス上での扱いが異なるように感じられます。

AppleScript名:同義語辞書【新語対応】
– Created 2016-10-27 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version “2.5″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4294

set reqURLStr to “https://api.apitore.com/api/9/word2vec-neologd-jawiki/distance”
set accessToken to retAccessToken() —Access Token
set aRec to {access_token:accessToken, |word|:“ガンダム”, num:“10″}
set aURL to retURLwithParams(reqURLStr, aRec) of me

set aRes to callRestGETAPIAndParseResults(aURL) of me

set aRESTres to (json of aRes) as record
return aRESTres
–>  {input:”ガンダム”, endTime:”1477742279389″, processTime:”1019″, log:”Success.”, distances:{{word:”ζガンダム”, distance:0.819100677967}, {word:”rx-78″, distance:0.798426866531}, {word:”ζζガンダム”, distance:0.794555306435}, {word:”ザク”, distance:0.783695220947}, {word:”zガンダム”, distance:0.776543617249}, {word:”フルアーマー”, distance:0.757733106613}, {word:”gアーマー”, distance:0.75621265173}, {word:”νガンダム”, distance:0.754522383213}, {word:”ガンキャノン”, distance:0.752012193203}, {word:”モビルスーツ”, distance:0.744036734104}}, startTime:”1477742278370″, num:”10″}

–>  {input:”グフ・カスタム”, endTime:”1477742501687″, processTime:”934″, log:”Success.”, distances:{{word:”sideral”, distance:0.922877013683}, {word:”北海道道104号網走端野線”, distance:0.922159075737}, {word:”北海道道966号十勝岳温泉美瑛線”, distance:0.921318411827}, {word:”kuttner”, distance:0.916471898556}, {word:”北海道道102号網走川湯線”, distance:0.915675938129}, {word:”北海道道42号八雲北檜山線”, distance:0.915441274643}, {word:”三浦隆”, distance:0.914838135242}, {word:”桧山泰浩”, distance:0.914380848408}, {word:”北海道道120号美深中頓別線”, distance:0.914329528809}, {word:”knipex”, distance:0.913379848003}}, startTime:”1477742500753″, num:”10″}

set aRESCode to responseCode of aRes
–>  200

set aRESHeader to responseHeader of aRes

–GET methodのREST APIを呼ぶ
on callRestGETAPIAndParseResults(aURL)
  
  
set aRequest to current application’s NSMutableURLRequest’s requestWithURL:(current application’s |NSURL|’s URLWithString:aURL)
  
  
aRequest’s setHTTPMethod:“GET”
  
aRequest’s setCachePolicy:(current application’s NSURLRequestReloadIgnoringLocalCacheData)
  
aRequest’s setHTTPShouldHandleCookies:false
  
aRequest’s setTimeoutInterval:60
  
aRequest’s setValue:“application/json” forHTTPHeaderField:“Accept”
  
  
set aRes to current application’s NSURLConnection’s sendSynchronousRequest:aRequest returningResponse:(reference) |error|:(missing value)
  
set resList to aRes as list
  
  
set bRes to contents of (first item of resList)
  
set resStr to current application’s NSString’s alloc()’s initWithData:bRes encoding:(current application’s NSUTF8StringEncoding)
  
  
set jsonString to current application’s NSString’s stringWithString:resStr
  
set jsonData to jsonString’s dataUsingEncoding:(current application’s NSUTF8StringEncoding)
  
set aJsonDict to current application’s NSJSONSerialization’s JSONObjectWithData:jsonData options:0 |error|:(missing value)
  
  
–Get Response Code & Header
  
set dRes to contents of second item of resList
  
if dRes is not equal to missing value then
    set resCode to (dRes’s statusCode()) as number
    
set resHeaders to (dRes’s allHeaderFields()) as record
  else
    set resCode to 0
    
set resHeaders to {}
  end if
  
  
return {json:aJsonDict, responseCode:resCode, responseHeader:resHeaders}
  
end callRestGETAPIAndParseResults

on retURLwithParams(aBaseURL, aRec)
  set aDic to current application’s NSMutableDictionary’s dictionaryWithDictionary:aRec
  
  
set aKeyList to (aDic’s allKeys()) as list
  
set aValList to (aDic’s allValues()) as list
  
set aLen to length of aKeyList
  
set bLen to length of aValList
  
if aLen is not equal to bLen then return false
  
  
set qList to {}
  
repeat with i from 1 to aLen
    set aName to contents of item i of aKeyList
    
set aVal to contents of item i of aValList
    
set the end of qList to (current application’s NSURLQueryItem’s queryItemWithName:aName value:aVal)
  end repeat
  
  
set aComp to current application’s NSURLComponents’s alloc()’s initWithString:aBaseURL
  
aComp’s setQueryItems:qList
  
set aURL to (aComp’s |URL|()’s absoluteString()) as text
  
  
return aURL
end retURLwithParams

on retAccessToken()
  return “XXxXXXxx-XXxX-XXXx-XXxX-XXxxXxXXXxXX” –API Tore Access Token
end retAccessToken

on urlencodeStr(aStr)
  set aString to current application’s NSString’s stringWithString:aStr
  
set aString to (aString’s stringByAddingPercentEncodingWithAllowedCharacters:(current application’s NSCharacterSet’s URLQueryAllowedCharacterSet())) as text
  
return aString
end urlencodeStr

★Click Here to Open This Script 

2016/10/28 ベクトルのコサイン類似度を計算する v2

ベクトル同士のコサイン類似度を計算するAppleScriptの改良版です。

「ガンダム」「アムロ・レイ」「ガンキャノン」

という3つの言葉の類似度を計算したところ、

 (1)「ガンダムとガンキャノン」
 (2)「アムロ・レイとガンキャノン」
 (3)「アムロ・レイとガンダム」

の順に類似度が計算されてしまい、「ガンキャノン問題」として問題視されました。

Apitoreさんより「ベクトルの長さで正規化するとよい」という助言をいただき、いろいろ調べて改良してみたものです。

その結果、

 (1)「ガンダムとガンキャノン」
 (2)「ガンダムとアムロ・レイ」
 (3)「アムロ・レイとガンキャノン」

の順番に計算結果が出るようになり、一安心しています。

AppleScript名:ベクトルのコサイン類似度を計算する v2
– Created 2016-10-28 by Takaaki Naganoya
– 2016 Piyomaru Software
–以下のページを参照しました
–http://www.cse.kyoto-su.ac.jp/~g0846020/keywords/cosinSimilarity.html
–http://piyocast.com/as/archives/4293

set aRec to {startTime:“1477635439753″, |word|:“ガンダム”, endTime:“1477635439754″, |log|:“Success.”, |vector|:{-0.173511996865, 0.186350002885, 0.288884997368, 0.107758000493, 0.287292987108, 0.119222998619, 0.246404007077, -0.332718014717, -0.309754997492, 0.326180011034, 0.499563008547, -0.131274998188, 0.238587006927, -0.317025989294, -0.008682000451, 0.619518995285, 0.316774994135, -0.053045999259, 0.028408000246, -0.428086012602, -0.607270002365, 0.657006978989, 0.676119029522, 0.203107997775, -0.316679000854, 0.082666002214, -0.310041993856, 0.603790998459, 0.468154996634, 0.206021994352, 0.028333999217, -0.087867997587, -0.358617991209, 0.128415003419, 0.037046000361, -0.260360985994, -0.210915997624, -0.015564999543, -0.180935993791, 0.083250999451, -0.193316996098, 0.250761002302, 0.202393993735, -0.155086994171, 0.036905001849, 0.418110996485, 0.067231997848, -0.116421997547, -0.341655999422, 0.05919200182, 0.389017999172, -0.544457018375, -0.244222998619, 0.337971001863, 0.163227006793, 0.117914997041, -0.042672999203, -0.215838998556, 0.191798001528, 0.174465000629, -0.055527999997, 0.121985003352, -0.046782001853, -0.347003012896, -0.425747990608, 0.576622009277, 0.322551995516, -0.426732987165, -0.580038011074, -0.579939007759, 0.29191800952, 0.076993003488, 0.220890000463, -0.374727010727, 0.11546599865, 0.239750996232, -0.599394023418, 0.581852018833, -0.124090999365, -0.180638998747, 0.5446190238, -0.65235298872, 0.456075012684, 0.494884997606, 0.484183996916, 0.020594999194, 0.362075001001, -0.089720003307, 0.230300992727, 0.281304001808, 0.286731004715, 0.374053001404, -0.177623003721, 0.090945996344, -0.399394005537, 0.573561012745, 0.130366995931, 0.15235799551, -0.323183000088, 0.143162995577, 0.274109989405, 0.520829021931, 0.171061992645, -0.079223997891, -0.529187977314, 0.109682999551, -0.433328002691, -0.26163700223, -0.624193012714, 1.016695022583, -0.359939008951, 0.183194994926, 0.018155999482, -0.14149799943, -0.240256994963, 0.413583993912, 0.378069013357, -0.35772100091, 0.056784998626, 0.842347025871, -0.041281998158, 0.121949002147, -0.55557101965, -0.012947999872, -0.451754003763, 0.095089003444, 0.468187004328, -0.376350998878, 0.78152102232, 0.307211011648, -0.709493994713, -0.498080998659, -0.324746012688, -0.199910998344, 0.066499002278, -0.047377999872, -0.116584002972, -0.392536014318, 0.534222006798, -0.004480999894, 0.106450997293, 0.492370009422, -0.205549001694, -0.138926997781, -0.25551199913, 0.122440002859, -0.063225999475, 0.400667995214, -0.294638991356, -0.618892014027, -0.163193002343, -0.203306004405, -0.500850975513, 0.183540001512, -0.46670499444, -0.213167995214, -0.276264995337, 0.204497992992, -0.156630992889, 0.383563011885, 0.496547013521, 0.113885998726, 0.020508000627, -0.389571994543, 0.218575999141, -0.064272001386, -0.026503000408, -0.173591002822, 0.254842013121, 0.464908987284, -0.103918999434, -0.269497007132, 0.070835001767, 0.203738003969, 0.181133002043, -0.246653005481, -0.136351004243, -0.24780100584, 0.326480001211, -0.193390995264, -0.041266001761, 0.245121002197, -0.118851996958, -0.083679996431, -0.171301007271, 0.031709998846, -0.332567989826, -0.059787001461, 0.001627000049, -0.048179998994, -0.396964997053, 0.31639200449, -0.352144986391, 0.008798000403, -0.232255995274, -0.394028007984, 0.116296000779, 0.171626001596, 0.013128999621, -0.295181006193}, processTime:“1″}

set bRec to {startTime:“1477635460487″, |word|:“アムロ・レイ”, endTime:“1477635460487″, |log|:“Success.”, |vector|:{0.03407099843, 0.10659699887, 0.127606004477, -0.13093200326, 0.17143599689, -0.386317998171, 0.223474994302, -0.63797801733, -0.21521499753, 0.215176001191, 0.607864022255, 0.176204994321, -0.184221997857, 0.361393988132, 0.16435199976, 0.652567028999, 0.242174997926, -0.325437992811, 0.394699007273, -0.393142998219, -0.312689989805, 0.173059001565, 0.660327970982, -0.07935500145, -0.34789198637, -0.223361998796, -0.153245002031, 0.175822004676, 0.104438997805, 0.50031298399, 0.16487300396, -0.138288006186, -0.054469998926, 0.100807003677, 0.05673699826, -0.067408002913, 0.017626000568, -0.07518299669, -0.201003998518, -0.005166999996, -0.088767997921, 0.615378975868, 0.126588001847, -0.127129003406, 0.159886002541, 0.374316006899, -0.03769300133, -0.050262000412, 0.063642002642, 0.169852003455, 0.409768998623, -0.453413009644, -0.122203998268, 0.294649988413, 0.11619400233, 0.576021015644, -0.117141999304, -0.486111998558, 0.283957004547, -0.101135000587, -0.078950002789, 0.173895001411, -0.083311997354, 0.028666999191, -0.21795900166, 0.184988006949, -0.185552999377, -0.399181008339, -0.098324000835, -0.352382987738, 0.075119003654, -0.17525100708, 0.373353004456, -0.152073994279, 0.051049001515, 0.110192000866, -0.726333022118, 0.334517002106, -0.075718998909, -0.354999989271, 0.655991971493, -0.298009991646, 0.508288025856, 0.243245005608, 0.239094004035, -0.086781002581, -0.161684006453, -0.507776021957, 0.261065006256, 0.284135997295, 0.307931989431, 0.213102996349, 0.136901006103, 0.397157996893, -0.464179992676, 0.262387990952, 0.380863010883, -0.071410998702, -0.165156006813, 0.135739997029, 0.283789008856, 0.820464015007, -0.359337002039, 0.155907005072, -0.330406993628, 0.400182008743, 0.119069002569, -0.182172998786, -0.147823005915, 0.674717009068, -0.637548983097, -0.110163003206, 0.025941999629, -0.274792999029, -0.184186995029, 0.543650984764, 0.189351007342, -0.354799985886, -0.005100999959, 0.318190008402, 0.088809996843, 0.300523996353, -0.336024999619, -0.279132008553, -0.489708006382, 0.119197003543, 0.357654988766, -0.009196000174, 0.908367991447, 0.127497002482, -0.877427995205, -0.362311005592, 0.045292001218, 0.228176996112, 0.003637999995, -0.021867999807, 0.264483004808, -0.531185984612, 0.075176000595, -0.258029013872, 0.180007994175, 0.549230992794, 0.085698001087, 0.164148002863, 0.198268994689, 0.206103995442, 0.182986006141, 0.262667000294, -0.509878993034, -0.44718798995, 0.136090993881, -0.18127900362, -0.148757994175, 0.263893991709, -0.386029988527, -0.198642000556, 0.220932006836, 0.202956005931, 0.048569001257, 0.194492995739, 0.180389001966, 0.697315990925, 0.139156997204, -0.228732004762, 0.201507002115, -0.043519001454, -0.419701009989, -0.424322992563, 0.085637003183, 0.513258993626, -0.90073800087, -0.365974009037, -0.043921001256, -0.012201000005, 0.343672990799, -0.352656006813, 0.335415005684, -0.584758996964, -0.045765001327, -0.614067018032, 0.095513001084, 0.461355000734, -0.371479004622, -0.612700998783, 0.043907001615, 0.56964302063, -0.364234000444, -0.080641999841, 0.140410006046, -0.180212005973, -0.543507993221, 0.225119993091, -0.285872995853, 0.08812700212, -0.299535006285, 0.026107000187, -0.221154004335, 0.39902600646, 0.160721004009, -0.433041006327}, processTime:“0″}

set cRec to {startTime:“1477635477524″, |word|:“ガンキャノン”, endTime:“1477635477524″, |log|:“Success.”, |vector|:{0.072226002812, -0.123470000923, 0.229124993086, 0.024253999814, 0.090787000954, -0.554116010666, 0.127351999283, -0.277144014835, -0.273193985224, 0.049963001162, 0.459771990776, -0.271524995565, 0.12961499393, -0.174656003714, 0.56355202198, 0.922071993351, 0.629299998283, 0.046698000282, 0.017914000899, -0.093442000449, -0.435452997684, 0.599241018295, 0.600166976452, -0.085536003113, -0.361353993416, 0.147931993008, -0.145070001483, 0.277393013239, 0.016388999298, 0.262728989124, 0.212905004621, 0.189909994602, -0.292201012373, 0.332486003637, 0.308021992445, -0.036079999059, -0.271553009748, -0.20025600493, -0.090479001403, 0.268270999193, -0.272096991539, 0.199298992753, 0.15323600173, -0.348919987679, 0.290313988924, 0.180563002825, -0.179280996323, -0.239015996456, -0.279372006655, 0.237440004945, 0.588576972485, -0.73378098011, -0.176648005843, 0.382687985897, 0.023191999644, 0.218005001545, 0.104557998478, -0.209011003375, -0.139624997973, 0.429735004902, 0.027498999611, -0.114556998014, 0.439689993858, -0.343279987574, -0.206854000688, 0.510254979134, 0.38624098897, -0.413646996021, -0.354449987411, -0.344117999077, -0.059645000845, 0.084478996694, 0.013961999677, -0.162633001804, 0.16069200635, -0.239609003067, -0.710308015347, 0.490334004164, 0.209011003375, -0.068875998259, 0.620296001434, -0.67517799139, 0.308690011501, 0.349496990442, 0.543331027031, 0.014736999758, 0.265686988831, -0.242991000414, 0.08111499995, 0.433555006981, 0.534663021564, 0.440093994141, 0.046149998903, 0.456764996052, -0.426779985428, 1.205618023872, 0.433625012636, 0.19698600471, -0.024245999753, -0.195654004812, 0.778258979321, 1.02594602108, -0.0279610008, -0.08894199878, -0.757061004639, 0.001425000024, -0.355924993753, 0.055286001414, 0.080266997218, 0.389950990677, -0.39531698823, 0.532419979572, 0.106784999371, -0.050149999559, -0.230510994792, 0.41841301322, 0.785488009453, 0.17853499949, 0.012822999619, 0.533285975456, 0.046064998955, 0.457116991282, -0.336412996054, 0.086345002055, -0.490134000778, -0.060506001115, 0.505389988422, -0.440815001726, 0.701705992222, 0.233691006899, -0.556469976902, -0.175993993878, 0.047694001347, -0.439999997616, 0.048073999584, 0.32014799118, -0.157723993063, -0.406812012196, -0.235781997442, 0.149423003197, 0.221878007054, 0.274697005749, -0.336528003216, -0.027574999258, -0.05121299997, 0.049157001078, -0.061744999141, 0.571139991283, -0.426824986935, -0.511521995068, -0.180418998003, -0.173777997494, -0.501815021038, 0.165115997195, -0.52134001255, -0.110209003091, -0.296977996826, 0.113278999925, -0.254267007113, 0.274937003851, 0.171541005373, 0.226473003626, -0.05610800162, -0.063437998295, 0.179731994867, 0.016723999754, -0.181597992778, -0.0923660025, 0.297807008028, 0.402370989323, -0.933079004288, -0.062503002584, 0.156483992934, 0.066535003483, -0.129124999046, -0.464343994856, 0.046394001693, -0.510720014572, 0.117109999061, -0.378863990307, 0.104653000832, 0.297672003508, 0.057688999921, -0.290758013725, -0.042853001505, 0.69950902462, -0.666705012321, -0.062345001847, 0.131890997291, 0.12205799669, 0.190595000982, 0.141661003232, -0.141069993377, 0.29548099637, -0.252436995506, -0.12503400445, 0.245934993029, 0.292874008417, -0.207329005003, -0.592303991318}, processTime:“0″}

set aList to |vector| of aRec
set bList to |vector| of bRec
set cList to |vector| of cRec

set aRes to calcCosinSimilarity(aList, bList) of me –ガンダムとアムロ・レイ
set bRes to calcCosinSimilarity(aList, cList) of me –ガンダムとガンキャノン
set cRes to calcCosinSimilarity(bList, cList) of me –アムロ・レイとガンキャノン

return {aRes, bRes, cRes}
–> {44.057800255168, 50.555325012947, 32.83911534787}
–(1)「ガンダムとガンキャノン」、(2)「ガンダムとアムロ・レイ」、(3)「アムロ・レイとガンキャノン」の順番

–コサイン類似度をベクターのリストから計算する
on calcCosinSimilarity(aList, bList)
  set aLen to length of aList
  
set bLen to length of bList
  
if aLenbLen then error “Not Same Item Nums”
  
  
set aRes to 0
  
repeat with i from 1 to aLen
    set a1 to (contents of item i of aList)
    
set b1 to (contents of item i of bList)
    
    
set vL to getVectorLength(a1, b1) of me
    
set normF to (1 / vL)
    
set aRes to aRes + ((a1 * normF) * (b1 * normF))
  end repeat
  
  
return aRes
end calcCosinSimilarity

–ベクトルの長さを求める
on getVectorLength(a, b)
  return getSQR(a ^ 2 + b ^ 2) of me
end getVectorLength

–平方根を求める
on getSQR(aNum)
  return (aNum ^ 0.5)
end getSQR

★Click Here to Open This Script 

2016/10/28 ベクトルのコサイン類似度を計算する

ベクトル同士の類似度を求めるために、2つのベクトル同士のコサイン類似度を計算するAppleScriptです。

なんのことやら?(^ー^;;; 

だいたい、なぜこんなものを作ってみたかといえば、Apitoreの「単語ベクトル変換【新語対応】」というWebサービスをAppleScriptから呼び出して、200次元のベクトルを取得。このベクトル同士の類似度を計算する方法を聞いてみたところ、「コサイン距離を求めればわかるよー」とのこと。

本来、単語同士の類似度を計算するサービスはApitoreの「Word2Vec-Neologd-Wiki」にあるSimilarity APIがあり、これを呼べば2つの単語の意味的な近さを求めてくれます。

ただ、ベクトル同士の近さを求める「やりかた」自体は理解しておいたほうがよいと考え、やや「車輪の再発明」的な内容であるものの、調べて、理解して、実装してみました。

なんだー、要素ごとに掛け算して足すだけでいいんじゃん(汗) というわけで、いろいろ実際に計算した内容を検証してみました。

A「富士山」B「エベレスト」C「きゃりーぱみゅぱみゅ」という3つの単語のベクトルを単語ベクトル変換【新語対応】から求め、AとB、AとC、BとCの3つのコサイン類似度の計算を行ってみました。

  富士山とエベレスト:9.96044011858
  富士山ときゃりーぱみゅぱみゅ:5.348813123563
  エベレストときゃりーぱみゅぱみゅ:6.25804549236

この結果から、これら3つの単語の間では「富士山とエベレスト」の類似度が高い、という計算結果が得られました(よかったよかった ^ー^;)。

ちなみに、A「ガンダム」B「アムロ・レイ」C「ガンキャノン」で類似度を計算してみたところ、

  ガンダムとアムロ・レイ:14.92435981554
  ガンダムとガンキャノン:17.465853286865
  アムロ・レイとガンキャノン:15.693039744314

「ガンダムとガンキャノン」というメカ同士の類似度が高いという結果が得られた一方で、アムロ・レイと距離が近いのがガンダムよりもガンキャノンだという謎の計算結果が出てきました。これは、学習データの内容によりものでしょうか。それとも、「こまけえことはいいんだよ」というレベルの問題なんでしょうか。

→ ベクトルを長さで正規化すると解決するとのこと。さぁ、勉強だ(汗)

AppleScript名:ベクトルのコサイン類似度を計算する
– Created 2016-10-28 by Takaaki Naganoya
– 2016 Piyomaru Software
–以下のページを参照しました
–http://www.cse.kyoto-su.ac.jp/~g0846020/keywords/cosinSimilarity.html

–http://piyocast.com/as/archives/4292

set aRec to {startTime:“1477632528599″, |word|:“富士山”, endTime:“1477632528599″, |log|:“Success.”, |vector|:{0.123668000102, -0.309015005827, 0.120112001896, -0.044573001564, 0.313836991787, 0.077581003308, 0.495095998049, -0.352721989155, 0.492121994495, 0.637359976768, 0.116067998111, 0.188023999333, -0.17861700058, -0.28166899085, -0.01465999987, 0.337170988321, -0.071643002331, 0.432227998972, -0.097863003612, -0.035069998354, -0.010216999799, -0.192351996899, 0.319081991911, -0.109619997442, 0.187950998545, -0.27009499073, -0.088083997369, 0.284711003304, 0.128161996603, -0.291191011667, -0.052581999451, -0.291323006153, -0.403849005699, 0.480201989412, -0.261173009872, -0.603130996227, 0.340840995312, -0.538646996021, 0.441242009401, 0.168537005782, -0.287396997213, 0.027472000569, 0.478017985821, 0.006159000099, -0.536579012871, -0.182714998722, -0.434570014477, -0.619507014751, -0.044015999883, -0.066451996565, 0.252929985523, 0.088529996574, -0.263377010822, 0.312680006027, 0.174722999334, -0.117349997163, 0.059971999377, -0.477564007044, -0.220599994063, 0.322254002094, -0.093304999173, 0.297847986221, -0.308070003986, 0.007362000179, -0.201299995184, 0.564171016216, 0.197040006518, -0.212391003966, -0.332953006029, -0.015080000274, 0.061990000308, 0.300307005644, 0.063493996859, -0.033411998302, -0.274958997965, -0.239563003182, -0.499040007591, 0.127872005105, -0.08571100235, 0.209193006158, -0.010835999623, -0.373616993427, -0.13042999804, 0.322919011116, 0.569968998432, 0.135514006019, 0.412106990814, 0.246760994196, 0.584402024746, 0.038107000291, 0.485549002886, 0.36462700367, 0.210249006748, 0.168840005994, -0.015666000545, -0.231536999345, -0.339715987444, 0.12304700166, -0.186777994037, -0.291483014822, 0.328925997019, -0.075723998249, -0.313980996609, -0.460673004389, -0.305492013693, 0.083364002407, 0.28477498889, 0.163294002414, 0.020129000768, 0.138465002179, -0.280802994967, 0.0436029993, 0.114759996533, -0.494895011187, 0.526228010654, 0.214810997248, 0.592833995819, -0.495696008205, 0.446736991405, 0.147870004177, 0.09175799787, -0.071817003191, 0.095923997462, -0.323009997606, 0.282640010118, 0.197969004512, 0.017850000411, -0.220227003098, 0.057261001319, 0.5905200243, -0.261938005686, 0.238176003098, -0.202760994434, -0.042277999222, 0.639414012432, -0.042134001851, -0.076684996486, -0.118372000754, 0.333503007889, -0.22937899828, -0.299755007029, -0.443275988102, -0.31064799428, 0.301041990519, -0.056919999421, 0.286974996328, 0.50066202879, -0.196336001158, 0.005377999973, -0.049904000014, -0.872128009796, 0.097332000732, 0.273398011923, 0.015759000555, -0.182218998671, 0.018466999754, 0.619598984718, 0.276064991951, -0.191751003265, 0.025626000017, 0.12149900198, 0.00335699995, -0.112106002867, -0.097810000181, 0.170493006706, 0.321725994349, 0.06719700247, -0.009019000456, -0.056265998632, 0.147505998611, 0.136828005314, 0.228912994266, 0.329273998737, -0.011854999699, 0.038917001337, -0.122969001532, 0.194609001279, -0.158902004361, -0.372310996056, -0.433764994144, 0.023022999987, 0.764874994755, 0.246930003166, -0.331984996796, -0.00559599977, 0.078703999519, 0.091015003622, 0.119796998799, 0.006475999951, 0.124388001859, 0.199450001121, 0.327385008335, -0.006484000012, 0.067487999797, 0.17902199924, -0.356110006571, -0.206619992852, 0.086388997734, -0.275979995728, -0.136234998703}, processTime:“0″}

set bRec to {startTime:“1477632723419″, |word|:“エベレスト”, endTime:“1477632723419″, |log|:“Success.”, |vector|:{0.232161998749, -0.021962000057, 0.018812000751, 0.019821999595, -0.172334998846, -0.207186996937, 0.131844997406, -0.304751992226, -0.044002000242, 0.681266009808, -0.321467995644, 0.303873986006, -0.19711600244, -0.806095004082, -0.046836998314, -0.160034000874, 0.036371000111, 0.706255972385, 0.053663000464, -0.246535003185, -0.13503099978, 0.073703996837, 0.197100996971, -0.171170994639, 0.193028002977, -0.215641006827, 0.220181003213, 0.603963017464, 0.208072006702, 0.188728004694, 0.088546000421, -0.361923009157, 0.07780700177, -0.059170998633, -0.068483002484, -0.805943012238, 0.122937999666, -0.318515002728, 0.465512007475, 0.264575988054, -0.308703988791, -0.162440001965, 0.371463000774, 0.011003999971, -0.44861599803, -0.052464999259, -0.079640999436, -0.742060005665, 0.004040999804, 0.00926699955, 0.106600999832, 0.023274000734, -0.225715994835, -0.023219000548, 0.003835000098, 0.330017000437, 0.450482994318, -0.321902990341, 0.221350997686, -0.031302001327, -0.074280999601, -0.057861000299, 0.122330002487, 0.359564006329, -0.182457000017, 0.15286000073, 0.300184994936, -0.264039993286, -0.23186199367, -0.212647005916, 0.022517999634, 0.06595300138, 0.322301000357, -0.685081005096, -0.207968994975, 0.125552996993, -0.568157970905, 0.373304992914, -0.317216992378, -0.200730994344, -0.078373000026, -0.423943012953, -0.145215004683, -0.07396300137, 0.174961999059, 0.653276979923, 0.163136005402, -0.386029005051, 0.318922996521, -0.397913008928, 0.446060985327, -0.020895000547, -0.65869897604, 0.412039995193, 0.343986004591, 0.147389993072, -0.001555999974, 0.19599199295, 0.128003999591, -0.560048997402, -0.031364999712, 0.103477999568, -0.62273401022, -0.152143999934, -0.769581973553, 0.329198986292, -0.024667000398, 0.061011999846, 0.203813001513, 0.300633996725, -0.918317019939, -0.110868997872, 0.058814998716, -0.473046988249, 0.317030012608, 0.014874000102, 0.756187975407, -0.373053014278, 0.016914999112, -0.286927014589, 0.038632001728, -0.183412998915, 0.010959000327, -0.632750988007, 0.469480007887, -0.218618005514, 0.113091997802, -0.177783995867, -0.068285003304, -0.108176998794, -0.384323000908, -0.139712005854, -0.224274992943, 0.281195014715, 0.324263989925, 0.230408996344, 0.055860001594, -0.027174999937, -0.079732000828, -0.390644013882, -0.561515986919, -0.64296400547, 0.074805997312, -0.134819999337, 0.699452996254, -0.097543999553, 0.650906980038, 0.016352999955, 0.237734004855, 0.100365996361, 0.281136989594, 0.074234999716, 0.2350410074, -0.754948019981, -0.447870999575, 0.170350000262, 0.469761997461, 0.075043998659, -0.560901999474, 0.050087001175, 0.067097000778, -0.204071000218, -0.089464001358, -0.604591012001, 0.399424999952, -0.188191995025, -0.184063002467, -0.275462001562, -0.438647985458, -0.028305999935, -0.10909999907, 0.306037008762, 0.553808987141, -0.042507998645, -0.089280001819, -0.030742000788, 0.307033002377, -0.102701000869, -0.226081997156, 0.122754998505, -0.509634971619, 0.82189899683, 0.012555999681, -0.309893995523, 0.617228984833, 0.13081599772, 0.264277994633, -0.521031022072, 0.369996011257, 0.402808994055, 0.169545993209, -0.144013002515, -0.26952201128, 0.852178990841, 0.489789992571, -0.407970011234, -0.20611999929, -0.025805000216, -0.042392000556, -0.245032995939}, processTime:“0″}

set cRec to {startTime:“1477632906147″, |word|:“きゃりーぱみゅぱみゅ”, endTime:“1477632906147″, |log|:“Success.”, |vector|:{0.117769002914, 0.547421991825, -0.55005300045, -0.004116999917, 0.037840001285, -0.220541000366, 0.278791993856, -0.126565992832, -0.11717300117, -0.134132996202, -0.169262006879, -0.047348998487, 0.139651998878, 0.096625000238, -0.524344027042, 0.171568006277, -0.438012003899, 0.096740998328, 0.181114003062, -0.507890999317, -0.162144005299, -0.256267994642, 0.787092983723, -0.301274001598, -0.131623998284, -0.667850971222, 0.126826003194, 0.399556994438, -0.331470012665, 0.086039997637, -0.207508996129, -0.341479003429, 0.453637003899, 0.682955026627, 0.022078000009, -0.187252998352, 0.1002940014, -0.123255997896, 0.297253012657, 0.347470998764, 0.979870975018, 0.439393997192, 0.264191001654, -0.245868995786, -0.534951984882, 0.524555027485, -0.281354993582, -0.382270008326, -0.550571024418, -0.219003006816, 0.700820982456, 0.090194001794, 0.438223004341, 0.132016003132, -0.120622001588, 0.094403997064, -0.341901004314, -0.091567002237, 0.096225000918, -0.574598014355, 0.054416999221, -0.12799499929, 0.207303002477, 0.40427801013, 0.237173005939, 0.645721971989, 0.359672009945, -0.744382977486, 0.071580000222, 0.231180995703, 0.02777400054, 0.596056997776, 0.363346010447, -0.457264989614, -0.19236600399, -0.514294981956, -0.183853000402, 0.215189993382, -0.372281998396, -0.235982000828, 0.153041005135, -0.050188001245, 0.359631001949, -0.440890014172, 0.174553006887, -0.100065998733, 0.210250005126, 0.280330985785, 0.398196995258, 0.281033992767, 0.437768012285, 0.521552026272, -0.481240004301, -0.100391998887, 0.687992990017, 0.415670007467, 0.054366998374, 0.302630990744, 0.081652998924, -0.326240986586, 0.312976002693, 0.380755007267, 0.360621005297, -0.277276992798, -0.586230993271, 0.284016996622, -0.145888999104, -0.001132000005, 0.148311004043, 0.462684988976, -0.186974003911, -0.078097999096, -0.23281699419, -0.601405024529, 0.15837700665, 0.270709007978, 0.093841001391, -0.415028005838, 0.17201000452, -0.199463993311, -0.206508994102, 0.053318999708, 0.02006999962, -0.278010010719, 0.069329999387, -0.211704999208, 0.353031992912, 0.172609999776, 0.551793992519, 0.14820599556, -0.182607993484, 0.301723003387, -0.48807901144, 0.072370998561, 0.105828002095, 0.417632997036, 0.369803994894, -0.471235990524, 0.064530000091, -0.206820994616, -0.28040599823, 0.652179002762, -0.340546995401, 0.400236010551, 0.204622000456, 0.056784000248, -0.331907987595, 0.029787000269, -0.311051011086, -0.262612998486, -0.001846999978, 0.027634000406, 0.312009006739, -0.03695999831, -0.153132006526, -0.026866000146, 0.039252001792, 0.203341007233, -0.157428994775, 0.121481001377, -0.154116004705, -0.0451150015, 0.686644017696, -0.484241992235, 0.184045001864, 0.30873298645, 0.204081997275, -0.321480989456, 0.391580998898, -0.106555998325, -0.475353002548, 0.141835004091, 0.37692001462, 0.202901005745, 0.021635999903, 0.070069000125, 0.195032000542, 0.300967991352, -0.341152012348, 0.018368000165, 0.102963000536, 0.260273009539, -0.323379009962, -0.125611007214, 0.145910993218, 0.321619004011, -0.191367998719, 0.006186999846, 0.089144997299, 0.144384995103, -0.150334000587, 0.465972006321, -0.099472999573, -0.001772999996, 0.331198006868, -0.031812999398, -0.196685001254, 0.192193999887, -0.468513011932, 0.307538002729}, processTime:“0″}

set aList to |vector| of aRec
set bList to |vector| of bRec
set cList to |vector| of cRec

set aRes to calcCosinSimilarity(aList, bList) of me –富士山とエベレスト
set bRes to calcCosinSimilarity(aList, cList) of me –富士山ときゃりーぱみゅぱみゅ
set cRes to calcCosinSimilarity(bList, cList) of me –エベレストときゃりーぱみゅぱみゅ

return {aRes, bRes, cRes}
–> {9.96044011858, 5.348813123563, 6.25804549236}–「富士山とエベレスト」の距離が一番近い

–コサイン類似度をベクターのリストから計算する
on calcCosinSimilarity(aList, bList)
  set aLen to length of aList
  
set bLen to length of bList
  
if aLenbLen then error “Not Same items”
  
  
set aRes to 0
  
repeat with i from 1 to aLen
    set a1 to contents of item i of aList
    
set b1 to contents of item i of bList
    
set c to a1 * b1
    
set aRes to aRes + c
  end repeat
  
  
return aRes
end calcCosinSimilarity

★Click Here to Open This Script 

2016/10/27 ドライブマウント検出

外付けドライブをUSB端子などに接続/脱着して実際にマウント/アンマウントが発生したことを検出するAppleScriptです。

# たいへんによくありがちなものです(^ー^;;;;

アプレット(アプリケーション)として、「ハンドラの実行後に終了しない」にチェックを入れつつ書き出して実行し、常駐させておいてください。

drivemount.jpg

とりあえずお手軽にsayコマンドで音声案内をしていますが、ここを自分でさらに拡張するとよいでしょう。

1日中常駐させて動かしていたら、Time Machineのクリーンナップ動作時やソフトウェアのアップデートインストール時などに細かくマウント→アンマウントを実行するようで、やはりドライブの情報を取得しないと(汗)

AppleScript名:ドライブマウント検出
– Created 2016-10-27 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”
–http://piyocast.com/as/archives/4291

on run
  current application’s NSWorkspace’s sharedWorkspace()’s notificationCenter()’s addObserver:me selector:“onVolumeMount:” |name|:“NSWorkspaceDidMountNotification” object:(missing value)
  
  
current application’s NSWorkspace’s sharedWorkspace()’s notificationCenter()’s addObserver:me selector:“onVolumeUnmount:” |name|:“NSWorkspaceDidUnmountNotification” object:(missing value)
end run

on onVolumeMount:aNotif
  say “マウントしました” using “Kyoko” –Mount Message In Japanese
end onVolumeMount:

on onVolumeUnmount:aNotif
  say “アンマウントしました” using “Kyoko” –Unmount Message In Japanese
end onVolumeUnmount:

★Click Here to Open This Script 

2016/10/27 感情推定【極性判定】

Apitore「感情推定」APIを呼び出して、指定の日本語の文章がPositive(肯定的)かNegative(否定的)かを判定するAppleScriptです。

実行前にapitoreにユーザー登録を行い(無料)、Web上でアクセストークンを取得。そのトークンをretAccessToken()内で返すように書いておく必要があります(掲載のリストのまま実行すると、エラーになります。かならずアクセストークンを取得してください)。

用途は割といろいろあって、ちょっと考えただけでも、

「メールの文面をチェックして、日本語であれば(NSLinguisticTaggerを使って判定)感情推定APIを呼び出し、Negativeと判定されたらメールの一覧に赤く色をつける」

とかいうAppleScriptはかんたんに書けますし、便利だと思います(色付きメールを読みたくなくなる、とかいう心理的なフィードバックが発生することについてはさておき)。

また、

Safariの閲覧履歴を取得して、各URLにアクセスして本文のみ取得。読んだ内容がPositveかNegativeかの内訳をグラフで表示」

とかいうのも面白そうです。

テストしてみたところ、たまたまサーバー側で問題を起こしていた最中のようで、サンプルプログラム中に記述してある「かならずPositive(肯定的)と判定される例文」がNegative(否定的)と出てきて焦りましたが、じきに安定することでしょう。

AppleScript名:感情推定【極性判定】
– Created 2016-10-27 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
–http://piyocast.com/as/archives/4289

set aText to "おめでとう!カブスが4勝2敗でドジャースを下し、2016年ナ・リーグの覇者に!次は水曜日(10月26日)に行われるワールドシリーズでア・リーグの覇者インディアンスと対決!"

set reqURLStr to "https://api.apitore.com/api/11/sentiment/predict"
set accessToken to retAccessToken() —Access Token
set aRec to {access_token:accessToken, |text|:aText}
set aURL to retURLwithParams(reqURLStr, aRec) of me

set aRes to callRestGETAPIAndParseResults(aURL) of me

set aRESTres to (json of aRes) as record
return aRESTres
–>  {endTime:"1477617363491", processTime:"44", text:"おめでとう!カブスが4勝2敗でドジャースを下し、2016年ナ・リーグの覇者に!次は水曜日(10月26日)に行われるワールドシリーズでア・リーグの覇者インディアンスと対決!", log:"Success.", predict:{score:0.520746946335, sentiment:"positive"}, startTime:"1477617363447", sentimens:{{score:0.520746946335, sentiment:"positive"}, {score:0.479253053665, sentiment:"negative"}}}

–set aRESCode to (responseCode of aRes) as integer
–>  200

–set aRESHeader to (responseHeader of aRes) as record
–>  {Content-Type:"application/json;charset=UTF-8", Access-Control-Allow-Origin:"*", Pragma:"no-cache", X-XSS-Protection:"1; mode=block, 1; mode=block", Server:"nginx/1.10.1", Transfer-Encoding:"Identity", Expires:"0", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Date:"Thu, 27 Oct 2016 03:22:11 GMT", Strict-Transport-Security:"max-age=31536000; includeSubDomains;", Connection:"keep-alive", X-Content-Type-Options:"nosniff, nosniff", X-Frame-Options:"DENY, SAMEORIGIN"}

–GET methodのREST APIを呼ぶ
on callRestGETAPIAndParseResults(aURL)
  
  
set aRequest to current application’s NSMutableURLRequest’s requestWithURL:(current application’s |NSURL|’s URLWithString:aURL)
  
  
aRequest’s setHTTPMethod:"GET"
  
aRequest’s setCachePolicy:(current application’s NSURLRequestReloadIgnoringLocalCacheData)
  
aRequest’s setHTTPShouldHandleCookies:false
  
aRequest’s setTimeoutInterval:60
  
aRequest’s setValue:"application/json" forHTTPHeaderField:"Accept"
  
  
set aRes to current application’s NSURLConnection’s sendSynchronousRequest:aRequest returningResponse:(reference) |error|:(missing value)
  
set resList to aRes as list
  
  
set bRes to contents of (first item of resList)
  
set resStr to current application’s NSString’s alloc()’s initWithData:bRes encoding:(current application’s NSUTF8StringEncoding)
  
  
set jsonString to current application’s NSString’s stringWithString:resStr
  
set jsonData to jsonString’s dataUsingEncoding:(current application’s NSUTF8StringEncoding)
  
set aJsonDict to current application’s NSJSONSerialization’s JSONObjectWithData:jsonData options:0 |error|:(missing value)
  
  
–Get Response Code & Header
  
set dRes to contents of second item of resList
  
if dRes is not equal to missing value then
    set resCode to (dRes’s statusCode()) as number
    
set resHeaders to (dRes’s allHeaderFields()) as record
  else
    set resCode to 0
    
set resHeaders to {}
  end if
  
  
return {json:aJsonDict, responseCode:resCode, responseHeader:resHeaders}
  
end callRestGETAPIAndParseResults

on retAccessToken()
  return "xxxXxxXx-XXXX-XXXX-XxXX-XXxXXxxXXxxx" –API Tore Access Token
end retAccessToken

on retURLwithParams(aBaseURL, aRec)
  set aDic to current application’s NSMutableDictionary’s dictionaryWithDictionary:aRec
  
  
set aKeyList to (aDic’s allKeys()) as list
  
set aValList to (aDic’s allValues()) as list
  
set aLen to length of aKeyList
  
  
set qList to {}
  
repeat with i from 1 to aLen
    set aName to contents of item i of aKeyList
    
set aVal to contents of item i of aValList
    
set the end of qList to (current application’s NSURLQueryItem’s queryItemWithName:aName value:aVal)
  end repeat
  
  
set aComp to current application’s NSURLComponents’s alloc()’s initWithString:aBaseURL
  
aComp’s setQueryItems:qList
  
set aURL to (aComp’s |URL|()’s absoluteString()) as text
  
  
return aURL
end retURLwithParams

★Click Here to Open This Script 

2016/10/25 指定ムービーを指定形式に変換する v2

指定のムービーファイルを指定形式に変換するAppleScriptの改良版です。

一晩たったら、旧石器時代から現代までタイムスリップしたぐらいの改良が加わっています(汗)。野蛮な手段でファイル拡張子からUTIを求めていたのが、フレームワーク呼び出し一発で、、、処理速度も大幅に向上しています。

AppleScript名:指定ムービーを指定形式に変換する v2
– Created 2016-10-24 by Shane Stanley
– Modified 2016-10-24 by Takaaki Naganoya
– Modified 2016-10-25 by Shane Stanley
use AppleScript version “2.4″
use framework “Foundation”
use framework “AVFoundation”
use scripting additions
use BridgePlus : script “BridgePlus” –Version 1.3.2以降

load framework
–http://piyocast.com/as/archives/4288

set posixPath to POSIX path of (choose file with prompt “Choose a Movie file:”)
my convertMovieAt:posixPath ToType:“AVAssetExportPresetAppleM4A” withExtension:“m4a” deleteOriginal:false

–指定のムービーを、指定の書き出しプリセットで、指定のファイル形式で、オリジナルファイルを削除するかどうか指定しつつ書き出し
on convertMovieAt:(posixPath as string) ToType:(assetTypeStr as string) withExtension:(aExt as string) deleteOriginal:(deleteFlag as boolean)
  set theURL to current application’s |NSURL|’s fileURLWithPath:posixPath
  
  
set aPreset to current application’s NSString’s stringWithString:assetTypeStr
  
  
– set destination to use same path, different extension
  
set destURL to theURL’s URLByDeletingPathExtension()’s URLByAppendingPathExtension:aExt
  
set theAsset to current application’s AVAsset’s assetWithURL:theURL
  
  
– check asset can be converted
  
set allowedPresets to current application’s AVAssetExportSession’s exportPresetsCompatibleWithAsset:theAsset
  
if (allowedPresets’s containsObject:aPreset) as boolean is false then
    error “Can’t export this file as an .” & aExt & ” file.”
  end if
  
  
– set up export session
  
set fileTypeUTIstr to retFileFormatUTI(aExt) of me –ファイル拡張子からFile Type UTIを求める
  
set theSession to current application’s AVAssetExportSession’s exportSessionWithAsset:theAsset presetName:aPreset
  
theSession’s setOutputFileType:fileTypeUTIstr
  
theSession’s setOutputURL:destURL
  
  
– begin export and poll for completion
  
theSession’s exportAsynchronouslyWithCompletionHandler:(missing value)
  
repeat
    set theStatus to theSession’s status() as integer
    
if theStatus < 3 then
      delay 0.2
    else
      exit repeat
    end if
  end repeat
  
  
– throw error if it failed
  
if theStatus = (current application’s AVAssetExportSessionStatusFailed) as integer then
    error (theSession’s |error|()’s localizedDescription() as text)
  end if
  
  
– delete original if required
  
if deleteFlag then
    current application’s NSFileManager’s defaultManager()’s removeItemAtURL:theURL |error|:(missing value)
  end if
end convertMovieAt:ToType:withExtension:deleteOriginal:

on retFileFormatUTI(aExt as string)
  return (current application’s SMSForder’s UTIForExtension:aExt)
end retFileFormatUTI

★Click Here to Open This Script 

2016/10/25 ムービー系の拡張子からFile Format UTIを取得する v2, v3

ムービー系のファイルの拡張子から、File Format UTIを取得するAppleScriptの改良版です。

Shane Stanleyから指摘があって、

(1)com.apple.quicktime-movieと current application’s AVFileTypeQuickTimeMovieは同じものなので変換する必要はないよ(なんとなく、そうじゃないかとは思ってました ^ー^;;)

(2)BridgePlus v1.3.2に拡張子からUTIを求めるメソッドが用意してあるよ(!!!)

というわけで、(1)を反映させたv2、(2)まで反映させたv3を作成してみましたが、v3にいたってはたったの1行。どこかにもっとスマートな解決策が転がっていると思っていましたが、ここまでスマートになるとは(^ー^;;;

一応、試した範囲ではv1もv2もv3も実行結果は同じです。

AppleScript名:ムービー系の拡張子からFile Format UTIを取得する v2
– Created 2016-10-24 by Takaaki Naganoya
– Modified 2016-10-25 by Takaaki Naganoya
– Modified 2016-10-25 by Shane Stanley
– 2016 Piyomaru Software
use AppleScript version “2.4″
use framework “Foundation”
use framework “AVFoundation”
use framework “AppKit”
use scripting additions
–http://piyocast.com/as/archives/4287

set aRes to retFileFormatUTI(“mov”) of me
–>  (NSString) “com.apple.quicktime-movie”

set aRes to retFileFormatUTI(“mp4″) of me
–>  (NSString) “public.mpeg-4″

set aRes to retFileFormatUTI(“m4v”) of me
–>  (NSString) “com.apple.m4v-video”

set aRes to retFileFormatUTI(“m4a”) of me
–>  (NSString) “com.apple.m4a-audio”

set aRes to retFileFormatUTI(“3gp”) of me
–>  (NSString) “public.3gpp”

set aRes to retFileFormatUTI(“3gp2″) of me
–>  (NSString) “public.3gpp2″

set aRes to retFileFormatUTI(“caf”) of me
–>  (NSString) “com.apple.coreaudio-format”

set aRes to retFileFormatUTI(“wav”) of me
–>  (NSString) “com.microsoft.waveform-audio”

set aRes to retFileFormatUTI(“aif”) of me
–>  (NSString) “public.aifc-audio”

set aRes to retFileFormatUTI(“aifc”) of me
–>  (NSString) “public.aifc-audio”

set aRes to retFileFormatUTI(“amr”) of me
–>  (NSString) “org.3gpp.adaptive-multi-rate-audio”

set aRes to retFileFormatUTI(“mp3″) of me
–>  (NSString) “public.mp3″

set aRes to retFileFormatUTI(“au”) of me
–>  (NSString) “public.au-audio”

set aRes to retFileFormatUTI(“ac3″) of me
–>  (NSString) “public.ac3-audio”

on retFileFormatUTI(aExt)
  set theWorkspace to current application’s NSWorkspace’s sharedWorkspace()
  
set valList to {“com.apple.quicktime-movie”, “public.mpeg-4″, “com.apple.m4v-video”, “com.apple.m4a-audio”, “public.3gpp”, “public.3gpp2″, “com.apple.coreaudio-format”, “com.microsoft.waveform-audio”, “public.aiff-audio”, “public.aifc-audio”, “org.3gpp.adaptive-multi-rate-audio”, “public.mp3″, “public.au-audio”, “public.ac3-audio”}
  
repeat with aUTI in valList
    if (theWorkspace’s filenameExtension:aExt isValidForType:aUTI) as boolean then
      return (current application’s NSString’s stringWithString:aUTI)
    end if
  end repeat
  
error “Invalid Constant String”
end retFileFormatUTI

★Click Here to Open This Script 

AppleScript名:ムービー系の拡張子からFile Format UTIを取得する v3
– Created 2016-10-24 by Takaaki Naganoya
– Modified 2016-10-25 by Shane Stanley
– 2016 Piyomaru Software
use AppleScript version “2.4″
use framework “Foundation”
use framework “AVFoundation”
use scripting additions
use BridgePlus : script “BridgePlus” –Version 1.3.2以降
load framework

–http://piyocast.com/as/archives/4287

set aRes to retFileFormatUTI(“mov”) of me
–>  (NSString) “com.apple.quicktime-movie”

set aRes to retFileFormatUTI(“mp4″) of me
–>  (NSString) “public.mpeg-4″

set aRes to retFileFormatUTI(“m4v”) of me
–>  (NSString) “com.apple.m4v-video”

set aRes to retFileFormatUTI(“m4a”) of me
–>  (NSString) “com.apple.m4a-audio”

set aRes to retFileFormatUTI(“3gp”) of me
–>  (NSString) “public.3gpp”

set aRes to retFileFormatUTI(“3gp2″) of me
–>  (NSString) “public.3gpp2″

set aRes to retFileFormatUTI(“caf”) of me
–>  (NSString) “com.apple.coreaudio-format”

set aRes to retFileFormatUTI(“wav”) of me
–>  (NSString) “com.microsoft.waveform-audio”

set aRes to retFileFormatUTI(“aif”) of me
–>  (NSString) “public.aifc-audio”

set aRes to retFileFormatUTI(“aifc”) of me
–>  (NSString) “public.aifc-audio”

set aRes to retFileFormatUTI(“amr”) of me
–>  (NSString) “org.3gpp.adaptive-multi-rate-audio”

set aRes to retFileFormatUTI(“mp3″) of me
–>  (NSString) “public.mp3″

set aRes to retFileFormatUTI(“au”) of me
–>  (NSString) “public.au-audio”

set aRes to retFileFormatUTI(“ac3″) of me
–>  (NSString) “public.ac3-audio”

on retFileFormatUTI(aExt as string)
  return (current application’s SMSForder’s UTIForExtension:aExt)
end retFileFormatUTI

★Click Here to Open This Script 

2016/10/24 指定ムービーを指定形式に変換する

指定のムービーファイルを指定形式に変換するAppleScriptです。

オリジナルはShane StanleyがAppleScript Users-MLに投稿したものですが、変換(エクスポート)形式が固定で指定されていました(ムービーからオーディオ部のみ書き出し)。

たいへんに有用性が高いものの、エクスポート形式固定のままでは使い勝手がいまひとつだったので、形式を可変指定できるように改修してみました。

エクスポート形式で指定可能なものは、このように一覧を取得できます。この中から選択してください。

本Scriptをそのまま実行すると、指定のムービーファイルから音声部分のみ、同一ファイル名で拡張子を「m4a」にした別ファイルをオリジナルのファイルと同一フォルダ内に書き出します。オリジナルのファイルは消去せずにそのまま残す設定です。

AppleScript名:指定ムービーを指定形式に変換する
– Created 2016-10-24 by Shane Stanley
– Modified 2016-10-24 by Takaaki Naganoya
use AppleScript version “2.4″
use framework “Foundation”
use framework “AVFoundation”
use scripting additions
–http://piyocast.com/as/archives/4286

set posixPath to POSIX path of (choose file with prompt “Choose a Movie file:”)
my convertMovieAt:posixPath ToType:“AVAssetExportPresetAppleM4A” withExtension:“m4a” deleteOriginal:false

–指定のムービーを、指定の書き出しプリセットで、指定のファイル形式で、オリジナルファイルを削除するかどうか指定しつつ書き出し
on convertMovieAt:(posixPath as string) ToType:(assetTypeStr as string) withExtension:(aExt as string) deleteOriginal:(deleteFlag as boolean)
  set theURL to current application’s |NSURL|’s fileURLWithPath:posixPath
  
  
set aPreset to current application’s NSString’s stringWithString:assetTypeStr
  
  
– set destination to use same path, different extension
  
set destURL to theURL’s URLByDeletingPathExtension()’s URLByAppendingPathExtension:aExt
  
set theAsset to current application’s AVAsset’s assetWithURL:theURL
  
  
– check asset can be converted
  
set allowedPresets to current application’s AVAssetExportSession’s exportPresetsCompatibleWithAsset:theAsset
  
if (allowedPresets’s containsObject:aPreset) as boolean is false then
    error “Can’t export this file as an .” & aExt & ” file.”
  end if
  
  
– set up export session
  
set fileTypeUTIstr to retFileFormatUTI(aExt) of me –ファイル拡張子からFile Type UTIを求める
  
set theSession to current application’s AVAssetExportSession’s exportSessionWithAsset:theAsset presetName:aPreset
  
theSession’s setOutputFileType:fileTypeUTIstr
  
theSession’s setOutputURL:destURL
  
  
– begin export and poll for completion
  
theSession’s exportAsynchronouslyWithCompletionHandler:(missing value)
  
repeat
    set theStatus to theSession’s status() as integer
    
if theStatus < 3 then
      delay 0.2
    else
      exit repeat
    end if
  end repeat
  
  
– throw error if it failed
  
if theStatus = (current application’s AVAssetExportSessionStatusFailed) as integer then
    error (theSession’s |error|()’s localizedDescription() as text)
  end if
  
  
– delete original if required
  
if deleteFlag then
    current application’s NSFileManager’s defaultManager()’s removeItemAtURL:theURL |error|:(missing value)
  end if
end convertMovieAt:ToType:withExtension:deleteOriginal:

on retFileFormatUTI(aExt as string)
  set aUTIstr to getUTIfromNameExtension(aExt) of me
  
set keyList to {current application’s AVFileTypeQuickTimeMovie, current application’s AVFileTypeMPEG4, current application’s AVFileTypeAppleM4V, current application’s AVFileTypeAppleM4A, current application’s AVFileType3GPP, current application’s AVFileType3GPP2, current application’s AVFileTypeCoreAudioFormat, current application’s AVFileTypeWAVE, current application’s AVFileTypeAIFF, current application’s AVFileTypeAIFC, current application’s AVFileTypeAMR, current application’s AVFileTypeMPEGLayer3, current application’s AVFileTypeSunAU, current application’s AVFileTypeAC3}
  
set valList to {“com.apple.quicktime-movie”, “public.mpeg-4″, “com.apple.m4v-video”, “com.apple.m4a-audio”, “public.3gpp”, “public.3gpp2″, “com.apple.coreaudio-format”, “com.microsoft.waveform-audio”, “public.aiff-audio”, “public.aifc-audio”, “org.3gpp.adaptive-multi-rate-audio”, “public.mp3″, “public.au-audio”, “public.ac3-audio”}
  
if aUTIstr is not in valList then
    error “Invalid Constant String”
  end if
  
  
set aPos to offsetOf(valList, aUTIstr) of me
  
set cRes to contents of item aPos of keyList
  
return cRes
end retFileFormatUTI

on offsetOf(aList as list, aTarg)
  set aArray to current application’s NSArray’s arrayWithArray:aList
  
set aIndex to (aArray’s indexOfObject:aTarg) as number
  
return (aIndex + 1)
end offsetOf

–ファイル拡張子からUTI文字列を取得する
on getUTIfromNameExtension(anExtStr as string)
  set aTempPath to (POSIX path of (path to temporary items from user domain))
  
set aTempName to (current application’s NSUUID’s UUID()’s UUIDString()) as string
  
set bTempPath to (aTempPath & aTempName & “.” & anExtStr)
  
do shell script “touch “ & quoted form of bTempPath
  
set utiStr to current application’s NSWorkspace’s sharedWorkspace()’s typeOfFile:bTempPath |error|:(missing value)
  
do shell script “rm -f “ & quoted form of bTempPath
  
return utiStr as string
end getUTIfromNameExtension

★Click Here to Open This Script 

2016/10/24 指定のムービーファイルのエクスポート可能な形式一覧を取得する

指定のムービーファイルのエクスポート(書き出し)可能なファイル形式一覧を取得するAppleScriptです。

AppleScript名:指定のムービーファイルのエクスポート可能な形式一覧を取得する
– Created 2016-10-24 by Shane Stanley
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AVFoundation"
–http://piyocast.com/as/archives/4285

set posixPath to POSIX path of (choose file with prompt "Choose an Movie file:")
set theURL to current application’s |NSURL|’s fileURLWithPath:posixPath
set theAsset to current application’s AVAsset’s assetWithURL:theURL
set allowedPresets to current application’s AVAssetExportSession’s exportPresetsCompatibleWithAsset:theAsset
–>  (NSArray) {"AVAssetExportPreset1920×1080", "AVAssetExportPresetLowQuality", "AVAssetExportPresetAppleM4V720pHD", "AVAssetExportPresetAppleM4VAppleTV", "AVAssetExportPresetAppleM4A", "AVAssetExportPreset640×480", "AVAssetExportPresetAppleProRes422LPCM", "AVAssetExportPreset3840×2160", "AVAssetExportPresetAppleM4VWiFi", "AVAssetExportPresetHighestQuality", "AVAssetExportPresetAppleM4VCellular", "AVAssetExportPreset1280×720", "AVAssetExportPresetMediumQuality", "AVAssetExportPresetAppleM4V1080pHD", "AVAssetExportPresetAppleM4V480pSD", "AVAssetExportPreset960×540", "AVAssetExportPresetAppleM4ViPod"}

★Click Here to Open This Script 

2016/10/24 ムービー系の拡張子からFile Format UTIを取得する

ムービー系のファイル拡張子(movとか)から、File Format UTI(AVFileTypeQuickTimeMovieとか)を取得するAppleScriptです。

filetypeuti.jpg

だいたい予想どおりの動きをしていますが、下位ルーチン(ファイル拡張子からUTIを取得する)の動作の問題か、AIFF audioとAIFC audioが同一視されています(どちらもAIFC=public.aifc-audioになる)。AIFFとAIFCの区別ができていない点にのみ注意を要します。

AppleScript名:ムービー系の拡張子からFile Format UTIを取得する
– Created 2016-10-24 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version "2.4"
use framework "Foundation"
use framework "AVFoundation"
use framework "AppKit"
use scripting additions
–http://piyocast.com/as/archives/4283

set aRes to retFileFormatUTI("mov") of me
–>  (NSString) "com.apple.quicktime-movie"

set aRes to retFileFormatUTI("mp4") of me
–>  (NSString) "public.mpeg-4"

set aRes to retFileFormatUTI("m4v") of me
–>  (NSString) "com.apple.m4v-video"

set aRes to retFileFormatUTI("m4a") of me
–>  (NSString) "com.apple.m4a-audio"

set aRes to retFileFormatUTI("3gp") of me
–>  (NSString) "public.3gpp"

set aRes to retFileFormatUTI("3gp2") of me
–>  (NSString) "public.3gpp2"

set aRes to retFileFormatUTI("caf") of me
–>  (NSString) "com.apple.coreaudio-format"

set aRes to retFileFormatUTI("wav") of me
–>  (NSString) "com.microsoft.waveform-audio"

set aRes to retFileFormatUTI("aif") of me
–>  (NSString) "public.aifc-audio"

set aRes to retFileFormatUTI("aifc") of me
–>  (NSString) "public.aifc-audio"

set aRes to retFileFormatUTI("amr") of me
–>  (NSString) "org.3gpp.adaptive-multi-rate-audio"

set aRes to retFileFormatUTI("mp3") of me
–>  (NSString) "public.mp3"

set aRes to retFileFormatUTI("au") of me
–>  (NSString) "public.au-audio"

set aRes to retFileFormatUTI("ac3") of me
–>  (NSString) "public.ac3-audio"

on retFileFormatUTI(aExt as string)
  set aUTIstr to getUTIfromNameExtension(aExt) of me
  
set keyList to {current application’s AVFileTypeQuickTimeMovie, current application’s AVFileTypeMPEG4, current application’s AVFileTypeAppleM4V, current application’s AVFileTypeAppleM4A, current application’s AVFileType3GPP, current application’s AVFileType3GPP2, current application’s AVFileTypeCoreAudioFormat, current application’s AVFileTypeWAVE, current application’s AVFileTypeAIFF, current application’s AVFileTypeAIFC, current application’s AVFileTypeAMR, current application’s AVFileTypeMPEGLayer3, current application’s AVFileTypeSunAU, current application’s AVFileTypeAC3}
  
set valList to {"com.apple.quicktime-movie", "public.mpeg-4", "com.apple.m4v-video", "com.apple.m4a-audio", "public.3gpp", "public.3gpp2", "com.apple.coreaudio-format", "com.microsoft.waveform-audio", "public.aiff-audio", "public.aifc-audio", "org.3gpp.adaptive-multi-rate-audio", "public.mp3", "public.au-audio", "public.ac3-audio"}
  
if aUTIstr is not in valList then
    error "Invalid Constant String"
  end if
  
  
set aPos to offsetOf(valList, aUTIstr) of me
  
set cRes to contents of item aPos of keyList
  
return cRes
end retFileFormatUTI

on offsetOf(aList as list, aTarg)
  set aArray to current application’s NSArray’s arrayWithArray:aList
  
set aIndex to (aArray’s indexOfObject:aTarg) as number
  
return (aIndex + 1)
end offsetOf

–ファイル拡張子からUTI文字列を取得する
on getUTIfromNameExtension(anExtStr as string)
  set aTempPath to (POSIX path of (path to temporary items from user domain))
  
set aTempName to (current application’s NSUUID’s UUID()’s UUIDString()) as string
  
set bTempPath to (aTempPath & aTempName & "." & anExtStr)
  
do shell script "touch " & quoted form of bTempPath
  
set utiStr to current application’s NSWorkspace’s sharedWorkspace()’s typeOfFile:bTempPath |error|:(missing value)
  
do shell script "rm -f " & quoted form of bTempPath
  
return utiStr as string
end getUTIfromNameExtension

★Click Here to Open This Script 

2016/10/24 ファイル拡張子からUTIを取得する v1

ファイル名の拡張子の文字列からUTI(Uniform Type Identifier)の文字列を取得するAppleScriptです。

当初、Cocoaの機能を用いて簡単に求められるだろうとタカをくくっていたのですが、ネット上で見つけた方法ではCの機能を使っているため(UTTypeCreatePreferredIdentifierForTagを使用)、AppleScriptからは逆立ちしても呼び出せませんでした。

できないことがわかったので、少々気楽になりました。スマートな解決方法がとれないのであれば、スマートではない野蛮な方法を使えばいいわけです。

そんなわけで、指定の拡張子をつけた一時ファイルを作成し、その一時ファイルからUTIの情報を取得しています。HDD搭載でかつ極端にCPUが遅いマシンの場合には、ファイル書き込みしたあとに”sync”を実行しておくとよいかもしれません(最近はそんな極限環境には滅多にお目にかからないのですが、ねんのため)。

そのうち、もっとスマートな方法がみつかることでしょう。

AppleScript名:ファイル拡張子からUTIを取得する v1
– Created 2016-10-24 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”
–http://piyocast.com/as/archives/4282

set aUTIstr to getUTIfromNameExtension(“m4a”) of me
–>  ”com.apple.m4a-audio”

set aUTIstr to getUTIfromNameExtension(“jpg”) of me
–>  ”public.jpeg”

–ファイル拡張子からUTI文字列を取得する
on getUTIfromNameExtension(anExtStr as string)
  set aTempPath to (POSIX path of (path to temporary items from user domain))
  
set aTempName to (current application’s NSUUID’s UUID()’s UUIDString()) as string
  
set bTempPath to (aTempPath & aTempName & “.” & anExtStr)
  
do shell script “touch “ & quoted form of bTempPath
  
set utiStr to current application’s NSWorkspace’s sharedWorkspace()’s typeOfFile:bTempPath |error|:(missing value)
  
do shell script “rm -f “ & quoted form of bTempPath
  
return utiStr as string
end getUTIfromNameExtension

★Click Here to Open This Script 

2016/10/19 SierraのScript Menuにバグ〜凝ったAppleScriptが実行途中で停まる

macOS Sierraで日々いろいろ試していますが、その中で1つ大きなバグを見つけてしまいました。

scriptmenu1.jpg

Script Menuから実行したAppleScriptが途中で停止してしまうというものです(Appleに報告&検証&認定ずみ)。

かなり凝った(Cocoaの機能を呼び出しまくりな)AppleScriptをScript Menuから実行させてみたところ、途中で停止。スクリプトエディタ上でも、ASObjC Explorer 4上でも問題なく実行できているのに、です。

しかし、テスト前から「このレベルだとうまく動くかどうかわからんな〜」という予感はありました。macOS Sierraが機能よりもセキュリティを重視している印象があったため、「疑わしきは罰しまくり」な内部処理を行っていると感じていたからです。

停まったScriptの処理内容:

(1)Skimでオープン中のPDFのファイルコメント(Finder上で確認できるコメント)を取得して、コメント欄にURLが書いてあるか確認

(2)Skim上のPDFのページ数を確認して、いったんPDFをクローズ

(3)WebサーバーにアクセスしてWeb4コママンガの最新エピソードで、PDFのページ数を超える(=新規更新された)エピソードが存在するかを確認

(4)新規エピソードが存在していたら、1つずつ画像をダウンロードしてPDFに追記

(5)SkimでPDFを再オープンし、更新されたコンテンツの最初のページを表示

というものです(Webマンガを読むためだけに書いたもの)。Skim上のPDFをクローズしたまま実行が停止してしまいました。

問題が起きたと思われる箇所:

・最初にオープンしていた書類の再オープン???

・アプリケーションを指定しないでCocoaの機能を用いてのインターネットアクセス???

・httpsではなくhttpによる通信をしているから???

事前にApple側で想定していた範囲を超えるScriptを走らせたため、何らかのセキュリティ機構が働いたものと推測。これが、macOS Sierra, 10.12.1で修正されるかどうかは不明です。まー、10.12.3ぐらいに直れば御の字、常識的には10.12.5ぐらいまで行ってしまいそうな予感はあります(その頃には10.13のBetaが、、、、)。

ちなみに、ちょっとしたAppleScript(メールの仕分けを行う。何もopen/closeしない)であればScript Menuから問題なく実行できています。Finder上で選択中のファイルをPhotoshopでリサイズするScriptも大丈夫です。ファイルのopen/closeを行ったり、ネットワークへのアクセスを行ったりすると問題が出そうです。

2016/10/18 URLにリソースが存在するかチェック v3

指定したURLにリソース(ファイル)が存在するかを確認するAppleScriptの改良版です。

Webサーバーなどのリモート環境を指しているURLをファイル名までフルに記述して、画像ファイルなどの存在確認を行います。「存在確認だけ」を行うことができないので、確認すると実際にデータも取得します。

  結果:{存在確認(true/false), レスポンスヘッダー(NSDictionary), データ本体(NSData)}

v3では、Webサーバーに問い合わせを行ってエラーになったときの対応を追加しています。

AppleScript名:URLにリソースが存在するかチェック v3
– Created 2016-10-18 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4279

set aStr to “http://piyocast.com/as/wp-content/uploads/2016/10/xfinder2.jpg.pagespeed.ic.jFDNAr4CuI.jpg”

set aURL to (current application’s |NSURL|’s URLWithString:aStr)
set {exRes, headerRes, aData} to checkURLResourceExistence(aURL, 3) of me

exRes
–> true / false

headerRes
–> (NSDictionary) {Connection:”Keep-Alive”, Content-Type:”image/jpeg”, Server:”Apache”, Last-Modified:”Mon, 10 Oct 2016 03:43:53 GMT”, Expires:”Tue, 10 Oct 2017 03:43:53 GMT”, Cache-Control:”max-age=31536000″, Accept-Ranges:”bytes”, Date:”Mon, 10 Oct 2016 05:24:38 GMT”, Keep-Alive:”timeout=1, max=100″, Content-Length:”4383″, Etag:”W/”0″”}

aData
–> (NSData)

set conType to (headerRes’s valueForKey:“Content-Type”) as string
–>  ”image/jpeg”

set modDate to (headerRes’s valueForKey:“Last-Modified”) as string
–>  ”Mon, 10 Oct 2016 03:43:53 GMT”

– 指定URLにファイル(画像など)が存在するかチェック
–> {存在確認結果(boolean), レスポンスヘッダー(NSDictionary), データ(NSData)}
on checkURLResourceExistence(aURL, timeOutSec as real)
  set aRequest to (current application’s NSURLRequest’s requestWithURL:aURL cachePolicy:(current application’s NSURLRequestUseProtocolCachePolicy) timeoutInterval:timeOutSec)
  
set aRes to (current application’s NSURLConnection’s sendSynchronousRequest:aRequest returningResponse:(reference) |error|:(missing value))
  
set dRes to (first item of (aRes as list))
  
set bRes to (second item of (aRes as list))
  
if bRes is not equal to missing value then
    set hRes to (bRes’s allHeaderFields())
    
set aResCode to (bRes’s statusCode()) as integer
  else
    set hRes to {}
    
set aResCode to -1 –error
  end if
  
return {(aResCode = 200), hRes, dRes}
end checkURLResourceExistence

★Click Here to Open This Script 

2016/10/17 リマインダーで指定のリスト内の終わっていない項目をテキストで返す

リマインダー(Reminders.app)の指定名称のリスト内で、まだ終わっていない(completedがfalseな)項目をテキストで返すAppleScriptです。

リマインダーでさまざまなToDo管理を行っており、その一環としてマンガの発売予定日をまとめたリストがあるのですが、

rem1_resized.png

項目を選んでコピーし、普通にテキストエディタ(ここではmiを利用)にペーストすると、

rem2_resized.png

のようになります。親切というか、出来過ぎというか、不必要な情報まで入ってくるので、もっとシンプルに名称だけ取得してくれたほうが使い勝手がいいと思います(個人の意見です)。

そこで、さくっとAppleScriptを組んで件名(name)をテキストとして連結して取得できるようにしてみました。

AppleScript名:リマインダーで指定のリスト内の終わっていない項目をテキストで返す
– Created 2015-10-14 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4278

tell application “Reminders”
  tell list “マンガの発売予定日”
    set rList to name of every reminder whose completed is false
    
–リマインド項目は以下のように返ってくる
    
–>{{due date:date “2016年10月19日水曜日 12:00:00″, modification date:date “2016年10月5日水曜日 11:08:23″, class:reminder, body:missing value, completed:false, id:”x-apple-reminder://05A1CBEE-0737-47A7-ABB9-9AF582A604AF”, creation date:date “2016年10月5日水曜日 11:05:36″, name:”87 Clockers 9巻 2016/10/19″, completion date:missing value, container:list id “FA4B1A00-E1AD-4E81-921F-FDCBC7191FA3″ of application “Reminders”, priority:0, remind me date:date “2016年10月19日水曜日 12:00:00″}…. }
  end tell
end tell

set aRes to retStrFromArrayWithDelimiter(rList, return) of me
–>
(*
“87 Clockers 9巻 2016/10/19
マリアージュ 神の雫最終章 5巻 2016/10/21
女騎士、経理になる。 3巻 2016/10/24
王様達のヴァイキング 11巻 2016/10/28
アオイホノオ 16巻 2016/11/12
ピアノのムシ 9巻 2016/11/16
機動戦士Zガンダム Define 12巻 2016/11/19
MIX 10巻 2016/12/8
大砲とスタンプ 6巻 2016/12/21
スティーブス 6巻 2017/1/13
甘城ブリリアントパーク 9巻 2017/2/15
宇宙兄弟 30巻 2017/2/24
ヒーローカンパニー 10巻 2017/6/6″
*)

–リストを指定デリミタをはさんでテキスト化
on retStrFromArrayWithDelimiter(aList, aDelim)
  set anArray to current application’s NSArray’s arrayWithArray:aList
  
set aRes to anArray’s componentsJoinedByString:aDelim
  
return aRes as text
end retStrFromArrayWithDelimiter

★Click Here to Open This Script 

2016/10/13 意図しないiTunesの起動を抑止する

AppleScriptによる自動処理を専門で行わせるMacでは、なるべく最低限の設定しか行わず、プログラムの動作を阻害するような要素は排除しておきたいところですが、

  何も操作していないのに、突然iTunesが起動する

という挙動に悩まされてきました。この解決策を見つけたので、ご紹介しておきます。

(1)キーボードのF1〜F12キーを標準ファンクションキーとして使用

「システム環境設定」>「キーボード」>「キーボード」にある「F1、F2などのすべてのキーを標準のファンクションキーとして使用」にチェックを入れます。

system1.png

自分の経験上、これがオフになっていて(デフォルト状態)F1〜F12が音量調整や再生ボタンなどの役目を担う「メディアキー」として利用可能な状態だと定期的にiTunesが起動してしまうようです。

sys2.jpg

自動処理用のMac(とくにMac mini)では、iTunesに音楽ライブラリなど入れていないですし、アンインストールしておいてもいいぐらいなんですが、とりあえずこれで処理中に不意にiTunesが起動するといった事故は防げています。

(2)すべてのキーボードを外しておく

(1)の理屈でいえば、USB、Bluetooth接続などすべてのキーボードを接続解除しておけば、意図しないiTunesの起動は回避できるはずです(未確認)。

2016/10/12 AppleScript自身の「説明」を取得する

実行中のAppleScript自身の「説明」欄に書かれたテキストを取得するAppleScriptです。

scriptcom1.jpg

AppleScript書類がスクリプトバンドル形式になっている場合にかぎられますが、実行中のAppleScript書類自体の「説明」欄に書かれているテキストを取得できます。

「説明」欄についてかる〜くご説明しておきますと、

「説明」欄にはそのAppleScript自体の説明やバージョンアップ履歴を書いておくことが多いようです。好きに使えます。そして、スタイル付きテキストを許容しますし、画像やムービーや音声をペーストしておくことも可能です。Applet書き出しを行い、初期画面を表示させるように設定しておくと、Applet起動時に表示されます。

AppleScriptをスクリプトバンドル形式(.scptd)で保存すると、「説明」欄の内容はバンドル中の、

  /Contents/Resources/description.rtfd

に記録されます。

scriptcom2.jpg

RTFではなくRTFDなので、さらにこのファイル自体がバンドルになっており、

  /Contents/Resources/description.rtfd/TXT.rtf

の中にリッチテキストが入っています。

scriptcom3.jpg

実行中のAppleScriptのパス(path to me)を取得し、そこからスクリプトバンドル中のrtf書類までのパスを組み立て、そこからテキストのみを抽出します。

scriptcmment4.jpg

最初、RTFのつもりでdescription.rtfdにアクセスして、テキストが取得できずに困ってしまいました。

なお、掲載しているAppleScriptのリストにも、文字色が黒なのでわかりにくいですが「説明」欄の内容が入っています(本Blog開設時の8年前から)。こちらは、スクリプトエディタに対してAppleScriptから問い合わせを行って取得しているもので、本Scriptとはアクセス方法が根本的に異なります。

AppleScript名:test script
【コメント】 このScriptの説明文を書いておきますよー
– Created 2016-10-12 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4268

set cRes to retMyComment() of me
–> “このScriptの説明文を書いておきますよー”

on retMyComment()
  set myPath to (path to me) as string
  
set docPath to myPath & “Contents:Resources:description.rtfd:TXT.rtf”
  
set aRes to retTextFromRTF(docPath) of me
  
return aRes
end retMyComment

on retTextFromRTF(aFile)
  set aFilePath to current application’s NSString’s stringWithString:(POSIX path of aFile)
  
set aData to current application’s NSData’s dataWithContentsOfFile:aFilePath options:0 |error|:(missing value)
  
set theStyledText to current application’s NSMutableAttributedString’s alloc()’s initWithData:aData options:(missing value) documentAttributes:(null) |error|:(missing value)
  
if theStyledText is not equal to missing value then
    return (theStyledText’s |string|()) as string
  else
    return false –Not RTF file
  end if
end retTextFromRTF

★Click Here to Open This Script 

2016/10/12 うっかりミス例:バージョン確認

macOS SierraになってMail.appのバージョンも”10.1″になりました。Mail.app用に作って毎日便利に使っている、

「選択中のメールフォルダ以下のメールを仕分けする。各サブフォルダについている名称をカンマで分離して同義語を許容。さらに、フォルダ名の長い順に重視してSubjectとメールフォルダ名のマッチングを行う」

という超高機能AppleScriptが、macOS Sierraになって正常に動かなくなっていました(スゲー困る)。この原因がわかったので、そのあたりを説明します。

原因は、バージョン番号の判定をしくじっていたというものでした。

バージョン番号は文字列で返ってくるため、macOS SierraのMail.appだと、

AppleScript名:バージョンを求める0
tell application “Mail”
  set aVer to version
end tell
–> “10.1″

★Click Here to Open This Script 

のように”10.1″とかえってきます。

Mail.appは、OS X 10.8あたりで(AppleScriptのmove命令の)機能がダウンして「複数のmessageを他のフォルダに一発で移動させる」ことができなくなりました。

解決策もないため、仕方なくMail.appのバージョン番号を見て「6よりも新しいバージョンであれば1 messageずつループして移動させる」ように処理していました。

ここのバージョン番号の比較判定で「considering numeric strings」を指定していなかったので、「10.1」という文字列を「6より大きくない」と判定。昔のバージョンどおり、複数messageを同時に移動させようとして失敗していたのでした。

大昔に書いて、小幅な改良を施しつつ使い続けているAppleScriptの場合には、こういう「うっかりミス」がOSバージョンアップにともなって表面化することもあります。ご注意ください。

ちなみに、このMailの仕分けScriptの場合、最初に作ったのは2005年ごろのようで、当時はEntourageを相手にしていました。Entourageのデータベースの自己破壊が激しくなり、とても常用できなくなったのをきっかけにMail.appに全面移行して支援ツール類もすべてMail.app用に書き換え。その後、二度とMicrosoftのメーラーは使わなくなりました。

Scriptに残されている最古のコメントが以下のものです。

「Entourageで、指定フォルダのメッセージを再仕分け1.13」
2005年 5月 30日 月曜日 7:48:16 PMにバージョンアップ

Entourageで選択中のフォルダ内にあるメールを、そのフォルダ内のサブフォルダにフォルダ名とサブジェクトの比較を行って再仕分けを行うAppleScript。

短い単語の振り分けが厳しすぎるので緩和
Growlがあれば、それを用いるように機能追加

振り分けずみのメールをスキップする機能を付けたバージョン。スキップ機構を単純化したことにより、速度低下を防いだ。

フォルダ名称の長さでソートして、長い順に仕分けを行う仕様
ハイフンも空白もピリオドも大文字小文字も無視して比較

AppleScript名:バージョンを求める1
tell application “Mail”
  set aVer to version
  
if aVer > “6″ then
    display dialog “Newer”
  else
    display dialog “Older”
  end if
end tell

★Click Here to Open This Script 

mailver1.jpg
▲macOS SierraのMail.appに対してバージョン番号を求め、漫然と大小判定した結果。想定していたものと異なる結果になってしまった

AppleScript名:バージョンを求める2
tell application “Mail”
  set aVer to version
  
considering numeric strings
    if aVer > “6″ then
      display dialog “Newer”
    else
      display dialog “Older”
    end if
  end considering
end tell

★Click Here to Open This Script 

mailver2.jpg
▲considering numeric strings節で囲って、バージョン文字列の判定をきちんと行った結果、期待どおりの処理結果が得られた

2016/10/10 ASObjC Explorer 4が発展的解消を遂げる

yyyeyoyycyaye-2016-10-10-203135_resized.png

2016年9月25日付けで、Shane Stanleyが「asobjcEx」メーリングリストに投稿したところによると、ASObjCに特化した開発ツール「ASObjC Explorer 4」をディスコンにするとのこと。ASObjC Explorer 4の最新バージョン「4.1.17」はmacOS Sierraに対応しており、今日明日ですぐに困るようなことはないと思われます。

Script DebuggerのLate Night Software(Mark Alldritt)とShane Stanleyが協業することになり、その結果としてScript Debugger 6にCocoa Loggingなどの機能が導入されました。反面、ASObjC Explorer 4の今後が非常に微妙なものになってしまいました。

scripteditors.png
▲2015年2月にAppleScript関連ツールの状況をまとめた図

結局、ASObjC Explorer 4の終息(ディスコン)ということを選択したものと思われます。あえて日本語的な表現をするなら「発展的解消」ということになるでしょうか。

Shaneの開発力がよりメジャーな製品の開発現場で生かされるわけで、それについてはよかったと思います。

ただ問題は、Script Debugger 6がASObjC Explorer 4よりも使いやすいかというと、まだそういうレベルに達していないように感じる(Front-end processでの強制実行などなど)ことです。

asedito3_resized.png

Script Debugger 6にこの「最前面で実行する(Run in foreground)」の機能がなく、AppleScript互換のOSA言語を自前で実装しているという特殊な構造ゆえに、実装も難しいという状況と聞いています。これを解消するための解決策が「ASObjC Explorer 4をなくす」ということであれば、ちょっと残念です。

runinforeground1_resized.png
▲Apple純正スクリプトエディタの「フォアグラウンドで実行」機能(Controlキーを押すとメニューに出てくる)

runsinforeground2.jpg
▲ASObjC Explorer 4の「Run in foreground」機能

ASObjC Explorer 4自体にも問題がないことはなかった(エディタとして見ると、スタイル付きテキストのコピー&ペーストで、スペースに意図しない不可視キャラクタが挿入されるなど問題があった)のですが、個人的にはしばらくASObjC Explorer 4を使いたいところです。

2016/10/10 URLにリソースが存在するかチェック v2

指定したURLにリソース(ファイル)が存在するかを確認するAppleScriptです。

Webサーバーなどのリモート環境を指しているURLをファイル名までフルに記述して、画像ファイルなどの存在確認を行います。

ただし、「存在確認だけ」を行うことができないようで、確認すると実際にデータも取得できてしまいます。

本来なら、このような処理は並列で同時に行いたいところ。強制的に並列化するツールも作って実験していますが、同時に大量のURLの存在確認を行うような処理はとてもありえそうです。

ただ、shell commandで行なっても割と手軽にできそうで、Cocoaのサービスを呼び出すのか、実際に処理速度を計測して選択したいところです。

AppleScript名:URLにリソースが存在するかチェック v2
– Created 2016-10-10 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4254

set aStr to “http://piyocast.com/as/wp-content/uploads/2016/10/xfinder2.jpg.pagespeed.ic.jFDNAr4CuI.jpg”

set aURL to (current application’s |NSURL|’s URLWithString:aStr)
set {exRes, headerRes, aData} to checkURLResourceExistence(aURL, 3) of me

exRes
–> true / false

headerRes
–> (NSDictionary) {Connection:”Keep-Alive”, Content-Type:”image/jpeg”, Server:”Apache”, Last-Modified:”Mon, 10 Oct 2016 03:43:53 GMT”, Expires:”Tue, 10 Oct 2017 03:43:53 GMT”, Cache-Control:”max-age=31536000″, Accept-Ranges:”bytes”, Date:”Mon, 10 Oct 2016 05:24:38 GMT”, Keep-Alive:”timeout=1, max=100″, Content-Length:”4383″, Etag:”W/”0″”}

aData
–> (NSData)

set conType to (headerRes’s valueForKey:“Content-Type”) as string
–>  ”image/jpeg”

set modDate to (headerRes’s valueForKey:“Last-Modified”) as string
–>  ”Mon, 10 Oct 2016 03:43:53 GMT”

– 指定URLにファイル(画像など)が存在するかチェック
–> {存在確認結果(boolean), レスポンスヘッダー(NSDictionary), データ(NSData)}
on checkURLResourceExistence(aURL, timeOutSec as real)
  set aRequest to (current application’s NSURLRequest’s requestWithURL:aURL cachePolicy:(current application’s NSURLRequestUseProtocolCachePolicy) timeoutInterval:timeOutSec)
  
set aRes to (current application’s NSURLConnection’s sendSynchronousRequest:aRequest returningResponse:(reference) |error|:(missing value))
  
set dRes to (first item of (aRes as list))
  
set bRes to (second item of (aRes as list))
  
set hRes to (bRes’s allHeaderFields())
  
set aResCode to (bRes’s statusCode()) as integer
  
return {(aResCode = 200), hRes, dRes}
end checkURLResourceExistence

★Click Here to Open This Script 

2016/10/10 数値に3桁セパレータを付加、外して数値に戻す

数値に3桁セパレーター(カンマ)を付加した文字列にするAppleScriptと、そのセパレーター入り文字列を数字に戻すAppleScriptです。

AppleScript名:数値に3桁セパレータを付加、外して数値に戻す
– Created 2016-10-09 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
–http://piyocast.com/as/archives/4253

set aNum to 100000
set aStr to formatNum(aNum) of me
–> "100,000"

set bNum to deFromatNumStr(aStr) of me
–>  100000

on formatNum(theNumber as number)
  set theResult to current application’s NSNumberFormatter’s localizedStringFromNumber:theNumber numberStyle:(current application’s NSNumberFormatterDecimalStyle)
  
return theResult as text
end formatNum

on deFromatNumStr(theNumericString as string)
  set notWantChars to current application’s NSCharacterSet’s characterSetWithCharactersInString:","
  
set targStr to current application’s NSString’s stringWithString:theNumericString
  
set newStr to (targStr’s componentsSeparatedByCharactersInSet:notWantChars)’s componentsJoinedByString:""
  
return ((newStr as string) as number) –Danger in OS X 10.10 (floating point casting bug)
end deFromatNumStr

★Click Here to Open This Script 

2016/10/07 サウンド入出力を変更

Macのサウンド入出力先を変更するAppleScriptです。自分で作って使っているAppleScript Libraries「soundIO Lib」のインストールを必要とします(入っていない環境では構文確認自体を行えません)。

とくに、システム環境設定を起動したりすることはありません。すぐに実行は終了します。

本Scriptは実際のライブラリ呼び出しコードではなく、動作確認のためのコードなので、実際にはここまでしつこく設定内容の確認を行う必要はありません。ライブラリ側で切り替わったことを検証してtrue/falseを返しています。

書籍購入者で、書籍の感想を送って下さった方にsoundIO Libをプレゼントします。maro@piyocast.comまでご感想をお送りください

AppleScript名:サウンド入出力を変更
– Created 2016-10-07 by Takaaki Naganoya
– 2016 Piyomaru Software
– http://piyocast.com/as/archives/4252
use AppleScript version “2.4″
use scripting additions
use soundIO : script “soundIO Lib” version “1.0″

set targOutputDevice to “Logicool Z600″
set targIntputDevice to “Built-in Microphone”

–出力デバイス一覧に設定対象が入っているかチェック
set aList to soundIO’s getEveryAudioOutputDevice()
if targOutputDevice is not in aList then return false
–> {”Logicool Z600″, “Built-in Output”, “Mobiola Headphone”, “Mobiola Microphone”, “Soundflower (2ch)”, “Soundflower (64ch)”}

–入力デバイス一覧に設定対象が入っているかチェック
set bList to soundIO’s getEveryAudioInputDevice()
if targIntputDevice is not in bList then return false
–>  {”Built-in Microphone”, “Mobiola Headphone”, “Mobiola Microphone”, “Soundflower (2ch)”, “Soundflower (64ch)”}

–入出力デバイスを設定
set i1 to soundIO’s setAudioInuptDevice(targIntputDevice)
set o1 to soundIO’s setAudioOutuptDevice(targOutputDevice)

–サウンド入出力デバイスの変更確認
set i2 to soundIO’s getCurrentAudioInuptDevice()
set o2 to soundIO’s getCurrentAudioOutuptDevice()

set aRes to (i1 = true and o1 = true) and (i2 = targIntputDevice and o2 = targOutputDevice)
if aRes = true then
  tell current application
    display dialog “サウンド入出力を” & targOutputDevice & “に設定しました。”
  end tell
else
  tell current application
    display dialog “サウンド入出力の設定に失敗しました。”
  end tell
end if

★Click Here to Open This Script 

2016/10/05 SDカードを検出

マウント中のドライブのマウントポイント(例:/Volumes/ドライブ名)を指定すると、当該ドライブがSDカードかどうかを判定するAppleScriptです。

system_profilerコマンドを呼び出して詳細な情報を取得して判定するようにして、手元にある2枚のSDカードはこれで判定できています。MacBook Pro Retina 2012の内蔵SDカードリーダー、およびUSB接続のSDカードリーダーの両方で判定できることを確認しています。

system_profilerの実行結果は、

mountedsd1.jpg

MacBook Pro Retina内蔵SDカードリーダーに入れたSDXCカード「JVCCAM_SD」
-> {writable:”yes”, _name:”JVCCAM_SD”, ignore_ownership:”yes”, file_system:”MS-DOS FAT32″, size_in_bytes:3.3179041792E+10, bsd_name:”disk3s1″, free_space_in_bytes:2.0819673088E+10, mount_point:”/Volumes/JVCCAM_SD”, physical_drive:{is_internal_disk:”yes”, device_name:”Built In SDXC Reader”, protocol:”Secure Digital”, media_name:”Apple SDXC Reader Media”, partition_map_type:”master_boot_record_partition_map_type”}}

USB接続SDカードリーダーに入れたSDカード「RICOHDCX」
–> {writable:”yes”, _name:”RICOHDCX”, ignore_ownership:”yes”, file_system:”MS-DOS FAT32″, volume_uuid:”3BD2F468-5B42-327C-AB96-2812A02E7126″, size_in_bytes:7.939817472E+9, bsd_name:”disk4s1″, free_space_in_bytes:5.415960576E+9, mount_point:”/Volumes/RICOHDCX”, physical_drive:{is_internal_disk:”no”, device_name:”SD Transcend”, protocol:”USB”, media_name:”TS-RDF5 SD Transcend Media”, partition_map_type:”master_boot_record_partition_map_type”}}

mountedsd2.jpg

MacBook Pro Retina内蔵SDカードリーダーに入れたSDカード「RICOHDCX」
–> {writable:”yes”, _name:”RICOHDCX”, ignore_ownership:”yes”, file_system:”MS-DOS FAT32″, volume_uuid:”3BD2F468-5B42-327C-AB96-2812A02E7126″, size_in_bytes:7.939817472E+9, bsd_name:”disk3s1″, free_space_in_bytes:5.415960576E+9, mount_point:”/Volumes/RICOHDCX”, physical_drive:{is_internal_disk:”yes”, device_name:”Built In SDXC Reader”, protocol:”Secure Digital”, media_name:”Apple SDXC Reader Media”, partition_map_type:”master_boot_record_partition_map_type”}}

USB接続SDカードリーダーに入れたSDXCカード「JVCCAM_SD」
–> {writable:”yes”, _name:”JVCCAM_SD”, ignore_ownership:”yes”, file_system:”MS-DOS FAT32″, size_in_bytes:3.3179041792E+10, bsd_name:”disk4s1″, free_space_in_bytes:2.0819673088E+10, mount_point:”/Volumes/JVCCAM_SD”, physical_drive:{is_internal_disk:”no”, device_name:”SD Transcend”, protocol:”USB”, media_name:”TS-RDF5 SD Transcend Media”, partition_map_type:”master_boot_record_partition_map_type”}}

となっており、device_nameとmedia_nameを単語ごとにリスト化し、「SD」「SDHC」「SDXC」の単語が入っているかどうかを判定しています。

同一名称のSDカードが複数枚同時にマウントされた場合の挙動については検証していないため、そういうケースには対応しきれていないと思われます。ご注意ください。

AppleScript名:SDカードを検出
– Created 2016-10-04 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4251

tell application “Finder”
  set driveList to every disk whose format is (MSDOS format) and ejectable is true and startup is false
  
  repeat with i in driveList
    set myDisk to disk of (first item of i)
    
set myMountPoint to POSIX path of (myDisk as alias)
    
–> “/Volumes/JVCCAM_SD/”
    
–> “/Volumes/RICOHDCX/”
    
set sdRes to detectSDCard(myMountPoint) of me
    
–> true –SD Card, false –Not SD Card
  end repeat
end tell

on detectSDCard(myMountPoint as string)
  
  set resData to runCommandString(“system_profiler -xml SPStorageDataType”) of me
  
set aaDict to (readPlistFromStr(resData) of me) as list
  
set aDictList to (_items of first item of aaDict)
  
  repeat with i in aDictList
    set j to contents of i
    
    set aMountPoint to (mount_point of j) as string
    
–> “/Volumes/JVCCAM_SD”
    
–> “/Volumes/RICOHDCX”
    
    if aMountPoint is not equal to “/” then
      if ((aMountPoint & “/”) is equal to myMountPoint) then
        set aDevName to words of (device_name of physical_drive of j)
        
set aMediaName to words of (media_name of physical_drive of j)
        
        –SD/SDHC/SDXCのカード検出
        
set aDevF to (“SD” is in aDevName) or (“SDHC” is in aDevName) or (“SDXC” is in aDevName)
        
set aMediaF to (“SD” is in aMediaName) or (“SDHC” is in aMediaName) or (“SDXC” is in aMediaName)
        
        if (aDevF and aMediaF) then return true
      end if
    end if
  end repeat
  
  return false
end detectSDCard

–文字列で与えたシェルコマンドを実行する
on runCommandString(commandStr as string)
  set aPipe to current application’s NSPipe’s pipe()
  
set aTask to current application’s NSTask’s alloc()’s init()
  
aTask’s setLaunchPath:“/bin/sh”
  
aTask’s setArguments:{“-c”, current application’s NSString’s stringWithFormat_(“%@”, commandStr)}
  
aTask’s setStandardOutput:aPipe
  
set aFile to aPipe’s fileHandleForReading()
  
aTask’s |launch|()
  
return current application’s NSString’s alloc()’s initWithData:(aFile’s readDataToEndOfFile()) encoding:(current application’s NSUTF8StringEncoding)
end runCommandString

–stringのplistを読み込んでRecordに
on readPlistFromStr(theString)
  set aSource to current application’s NSString’s stringWithString:theString
  
set pListData to aSource’s dataUsingEncoding:(current application’s NSUTF8StringEncoding)
  
set aPlist to current application’s NSPropertyListSerialization’s propertyListFromData:pListData mutabilityOption:(current application’s NSPropertyListImmutable) |format|:(current application’s NSPropertyListFormat) errorDescription:(missing value)
  
return aPlist
end readPlistFromStr

★Click Here to Open This Script 

2016/10/04 SDカードと思われるドライブを抽出

Finderで、マウント中のドライブのうちSDカードと思われるものを抽出するAppleScriptです。

抽出条件は、

 ディスクフォーマット:MS-DOS
 イジェクト可能なドライブか?:はい
 起動可能なドライブか?:いいえ
 ローカルボリュームか?:はい

finder2.jpg

というだけで、それがSDカードかどうかという確実な判定は行なっていません。

「多分こういう条件を満たすドライブはSDカードなんだろー」

という方法によるものです(この条件だと、USBメモリーとかDOSフォーマットした外付けHDDも該当しますね)。Finder上ではSDカードのアイコンがついているので、OS的にはそれがSDカードであることは認識されています。

Finder上で抽出したドライブのpropertiesを取得すると、

{class:disk, name:”JVCCAM_SD”, index:5, displayed name:”JVCCAM_SD”, name extension:”", extension hidden:false, container:computer container of application “Finder”, disk:disk “JVCCAM_SD” of application “Finder”, position:{-1, -1}, desktop position:{-1, -1}, bounds:{-33, -33, 31, 31}, kind:”ボリューム”, label index:0, locked:false, description:missing value, comment:”", size:1.2359368704E+10, physical size:1.2359368704E+10, creation date:date “2014年2月14日金曜日 5:39:40″, modification date:date “2016年9月15日木曜日 12:26:26″, icon:missing value, URL:”file:///Volumes/JVCCAM_SD/”, owner:”maro”, group:”(不明)”, owner privileges:read write, group privileges:read write, everyones privileges:read write, container window:container window of disk “JVCCAM_SD” of application “Finder”, id:-105, capacity:3.3179041792E+10, free space:2.0819673088E+10, ejectable:true, startup:false, format:MSDOS format, journaling enabled:false, local volume:true, ignore privileges:true}

のように結果が帰ってきます。この中にはディスク種別に関する情報は含まれていないため、別途何かのOS内部のサービスを利用して判定できるのでしょう。

AppleScript名:SDカードと思われるドライブを抽出
– Created 2016-10-04 by Takaaki Naganoya
– 2016 Piyomaru Software
–http://piyocast.com/as/archives/4247
tell application “Finder”
  set aDrive to every disk whose format is (MSDOS format) and ejectable is true and startup is false and local volume is true
end tell
–> {disk “JVCCAM_SD” of application “Finder”}

★Click Here to Open This Script 

2016/10/04 Finderの最前面のフォルダを取得して、choose folderの始点フォルダに指定する

Finderの最前面のWindowで表示しているフォルダ(target)を取得して、後続のchoose folderコマンドで表示するデフォルトフォルダに指定するAppleScriptです。

targwin1_resized.png
▲最前面のWindowの内容

targwin2_resized.png
▲最前面のWindowの対象フォルダ(target)を取得してchoose folder

こういうのは、技術的にすごいとかどーのとかいうことは全然なくて、「おもてなし度が向上する」ワザ。過剰にやりすぎると嫌われることもあるので、用法・容量を守って過剰に使いすぎない程度に使ってみるといいのでしょう。

既存のPDFに対して指定フォルダ内のJPEG画像を末尾に追加するAppleScriptを書いたときに、「指定フォルダ」が最前面にあるのになんでこれを毎回指定しないとダメなんだろうか、と思って作ってみたものです。

AppleScript名:Finderの最前面のフォルダを取得して、choose folderの始点フォルダに指定する
– Created 2016-10-04 by Takaaki Naganoya
– 2016 Piyomaru Software
–http://piyocast.com/as/archives/4244

set targAlias to retFrontFinderWindowsTargetIfExits(path to desktop) of me
set aFol to choose folder default location targAlias

on retFrontFinderWindowsTargetIfExits(aDefaultLocation)
  tell application “Finder”
    set wCount to count every window
    
if wCount 1 then
      tell front window
        set aTarg to target as alias
      end tell
      
return aTarg
    else
      return aDefaultLocation
    end if
  end tell
end retFrontFinderWindowsTargetIfExits

★Click Here to Open This Script 

2016/10/03 信頼性の低いユニバーサルクリップボード機能

dock1.png

macOS Sierra+iOS 10.xを組み合わせた環境で利用できる「ユニバーサルクリップボード」機能。AppleScriptからOSの機能をこづきまわしているユーザーにとっては、AppleScriptからMac側のクリップボード情報を更新したような場合に、きちんとiOSデバイス側とクリップボードのシンクロが行われるのか気になります。

実際に試してみると、予想どおり、

「ユニバーサルクリップボードが効く場合と効かない場合がある」

という状況で、

「いつでもMacとiOSデバイスの間でコピー&ペーストができるわけではない」

ようです。

厳密にやりすぎるとMac側にもiOSデバイス側にも処理のオーバーヘッドが大きくなりすぎるので、ある程度の割り切りというか、味付けを行なっている(前回実行時からの間隔が短すぎるとイネーブルにしないとか)のでは、と推測していました。

MacのDock上にiOSデバイスのアプリケーションアイコンが表示されている状態だと、ユニバーサルクリップボード機能が利いているようでした。非表示の状態だとMac+iOSデバイスが稼働中でユニバーサルクリップボードの利用条件を満たしていたとしても、デバイス間のコピー&ペーストは効きませんでした。

iOSデバイスのメモ帳で「霤帖廚箸いκ源をコピーし、Mac側でclipboard infoコマンドでクリップボードの情報を取得してみたところ、初回のみ、

–> {{«class rtfd», 448}, {«class utf8», 6}, {«class weba», 623}}

というデータが得られました。2回目以降は、

–> {{«class rtfd», 448}, {«class utf8», 6}, {«class weba», 623}, {«class ut16», 6}, {string, 4}, {Unicode text, 4}}

というデータが返ってきました。これがよくないと言うつもりはなく、AppleScriptの自動処理で、Mac側のクリップボードにデータを入れたので必ずiOSデバイスのクリップボード側にも同じデータを引き渡せるはず、とは言えないということだけ知っておく必要があります。

それぞれ、データ形式およびデータのバイト数がペアになって返ってきています。iOS側からユニバーサルクリップボード経由でデータを受信したとおぼしき挙動を行ったときが前者、2回目以降は後者。

ユニバーサルクリップボードからデータを取得した直後はクリップボードの内容が(わずかに)異なるということに気をつけておきたいところです。

この機能がOSのアップデートによってより信頼性の高いものになっていくのか、それとも相変わらずこの程度のままなのかは不明ですが、現状ではサードパーティのツールの方が信頼性が高いという状態です。