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

132 lines
4.4 KiB
Python
Executable File

#!/usr/bin/env python3
import dbus
from gi.repository import AppIndicator3
from gi.repository import Gtk, GLib
import subprocess
import threading
import pulsectl # Asegúrate de tener pulsectl instalado
class VolumeApplet:
def __init__(self):
self.app = 'volume-applet'
# Define el icono inicial
self.indicator = AppIndicator3.Indicator.new(
self.app,
"audio-volume-medium", # Icono predeterminado
AppIndicator3.IndicatorCategory.APPLICATION_STATUS
)
self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
self.indicator.set_menu(self.create_menu())
# Icono inicial basado en el volumen actual
current_volume = self.get_current_volume()
self.update_icon(current_volume)
self.window = None # Ventana de la barra de volumen
# Iniciar el monitoreo de cambios de volumen en un hilo separado
self.pulse = pulsectl.Pulse('volume-applet')
self.pulse.event_mask_set('sink') # Monitorea cambios en los sinks
self.pulse.event_callback_set(self.on_pulse_event)
self.monitor_thread = threading.Thread(
target=self.pulse_event_listener, daemon=True)
self.monitor_thread.start()
def create_menu(self):
menu = Gtk.Menu()
# Agregar opción para abrir la barra de volumen vertical
volume_item = Gtk.MenuItem(label="Ajustar Volumen")
volume_item.connect("activate", self.show_volume_control)
menu.append(volume_item)
# Agregar opción para salir
quit_item = Gtk.MenuItem(label="Salir")
quit_item.connect("activate", Gtk.main_quit)
menu.append(quit_item)
menu.show_all()
return menu
def show_volume_control(self, source=None):
if self.window:
self.window.destroy()
self.window = Gtk.Window(title="Control de Volumen")
self.window.set_default_size(50, 200) # Barra vertical
self.window.set_border_width(10)
# Configurar la barra de volumen en orientación vertical
volume_scale = Gtk.Scale.new_with_range(
Gtk.Orientation.VERTICAL, 0, 100, 1)
volume_scale.set_value(self.get_current_volume())
volume_scale.connect("value-changed", self.on_volume_changed)
self.window.add(volume_scale)
self.window.show_all()
def on_volume_changed(self, scale):
volume = int(scale.get_value())
subprocess.run(["pamixer", "--set-volume", str(volume)])
# Actualizar el icono y el tooltip en función del nuevo volumen
self.update_icon(volume)
def get_current_volume(self):
try:
result = subprocess.check_output(["pamixer", "--get-volume"])
return int(result.strip())
except subprocess.CalledProcessError:
return 50 # Valor por defecto si pamixer falla
def update_icon(self, volume):
"""Actualiza el icono y el tooltip basado en el nivel de volumen."""
if volume == 0:
icon_name = "volume-0.png"
elif 1 <= volume <= 33:
icon_name = "volume-1.png"
elif 34 <= volume <= 66:
icon_name = "volume-2.png"
elif 67 <= volume <= 75:
icon_name = "volume-3.png"
else:
icon_name = "volume-4.png"
# Ruta completa del icono
icon_path = f"/home/teraflops/Icons/{icon_name}"
tooltip = f"Volumen Actual: {volume}%"
self.indicator.set_icon_full(icon_path, tooltip)
# Establecer el tooltip explícitamente
self.indicator.set_title(tooltip)
def pulse_event_listener(self):
"""Escucha eventos de PulseAudio en un hilo separado."""
try:
self.pulse.event_listen()
except Exception as e:
print(f"Error al escuchar eventos de PulseAudio: {e}")
def on_pulse_event(self, event):
"""Callback para manejar eventos de PulseAudio."""
if event.t == 'change':
# Verifica si el cambio es relevante para el volumen
if event.facility == 'sink':
# Obtén el volumen actual
current_volume = self.get_current_volume()
# Actualiza el icono y el tooltip en el hilo principal
GLib.idle_add(self.update_icon, current_volume)
def __del__(self):
if hasattr(self, 'pulse'):
self.pulse.close()
def main():
app = VolumeApplet()
Gtk.main()
if __name__ == "__main__":
main()