# Python imports # Lib imports import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk # Application imports class AudioSink(Gtk.Box): """docstring for AudioSink.""" def __init__(self, pulse, sink): super(AudioSink, self).__init__() self._scale = None self._mute_btn = None self.pulse = pulse self.sink = sink self.min_range = 0 self.max_range = 150 self.muted = False self.block_update = False self._setup_styling() self._setup_signals() self._load_widgets() self.show_all() def _setup_styling(self): self.set_orientation(Gtk.Orientation.VERTICAL) self.set_margin_top(10) self.set_margin_bottom(10) self.set_margin_left(10) self.set_margin_right(10) def _setup_signals(self): ... def _load_widgets(self): current_lvl = self.sink.volume.values[0] * 100 box = Gtk.Box() label = Gtk.Label() scale = Gtk.Scale.new_with_range(Gtk.Orientation.HORIZONTAL, self.min_range, self.max_range, 1) mute_btn = Gtk.Button() self.muted = False if self.sink.mute == 0 else True # logger.debug(f"{self.sink.proplist}") try: name = self.sink.description except Exception as e: name = self.sink.proplist["application.name"] label.set_text(name) label.set_xalign(0.0) scale.add_mark(0.0, Gtk.PositionType.BOTTOM, "Silence") scale.add_mark(50.0, Gtk.PositionType.BOTTOM, "50%") scale.add_mark(100.0, Gtk.PositionType.BOTTOM, "100%") scale.set_value(current_lvl) scale.set_hexpand(True) box.set_orientation(Gtk.Orientation.HORIZONTAL) mute_btn.set_margin_left(10) self.set_mute_image(mute_btn) scale.connect("value-changed", self.set_volume) mute_btn.connect("clicked", self.toggle_mute) mute_btn.set_tooltip_text("Mute...") self._scale = scale self._mute_btn = mute_btn self.add(label) box.add(scale) box.add(mute_btn) self.add(box) def set_volume(self, range): if self.block_update: return value = range.get_value() / 100 sink_vol_info = self.sink.volume new_level = [] for level in sink_vol_info.values: new_level.append(value) sink_vol_info.values = new_level try: self.pulse.sink_input_volume_set(self.sink.index, sink_vol_info) except Exception as e: self.pulse.sink_volume_set(self.sink.index, sink_vol_info) def toggle_mute(self, widget = None, eve = None): self.muted = not self.muted self.set_mute_image(widget) self.pulse.sink_input_mute(self.sink.index, mute=self.muted) def set_mute_image(self, mute_btn): mute_btn.set_image( Gtk.Image.new_from_icon_name( "gtk-disconnect" if self.muted else "gtk-connect" , 3) ) def do_update(self): self.block_update = True sink_inputs = self.pulse.sink_input_list() for sink_input in sink_inputs: if sink_input.index == self.sink.index: self.sink = sink_input sink_vol_info = self.sink.volume.values self.muted = False if self.sink.mute == 0 else True self.set_mute_image(self._mute_btn) self._scale.set_value( sink_vol_info[0] * 100 ) self.block_update = False