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

167 lines
4.2 KiB
Python
Executable File

#!/usr/bin/env python3
import os
import subprocess
import sys
from PIL import Image
import pystray
from pystray import MenuItem as item
import threading
import time
# Ruta a los iconos
ICON_PATH = "/home/teraflops/Icons/"
def get_volume():
"""Obtiene el volumen actual usando pamixer."""
try:
result = subprocess.check_output(["pamixer", "--get-volume"])
return int(result.strip())
except subprocess.CalledProcessError:
return 50 # Valor por defecto si pamixer falla
def set_volume(volume):
"""Establece el volumen usando pamixer."""
subprocess.run(["pamixer", "--set-volume", str(volume)])
def toggle_mute():
"""Alterna el mute usando pamixer."""
subprocess.run(["pamixer", "--toggle-mute"])
def get_icon(volume):
"""Retorna el icono adecuado basado en el volumen."""
if volume == 0:
icon_file = "volume-mute.png"
elif 1 <= volume <= 33:
icon_file = "volume-low.png"
elif 34 <= volume <= 66:
icon_file = "volume-medium.png"
else:
icon_file = "volume-high.png"
return Image.open(os.path.join(ICON_PATH, icon_file))
def create_menu(icon, volume):
"""Crea el menú para el icono de la bandeja."""
return (
item('Ajustar Volumen', None), # Este ítem no hace nada
item('Salir', on_quit)
)
def on_quit(icon, item):
"""Maneja la opción de salir."""
icon.stop()
sys.exit()
def update_icon(icon):
"""Actualiza el icono basado en el volumen actual."""
volume = get_volume()
icon.icon = get_icon(volume)
def on_click(icon, item):
"""Maneja el clic izquierdo para mostrar el control de volumen."""
# Aquí puedes implementar una ventana flotante para ajustar el volumen
# Por simplicidad, este ejemplo solo alterna el mute
toggle_mute()
update_icon(icon)
def on_scroll(icon, direction):
"""Ajusta el volumen basado en la dirección del scroll."""
volume = get_volume()
if direction == "up":
new_volume = min(volume + 5, 100)
elif direction == "down":
new_volume = max(volume - 5, 0)
set_volume(new_volume)
update_icon(icon)
def run_tray():
"""Configura y ejecuta el icono de la bandeja."""
icon = pystray.Icon("volume-applet")
icon.icon = get_icon(get_volume())
icon.title = "Control de Volumen"
# Definir el menú
icon.menu = pystray.Menu(
item('Salir', on_quit)
)
# Asignar eventos de clic y scroll
icon.run_detached = False # Ejecutar en el hilo principal
def on_left_click(icon, item):
on_click(icon, item)
def on_right_click(icon, item):
# Los eventos de scroll no están directamente soportados, así que usaremos atajos
pass
icon.visible = True
# Asignar evento de clic izquierdo
icon.visible = True
icon.update_menu = False
icon.run(lambda icon: None)
def main():
"""Función principal para configurar el tray."""
icon = pystray.Icon("volume-applet")
icon.icon = get_icon(get_volume())
icon.title = "Control de Volumen"
# Crear menú
icon.menu = pystray.Menu(
item('Salir', on_quit)
)
# Definir acciones
icon.visible = True
# Asignar eventos de clic
icon.run(setup=lambda icon: icon.visible=True)
# Manejar clic izquierdo para alternar mute
def on_left_click(icon, button, pressed):
if button == pystray.Button.LEFT and pressed:
on_click(icon, None)
# Manejar eventos de scroll (pystray no los soporta directamente, así que usaremos un workaround)
# Implementaremos una forma alternativa de detectar scroll usando un hilo
def listen_for_scroll():
import pynput.mouse as mouse
from pynput.mouse import Listener
def on_scroll(x, y, dx, dy):
if dy > 0:
on_scroll_icon("up")
elif dy < 0:
on_scroll_icon("down")
with Listener(on_scroll=on_scroll) as listener:
listener.join()
def on_scroll_icon(direction):
on_scroll(icon, direction)
# Iniciar el hilo para escuchar el scroll
scroll_thread = threading.Thread(target=listen_for_scroll, daemon=True)
scroll_thread.start()
# Iniciar el icono
icon.run()
if __name__ == "__main__":
main()