# Written by Bart Nagel https://bartnagel.ca/ #!/usr/bin/env python import optparse import re import subprocess import sys class Volume: def __init__(self, options): self.options = options self.state = None self.modified = False def get_state(self): """Return a string output from pacmd list-sinks """ if self.state is None or self.modified: self.state = subprocess.check_output(["pacmd", "list-sinks"]) return self.state def get_default_sink(self): """Return the index of the default sink """ match = re.search(r"^\s*\*\s*index:\s*(\d+)$", self.get_state(), flags=re.MULTILINE) if not match: raise Exception("couldn't find default sink in pacmd's output: %s" % self.get_state()) return int(match.group(1)) def get_volume(self): """Return the volume (integer 0 to maximum volume, which might be 65000 or whatever) """ correctSink = False for line in self.get_state().split("\n"): if not correctSink: if re.search(r"^[\s*]*index: %d$" % self.options.sink, line): correctSink = True continue match = re.search(r"^\s*volume:\s+front-left:\s+(\d+)", line) if match: return int(match.group(1)) raise Exception("couldn't find volume in pacmd's output: %s" % self.get_state()) def get_mute(self): """Return true if the sink is muted """ return bool(re.search(r"^\s*muted: yes$", self.get_state(), flags=re.MULTILINE)) def get_max_volume(self): """Return the maximum volume (integer, 65000 or whatever) """ match = re.search(r"^\s*volume steps:\s+(\d+)$", self.get_state(), flags=re.MULTILINE) if not match: raise Exception("couldn't find volume steps in pacmd's output: %s" % self.get_state()) return int(match.group(1)) def set_mute(self, muted=True): """Switch on mute, or switch it off if passed False """ subprocess.call(["pactl", "set-sink-mute", str(self.options.sink), str(int(muted))]) self.modified = True def set_volume(self, volume): """Set the volume (integer 0 to maximum volume, which might be 65000 or whatever). Silently caps to 0 or maximum volume if given an argument out of range. """ if volume < 0: volume = 0 else: volume = min(volume, self.get_max_volume()) subprocess.call(["pactl", "set-sink-volume", str(self.options.sink), str(volume)]) self.modified = True def vol_string(self): """Return a string describing the current volume """ vol = self.get_volume() maxvol = self.get_max_volume() return "%d/%d (%d%%)" % (vol, maxvol, int(100 * float(vol) / maxvol)) def mute_string(self): """Return a string describing the current mute state """ if self.get_mute(): return "yes" return "no" if __name__ == "__main__": optionparser = optparse.OptionParser(usage="%prog [options] [<volume>[%][+|-]]") optionparser.add_option("-q", "--quiet", action="store_true", help="Don't print the new volume and mute status") optionparser.add_option("-s", "--sink", type="int", default=-1, help="Set the sink number to control (default: %default, which means use Pulse default)") optionparser.add_option("--toggle", action="store_true", help="Toggle mute status") optionparser.add_option("--unmute", action="store_true", help="Unmute") optionparser.add_option("--mute", action="store_true", help="Mute") optionparser.add_option("--muted", action="store_true", help="Exit with success status (0) if muted, 1 if not muted, do nothing else") (options, args) = optionparser.parse_args() if len(args) > 1: optionparser.error("Expected either no non-option arguments or one non-option argument") if options.unmute and options.mute: optionparser.error("--unmute and --mute connot be used at the same time") volume = Volume(options) if options.sink == -1: options.sink = volume.get_default_sink() if options.muted: sys.exit(0 if volume.get_mute() else 1) if options.toggle: volume.set_mute(not volume.get_mute()) elif options.mute: volume.set_mute() elif options.unmute: volume.set_mute(False) if len(args) == 1: match = re.search(r"^(\d+)(%?)([+-]?)$", args[0]) if not match: optionparser.error("Unrecognized argument") amount = int(match.group(1)) percentage = match.group(2) == r"%" relative = len(match.group(3)) > 0 increment = match.group(3) == "+" if percentage: amount = int(round(float(volume.get_max_volume()) * amount / 100)) if relative: base = volume.get_volume() if increment: amount += base else: amount = base - amount volume.set_volume(amount) if not options.quiet: print "%s (muted: %s)" % (volume.vol_string(), volume.mute_string())
(Jan-23-2018, 01:53 AM)Larz60+ Wrote: post the code so someone can determine if they want to answer yes.
But if there's a lot of it, better to put on gothub and post a link.
I found the problem.
I forgot to precede the code with ./.
Is that the only way to run python code?