diff --git a/controldeck.py b/controldeck.py
index e7afcb3..4af759f 100755
--- a/controldeck.py
+++ b/controldeck.py
@@ -61,9 +61,17 @@ APP_NAME = "ControlDeck"
COLOR_PRIME = "blue-grey-8" # "blue-grey-7" "blue-grey-8" 'light-blue-9'
COLOR_PRIME_TEXT = "blue-grey-7"
COLOR_SELECT = "light-blue-9"
+DEBUG = False
-CONFIG_FILE = '~/.config/controldeck/controldeck.conf'
-CONFIG_FILE_FULL = path.expanduser(CONFIG_FILE)
+CONFIG_DIR = path.join(path.expanduser("~"), '.config', APP_NAME.lower())
+CONFIG_FILE_NAME = APP_NAME.lower() + '.conf'
+CONFIG_FILE = path.join(CONFIG_DIR, CONFIG_FILE_NAME)
+CACHE_DIR = path.join(path.expanduser('~'), '.cache', APP_NAME.lower())
+STATIC_DIR = path.join(CACHE_DIR, 'static')
+
+# justpy config overwrite
+import jpcore.justpy_config
+jpcore.justpy_config.STATIC_DIRECTORY = STATIC_DIR
def tohtml(text):
return text.replace("\n", "
")
@@ -94,17 +102,18 @@ def process(command_line, shell=False, output=True, stdout=PIPE, stderr=STDOUT):
def config_load(conf=''):
config = ConfigParser(strict=False)
+ # fist check if file is given
if conf:
- full_config_file_path = conf
+ config_file_path = conf
else:
- config_file = "controldeck.conf"
- full_config_file_path = path.dirname(path.realpath(__file__)) + sep + config_file
+ # check if config file is located at the script's location
+ config_file = path.dirname(path.realpath(__file__)) + sep + CONFIG_FILE_NAME # realpath; resolve symlink
if not path.exists(config_file):
- config_folder = path.join(path.expanduser("~"), '.config', APP_NAME.lower())
- makedirs(config_folder, exist_ok=True)
- full_config_file_path = path.join(config_folder, config_file)
+ # if not, use the file inside .config
+ makedirs(CONFIG_DIR, exist_ok=True)
+ config_file = CONFIG_FILE
try:
- config.read(full_config_file_path)
+ config.read(path.expanduser(config_file))
except Exception as e:
print(f"{e}")
#print(config.sections())
@@ -148,9 +157,13 @@ class Button(QBtn):
self.style += "min-height: 77px;" # image + 2 text lines
self.style += "line-height: 1em;"
if self.image and path.exists(self.image):
- static_dir = getcwd() + '/static'
- shutil.copy2(self.image, static_dir)
+ # copy image files into the static folder
basename = path.basename(self.image)
+ staticfile = path.join(STATIC_DIR, basename)
+ if not path.exists(staticfile):
+ shutil.copy2(self.image, staticfile)
+ if DEBUG:
+ print(f'[DEBUG] copy {self.image} to {staticfile}')
self.icon = f"img:/static/{basename}"
#
#
@@ -572,9 +585,9 @@ async def application(request):
def toggle_edit_config(self, msg):
self.dialog.value = True
- if path.exists(CONFIG_FILE_FULL):
+ if path.exists(CONFIG_FILE):
self.dialog_label.text = CONFIG_FILE
- with open(CONFIG_FILE_FULL, encoding='utf-8') as file:
+ with open(CONFIG_FILE, encoding='utf-8') as file:
self.dialog_input.value = file.read()
def edit_dialog_after(self, msg):
self.dialog_input.remove_class('changed')
@@ -594,8 +607,8 @@ async def application(request):
QSpace(a=edit_dialog_bar)
QSeparator(vertical=True,spaced=True,a=edit_dialog_bar)
def edit_dialog_save(self, msg):
- if path.exists(CONFIG_FILE_FULL):
- with open(CONFIG_FILE_FULL, mode='w', encoding='utf-8') as file:
+ if path.exists(CONFIG_FILE):
+ with open(CONFIG_FILE, mode='w', encoding='utf-8') as file:
file.write(self.dialog_input.value)
self.dialog_input.remove_class('changed')
edit_dialog_btn_save = QBtn(
@@ -786,86 +799,6 @@ async def application(request):
self.qnotify.notify = False
test_btn.on('after', test_btn_after)
- # tmp = process('pactl -f json list sink-inputs', stderr=None)
- # print('')
- # #print(tmp)
- # #print(len(tmp))
- # tmp = json.loads(tmp)
- # print(tmp)
- # print(len(tmp))
- # if tmp:
- # print('mute:', tmp[0]['mute'])
- # print('volume:', tmp[0]['volume']['front-left']['value_percent'][:-1])
- # print('application.process.binary:', tmp[0]['properties']['application.process.binary'])
- # print('application.process.id:', tmp[0]['properties']['application.process.id'])
- # if 'application.icon_name' in tmp[0]['properties']:
- # print('application.icon_name:', tmp[0]['properties']['application.icon_name'])
- # if 'media.icon_name' in tmp[0]['properties']:
- # print('media.icon_name:', tmp[0]['properties']['media.icon_name'])
- # print('media.name:', tmp[0]['properties']['media.name'])
- # print('')
-
- #tmp2 = process('pactl list sink-inputs | grep media.name', shell=True, stderr=None)
- #print(tmp2)
- # remove ' name.media = ' and remove quotation marks at front and back
- # print([i[1:-1] for i in re.sub('[ \t]*media.name = ', '', tmp2, re.S).split('\n')])
-
- # own pactl list sink-inputs parser (pactl 16.1, Compiled with libpulse 16.1.0)
- tmp2 = process("pactl list sink-inputs", shell=True, stderr=None)
- #print(tmp2)
- tmp3 = []
- for i in tmp2.split('Sink Input #'): # split block
- if i:
- tmp4 = {}
- for j,k in enumerate(i.split('\n')): # split on every line
- if j == 0: # fist entry
- tmp4['id'] = k # is the id
- tmp4['properties'] = {} # initialize
- if k: # others are attributes
- if 'Driver: ' in k:
- tmp4['driver'] = re.sub('[ \t]*Driver: ', '', k)
- elif 'Mute: ' in k:
- tmp5 = re.sub('[ \t]*Mute: ', '', k)
- tmp5 = tmp5.replace('no', 'false')
- tmp5 = tmp5.replace('yes', 'true')
- tmp4['mute'] = tmp5
- elif 'Volume: ' in k:
- tmp4['volume'] = {}
- for l in re.sub('[ \t]*Volume: ', '', k).split(','):
- tmp5 = l.split(': ')
- tmp6 = tmp5[1].split(' / ')
- tmp4['volume'][tmp5[0].strip()] = {
- 'value': tmp6[0], 'value_percent': tmp6[1], 'db': tmp6[2]}
- # Properties
- elif 'application.name = ' in k:
- # remove '\t\tapplication.name = ' and remove quotation marks at front and back
- tmp4['properties']['application.name'] = re.sub('[ \t]*application.name = ', '', k)[1:-1]
- elif 'application.process.id = ' in k:
- # remove '\t\tapplication.process.id = ' and remove quotation marks at front and back
- tmp4['properties']['application.process.id'] = re.sub('[ \t]*application.process.id = ', '', k)[1:-1]
- elif 'application.process.binary = ' in k:
- # remove '\t\tapplication.process.binary = ' and remove quotation marks at front and back
- tmp4['properties']['application.process.binary'] = re.sub('[ \t]*application.process.binary = ', '', k)[1:-1]
- elif 'media.icon_name = ' in k:
- # remove '\t\tmedia.icon_name = ' and remove quotation marks at front and back
- tmp4['properties']['media.icon_name'] = re.sub('[ \t]*media.icon_name = ', '', k)[1:-1] # only pipewire?
- elif 'application.icon_name = ' in k:
- # remove '\t\tapplication.icon_name = ' and remove quotation marks at front and back
- tmp4['properties']['application.icon_name'] = re.sub('[ \t]*application.icon_name = ', '', k)[1:-1] # only pulseaudio? (seen on wsl)
- elif 'media.name = ' in k:
- # remove '\t\tmedia.name = ' and remove quotation marks at front and back
- tmp4['properties']['media.name'] = re.sub('[ \t]*media.name = ', '', k)[1:-1]
- elif 'node.name = ' in k:
- # remove '\t\tnode.name = ' and remove quotation marks at front and back
- tmp4['properties']['node.name'] = re.sub('[ \t]*node.name = ', '', k)[1:-1]
- tmp3.append(tmp4)
- #import xdg.IconTheme
- #print(tmp3)
- #icon_name = ''
- #icon_name = i['properties']['application.icon_name'] if 'application.icon_name' in i['properties'] else icon_name
- #icon_name = i['properties']['media.icon_name'] if 'media.icon_name' in i['properties'] else icon_name
- #icon = 'img:' + xdg.IconTheme.getIconPath(icon_name, size=None, extensions=['svg', 'png']),
-
# TODO: change reference wp.components to ...
if not wp.components:
# config not found or empty, therefore insert an empty div to not get an error
@@ -887,9 +820,14 @@ def main(args):
config = config_load(args.config)
host = config.get('default', 'host', fallback='0.0.0.0')
port = config.get('default', 'port', fallback='8000')
- justpy(host=host, port=port, static_directory="./static")
+
+ if not path.exists(STATIC_DIR):
+ makedirs(STATIC_DIR, exist_ok=True)
+ justpy(host=host, port=port, start_server=True)
+ # this process will run as main loop
def cli():
+ global DEBUG
parser = argparse.ArgumentParser(
description=__doc__, prefix_chars='-',
formatter_class=argparse.RawTextHelpFormatter,
@@ -901,7 +839,10 @@ def cli():
args = parser.parse_args()
if args.debug:
- print(args)
+ DEBUG = True
+ print('[DEBUG] args:', args)
+ print('[DEBUG] __file__:', __file__)
+ print('[DEBUG] cwd:', getcwd())
main(args)