pulseaudio: allow to configure the sink

When we have multiple sinks, this change allows to have all/some of them
available in i3pystatus and to identify which one is currently the
default. Also it allows to configure if we want that the hook
change_sink move all inputs to the new sink or not.
This commit is contained in:
Mehdi Abaakouk 2016-10-05 23:29:42 +02:00
parent 962f376f43
commit d1e8f6f1b7

View File

@ -21,14 +21,18 @@ class PulseAudio(Module, ColorRangeModule):
(the literal value for -infinity is `-`) (the literal value for -infinity is `-`)
* `{muted}` the value of one of the `muted` or `unmuted` settings * `{muted}` the value of one of the `muted` or `unmuted` settings
* `{volume_bar}` unicode bar showing volume * `{volume_bar}` unicode bar showing volume
* `{selected}` show the format_selected string if selected sink is the configured one
""" """
settings = ( settings = (
"format", "format",
("format_muted", "optional format string to use when muted"), ("format_muted", "optional format string to use when muted"),
("format_selected", "string used to mark this sink if selected"),
"muted", "unmuted", "muted", "unmuted",
"color_muted", "color_unmuted", "color_muted", "color_unmuted",
("step", "percentage to increment volume on scroll"), ("step", "percentage to increment volume on scroll"),
("sink", "sink name to use, None means pulseaudio default"),
("move_sink_inputs", "Move all sink inputs when we change the default sink"),
("bar_type", "type of volume bar. Allowed values are 'vertical' or 'horizontal'"), ("bar_type", "type of volume bar. Allowed values are 'vertical' or 'horizontal'"),
("multi_colors", "whether or not to change the color from " ("multi_colors", "whether or not to change the color from "
"'color_muted' to 'color_unmuted' based on volume percentage"), "'color_muted' to 'color_unmuted' based on volume percentage"),
@ -39,11 +43,15 @@ class PulseAudio(Module, ColorRangeModule):
unmuted = "" unmuted = ""
format = "♪: {volume}" format = "♪: {volume}"
format_muted = None format_muted = None
format_selected = " 🗸"
currently_muted = False currently_muted = False
has_amixer = False has_amixer = False
color_muted = "#FF0000" color_muted = "#FF0000"
color_unmuted = "#FFFFFF" color_unmuted = "#FFFFFF"
sink = None
move_sink_inputs = True
step = 5 step = 5
multi_colors = False multi_colors = False
bar_type = 'vertical' bar_type = 'vertical'
@ -83,13 +91,16 @@ class PulseAudio(Module, ColorRangeModule):
def request_update(self, context): def request_update(self, context):
"""Requests a sink info update (sink_info_cb is called)""" """Requests a sink info update (sink_info_cb is called)"""
pa_operation_unref(pa_context_get_sink_info_by_name( pa_operation_unref(pa_context_get_sink_info_by_name(
context, self.sink.encode(), self._sink_info_cb, None)) context, self.current_sink.encode(), self._sink_info_cb, None))
def success_cb(self, context, success, userdata): def success_cb(self, context, success, userdata):
pass pass
@property @property
def sink(self): def current_sink(self):
if self.sink is not None:
return self.sink
self.sinks = subprocess.check_output(['pactl', 'list', 'short', 'sinks'], self.sinks = subprocess.check_output(['pactl', 'list', 'short', 'sinks'],
universal_newlines=True).splitlines() universal_newlines=True).splitlines()
bestsink = None bestsink = None
@ -167,34 +178,47 @@ class PulseAudio(Module, ColorRangeModule):
else: else:
raise Exception("bar_type must be 'vertical' or 'horizontal'") raise Exception("bar_type must be 'vertical' or 'horizontal'")
selected = ""
dump = subprocess.check_output("pacmd dump".split(), universal_newlines=True)
for line in dump.split("\n"):
if line.startswith("set-default-sink"):
default_sink = line.split()[1]
if default_sink == self.current_sink:
selected = self.format_selected
self.output = { self.output = {
"color": color, "color": color,
"full_text": output_format.format( "full_text": output_format.format(
muted=muted, muted=muted,
volume=volume_percent, volume=volume_percent,
db=volume_db, db=volume_db,
volume_bar=volume_bar), volume_bar=volume_bar,
selected=selected),
} }
self.send_output() self.send_output()
def change_sink(self): def change_sink(self):
curr_sink = self.sink
sinks = list(s.split()[1] for s in self.sinks) sinks = list(s.split()[1] for s in self.sinks)
next_sink = (sinks.index(curr_sink) + 1) % len(sinks) if self.sink is None:
next_sink = sinks[(sinks.index(self.current_sink) + 1) %
len(sinks)]
else:
next_sink = self.current_sink
sink_inputs = subprocess.check_output("pacmd list-sink-inputs".split(), if self.move_sink_inputs:
universal_newlines=True) sink_inputs = subprocess.check_output("pacmd list-sink-inputs".split(),
for input_index in re.findall('index:\s+(\d+)', sink_inputs): universal_newlines=True)
command = "pacmd move-sink-input {} {}".format(input_index, sinks[next_sink]) for input_index in re.findall('index:\s+(\d+)', sink_inputs):
subprocess.call(command.split()) command = "pacmd move-sink-input {} {}".format(input_index, next_sink)
subprocess.call("pacmd set-default-sink {}".format(sinks[next_sink]).split()) subprocess.call(command.split())
subprocess.call("pacmd set-default-sink {}".format(next_sink).split())
def switch_mute(self): def switch_mute(self):
subprocess.call(['pactl', '--', 'set-sink-mute', self.sink, "toggle"]) subprocess.call(['pactl', '--', 'set-sink-mute', self.current_sink, "toggle"])
def increase_volume(self): def increase_volume(self):
subprocess.call(['pactl', '--', 'set-sink-volume', self.sink, "+%s%%" % self.step]) subprocess.call(['pactl', '--', 'set-sink-volume', self.current_sink, "+%s%%" % self.step])
def decrease_volume(self): def decrease_volume(self):
subprocess.call(['pactl', '--', 'set-sink-volume', self.sink, "-%s%%" % self.step]) subprocess.call(['pactl', '--', 'set-sink-volume', self.current_sink, "-%s%%" % self.step])