Warning, /plasma/latte-dock/plasmoid/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.2 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 property int maxVolumePercent: 125 0020 property int maxVolumeValue: Math.round(maxVolumePercent * PulseAudio.NormalVolume / 100.0) 0021 property int volumeStep: Math.round(5 * PulseAudio.NormalVolume / 100.0) 0022 0023 function boundVolume(volume) { 0024 return Math.max(PulseAudio.MinimalVolume, Math.min(volume, maxVolumeValue)); 0025 } 0026 0027 // TODO Evict cache at some point, preferably if all instances of an application closed. 0028 function registerPidMatch(appName) { 0029 if (!hasPidMatch(appName)) { 0030 pidMatches[appName] = true; 0031 0032 // In case this match is new, notify that streams might have changed. 0033 // This way we also catch the case when the non-playing instance 0034 // shows up first. 0035 // Only notify if we changed to avoid infinite recursion. 0036 streamsChanged(); 0037 } 0038 } 0039 0040 function hasPidMatch(appName) { 0041 return pidMatches[appName] === true; 0042 } 0043 0044 function findStreams(key, value) { 0045 var streams = [] 0046 for (var i = 0, length = instantiator.count; i < length; ++i) { 0047 var stream = instantiator.objectAt(i); 0048 if (stream[key] === value || (key==="appName" && stream[key].toLowerCase() === value.toLowerCase())) { 0049 streams.push(stream); 0050 } 0051 } 0052 return streams 0053 } 0054 0055 function streamsForAppName(appName) { 0056 return findStreams("appName", appName); 0057 } 0058 0059 function streamsForPid(pid) { 0060 var streams = findStreams("pid", pid); 0061 0062 if (streams.length === 0) { 0063 for (var i = 0, length = instantiator.count; i < length; ++i) { 0064 var stream = instantiator.objectAt(i); 0065 0066 if (stream.parentPid === -1) { 0067 stream.parentPid = backend.parentPid(stream.pid); 0068 } 0069 0070 if (stream.parentPid === pid) { 0071 streams.push(stream); 0072 } 0073 } 0074 } 0075 0076 return streams; 0077 } 0078 0079 // QtObject has no default property, hence adding the Instantiator to one explicitly. 0080 property var instantiator: Instantiator { 0081 model: PulseObjectFilterModel { 0082 filters: [ { role: "VirtualStream", value: false } ] 0083 sourceModel: SinkInputModel {} 0084 } 0085 0086 delegate: QtObject { 0087 readonly property int pid: Client ? Client.properties["application.process.id"] : 0 0088 // Determined on demand. 0089 property int parentPid: -1 0090 readonly property string appName: Client ? Client.properties["application.name"] : "" 0091 readonly property bool muted: Muted 0092 // whether there is nothing actually going on on that stream 0093 readonly property bool corked: Corked 0094 0095 readonly property int volume: Math.round(pulseVolume / PulseAudio.NormalVolume * 100.0) 0096 readonly property int pulseVolume: Volume 0097 0098 function mute() { 0099 Muted = true 0100 } 0101 function unmute() { 0102 Muted = false 0103 } 0104 0105 function increaseVolume() { 0106 var bVolume = pulseAudio.boundVolume(Volume + pulseAudio.volumeStep); 0107 Volume = bVolume; 0108 } 0109 0110 function decreaseVolume() { 0111 var bVolume = pulseAudio.boundVolume(Volume - pulseAudio.volumeStep); 0112 Volume = bVolume; 0113 } 0114 } 0115 0116 onObjectAdded: pulseAudio.streamsChanged() 0117 onObjectRemoved: pulseAudio.streamsChanged() 0118 } 0119 0120 Component.onCompleted: { 0121 console.log("PulseAudio Latte interface was loaded..."); 0122 } 0123 }