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

@ -1,11 +1,18 @@
import os
import re
import subprocess
from asyncio import Queue
from threading import Thread
from time import sleep
import cairocffi
import notify2
import numpy
import pyaudio
import six
from libqtile import widget, bar
from libqtile.widget.currentlayout import CurrentLayoutIcon
from libqtile.widget.graph import _Graph
from libqtile.window import Internal
from libqtile.bar import Bar
from libqtile.utils import catch_exception_and_warn, UnixCommandNotFound
@ -38,12 +45,34 @@ def is_running(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):
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():
@ -217,18 +246,18 @@ class AppLauncherIcon(Image):
spawn_popup(self.qtile, self.offsetx, self.offsety, "Hovered over AppLauncherIcon!")
class CheckUpdatesYaourt(CheckUpdates):
class CheckUpdatesYay(CheckUpdates):
def __init__(self, **config):
super(CheckUpdatesYaourt, self).__init__(**config)
# Override command and output with yaourt command
self.cmd = "yaourt -Qua".split()
self.status_cmd = "yaourt -Qua".split()
self.update_cmd = "sudo yaourt -Sya".split()
super(CheckUpdatesYay, self).__init__(**config)
# Override command and output with yay command
self.cmd = "yay -Qua".split()
self.status_cmd = "yay -Qua --color never".split()
self.update_cmd = "sudo yay".split()
self.subtr = 0
def _check_updates(self):
#subprocess.check_output(self.update_cmd)
res = super(CheckUpdatesYaourt, self)._check_updates()
res = super(CheckUpdatesYay, self)._check_updates()
return res
def button_press(self, x, y, button):
@ -253,6 +282,7 @@ class CheckUpdatesYaourt(CheckUpdates):
elif button == BUTTON_MIDDLE and self.execute is not None:
subprocess.Popen(self.execute, shell=True)
class KuroBatteryIcon(BatteryIcon):
status_cmd = "acpi"
@ -265,6 +295,7 @@ class KuroBatteryIcon(BatteryIcon):
output
)
class PulseVolumeWidget(Volume):
defaults = [
@ -535,3 +566,255 @@ class ThermalSensorWidget(ThermalSensor):
command.append("-f")
sensors_out = self.call_process(command)
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,
'right': Color.WHITE,
}))
elif "chromium" in wm_class[0]:
elif "Firefox" in wm_class[1]:
BacklightController.reset_backlight(state=KeyboardState(values={
'brightness': Brightness.FULL,
'left': Color.WHITE,
'middle': Color.BLUE,
'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]:
BacklightController.reset_backlight(state=KeyboardState(values={
'brightness': Brightness.MEDIUM,
@ -92,6 +99,32 @@ def handle_focus_change(theme):
'middle': Color.WHITE,
'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:
BacklightController.reset_backlight()