Add MPG341CX input switcher
This commit is contained in:
@@ -525,7 +525,7 @@ bind = $hyper, R, exec, rofi-systemd
|
|||||||
bind = $hyper, slash, exec, toggle_taffybar
|
bind = $hyper, slash, exec, toggle_taffybar
|
||||||
bind = $hyper, 9, exec, start_synergy.sh
|
bind = $hyper, 9, exec, start_synergy.sh
|
||||||
bind = $hyper, I, exec, rofi_select_input.hs
|
bind = $hyper, I, exec, rofi_select_input.hs
|
||||||
bind = $hyper, backslash, exec, /home/imalison/dotfiles/dotfiles/lib/functions/monitor_input toggle
|
bind = $hyper, backslash, exec, /home/imalison/dotfiles/dotfiles/lib/functions/mpg341cx_input toggle
|
||||||
bind = $hyper, O, exec, rofi_paswitch
|
bind = $hyper, O, exec, rofi_paswitch
|
||||||
bind = $hyper, W, exec, rofi_wallpaper.sh
|
bind = $hyper, W, exec, rofi_wallpaper.sh
|
||||||
bind = $hyper, Y, exec, rofi_agentic_skill
|
bind = $hyper, Y, exec, rofi_agentic_skill
|
||||||
|
|||||||
@@ -1,93 +0,0 @@
|
|||||||
#!/usr/bin/env zsh
|
|
||||||
|
|
||||||
function monitor_input_usage {
|
|
||||||
cat <<'EOF'
|
|
||||||
Usage:
|
|
||||||
monitor_input [toggle|dp|usb-c|hdmi1|hdmi2]
|
|
||||||
|
|
||||||
Switches the current DDC/CI monitor input. On the MSI MPG341CX OLED:
|
|
||||||
dp -> DisplayPort
|
|
||||||
usb-c -> USB-C / Type-C
|
|
||||||
toggle -> DisplayPort <-> USB-C
|
|
||||||
|
|
||||||
Environment:
|
|
||||||
MONITOR_INPUT_DDC_DISPLAY ddcutil display number, default: 1
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
function monitor_input_notify {
|
|
||||||
local message="$1"
|
|
||||||
if command -v notify-send >/dev/null 2>&1; then
|
|
||||||
notify-send "Monitor input" "$message"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function monitor_input_current {
|
|
||||||
local display="$1"
|
|
||||||
ddcutil --display "$display" getvcp 60 --terse 2>/dev/null \
|
|
||||||
| grep -Eo 'x[0-9a-fA-F]+' \
|
|
||||||
| tail -1
|
|
||||||
}
|
|
||||||
|
|
||||||
function monitor_input {
|
|
||||||
local target="${1:-toggle}"
|
|
||||||
local display="${MONITOR_INPUT_DDC_DISPLAY:-1}"
|
|
||||||
local value label current
|
|
||||||
|
|
||||||
if [[ "$target" == "-h" || "$target" == "--help" ]]; then
|
|
||||||
monitor_input_usage
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! command -v ddcutil >/dev/null 2>&1; then
|
|
||||||
echo "monitor_input: ddcutil is not available on PATH" >&2
|
|
||||||
monitor_input_notify "ddcutil is not available"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
case "${target:l}" in
|
|
||||||
toggle)
|
|
||||||
current="$(monitor_input_current "$display")"
|
|
||||||
case "${current:l}" in
|
|
||||||
x0f)
|
|
||||||
target="dp"
|
|
||||||
;;
|
|
||||||
x10)
|
|
||||||
target="usb-c"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "monitor_input: current input is '${current:-unknown}', defaulting to DisplayPort" >&2
|
|
||||||
target="dp"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
case "${target:l}" in
|
|
||||||
dp|displayport|display-port)
|
|
||||||
value="0x10"
|
|
||||||
label="DisplayPort"
|
|
||||||
;;
|
|
||||||
usb-c|usbc|type-c|typec)
|
|
||||||
value="0x0f"
|
|
||||||
label="USB-C"
|
|
||||||
;;
|
|
||||||
hdmi1|hdmi-1)
|
|
||||||
value="0x11"
|
|
||||||
label="HDMI 1"
|
|
||||||
;;
|
|
||||||
hdmi2|hdmi-2)
|
|
||||||
value="0x12"
|
|
||||||
label="HDMI 2"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
monitor_input_usage >&2
|
|
||||||
return 2
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
monitor_input_notify "Switching to $label"
|
|
||||||
ddcutil --display "$display" --noverify setvcp 60 "$value"
|
|
||||||
}
|
|
||||||
|
|
||||||
monitor_input "$@"
|
|
||||||
271
dotfiles/lib/functions/mpg341cx_input
Executable file
271
dotfiles/lib/functions/mpg341cx_input
Executable file
@@ -0,0 +1,271 @@
|
|||||||
|
#!/usr/bin/env -S zsh -f
|
||||||
|
|
||||||
|
function mpg341cx_input_usage {
|
||||||
|
cat <<'EOF'
|
||||||
|
Usage:
|
||||||
|
mpg341cx_input [toggle|dp|usb-c|hdmi1|hdmi2]
|
||||||
|
|
||||||
|
Switches the current DDC/CI monitor input. On the MSI MPG341CX OLED:
|
||||||
|
dp -> DisplayPort
|
||||||
|
usb-c -> USB-C / Type-C
|
||||||
|
toggle -> DisplayPort <-> USB-C
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
MPG341CX_INPUT_DDC_DISPLAY DDC display number, default: 1
|
||||||
|
MPG341CX_INPUT_BACKEND auto, ddcutil, ddcctl, or m1ddc; default: auto
|
||||||
|
MPG341CX_INPUT_STATE_FILE fallback toggle state file
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
function mpg341cx_input_notify {
|
||||||
|
local message="$1"
|
||||||
|
if command -v notify-send >/dev/null 2>&1; then
|
||||||
|
notify-send "MPG341CX input" "$message"
|
||||||
|
elif command -v osascript >/dev/null 2>&1; then
|
||||||
|
osascript - "$message" <<'EOF' >/dev/null 2>&1
|
||||||
|
on run argv
|
||||||
|
display notification (item 1 of argv) with title "MPG341CX input"
|
||||||
|
end run
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function mpg341cx_input_backend {
|
||||||
|
local requested="${MPG341CX_INPUT_BACKEND:-auto}"
|
||||||
|
local candidate
|
||||||
|
local -a candidates
|
||||||
|
MPG341CX_INPUT_SELECTED_BACKEND=""
|
||||||
|
|
||||||
|
if [[ "$requested" != auto ]]; then
|
||||||
|
if command -v "$requested" >/dev/null 2>&1; then
|
||||||
|
MPG341CX_INPUT_SELECTED_BACKEND="$requested"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "mpg341cx_input: requested backend '$requested' is not available on PATH" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$OSTYPE" == darwin* ]]; then
|
||||||
|
candidates=(m1ddc ddcctl ddcutil)
|
||||||
|
else
|
||||||
|
candidates=(ddcutil ddcctl)
|
||||||
|
fi
|
||||||
|
|
||||||
|
for candidate in "${candidates[@]}"; do
|
||||||
|
if command -v "$candidate" >/dev/null 2>&1; then
|
||||||
|
MPG341CX_INPUT_SELECTED_BACKEND="$candidate"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "mpg341cx_input: no supported DDC command is available on PATH" >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function mpg341cx_input_current_ddcutil {
|
||||||
|
local display="$1"
|
||||||
|
local output_file
|
||||||
|
|
||||||
|
output_file="${TMPDIR:-/tmp}/mpg341cx-input-current-$$-$RANDOM"
|
||||||
|
ddcutil --display "$display" getvcp 60 --terse 2>/dev/null \
|
||||||
|
| grep -Eo 'x[0-9a-fA-F]+' \
|
||||||
|
| tail -1 > "$output_file"
|
||||||
|
read -r MPG341CX_INPUT_CURRENT < "$output_file"
|
||||||
|
rm -f "$output_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
function mpg341cx_input_current_ddcctl {
|
||||||
|
local display="$1"
|
||||||
|
local current
|
||||||
|
local output_file
|
||||||
|
|
||||||
|
output_file="${TMPDIR:-/tmp}/mpg341cx-input-current-$$-$RANDOM"
|
||||||
|
ddcctl -d "$display" -i '?' 2>/dev/null \
|
||||||
|
| sed -nE 's/.*current: ([0-9]+).*/\1/p' \
|
||||||
|
| tail -1 > "$output_file"
|
||||||
|
read -r current < "$output_file"
|
||||||
|
rm -f "$output_file"
|
||||||
|
|
||||||
|
if [[ -n "$current" ]]; then
|
||||||
|
printf -v MPG341CX_INPUT_CURRENT 'x%02x' "$current"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function mpg341cx_input_current_m1ddc {
|
||||||
|
local display="$1"
|
||||||
|
local current
|
||||||
|
local output_file parsed_file
|
||||||
|
|
||||||
|
output_file="${TMPDIR:-/tmp}/mpg341cx-input-current-$$-$RANDOM"
|
||||||
|
parsed_file="${TMPDIR:-/tmp}/mpg341cx-input-parsed-$$-$RANDOM"
|
||||||
|
|
||||||
|
m1ddc display "$display" get input > "$output_file" 2>/dev/null
|
||||||
|
sed -nE 's/.*[^0-9]([0-9]+)$/\1/p; /^[0-9]+$/p' "$output_file" | tail -1 > "$parsed_file"
|
||||||
|
read -r current < "$parsed_file"
|
||||||
|
rm -f "$output_file" "$parsed_file"
|
||||||
|
|
||||||
|
if [[ -n "$current" ]]; then
|
||||||
|
printf -v MPG341CX_INPUT_CURRENT 'x%02x' "$current"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function mpg341cx_input_current {
|
||||||
|
local backend="$1"
|
||||||
|
local display="$2"
|
||||||
|
MPG341CX_INPUT_CURRENT=""
|
||||||
|
|
||||||
|
case "$backend" in
|
||||||
|
ddcutil)
|
||||||
|
mpg341cx_input_current_ddcutil "$display"
|
||||||
|
;;
|
||||||
|
ddcctl)
|
||||||
|
mpg341cx_input_current_ddcctl "$display"
|
||||||
|
;;
|
||||||
|
m1ddc)
|
||||||
|
mpg341cx_input_current_m1ddc "$display"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
function mpg341cx_input_current_target {
|
||||||
|
local backend="$1"
|
||||||
|
local current="${2:l}"
|
||||||
|
MPG341CX_INPUT_CURRENT_TARGET=""
|
||||||
|
|
||||||
|
case "$backend:$current" in
|
||||||
|
m1ddc:x0f|m1ddc:0x0f)
|
||||||
|
MPG341CX_INPUT_CURRENT_TARGET="dp"
|
||||||
|
;;
|
||||||
|
m1ddc:x10|m1ddc:0x10)
|
||||||
|
MPG341CX_INPUT_CURRENT_TARGET="usb-c"
|
||||||
|
;;
|
||||||
|
ddcutil:x0f|ddcutil:0x0f|ddcctl:x0f|ddcctl:0x0f)
|
||||||
|
MPG341CX_INPUT_CURRENT_TARGET="usb-c"
|
||||||
|
;;
|
||||||
|
ddcutil:x10|ddcutil:0x10|ddcctl:x10|ddcctl:0x10)
|
||||||
|
MPG341CX_INPUT_CURRENT_TARGET="dp"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
function mpg341cx_input_state_file {
|
||||||
|
MPG341CX_INPUT_SELECTED_STATE_FILE="${MPG341CX_INPUT_STATE_FILE:-${XDG_STATE_HOME:-$HOME/.local/state}/mpg341cx_input/input}"
|
||||||
|
}
|
||||||
|
|
||||||
|
function mpg341cx_input_current_state {
|
||||||
|
local state_file
|
||||||
|
|
||||||
|
mpg341cx_input_state_file
|
||||||
|
state_file="$MPG341CX_INPUT_SELECTED_STATE_FILE"
|
||||||
|
if [[ -r "$state_file" ]]; then
|
||||||
|
read -r MPG341CX_INPUT_CURRENT_TARGET < "$state_file"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function mpg341cx_input_write_state {
|
||||||
|
local current="$1"
|
||||||
|
local state_file state_dir
|
||||||
|
|
||||||
|
mpg341cx_input_state_file
|
||||||
|
state_file="$MPG341CX_INPUT_SELECTED_STATE_FILE"
|
||||||
|
state_dir="${state_file:h}"
|
||||||
|
|
||||||
|
mkdir -p "$state_dir" >/dev/null 2>&1 || return 0
|
||||||
|
print -r -- "$current" > "$state_file" 2>/dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
|
function mpg341cx_input {
|
||||||
|
local target="${1:-toggle}"
|
||||||
|
local display="${MPG341CX_INPUT_DDC_DISPLAY:-1}"
|
||||||
|
local backend value_hex value_dec value_m1ddc label current current_target
|
||||||
|
|
||||||
|
if [[ "$target" == "-h" || "$target" == "--help" ]]; then
|
||||||
|
mpg341cx_input_usage
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! mpg341cx_input_backend; then
|
||||||
|
mpg341cx_input_notify "No DDC command is available"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
backend="$MPG341CX_INPUT_SELECTED_BACKEND"
|
||||||
|
|
||||||
|
case "${target:l}" in
|
||||||
|
toggle)
|
||||||
|
mpg341cx_input_current "$backend" "$display"
|
||||||
|
current="$MPG341CX_INPUT_CURRENT"
|
||||||
|
mpg341cx_input_current_target "$backend" "$current"
|
||||||
|
current_target="$MPG341CX_INPUT_CURRENT_TARGET"
|
||||||
|
if [[ -z "$current_target" ]]; then
|
||||||
|
mpg341cx_input_current_state
|
||||||
|
current_target="$MPG341CX_INPUT_CURRENT_TARGET"
|
||||||
|
fi
|
||||||
|
case "${current_target:l}" in
|
||||||
|
dp)
|
||||||
|
target="usb-c"
|
||||||
|
;;
|
||||||
|
usb-c)
|
||||||
|
target="dp"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "mpg341cx_input: current input is '${current:-unknown}', defaulting to DisplayPort" >&2
|
||||||
|
target="dp"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "${target:l}" in
|
||||||
|
dp|displayport|display-port)
|
||||||
|
value_hex="0x10"
|
||||||
|
value_dec="16"
|
||||||
|
value_m1ddc="15"
|
||||||
|
label="DisplayPort"
|
||||||
|
target="dp"
|
||||||
|
;;
|
||||||
|
usb-c|usbc|type-c|typec)
|
||||||
|
value_hex="0x0f"
|
||||||
|
value_dec="15"
|
||||||
|
value_m1ddc="16"
|
||||||
|
label="USB-C"
|
||||||
|
target="usb-c"
|
||||||
|
;;
|
||||||
|
hdmi1|hdmi-1)
|
||||||
|
value_hex="0x11"
|
||||||
|
value_dec="17"
|
||||||
|
value_m1ddc="17"
|
||||||
|
label="HDMI 1"
|
||||||
|
target="hdmi1"
|
||||||
|
;;
|
||||||
|
hdmi2|hdmi-2)
|
||||||
|
value_hex="0x12"
|
||||||
|
value_dec="18"
|
||||||
|
value_m1ddc="18"
|
||||||
|
label="HDMI 2"
|
||||||
|
target="hdmi2"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
mpg341cx_input_usage >&2
|
||||||
|
return 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
mpg341cx_input_notify "Switching to $label"
|
||||||
|
|
||||||
|
case "$backend" in
|
||||||
|
ddcutil)
|
||||||
|
ddcutil --display "$display" --noverify setvcp 60 "$value_hex" || return $?
|
||||||
|
;;
|
||||||
|
ddcctl)
|
||||||
|
ddcctl -d "$display" -i "$value_dec" || return $?
|
||||||
|
;;
|
||||||
|
m1ddc)
|
||||||
|
m1ddc display "$display" set input "$value_m1ddc" || return $?
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
mpg341cx_input_write_state "$target"
|
||||||
|
}
|
||||||
|
|
||||||
|
mpg341cx_input "$@"
|
||||||
@@ -254,6 +254,10 @@
|
|||||||
homebrew = {
|
homebrew = {
|
||||||
enable = true;
|
enable = true;
|
||||||
taps = builtins.attrNames config.nix-homebrew.taps;
|
taps = builtins.attrNames config.nix-homebrew.taps;
|
||||||
|
brews = [
|
||||||
|
"ddcctl"
|
||||||
|
"m1ddc"
|
||||||
|
];
|
||||||
casks = [
|
casks = [
|
||||||
"codex-app"
|
"codex-app"
|
||||||
"ghostty"
|
"ghostty"
|
||||||
|
|||||||
Reference in New Issue
Block a user