diff options
Diffstat (limited to 'pa.py')
-rw-r--r-- | pa.py | 101 |
1 files changed, 76 insertions, 25 deletions
@@ -1,10 +1,14 @@ from collections import namedtuple import pacmd -class Sink: - def __init__(self, pitem): +class SinkSource: + def __init__(self, pitem, kind_of_thing): assert type(pitem) == pacmd.Item self._i = pitem + self._kind_of_thing = kind_of_thing + + def kind(self): + return self._kind_of_thing def name(self): return self._i.ch["name"].value @@ -30,28 +34,57 @@ class Sink: def set_volume(self, vol): assert type(vol) == float or type(vol) == int vol = round(vol * _get_maxvol(self._i)) - pacmd.pacmd("set-sink-volume", str(self.index()), str(vol)) + pacmd.pacmd("set-{}-volume".format(self._kind_of_thing), + str(self.index()), str(vol)) def set_muted(self, yes): - pacmd.pacmd("set-sink-mute", str(self.index()), "true" if yes else "false") + pacmd.pacmd("set-{}-mute".format(self._kind_of_thing), + str(self.index()), "true" if yes else "false") def set_default(self): - pacmd.pacmd("set-default-sink", str(self.index())) + pacmd.pacmd("set-default-{}".format(self._kind_of_thing), + str(self.index())) + +class Sink(SinkSource): + def __init__(self, pitem): + super().__init__(pitem, "sink") -class SinkInput: +class Source(SinkSource): def __init__(self, pitem): + super().__init__(pitem, "source") + +class InputOutput: + def __init__(self, pitem, kind_of_thing, linked_kind): assert type(pitem) == pacmd.Item self._i = pitem + self._kind_of_thing = kind_of_thing + self._linked_kind = linked_kind + + # sink-input or source-output + def kind(self): + return self._kind_of_thing + + # sink or source + def linked_kind(self): + return self._linked_kind def name(self): try: name = self._i.ch["properties"].ch["media.name"].value - if "application.process.binary" in self._i.ch["properties"].ch: - name += " (" + self._i.ch["properties"].ch["application.process.binary"].value + ")" + # Append the first that is present, if any + for key in ["application.name", "application.process.binary"]: + if key in self._i.ch["properties"].ch: + name += " (" + self._i.ch["properties"].ch[key].value + ")" + break except Exception as e: return "???" return name + def linked_index(self): + return int(self._i.ch[self._linked_kind].value.split()[0]) + + # Don't know if this is ever true; it wouldn't make much sense to have a + # 'default' input or output. def default(self): return self._i.default @@ -61,9 +94,6 @@ class SinkInput: def driver(self): return self._i.ch["driver"].value - def sink(self): - return int(self._i.ch["sink"].value.split()[0]) - def muted(self): return _parse_muted(self._i) @@ -73,19 +103,35 @@ class SinkInput: def set_volume(self, vol): assert type(vol) == float or type(vol) == int vol = round(vol * _get_maxvol(self._i)) - pacmd.pacmd("set-sink-input-volume", str(self.index()), str(vol)) + pacmd.pacmd("set-{}-volume".format(self._kind_of_thing), str(self.index()), str(vol)) def set_muted(self, yes): - pacmd.pacmd("set-sink-input-mute", str(self.index()), "true" if yes else "false") + pacmd.pacmd("set-{}-mute".format(self._kind_of_thing), str(self.index()), "true" if yes else "false") - def move_to_sink(self, idx): + def move_to(self, idx): assert type(idx) == int - pacmd.pacmd("move-sink-input", str(self.index()), str(idx)) + pacmd.pacmd("move-{}".format(self._kind_of_thing), str(self.index()), str(idx)) + +class SinkInput(InputOutput): + def __init__(self, pitem): + super().__init__(pitem, "sink-input", "sink") + +class SourceOutput(InputOutput): + def __init__(self, pitem): + super().__init__(pitem, "source-output", "source") +# TODO: How should one really do this? This is just a collection of hacks that +# accidentally works for all my devices, but will probably fail the moment you +# try another. def _get_maxvol(item): - if "base volume" in item.ch: - return int(item.ch["base volume"].value.split("/")[0].strip()) + if "volume steps" in item.ch: + return int(item.ch["volume steps"].value.strip()) - 1 + elif "base volume" in item.ch: + num, perc = item.ch["base volume"].value.split("/")[0:2] + num = int(num.strip()) + perc = int(num.replace("%", "").strip()) + return num * (100 / perc) else: return 65536 @@ -100,14 +146,19 @@ def _parse_muted(item): elif item.ch["muted"].value == "no": return False else: assert False +def _list_things(pacmd_obj, section_name, klass): + assert len(pacmd_obj.sections) == 1 + assert pacmd_obj.sections[0].name == section_name + return [klass(item) for item in pacmd_obj.sections[0].items] + def list_sinks(): - res = pacmd.list_sinks() - assert len(res.sections) == 1 - assert res.sections[0].name == "sink" - return [Sink(item) for item in res.sections[0].items] + return _list_things(pacmd.list_sinks(), "sink", Sink) def list_sink_inputs(): - res = pacmd.list_sink_inputs() - assert len(res.sections) == 1 - assert res.sections[0].name == "input" - return [SinkInput(item) for item in res.sections[0].items] + return _list_things(pacmd.list_sink_inputs(), "input", SinkInput) + +def list_sources(): + return _list_things(pacmd.list_sources(), "source", Source) + +def list_source_outputs(): + return _list_things(pacmd.list_source_outputs(), "output", SourceOutput) |