def __init__(self): QtCore.QThread.__init__(self) self.pulse = Pulse('volume-mixer-monitor') self.__sinksInput = {} self.__sinksOutput = {}
def __init__(self, cm): self.pulse = Pulse() self.cm = cm self.pulse.event_mask_set('all') self.pulse.event_callback_set(self.state_change) self.pulse.event_listen(timeout=10)
def volume(): pulse = Pulse() for sink in pulse.sink_list(): if sink.description.lower().startswith('built-in'): volume = pulse.volume_get_all_chans(sink) return f"{100 * volume:.2f}" return 'n/a'
def __init__(self,args): # get arguments if 'allow_reload' in args: self.allow_reload = args.allow_reload else: self.allow_reload = False self.restart = args.internal_restart self.num_channels = args.num_channels self.pulse_mon = Pulse('pa2jack-monitor') self.pulse_act = Pulse('pa2jack-actor') # Get jack sink self.jack_sink = self._get_jack_sink() # Reload jack module with correct channels self.reload_jack_module(self.num_channels) # Unload module-remap-sink for m in self.pulse_act.module_list(): if m.name == "module-remap-sink": self.pulse_act.module_unload(m.index) # Make our stereo remapping sinks self.remap_sink_modules = set([self._new_remap_sink("remap_sink_{}".format(i),start=i*2) for i in range(math.floor(self.num_channels/2))]) # Get sink indices self.remap_sinks = [s.index for s in self.pulse_act.sink_list() if s.owner_module in self.remap_sink_modules] # Listen to sink_input events and set handler self.pulse_mon.event_mask_set('sink_input') self.pulse_mon.event_callback_set(self._pa_event_handler)
def switch_pulse_default(prop): pulse = Pulse('qtile') current_default = getattr(pulse.server_info(), 'default_{}_name'.format(prop)) set_next = False things = getattr(pulse, '{}_list'.format(prop))() for thing in itertools.chain(things, things): if set_next: notify("Sound", "Default {} to {}".format(prop, thing.name)) pulse.default_set(thing) break elif thing.name == current_default: set_next = True if prop == 'sink': list_cmd = 'list-sink-inputs' move_cmd = 'move-sink-input' else: list_cmd = 'list-source-outputs' move_cmd = 'move-source-output' streams = subprocess.getoutput( "pacmd {} | grep index | awk '{{ print $2 }}'".format(list_cmd)) streams = [int(idx.strip()) for idx in streams.splitlines()] for stream in streams: cmd = "pacmd {cmd} {stream_id} {thing_id}".format(cmd=move_cmd, stream_id=stream, thing_id=thing.index) print(cmd) subprocess.check_call(shlex.split(cmd))
def __init__(self): self.pulse = Pulse('volume-controller') self.sinks = self.pulse.sink_list() self.seeed_sink = None for i in self.sinks: if "seeed" in i.name: self.seeed_sink = i break
def async_listener(self): self.pulse_d = Pulse('volume-daemon') self.pulse_d.event_mask_set('sink') # Glib.idle_add is to run the callback in the UI thread self.pulse_d.event_callback_set( lambda e: GLib.idle_add(self.callback) ) self.pulse_d.event_listen()
def async_listener(self): self.pulse_d = Pulse('volume-daemon') self.pulse_d.event_mask_set('sink', 'card') # Glib.idle_add is to run the callback in the UI thread self.pulse_d.event_callback_set(self.callback()) try: self.pulse_d.event_listen() except PulseDisconnected: time.sleep(3) self.pulse = Pulse('volume-control') self.async_listener()
def __init__(self): self.pulse = Pulse('volume-mixer') self.SinksMonitoringThread = SinksMonitoring() self.addSinkInput = self.SinksMonitoringThread.addSinkInput self.removeSinkInput = self.SinksMonitoringThread.removeSinkInput self.changeVolumeInput = self.SinksMonitoringThread.changeVolumeInput self.addSinkOutput = self.SinksMonitoringThread.addSinkOutput self.removeSinkOutput = self.SinksMonitoringThread.removeSinkOutput self.changeVolumeOutput = self.SinksMonitoringThread.changeVolumeOutput self.SinksMonitoringThread.start()
class Volume(StatusItem): def __init__(self, **kwargs): super().__init__() self.pulse = Pulse("deity i3bar statusitem") self.muted = True self.volume = -1 def refresh(self, periodic): if not periodic: sink = self.pulse.get_sink_by_name("@DEFAULT_SINK@") muted = bool(sink.mute) volume = int(round(sink.volume.value_flat * 100)) has_changed = muted != self.muted or volume != self.volume self.muted = muted self.volume = volume return has_changed return False def color(self): if self.muted: return Color.NEUTRAL return Color.POSITIVE def full_text(self): return "\uf028 " + str(self.volume) + "%"
def setup_platform(hass, config, add_entities, discovery_info=None): """Read in all of our configuration, and initialize the loopback switch.""" name = config.get(CONF_NAME) sink_name = config.get(CONF_SINK_NAME) source_name = config.get(CONF_SOURCE_NAME) host = config.get(CONF_HOST) port = config.get(CONF_PORT) hass.data.setdefault(DOMAIN, {}) server_id = str.format("{0}:{1}", host, port) if host: connect_to_server = server_id else: connect_to_server = None if server_id in hass.data[DOMAIN]: server = hass.data[DOMAIN][server_id] else: server = Pulse(server=connect_to_server, connect=False, threading_lock=True) hass.data[DOMAIN][server_id] = server add_entities([PALoopbackSwitch(name, server, sink_name, source_name)], True)
def __init__(self, sink_name: Optional[str] = None, volume_boost: bool = False): """ :param sink_name: Sink name to use. Empty uses default sink :param volume_boost: Whether to allow setting volume above 1.0 - uses software boost """ self._sink_name = sink_name self._sink_info: Optional[PulseSinkInfo] self._volume_boost = volume_boost self._pulse_connector = Pulse('py3status-pulse-connector', threading_lock=True) self._pulse_connector_lock = threading.Lock() self._volume: Optional[Volume] = None self._backend_thread = threading.Thread
def __init__(self, volctl): self._volctl = volctl self._pulse_loop_paused = False self._pulse = Pulse(client_name=PROGRAM_NAME, connect=False) self._poller_thread = None self._pulse_lock, self._pulse_hold = threading.Lock(), threading.Lock() signal.signal(signal.SIGALRM, self._handle_pulse_events) # Stream monitoring self._monitor_streams = {} self._read_cb_ctypes = c.PA_STREAM_REQUEST_CB_T(self._read_cb) self._samplespec = c.PA_SAMPLE_SPEC(format=c.PA_SAMPLE_FLOAT32BE, rate=25, channels=1) self._connect()
def get_volume(self): from pulsectl import Pulse with Pulse() as pulse: for input in pulse.sink_input_list(): if input.name == 'Spotify': self.spotify = input break self.volume = self.spotify.volume.value_flat
def __init__(self): self.pulse = Pulse("g15mediadaemon-spotifyapp") self.lastpid = -1 self.proxy = None self.player = None self.props = None if self.is_running(): pass
class pulseManagement(): def __init__(self): self.pulse = Pulse('volume-mixer') self.SinksMonitoringThread = SinksMonitoring() self.addSinkInput = self.SinksMonitoringThread.addSinkInput self.removeSinkInput = self.SinksMonitoringThread.removeSinkInput self.changeVolumeInput = self.SinksMonitoringThread.changeVolumeInput self.addSinkOutput = self.SinksMonitoringThread.addSinkOutput self.removeSinkOutput = self.SinksMonitoringThread.removeSinkOutput self.changeVolumeOutput = self.SinksMonitoringThread.changeVolumeOutput self.SinksMonitoringThread.start() def setVolSink(self, sink, vol): self.pulse.volume_set( sink, PulseVolumeInfo(vol / 100, len(sink.volume.values)))
def __init__(self, config, bt_device, sp_device, hs_device): """ Constructor for PulseAudio connection. :param config: """ self.config = config self.pulse_conn = PulseLib('maxime-manage_connection') self.ladspa_device = self._lookup_sink_input_device("LADSPA Stream") self.bt_device = bt_device self.hs_device = hs_device self.sp_device = sp_device
def _toggle_mute_sinks(self, sinks): """ Simply toggle the mute status of all given sinks. :param sinks: A list of sink objects. :return: Nothing. """ # Toggle the mute status with Pulse(threading_lock=True) as pulse: for sink in sinks: muted = bool(sink.mute) pulse.mute(sink, mute=not muted)
def __init__(self, i3, bat, bus, bar, display_title=True): self.out = '' self.datetime = '' self.workspaces = dict() self.volume = '' self.battery = '' self.i3 = i3 self.bar = bar self.display_title = display_title focused = i3.get_tree().find_focused() self.focusedWinTitle = focused.name if not focused.type == 'workspace' and display_title else '' self.currentBindingMode = '' self.mode = '' self.bat = bat self.bus = bus self.pulse = Pulse('my-client-name') self.outputs = '' self.notitle = " %%{R B-}%s%%{F-}" % self.bar.sep_left self.title = self.notitle self.set_outputs()
class RecordingIndicator(tk.Tk): def __init__(self): super().__init__() # Remove root window to avoid two windows # See : https://stackoverflow.com/a/48289343/1079254 self.withdraw() # Register overlay self.overlay = Overlay(self, cursor='hand1', borderwidth=2, relief='solid') # Init pulse (do not support multi-thread !) self.pulse = Pulse(self.__class__.__name__) self.recording_color = [ '#c4181a', '#f9df74', '#ea2b1f', ] # Custom methods def active_recording(self): self.overlay.icon.config(bg=random.choice(self.recording_color)) def inactive_recording(self): self.overlay.icon.config(bg='grey') def do_update(self): # Check status for recording indicator if self.is_sources_muted(): self.inactive_recording() else: self.active_recording() # Update tkinter window self.update_idletasks() self.update() def is_sources_muted(self): """Return False if at least one source is recording """ for source in self.pulse.source_list(): # Exclude monitors input if source.name.endswith('.monitor'): continue # mute = 0 mean recording if source.mute == 0: return False # No source recording found, all are muted return True
def __init__(self): super().__init__() # Remove root window to avoid two windows # See : https://stackoverflow.com/a/48289343/1079254 self.withdraw() # Register overlay self.overlay = Overlay(self, cursor='hand1', borderwidth=2, relief='solid') # Init pulse (do not support multi-thread !) self.pulse = Pulse(self.__class__.__name__) self.recording_color = [ '#c4181a', '#f9df74', '#ea2b1f', ]
def run(): loop = MainLoop() bus = SystemBus(mainloop=dglib.DBusGMainLoop()) dglib.threads_init() bat_object = bus.get_object( 'org.freedesktop.UPower', '/org/freedesktop/UPower/devices/battery_BAT1') bat = Interface(bat_object, 'org.freedesktop.DBus.Properties') lemonbar = Feeder(i3, bat, bus, bar, display_title) lemonbar.render_all() pulse = Pulse('event-printer') pulse.event_mask_set('sink', 'server') pulse.event_callback_set(lemonbar.on_volume_event) pulse_thread = Thread(target=pulse.event_listen, args=[0]) pulse_thread.daemon = True pulse_thread.start() bat_object.connect_to_signal( "PropertiesChanged", lemonbar.on_battery_event, dbus_interface='org.freedesktop.DBus.Properties') bat_thread = Thread(target=loop.run) bat_thread.daemon = True bat_thread.start() sched = BackgroundScheduler(daemon=True) sched.add_job(lemonbar.on_timedate_event, 'cron', second=0) sched.start() def shutdown(caller, e): bar.stop_bar(wbak, bar_pid) print(e.change) exit(0) def reload_bar(caller, data): global bar_pid bar.stop_bar(wbak, bar_pid) #print("reloading...") bar_pid = bar.start_bar() lemonbar.set_outputs() lemonbar.render_all(caller=caller, e=data) i3.on('workspace::urgent', lemonbar.on_workspace_event) i3.on('workspace::empty', lemonbar.on_workspace_event) if display_title: i3.on('window::title', lemonbar.on_window_title_change) i3.on('window::close', lemonbar.on_window_close) i3.on('window::focus', lemonbar.on_window_title_change) i3.on('workspace::focus', lemonbar.on_workspace_focus) else: i3.on('workspace::focus', lemonbar.on_workspace_event) i3.on('mode', lemonbar.on_binding_mode_change) i3.on('output', reload_bar) i3.on('shutdown', shutdown) i3.main()
def _activate_profile(): try: with Pulse(PULSE_NAME) as pulse: card = pulse.get_sink_by_name(card_name) pulse.card_profile_set(card, profile_name) except PulseIndexError: _LOGGER.error("Can't find %s profile %s", card_name, profile_name) raise PulseAudioError() except PulseError as err: _LOGGER.error( "Can't activate %s profile %s: %s", card_name, profile_name, err ) raise PulseAudioError()
def list_modules(pulseaudio: pulsectl.Pulse) -> List[pulsectl.PulseModuleInfo]: """ Shortcut for the pactl list modules short command. :return: String output from the command. """ listable_module_names = [ 'module-null-sink', 'module-loopback', 'module-null-source', 'module-remap-source', ] return [ module for module in pulseaudio.module_list() if module.name in listable_module_names ]
def _activate_profile(): try: with Pulse(PULSE_NAME) as pulse: card = pulse.get_card_by_name(card_name) pulse.card_profile_set(card, profile_name) except PulseIndexError as err: raise PulseAudioError( f"Can't find {card_name} profile {profile_name}", _LOGGER.error) from err except PulseError as err: raise PulseAudioError( f"Can't activate {card_name} profile {profile_name}: {err}", _LOGGER.error, ) from err
def _change_volume_sinks(self, sinks, rotation): """ Simple change the volume of all given sinks and display a notification. :param sinks: A list of sink objects. :param rotation: The amount and direction of the rotation. :return: Nothing. """ # Change the volume of the sinks with Pulse(threading_lock=True) as pulse: for sink in sinks: pulse.volume_change_all_chans(sink, rotation * 0.005) # Show the notification self._display_notification(sink)
def _get_sinks(self): """ Get a list of active pulseaudio sinks :return: List. A list containing all the active sink objects. """ # Get the list of input sinks with Pulse(threading_lock=True) as pulse: sinks = [ sink for sink in pulse.sink_input_list() if sink.proplist.get( "application.process.id", None) is not None ] # Return the list of active sinks return sinks
def _set_default(): try: with Pulse(PULSE_NAME) as pulse: if stream_type == StreamType.INPUT: # Get source and set it as default source = pulse.get_source_by_name(name) pulse.source_default_set(source) else: # Get sink and set it as default sink = pulse.get_sink_by_name(name) pulse.sink_default_set(sink) except PulseIndexError: _LOGGER.error("Can't find %s stream %s", source, name) raise PulseAudioError() except PulseError as err: _LOGGER.error("Can't set %s as stream: %s", name, err) raise PulseAudioError()
class Volume(ThreadModule): defaults = { "icon_low": Tools.sym(""), "icon_high": Tools.sym(""), "icon_muted": Tools.sym("") } def __init__(self, sink_index=0, template="$icon $volume", interval=2, **kwargs): super().__init__(template, interval, **kwargs) self.pulse = Pulse() self.sink_index = sink_index def clicked(self, button, *_): if button == 1: os.system("pavucontrol") elif button == 4 or button == 5: sink = self.pulse.sink_list()[0] cur_volume = self.pulse.volume_get_all_chans(sink) if button == 4 and cur_volume < 1.0: self.pulse.volume_change_all_chans(sink, 0.05) elif cur_volume > 0.0: self.pulse.volume_change_all_chans(sink, -0.05) self._set_values() self.trigger_refresh() def _set_values(self): info = self.pulse.sink_info(self.sink_index) volume = int(self.pulse.volume_get_all_chans(info)*100) self.values["volume"] = volume if info.mute == 1: self.values["icon"] = self.values["icon_muted"] self.props["color"] = "#ff0000" else: self.props["color"] = "#ffffff" if volume < 30: self.values["icon"] = self.values["icon_low"] else: self.values["icon"] = self.values["icon_high"] def repeat(self): self._set_values()
def _set_default(): source = sink = None try: with Pulse(PULSE_NAME) as pulse: if stream_type == StreamType.INPUT: # Get source and set it as default source = pulse.get_source_by_name(name) pulse.source_default_set(source) else: # Get sink and set it as default sink = pulse.get_sink_by_name(name) pulse.sink_default_set(sink) except PulseIndexError as err: raise PulseAudioError(f"Can't find {source} stream {name}", _LOGGER.error) from err except PulseError as err: raise PulseAudioError(f"Can't set {name} as stream: {err}", _LOGGER.error) from err
def __init__(self, observer): """ Initialize the super class and define the local members :param path: The path to the powermate device """ self._long_pressed = False self._pulse = Pulse(threading_lock=True) self._stored_app = None self._display = Display() # Connects to the default display self._note = pynotify.Notification("Volume", "0", "/usr/share/icons/Faenza/apps/48/" "gnome-volume-control.png") self._note.set_urgency(0) self._led = PowermateLed() self._led.max() self._rofi = Rofi() self._rofi.hide_scrollbar = True self._rofi.prompt = "App. name?"
def pulse_main(notify, mac): notify.update("Init pulse...") with Pulse('blue-audio-con') as pulse: notify.update("Pulse connected, looking for bluez card and sink") card = find_card(pulse, mac) notify.update("Resetting profiles for %s" % card) reset_card(pulse, card) sink = find_sink(mac, pulse) notify.update("Setting default sink to %s" % sink) pulse.sink_default_set(sink) # for input in pulse.sink_input_list(): # notify.update("Moving input %s to bluez sink" % input) # pulse.sink_input_move(input.index, sink.index) notify.update("Setting GNOME sink to %s" % sink.name) set_gnome_sink(sink.name) notify.update("Setting profile for %s to a2dp" % card) pulse.card_profile_set(card, "a2dp_sink")
class SpotifyApp(G15App): def __init__(self): self.pulse = Pulse("g15mediadaemon-spotifyapp") self.lastpid = -1 self.proxy = None self.player = None self.props = None if self.is_running(): pass def _get_iface(self): try: self.proxy = dbus.SessionBus().get_object('org.mpris.MediaPlayer2.spotify', '/org/mpris/MediaPlayer2') self.player = dbus.Interface(self.proxy, dbus_interface='org.mpris.MediaPlayer2.Player') self.props = dbus.Interface(self.proxy, dbus_interface='org.freedesktop.DBus.Properties') except DBusException: self.proxy = None self.player = None self.props = None for s in self.pulse.sink_input_list(): if s.name.lower() == "spotify": self.sink = s return True @property def name(self): return "spotify" def is_running(self): s = subprocess.Popen(["ps cxo pid,command --sort=start_time | grep spotify | grep -v \<defunct\>"], shell=True, stdout=subprocess.PIPE) for line in s.stdout: if self.lastpid != line or self.player is None: self.lastpid = line self._get_iface() return True self.lastpid = -1 self.proxy = None self.player = None self.props = None return False def get_metadata(self): if self.is_running(): md = self.props.Get('org.mpris.MediaPlayer2.Player', 'Metadata') return {v[6:].lower(): md[v] for v in md} return {} def tick(self, g15): if self.is_running(): position = self.props.Get('org.mpris.MediaPlayer2.Player', 'PlaybackStatus') md = self.get_metadata() g15.render_string("%s - %s" % (md['artist'][0], md['title']), 2, g15daemon.G15_TEXT_LARGE, 0, 0, True) g15.render_string("%s / %s" % (position, self.formatTime(md['length'])), 3, g15daemon.G15_TEXT_LARGE, 0, 0) else: g15.render_string("not running", 2, g15daemon.G15_TEXT_LARGE, 0, 0) def start(self): subprocess.Popen("/usr/bin/spotify", shell=True) def play_pause(self): if self.is_running(): self.player.PlayPause() else: self.start() def stop(self): if self.is_running(): self.player.Stop() def next(self): if self.is_running(): self.player.Next() def previous(self): if self.is_running(): self.player.Previous() def volume_down(self): if self.is_running(): nextvol = max(0.0, self.sink.volume.value_flat - 0.1) self.pulse.volume_set_all_chans(self.sink, nextvol) def volume_up(self): if self.is_running(): nextvol = min(1.0, self.sink.volume.value_flat + 0.1) self.pulse.volume_set_all_chans(self.sink, nextvol)
class Dispatcher: """ A simple dispatcher class that receive powermate events and dispatch them to the right controller """ def __init__(self, observer): """ Initialize the super class and define the local members :param path: The path to the powermate device """ self._long_pressed = False self._pulse = Pulse(threading_lock=True) self._stored_app = None self._display = Display() # Connects to the default display self._note = pynotify.Notification("Volume", "0", "/usr/share/icons/Faenza/apps/48/" "gnome-volume-control.png") self._note.set_urgency(0) self._led = PowermateLed() self._led.max() self._rofi = Rofi() self._rofi.hide_scrollbar = True self._rofi.prompt = "App. name?" def short_press(self): """ Manage the short_press event :return: None """ # Get the list of active sinks sinks = self._get_sinks() # Get the names of the apps linked to the sinks app_sinks = {"{} {}".format(sink.proplist.get("application.name"), sink.index): sink for sink in sinks} if len(app_sinks) > 1: # Display a menu to select the application to control try: res = self._rofi(app_sinks) except MenuError: return app_sink = res.value elif len(app_sinks) == 1: _, app_sink = app_sinks.popitem() else: app_sink = None # If successful if app_sink is not None: # Toggle the mute status of the selected sink self._toggle_mute_sinks([app_sink]) # Declare a new notification self._note.update("Toggle Mute status", "{}".format(app_sink.proplist.get("application.name")), "/usr/share/icons/Faenza/apps/48/gnome-volume-control.png") # Show the notification self._note.show() def long_press(self): """ For the moment this method simply toggles the lights on/off :return: A LedEvent class """ if self._long_pressed: # Re-initialize the state of the powermate self._long_pressed = False self._stored_app = None # Just light up the powermate self._led.max() else: # Get the list of active sinks sinks = self._get_sinks() # Get the names of the apps linked to the sinks app_sinks = {sink.proplist.get("application.name"):sink.proplist.get("application.process.binary") for sink in sinks if sink.proplist.get("application.process.binary") not in self._get_active_win_class()} if len(app_sinks) > 1: # Display a menu to select the application to control try: res = self._rofi(app_sinks) except MenuError: return app_name = res.value elif len(app_sinks) == 1: _, app_name = app_sinks.popitem() else: app_name = None # If successful if app_name is not None: # Store the list of sinks corresponding to the app name self._stored_app = app_name # Toggle the long press state self._long_pressed = True # Have the powermate pulse self._led.pulse() else: # Make sure the long press flag is off self._long_pressed = False # Stop the pulse self._led.max() def rotate(self, rotation): """ Manage the rotate event :param rotation: The direction of rotation negative->left, positive->right :return: None """ # Get the class of the active window win_cls = self._get_active_win_class() if win_cls is not None: # Change the volume of the sinks self._change_volume_sinks(self._get_app_sinks(win_cls), rotation) def push_rotate(self, rotation): """ Changes the volume of the sinks registered by the long_press event, according to the given rotation. :param rotation: The direction and amplitude of the rotation. (negative = left, positive = right). :return: Nothing. """ # Change the volume of the current sinks self._change_volume_sinks(self._get_app_sinks(self._stored_app), rotation) def _toggle_mute_sinks(self, sinks): """ Simply toggle the mute status of all given sinks. :param sinks: A list of sink objects. :return: Nothing. """ # Toggle the mute status for sink in sinks: muted = bool(sink.mute) self._pulse.mute(sink, mute=not muted) def _change_volume_sinks(self, sinks, rotation): """ Simple change the volume of all given sinks and display a notification. :param sinks: A list of sink objects. :param rotation: The amount and direction of the rotation. :return: Nothing. """ # Change the volume of the sinks for sink in sinks: self._pulse.volume_change_all_chans(sink, rotation * 0.005) # Show the notification self._display_notification(sink) def _get_active_win_class(self): """ Use the xlib module to get the class of the window that has the focus :return: Return the window class or None if none found """ # Get the window that has the focus focus_win = self._display.get_input_focus().focus # Get the window class win_cls = focus_win.get_wm_class() if win_cls is None: # Get the class of the parent window parent_cls = focus_win.query_tree().parent.get_wm_class() if parent_cls is not None: return str(parent_cls[-1].lower()) else: return None else: return str(win_cls[-1].lower()) def _get_app_sinks(self, app_name): """ Get the sinks corresponding to the given application :param app_name: Name of the application :return: List of sink objects otherwise. """ # Make sure the app_name is a string if isinstance(app_name, str) and app_name is not None: # Get the list of input sinks sinks = self._get_sinks() # Return the list of sinks corresponding to the application return [sink for sink in sinks if sink.proplist.get("application.process.binary").lower() == app_name] else: return [] def _get_sinks(self): """ Get a list of active pulseaudio sinks :return: List. A list containing all the active sink objects. """ # Get the list of input sinks sinks = [sink for sink in self._pulse.sink_input_list() if sink.proplist.get("application.process.binary", None) is not None] # Return the list of active sinks return sinks def _display_notification(self, sink_in): """ Display a notification showing the overall current volume. :param volume: A float representing the value of the current sink input. :return: Nothing. """ # Get the volume of the input sink volume = self._pulse.volume_get_all_chans(sink_in) # Get the main sink for sink in self._pulse.sink_list(): if sink.index == sink_in.sink: main_vol = sink.volume.value_flat break else: main_vol = 1 # Declare a new notification self._note.update("Volume", "{:.2%}".format(volume * main_vol), "/usr/share/icons/Faenza/apps/48/" "gnome-volume-control.png") # Show the notification self._note.show() def _handle_exception(self): """ Close the connection to the pulse server. :return: Nothing """ # Close the connection to the pulse server self._pulse.close() self._led.off()
#!/usr/bin/python from pulsectl import Pulse ### Sound check # https://pypi.python.org/pypi/pulsectl # equivalent to: # cat /proc/asound/card*/pcm*/sub*/status | grep RUNNING # pacmd list-sink-inputs | wc -l try: pulse = Pulse('sleep-if-idle') if len(pulse.sink_input_list()): active = 1 else: active = 0 except: active = 0 print(active, end='')