dotfiles/.local/bin/gpu_psystray.py
2025-05-28 18:33:04 +02:00

237 lines
6.9 KiB
Python
Executable File

#!/usr/bin/env python3
import time
import dbus
import dbus.mainloop.glib
import os
from gi.repository import GLib, Notify
import pystray
from PIL import Image
import threading
import queue
import subprocess
import time
start_time = time.time()
# Código de inicialización
print(f"Tiempo después de la inicialización: {
time.time() - start_time} segundos")
# Define the paths to the PNG icons
ICON_PATHS = {
"nvidia": "/home/teraflops/Icons/nvidia.png",
"integrated": "/home/teraflops/Icons/amd.png",
}
# Global variables
systray_icon = None
update_queue = queue.Queue()
# Function to interpret the numerical status into a clearer message
def interpret_gpu_status(status):
if status == 0:
return "nvidia"
elif status == 1:
return "integrated"
else:
return None # Ignore "switching mode" and other unknown statuses
# Function to update the systray icon
def update_systray_icon(status_message):
icon_path = ICON_PATHS.get(status_message)
if icon_path and os.path.exists(icon_path):
try:
image = Image.open(icon_path)
# Put the update information in the queue
update_queue.put((image, f"GPU: {status_message.capitalize()}"))
print(f"Queued systray icon update to {status_message}")
except Exception as e:
print(f"Error preparing systray icon update: {e}")
else:
print(f"No icon found for status: {status_message}")
# Callback for `NotifyGfxStatus`
def on_notify_gfx_status(status):
print(f"Callback `on_notify_gfx_status` invoked with status: {status}")
status_message = interpret_gpu_status(status)
# If the status is "nvidia" or "integrated", update the systray icon
if status_message:
print(f"GPU status changed: {status_message}")
update_systray_icon(status_message)
# Guardar el estado y el timestamp en /tmp
try:
with open("/tmp/gpu_mode", "w") as f:
f.write(status_message)
with open("/tmp/gpu_mode_timestamp", "w") as f:
f.write(str(int(time.time())))
print(f"Estado GPU guardado en /tmp/gpu_mode: {status_message}")
except Exception as e:
print(f"Error al escribir /tmp/gpu_mode o timestamp: {e}")
else:
print("Intermediate status detected, no action taken.")
def set_integrated(icon, item):
print("Setting GPU mode to Integrated...")
result = subprocess.run(
["/usr/bin/supergfxctl", "-m", "Integrated"],
capture_output=True,
text=True
)
output = result.stdout.strip()
error = result.stderr.strip()
# Crear y mostrar la notificación
if result.returncode == 0:
message = output if output else "Modo GPU cambiado a Integrado."
notification = Notify.Notification.new("Modo GPU Cambiado", message)
else:
message = error if error else "Error al cambiar a modo Integrado."
notification = Notify.Notification.new(
"Error al Cambiar Modo GPU", message)
notification.show()
print(message)
def set_hybrid(icon, item):
print("Setting GPU mode to Hybrid...")
result = subprocess.run(
["/usr/bin/supergfxctl", "-m", "Hybrid"],
capture_output=True,
text=True
)
output = result.stdout.strip()
error = result.stderr.strip()
# Crear y mostrar la notificación
if result.returncode == 0:
message = output if output else "Modo GPU cambiado a Híbrido."
notification = Notify.Notification.new("Modo GPU Cambiado", message)
else:
message = error if error else "Error al cambiar a modo Híbrido."
notification = Notify.Notification.new(
"Error al Cambiar Modo GPU", message)
notification.show()
print(message)
def set_dedicated(icon, item):
print("Setting GPU mode to Dedicated...")
result = subprocess.run(
["/usr/bin/supergfxctl", "-m", "AsusMuxDgpu"],
capture_output=True,
text=True
)
output = result.stdout.strip()
error = result.stderr.strip()
# Crear y mostrar la notificación
if result.returncode == 0:
message = output if output else "Modo GPU cambiado a Dedicado."
notification = Notify.Notification.new("Modo GPU Cambiado", message)
else:
message = error if error else "Error al cambiar a modo Dedicado."
notification = Notify.Notification.new(
"Error al Cambiar Modo GPU", message)
notification.show()
print(message)
# Initialize the D-Bus loop and signal handlers
def init_dbus_loop():
# Initialize the D-Bus main loop
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
# Connect to the system bus and get the object
bus = dbus.SystemBus()
proxy = bus.get_object("org.supergfxctl.Daemon", "/org/supergfxctl/Gfx")
# Subscribe to the `NotifyGfxStatus` signal
bus.add_signal_receiver(
on_notify_gfx_status,
dbus_interface="org.supergfxctl.Daemon",
signal_name="NotifyGfxStatus",
)
print("Monitoring GPU signals...")
# Start the main loop
loop = GLib.MainLoop()
loop.run()
# Function to create the systray icon
def create_systray_icon():
global systray_icon
# Use a default icon initially
default_status = "integrated"
default_icon_path = ICON_PATHS.get(default_status)
if default_icon_path and os.path.exists(default_icon_path):
image = Image.open(default_icon_path)
else:
# Create a blank icon if default not found
image = Image.new("RGB", (64, 64), color=(255, 0, 0))
# Define the menu
menu = pystray.Menu(
pystray.MenuItem("Integrated", set_integrated),
pystray.MenuItem("Hybrid", set_hybrid),
pystray.MenuItem("Dedicated", set_dedicated),
pystray.MenuItem("Salir", lambda icon, item: icon.stop())
)
systray_icon = pystray.Icon(
"gpu_status",
icon=image,
title=f"GPU: {default_status.capitalize()}",
menu=menu
)
# Function to check the queue and update the icon
def check_queue():
try:
while True:
new_image, new_title = update_queue.get_nowait()
systray_icon.icon = new_image
systray_icon.title = new_title
systray_icon.visible = True
print(f"Systray icon updated to {new_title}")
except queue.Empty:
pass
# Schedule the next check
threading.Timer(1, check_queue).start()
# Start checking the queue
check_queue()
# Start the systray icon
systray_icon.run()
def main():
# Inicializar Notify
Notify.init("GPU Mode Switcher")
# Start the D-Bus loop in a separate thread
dbus_thread = threading.Thread(target=init_dbus_loop)
dbus_thread.daemon = True
dbus_thread.start()
# Start the systray icon in the main thread
create_systray_icon()
if __name__ == "__main__":
main()