web-dev-qa-db-ja.com

モニターが接続されている、または接続されていないことを検出するにはどうすればよいですか?

ノートパソコンのDisplayPortに外部モニターをプラグインまたはプラグアウトしたときにトリガーされるanyイベントはありますか? ACPIDとUDEVはまったく反応しません。

Intelチップでオンボードグラフィックスを使用しています。 ここ は、すでに数年前の同様の議論です。

ポーリングを使用したくありませんが、ディスプレイが接続されているかどうかに応じて、ディスプレイ設定を自動的に設定するいくつかの構成が必要です。

54
janoliver

注:これは、i915駆動グラフィックカードを搭載したラップトップでテストされました。


バックグラウンド

注:新しい画面が接続されると、イベントがホストに送信されず、これは最後の編集後もtrueのままでした。したがって、唯一の方法はポーリングを使用することです。それらを可能な限り効率的にしようとしています...

編集#3

最後に、(ACPIを介して)1つのより良いソリューションがあります。

まだイベントはありませんが、ACPIはxrandrよりも問い合わせに効率的です。 (注意:これはACPIカーネルモジュールをロードする必要がありますが、root権限は必要ありません)。

私の最終的な解決策(bashを使用):

isVgaConnected() {
    local crtState
    read -a < /proc/acpi/video/VID/CRT0/state crtState
    test $(( ( ${crtState[1]} >>4 ) ${1:+*-1+1} )) -ne 0
}

今テスト:

$ if isVgaConnected; then echo yes; else echo no; fi 
yes

差し込まれているので、今は外します。

$ if isVgaConnected; then echo yes; else echo no; fi 
no

注:${1:+*-1+1} permit boolean argument:If something is現在、答えは逆になります:( crtState >> 4 ) * -1 + 1

そして最後のスクリプト:

#!/bin/bash

export crtProcEntry=/proc/acpi/video/VID/CRT0/state

isVgaConnected() {
    local crtState
    read -a < $crtProcEntry crtState
    test $(( ( ${crtState[1]} >>4 ) ${1:+*-1+1} )) -ne 0
}

delay=.1
unset switch
isVgaConnected || switch=not
while :;do
    while isVgaConnected $switch;do
        sleep $delay
      done
    if [ "$switch" ];then
        unset switch
        echo VGA IS connected
        # doing something while VGA is connected
      else
        switch=not
        echo VGA is NOT connected.
        # doing something else, maybe.
      fi
  done

警告:xrandrよりも軽いが、重要ではない0.02秒、Bashスクリプトはリソースイータープロセス(top)の先頭に移動します!

これには約0.001秒かかりますが、

$ time read -a </proc/stat crtStat

これには〜0.030秒必要です:

$ read -a < /proc/acpi/video/VID/CRT0/state crtState

これは大きいです!したがって、必要に応じて、delay0.52の間で合理的に設定できます。

編集#2

これを使って、ようやく何かを見つけました:

重要な免責事項:/procおよび/sysエントリを使用すると、システムが壊れる可能性があります!!!したがって、本番システムでは以下を試さないでください。

mapfile watchFileList < <(
    find /sys /proc -type f 2>/dev/null |
    grep -i acpi\\\|i91 
)

Prompt=("/" "|" '\' '-');

l=0
while :; do
  mapfile watchStat < <(
    grep -H . ${watchFileList[@]} 2>/dev/null
  )

  for ((i=0;i<=${#watchStat[@]};i++)); do
    [ "${watchStat[i]}" == "${oldStat[i]}" ] || echo ${watchStat[i]}
  done

  oldStat=("${watchStat[@]}")
  sleep .5
  printf "\r%s\r" ${Prompt[l++]}
  [ $l -eq 4 ]&&l=0
done

...不要なエントリをいくつか削除した後:

for ((i=0;i<=${#watchFileList[@]};i++)); do
  [[ "${watchFileList[$i]}" =~ /sys/firmware/acpi/interrupts/sci ]] &&
      unset watchFileList[$i] && echo $i
done

私はこれを読むことができました:

/proc/acpi/video/VID/CRT0/state:state: 0x1d
/proc/acpi/video/VID/CRT0/state:state: 0x0d
/proc/acpi/video/VID/CRT0/state:state: 0x1d

モニターケーブルを接続、取り外し、再接続したとき。

設定が照会されると(system/preferences/monitorまたはxrandrを実行)、グラフィックカードは scan のタイプを実行するため、xrandr -qを実行すると、情報ですが、ステータスをポーリングする必要があります。

私はすべてのログ(カーネル、デーモン、Xなど)をスキャンして/proc/sysを検索しましたが、リクエストを満たすものが何も存在しないようです。

私もこれを試しました:

export spc50="$(printf "%50s" "")"
watch -n1  '
    find /proc/acpi/video -type f |
        xargs grep -H . |
        sed "s/^\([^:]*):/\1'$spc50'}:/;
             s/^\(.\{50\}\) *:/\1 /"'

結局、新しい画面が接続されていない、または接続されていないときにSystem/Preferences/Monitorを実行すると、ツールは(通常は)単純に表示されます。ただし、以前に画面を接続または切断したことがある場合は、このツールを実行すると、デスクトップが reset またはのタイプを作成することがわかります更新xrandrを実行した場合も同じ)。

これは、このツールが実行時に開始して定期的にステータスをポーリングすることにより、このツールがxrandrを要求する(または同じように機能する)ことを確認しているようです。

あなたは自分で試すことができます:

$ for ((i=10;i--;)); do xrandr -q | grep ' connected' | wc -l; sleep 1; done
1
1
1
2
2
2
1
1
1
1

これにより、接続されている画面(ディスプレイ)の数が10秒間表示されます。

これが実行されている間、画面/モニターを接続または取り外して、何が起こっているかを確認します。したがって、小さなBashテスト関数を作成できます。

isVgaConnected() {
    local xRandr=$(xrandr -q)
    [ "$xRandr" == "${xRandr#*VGA1 con}" ] || return 0
    return 1
}

これは次のように使用できます。

$ if isVgaConnected; then echo yes; fi

ただし、xrandrには約0.140秒から0.200秒かかりますが、プラグおよび0.700秒直前に何かが接続または取り外しされたとき(注:リソースではないようです食べる人)。

編集#1

私が何か間違ったことを教えていないことを確認するために、私はWebとドキュメントを検索しましたが、 DBusとScreens については何も見つかりませんでした。

最後に、2つの異なるウィンドウdbus-monitor --system(私もオプションで遊んでいます)で実行し、記述した小さなスクリプトを実行しました。

$ for ((i=1000;i--;)); do isVgaConnected && echo yes || echo no; sleep .5; done

...何度も何度も、プラグを抜いて、モニターを抜いた。だから今私は言うことができます:

  • この構成では、i915ドライバーを使用してxrandr -qを実行して、モニターが接続されているかどうか。

しかし、他の方法がないように見えるので、注意してください。たとえば、xrandrはこの情報を共有しているようです。そのため、GNOMEデスクトップはxineramaに自動的に切り替わります...実行したときにxrandr

一部のドキュメント

14
F. Hauri

次の行がudevadm monitor

KERNEL[46578.184280] change   /devices/pci0000:00/0000:00:02.0/drm/card0 (drm)
UDEV  [46578.195887] change   /devices/pci0000:00/0000:00:02.0/drm/card0 (drm)

モニターをVGAコネクタに接続する場合。したがって、これを理解する方法があるかもしれません。

4
sebastianwagner

srandrd の使用にこだわりました。 Xイベントを監視し、ディスプレイが接続または切断されたときにスクリプトをトリガーします。

3
scorpp

何らかの理由でhotplugルートを使用したくない場合は、inotifywaitを使用してスクリプト内でポーリングしないことも可能です。

#!/ bin/bash 
 
 SCREEN_LEFT = DP2 
 SCREEN_RIGHT = eDP1 
 START_DELAY = 5 
 
 renice +19 $$>/dev/null 
 
 sleep $ START_DELAY 
 
 OLD_DUAL = "dummy" 
 
 while [ 1]; do 
 DUAL = $(cat /sys/class/drm/card0-DP-2/status)

 if ["$ OLD_DUAL"!= "$ DUAL"];次に
 if ["$ DUAL" == "connected"]; then 
 echo 'デュアルモニターのセットアップ' 
 xrandr --output $ SCREEN_LEFT --auto --rotate normal --pos 0x0 --output $ SCREEN_RIGHT --auto --rotate normal --below $ SCREEN_LEFT 
 else 
 echo 'シングルモニターセットアップ' 
 xrandr --auto 
 fi 
 
 OLD_DUAL = "$ DUAL" 
 fi 
 
 inotifywait -q -e close/sys/class/drm/card0-DP-2/status>/dev/null 
 done 
 

末尾の&を忘れないで、.xsessionrcから呼び出すのが最適です。 xrandrでポーリングすると、私の真新しいラップトップで深刻なユーザビリティの問題が発生しました(マウスは定期的に停止します)。

3
Balzola

明らかに何かがあるはずです! :)/sysファイルシステムは、利用可能なハードウェアをユーザー空間に通知するため、ユーザー空間ツール(udevやmdevなど)は、現在利用可能なハードウェアを表すデバイスノードを「/ dev」ディレクトリに動的に入力できます。 Linuxには、/ sbin/hotplugとnetlinkの2つのホットプラグインターフェイスが用意されています。

次のファイルに小さなCデモがあります。 http://www.kernel.org/doc/pending/hotplug.txt

0
roncsak

今日のLinuxのシステム/アプリケーションソフトウェアのほとんどは、相互に通信するためにいくつかのipcテクニックを使用しています。 D-Busは現在GNOMEアプリケーションで主に使用されており、役立つ可能性があります。

Linuxジャーナル:

D-BUSは、システムを介したイベントまたは信号の送信を容易にし、システム内のさまざまなコンポーネントが通信し、最終的にはより適切に統合できるようにします。たとえば、Bluetoothデーモンは、音楽プレーヤーが傍受できる着信信号を送信し、通話が終了するまで音量をミュートできます。

wiki:

D-Busは、システムデーモン(「新しいハードウェアデバイスの追加」や「プリンターキューの変更」などのイベント用)とユーザーごとのログインセッションデーモン(ユーザーアプリケーション間の一般的なプロセス間通信のニーズ用)の両方を提供します

Pythonこのためのライブラリもあり、ubuntuは最近、「 zeitgeist 」と呼ばれるこの機能を使用しました。

0
Amir Naghizadeh