#!/usr/bin/python
# pa_switch_sinks.py - (c) scuq 2011
# v0.1
# switches pulse audio sinks for xbmc
# I used it to switch between analog sound output with
# my usb creative xfi, the hdmi audio of my nvidia 430
# and a simultaneous output to both
# i've tested this with ubuntu (11.10)
##
## /etc/pulse/default.pa:
##
## load-module module-alsa-sink device=surround51:CARD=S51,DEV=0 sink_name=xfi
## load-module module-alsa-sink device=hdmi:CARD=NVidia,DEV=0 sink_name=hdmi
## load-module module-combine sink_name=xfi_and_hdmi slaves=xfi,hdmi adjust_time=3
##
#
## xbmc-keybinding: ~/.xbmc/userdata/keymaps/keyboard.xml
##
##
##
##XBMC.RunScript(special://home/scripts/pa_switch_sinks.py,-shortcut)
import re
from subprocess import Popen, PIPE, STDOUT
import sys
import logging
from logging.handlers import SysLogHandler
logger = logging.getLogger('pa_switch_sinks.py')
logger.setLevel(logging.INFO)
syslog = SysLogHandler(address='/dev/log')
formatter = logging.Formatter('%(name)s: %(levelname)s %(message)s')
syslog.setFormatter(formatter)
logger.addHandler(syslog)
# list of sinks (see example at the top)
sinks=["xfi", "hdmi", "xfi_and_hdmi"]
sinks_count = len(sinks)-1
# trim function
def retrim(inputstr):
inputstr = re.sub("^[^\w]+","",inputstr)
inputstr = re.sub("[^\w]+$","",inputstr)
inputstr = re.sub(" +"," ",inputstr)
return inputstr
# simple wrapper for Popen
def execute(command):
p = Popen(command, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
stdOut=re.sub('\\n+','\\n',str(p.stdout.read().decode("utf-8"))).split("\n")
stdErr=str(p.stderr.read()).split("\n")
return stdOut, stdErr
# get the current default sink
current_default_sink_out, current_default_sink_err = execute('pactl stat | grep "Default Sink" | sed s\'/Default Sink: //\'')
current_default_sink = current_default_sink_out[0]
# get a list of pulseaudio clients
current_clients_out, current_clients_err = execute('pactl list clients')
# "parse" the client list and try to find xbmc
xbmc_pulse_client_num=0
last_found_client_num=0
for line in current_clients_out:
if line.startswith("Client #"):
last_found_client_num=retrim(line.replace("Client #",""))
if line.count("xbmc") > 0:
xbmc_pulse_client_num=last_found_client_num
# determine next sink from the sink list
next_sink=""
next_sink_index=0
print sinks.index(current_default_sink)
print sinks_count
if sinks.index(current_default_sink) != sinks_count:
next_sink_index=sinks.index(current_default_sink)+1
next_sink=sinks[next_sink_index]
logger.info(current_default_sink+"->"+next_sink)
# set the new default sink
std, err = execute('pacmd set-default-sink '+next_sink)
# move the xbmc client to the new default sink
if xbmc_pulse_client_num != 0:
xbmc_sink_change_out, xbmc_sink_change_err = execute('pactl move-sink-input '+xbmc_pulse_client_num+' '+next_sink)