dunst로 volume 컨트롤 메시지를 받아보자
나는 왜 이 방식을 연구해야 했나?
Qtile에서 dwm으로 넘어왔다.
미니멀리즘 그 자체다.
필요한 것에 한해 패치를 하면서 몇몇 기능들을 추가해주고 있다.
그 과정에 하나의 문제가 발생했다.
slstatus에 volume이 표시되도록 만들고 싶었는데, 생각대로 잘 되지 않았다.
CPU, Memory, Disk size 등은 autostart를 통해 정상적으로 수치가 잘 표시되지만, volume만은 autostart가 아니라 직접 slstatus & disown 의 방식으로 실행을 해줄때만 표시되는 것이었다.
한참 방법을 찾다가 결국 slstatus에 표시하는 것은 포기했다.
번거롭게 pc를 켤때마다 수동으로 실행하고 싶진 않았기 때문이다.
그러다 문득 생각이 들었다. 굳이 volume을 항상 표시해둘 필요가 있나? volume은 변경될 때만 확인하지 않나? 그렇다. 우리는 volume이 변경될 때만 확인하면 된다.
이를 위해 필요한 방법이 dunst를 통해 메시지 형태로 volume 정보를 띄워주는 것이다.
그 과정을 정리해서 포스팅으로 남겨둔다.
준비사항
본 포스팅은 다음이 준비되어 있는 상황을 가정한다.
- dunst
- pulseaudio (pactl)
- sh 스크립트를 작성에 대한 기본적인 이해
리눅스 배포판이나 desktop environment는 어떤 것이든 상관없을 것 같다.
dunst의 아주 간단한 사용법
dunst의 dunstify 명령어를 사용하면 다음처럼 화면에 원하는 메시지를 띄울 수 있다.
dunstify "dunst 테스트 중입니다. 메시지가 잘 보이나요?"
이걸 응용하면 volume을 조절할 때마다 자동으로 현재 volme값을 메시지로 띄워줄 수 있다.
dunst에 기반하여 volume 메시지를 띄우는 스크립트
이 방식을 구현하고 있는 참고자료가 arch wiki의 dunst 페이지에 있다. 이걸 가져와서 내 환경에 맞게 조금 수정했더니 아주 손쉽게 성공했다. 나는 사용중인 pulseaudio에 맞춰 조금 수정하였다.
#!/bin/bash
# Arbitrary but unique message tag
msgTag="dun-volume"
# Query pactl for the current volume and whether or not the speaker is muted
volume="$(pactl get-sink-volume @DEFAULT_SINK@ | awk '{print $5}' | sed 's/[^0-9]*//g')"
mute="$(pactl get-sink-mute @DEFAULT_SINK@ | awk '{print $2}')"
if [[ $volume == 0 || "$mute" == "yes" ]]; then
# Show the sound muted notification
dunstify -a "changeVolume" -u low -i audio-volume-muted -h string:x-dunst-stack-tag:$msgTag "Volume muted"
else
# Show the volume notification
dunstify -a "changeVolume" -u low -i audio-volume-high -h string:x-dunst-stack-tag:$msgTag \
-h int:value:"$volume" "Volume: ${volume}%"
fi
# Play the volume changed sound
canberra-gtk-play -i audio-volume-change -d "changeVolume"위 스크립트는 다음과 같은 기능을 순차적으로 처리한다.
pactl명령어를 통해DEFAULT_SINK의 volume 수치와 mute 상태를 가져온다.- 가져온 volume과 mute 상태를
dunstify -a "ChangeVolume" ~~와 같은 형태로 dunst에 메시지를 보낸다. 이때 모든 메시지에는dun-volume라는 stack-tag를 붙여준다.
여기서 string:x-dunst-stack-tag:$msgTag 부분이 stack-tag를 달아주는 부분이다.
이를 통해 volume 관련 메시지가 중복해서 쌓이는 것을 방지할 수 있다.
그리고 이 stack-tag를 기준으로 메시지가 표시되는 시간인 timeout을 지정해줄 수 있다.
volume 메시지는 오래 표시할 필요가 없지 않은가? 그래서 아주 짧은 시간(e.g. 1초)으로 설정해주면 된다.
timeout을 추가하려면 dunstrc에 다음의 항목을 추가해준다.
[dun-volume]
stack_tag = dun-volume
timeout = 1 # timeout을 1초로 설정dunst는 dunstrc가 수정된 것을 자동으로 인지하여 reload하는 기능을 가지고 있지 않다.
그러니 저장 후 결과가 정상적으로 반영되도록 하기위해 다음을 실행해주자.
dunstctl reload # reload 명령어
killall dunst # 모든 dunst 프로세스 종료volume 조절 버튼이 눌릴 때 스크립트가 실행되게 설정하기
dunst로 메시지를 보내는 스크립트를 작성하였으니, 볼륨조절키가 눌릴때 메시지를 보내는 스크립트를 실행하도록 설정만 해주면 된다.
나는 다음처럼 dwm의 config.h를 수정함으로써 volume을 조절하고 msg를 보내도록 만들었다.
# define cmd
...
static const char *upvolcmd[] = { "sh", "-c", "pactl set-sink-volume @DEFAULT_SINK@ +2% && ~/.local/bin/dun-volume", NULL };
static const char *downvolcmd[] = { "sh", "-c", "pactl set-sink-volume @DEFAULT_SINK@ -2% && ~/.local/bin/dun-volume", NULL };
static const char *mutevolcmd[] = { "sh", "-c", "pactl set-sink-mute @DEFAULT_SINK@ toggle && ~/.local/bin/dun-volume", NULL };
...# key mapping
...
{ 0, XF86XK_AudioLowerVolume, spawn, {.v = downvolcmd } },
{ 0, XF86XK_AudioRaiseVolume, spawn, {.v = upvolcmd } },
{ 0, XF86XK_AudioMute, spawn, {.v = mutevolcmd } },
...dwm을 사용하지 않고 있다면, 사용하는 desktop environmet나 wm에서 volume 조절 및 mute 버튼을 누를 때 실행되는 명령어에 우리가 만든 dun-volume 스크립트가 함께 실행되게 만들어주면 된다.
두구두구~~ 결과는?
자~ 이렇게 스크립트를 짜고 key mapping까지 해주었으면 결과를 확인해보자. 필자는 다음처럼 volume과 mute 메시지가 잘 표시되는 것을 확인했다. 덤으로 1초만에 메시지가 사라지는 것도 잘 작동한다.
마무리하며
dunst가 생각보다 재밌는 것 같다. 잘 활용하면 별별 기능을 다 구현할 수 있을 것 같다. 또 좋은 게 생기면 후속 포스팅을 올려야겠다.