1
0
mirror of https://gitlab.com/linuxstuff/dotfiles.git synced 2026-06-19 04:06:00 +02:00
Files
dotfiles/.config/polybar/scripts/modules/cava.py
T
2021-01-14 14:39:40 +01:00

189 lines
4.9 KiB
Python

#!/usr/bin/python3
import sys
import time
import struct
import os.path
import subprocess
import configparser
from collections import defaultdict
##################################################
# Config
# Decide if the output should go to STDOUT or a fifo buffer
PRINT_TO_STDOUT = False
# Display no output if all bars are at level 0
HIDE_WHEN_EMPTY = True
# Separator Character between bars
# Examples: https://www.compart.com/en/unicode/category/Zs
SEPARATOR = ''
CONFIG_PATH = os.path.join(os.sep, "tmp","cava_polybar.config")
RAW_PIPE_OUT = os.path.join(os.sep, "tmp","cava_polybar_output.fifo")
# Data from the cava config
RAW_PIPE_IN = os.path.join(os.sep, "tmp","cava_polybar_input.fifo")
OUTPUT_FILE = os.path.join(os.sep, "tmp","cava_polybar.out")
BARS_NUMBER = 8
OUTPUT_BIT_FORMAT = "8bit"
# Values range from 0 to 100
# Distribute 9 states over this value range
# ▁▂▃▄▅▆▇█
bar_factor = 100 / 10
bar_characters = dict([
(0, ''),
(bar_factor * 1, ''),
(bar_factor * 2, ''),
(bar_factor * 3, ''),
(bar_factor * 4, ''),
(bar_factor * 5, ''),
(bar_factor * 6, ''),
(bar_factor * 7, ''),
(bar_factor * 8, '')
])
##################################################
# Code begins here
bytetype, bytesize, bytenorm = ("H", 2, 65535) if (OUTPUT_BIT_FORMAT == "16bit") else ("B", 1, 255)
def output(value, fifo):
if (PRINT_TO_STDOUT):
print(value, end="")
else:
fifo.write(value)
def valToBar(value):
for bar_threshold in bar_characters:
if(value < bar_threshold):
return bar_characters[bar_threshold]
return bar_characters[bar_factor * 8]
def test():
print("")
print("Bar Characters:")
for bar_threshold in bar_characters:
print('{:02.2f}: {}'.format(bar_threshold,bar_characters[bar_threshold]))
print("")
print("Value Test:")
for i in range(101):
print('{:03d}: {}'.format(i,valToBar(i)))
def createCavaConfig():
# Exit if file is already there
#if (os.path.isfile(CONFIG_PATH)):
# return
config = configparser.ConfigParser()
config.add_section('general')
config.set('general', 'bars', str(BARS_NUMBER))
#config.set('general', 'overshoot', str(0))
config.add_section('output')
config.set('output', 'method', 'raw')
#config.set('output', 'channels', 'mono')
#config.set('output', 'mono_option', 'average')
config.set('output', 'raw_target', RAW_PIPE_IN)
config.set('output', 'bit_format', OUTPUT_BIT_FORMAT)
#config.add_section('smoothing')
#config.set('smoothing', 'integral', '0')
with open(CONFIG_PATH, 'w') as configfile:
config.write(configfile)
def run():
createCavaConfig()
process = subprocess.Popen(["cava", "-p", CONFIG_PATH])
exit_code = 0
fifo_out = None
if (not PRINT_TO_STDOUT):
if os.path.exists(RAW_PIPE_OUT):
os.remove(RAW_PIPE_OUT)
os.mkfifo(RAW_PIPE_OUT)
print("Output can be found in " + RAW_PIPE_OUT)
fifo_out = open(RAW_PIPE_OUT, "w")
fifo_in = open(RAW_PIPE_IN, "rb")
try:
convert(fifo_in, fifo_out)
except KeyboardInterrupt:
exit_code = 1
finally:
if (not PRINT_TO_STDOUT):
fifo_out.close()
os.remove(RAW_PIPE_OUT)
fifo_in.close()
sys.exit(exit_code)
def convert(fifo_in, fifo_out):
chunk = bytesize * BARS_NUMBER
fmt = bytetype * BARS_NUMBER
emptyOutputs = 0
tstring = ""
while True:
rawData = fifo_in.read(chunk)
if len(rawData) < chunk:
break
empty = True
tstring = ""
for i in struct.unpack(fmt, rawData):
value = int(i / bytenorm * 100)
tstring += valToBar(value) + SEPARATOR
if (value != 0):
empty = False
if (empty and HIDE_WHEN_EMPTY):
emptyOutputs += 1
if (emptyOutputs > 5):
output(" " + '\n', fifo_out)
else:
emptyOutputs = 0
output(tstring + '\n', fifo_out)
if __name__ == "__main__":
for arg in sys.argv:
if (arg == "h" or arg == "help"):
print("")
print("cava polybar parse script")
print("Converts cava raw values into characters and outputs to STDOUT or a fifo buffer")
print("")
print("Adjust thresholds, characters and config directly in the script")
print("If the config file at 'CONFIG_PATH' (/tmp/cava_polybar.config) is messed up, simply delet it")
print("")
print("Arguments:")
print("<none> ... Execute normally")
print("t, test ... Run test mode (stdout only)")
print("h, help ... Show this help message and exit (stdout only)")
print("")
sys.exit()
if (arg == "t" or arg == "test"):
test()
sys.exit()
run()