Why not login to Qiita and try out its useful features?

We'll deliver articles that match you.

You can read useful information later.

0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Ubuntuのホームリモート環境でホスト側デバイスを一時的に無効にする(途中)

Last updated at Posted at 2025-09-05

Ubuntu 24.04のホームリモート環境 (Moonlight+Sunshine) でホスト側のデバイスを一時的に無効にしたいと思ってスクリプトを書いてみました。なおホスト環境とホームリモート環境の切り替えはホスト側に接続されたマクロキーボード(MKESPN K806)で行っています(参考)。

現状ではディスプレイの復帰でWMの設定やウインドウの位置がおかしくなったり、インプットデバイスの無効化のコードが不安定だったり(こっちはコメントアウト中)で、まだオススメできる段階ではないですが、方向は合ってるはずなので誰かの参考になれば幸いです。

ホームリモート環境への切り替え:

switch_to_sunshine.sh
#!/bin/sh

# PID を取得
PID=$(pgrep -x sunshine)

if [ -z "$PID" ]; then
    echo "Sunshine is not running. Starting..."
    /usr/bin/sunshine &>/dev/null &
fi

# プロセス状態を確認
STAT=$(ps -o stat= -p "$PID")
if echo "$STAT" | grep -q "[ZT]"; then
    echo "Sunshine exists but is stopped or zombie (STAT=$STAT). Restarting..."
    kill -9 "$PID" 2>/dev/null
    /usr/bin/sunshine &>/dev/null &
fi


# ポート応答チェック
if ! ss -u -l | grep -q "$SUNSHINE_PORT"; then
    echo "Sunshine not responding on port $SUNSHINE_PORT. Restarting..."
    pkill -x sunshine
    /usr/bin/sunshine &>/dev/null &
fi

if ! ss -u -l | grep -q "$SUNSHINE_PORT"; then
    echo "Sunshine is not running because of unknown error."
    exit 1
fi

echo "Sunshine is running and responding."


# ddcutil detect 出力から I2C bus と Product code を取得
mapfile -t displays < <(ddcutil detect --sleep-multiplier 0.1 | awk '
/Display [0-9]+/ {display_id=$2}
/I2C bus:/ {i2c=$3}
/Product code:/ {code=$3; print i2c ":" code}
')

# ディスプレイごとに消灯
for display in "${displays[@]}"; do
    bus="${display%%:*}"
    code="${display##*:}"

    # Product code に応じて値を決定
    case "$code" in
        48322)  # MSI MPG 274URF QD
                # https://qiita.com/vipper36/items/9d400c6147f5b4af94e2
            value=4
            ;;
        19771)  # ViewSonic VX2718 Series
            value=5
            ;;
        *)
            echo "Unknown product code $code on bus $bus, skipping."
            continue
            ;;
    esac

    echo "Setting value $value on bus $bus (Product code $code)"
    DDCCONTROL_NO_DAEMON=1 ddccontrol -r 0xd6 -w "$value" "dev:$bus" &
done

# スクリーンセーバーのロックを無効にする
gsettings set org.gnome.desktop.screensaver lock-enabled false

# ホスト側のオーディオ出力をミュートにする
DEFAULT_SINK=$(LANG=C pactl info | grep "Default Sink" | awk '{print $3}')
pactl set-sink-mute "$DEFAULT_SINK" 1

# バグりやすいため無効化
if [ ]; then

# 無効化したくないデバイス名のリスト(改行区切り)
# 重要: "INSTANT USB GAMING MOUSE  Keyboard" (MKESPN K806) の部分は復帰用デバイスを指定する
EXCLUDE_DEVICES=$(cat <<'END'
Virtual core pointer
Virtual core keyboard
Virtual core XTEST pointer
Virtual core XTEST keyboard
Mouse passthrough
Keyboard passthroughxin
Power Button
Sleep Button
INSTANT USB GAMING MOUSE  Keyboard
END
)

# masterの番号を保存
xinput list > /tmp/xinput_list

# xinput listから "名前, ID" をまとめて取得してループ
xinput list | grep -oP '↳\s+.*id=\d+' | while read -r line; do
    # 名前部分とID部分を分割
    dev=$(printf "%s" "$line" | sed -E 's/↳\s*([^ ].*[^ ])\s+id=.*/\1/')
    id=$(printf "%s" "$line" | sed -E 's/.*id=([0-9]+).*/\1/')

    # 除外リストに含まれていなければ無効化解除
    echo "$EXCLUDE_DEVICES" | grep -Fxq "$dev"
    if [ $? -ne 0 ]; then
        echo "Disabling $dev (ID: $id)"
        # xinput disable "$id"
        xinput float "$id"
    fi
done

fi

ホスト環境への切り替え:

switch_from_sunshine.sh
#!/bin/sh

# PID を取得
PID=$(pgrep -x sunshine)

# プロセスを終了
if [ -z "$PID" ]; then
    kill -9 "$PID" 2>/dev/null
fi

# ddcutil detect 出力から I2C bus と Product code を取得
mapfile -t displays < <(ddcutil detect --sleep-multiplier 0.1 | awk '
/Display [0-9]+/ {display_id=$2}
/I2C bus:/ {i2c=$3}
/Product code:/ {code=$3; print i2c ":" code}
')

# ディスプレイごとに消灯より復帰
for display in "${displays[@]}"; do
    bus="${display%%:*}"
    code="${display##*:}"

    # Product code に応じて値を決定
    case "$code" in
        48322)  # MSI MPG 274URF QD
                # https://qiita.com/vipper36/items/9d400c6147f5b4af94e2
            value=2
            ;;
        19771)  # ViewSonic VX2718 Series
            value=1
            ;;
        *)
            echo "Unknown product code $code on bus $bus, skipping."
            continue
            ;;
    esac

    echo "Setting value $value on bus $bus (Product code $code)"
    DDCCONTROL_NO_DAEMON=1 ddccontrol -r 0xd6 -w "$value" "dev:$bus" &
done

# スクリーンセーバーのロックを有効にする
gsettings set org.gnome.desktop.screensaver lock-enabled true

# ホスト側のオーディオ出力をミュートより復帰
DEFAULT_SINK=$(LANG=C pactl info | grep "Default Sink" | awk '{print $3}')
pactl set-sink-mute "$DEFAULT_SINK" 0

# バグりやすいため無効化
if [ ]; then

# 無効化したくないデバイス名のリスト(改行区切り)
# 重要: "INSTANT USB GAMING MOUSE  Keyboard" (MKESPN K806) の部分は復帰用デバイスを指定する
EXCLUDE_DEVICES=$(cat <<'END'
Virtual core pointer
Virtual core keyboard
Virtual core XTEST pointer
Virtual core XTEST keyboard
Mouse passthrough
Keyboard passthrough
Power Button
Sleep Button
INSTANT USB GAMING MOUSE  Keyboard
END
)

# xinput listから "名前, ID, Master ID" をまとめて取得してループ
cat /tmp/xinput_list | grep -oP '↳\s+.*id=\d+.*\(\d+\)\]' | while read -r line; do
    # 名前部分とID部分を分割
    dev=$(printf "%s" "$line" | sed -E 's/↳\s*([^ ].*[^ ])\s+id=.*/\1/')
    id=$(printf "%s" "$line" | sed -E 's/.*id=([0-9]+).*/\1/')
    master=$(printf "%s" "$line" | sed -E 's/.*\(([0-9]+)\)\].*/\1/')

    # 除外リストに含まれていなければ無効化解除
    echo "$EXCLUDE_DEVICES" | grep -Fxq "$dev"
    if [ $? -ne 0 ]; then
        echo "Enabling $dev (ID: $id)"
        # xinput enable "$id"
        xinput reattach "$id" "$master"
    fi
done

fi
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up

Comments

No comments

Let's comment your feelings that are more than good

0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Login to continue?

Login or Sign up with social account

Login or Sign up with your email address