pragma Singleton

// Shared PipeWire device discovery and default selection. Quick Settings and
// Panama Settings intentionally use this same boundary so they cannot disagree
// about what counts as an input or which node should become the default.

import Quickshell
import Quickshell.Services.Pipewire
import QtQuick

import "AudioStreams.js" as AudioStreams

Singleton {
    id: root

    readonly property var outputs: Pipewire.nodes.values.filter(node =>
        !node.isStream && node.isSink)

    readonly property var inputs: Pipewire.nodes.values.filter(node =>
        !node.isStream
        && (node.type & PwNodeType.AudioSource) === PwNodeType.AudioSource)

    readonly property var playbackStreams: Pipewire.nodes.values.filter(node =>
        node.ready && node.audio
        && (node.type & PwNodeType.AudioOutStream) === PwNodeType.AudioOutStream)

    readonly property var applications: AudioStreams.group(
        root.playbackStreams, PwNodeType.AudioOutStream)

    function nodes(output: bool): var {
        return output ? root.outputs : root.inputs;
    }

    function current(output: bool): var {
        return output ? Pipewire.defaultAudioSink : Pipewire.defaultAudioSource;
    }

    function select(output: bool, node: var): void {
        if (!node)
            return;
        if (output)
            Pipewire.preferredDefaultAudioSink = node;
        else
            Pipewire.preferredDefaultAudioSource = node;
    }

    function label(node: var): string {
        if (!node)
            return "Unknown device";
        return node.description || node.nickname || node.name || "Unknown device";
    }

    function applicationVolume(application: var): real {
        return AudioStreams.volume(application);
    }

    function applicationMuted(application: var): bool {
        return AudioStreams.muted(application);
    }

    function setApplicationVolume(application: var, value: real): bool {
        return AudioStreams.setVolume(application, value);
    }

    function setApplicationMuted(application: var, muted: bool): bool {
        return AudioStreams.setMuted(application, muted);
    }
}
