Close

又少了一個用桌面環境的理由——在dwm中配置聲音操控

在b站摸魚的時候突然想到,萬一有那種需要調低音量的情況,怎麼便捷地實現呢。(至於是怎樣的情況纔會有這個需求,有機會再考慮吧……)如果使用 Gnome 或者 KDE 的話,似乎都有很完整的配件來識別膝上型電腦上各種功能鍵,也有小配件(widgets)能夠展示目前的音量大小。但是爲了這樣簡單的功能,真的需要安裝一個程式麼?

綁定音量鍵

Xorg 的包當中有一個非常實用的功能 xbindkeys,用於自定義鍵盤設置,其優點在於能夠在每次登錄圖形界面的時候加載配置文件,而不需要重新編譯(和 dwm 本身不同)。配置文件 .xbindkeysrc 在用戶目錄中,基本語法是:

# "command" for example "ls"
#   keycode for example "Mod4 + l"

於是我們需要確認兩件事:

  • 調整音量的語句
  • 鍵盤上的功能鍵的 keycode

ALSA (Linux 高級音響機構)

之所以要把翻譯打出來,大家不覺得這個名字很帥氣麼 Advanced Linux Sound Architecture,帶上了 Advanced 就讓人覺得很賽博時代,實際上 ALSA 的操作界面 amixer 是一個乾脆無比的命令行工具,具體用法是:amixer set <device> <options>,在我的情況,我只需要調整整體音量就可以,所以 <device> 就是 Master,而設置的參數可以是 x(dB|%)+x(dB|%)-(un)mutetoggle,對我來說由於並沒有專業設備,所以按照百分數來設置聲音更直觀一些,而因爲 thinkpad 上只有一個靜音按鈕,所以用 toggle 會比較方便,那麼我用到的命令就是:

# toggle sound status
amixer set Master toggle > /dev/null

# lower volume
amixer set Master 2%- > /dev/null

# raise volume
amixer set Master 2%+ > /dev/null

注意到,我把所有的輸出都丟到了 /dev/null 裏面,這個看上去像文件一樣的東西實際上是一個黑洞,任何丟進去的東西都會消失不見,就方便我們把不想看見的輸出丟棄了。

xbindkeys 找到鍵名

xbindkeys 提供了一個很好的工具,用來找到鍵名,所以說一個款好的工具就是那麼貼心,不會在你不舒服的時候叫你喝熱水。輸入

xbindkeys --multikey

按的任何鍵的鍵名都會被打印在終端裏,我按順序按下了靜音、調低和調高聲響的按鈕,於是得到鍵名(keycode)把它們寫到剛剛的 .xbindkeysrc 中:

# toggle sound status
“amixer set Master toggle > /dev/null”
  m:0x0 + c:121

# lower volume
"amixer set Master 2%- > /dev/null"
  m:0x0 + c:122

# raise volume
"amixer set Master 2%+ > /dev/null"
  m:0x0 + c:123

這樣一來就完成了音量鍵的設置,然後我就突然意識到,剛剛文章開頭的情況,我只要設置靜音鍵就可以了吧?

狀態欄設置

如果我有好好更新部落格的話,本來大家是應該知道 dwm 的狀態欄是通過 xsetroot -name 來更新的,所以我們要做的僅僅是獲取音量情況,然後把信息添加到 xsetroot 後面。

再一次呼喚 amixer 然後這次用 sed 秀操作

前文中,我們用 amixer set <device> 的命令來設置音量的值,這裏我們可以用 amixer sget <device> 來獲得音量的值,結果大致是這樣的:

$ amixer set Master toggle
Simple mixer control 'Master',0
  Capabilities: pvolume pswitch pswitch-joined
  Playback channels: Front Left - Front Right
  Limits: Playback 0 - 65536
  Mono:
  Front Left: Playback 31730 [48%] [on]
  Front Right: Playback 31730 [48%] [on]

我的目標就是最後兩行中的最後兩個括弧中的內容。參考了 Danilo Bargen 的腳本,他的腳本當中同時使用了 grepsed, 我認爲這就有點 overkill 了,畢竟我們要找的內容結構清晰,單用 sed 足以找到並且打印出來:

首先我們要找到包含 "Front Left:" 的行,仔細觀察可以發現字符序列 ft: 足以區分出這一行,由於我們不需要別的行,因此我們指定 sed -n 來阻止他打印別的行,而後用 p 來指定打印吻合的內容,最後我們尋找需要匹配的內容,來代替(substitute)整行,所以這個代碼應該具有這樣的格式:

sed -n "s/...\(<pattern needed>\).../\1/p"

考慮我們的行,應該是 .*ft:.*,而後,需要的 pattern 是 \[[0-9].*$,即從方括弧開始,繼以一個數字,一直到行末的信息。將上述內容組合起來:

amixer sget Master | sed -n 's/.*ft:.*\(\[[0-9].*%\)/\1/p'

上述命令打印出來 [48%] [on] 就是我們需要的內容。

無限循環更新狀態

.xinitrc 中加入這個 while true 循環:

while true; do
  VOLUME=`amixer sget Master | sed -n '...'`
  xsetroot -name "$VOLUME"
done

當然,我們也可以在 xsetroot 當中加入更多需要的狀態,我的話加入了 date +"%e %b %r" 時鐘和 ibus engine | cut -d: -f4 輸入法狀態。

這樣在利用系統已有的服務而不新安裝包裹的情況下,我們完成了看電視調控聲音的需求。這是一篇做完設定然後突然想起來記錄一下的文章,所以各方面組織就比較隨意了。

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

沪ICP备19039127号-1