mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-05 21:15:38 -05:00
@@ -59,6 +59,7 @@ const DMS_ACTIONS = [
|
|||||||
{ id: "spawn dms ipc call audio decrement 10", label: "Volume Down (10%)" },
|
{ id: "spawn dms ipc call audio decrement 10", label: "Volume Down (10%)" },
|
||||||
{ id: "spawn dms ipc call audio mute", label: "Volume Mute Toggle" },
|
{ id: "spawn dms ipc call audio mute", label: "Volume Mute Toggle" },
|
||||||
{ id: "spawn dms ipc call audio micmute", label: "Microphone Mute Toggle" },
|
{ id: "spawn dms ipc call audio micmute", label: "Microphone Mute Toggle" },
|
||||||
|
{ id: "spawn dms ipc call audio cycleoutput", label: "Audio Output: Cycle" },
|
||||||
{ id: "spawn dms ipc call brightness increment", label: "Brightness Up" },
|
{ id: "spawn dms ipc call brightness increment", label: "Brightness Up" },
|
||||||
{ id: "spawn dms ipc call brightness increment 1", label: "Brightness Up (1%)" },
|
{ id: "spawn dms ipc call brightness increment 1", label: "Brightness Up (1%)" },
|
||||||
{ id: "spawn dms ipc call brightness increment 5", label: "Brightness Up (5%)" },
|
{ id: "spawn dms ipc call brightness increment 5", label: "Brightness Up (5%)" },
|
||||||
|
|||||||
@@ -313,6 +313,7 @@ Singleton {
|
|||||||
property bool osdMicMuteEnabled: true
|
property bool osdMicMuteEnabled: true
|
||||||
property bool osdCapsLockEnabled: true
|
property bool osdCapsLockEnabled: true
|
||||||
property bool osdPowerProfileEnabled: true
|
property bool osdPowerProfileEnabled: true
|
||||||
|
property bool osdAudioOutputEnabled: true
|
||||||
|
|
||||||
property bool powerActionConfirm: true
|
property bool powerActionConfirm: true
|
||||||
property int powerActionHoldDuration: 1
|
property int powerActionHoldDuration: 1
|
||||||
|
|||||||
@@ -212,6 +212,7 @@ var SPEC = {
|
|||||||
osdMicMuteEnabled: { def: true },
|
osdMicMuteEnabled: { def: true },
|
||||||
osdCapsLockEnabled: { def: true },
|
osdCapsLockEnabled: { def: true },
|
||||||
osdPowerProfileEnabled: { def: false },
|
osdPowerProfileEnabled: { def: false },
|
||||||
|
osdAudioOutputEnabled: { def: true },
|
||||||
|
|
||||||
powerActionConfirm: { def: true },
|
powerActionConfirm: { def: true },
|
||||||
powerActionHoldDuration: { def: 1 },
|
powerActionHoldDuration: { def: 1 },
|
||||||
|
|||||||
@@ -700,6 +700,14 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Variants {
|
||||||
|
model: SettingsData.getFilteredScreens("osd")
|
||||||
|
|
||||||
|
delegate: AudioOutputOSD {
|
||||||
|
modelData: item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LazyLoader {
|
LazyLoader {
|
||||||
id: hyprlandOverviewLoader
|
id: hyprlandOverviewLoader
|
||||||
active: CompositorService.isHyprland
|
active: CompositorService.isHyprland
|
||||||
|
|||||||
80
quickshell/Modules/OSD/AudioOutputOSD.qml
Normal file
80
quickshell/Modules/OSD/AudioOutputOSD.qml
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
import QtQuick
|
||||||
|
import qs.Common
|
||||||
|
import qs.Services
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
DankOSD {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property string deviceName: ""
|
||||||
|
property string deviceIcon: "speaker"
|
||||||
|
|
||||||
|
osdWidth: Math.min(Math.max(120, Theme.iconSize + textMetrics.width + Theme.spacingS * 4), Screen.width - Theme.spacingM * 2)
|
||||||
|
osdHeight: 40 + Theme.spacingS * 2
|
||||||
|
autoHideInterval: 2500
|
||||||
|
enableMouseInteraction: false
|
||||||
|
|
||||||
|
TextMetrics {
|
||||||
|
id: textMetrics
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
font.weight: Font.Medium
|
||||||
|
font.family: Theme.fontFamily
|
||||||
|
text: root.deviceName
|
||||||
|
}
|
||||||
|
|
||||||
|
function getIconForSink(sink) {
|
||||||
|
if (!sink)
|
||||||
|
return "speaker";
|
||||||
|
const name = sink.name || "";
|
||||||
|
if (name.includes("bluez"))
|
||||||
|
return "headset";
|
||||||
|
if (name.includes("hdmi"))
|
||||||
|
return "tv";
|
||||||
|
if (name.includes("usb"))
|
||||||
|
return "headset";
|
||||||
|
return "speaker";
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: AudioService
|
||||||
|
|
||||||
|
function onAudioOutputCycled(name) {
|
||||||
|
if (!SettingsData.osdAudioOutputEnabled)
|
||||||
|
return;
|
||||||
|
root.deviceName = name;
|
||||||
|
root.deviceIcon = getIconForSink(AudioService.sink);
|
||||||
|
root.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
content: Item {
|
||||||
|
property int gap: Theme.spacingS
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: parent.width - Theme.spacingS * 2
|
||||||
|
height: 40
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
id: iconItem
|
||||||
|
width: Theme.iconSize
|
||||||
|
height: Theme.iconSize
|
||||||
|
x: parent.gap
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
name: root.deviceIcon
|
||||||
|
size: Theme.iconSize
|
||||||
|
color: Theme.primary
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: textItem
|
||||||
|
x: parent.gap * 2 + Theme.iconSize
|
||||||
|
width: parent.width - Theme.iconSize - parent.gap * 3
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
text: root.deviceName
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
font.weight: Font.Medium
|
||||||
|
color: Theme.surfaceText
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -141,6 +141,13 @@ Item {
|
|||||||
checked: SettingsData.osdPowerProfileEnabled
|
checked: SettingsData.osdPowerProfileEnabled
|
||||||
onToggled: checked => SettingsData.set("osdPowerProfileEnabled", checked)
|
onToggled: checked => SettingsData.set("osdPowerProfileEnabled", checked)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SettingsToggleRow {
|
||||||
|
text: I18n.tr("Audio Output Switch")
|
||||||
|
description: I18n.tr("Show on-screen display when cycling audio output devices")
|
||||||
|
checked: SettingsData.osdAudioOutputEnabled
|
||||||
|
onToggled: checked => SettingsData.set("osdAudioOutputEnabled", checked)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,33 @@ Singleton {
|
|||||||
property var mediaDevicesConnections: null
|
property var mediaDevicesConnections: null
|
||||||
|
|
||||||
signal micMuteChanged
|
signal micMuteChanged
|
||||||
|
signal audioOutputCycled(string deviceName)
|
||||||
|
|
||||||
|
function getAvailableSinks() {
|
||||||
|
return Pipewire.nodes.values.filter(node => node.audio && node.isSink && !node.isStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cycleAudioOutput() {
|
||||||
|
const sinks = getAvailableSinks();
|
||||||
|
if (sinks.length < 2)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
const currentSink = root.sink;
|
||||||
|
let currentIndex = -1;
|
||||||
|
for (let i = 0; i < sinks.length; i++) {
|
||||||
|
if (sinks[i] === currentSink) {
|
||||||
|
currentIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextIndex = (currentIndex + 1) % sinks.length;
|
||||||
|
const nextSink = sinks[nextIndex];
|
||||||
|
Pipewire.preferredDefaultAudioSink = nextSink;
|
||||||
|
const name = displayName(nextSink);
|
||||||
|
audioOutputCycled(name);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: root.sink?.audio ?? null
|
target: root.sink?.audio ?? null
|
||||||
@@ -595,6 +622,13 @@ Singleton {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cycleoutput(): string {
|
||||||
|
const result = root.cycleAudioOutput();
|
||||||
|
if (!result)
|
||||||
|
return "Only one audio output available";
|
||||||
|
return `Switched to: ${result}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
|
|||||||
Reference in New Issue
Block a user