AppleScript Javascript Mac ガジェット シェルコマンド プログラミング 周辺機器 工作 電子工作

obniz board + Node.js + AppleScriptでStream DeckっぽいMac用コントローラーを作った

やっぱり専用コントローラーは便利

以前、自作のメディアプレーヤー専用のコントローラーを作りました。

使っていると、やっぱり専用コントローラーはいいなぁと思います。

とにかく1ボタン1機能で押したら必ず決められた処理が行われると言うのは、とてもシンプルで使いやすいです。

obniz boardを使ったおかげでアプリやウインドウが裏に隠れていても動作するので、本当に押せば必ず動くコントローラーになりました。

上記のコントローラーはWebアプリのコントロール用です。Webアプリ内のjavascriptでobnizのライブラリを利用しています。

obniz boardのライブラリはNode.js上でも動かすことができます。

obniz公式サイト:Node.jsで動かすには

Node.jsで動かせばWebアプリの制限に縛られずにいろいろなことができます。

今回は、Node.jsからAppleScriptを呼び出せるライブラリと組み合わせて汎用コントローラーを作ってみました。

ボタンを押すと任意のAppleScriptが起動します。

ボタンひとつでアプリケーションを切り替えたり、アプリ上のツール切り替えなどができます。基本的にAppleScriptでできることはなんでもできます。

イメージとしてはYoutuberさんや生配信者さんがよく使っているらしいStream Deckっぽいものです。

ハードウエアはWebアプリ用のものを流用

ハードウエアはWebアプリ版のコントローラーと同じです。

obniz boardは使う度にクラウド経由でプログラムをダウンロードするので、ひとつのボードを色んな用途に兼用できます。

とりあえずボタンは4つ。将来的にはもっとたくさんボタンがあってしっかりした筐体を作ろうかなと思っています。

全体はこんな感じです。

obniz boardのgpioに繋がったボタンが押されると、javascript側でイベントを検知してAppleScriptを起動、Macのシステムやアプリケーションを制御します。

Node.js上で動くのでターミナルアプリとなります。

obnizライブラリとnode-osascriptライブラリのインストール

ここからはNode.js環境があることを前提にしています。

Node.jsのインストールは以下の記事で書きました。

あと、Nodeのライブラリマネージャーとしてyarnをインストールしました。npmよりこっちの方が今風らしい。

npm install -g yarn

適当な名前のディレクトリを作り、そこに移動します。

mkdir control-deck

cd control-deck

yarnを初期化して、package.jsonを作ります。

yarn init -y

## -y は質問に全部自動でYesと答えるオプション

yarn init v1.22.17
warning The yes flag has been set. This will automatically answer yes to all questions, which may have security implications.
success Saved package.json
✨  Done in 0.01s.

ls
package.json

cat package.json 

{
  "name": "control-deck",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT"
}

obnizライブラリをインストールします

yarn add obniz

次にNode.jsからAppleScriptを呼び出すためのライブラリをインストールします。

Node.js用のAppleScript対応ライブラリは色々あります。

今回はnode-osascriptを使いました。

node-osascript

このライブラリはJavaScriptから、AppleScriptの変数に値を渡せるのがいいです。

yarn add node-osascript

package.jsonの中身はこんな感じになりました。

これがディレクトリ内にあれば "yarn" コマンドひとつで必要なライブラリがインストールされます。

{
  "name": "control-deck",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "node-osascript": "^2.1.0",
    "obniz": "^3.19.0"
  }
}

obnizとやりとりするindex.js

obnizとのやりとりを行うindex.jsを作ります。

最初はアプリケーションスイッチャーとして動かすので、"switch-app.applescript"というAppleScriptファイルを指定してあります。

押されたボタンによってAppleScriptに渡すaction: の値を変えます。

AppleScript側ではactionの値に応じた動作をします。

obniz boardのid番号をvar obniz = new Obnizのところに設定します。

var Obniz = require("obniz");
var osascript = require('node-osascript');

// const scriptFile = './actions.applescript';
const scriptFile = './switch-app.applescript';

function doAction(act) {
  osascript.executeFile(scriptFile, { action: act },
    function (err, result, raw) {
      if (err) return console.error(err)
      console.log(result, raw)
    });
}

var obniz = new Obniz("************ onniz board id *****************");
obniz.onconnect = async function () {
  console.log('connected');

  var button0 = obniz.wired("Button", { signal: 0, gnd: 11 });
  button0.onchange = function (pressed) {
    if (pressed) {
      console.log("buton 0 pressed");
      doAction("0");
    }
  };

  var button1 = obniz.wired("Button", { signal: 1 });
  button1.onchange = function (pressed) {
    if (pressed) {
      console.log("buton 1 pressed");
      doAction("1");
    }
  };

  var button2 = obniz.wired("Button", { signal: 2 });
  button2.onchange = function (pressed) {
    if (pressed) {
      console.log("buton 2 pressed");
      doAction("2");
    }
  };

  var button3 = obniz.wired("Button", { signal: 3 });
  button3.onchange = function (pressed) {
    if (pressed) {
      console.log("buton 3 pressed");
      doAction("3");
    }
  };

}

node-osascriptの使い方

node-osascriptは、以下のようなオブジェクトとしてAppleScript内の変数の値を設定できます。

## JavaScript

//scriptFileにAppleScriptファイルへのパスが入る 
 osascript.executeFile(scriptFile, { action: "Do It" },
    function (err, result, raw) {
      if (err) return console.error(err)
      console.log(result, raw)
    });

## AppleScript
display dialog action

##結果
"Do It"というダイアログが表示される

excecuteメソッドを使うと直接AppleScriptを渡すこともできます。

osascript.execute('display dialog message', { message : "Hello from Node.JS" },function(err, result, raw){
  if (err) return console.error(err)
  console.log(result, raw)
});

アプリケーションランチャーのAppleScript

switch-app.applescript というファイルを作ります。

AppleScript側ではactionの値に応じた動作をします。

AppleScriptにはswitch case文が無いようなので、if then else を重ねて書きました。if文の条件式のイコールがひとつなのはAppleScriptっぽいですね。

この例では各ボタンにFinder、Google Chrome、Mail、Safariへのを切り替えを設定しています。もちろん、アプリ名を変更すれば任意のアプリへ切り替えられます。


if (action = "0") then

tell application "Finder"
    activate
end tell

else if (action = "1") then

tell application "Google Chrome"
    activate
end tell

else if (action = "2") then

tell application "Mail"
    activate
end tell

else if (action = "3") then

tell application "Safari"
    activate
end tell

end if

実際に使ってみる

使う時はまずobniz boardを電源(USB)に繋ぎます。まだであればWifiアクセスポイントへの接続設定も行います。

obniz boardがwifiに繋がっている状態でターミナルから以下のコマンドで実行します。

node index.js

ターミナルにconnected と表示されたら準備完了です。

obniz boardに繋いであるボタンを押すと各アプリケーションへの切り替えや起動が行えるはずです。最初はセキュリティ認証のダイアログが出ると思いますので許可しましょう。

許可しそこなったり、ブロックされてしまうときは、システム環境設定のセキュリティとプライバシー:プライバシーで、「オートメーション」とか「アクセシビリティ」とかでターミナルを有効にすればいけると思います。たぶん。

実際に使うとこれは予想以上に便利です。

慣れるまではいつものやり方でアプリケーションを切り替えてしまいますが、慣れればアプリ間のいったり来たりがとても楽になります。

しかも従来の切り替え方法が使えなくなるわけではないのでマイナス要素は無いです(自画自賛)

Illlustratorのツール選択や簡単な自動操作をやってみる

AppleScriptを使っているので、アプリケーション切り替え以外のこともできます。

Adobe Illustratorのツール切り替えを専用ボタンでできるようにしてみます。

Illustratorでの作業は、ツール切り替えを頻繁に行うので専用ボタン化できると効率が上がります。

actions.applescriptというファイルを作って以下のような内容にします。

index.js側もscriptFileの値を"actions.applescript"に変更します。前期のコードでコメントアウトされているところです。代わりに"switch-app.applescript"の文をコメントアウトします。

これで選択ツール、ダイレクト選択ツール、ペンツールを専用ボタンで切り替えられます。

ツール切り替えについては以下のサイトの情報がたいへん有用でした。感謝。

Illustrator Reference

tell application "Adobe Illustrator"
    activate

if (action = "0") then

    Select Tool tool name "Adobe Select Tool"

else if (action = "1") then

    Select Tool tool name "Adobe Direct Select Tool"

else if (action = "2") then

    Select Tool tool name "Adobe Pen Tool"

else if (action = "3") then

    tell application "System Events"
      key code 53
      key code 102
      keystroke "d" 
    end tell

end if

end tell

キーストロークでショートカットを送る

4つめのボタンには以下のようなスクリプトを設定しています。

    tell application "System Events"
      key code 53
      key code 102
      keystroke "d" 
    end tell

このスクリプトでIllustrator上で選択されているオブジェクトに「デフォルトの塗りと線」を設定できます。

これは、ESCキー、英数キー、dキーを順番に押すショートカットマクロとなっています。

dキーは「デフォルトの塗りと線」を設定するショートカットキーです。Illustratorのショートカットキーには修飾キーを使わないものがあります。

しかし、dキーを押した時にたまたまテキスト入力の状態だとそこに文字が入力されてしまい、ショートカットとしては機能しません。

そこでまず key code 53 でESCキーを送ってテキスト編集の状態を解除します。

また、日本語入力モードになっているとショートカットキーがうまく働かないので key code 102 で英数キーを押します。

最後にdキーを押してデフォルトの塗りと線を適用します。

AppleScriptのキーコードについては以下のサイトが詳しいです。

Complete list of AppleScript key codes

上記サイトにはない日本語キーボード独自の「英数」は 102 、「かな」は 104 です。

私は単純なツール切り替えや設定しか作れていませんが,Adobeのアプリケーションは高度な自動化に対応しているので、詳しい人がスクリプトを書けばもっと色んなことができると思います。

あと、この仕組みは後ろにあるアプリもコントロールできたり、obnizはWifi経由で繋がっているので遠隔でMacをコントロールすることもできるという特徴もあったりします。色んな使い方ができそうです。

-AppleScript, Javascript, Mac, ガジェット, シェルコマンド, プログラミング, 周辺機器, 工作, 電子工作