"""Applications tab: horizontally-scrolling row of every app currently playing audio (pactl sink-inputs), each with its own volume meter (or independent L/R pair), mute, live peak bar, an output-device dropdown, and — for whichever of those apps also happen to be recording (matched against pactl source-outputs by application binary/name) — an input-device dropdown mirroring the output one.""" from __future__ import annotations import gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk # noqa: E402 from ui.app_card import ApplicationCard from ui.scroll_row import ScrollRow class ApplicationsTab(Gtk.Box): def __init__(self, backend, peaks) -> None: super().__init__(orientation=Gtk.Orientation.VERTICAL) self.add_css_class("sb-tab-page") self._backend = backend self._peaks = peaks self._row = ScrollRow(self._make_card, empty_text="Nothing is playing audio right now") self.append(self._row) def _make_card(self, item: dict, sinks: list[dict], sources: list[dict], source_outputs: list[dict]) -> ApplicationCard: return ApplicationCard(self._backend, self._peaks, item, sinks, sources, source_outputs) def refresh(self) -> None: def got_sinks(sinks: list[dict]) -> None: def got_inputs(inputs: list[dict]) -> None: def got_sources(sources: list[dict]) -> None: def got_source_outputs(source_outputs: list[dict]) -> None: self._row.sync(inputs, sinks, sources, source_outputs) self._backend.list_source_outputs(got_source_outputs) self._backend.list_sources(got_sources) self._backend.list_sink_inputs(got_inputs) self._backend.list_sinks(got_sinks) def activate(self) -> None: self._row.activate() self.refresh() def deactivate(self) -> None: self._row.deactivate()