AirPlay非対応のMacを受信機にする。START/STOPとPIN表示付きのGUIを作る

この記事では、UxPlayをGUIからSTART/STOPできるようにし、AirPlay接続時に求められる4桁PINもGUI上に表示できるようにします。

前回までに、UxPlay本体のビルド、起動スクリプト、LaunchAgentの作成まで完了している前提です。

もし実施してなければ、過去記事を参考にしてください。

本記事に記載されたコードや手順を実行したことによって生じたいかなる損害・トラブルについても、筆者および所属組織は一切の責任を負いかねます。

システムの変更やコマンドの実行は、必ずご自身の責任と判断のもとで行ってください。

また、本記事の内容は筆者個人の見解であり、所属する企業や団体を代表するものではありません。

目次

今回作るもの

今回作るのは、以下のような簡易GUIコントローラーです。

  • アプリを開くと、UxPlayが停止中なら自動で起動する
  • 現在の実行状態をテキストで表示する
  • AirPlay接続用の4桁PINを表示する
  • STARTボタンでUxPlayを開始 / 再起動する
  • STOPボタンでUxPlayを停止する
  • 閉じるボタンでコントローラーだけ閉じる

UxPlay本体はLaunchAgent経由で起動しますが、KeepAlive=falseにしているため、STOP後に勝手に復活しません。

制御スクリプトを作る

まず、GUIから呼び出す制御スクリプトを作ります。

このスクリプトは、以下の処理を担当します。

  • ensure:UxPlayが停止中なら起動する
  • start:新しい4桁PINを生成してUxPlayを起動 / 再起動する
  • stop:UxPlayを停止する
  • status:現在の状態とPINを表示する
cat > ~/bin/uxplay-control.sh <<'EOF'
#!/bin/zsh

LABEL="com.local.uxplay"
PLIST="$HOME/Library/LaunchAgents/$LABEL.plist"
LOG_DIR="$HOME/Library/Logs/UxPlay"
PIN_FILE="$LOG_DIR/uxplay.pin"

mkdir -p "$LOG_DIR"

generate_pin() {
  /usr/bin/jot -r 1 1000 9999 > "$PIN_FILE"
}

is_loaded() {
  /bin/launchctl print "gui/$(/usr/bin/id -u)/$LABEL" >/dev/null 2>&1
}

is_running() {
  /usr/bin/pgrep -x uxplay >/dev/null 2>&1
}

load_agent() {
  if ! is_loaded; then
    /bin/launchctl bootstrap "gui/$(/usr/bin/id -u)" "$PLIST" 2>/dev/null || true
  fi
}

ensure_start() {
  load_agent

  if ! is_running; then
    generate_pin
    /bin/launchctl kickstart "gui/$(/usr/bin/id -u)/$LABEL"
  fi
}

force_start() {
  generate_pin
  load_agent
  /bin/launchctl kickstart -k "gui/$(/usr/bin/id -u)/$LABEL"
}

stop_uxplay() {
  /bin/launchctl bootout "gui/$(/usr/bin/id -u)" "$PLIST" 2>/dev/null || true
  /usr/bin/pkill -x uxplay 2>/dev/null || true
  /usr/bin/pkill -f "$HOME/Downloads/UxPlay/uxplay" 2>/dev/null || true
}

show_status() {
  if is_loaded; then
    LAUNCHD_STATUS="読み込み済み"
  else
    LAUNCHD_STATUS="未読み込み"
  fi

  if is_running; then
    RUN_STATUS="稼働中"
    PROCESS_INFO="$(/usr/bin/pgrep -fl uxplay | /usr/bin/head -5)"
  else
    RUN_STATUS="停止中"
    PROCESS_INFO="uxplayプロセスなし"
  fi

  if [ -f "$PIN_FILE" ]; then
    PIN_CODE="$(/bin/cat "$PIN_FILE")"
  else
    PIN_CODE="未生成"
  fi

  echo "UxPlay 状態: $RUN_STATUS"
  echo "LaunchAgent: $LAUNCHD_STATUS"
  echo ""
  echo "AirPlay接続PIN: $PIN_CODE"
  echo ""
  echo "iPhone/iPad側でPINを求められたら、この4桁を入力してください。"
  echo ""
  echo "プロセス:"
  echo "$PROCESS_INFO"
  echo ""
  echo "START: AirPlay待受を開始 / 再起動"
  echo "STOP: AirPlay待受を停止"
}

case "$1" in
  ensure)
    ensure_start
    ;;
  start)
    force_start
    ;;
  stop)
    stop_uxplay
    ;;
  status)
    show_status
    ;;
  *)
    echo "Usage: $0 {ensure|start|stop|status}"
    exit 1
    ;;
esac
EOF

実行権限を付けます。

chmod +x ~/bin/uxplay-control.sh

状態表示を確認します。

~/bin/uxplay-control.sh status

以下のように表示されればOKです。

UxPlay 状態: 停止中
LaunchAgent: 読み込み済み

AirPlay接続PIN: 未生成

iPhone/iPad側でPINを求められたら、この4桁を入力してください。

プロセス:
uxplayプロセスなし

START: AirPlay待受を開始 / 再起動
STOP: AirPlay待受を停止

GUIコントローラーを作る

次に、AppleScriptでGUIコントローラーを作ります。

このコントローラーは、起動したタイミングでUxPlayが停止していれば自動で起動します。また、接続用の4桁PINも画面に表示します。

cat > ~/bin/uxplay-controller.applescript <<'EOF'
set controlScript to (POSIX path of (path to home folder)) & "bin/uxplay-control.sh"

-- Controller起動時に、UxPlayが止まっていれば自動START
do shell script quoted form of controlScript & " ensure"

repeat
	set statusText to do shell script quoted form of controlScript & " status"

	set buttonResult to button returned of (display dialog statusText buttons {"STOP", "START", "閉じる"} default button "閉じる" with title "UxPlay Controller")

	if buttonResult is "閉じる" then
		exit repeat

	else if buttonResult is "START" then
		do shell script quoted form of controlScript & " start"
		delay 1

	else if buttonResult is "STOP" then
		do shell script quoted form of controlScript & " stop"
		delay 1
	end if
end repeat
EOF

アプリ化します。

mkdir -p ~/Applications
osacompile -o ~/Applications/UxPlay\ Controller.app ~/bin/uxplay-controller.applescript

起動します。

open ~/Applications/UxPlay\ Controller.app

起動すると、以下のような画面が表示されます。

UxPlay 状態: 稼働中
LaunchAgent: 読み込み済み

AirPlay接続PIN: 4832

iPhone/iPad側でPINを求められたら、この4桁を入力してください。

プロセス:
12345 /Users/ユーザー名/Downloads/UxPlay/uxplay ...

START: AirPlay待受を開始 / 再起動
STOP: AirPlay待受を停止

ボタンの意味

  • START:新しい4桁PINを生成して、UxPlayを起動 / 再起動する
  • STOP:UxPlayを停止する
  • 閉じる:コントローラーだけ閉じる

コントローラーを閉じても、UxPlay本体は停止しません。使い終わるときは、必ずSTOPを押します。

Dockから使いやすくする

Finderでアプリフォルダを開きます。

open ~/Applications

UxPlay Controller.appをDockにドラッグしておくと、次回からクリックだけでAirPlay待受を開始できます。

Macログイン時に自動で開く場合

Macログイン時に自動でコントローラーを開きたい場合は、ログイン項目に追加します。

システム設定
→ 一般
→ ログイン項目
→ UxPlay Controller.appを追加

この設定にすると、Macログイン時にコントローラーが開き、コントローラー起動時の自動START処理によってUxPlayも起動します。

トラブルシューティング

緑色の画面が出る

GStreamerの映像出力ウィンドウが緑色で表示される場合があります。これはAirPlay接続前の待受ウィンドウなので異常ではありません。

iPhoneやiPadから接続すると、そのウィンドウにミラーリング映像が表示されます。

STOPしても復活する

LaunchAgentのplistに以下が入っていると、UxPlayが終了しても自動復活します。

<key>KeepAlive</key>
<true/>

今回の構成では以下にします。

<key>KeepAlive</key>
<false/>

もし勝手に復活する場合は、停止コマンドを実行します。

~/bin/uxplay-control.sh stop

GUIにPINが表示されない

PINファイルがまだ作られていない可能性があります。

以下でSTARTし直します。

~/bin/uxplay-control.sh start

その後、状態を確認します。

~/bin/uxplay-control.sh status

UxPlayが起動しない

まずログを確認します。

tail -100 ~/Library/Logs/UxPlay/uxplay.err.log
tail -100 ~/Library/Logs/UxPlay/uxplay-launch.log

uxplay not foundと出る場合は、start-uxplay.sh内のUxPlay本体パスが違っています。

探すには以下を実行します。

find ~/Downloads ~/bin ~/Applications /usr/local /opt/homebrew -name uxplay -type f 2>/dev/null

今回の手順通りなら、以下にあるはずです。

~/Downloads/UxPlay/uxplay

違う場所にある場合は、~/bin/start-uxplay.sh内の以下を修正してください。

UXPLAY_BIN="$HOME/Downloads/UxPlay/uxplay"

まとめ

これで、AirPlay非対応のMacでも、UxPlayを使ってiPhoneやiPadの画面をミラーリングできるようになります。

最終的な構成は以下です。

GStreamer:公式pkg版を使用
UxPlay:GitHubから取得してビルド
起動:~/bin/start-uxplay.sh
制御:~/bin/uxplay-control.sh
管理:LaunchAgent
操作:UxPlay Controller.app
PIN表示:GUI上に4桁PINを表示

普段はDockのUxPlay Controller.appを開くだけでAirPlay待受を開始できます。iPhoneやiPad側でPINを求められた場合も、GUIに表示された4桁を入力すればOKです。

よかったらシェアしてね!
  • URLをコピーしました!
目次