我有这个脚本可以使用 MIDI 控制器更改计算机的音量:
#!/bin/bash
# both times in ms
CURRENT_TIME=$(($(date +%s%N)/1000000))
DELAY=70
aseqdump -p "MPK mini 3" | \
while IFS=" ," read src ev1 ev2 ch label1 data1 label2 data2 rest; do
if (( (($(date +%s%N)/1000000)) > (($CURRENT_TIME + $DELAY)) ))
then
case "$ev1 $ev2 $data1 $data2" in
"Control change 23 $data2" )
echo $data2
pamixer --set-volume $data2 ;;
esac
fi
done
aseqdump
发送旋钮变化的数据流,如下所示:
16:0 Control change 0, controller 23, value 50
16:0 Control change 0, controller 23, value 51
16:0 Control change 0, controller 23, value 52
16:0 Control change 0, controller 23, value 53
16:0 Control change 0, controller 23, value 54
该脚本有一个延迟,以确保它只每隔一段时间而不是不断地读取一行,但这似乎不起作用。无论我做什么,它总是从头到尾贯穿整个流程。
即使我添加了延迟,脚本也会遍历
aseqdump
生成的每一行。我希望它只读取程序输出的最后一行,因为不断地使用每个值设置音量会导致音量变化显着延迟。
我还尝试用
sleep
命令替换延迟,但这似乎只会使更改音量需要更长的时间。
#!/bin/bash
aseqdump -p "MPK mini 3" | \
while IFS=" ," read src ev1 ev2 ch label1 data1 label2 data2 rest; do
sleep 0.07
case "$ev1 $ev2 $data1 $data2" in
<the rest of the script from above>
我不知道如何只使用最近的一行,坦率地说,我花了几个小时思考和谷歌搜索,但毫无结果。如果有人可以提供帮助,我将非常感激。
在
(( (($(date +%s%N)/1000000)) > (($CURRENT_TIME + $DELAY)) ))
中,外部双括号告诉 bash 对 (( ... ))
的内容进行算术运算,但内部双括号只是冗余地加倍,因为它们是算术运算的一部分,相当于 (( ($(date +%s%N)/1000000) > ($CURRENT_TIME + $DELAY) ))
不要在循环内重复计算任何无法在循环内更改的内容,在这种情况下
$CURRENT_TIME + $DELAY
- 在循环开始之前计算一次。
关于“脚本有延迟以确保它只每隔一段时间读取一行” - 不,它不会,它会不断旋转读取输入并调用
date
但只执行 case
语句经常这样。
听起来这可能就是您想要做的:
#!/usr/bin/env bash
# both times in ms
current_time=$(( $(date +%s%N) / 1000000 ))
delay=70
while :; do
IFS=" ," read src ev1 ev2 ch label1 data1 label2 data2 rest \
< <(aseqdump -p "MPK mini 3" | tail -1)
if [[ "$ev1 $ev2 $data1 $data2" == "Control change 23 $data2" )
echo "$data2"
pamixer --set-volume "$data2" ;;
fi
sleep "$delay"
done
但是从你的问题中并不清楚。