From 938c3ac56ee51ab2822f284e34519cd46752eb2a Mon Sep 17 00:00:00 2001 From: Charles Daniels Date: Sat, 17 Nov 2018 17:54:58 -0500 Subject: [PATCH] added support for changing mixer dev Also switch all tabs to use grids for layout --- CHANGELOG | 8 ++++++- README.md | 6 +++-- gmixerctl/constants.py | 2 ++ gmixerctl/gui.py | 52 ++++++++++++++++++++++++++++++++---------- gmixerctl/mixerctl.py | 8 +++++-- 5 files changed, 59 insertions(+), 17 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 144ee39..4687317 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,10 @@ 0.1.0 - * Add support for basic configuration of sndiod, mainly with a focus + * Added support for basic configuration of sndiod, mainly with a focus on the ability to switch audio devices. + + * Switched to using tkinter grids, rather than packed frames for layout, + leading to a more visually appealing widget alignment. + + * Added support for switching mixer devices via the "basic" tab by + re-starting the application in-place. diff --git a/README.md b/README.md index 23ab427..7e73f09 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,10 @@ Contributions are more than welcome. If there is a feature you would like added to gmixerctl, please feel free to open a pull request. In particular, I would appreciate help implementing the following features: -* Changing the mixer device at run time (this may be a Tk limitation, but I'm - not experienced enough with Tk at the moment) +* ~~Changing the mixer device at run time (this may be a Tk limitation, but I'm + not experienced enough with Tk at the moment)~~ + + * Support added in 0.1.0 * ~~Configuring `sndiod` flags (i.e. a menu for running `rcctl set sndiod flags -f rsnd/X ; rcctl restart sndiod`)~~ diff --git a/gmixerctl/constants.py b/gmixerctl/constants.py index fabbabb..ec13f77 100644 --- a/gmixerctl/constants.py +++ b/gmixerctl/constants.py @@ -8,6 +8,8 @@ log_level = logging.DEBUG +mixer_device = "/dev/mixer" + # control names to appear in the basic tab basic_controls = [ "outputs.master", diff --git a/gmixerctl/gui.py b/gmixerctl/gui.py index 6ea784a..8cb5049 100644 --- a/gmixerctl/gui.py +++ b/gmixerctl/gui.py @@ -4,6 +4,7 @@ import tkinter.messagebox import time import subprocess +import glob from . import mixerctl from . import util @@ -82,7 +83,17 @@ def on_press (this): "\n\nerror was:\n\n{}".format(e) ) +class SetMixerDevice: + def __init__(this, parent): + this.parent = parent + + def __call__(this, val): + # implement callback for setting mixer device + constants.mixer_device = val + logging.debug("updated mixer device to {}".format(val)) + this.parent.destroy() + main() class MultiSelect(tkinter.Frame): # https://stackoverflow.com/a/34550169 @@ -126,7 +137,7 @@ def update(this): mixerctl.set_value(this.name, ",".join( [x for x in this.choices if this.choices[x].get() == 1])) -def render_control(parent, control, tabs, tkvars): +def render_control(parent, control, tabs, tkvars, row): name = control["name"] @@ -136,7 +147,7 @@ def render_control(parent, control, tabs, tkvars): parent, text = name, width = constants.label_width) - text_widget.pack(side=tkinter.LEFT) + text_widget.grid(row = row, column = 0) # create a new callback object - we need to use the update_value # class so that mixerctl.set_value() knows what control we want @@ -160,7 +171,7 @@ def render_control(parent, control, tabs, tkvars): command = callback, ) # scale.config(width = constants.control_width) - scale.pack(side=tkinter.RIGHT) + scale.grid(row = row, column = 1) elif control["type"] == "enum": @@ -178,7 +189,7 @@ def render_control(parent, control, tabs, tkvars): command = callback, ) menu.config(width = constants.control_width) - menu.pack(side=tkinter.RIGHT) + menu.grid(row = row, column = 1) elif control["type"] == "set": @@ -190,14 +201,14 @@ def render_control(parent, control, tabs, tkvars): control["possible"], tkvars[name].choices ) - menu.pack(side=tkinter.RIGHT) + menu.grid(row = row, column = 1) else: menu = MultiSelect( parent, name, control["possible"], ) - menu.pack(side=tkinter.RIGHT) + menu.grid(row = row, column = 1) tkvars[name] = menu @@ -222,6 +233,7 @@ def main(): tkvars = {} # custom-build "basic" tab + row_counter = 0 for name in controls: # only display the controls we have configured @@ -237,9 +249,25 @@ def main(): nb.add(tabs[tab_name], text=tab_name) # create the frame for this control - frame = ttk.Frame(tabs[tab_name]) - render_control(frame, control, tabs, tkvars) - frame.pack() + render_control(tabs[tab_name], control, tabs, tkvars, row_counter) + row_counter += 1 + + # add mixer device selector to basic tab + dev_selector_label = tkinter.Label(tabs[tab_name], + text = "select mixer device") + dev_selector_label.grid(row = row_counter, column = 0) + + callback = SetMixerDevice(root) + available_device = [] + dev_selector_var = tkinter.StringVar() + dev_selector_var.set(constants.mixer_device) + mixer_dev_selector = tkinter.OptionMenu( + tabs[tab_name], + dev_selector_var, + *list(glob.glob("/dev/mixer*")), + command = callback, + ) + mixer_dev_selector.grid(row = row_counter, column = 1) # sndiod control tab @@ -286,6 +314,7 @@ def main(): # automatically generate the rest of the tabs + row_counter = 0 for name in controls: control = controls[name] @@ -296,9 +325,8 @@ def main(): nb.add(tabs[tab_name], text=tab_name) # create the frame for this control - frame = ttk.Frame(tabs[tab_name]) - render_control(frame, control, tabs, tkvars) - frame.pack() + render_control(tabs[tab_name], control, tabs, tkvars, row_counter) + row_counter += 1 # add about tab about = ttk.Frame(nb) diff --git a/gmixerctl/mixerctl.py b/gmixerctl/mixerctl.py index b62e952..506aa01 100644 --- a/gmixerctl/mixerctl.py +++ b/gmixerctl/mixerctl.py @@ -3,6 +3,7 @@ import subprocess from . import util +from . import constants def parse_line(line): """parse_line @@ -57,7 +58,8 @@ def get_state(): Get the current mixer state. """ - raw = subprocess.check_output(["mixerctl", "-v"], stderr=subprocess.STDOUT) + raw = subprocess.check_output(["mixerctl", "-f", constants.mixer_device, + "-v"], stderr=subprocess.STDOUT) raw = raw.decode() control = {} @@ -79,6 +81,8 @@ def set_value(control, value): :param value: """ logging.debug("setting {} = {}".format(control, value)) - raw = subprocess.check_output(["mixerctl", "{}={}".format(control, value)], + raw = subprocess.check_output( + ["mixerctl", "-f", constants.mixer_device, + "{}={}".format(control, value)], stderr=subprocess.STDOUT) logging.debug("mixerctl says {}".format(raw))