mmswitch

minimal multimedia switch
git clone git://git.2f30.org/mmswitch.git
Log | Files | Refs

commit 6476b76f59296025ec3429d3453553b3017919d4
Author: sin <sin@2f30.org>
Date:   Thu Jun 20 13:16:39 +0100

Initial commit

Diffstat:
mmswitch-monitor | 194+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
mmswitch-sound | 111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 305 insertions(+), 0 deletions(-)
diff --git a/mmswitch-monitor b/mmswitch-monitor @@ -0,0 +1,194 @@ +#!/bin/sh + +DMENU_ARGS='-nb #151515 -nf #787878 -sb #151515 -sf #a78edb -fn -*-*-medium-r-normal-*-*-*-*-*-*-80-*-*' + +usage() { + echo "Usage $(basename $0) [options] [MONITOR ..]" + echo + echo "Options:" + echo " -h, --help Show this help menu" + echo " -l, --list-monitors List connected monitors" + echo " -e Extent all monitors (ignores [MONITOR ..] list)" + echo " -d Duplicate all monitors (ignores [MONITOR ..] list)" + echo " --dmenu Use dmenu" + echo + echo "If a connected monitor is not listed in the arguments, then it will switched off." + echo + echo "Monitor syntax by example:" + echo " MONITOR1 - Use MONITOR1 only" + echo " MONITOR1 MONITOR2 - MONITOR1 is at the left of MONITOR2" + echo " MONITOR2 MONITOR1 - MONITOR2 is at the left of MONITOR1" + echo " MONITOR2=MONITOR1 - MONITOR2 is a duplicate of MONITOR1" + echo " MONITOR2=MONITOR3=MONITOR1 - MONITOR2 and MONITOR3 are duplicates of MONITOR1" + echo " MONITOR2 MONITOR3=MONITOR1 - MONITOR2 is at the left of MONITOR1" + echo " and MONITOR3 is a duplicate of MONITOR1" + echo " MONITOR1 MONITOR2 MONITOR3 - MONITOR1 is at the left of MONITOR2" + echo " and MONITOR3 is at the right of MONITOR2" + echo + echo "Example:" + echo " $(basename $0) LVDS-0 DP-0" + echo " $(basename $0) -e" + echo " $(basename $0) -d" +} + +die() { + echo "$(basename $0): Error: $1" >&2 + exit 1 +} + +list_monitors() { + xrandr -q | grep ' connected' | awk '{print $1}' +} + +list_forced_unplugged() { + xrandr -q | grep ' 0mm x 0mm' | awk '{print $1}' +} + +is_connected() { + list_monitors | grep -E "^$1\$" > /dev/null 2>&1 +} + +is_monitor_in() { + local mon="$1" + local x + local y + shift + + for x in "$@"; do + for y in $(echo $x | tr '=' ' '); do + [ "$mon" = "$y" ] && return 0 + done + done + + return 1 +} + +last_arg() { + local last + local x + + for x in "$@"; do + last="$x" + done + + echo $last +} + +ARGS=$(getopt -o lhed -l "list-monitors,help,dmenu" -n $(basename $0) -- "$@") +[ $? -ne 0 ] && exit 1 +eval set -- "$ARGS" + +while :; do + case "$1" in + -h|--help) + usage + exit 1 + ;; + -l|--list-monitors) + list_monitors + exit 0 + ;; + -e) + ARGS= + for x in $(list_monitors); do + ARGS="${ARGS} ${x}" + done + break + ;; + -d) + ARGS= + for x in $(list_monitors); do + [ -n "$ARGS" ] && ARGS="${ARGS}=" + ARGS="${ARGS}${x}" + done + break + ;; + --dmenu) + SELECT=$({ + echo Extend monitors + echo Duplicate monitors + list_monitors + } | dmenu -i -p 'Choose monitor:' $DMENU_ARGS) + + [ -z "$SELECT" ] && exit 0 + + ARGS= + case "$SELECT" in + "Extend monitors") + for x in $(list_monitors); do + ARGS="${ARGS} ${x}" + done + ;; + "Duplicate monitors") + for x in $(list_monitors); do + [ -n "$ARGS" ] && ARGS="${ARGS}=" + ARGS="${ARGS}${x}" + done + ;; + *) + ARGS="$SELECT" + ;; + esac + break + ;; + --) + shift + ARGS="$@" + break + ;; + esac +done + +if [ -z "$ARGS" ]; then + usage + exit 1 +fi + +ARGS=$(echo $ARGS | tr '[a-z]' '[A-Z]') + +for x in $ARGS; do + for y in $(echo $x | tr '=' ' '); do + is_connected $y || die "Monitor \`$y' is not in the connected list. Use -l argument to see the list." + done +done + +ALL_OFF=1 + +for x in $(list_monitors); do + is_monitor_in "$x" $ARGS && { + ALL_OFF=0 + continue + } + OPT="${OPT} --output $x --off" +done + +[ $ALL_OFF -eq 1 ] && die "You can not switch off all the monitors" + +for x in $(list_forced_unplugged); do + OPT="${OPT} --output $x --off" +done + +for x in $ARGS; do + k=$(echo $x | tr '=' ' ') + if [ "$k" != "$x" ]; then + SAME_AS=$(last_arg $k) + OPT="${OPT} --output $SAME_AS --auto" + if [ -n "$PREV" ]; then + OPT="${OPT} --right-of ${PREV}" + fi + for y in $k; do + [ "$SAME_AS" = "$y" ] && continue + OPT="${OPT} --output $y --auto --same-as $SAME_AS" + done + PREV=$SAME_AS + continue + fi + + OPT="${OPT} --output ${x} --auto" + if [ -n "$PREV" ]; then + OPT="${OPT} --right-of ${PREV}" + fi + PREV="$x" +done + +xrandr $OPT diff --git a/mmswitch-sound b/mmswitch-sound @@ -0,0 +1,111 @@ +#!/bin/sh + +DMENU_ARGS='-nb #151515 -nf #787878 -sb #151515 -sf #a78edb -fn -*-*-medium-r-normal-*-*-*-*-*-*-80-*-*' + +die() { + echo "$(basename $0): Error: $1" >&2 + exit 1 +} + +list_sinks() { + pacmd list-sinks | grep -E "index: |name: |device.description = " | paste - - - | \ + tr '*' ' ' | tr '<>' '"' | sed 's/device.description =/description:/' | \ + sed -e 's/[ \t][ \t]*/ /g' | sed -e 's/^ //' +} + +list_sink_inputs() { + pacmd list-sink-inputs | grep 'index: ' | awk '{print $2}' +} + +get_index_from_desc() { + list_sinks | grep "description: \"$1\"" | awk '{print $2}' +} + +get_index_from_name() { + list_sinks | grep " name: \"$1\" " | awk '{print $2}' +} + +get_desc_from_index() { + list_sinks | grep -E "^index: $1 " | sed 's/.* description: \"\(.*\)\"$/\1/' +} + +get_name_from_index() { + list_sinks | grep -E "^index: $1 " | sed 's/.* name: \"\(.*\)\" .*$/\1/' +} + +set_sink_from_index() { + local x + pacmd set-default-sink $1 > /dev/null 2>&1 + for x in $(list_sink_inputs); do + pacmd move-sink-input $x $1 > /dev/null 2>&1 + done +} + +usage() { + echo "Usage $(basename $0) [options] index:NUMBER | name:NAME | desc:DESCRIPTION" + echo + echo "Options:" + echo " -h, --help Show this help menu" + echo " -l, --list-cards List sound cards" + echo " --dmenu Use dmenu" + echo + echo "Examples:" + echo " $(basename $0) index:0" + echo " $(basename $0) name:$(get_name_from_index 0)" + echo " $(basename $0) desc:\"$(get_desc_from_index 0)\"" +} + +ARGS=$(getopt -o lh -l "list-cards,dmenu,help" -n $(basename $0) -- "$@") +[ $? -ne 0 ] && exit 1 +eval set -- "$ARGS" + +while :; do + case "$1" in + -h|--help) + usage + exit 1 + ;; + -l|--list-cards) + list_sinks + exit 0 + ;; + --dmenu) + SELECT=$(list_sinks | sed 's/.* description: \"\(.*\)\"$/\1/' | \ + dmenu -i -p 'Choose sound card:' $DMENU_ARGS) + [ -z "$SELECT" ] && exit 0 + ARG=desc:"$SELECT" + break + ;; + --) + shift + ARG="$@" + break + ;; + esac +done + +if [ -z "$ARG" ]; then + usage + exit 1 +fi + +case "${ARG%%:*}" in + index) + [ $(list_sinks | grep -E -c "^index: ${ARG#*:} ") -eq 0 ] && \ + die "Sound card with index \`${ARG#*:}' does not exist." + set_sink_from_index "${ARG#*:}" + ;; + name) + INDEX=$(get_index_from_name "${ARG#*:}") + [ -z "$INDEX" ] && die "Sound card with name \`${ARG#*:}' does not exist." + set_sink_from_index $INDEX + ;; + desc) + INDEX=$(get_index_from_desc "${ARG#*:}") + [ -z "$INDEX" ] && die "Sound card with description \`${ARG#*:}' does not exist." + set_sink_from_index $INDEX + ;; + *) + die "You must specify if \`${ARG#*:}' is an index, a name or a description. See --help." + ;; +esac