From 7581078bbaed046604f3d40c3143e013f2a5b1d4 Mon Sep 17 00:00:00 2001 From: Daniel Weschke Date: Wed, 7 Apr 2021 14:12:50 +0200 Subject: [PATCH] change volume button style, volume status with mute and toggle button and move button logic to button class --- controldeck.py | 162 +++++++++++++++++++++++++++---------------------- 1 file changed, 89 insertions(+), 73 deletions(-) diff --git a/controldeck.py b/controldeck.py index 24a4d08..bafd69f 100644 --- a/controldeck.py +++ b/controldeck.py @@ -20,20 +20,20 @@ def process(args, output=True): print(f"{e} failed!") def volume(name): - result = process(f'pamixer --get-volume --sink "{name}"') + result = process(f'pamixer --get-volume-human --sink "{name}"') if search("The sink doesn't exit", result): result = "--" elif search("pamixer: command not found", result) is not None: n = process(r"pactl list sinks short | awk '{print $2}'").split() v = process(r"pactl list sinks | grep '^[[:space:]]Volume:' | sed -e 's,.* \([0-9][0-9]*\)%.*,\1,'").split() if name in n: - result = v[n.index(name)] + result = v[n.index(name)] + '%' else: result = '--' return result def volume_decrease(name): - result = process(f'pamixer --get-volume --sink "{name}" --decrease 5') + result = process(f'pamixer --get-volume-human --sink "{name}" --decrease 5') if search("pamixer: command not found", result) is not None: process(f'pactl set-sink-volume "{name}" -5%') #process(f'pactl set-sink-volume "{name}" -5db') @@ -41,13 +41,20 @@ def volume_decrease(name): return result def volume_increase(name): - result = process(f'pamixer --get-volume --sink "{name}" --increase 5') + result = process(f'pamixer --get-volume-human --sink "{name}" --increase 5') if search("pamixer: command not found", result) is not None: process(f'pactl set-sink-volume "{name}" +5%') #process(f'pactl set-sink-volume "{name}" +5db') result = volume(name) return result +def volume_mute(name): + result = process(f'pamixer --get-volume-human --sink "{name}" --toggle-mute') + if search("pamixer: command not found", result) is not None: + process(f'pactl set-sink-mute "{name}" toggle') + result = volume(name) + return result + def config_load(): config = ConfigParser(strict=False) config_file = "controldeck.conf" @@ -64,29 +71,67 @@ def config_load(): return config class Button(Div): + btype = None command = None - empty = None + color_bg = '' + color_fg = '' + icon = '' + icon_image = '' def __init__(self, **kwargs): super().__init__(**kwargs) - if self.empty: + #print(dir(self)) + if self.btype == 'empty': self.classes = "w-20 h-20 m-2 p-1 flex select-none" + self.text = '' + else: self.classes = "bg-gray-800 hover:bg-gray-700 text-gray-500 w-20 h-20 m-2 p-1 rounded-lg font-bold flex items-center text-center justify-center select-none" - if self.command is not None: - def click(self, msg): - print(self.command) - # string works only with shell - if isinstance(self.command, (list)): - # e.g.: [['pkill', 'ArdourGUI'], ['systemctl', '--user', 'restart', 'pipewire', 'pipewire-pulse'], ['ardour6', '-n', 'productive-pipewire']] - if isinstance(self.command[0], (list)): - [process(i, False) for i in self.command] + + self.style = f"background-color:{self.color_bg};" if ishexcolor(self.color_bg) else '' + self.style += f"color:{self.color_fg};" if ishexcolor(self.color_fg) else '' + + if self.command is not None: + def click(self, msg): + print(self.command) + # string works only with shell + if isinstance(self.command, (list)): + # e.g.: [['pkill', 'ArdourGUI'], ['systemctl', '--user', 'restart', 'pipewire', 'pipewire-pulse'], ['ardour6', '-n', 'productive-pipewire']] + if isinstance(self.command[0], (list)): + [process(i, False) for i in self.command] + else: + # e.g.: ['pkill', 'ArdourGUI'] + process(self.command, False) else: - # e.g.: ['pkill', 'ArdourGUI'] + # e.g.: 'pkill ArdourGUI' process(self.command, False) - else: - # e.g.: 'pkill ArdourGUI' - process(self.command, False) - self.on('click', click) + self.on('click', click) + + if self.icon_image: + self.text = '' + svg = '' + if path.isfile(path.expanduser(self.icon_image)): + try: + with open(path.expanduser(self.icon_image)) as f: + svg = f.read() + except Exception as e: + print(f"{e}") + try: # svg with custom tags, as inkscape is using, cannot be interpreted + _svg = parse_html(svg) + #print(dir(tmp_svg)) # add_attribute + #print(tmp2.attributes) + # set width and height to viewBox to update width and height for scaling + w = _svg.width if hasattr(_svg, 'width') else "64" + h = _svg.height if hasattr(_svg, 'height') else "64" + vb = _svg.viewBox if hasattr(_svg, 'viewBox') else '0 0 ' + w + ' ' + h + _svg.viewBox = vb + _svg.width = 64 + _svg.height = 64 + self.add(_svg) + except Exception as e: + print(f"[Error SVG]: {e}") + + elif self.icon: + self.inner_html = f"" class ButtonSound(Div): div = None @@ -99,16 +144,27 @@ class ButtonSound(Div): super().__init__(**kwargs) self.classes = "grid-rows-2" self.div = Div(classes="flex") - Button(inner_html=f'{self.description}
- 5%', style=self.button_style, click=self.decrease, a=self.div) - Button(inner_html=f'{self.description}
+ 5%', style=self.button_style, click=self.increase, a=self.div) + #Button(inner_html=f'{self.description}
- 5%', click=self.decrease, a=self.div) + #Button(inner_html=f'{self.description}
+ 5%', click=self.increase, a=self.div) + #Button(inner_html=f'{self.description}
(un)mute', click=self.mute, a=self.div) + Button(inner_html=f'- 5%', click=self.decrease, a=self.div) + Button(inner_html=f'+ 5%', click=self.increase, a=self.div) + Button(inner_html=f'toggle mute', click=self.mute, a=self.div) self.add(self.div) - self.volume = Div(text=f"Volume: {volume(self.name)}%", classes="text-gray-600 text-center -mt-2", a=self) + #self.volume = Div(text=f"Volume: {volume(self.name)}", classes="text-gray-600 text-center -mt-2", a=self) + self.volume = Div(text=f"{self.description}: {volume(self.name)}", classes="text-gray-600 text-center -mt-2", a=self) async def decrease(self, msg): - self.volume.text = f'Volume: {volume_decrease(self.name)}%' + #self.volume.text = f'Volume: {volume_decrease(self.name)}' + self.volume.text = f'{self.description}: {volume_decrease(self.name)}' async def increase(self, msg): - self.volume.text = f'Volume: {volume_increase(self.name)}%' + #self.volume.text = f'Volume: {volume_increase(self.name)}' + self.volume.text = f'{self.description}: {volume_increase(self.name)}' + + async def mute(self, msg): + #self.volume.text = f'Volume: {volume_mute(self.name)}' + self.volume.text = f'{self.description}: {volume_mute(self.name)}' async def reload(self, msg): await msg.page.reload() @@ -153,16 +209,18 @@ def application(request): tmp = [{'description': i[iname.end(0)+1:], 'color-bg': config.get(i, 'color-bg', fallback=''), 'color-fg': config.get(i, 'color-fg', fallback=''), - 'name': config.get(i, 'name', fallback=None)}] + 'name': config.get(i, 'name', fallback=None), + 'decrease-icon': config.get('default', 'volume-decrease-icon', fallback=''), + 'decrease-icon-image': config.get('default', 'volume-decrease-icon-image', fallback='')}] try: volume_dict[id] += tmp except KeyError: volume_dict[id] = tmp - # button - iname = search("^([0-9]*.?)button", i, flags=IGNORECASE) + # button or empty + iname = search("^([0-9]*.?)(button|empty)", i, flags=IGNORECASE) if iname is not None: id = iname.group(1)[:-1] # remove dot - tmp = [{'type': 'normal', 'text': i[iname.end(0)+1:], + tmp = [{'type': iname.group(2), 'text': i[iname.end(0)+1:], 'color-bg': config.get(i, 'color-bg', fallback=''), 'color-fg': config.get(i, 'color-fg', fallback=''), 'command': config.get(i, 'command', fallback=None), @@ -172,15 +230,6 @@ def application(request): button_dict[id] += tmp except KeyError: button_dict[id] = tmp - # empty - iname = search("^([0-9]*.?)empty", i, flags=IGNORECASE) - if iname is not None: - id = iname.group(1)[:-1] # remove dot - tmp = [{'type': 'empty', 'text': i[iname.end(0)+1:]}] - try: - button_dict[id] += tmp - except KeyError: - button_dict[id] = tmp var_prefix = "_div" for i in volume_dict: var = var_prefix+i @@ -194,44 +243,11 @@ def application(request): for i in button_dict: var = var_prefix+i for j in button_dict[i]: - if j['type'] == 'normal': - color_bg = f"background-color:{j['color-bg']};" if ishexcolor(j['color-bg']) else '' - color_fg = f"color:{j['color-fg']};" if ishexcolor(j['color-fg']) else '' if var not in vars(): vars()[var] = Div(classes="flex flex-wrap", a=wp) - if j['type'] == 'empty': - Button(empty=True, a=eval(var)) - elif 'icon-image' in j and j['icon-image'] != '': - svg = '' - if path.isfile(path.expanduser(j['icon-image'])): - try: - with open(path.expanduser(j['icon-image'])) as f: - svg = f.read() - except Exception as e: - print(f"{e}") - try: # svg with custom tags, as inkscape is using, cannot be interpreted - tmp = Button(style = color_bg, command=j['command'], a=eval(var)) - tmp_svg = parse_html(svg) - #print(dir(tmp_svg)) # add_attribute - #print(tmp2.attributes) - # set width and height to viewBox to update width and height for scaling - w = tmp_svg.width if hasattr(tmp_svg, 'width') else "64" - h = tmp_svg.height if hasattr(tmp_svg, 'height') else "64" - vb = tmp_svg.viewBox if hasattr(tmp_svg, 'viewBox') else '0 0 ' + w + ' ' + h - tmp_svg.viewBox = vb - tmp_svg.width = 64 - tmp_svg.height = 64 - tmp += tmp_svg - except Exception as e: - print(f"[Error SVG]: {e}") - elif 'icon' in j and j['icon'] != '': - Button(inner_html=f"", - style = color_bg + color_fg, - command=j['command'], a=eval(var)) - else: - Button(text=j['text'], - style = color_bg + color_fg, - command=j['command'], a=eval(var)) + Button(text=j['text'], btype=j['type'], command=j['command'], + color_bg=j['color-bg'], color_fg=j['color-fg'], + icon=j['icon'], icon_image=j['icon-image'], a=eval(var)) if not wp.components: # config not found or empty, therefore insert an empty div to not get an error