inital commit

This commit is contained in:
2021-04-03 20:55:22 +02:00
commit 0e23771ab1
2 changed files with 142 additions and 0 deletions

18
controldeck.conf Normal file
View File

@@ -0,0 +1,18 @@
# Examples:
#
# [N.volume.NAME]
# name = sink_name
# : N. optional group/row specification
# : NAME name of the button
# : name sink name, see name with: pamixer --list-sinks
#
# [N.button.NAME]
# command = shell command
# second command
# ...
# : N. optional group/row specification
# : NAME name of the button
# : command command(s) to run
[4.button.Test]
command = notify-send -a foo baz

124
controldeck.py Normal file
View File

@@ -0,0 +1,124 @@
#!/usr/bin/env python
from subprocess import Popen, PIPE, STDOUT
from configparser import ConfigParser, DuplicateSectionError
from re import search, IGNORECASE
from justpy import Div, WebPage, SetRoute, justpy
def process(args):
try:
# with shell=True args can be a string
# detached process https://stackoverflow.com/a/65900355/992129 start_new_session
# https://docs.python.org/3/library/subprocess.html#popen-constructor
result = Popen(args, stdout=PIPE, stderr=STDOUT, shell=True, start_new_session=True)
return result.stdout.read().decode("utf-8").rstrip()
except Exception as e:
print(f"{e} failed!")
def volume(name):
return process(f'pamixer --get-volume --sink "{name}"')
def volume_decrease(name):
return process(f'pamixer --get-volume --sink "{name}" --decrease 5')
def volume_increase(name):
return process(f'pamixer --get-volume --sink "{name}" --increase 5')
class Button(Div):
command = None
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.classes = "bg-gray-800 hover:bg-gray-700 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) for i in self.command]
else:
# e.g.: ['pkill', 'ArdourGUI']
process(self.command)
else:
# e.g.: 'pkill ArdourGUI'
process(self.command)
self.on('click', click)
class ButtonSound(Div):
div = None
name = None
description = None
volume = None
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.classes = "grid-rows-2"
self.div = Div(classes="flex")
Button(inner_html=f'{self.description}<br> - 5%', click=self.decrease, a=self.div)
Button(inner_html=f'{self.description}<br> + 5%', click=self.increase, a=self.div)
self.add(self.div)
self.volume = Div(text=f"Volume: {volume(self.name)}%", classes="text-center -mt-2", a=self)
async def decrease(self, msg):
self.volume.text = f'Volume: {volume_decrease(self.name)}%'
async def increase(self, msg):
self.volume.text = f'Volume: {volume_increase(self.name)}%'
@SetRoute('/')
def application():
wp = WebPage(title="ControlDeck", body_classes="bg-gray-900")
wp.head_html = '<meta name="viewport" content="width=device-width, initial-scale=1">'
# div = Div(classes="flex flex-wrap", a=wp)
# ButtonSound(name="Stream_sink", description="Stream sink", a=div)
# div2 = Div(classes="flex flex-wrap", a=wp)
# Button(text="Sleep", command='systemctl suspend', a=div2)
config = ConfigParser(strict=False)
volume_dict = {}
button_dict = {}
try:
config.read('controldeck.conf')
except Exception as e:
print(f"{e}")
#print(config.sections())
for i in config.sections():
iname = None
iname = search("^([0-9]*.?)volume", i, flags=IGNORECASE)
if iname is not None:
id = iname.group(1)[:-1] # remove dot
try:
volume_dict[id] += [{'description': i[iname.end(0)+1:],
'name': config.get(i, 'name', fallback=None)}]
except KeyError:
volume_dict[id] = [{'description': i[iname.end(0)+1:],
'name': config.get(i, 'name', fallback=None)}]
iname = search("^([0-9]*.?)button", i, flags=IGNORECASE)
if iname is not None:
id = iname.group(1)[:-1] # remove dot
try:
button_dict[id] += [{'text': i[iname.end(0)+1:],
'command': config.get(i, 'command', fallback=None)}]
except KeyError:
button_dict[id] = [{'text': i[iname.end(0)+1:],
'command': config.get(i, 'command', fallback=None)}]
for i in volume_dict:
for j in volume_dict[i]:
if 'div'+i not in vars():
vars()['div'+i] = Div(classes="flex flex-wrap", a=wp)
ButtonSound(name=j['name'], description=j['description'], a=eval('div'+i))
for i in button_dict:
for j in button_dict[i]:
if 'div'+i not in vars():
vars()['div'+i] = Div(classes="flex flex-wrap", a=wp)
Button(text=j['text'], command=j['command'], a=eval('div'+i))
if not wp.components:
# config not found or empty, therefore insert an empty div to not get an error
Div(text="add elements in controldeck.conf", classes="flex flex-wrap", a=wp)
return wp
if __name__ == '__main__':
justpy()