aboutsummaryrefslogtreecommitdiff
path: root/pacmd.py
diff options
context:
space:
mode:
Diffstat (limited to 'pacmd.py')
-rw-r--r--pacmd.py146
1 files changed, 146 insertions, 0 deletions
diff --git a/pacmd.py b/pacmd.py
new file mode 100644
index 0000000..e9e019e
--- /dev/null
+++ b/pacmd.py
@@ -0,0 +1,146 @@
+import subprocess, re
+from collections import namedtuple
+
+class PacmdSection:
+ def __init__(self, name, items):
+ self.name = name # string
+ self.items = items # [PacmdItem]
+
+class PacmdItem:
+ def __init__(self, index, children):
+ self.index = index # int
+ self.children = children # {key: PacmdNode}
+
+class PacmdNode:
+ def __init__(self, value, children):
+ self.value = value # None | string | [string]
+ self.children = children # {key: PacmdNode}
+
+class Pacmd:
+ def __init__(self, full_output):
+ lines = full_output.decode("utf-8").split("\n")
+ self.infos = [] # [string]
+ self.sections = [] # [PacmdSection]
+
+ currsect = None
+ curritem = None
+ currpath = []
+
+ def close_curritem():
+ nonlocal curritem, currsect, currpath
+ if curritem:
+ currsect.items.append(curritem)
+ curritem = None
+ currpath = []
+
+ def close_currsect():
+ nonlocal self, currsect
+ if currsect:
+ close_curritem()
+ self.sections.append(currsect)
+
+ def q_is_key_value(ln):
+ return ln.find("=") != -1 or ln.find(": ") != -1
+
+ def q_get_key_value(ln):
+ if ln.find("=") != -1:
+ m = re.search(r"^\s*([^=]*?)\s*=\s*(.*)$", ln)
+ else:
+ m = re.search(r"^\s*([^:]*):\s*(.*)$", ln)
+ return m.group(1), m.group(2)
+
+ for line in lines:
+ line = line.rstrip()
+ if len(line) == 0:
+ continue
+
+ line = line.replace("\t", " ")
+ m = re.match(r"^( *(\* )?)([^ ].*)", line)
+ is_default = m.group(2) is not None # TODO use is_default
+ indent = len(m.group(1))
+ line = m.group(3)
+
+ # print(currpath)
+ # print(indent, line)
+
+ if indent == 0:
+ if line[0].isdigit():
+ close_currsect()
+
+ name = re.search(r" ([^ ]*)\(s\)", line).group(1)
+ currsect = PacmdSection(name, [])
+ else:
+ self.infos.append(line)
+
+ elif indent == 4:
+ close_curritem()
+
+ index = re.search(r"index: ([0-9]*)$", line).group(1)
+ curritem = PacmdItem(int(index), {})
+
+ elif indent >= 8:
+ assert curritem != None
+
+ is_aligned = indent % 8 == 0
+ indent_depth = (indent + 7) // 8 - 1
+
+ if is_aligned and indent_depth < len(currpath):
+ currpath = currpath[:indent_depth]
+
+ parentval, thisval = None, curritem
+ for k in currpath:
+ parentval, thisval = thisval, thisval.children[k]
+
+ if q_is_key_value(line):
+ key, value = q_get_key_value(line)
+ thisval.children[key] = PacmdNode(value, {})
+ currpath.append(key)
+
+ elif re.search(r":$", line) is not None:
+ key = line[:-1]
+ thisval.children[key] = PacmdNode(None, {})
+ currpath.append(key)
+
+ elif indent_depth >= len(currpath):
+ if type(thisval.value) != list:
+ thisval.value = [thisval.value]
+ thisval.value.append(line)
+
+ else:
+ print("line = " + line)
+ assert False
+
+ else:
+ print("indent = " + str(indent))
+ assert False
+
+ close_currsect()
+
+def pacmd(*args):
+ return Pacmd(subprocess.check_output(["pacmd"] + list(args)))
+
+def list_all():
+ return pacmd("list")
+
+def list_sinks():
+ return pacmd("list-sinks")
+
+def list_sink_inputs():
+ return pacmd("list-sink-inputs")
+
+
+def _make_indent(n):
+ return " " * n
+
+def dump_section(sect):
+ print("Section " + sect.name + ":")
+ for item in sect.items:
+ print(_make_indent(1) + "Item " + str(item.index) + ":")
+ for key, node in item.children.items():
+ dump_node(node, key, 2);
+
+def dump_node(node, key, indent):
+ print(_make_indent(indent) + key + ":" +
+ ("" if node.value is None else " " + str(node.value)))
+ for k2, n2 in node.children.items():
+ dump_node(n2, k2, indent + 1)