Warning, /plasma/plasma-desktop/applets/taskmanager/package/contents/ui/PulseAudio.qml is written in an unsupported language. File is not indexed.

0001 /*
0002     SPDX-FileCopyrightText: 2017 Kai Uwe Broulik <kde@privat.broulik.de>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 import QtQuick 2.15
0008 
0009 import org.kde.plasma.private.volume 0.1
0010 
0011 QtObject {
0012     id: pulseAudio
0013 
0014     signal streamsChanged
0015 
0016     // It's a JS object so we can do key lookup and don't need to take care of filtering duplicates.
0017     property var pidMatches: ({})
0018 
0019     // TODO Evict cache at some point, preferably if all instances of an application closed.
0020     function registerPidMatch(appName) {
0021         if (!hasPidMatch(appName)) {
0022             pidMatches[appName] = true;
0023 
0024             // In case this match is new, notify that streams might have changed.
0025             // This way we also catch the case when the non-playing instance
0026             // shows up first.
0027             // Only notify if we changed to avoid infinite recursion.
0028             streamsChanged();
0029         }
0030     }
0031 
0032     function hasPidMatch(appName) {
0033         return pidMatches[appName] === true;
0034     }
0035 
0036     function findStreams(key, value) {
0037         return findStreamsFn(stream => stream[key] === value);
0038     }
0039 
0040     function findStreamsFn(fn) {
0041         var streams = []
0042         for (var i = 0, length = instantiator.count; i < length; ++i) {
0043             var stream = instantiator.objectAt(i);
0044             if (fn(stream)) {
0045                 streams.push(stream);
0046             }
0047         }
0048         return streams;
0049     }
0050 
0051     function streamsForAppId(appId) {
0052         return findStreams("portalAppId", appId);
0053     }
0054 
0055     function streamsForAppName(appName) {
0056         return findStreams("appName", appName);
0057     }
0058 
0059     function streamsForPid(pid) {
0060         // skip stream that has portalAppId
0061         // app using portal may have a sandbox pid
0062         var streams = findStreamsFn(stream => stream.pid === pid && !stream.portalAppId);
0063 
0064         if (streams.length === 0) {
0065             for (var i = 0, length = instantiator.count; i < length; ++i) {
0066                 var stream = instantiator.objectAt(i);
0067 
0068                 if (stream.parentPid === -1) {
0069                     stream.parentPid = backend.parentPid(stream.pid);
0070                 }
0071 
0072                 if (stream.parentPid === pid) {
0073                     streams.push(stream);
0074                 }
0075             }
0076         }
0077 
0078         return streams;
0079     }
0080 
0081     // QtObject has no default property, hence adding the Instantiator to one explicitly.
0082     property var instantiator: Instantiator {
0083         model: PulseObjectFilterModel {
0084             filters: [ { role: "VirtualStream", value: false } ]
0085             sourceModel: SinkInputModel {}
0086         }
0087 
0088         delegate: QtObject {
0089             id: delegate
0090             required property var model
0091             readonly property int pid: model.Client ? model.Client.properties["application.process.id"] : 0
0092             // Determined on demand.
0093             property int parentPid: -1
0094             readonly property string appName: model.Client && model.Client.properties["application.name"] || ""
0095             readonly property string portalAppId: model.Client && model.Client.properties["pipewire.access.portal.app_id"] || ""
0096             readonly property bool muted: model.Muted
0097             // whether there is nothing actually going on on that stream
0098             readonly property bool corked: model.Corked
0099             readonly property int volume: model.Volume
0100 
0101             function mute() {
0102                 model.Muted = true
0103             }
0104             function unmute() {
0105                 model.Muted = false
0106             }
0107         }
0108 
0109         onObjectAdded: pulseAudio.streamsChanged()
0110         onObjectRemoved: pulseAudio.streamsChanged()
0111     }
0112 
0113     readonly property int minimalVolume: PulseAudio.MinimalVolume
0114     readonly property int normalVolume: PulseAudio.NormalVolume
0115 }