1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-05-02 02:22:06 -04:00

audio: defensive checks on PwNode objects

This commit is contained in:
bbedward
2026-04-15 14:16:32 -04:00
parent 10a235e686
commit 69fca14611
7 changed files with 28 additions and 29 deletions

View File

@@ -260,7 +260,7 @@ Column {
} }
case "audioOutput": case "audioOutput":
{ {
if (!AudioService.sink) if (!AudioService.sink?.audio)
return "volume_off"; return "volume_off";
let volume = AudioService.sink.audio.volume; let volume = AudioService.sink.audio.volume;
let muted = AudioService.sink.audio.muted; let muted = AudioService.sink.audio.muted;
@@ -276,7 +276,7 @@ Column {
} }
case "audioInput": case "audioInput":
{ {
if (!AudioService.source) if (!AudioService.source?.audio)
return "mic_off"; return "mic_off";
let muted = AudioService.source.audio.muted; let muted = AudioService.source.audio.muted;
return muted ? "mic_off" : "mic"; return muted ? "mic_off" : "mic";
@@ -369,7 +369,7 @@ Column {
} }
case "audioOutput": case "audioOutput":
{ {
if (!AudioService.sink) if (!AudioService.sink?.audio)
return I18n.tr("Select device", "audio status"); return I18n.tr("Select device", "audio status");
if (AudioService.sink.audio.muted) if (AudioService.sink.audio.muted)
return I18n.tr("Muted", "audio status"); return I18n.tr("Muted", "audio status");
@@ -380,7 +380,7 @@ Column {
} }
case "audioInput": case "audioInput":
{ {
if (!AudioService.source) if (!AudioService.source?.audio)
return I18n.tr("Select device", "audio status"); return I18n.tr("Select device", "audio status");
if (AudioService.source.audio.muted) if (AudioService.source.audio.muted)
return I18n.tr("Muted", "audio status"); return I18n.tr("Muted", "audio status");
@@ -412,9 +412,9 @@ Column {
case "bluetooth": case "bluetooth":
return !!(BluetoothService.available && BluetoothService.adapter && BluetoothService.adapter.enabled); return !!(BluetoothService.available && BluetoothService.adapter && BluetoothService.adapter.enabled);
case "audioOutput": case "audioOutput":
return !!(AudioService.sink && !AudioService.sink.audio.muted); return !!(AudioService.sink?.audio && !AudioService.sink.audio.muted);
case "audioInput": case "audioInput":
return !!(AudioService.source && !AudioService.source.audio.muted); return !!(AudioService.source?.audio && !AudioService.source.audio.muted);
default: default:
return false; return false;
} }

View File

@@ -351,8 +351,8 @@ Rectangle {
deviceRipple.trigger(mapped.x, mapped.y); deviceRipple.trigger(mapped.x, mapped.y);
} }
onClicked: { onClicked: {
if (modelData) { if (modelData && modelData.name) {
Pipewire.preferredDefaultAudioSource = modelData; AudioService.setDefaultSourceByName(modelData.name);
} }
} }
} }

View File

@@ -355,8 +355,8 @@ Rectangle {
deviceRipple.trigger(mapped.x, mapped.y); deviceRipple.trigger(mapped.x, mapped.y);
} }
onClicked: { onClicked: {
if (modelData) { if (modelData && modelData.name) {
Pipewire.preferredDefaultAudioSink = modelData; AudioService.setDefaultSinkByName(modelData.name);
} }
} }
} }

View File

@@ -35,7 +35,7 @@ Row {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onPressed: mouse => iconRipple.trigger(mouse.x, mouse.y) onPressed: mouse => iconRipple.trigger(mouse.x, mouse.y)
onClicked: { onClicked: {
if (defaultSink) { if (defaultSink?.audio) {
SessionData.suppressOSDTemporarily(); SessionData.suppressOSDTemporarily();
defaultSink.audio.muted = !defaultSink.audio.muted; defaultSink.audio.muted = !defaultSink.audio.muted;
} }
@@ -45,7 +45,7 @@ Row {
DankIcon { DankIcon {
anchors.centerIn: parent anchors.centerIn: parent
name: { name: {
if (!defaultSink) if (!defaultSink?.audio)
return "volume_off"; return "volume_off";
let volume = defaultSink.audio.volume; let volume = defaultSink.audio.volume;
@@ -62,18 +62,18 @@ Row {
return "volume_up"; return "volume_up";
} }
size: Theme.iconSize size: Theme.iconSize
color: defaultSink && !defaultSink.audio.muted && defaultSink.audio.volume > 0 ? Theme.primary : Theme.surfaceText color: defaultSink?.audio && !defaultSink.audio.muted && defaultSink.audio.volume > 0 ? Theme.primary : Theme.surfaceText
} }
} }
DankSlider { DankSlider {
id: volumeSlider id: volumeSlider
readonly property real actualVolumePercent: defaultSink ? Math.round(defaultSink.audio.volume * 100) : 0 readonly property real actualVolumePercent: defaultSink?.audio ? Math.round(defaultSink.audio.volume * 100) : 0
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
width: parent.width - (Theme.iconSize + Theme.spacingS * 2) width: parent.width - (Theme.iconSize + Theme.spacingS * 2)
enabled: defaultSink !== null enabled: defaultSink?.audio != null
minimum: 0 minimum: 0
maximum: AudioService.sinkMaxVolume maximum: AudioService.sinkMaxVolume
showValue: true showValue: true
@@ -83,7 +83,7 @@ Row {
trackColor: root.sliderTrackColor.a > 0 ? root.sliderTrackColor : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) trackColor: root.sliderTrackColor.a > 0 ? root.sliderTrackColor : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
onSliderValueChanged: function (newValue) { onSliderValueChanged: function (newValue) {
if (defaultSink) { if (defaultSink?.audio) {
SessionData.suppressOSDTemporarily(); SessionData.suppressOSDTemporarily();
defaultSink.audio.volume = newValue / 100.0; defaultSink.audio.volume = newValue / 100.0;
if (newValue > 0 && defaultSink.audio.muted) { if (newValue > 0 && defaultSink.audio.muted) {
@@ -97,7 +97,7 @@ Row {
Binding { Binding {
target: volumeSlider target: volumeSlider
property: "value" property: "value"
value: defaultSink ? Math.min(AudioService.sinkMaxVolume, Math.round(defaultSink.audio.volume * 100)) : 0 value: defaultSink?.audio ? Math.min(AudioService.sinkMaxVolume, Math.round(defaultSink.audio.volume * 100)) : 0
when: !volumeSlider.isDragging when: !volumeSlider.isDragging
} }
} }

View File

@@ -35,7 +35,7 @@ Row {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onPressed: mouse => iconRipple.trigger(mouse.x, mouse.y) onPressed: mouse => iconRipple.trigger(mouse.x, mouse.y)
onClicked: { onClicked: {
if (defaultSource) { if (defaultSource?.audio) {
SessionData.suppressOSDTemporarily(); SessionData.suppressOSDTemporarily();
defaultSource.audio.muted = !defaultSource.audio.muted; defaultSource.audio.muted = !defaultSource.audio.muted;
} }
@@ -45,7 +45,7 @@ Row {
DankIcon { DankIcon {
anchors.centerIn: parent anchors.centerIn: parent
name: { name: {
if (!defaultSource) if (!defaultSource?.audio)
return "mic_off"; return "mic_off";
let volume = defaultSource.audio.volume; let volume = defaultSource.audio.volume;
@@ -56,26 +56,26 @@ Row {
return "mic"; return "mic";
} }
size: Theme.iconSize size: Theme.iconSize
color: defaultSource && !defaultSource.audio.muted && defaultSource.audio.volume > 0 ? Theme.primary : Theme.surfaceText color: defaultSource?.audio && !defaultSource.audio.muted && defaultSource.audio.volume > 0 ? Theme.primary : Theme.surfaceText
} }
} }
DankSlider { DankSlider {
readonly property real actualVolumePercent: defaultSource ? Math.round(defaultSource.audio.volume * 100) : 0 readonly property real actualVolumePercent: defaultSource?.audio ? Math.round(defaultSource.audio.volume * 100) : 0
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
width: parent.width - (Theme.iconSize + Theme.spacingS * 2) width: parent.width - (Theme.iconSize + Theme.spacingS * 2)
enabled: defaultSource !== null enabled: defaultSource?.audio != null
minimum: 0 minimum: 0
maximum: 100 maximum: 100
value: defaultSource ? Math.min(100, Math.round(defaultSource.audio.volume * 100)) : 0 value: defaultSource?.audio ? Math.min(100, Math.round(defaultSource.audio.volume * 100)) : 0
showValue: true showValue: true
unit: "%" unit: "%"
valueOverride: actualVolumePercent valueOverride: actualVolumePercent
thumbOutlineColor: Theme.surfaceContainer thumbOutlineColor: Theme.surfaceContainer
trackColor: root.sliderTrackColor.a > 0 ? root.sliderTrackColor : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) trackColor: root.sliderTrackColor.a > 0 ? root.sliderTrackColor : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
onSliderValueChanged: function (newValue) { onSliderValueChanged: function (newValue) {
if (defaultSource) { if (defaultSource?.audio) {
SessionData.suppressOSDTemporarily(); SessionData.suppressOSDTemporarily();
defaultSource.audio.volume = newValue / 100.0; defaultSource.audio.volume = newValue / 100.0;
if (newValue > 0 && defaultSource.audio.muted) { if (newValue > 0 && defaultSource.audio.muted) {

View File

@@ -1,5 +1,4 @@
import QtQuick import QtQuick
import QtQuick.Effects
import Quickshell.Services.Pipewire import Quickshell.Services.Pipewire
import qs.Common import qs.Common
import qs.Services import qs.Services
@@ -25,7 +24,7 @@ Item {
} }
property bool usePlayerVolume: activePlayer && activePlayer.volumeSupported && !__isChromeBrowser property bool usePlayerVolume: activePlayer && activePlayer.volumeSupported && !__isChromeBrowser
property real currentVolume: usePlayerVolume ? activePlayer.volume : (AudioService.sink?.audio?.volume ?? 0) property real currentVolume: usePlayerVolume ? activePlayer.volume : (AudioService.sink?.audio?.volume ?? 0)
property bool volumeAvailable: (activePlayer && activePlayer.volumeSupported && !__isChromeBrowser) || (AudioService.sink && AudioService.sink.audio) property bool volumeAvailable: !!((activePlayer && activePlayer.volumeSupported && !__isChromeBrowser) || (AudioService.sink && AudioService.sink.audio))
property var availableDevices: { property var availableDevices: {
const hidden = SessionData.hiddenOutputDeviceNames ?? []; const hidden = SessionData.hiddenOutputDeviceNames ?? [];
return Pipewire.nodes.values.filter(node => { return Pipewire.nodes.values.filter(node => {
@@ -328,8 +327,8 @@ Item {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (modelData) { if (modelData && modelData.name) {
Pipewire.preferredDefaultAudioSink = modelData; AudioService.setDefaultSinkByName(modelData.name);
root.deviceSelected(modelData); root.deviceSelected(modelData);
} }
} }

View File

@@ -57,7 +57,7 @@ Item {
const id = activePlayer.identity.toLowerCase(); const id = activePlayer.identity.toLowerCase();
return id.includes("chrome") || id.includes("chromium"); return id.includes("chrome") || id.includes("chromium");
} }
readonly property bool volumeAvailable: (activePlayer && activePlayer.volumeSupported && !__isChromeBrowser) || (AudioService.sink && AudioService.sink.audio) readonly property bool volumeAvailable: !!((activePlayer && activePlayer.volumeSupported && !__isChromeBrowser) || (AudioService.sink && AudioService.sink.audio))
readonly property bool usePlayerVolume: activePlayer && activePlayer.volumeSupported && !__isChromeBrowser readonly property bool usePlayerVolume: activePlayer && activePlayer.volumeSupported && !__isChromeBrowser
readonly property real currentVolume: usePlayerVolume ? activePlayer.volume : (AudioService.sink?.audio?.volume ?? 0) readonly property real currentVolume: usePlayerVolume ? activePlayer.volume : (AudioService.sink?.audio?.volume ?? 0)