#!/usr/bin/env python2 # -*- coding: utf-8 -*- import os, sys import dbus import gobject import subprocess from dbus.mainloop.glib import DBusGMainLoop import sys from functools import partial import time home = os.path.expanduser('~') safe = { 'sink': None, 'muted': False, 'volume': 0, 'baseVolume': 0, } BAR_WIDTH = 50 def output_volume(vol): print('^cs()') bar = min(vol * BAR_WIDTH / 100, BAR_WIDTH) print('^fg(#999)^r(%dx6)^fg(#444)^r(%dx6)^fg()' % (bar, BAR_WIDTH - bar)) sys.stdout.flush() def output_mute(mute): if mute: print('^tw()^fg(#FF0000)^i(%s/.dzen2/icons/vol-mute.xbm)' % home) else: print('^tw()^fg()^i(%s/.dzen2/icons/vol-hi.xbm)' % home) sys.stdout.flush() def dbus_connect(): if 'PULSE_DBUS_SERVER' in os.environ: address = os.environ['PULSE_DBUS_SERVER'] else: bus = dbus.SessionBus() server_lookup = bus.get_object("org.PulseAudio1", "/org/pulseaudio/server_lookup1") address = server_lookup.Get("org.PulseAudio.ServerLookup1", "Address", dbus_interface="org.freedesktop.DBus.Properties") return dbus.connection.Connection(address) def update_volume(volumes, force=False): volume = (max(volumes) * 100)/safe['baseVolume'] if safe['volume'] != volume or force: safe['volume'] = volume output_volume(safe['volume']) def update_muted(muted, force=False): if safe['muted'] != muted or force: safe['muted'] = muted output_mute(muted) def signal_cb(*args, **kwargs): msg = kwargs['msg'] bus = kwargs['bus'] if msg.get_interface() == 'org.PulseAudio.Core1.Device': if safe['sink'] is not None and msg.get_path() != safe['sink']: return if msg.get_member() == 'VolumeUpdated': update_volume(args[0]) elif msg.get_member() == 'MuteUpdated': update_muted(args[0]) elif msg.get_interface() == 'org.PulseAudio.Core1': if msg.get_member() == 'FallbackSinkUpdated': init(bus, args[0]) else: print msg def init(bus, sink=None): if sink is not None: safe['sink'] = sink elif len(sys.argv) > 1: safe['sink'] = sys.argv[1] core = bus.get_object(object_path="/org/pulseaudio/core1") safe['sink'] = core.Get('org.PulseAudio.Core1', 'FallbackSink') sink = bus.get_object('org.PulseAudio.Core1.Device', safe['sink']) safe['baseVolume'] = sink.Get('org.PulseAudio.Core1.Device', 'BaseVolume') update_muted(sink.Get('org.PulseAudio.Core1.Device', 'Mute'), True) update_volume(sink.Get('org.PulseAudio.Core1.Device', 'Volume'), True) def setup(loop, conn=None): bus = None while True: try: if conn is not None: time.sleep(2) bus = dbus_connect() break except: if conn is None: break if bus is None: print "Could not connect to dbus!" sys.exit(1) bus.call_on_disconnection(partial(setup, loop)) init(bus) bus.add_signal_receiver(partial(signal_cb, bus=bus), message_keyword='msg') core = bus.get_object(object_path="/org/pulseaudio/core1") core.ListenForSignal('org.PulseAudio.Core1.Device.VolumeUpdated', dbus.Array(signature='o')) core.ListenForSignal('org.PulseAudio.Core1.Device.MuteUpdated', dbus.Array(signature='o')) if len(sys.argv) <= 1: core.ListenForSignal('org.PulseAudio.Core1.FallbackSinkUpdated', dbus.Array(signature='o')) loop.run() if __name__ == '__main__': DBusGMainLoop(set_as_default=True) loop = gobject.MainLoop() setup(loop)