diff --git a/Services/AudioService.qml b/Services/AudioService.qml index b84c0cd1..d5882f31 100644 --- a/Services/AudioService.qml +++ b/Services/AudioService.qml @@ -29,42 +29,66 @@ Singleton { Process { id: audioSinkLister - command: ["bash", "-c", "pactl list sinks | grep -E '^Sink #|device.description|Name:' | paste - - - | sed 's/Sink #//g' | sed 's/Name: //g' | sed 's/device.description = //g' | sed 's/\"//g'"] + command: ["pactl", "list", "sinks"] running: true stdout: StdioCollector { onStreamFinished: { if (text.trim()) { + console.log("Parsing pactl sink output...") let sinks = [] let lines = text.trim().split('\n') + let currentSink = null + for (let line of lines) { - let parts = line.split('\t') - if (parts.length >= 3) { - let id = parts[0].trim() - let name = parts[1].trim() - let description = parts[2].trim() - - // Use description as display name if available, fallback to name processing - let displayName = description - if (!description || description === name) { - if (name.includes("analog-stereo")) displayName = "Built-in Speakers" - else if (name.includes("bluez")) displayName = "Bluetooth Audio" - else if (name.includes("usb")) displayName = "USB Audio" - else if (name.includes("hdmi")) displayName = "HDMI Audio" - else if (name.includes("easyeffects")) displayName = "EasyEffects" - else displayName = name + line = line.trim() + + // New sink starts + if (line.startsWith('Sink #')) { + if (currentSink && currentSink.name && currentSink.id) { + sinks.push(currentSink) } - sinks.push({ - id: id, - name: name, - displayName: displayName, - active: false // Will be determined by default sink - }) + let sinkId = line.replace('Sink #', '').trim() + currentSink = { + id: sinkId, + name: "", + displayName: "", + description: "", + active: false + } + } + // Get the Name field + else if (line.startsWith('Name: ') && currentSink) { + currentSink.name = line.replace('Name: ', '').trim() + } + // Get description + else if (line.includes('device.description = ') && currentSink) { + currentSink.description = line.replace('device.description = ', '').replace(/"/g, '').trim() } } + // Add the last sink + if (currentSink && currentSink.name && currentSink.id) { + sinks.push(currentSink) + } + + // Process display names + for (let sink of sinks) { + let displayName = sink.description + if (!displayName || displayName === sink.name) { + if (sink.name.includes("analog-stereo")) displayName = "Built-in Speakers" + else if (sink.name.includes("bluez")) displayName = "Bluetooth Audio" + else if (sink.name.includes("usb")) displayName = "USB Audio" + else if (sink.name.includes("hdmi")) displayName = "HDMI Audio" + else if (sink.name.includes("easyeffects")) displayName = "EasyEffects" + else displayName = sink.name + } + sink.displayName = displayName + } + + console.log("Final audio sinks:", JSON.stringify(sinks, null, 2)) root.audioSinks = sinks defaultSinkChecker.running = true } @@ -112,16 +136,28 @@ Singleton { } function setAudioSink(sinkName) { - let sinkSetProcess = Qt.createQmlObject(' - import Quickshell.Io - Process { - command: ["pactl", "set-default-sink", "' + sinkName + '"] - running: true - onExited: { - defaultSinkChecker.running = true - audioSinkLister.running = true - } + console.log("Setting audio sink to:", sinkName) + + // Use a more reliable approach instead of Qt.createQmlObject + sinkSetProcess.command = ["pactl", "set-default-sink", sinkName] + sinkSetProcess.running = true + } + + // Dedicated process for setting audio sink + Process { + id: sinkSetProcess + running: false + + onExited: (exitCode) => { + console.log("Audio sink change exit code:", exitCode) + if (exitCode === 0) { + console.log("Audio sink changed successfully") + // Refresh current sink and list + defaultSinkChecker.running = true + audioSinkLister.running = true + } else { + console.error("Failed to change audio sink") } - ', root) + } } } \ No newline at end of file diff --git a/Widgets/ControlCenterPopup.qml b/Widgets/ControlCenterPopup.qml index 45313071..0aa8256a 100644 --- a/Widgets/ControlCenterPopup.qml +++ b/Widgets/ControlCenterPopup.qml @@ -1051,6 +1051,8 @@ PanelWindow { cursorShape: Qt.PointingHandCursor onClicked: { + console.log("Clicked audio device:", JSON.stringify(modelData)) + console.log("Device name to set:", modelData.name) AudioService.setAudioSink(modelData.name) } } diff --git a/Widgets/PowerConfirmDialog.qml b/Widgets/PowerConfirmDialog.qml index bf42ee51..58c133b4 100644 --- a/Widgets/PowerConfirmDialog.qml +++ b/Widgets/PowerConfirmDialog.qml @@ -61,8 +61,8 @@ PanelWindow { } Column { - anchors.fill: parent - anchors.margins: Theme.spacingL + anchors.centerIn: parent + width: parent.width - Theme.spacingL * 2 spacing: Theme.spacingL // Title diff --git a/scripts/set-wallpaper.sh b/scripts/set-wallpaper.sh index 08c7b2b5..1eca09a8 100755 --- a/scripts/set-wallpaper.sh +++ b/scripts/set-wallpaper.sh @@ -2,15 +2,17 @@ set -euo pipefail img=$1 +# Convert to absolute path to fix symlink issues +img=$(realpath "$img") QS_DIR="$HOME/quickshell" mkdir -p "$QS_DIR" LINK="$QS_DIR/current_wallpaper" + ln -sf -- "$img" "$LINK" swaybg -m fill -i "$LINK" & disown json="$(matugen image "$img" --json hex)" - get() { jq -r "$1" <<<"$json"; } bg=$(get '.colors.dark.background') @@ -34,27 +36,26 @@ inverse_b=$(get '.colors.light.inverse_primary') cat >"$QS_DIR/generated_niri_colors.kdl" <"$QS_DIR/generated_ghostty_colors.conf" <