From bdfed7136ac6bf03f828a6421ee9a1ea17cd512e Mon Sep 17 00:00:00 2001 From: facetoe Date: Mon, 6 Jun 2016 15:43:15 +0800 Subject: [PATCH 1/2] Support changing sinks on the fly. On double click, move all sink inputs to the next available sink and set as default. --- i3pystatus/pulseaudio/__init__.py | 38 +++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/i3pystatus/pulseaudio/__init__.py b/i3pystatus/pulseaudio/__init__.py index 3fb22f5..fffca7b 100644 --- a/i3pystatus/pulseaudio/__init__.py +++ b/i3pystatus/pulseaudio/__init__.py @@ -1,13 +1,11 @@ -import os -import shutil +import re +import subprocess + +from i3pystatus import Module from i3pystatus.core.color import ColorRangeModule from i3pystatus.core.util import make_vertical_bar, make_bar from .pulse import * -from i3pystatus.core.command import execute -from i3pystatus import Module -import subprocess - class PulseAudio(Module, ColorRangeModule): """ @@ -52,6 +50,7 @@ class PulseAudio(Module, ColorRangeModule): vertical_bar_width = 2 on_rightclick = "switch_mute" + on_doubleleftclick = "change_sink" on_leftclick = "pavucontrol" on_upscroll = "increase_volume" on_downscroll = "decrease_volume" @@ -79,27 +78,30 @@ class PulseAudio(Module, ColorRangeModule): pa_threaded_mainloop_start(_mainloop) self.colors = self.get_hex_color_range(self.color_muted, self.color_unmuted, 100) + self.sinks = [] def request_update(self, context): """Requests a sink info update (sink_info_cb is called)""" pa_operation_unref(pa_context_get_sink_info_by_name( - context, self.sink, self._sink_info_cb, None)) + context, self.sink.encode(), self._sink_info_cb, None)) def success_cb(self, context, success, userdata): pass @property def sink(self): - sinks = subprocess.Popen(['pactl', 'list', 'short', 'sinks'], stdout=subprocess.PIPE).stdout.read() + self.sinks = subprocess.Popen(['pactl', 'list', 'short', 'sinks'], + stdout=subprocess.PIPE, + universal_newlines=True).stdout.read().splitlines() bestsink = None - state = b'DEFAULT' - for sink in sinks.splitlines(): + state = 'DEFAULT' + for sink in self.sinks: attribs = sink.split() sink_state = attribs[-1] - if sink_state == b'RUNNING': + if sink_state == 'RUNNING': bestsink = attribs[1] state = 'RUNNING' - elif sink_state in (b'IDLE', b'SUSPENDED') and state == b'DEFAULT': + elif sink_state in ('IDLE', 'SUSPENDED') and state == 'DEFAULT': bestsink = attribs[1] return bestsink @@ -175,6 +177,18 @@ class PulseAudio(Module, ColorRangeModule): volume_bar=volume_bar), } + def change_sink(self): + sink_inputs = subprocess.Popen("pacmd list-sink-inputs".split(), + stdout=subprocess.PIPE, + universal_newlines=True).stdout.read() + curr_sink = self.sink + sinks = list(s.split()[1] for s in self.sinks) + next_sink = (sinks.index(curr_sink) + 1) % len(sinks) + subprocess.Popen("pacmd set-default-sink {}".format(next_sink).split()) + for input_index in re.findall('index:\s+(\d+)', sink_inputs): + subprocess.Popen("pacmd move-sink-input {} {}".format(input_index, next_sink).split(), + stdout=subprocess.PIPE) + def switch_mute(self): subprocess.Popen(['pactl', 'set-sink-mute', self.sink, "toggle"]) From 8140b3b73cda48ec87df8113bf5e32108a579b3e Mon Sep 17 00:00:00 2001 From: facetoe Date: Tue, 7 Jun 2016 16:24:04 +0800 Subject: [PATCH 2/2] Use sink name not index. --- i3pystatus/pulseaudio/__init__.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/i3pystatus/pulseaudio/__init__.py b/i3pystatus/pulseaudio/__init__.py index fffca7b..ad97b7e 100644 --- a/i3pystatus/pulseaudio/__init__.py +++ b/i3pystatus/pulseaudio/__init__.py @@ -178,16 +178,18 @@ class PulseAudio(Module, ColorRangeModule): } def change_sink(self): - sink_inputs = subprocess.Popen("pacmd list-sink-inputs".split(), - stdout=subprocess.PIPE, - universal_newlines=True).stdout.read() curr_sink = self.sink sinks = list(s.split()[1] for s in self.sinks) next_sink = (sinks.index(curr_sink) + 1) % len(sinks) - subprocess.Popen("pacmd set-default-sink {}".format(next_sink).split()) + + sink_inputs = subprocess.Popen("pacmd list-sink-inputs".split(), + stdout=subprocess.PIPE, + universal_newlines=True).stdout.read() for input_index in re.findall('index:\s+(\d+)', sink_inputs): - subprocess.Popen("pacmd move-sink-input {} {}".format(input_index, next_sink).split(), + command = "pacmd move-sink-input {} {}".format(input_index, sinks[next_sink]) + subprocess.Popen(command.split(), stdout=subprocess.PIPE) + subprocess.Popen("pacmd set-default-sink {}".format(sinks[next_sink]).split()) def switch_mute(self): subprocess.Popen(['pactl', 'set-sink-mute', self.sink, "toggle"])