Mercurial > system76-keyboard-colors
changeset 3:eb2aa09653bd default tip
beginnings of CPU colors, daemon
author | Brad Greco <brad@bgreco.net> |
---|---|
date | Mon, 29 Mar 2021 20:27:09 -0400 |
parents | 091a1f59a79c |
children | |
files | daemon.py keyboard_colors/color_profile.py keyboard_colors/custom/#custom.glade# keyboard_colors/custom/custom.glade keyboard_colors/custom/custom.py keyboard_colors/psutilx/__init__.py keyboard_colors/psutilx/psutilx.py main.py ui/main_window.py |
diffstat | 8 files changed, 286 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/daemon.py Mon Mar 29 20:27:09 2021 -0400 @@ -0,0 +1,46 @@ +from keyboard_colors.color_profile import ProfileManager, Color +from threading import Event +import keyboard_colors +import keyboard_colors.psutilx.psutilx +import signal + + +class KeyboardColorDaemon: + + transition_wait_time = 100 + + def __init__(self): + signal.signal(signal.SIGINT, self.signal_handler) + self.profile_manager = ProfileManager() + # self.run(keyboard_colors.custom.custom.ColorProfile()) + self.run(keyboard_colors.psutilx.psutilx.ColorProfile()) + + def run(self, profile): + # color = profile.color + color = Color.from_hex('#FF3300') + wait_time = profile.frequency_time - profile.transition_time + transition_steps = int(profile.transition_time / self.transition_wait_time) + + # print(Color.get_step_color(color, profile.next_color(), .3)) + # return + + self.break_event = Event() + while not self.break_event.is_set(): + next_color = profile.next_color() + step_colors = Color.get_steps(color, next_color, transition_steps) + + for step_color in step_colors: + print(step_color) + with open('/sys/devices/platform/system76/leds/system76::kbd_backlight/color_left', 'w') as f: + f.write(step_color.to_hex()) + self.break_event.wait(self.transition_wait_time / 1000) + + color = next_color + self.break_event.wait(wait_time / 1000) + + def signal_handler(self, signal, frame): + self.break_event.set() + + +if __name__ == "__main__": + KeyboardColorDaemon()
--- a/keyboard_colors/color_profile.py Tue Mar 02 20:17:36 2021 -0500 +++ b/keyboard_colors/color_profile.py Mon Mar 29 20:27:09 2021 -0400 @@ -1,8 +1,10 @@ +import colorsys import gi import importlib import json import os import pathlib +import re import sys import types import uuid @@ -19,6 +21,25 @@ def __init__(self): self.name = '' self.id = str(uuid.uuid4()) + self.transition_time = 1000 + self.frequency_time = 1000 + + def color_scale_value(self, value): + if value in self.color_scale: + return self.color_scale[value] + + thresholds = self.color_scale.keys() + thresholds_below = (i for i in thresholds if i < value) + thresholds_above = (i for i in thresholds if i > value) + threshold_below = max(thresholds_below, default=min(thresholds)) + threshold_above = min(thresholds_above, default=max(thresholds)) + + percent = value / (threshold_above - threshold_below) + return Color.get_step_color( + self.color_scale[threshold_below], + self.color_scale[threshold_above], + percent + ) def build_settings_ui(self): glade_file = sys.modules[self.__module__].__file__.replace('.py', '.glade') @@ -84,3 +105,84 @@ def get_profile(self, profile_id): return self.get_profiles()[profile_id] + + +class Color: + + def __init__(self, r, g, b): + self.r = r + self.g = g + self.b = b + + @staticmethod + def from_hsv(h, s, v): + return Color(*colorsys.hsv_to_rgb(h, s, v)) + + def to_hsv(self): + return colorsys.rgb_to_hsv(self.r, self.g, self.b) + + @staticmethod + def from_hex(hex): + hex = hex.strip().strip('#').lower() + if not re.match('[0-9a-f]{6}', hex): + raise ValueError('Invalid hex color string: ' + hex) + + r = int(hex[0:2], 16) / 255 + g = int(hex[2:4], 16) / 255 + b = int(hex[4:6], 16) / 255 + + return Color(r, g, b) + + def to_hex(self): + return format(int(self.r * 255), '02x') \ + + format(int(self.g * 255), '02x') \ + + format(int(self.b * 255), '02x') + + @staticmethod + def get_steps(start_color, end_color, step_count): + # (start_h, start_s, start_v) = start_color.to_hsv() + # (end_h, end_s, end_v) = end_color.to_hsv() + + # # Find the shortest distance between the two hues. + # if abs(start_h - end_h) < 0.5: + # h_step = (end_h - start_h) / step_count + # else: + # h_step = (1 - abs(end_h - start_h)) / step_count + # if (start_h < end_h): + # h_step = h_step * -1 + + # steps = [] + # for i in range(0, step_count): + # h = (start_h + h_step * i) % 1 + # s = start_s + (end_s - start_s) / step_count * i + # v = start_v + (end_v - start_v) / step_count * i + # steps.append(Color.from_hsv(h, s, v)) + + steps = [] + for i in range(0, step_count): + percent = i / step_count + steps.append(Color.get_step_color(start_color, end_color, percent)) + + return steps + + @staticmethod + def get_step_color(start_color, end_color, percent): + (start_h, start_s, start_v) = start_color.to_hsv() + (end_h, end_s, end_v) = end_color.to_hsv() + + # Find the shortest distance between the two hues. + if abs(start_h - end_h) < 0.5: + h_diff = end_h - start_h + else: + h_diff = 1 - abs(end_h - start_h) + if (start_h < end_h): + h_diff = h_diff * -1 + + h = (start_h + h_diff * percent) % 1 + s = start_s + (end_s - start_s) * percent + v = start_v + (end_v - start_v) * percent + + return Color.from_hsv(h, s, v) + + def __repr__(self): + return 'Color #' + self.to_hex()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/keyboard_colors/custom/#custom.glade# Mon Mar 29 20:27:09 2021 -0400 @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.22.2 --> +<interface> + <requires lib="gtk+" version="3.20"/> + <object class="GtkBox" id="edit_profile_container"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkGrid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkColorButton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkCheckButton"> + <property name="label" translatable="yes">checkbutton</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkSpinButton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> +</interface>
--- a/keyboard_colors/custom/custom.glade Tue Mar 02 20:17:36 2021 -0500 +++ b/keyboard_colors/custom/custom.glade Mon Mar 29 20:27:09 2021 -0400 @@ -7,10 +7,44 @@ <property name="can_focus">False</property> <property name="orientation">vertical</property> <child> - <object class="GtkLabel"> + <object class="GtkGrid"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="label" translatable="yes">label</property> + <child> + <object class="GtkColorButton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> </object> <packing> <property name="expand">False</property> @@ -18,11 +52,5 @@ <property name="position">0</property> </packing> </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> </object> </interface>
--- a/keyboard_colors/custom/custom.py Tue Mar 02 20:17:36 2021 -0500 +++ b/keyboard_colors/custom/custom.py Mon Mar 29 20:27:09 2021 -0400 @@ -1,4 +1,4 @@ -from keyboard_colors.color_profile import ColorProfileBase +from keyboard_colors.color_profile import ColorProfileBase, Color class ColorProfile(ColorProfileBase): @@ -7,3 +7,7 @@ def __init__(self): super().__init__() + self.color = Color.from_hex('#FF3300') + + def next_color(self): + return Color.from_hex('#FF0033')
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/keyboard_colors/psutilx/psutilx.py Mon Mar 29 20:27:09 2021 -0400 @@ -0,0 +1,17 @@ +import psutil +from keyboard_colors.color_profile import ColorProfileBase, Color + + +class ColorProfile(ColorProfileBase): + + type_name = 'Custom colors' + color_scale = { + 0: Color.from_hex('#00FF00'), + 100: Color.from_hex('#FF0000'), + } + + def __init__(self): + super().__init__() + + def next_color(self): + return self.color_scale_value(psutil.cpu_percent())
--- a/main.py Tue Mar 02 20:17:36 2021 -0500 +++ b/main.py Mon Mar 29 20:27:09 2021 -0400 @@ -1,7 +1,9 @@ from ui.main_window import MainWindow + def main(): MainWindow().init() + if __name__ == "__main__": main()
--- a/ui/main_window.py Tue Mar 02 20:17:36 2021 -0500 +++ b/ui/main_window.py Mon Mar 29 20:27:09 2021 -0400 @@ -1,3 +1,4 @@ +import itertools import gi import os from keyboard_colors.color_profile import ProfileManager @@ -50,6 +51,10 @@ window.show_all() Gtk.main() + def load_color_profiles(self): + for profile in self.profile_manager.get_profiles().values(): + self.color_profile_list_store.append([profile.id, profile.name]) + def create_profile(self, widget, profile_type): # todo move to profile manager profile = profile_type() @@ -61,7 +66,8 @@ self.builder.get_object('edit_profile_name_entry').grab_focus() def edit_profile(self, profile): - self.builder.get_object('edit_profile_box').show() + edit_profile_box = self.builder.get_object('edit_profile_box') + edit_profile_box.show() self.builder.get_object('edit_profile_type_name_label').set_text(profile.type_name) self.builder.get_object('edit_profile_name_entry').set_text(profile.name) @@ -71,6 +77,22 @@ edit_profile_details_box.remove(child) edit_profile_details_box.add(profile.build_settings_ui()) + edit_profile_entries = self.find_descendents(edit_profile_box, Gtk.Entry) + pass + + def find_descendents(self, widget, type): + if isinstance(widget, type): + return [widget] + + try: + matches = [] + for child in widget.get_children(): + matches = matches + self.find_descendents(child, type) + return matches + except AttributeError: + return [] + + def profile_tree_view_selection_changed(self, selection): (model, tree_iter) = selection.get_selected() profile_id = model.get_value(tree_iter, 0) @@ -85,10 +107,6 @@ def edit_profile_name_entry_focus_out(self, entry, event): pass - def load_color_profiles(self): - for profile in self.profile_manager.get_profiles().values(): - self.color_profile_list_store.append([profile.id, profile.name]) - class KeyboardSection(Gtk.Grid): def __init__(self, model):