Multiple changes including random wallpaper, theme colors and switching to yay instead of yaourt

This commit is contained in:
Kevin Alberts 2018-12-29 21:49:27 +01:00
parent b78b817a33
commit 5b7475e50f
Signed by: Kurocon
GPG key ID: BCD496FEBA0C6BC1
7 changed files with 609 additions and 46 deletions

View file

@ -65,7 +65,6 @@ hook.subscribe.changegroup(Theme.callback_changegroup)
hook.subscribe.focus_change(Theme.callback_focus_change) hook.subscribe.focus_change(Theme.callback_focus_change)
hook.subscribe.float_change(Theme.callback_float_change) hook.subscribe.float_change(Theme.callback_float_change)
hook.subscribe.group_window_add(Theme.callback_group_window_add) hook.subscribe.group_window_add(Theme.callback_group_window_add)
hook.subscribe.window_name_change(Theme.callback_window_name_change)
hook.subscribe.client_new(Theme.callback_client_new) hook.subscribe.client_new(Theme.callback_client_new)
hook.subscribe.client_managed(Theme.callback_client_managed) hook.subscribe.client_managed(Theme.callback_client_managed)
hook.subscribe.client_killed(Theme.callback_client_killed) hook.subscribe.client_killed(Theme.callback_client_killed)
@ -112,3 +111,6 @@ def main(qtile):
# Save qtile instance in theme # Save qtile instance in theme
Theme.qtile = qtile Theme.qtile = qtile
# Save theme instance in qtile
qtile.theme_instance = Theme

View file

@ -183,9 +183,6 @@ class BaseTheme:
def callback_group_window_add(self, *args, **kwargs): def callback_group_window_add(self, *args, **kwargs):
pass pass
def callback_window_name_change(self, *args, **kwargs):
pass
def callback_client_new(self, *args, **kwargs): def callback_client_new(self, *args, **kwargs):
pass pass

View file

@ -7,9 +7,17 @@ class Config(BaseConfig):
debug = False debug = False
verbose = False verbose = False
# Colors
foreground = "#ffffff"
background = "#000000"
highlight = "#1793d0"
inactive_light = "#777777"
inactive_dark = "#333333"
# Default Applications # Default Applications
app_terminal = "terminator" app_terminal = "terminator"
app_launcher = "dmenu_run -i -p '»' -nb '#000000' -fn 'Noto Sans-11' -nf '#777777' -sb '#1793d0' -sf '#ffffff'" app_launcher = "dmenu_run -i -p '»' -nb '" + background + "' -fn 'Noto Sans-11' -nf '" + inactive_light + \
"' -sb '" + highlight + "' -sf '" + foreground + "'"
web_browser = "firefox-developer-edition" web_browser = "firefox-developer-edition"
file_manager = "thunar" file_manager = "thunar"
cmd_brightness_up = "sudo /usr/bin/xbacklight -inc 10" cmd_brightness_up = "sudo /usr/bin/xbacklight -inc 10"
@ -18,7 +26,9 @@ class Config(BaseConfig):
# Images # Images
desktop_bg = "/home/kevin/Pictures/wallpapers/desktop.png" desktop_bg = "/home/kevin/Pictures/wallpapers/desktop.png"
desktop_bg_folder = "/home/kevin/Pictures/wallpapers/desktop_rotation"
applauncher_image = "/home/kevin/.config/qtile/kuro/resources/arch.png" applauncher_image = "/home/kevin/.config/qtile/kuro/resources/arch.png"
custom_layout_icon_paths = ['/home/kevin/.config/qtile/kuro/resources/layout_icons/']
# Fonts # Fonts
font_default = "Noto Sans" font_default = "Noto Sans"
@ -41,14 +51,14 @@ class Config(BaseConfig):
width_zoomy_column = 300 width_zoomy_column = 300
# Colours # Colours
colour_border_normal = "#333333" colour_border_normal = inactive_dark
colour_border_focus = "#ffffff" colour_border_focus = foreground
colour_border_urgent = "#774400" colour_border_urgent = highlight
colour_spacer_background = "#777777" colour_spacer_background = inactive_light
# Bar variables # Bar variables
bar_background = "#000000" bar_background = background
bar_opacity = 0.65 bar_opacity = 0.8
bar_hover_opacity = 1 bar_hover_opacity = 1
# Groupbox variables # Groupbox variables
@ -59,14 +69,14 @@ class Config(BaseConfig):
margin_groupbox = 0 margin_groupbox = 0
bool_groupbox_disable_drag = True bool_groupbox_disable_drag = True
bool_groupbox_rounded_borders = True bool_groupbox_rounded_borders = True
colour_groupbox_border_normal = "#333333" colour_groupbox_border_normal = inactive_dark
colour_groupbox_border_focus = "#aaaaaa" colour_groupbox_border_focus = foreground
colour_groupbox_icon_active = "#ffffff" colour_groupbox_icon_active = foreground
colour_groupbox_icon_inactive = "#777777" colour_groupbox_icon_inactive = inactive_light
# Tasklist variables # Tasklist variables
tasklist_border = "#ffffff" tasklist_border = foreground
tasklist_urgent_border = "#774400" tasklist_urgent_border = highlight
tasklist_font = "Noto Sans" tasklist_font = "Noto Sans"
tasklist_fontsize = 11 tasklist_fontsize = 11
@ -97,10 +107,10 @@ class Config(BaseConfig):
volume_font = "Noto Sans" volume_font = "Noto Sans"
volume_fontsize = 11 volume_fontsize = 11
volume_theme_path = "/home/kevin/.config/qtile/kuro/resources/volume" volume_theme_path = "/home/kevin/.config/qtile/kuro/resources/volume"
volume_get_command = "pamixer --sink 0 --get-volume".split() volume_get_command = "pamixer --sink 2 --get-volume".split()
volume_mute_command = "pamixer --sink 0 -t".split() volume_mute_command = "pamixer --sink 2 -t".split()
volume_up_command = "pamixer --sink 0 -i 2".split() volume_up_command = "pamixer --sink 2 -i 2".split()
volume_down_command = "pamixer --sink 0 -d 2".split() volume_down_command = "pamixer --sink 2 -d 2".split()
volume_is_bluetooth_icon = False volume_is_bluetooth_icon = False
volume_update_interval = 0.2 volume_update_interval = 0.2
@ -117,6 +127,15 @@ class Config(BaseConfig):
# CheckUpdates variables # CheckUpdates variables
updates_display_format = "{updates}" updates_display_format = "{updates}"
updates_execute_command = "terminator -e 'echo Updating\ via\ yaourt\ -Sayu...; yaourt -Sayu'" updates_execute_command = "terminator -e 'echo Updating\ via\ yay...; yay'"
updates_colour_available = '#f4d742' updates_colour_available = '#f4d742'
# Screen organization
laptop_screen = "eDP-1-1"
# Keyboard colors
do_keyboard_updates = False
# Show audio visualizer
show_audio_visualizer = True

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

View file

@ -1,3 +1,7 @@
import json
import os
import random
from libqtile.config import Key, Screen, Group, Drag, Click from libqtile.config import Key, Screen, Group, Drag, Click
from libqtile.command import lazy from libqtile.command import lazy
from libqtile import layout, bar, widget from libqtile import layout, bar, widget
@ -39,6 +43,12 @@ class Kuro(BaseTheme):
# Top bars # Top bars
topbars = [] topbars = []
# Current wallpaper path
current_wallpaper = None
# Whether or not to perform keyboard backlight updates
do_keyboard_updates = True
# Window manager name # Window manager name
wmname = "QTile" wmname = "QTile"
@ -60,6 +70,12 @@ class Kuro(BaseTheme):
def initialize(self): def initialize(self):
self.log_debug("Initializing Kuro Theme...") self.log_debug("Initializing Kuro Theme...")
# Update color scheme
self.initialize_colorscheme()
# Set settings
self.do_keyboard_updates = Config.get("do_keyboard_updates", True)
super(Kuro, self).initialize() super(Kuro, self).initialize()
self.update() self.update()
@ -108,7 +124,7 @@ class Kuro(BaseTheme):
Key([self.mod], "b", lazy.spawn(Config.get('web_browser', "xterm links"))), Key([self.mod], "b", lazy.spawn(Config.get('web_browser', "xterm links"))),
# Super-F to start file manager # Super-F to start file manager
# Key([self.mod], "f", lazy.spawn(Config.get('file_manager', "thunar"))), # Key([self.mod], "f", lazy.spawn(Config.get('file_m4anager', "thunar"))),
# Super-Shift-R to start spawncmd # Super-Shift-R to start spawncmd
Key([self.mod, "shift"], "r", lazy.spawncmd()), Key([self.mod, "shift"], "r", lazy.spawncmd()),
@ -132,13 +148,20 @@ class Kuro(BaseTheme):
# Shutdown QTile # Shutdown QTile
Key([self.mod, "control"], "q", lazy.shutdown()), Key([self.mod, "control"], "q", lazy.shutdown()),
# Update wallpaper
Key([self.mod, "control"], "w", lazy.function(self.update_wallpaper)),
# Reload colorscheme
Key([self.mod, "control"], "t", lazy.function(self.update_colorscheme)),
# Reorganize screens
Key([self.mod, "control"], "s", lazy.function(self.update_screens)),
## ##
# Debug keyboard shortcuts # Debug keyboard shortcuts
## ##
Key([self.mod, "control"], "w", lazy.function(display_wm_class)), Key([self.mod, "control"], "c", lazy.function(display_wm_class)),
# Redraw the top bar # Redraw the top bar
Key([self.mod, "shift", "control"], "r", lazy.function(self.redraw_bar)), Key([self.mod, "shift", "control"], "r", lazy.function(self.redraw_bar)),
@ -153,7 +176,7 @@ class Kuro(BaseTheme):
groups = [] groups = []
# http://fontawesome.io/cheatsheet # http://fontawesome.io/cheatsheet
groups.append(Group("", spawn=Config.get('web_browser', "xterm links"))) groups.append(Group("", spawn=Config.get('web_browser', "xterm links")))
groups.append(Group("", spawn=Config.get('app_terminal', "xterm"))) groups.append(Group("", spawn=Config.get('app_terminal', "xterm")))
groups.append(Group("")) groups.append(Group(""))
groups.append(Group("", spawn="franz4-bin")) groups.append(Group("", spawn="franz4-bin"))
@ -161,7 +184,7 @@ class Kuro(BaseTheme):
groups.append(Group("", spawn=Config.get('file_manager', "thunar"))) groups.append(Group("", spawn=Config.get('file_manager', "thunar")))
groups.append(Group("", spawn="thunderbird")) groups.append(Group("", spawn="thunderbird"))
groups.append(Group("")) groups.append(Group(""))
groups.append(Group("", spawn="qupzilla https://music.kurocon.nl/")) groups.append(Group(""))
groups.append(Group("")) groups.append(Group(""))
return groups return groups
@ -233,7 +256,23 @@ class Kuro(BaseTheme):
urgent_alert_method=Config.get('tasklist_urgent_alert_method', 'border'), urgent_alert_method=Config.get('tasklist_urgent_alert_method', 'border'),
urgent_border=Config.get('tasklist_urgent_border', '#ff0000'), urgent_border=Config.get('tasklist_urgent_border', '#ff0000'),
margin=Config.get('margin_groupbox', 0) margin=Config.get('margin_groupbox', 0)
), )
])
if Config.get('show_audio_visualizer', False):
widgets.append(utils.AudioVisualizerWidget(
graph_color=Config.get('visualizer_graph_color', "#ffffff"),
fill_color=Config.get('visualizer_fill_color', "#ffffff.3"),
border_color=Config.get('visualizer_border_color', "#000000"),
border_width=Config.get('visualizer_graph_width', 0),
line_width=Config.get('visualizer_line_width', 1),
frequency=0.05
))
widgets.extend([
utils.MediaWidget(),
utils.SeparatorWidget(),
utils.ThermalSensorWidget( utils.ThermalSensorWidget(
font=Config.get('font_topbar', 'Arial'), font=Config.get('font_topbar', 'Arial'),
@ -342,9 +381,9 @@ class Kuro(BaseTheme):
widgets.append(widget.Systray(**self.widget_defaults)) widgets.append(widget.Systray(**self.widget_defaults))
widgets.extend([ widgets.extend([
widget.CurrentLayoutIcon(), utils.KuroCurrentLayoutIcon(custom_icon_paths=Config.get('custom_layout_icon_paths', [])),
widget.Clock(format="%a %d %b, %H:%M", **self.widget_defaults), widget.Clock(format="%a %d %b, %H:%M", **self.widget_defaults),
utils.CheckUpdatesYaourt( utils.CheckUpdatesYay(
colour_no_updates=Config.get('updates_colour_none', '#ffffff'), colour_no_updates=Config.get('updates_colour_none', '#ffffff'),
colour_have_updates=Config.get('updates_colour_available', '#ff0000'), colour_have_updates=Config.get('updates_colour_available', '#ff0000'),
display_format=Config.get('updates_display_format', 'Updates: {updates}'), display_format=Config.get('updates_display_format', 'Updates: {updates}'),
@ -442,16 +481,67 @@ class Kuro(BaseTheme):
# Util functions # Util functions
@staticmethod @staticmethod
def redraw_bar(qtile): def redraw_bar(qtile):
for b in qtile.topbars: for s in qtile.screens:
b.draw() s.top.draw()
@staticmethod
def update_screens(qtile):
out = utils.call_process(["xrandr", "--current"])
laptop_screen = None
screens = []
for x in out.split("\n"):
if " connected " in x:
if Config.get("laptop_screen", None) is not None and Config.get("laptop_screen", None) in x:
laptop_screen = x
else:
screens.append(x)
# Only configure two screens. Open arandr if more screens are present.
if laptop_screen is not None and len(screens) == 1:
laptop = laptop_screen.split()[0]
other = screens[0].split()[0]
utils.call_process(["xrandr", "--output", laptop, "--below", other])
qtile.cmd_restart()
elif laptop_screen is not None and len(screens) > 1:
utils.execute("arandr")
# QTile base callbacks # QTile base callbacks
def callback_startup_once(self, *args, **kwargs):
pass
#Kuro.update_screens(self.qtile)
def callback_startup(self): def callback_startup(self):
utils.execute("sleep 3") utils.execute("sleep 3")
self.log_info("Restoring wallpaper...") # self.log_info("Restoring previous wallpaper...")
utils.execute_once("nitrogen --restore") # utils.execute_once("nitrogen --restore")
# self.update_wallpaper(self.qtile)
if self.current_wallpaper:
utils.execute_once(["wal", "-n", "-i", "{}".format(self.current_wallpaper)])
else:
wallpaper = None
if os.path.isfile("/home/kevin/.cache/wal/colors.json"):
with open("/home/kevin/.cache/wal/colors.json", 'r') as f:
try:
wallpaper = json.load(f)['wallpaper']
except KeyError:
wallpaper = None
if wallpaper:
Kuro.set_wallpaper(self.qtile, wallpaper)
else:
utils.execute_once("nitrogen --restore")
self.log_info("Starting compositor...")
utils.execute_once("compton -b")
# Update color scheme
self.initialize_colorscheme()
# Update color scheme
Kuro.update_colorscheme(self.qtile)
# display = os.environ['DISPLAY'] # display = os.environ['DISPLAY']
# #
# if not display: # if not display:
@ -467,7 +557,8 @@ class Kuro(BaseTheme):
# return True # return True
def callback_focus_change(self, *args, **kwargs): def callback_focus_change(self, *args, **kwargs):
kb_handle_focus_change(self) if self.do_keyboard_updates:
kb_handle_focus_change(self)
initial_windows = [] initial_windows = []
@ -487,6 +578,9 @@ class Kuro(BaseTheme):
self.callback_client_new() self.callback_client_new()
# Update color scheme
Kuro.update_colorscheme(self.qtile)
def callback_client_new(self, *args, **kwargs): def callback_client_new(self, *args, **kwargs):
if len(self.initial_windows) > 0: if len(self.initial_windows) > 0:
init = self.initial_windows.copy() init = self.initial_windows.copy()
@ -501,5 +595,140 @@ class Kuro(BaseTheme):
if r.matches(window): if r.matches(window):
self.qtile.dgroups.remove_rule(rid) self.qtile.dgroups.remove_rule(rid)
self.initial_windows.remove((pid, gname)) self.initial_windows.remove((pid, gname))
self.log_info("Removed group rule for PID {}, window {}".format(pid, window.name)) self.log_info("Removed group rule for PID {}, window {}".format(pid,
window.name))
self.log_info(str(self.qtile.dgroups.rules_map)) self.log_info(str(self.qtile.dgroups.rules_map))
@staticmethod
def update_wallpaper(qtile):
wallpapers = []
wallpaper_dir = Config.get("desktop_bg_folder", "")
try:
wallpapers = os.listdir(wallpaper_dir)
except os.error:
pass
if wallpapers:
qtile.theme_instance.current_wallpaper = os.path.join(wallpaper_dir, random.choice(wallpapers))
Kuro.set_wallpaper(qtile, qtile.theme_instance.current_wallpaper)
else:
utils.execute_once("nitrogen --restore")
@staticmethod
def set_wallpaper(qtile, filename):
utils.execute_once("wal-nitrogen {}".format(filename))
qtile.theme_instance.current_wallpaper = filename
Kuro.update_colorscheme(qtile)
@staticmethod
def update_mediaclients(*args, **kwargs):
return str(str(args) + " " + str(kwargs))
@staticmethod
def initialize_colorscheme():
colors = None
if os.path.isfile("/home/kevin/.cache/wal/colors.json"):
with open("/home/kevin/.cache/wal/colors.json", 'r') as f:
try:
colors = json.load(f)['colors']
except KeyError:
colors = None
if colors:
# Update Config
Config.foreground = colors['color15']
Config.background = colors['color0']
Config.highlight = colors['color3']
Config.inactive_light = colors['color4']
Config.inactive_dark = colors['color5']
@staticmethod
def update_colorscheme(qtile):
"""
:type qtile: libqtile.manager.Qtile
"""
if qtile.theme_instance.current_wallpaper:
utils.execute(["wal", "-n", "-i", "{}".format(qtile.theme_instance.current_wallpaper)])
colors = None
if os.path.isfile("/home/kevin/.cache/wal/colors.json"):
with open("/home/kevin/.cache/wal/colors.json", 'r') as f:
try:
colors = json.load(f)['colors']
except KeyError:
colors = None
if colors:
# Update Config
Config.foreground = colors['color15']
Config.background = colors['color0']
Config.highlight = colors['color3']
Config.inactive_light = colors['color4']
Config.inactive_dark = colors['color5']
# Update border colors in layouts
for group in qtile.groups:
for layout in group.layouts:
if isinstance(layout, kuro_layouts.KuroWmii):
layout.border_focus = colors['color15']
layout.border_focus_stack = colors['color1']
layout.border_normal = colors['color1']
layout.border_normal_stack = colors['color1']
for screen in qtile.screens:
bar = screen.top
bar.background = colors['color1']
bar.drawer.clear(bar.background)
for w in bar.widgets:
if hasattr(w, '_update_drawer'):
try:
w._update_drawer()
except Exception as e:
logger.error("Error while updating drawer: {}".format(e))
if hasattr(w, 'foreground'):
w.foreground = colors['color15']
if hasattr(w, 'foreground_normal'):
w.foreground_normal = colors['color15']
if hasattr(w, 'foreground_alert'):
w.foreground_alert = colors['color3']
if hasattr(w, 'border'):
w.border = colors['color15']
if hasattr(w, 'active'):
w.active = colors['color15']
if hasattr(w, 'highlight_color'):
w.highlight_color = colors['color3']
if hasattr(w, 'inactive'):
w.inactive = colors['color8']
if hasattr(w, 'this_current_screen_border'):
w.this_current_screen_border = colors['color15']
if hasattr(w, 'this_screen_border'):
w.this_screen_border = colors['color15']
if hasattr(w, 'other_current_screen_border'):
w.other_current_screen_border = colors['color8']
if hasattr(w, 'other_screen_border'):
w.other_screen_border = colors['color8']
if isinstance(w, utils.AudioVisualizerWidget):
w.graph_color = colors['color15']
w.fill_color = colors['color8']
bar.draw()
utils.notify(
"Updated colorscheme!",
"active: {}, inactive: {}".format(colors['color15'], colors['color1'])
)

View file

@ -1,11 +1,18 @@
import os import os
import re import re
import subprocess import subprocess
from asyncio import Queue
from threading import Thread
from time import sleep from time import sleep
import cairocffi import cairocffi
import notify2 import notify2
import numpy
import pyaudio
import six
from libqtile import widget, bar from libqtile import widget, bar
from libqtile.widget.currentlayout import CurrentLayoutIcon
from libqtile.widget.graph import _Graph
from libqtile.window import Internal from libqtile.window import Internal
from libqtile.bar import Bar from libqtile.bar import Bar
from libqtile.utils import catch_exception_and_warn, UnixCommandNotFound from libqtile.utils import catch_exception_and_warn, UnixCommandNotFound
@ -38,12 +45,34 @@ def is_running(process):
def execute(process): def execute(process):
return subprocess.Popen(process.split()) if isinstance(process, list):
return subprocess.Popen(process)
elif isinstance(process, str):
return subprocess.Popen(process.split())
else:
pass
def execute_once(process): def execute_once(process):
if not is_running(process): if not is_running(process):
return subprocess.Popen(process.split()) if isinstance(process, list):
return subprocess.Popen(process)
elif isinstance(process, str):
return subprocess.Popen(process.split())
else:
pass
def call_process(command, **kwargs):
"""
This method uses `subprocess.check_output` to run the given command
and return the string from stdout, which is decoded when using
Python 3.
"""
output = subprocess.check_output(command, **kwargs)
if six.PY3:
output = output.decode()
return output
def get_screen_count(): def get_screen_count():
@ -217,18 +246,18 @@ class AppLauncherIcon(Image):
spawn_popup(self.qtile, self.offsetx, self.offsety, "Hovered over AppLauncherIcon!") spawn_popup(self.qtile, self.offsetx, self.offsety, "Hovered over AppLauncherIcon!")
class CheckUpdatesYaourt(CheckUpdates): class CheckUpdatesYay(CheckUpdates):
def __init__(self, **config): def __init__(self, **config):
super(CheckUpdatesYaourt, self).__init__(**config) super(CheckUpdatesYay, self).__init__(**config)
# Override command and output with yaourt command # Override command and output with yay command
self.cmd = "yaourt -Qua".split() self.cmd = "yay -Qua".split()
self.status_cmd = "yaourt -Qua".split() self.status_cmd = "yay -Qua --color never".split()
self.update_cmd = "sudo yaourt -Sya".split() self.update_cmd = "sudo yay".split()
self.subtr = 0 self.subtr = 0
def _check_updates(self): def _check_updates(self):
#subprocess.check_output(self.update_cmd) #subprocess.check_output(self.update_cmd)
res = super(CheckUpdatesYaourt, self)._check_updates() res = super(CheckUpdatesYay, self)._check_updates()
return res return res
def button_press(self, x, y, button): def button_press(self, x, y, button):
@ -253,6 +282,7 @@ class CheckUpdatesYaourt(CheckUpdates):
elif button == BUTTON_MIDDLE and self.execute is not None: elif button == BUTTON_MIDDLE and self.execute is not None:
subprocess.Popen(self.execute, shell=True) subprocess.Popen(self.execute, shell=True)
class KuroBatteryIcon(BatteryIcon): class KuroBatteryIcon(BatteryIcon):
status_cmd = "acpi" status_cmd = "acpi"
@ -265,6 +295,7 @@ class KuroBatteryIcon(BatteryIcon):
output output
) )
class PulseVolumeWidget(Volume): class PulseVolumeWidget(Volume):
defaults = [ defaults = [
@ -535,3 +566,255 @@ class ThermalSensorWidget(ThermalSensor):
command.append("-f") command.append("-f")
sensors_out = self.call_process(command) sensors_out = self.call_process(command)
return self._format_sensors_output(sensors_out) return self._format_sensors_output(sensors_out)
class SeparatorWidget(base._TextBox):
def __init__(self):
super(SeparatorWidget, self).__init__(text="|", width=bar.CALCULATED, fontsize=14)
class MediaWidget(base.InLoopPollText):
"""Media Status Widget"""
class Status:
OFFLINE = 0
PLAYING = 1
PAUSED = 2
STOPPED = 3
orientations = base.ORIENTATION_HORIZONTAL
defaults = [
('off_text', '', 'The pattern for the text if no players are found.'),
('on_text_play', '{}', 'The pattern for the text if music is playing.'),
('on_text_pause', '{}', 'The pattern for the text if music is paused.'),
('on_text_stop', '{}', 'The pattern for the text if music is stopped.'),
('update_interval', 1, 'The update interval.'),
]
player_icons = {
'spotify': '',
'vlc': '',
'firefox': '',
}
custom_player_data = {
'firefox': {
'showing': False,
'title': '',
'state': Status.STOPPED,
}
}
def __init__(self, **config):
super(MediaWidget, self).__init__(**config)
self.add_defaults(MediaWidget.defaults)
self.surfaces = {}
def cmd_update_custom_player(self, player_name, data):
# Update firefox player
if player_name == "firefox":
if data['playing'] and data['muted']:
self.custom_player_data['firefox']['showing'] = True
self.custom_player_data['firefox']['state'] = MediaWidget.Status.PAUSED
self.custom_player_data['firefox']['title'] = data['title']
elif data['playing'] and not data['muted']:
self.custom_player_data['firefox']['showing'] = True
self.custom_player_data['firefox']['state'] = MediaWidget.Status.PLAYING
self.custom_player_data['firefox']['title'] = data['title']
elif not data['playing'] and data['muted']:
self.custom_player_data['firefox']['showing'] = True
self.custom_player_data['firefox']['state'] = MediaWidget.Status.STOPPED
self.custom_player_data['firefox']['title'] = data['title']
elif not data['playing'] and not data['muted']:
self.custom_player_data['firefox']['showing'] = False
self.custom_player_data['firefox']['state'] = MediaWidget.Status.OFFLINE
self.custom_player_data['firefox']['title'] = data['title']
def _get_players(self):
players = []
# Playerctl players
command = ["playerctl", "-l"]
result = self.call_process(command)
if result:
players.extend([x for x in result.split("\n") if x])
# Custom players - Firefox
if self.custom_player_data['firefox']['showing']:
players.append('firefox')
if players:
return players
else:
return None
def _get_info(self):
players = self._get_players()
if not players:
return {}
else:
result = {}
for player in players:
if player in self.custom_player_data.keys():
# Custom player -- Firefox
if player == "firefox":
result[player] = [self.custom_player_data['firefox']['state'], self.custom_player_data['firefox']['title']]
# Other custom players -- generic attempt with error catching
else:
try:
result[player] = [self.custom_player_data[player]['state'],
self.custom_player_data[player]['title']]
except KeyError:
pass
else:
# PlayerCtl player
command = ["playerctl", "-p", player, "status"]
cmd_result = self.call_process(command).strip()
text = "Unknown"
if cmd_result in ["Playing", "Paused"]:
artist = self.call_process(['playerctl', '-p', player, 'metadata', 'artist']).strip()
title = self.call_process(['playerctl', '-p', player, 'metadata', 'title']).strip()
if artist and title:
text = "{} - {}".format(artist, title)
elif artist:
text = artist
elif title:
text = title
if cmd_result == "Playing":
result[player] = [MediaWidget.Status.PLAYING, text]
elif cmd_result == "Paused":
result[player] = [MediaWidget.Status.PAUSED, text]
elif cmd_result == "Stopped":
result[player] = [MediaWidget.Status.STOPPED, ""]
return result
def _get_formatted_text(self, status):
if status[0] == MediaWidget.Status.PLAYING:
return self.on_text_play.format(status[1])
elif status[0] == MediaWidget.Status.PAUSED:
return self.on_text_pause.format(status[1])
elif status[0] == MediaWidget.Status.STOPPED:
return self.on_text_stop.format(status[1])
else:
return "Unknown"
def poll(self):
text = []
status = self._get_info()
if not status:
return self.off_text
else:
for player in status.keys():
icon = self.player_icons.get(player, player)
logger.warning([player, status[player]])
text.append("{} {}".format(icon, self._get_formatted_text(status[player])))
return " | ".join(text) if text else self.off_text
class AudioVisualizerWidget(_Graph):
"""Display Audio Visualization graph"""
orientations = base.ORIENTATION_HORIZONTAL
defaults = [
("audio_channel", "default", "Which audio channel to show"),
]
stream = None
fixed_upper_bound = True
def __init__(self, **config):
_Graph.__init__(self, **config)
self.add_defaults(AudioVisualizerWidget.defaults)
self.maxvalue = 100
self.samples = 1024
self.max_observed = 1
# initialize communication queue
self.q = Queue()
self.t = None
self.stream = None
self.tries = 0
def initialize_stream(self):
# initialize portaudio
p = pyaudio.PyAudio()
try:
self.stream = p.open(format=pyaudio.paInt16, channels=1, rate=44100, input=True, frames_per_buffer=self.samples)
# initialize thread
self.t = Thread(target=self.process, args=[self, self.q])
self.t.start()
except OSError as e:
logger.warning("Could not open audio stream: ".format(e))
self.tries += 1
@staticmethod
def process(widget: 'AudioVisualizerWidget', queue: Queue):
item = queue.get()
if widget.max_observed > 100:
widget.max_observed -= 100
# Discard all available frames
avail = widget.stream.get_read_available()
while avail > 1000:
_ = widget.stream.read(avail)
logger.debug("Discarded {} frames".format(avail))
avail = widget.stream.get_read_available()
if avail > 100:
data = widget.stream.read(widget.samples)
numpydata = numpy.abs(numpy.fromstring(data, dtype=numpy.int16))
if numpy.max(numpydata) > widget.max_observed:
widget.max_observed = numpy.max(numpydata)
numpydata = numpydata * (100 / widget.max_observed)
numpydata = AudioVisualizerWidget.window_rms(numpydata, 25)
widget.values = list(numpydata)
print(widget.values)
else:
widget.values = [0]*1024
@staticmethod
def window_rms(a, window_size):
a2 = numpy.power(a, 2)
window = numpy.ones(window_size) / float(window_size)
return numpy.sqrt(numpy.convolve(a2, window, 'valid'))
def update_graph(self):
if not self.stream and self.tries < 10:
self.initialize_stream()
else:
if self.q.empty():
self.q.put(True)
self.draw()
class KuroCurrentLayoutIcon(CurrentLayoutIcon):
def _get_layout_names(self):
names = super(KuroCurrentLayoutIcon, self)._get_layout_names()
from kuro.utils import layouts as kuro_layouts
from libqtile.layout.base import Layout
klayouts = [
layout_class_name.lower()
for layout_class, layout_class_name
in map(lambda x: (getattr(kuro_layouts, x), x), dir(kuro_layouts))
if isinstance(layout_class, six.class_types) and issubclass(layout_class, Layout)
]
names.extend(klayouts)
return list(set(names))

View file

@ -71,13 +71,20 @@ def handle_focus_change(theme):
'middle': Color.RED, 'middle': Color.RED,
'right': Color.WHITE, 'right': Color.WHITE,
})) }))
elif "chromium" in wm_class[0]: elif "Firefox" in wm_class[1]:
BacklightController.reset_backlight(state=KeyboardState(values={ BacklightController.reset_backlight(state=KeyboardState(values={
'brightness': Brightness.FULL, 'brightness': Brightness.FULL,
'left': Color.WHITE, 'left': Color.WHITE,
'middle': Color.BLUE, 'middle': Color.BLUE,
'right': Color.WHITE, 'right': Color.WHITE,
})) }))
elif "Thunderbird" in wm_class[1]:
BacklightController.reset_backlight(state=KeyboardState(values={
'brightness': Brightness.FULL,
'left': Color.BLUE,
'middle': Color.WHITE,
'right': Color.BLUE,
}))
elif "pycharm" in wm_class[1]: elif "pycharm" in wm_class[1]:
BacklightController.reset_backlight(state=KeyboardState(values={ BacklightController.reset_backlight(state=KeyboardState(values={
'brightness': Brightness.MEDIUM, 'brightness': Brightness.MEDIUM,
@ -92,6 +99,32 @@ def handle_focus_change(theme):
'middle': Color.WHITE, 'middle': Color.WHITE,
'right': Color.BLUE, 'right': Color.BLUE,
})) }))
elif "quasselclient" in wm_class[0]:
BacklightController.reset_backlight(state=KeyboardState(values={
'brightness': Brightness.MEDIUM,
'left': Color.BLUE,
'middle': Color.BLUE,
'right': Color.BLUE,
}))
elif "remmina" in wm_class[0]:
BacklightController.reset_backlight(state=KeyboardState(values={
'brightness': Brightness.FULL,
'left': Color.RED,
'middle': Color.GREEN,
'right': Color.BLUE,
}))
elif "spotify" in wm_class[0]:
BacklightController.reset_backlight(state=KeyboardState(values={
'brightness': Brightness.FULL,
'left': Color.GREEN,
'middle': Color.GREEN,
'right': Color.GREEN,
}))
elif "pulseeffects" in wm_class[0]:
BacklightController.reset_backlight(state=KeyboardState(values={
'brightness': Brightness.FULL,
'mode': Mode.RANDOM,
}))
else: else:
BacklightController.reset_backlight() BacklightController.reset_backlight()