# Python imports # Lib imports import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk # Application imports from ..widgets.audio_sink import AudioSink class SinkInputList(Gtk.ScrolledWindow): def __init__(self, pulse): super(SinkInputList, self).__init__() self.pulse = pulse self._vadjust = None self._box = None self._setup_styling() self._setup_signals() self._subscribe_to_events() self._load_widgets() self.show_all() def _setup_styling(self): ctx = self.get_style_context() ctx.add_class("sink-list-container") self.set_vexpand(True) self.set_overlay_scrolling(False) def _setup_signals(self): ... def _subscribe_to_events(self): event_system.subscribe("handle_new_sync_input", self._handle_new_sync_input) event_system.subscribe("handle_del_sync_input", self._handle_del_sync_input) event_system.subscribe("handle_cng_sync_input", self._handle_cng_sync_input) def _load_widgets(self): viewport = Gtk.Viewport() box = Gtk.Box() self._box = box self._vadjust = self.get_vadjustment() box.set_orientation(Gtk.Orientation.VERTICAL) viewport.add(box) self.add(viewport) def _handle_cng_sync_input(self, index): for child in self._box.get_children(): if index == child.sink.index: child.do_update() # If sink out of view in list just scroll fully down. # Most cases will scroll b/c most recently added sink volume changed elsewhere. # (Edge case is we update the volume of a sink in between and overshoot.) # I don't personally care and this isn't a pain point for me. if not child.get_mapped(): self._scroll_to_bottom(self._vadjust) def _handle_new_sync_input(self, index): sink_input = self.pulse.sink_input_list()[-1] self._box.add( AudioSink(self.pulse, sink_input) ) self._scroll_to_bottom(self._vadjust) def _handle_del_sync_input(self, index): parent = self.get_parent() for sink_input in parent.sink_inputs: if index == sink_input.index: parent.sink_inputs.remove(sink_input) for child in self._box.get_children(): if index == child.sink.index: child.destroy() self._scroll_to_bottom(self._vadjust) def _scroll_to_bottom(self, adjustment): self._vadjust.set_value( adjustment.get_upper() ) def get_box(self): return self._box