Arch Linuxで、USBスピーカーを抜き刺ししたときに自動的に音声出力先を変える。
ども、BobbyQuineです。今までUSBスピーカーはWindowsマシンの方で使っていたのでとくには弄って無かったのですが、色々あってArchマシンの方で使うことになったのでちょいと弄ってみました。
※2019/01/14追記:/etc/asound.confを編集するように書かれていますがこれだとシステム全体に適応されます。また、後の方に書いてあるシェルスクリプトを実行するにはsudoが必要になってしまいます。なのでユーザーごとの設定ファイルである~/.asoundrcに読み替えたほうがよいかと思われます。
まずは以前やったこちらについて、
http://bobbyquine.hatenablog.com/entry/2018/01/29/225506
この " /etc/modprobe.d/alsa-base.conf "と言うファイルはいらないので削除します。
と言うか邪魔です。
$ sudo rm /etc/modprobe.d/alsa-base.conf
次にここ( Advanced Linux Sound Architecture - ArchWiki )を参考に " /etc/udev/rules.d/00-local.rules " を編集します。と言うかコピペです。
$ sudo vim /etc/udev/rules.d/00-local.rules
KERNEL=="pcmC[D0-9cp]*", ACTION=="add", PROGRAM="/bin/sh -c 'K=%k ; K=$${K#pcmC}; K=$${K%%D*}; echo defaults.ctl.card $$K > /etc/asound.conf; echo defaults.pcm.card $$K >>/etc/asound.conf'"
KERNEL=="pcmC[D0-9cp]*", ACTION=="remove", PROGRAM="/bin/sh -c 'echo defaults.ctl.card 0 > /etc/asound.conf; echo defaults.pcm.card 0 >>/etc/asound.conf'"
2018/10/17追記
上記設定だと、USBスピーカーをつないだまま再起動すると発生するデバイスナンバリングの変化に対応できないのでこうした。
KERNEL=="pcmC[D0-9cp]*", ACTION=="add", PROGRAM="/bin/sh -c 'cat /proc/asound/modules|grep usb|sed -e s/^/defaults.ctl.card/ -e s/\ snd_usb_audio// > /etc/asound.conf; cat /proc/asound/modules|grep usb|sed -e s/^/defaults.pcm.card/ -e s/\ snd_usb_audio// >>/etc/asound.conf'"
KERNEL=="pcmC[D0-9cp]*", ACTION=="remove", PROGRAM="/bin/sh -c 'cat /proc/asound/modules|grep intel|sed -e s/^/defaults.ctl.card/ -e s/\ snd_hda_intel// > /etc/asound.conf; cat /proc/asound/modules|grep intel|sed -e s/^/defaults.pcm.card/ -e s/\ snd_hda_intel// >>/etc/asound.conf'"
こういうところでシェル芸やってたのが役にたつね。
追記以上
まぁそのまんまですね。カーネルまわりはよく分からないのでアレですが要するにUSBサウンドカードが追加されたら " /etc/asound.conf " を編集してるってだけですね。
でもこれ、自動化したぶんCPU食ってるのよね、ってことでこんなものも作ってみた。
vim ~/Command/usbaudio
#!/bin/bash
if test $1 = "0" ;then
echo "defaults.ctl.card 0" > /etc/asound.conf
echo "defaults.pcm.card 0" >> /etc/asound.conf
echo "set audio output Headphone"
else
if cat /proc/asound/modules|grep 1 > /dev/null ; then
echo "defaults.ctl.card 1" > /etc/asound.conf
echo "defaults.pcm.card 1" >> /etc/asound.conf
echo "set audio output USB Speaker"
else
echo "defaults.ctl.card 0" > /etc/asound.conf
echo "defaults.pcm.card 0" >> /etc/asound.conf
echo "set audio output Headphone"
fi
fi
まぁUSBスピーカーを抜き差ししたときにこれ実行すれば出力デバイス変えてくれるよね、ってことで。しかもこいつを使えばUSBスピーカー刺した状態でも内蔵チップ出力に変えられる。
http://bobbyquine.hatenablog.com/entry/2018/03/24/164602
こんな風にコマンド化して
$ usbaudio 0
ってね。
ちなみに余談だけどこのシェルスクリプトの入れ子のif文に使ってる条件式、
cat /proc/asound/modules|grep 1 > /dev/null
って部分、いつだったかツイッターで見かけて気に入って使ってるやり方。
順を追って説明すると
$ cat /proc/asound/modules
ってしたときにUSBスピーカーが刺さっていると当環境下だと
0 snd_hda_intel
1 snd_usb_audio
って出力され、USBスピーカーが刺さってないと
0 snd_hda_intel
って出力される。まぁ/dev化が監視されてて自動で書き換わるようにできてる(/proc下だから云々ってのはめんどいからry)。
んで、だ。こいつの標準出力をgrepに渡してやって " 1 " って条件で検索してやる。
で、検索結果は/dev/nullに捨てちゃう。欲しいのは処理が成功したか失敗したかだけだから。
USBスピーカーが刺さってればgrepは成功したとOS側に返す。刺さって無ければ失敗したって返す。これを横取りしてif文に渡してやればスピーカー刺さってる刺さってないが分けられる。
っていうかgrepって検索結果が無いときはエラーコード返してるのね、今回の収穫はそこだわ。
このやり方初めて見たときはめっちゃ感動したなぁ。
というわけでいつも通りグダグダな記事でした。