mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-06-15 23:55:21 -04:00
feat(media-control): support scroll and right-click on audio output devices in media popout (#2615)
* feat(media-control): support scroll and right-click on audio output devices in media popout * feat(media-control): make device list volume scrolling optional
This commit is contained in:
@@ -397,6 +397,7 @@ Singleton {
|
|||||||
property bool audioVisualizerEnabled: true
|
property bool audioVisualizerEnabled: true
|
||||||
property string audioScrollMode: "volume"
|
property string audioScrollMode: "volume"
|
||||||
property int audioWheelScrollAmount: 5
|
property int audioWheelScrollAmount: 5
|
||||||
|
property bool audioDeviceScrollVolumeEnabled: false
|
||||||
property bool clockCompactMode: false
|
property bool clockCompactMode: false
|
||||||
property int focusedWindowSize: 1
|
property int focusedWindowSize: 1
|
||||||
property bool focusedWindowCompactMode: false
|
property bool focusedWindowCompactMode: false
|
||||||
|
|||||||
@@ -156,6 +156,7 @@ var SPEC = {
|
|||||||
audioVisualizerEnabled: { def: true },
|
audioVisualizerEnabled: { def: true },
|
||||||
audioScrollMode: { def: "volume" },
|
audioScrollMode: { def: "volume" },
|
||||||
audioWheelScrollAmount: { def: 5 },
|
audioWheelScrollAmount: { def: 5 },
|
||||||
|
audioDeviceScrollVolumeEnabled: { def: false },
|
||||||
clockCompactMode: { def: false },
|
clockCompactMode: { def: false },
|
||||||
focusedWindowCompactMode: { def: false },
|
focusedWindowCompactMode: { def: false },
|
||||||
focusedWindowSize: { def: 1 },
|
focusedWindowSize: { def: 1 },
|
||||||
|
|||||||
@@ -108,9 +108,6 @@ DankPopout {
|
|||||||
MprisController.setActivePlayer(player);
|
MprisController.setActivePlayer(player);
|
||||||
root.__hideDropdowns();
|
root.__hideDropdowns();
|
||||||
}
|
}
|
||||||
onDeviceSelected: device => {
|
|
||||||
root.__hideDropdowns();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -383,7 +383,27 @@ Item {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
|
onPressed: mouse => {
|
||||||
|
if (mouse.button === Qt.RightButton) {
|
||||||
|
mouse.accepted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onWheel: wheelEvent => {
|
||||||
|
if (SettingsData.audioDeviceScrollVolumeEnabled && wheelEvent.x >= deviceMouseArea.width / 2) {
|
||||||
|
AudioService.handleNodeVolumeWheel(modelData, wheelEvent);
|
||||||
|
} else {
|
||||||
|
wheelEvent.accepted = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onClicked: mouse => {
|
||||||
|
if (mouse.button === Qt.RightButton) {
|
||||||
|
if (modelData && modelData.audio) {
|
||||||
|
SessionData.suppressOSDTemporarily();
|
||||||
|
modelData.audio.muted = !modelData.audio.muted;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (modelData && modelData.name) {
|
if (modelData && modelData.name) {
|
||||||
AudioService.setDefaultSinkByName(modelData.name);
|
AudioService.setDefaultSinkByName(modelData.name);
|
||||||
root.deviceSelected(modelData);
|
root.deviceSelected(modelData);
|
||||||
|
|||||||
@@ -866,7 +866,27 @@ Item {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
|
onPressed: mouse => {
|
||||||
|
if (mouse.button === Qt.RightButton) {
|
||||||
|
mouse.accepted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onWheel: wheelEvent => {
|
||||||
|
const delta = wheelEvent.angleDelta.y;
|
||||||
|
if (delta !== 0) {
|
||||||
|
AudioService.cycleAudioOutputDirection(delta < 0);
|
||||||
|
wheelEvent.accepted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onClicked: mouse => {
|
||||||
|
if (mouse.button === Qt.RightButton) {
|
||||||
|
if (AudioService.sink?.audio) {
|
||||||
|
SessionData.suppressOSDTemporarily();
|
||||||
|
AudioService.sink.audio.muted = !AudioService.sink.audio.muted;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (devicesExpanded) {
|
if (devicesExpanded) {
|
||||||
const sinks = AudioService.getAvailableSinks();
|
const sinks = AudioService.getAvailableSinks();
|
||||||
if (sinks && sinks.length > 1) {
|
if (sinks && sinks.length > 1) {
|
||||||
|
|||||||
@@ -113,6 +113,13 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SettingsToggleRow {
|
||||||
|
text: I18n.tr("Device list scroll volume")
|
||||||
|
description: I18n.tr("Allow adjusting device volume by scrolling on the right half of items in the device list")
|
||||||
|
checked: SettingsData.audioDeviceScrollVolumeEnabled
|
||||||
|
onToggled: checked => SettingsData.set("audioDeviceScrollVolumeEnabled", checked)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ Singleton {
|
|||||||
return SessionData.deviceMaxVolumes[name] ?? 100;
|
return SessionData.deviceMaxVolumes[name] ?? 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
readonly property int wheelVolumeStep: SettingsData.audioWheelScrollAmount
|
||||||
|
|
||||||
signal micMuteChanged
|
signal micMuteChanged
|
||||||
signal audioOutputCycled(string deviceName, string deviceIcon)
|
signal audioOutputCycled(string deviceName, string deviceIcon)
|
||||||
signal deviceAliasChanged(string nodeName, string newAlias)
|
signal deviceAliasChanged(string nodeName, string newAlias)
|
||||||
@@ -156,14 +158,19 @@ Singleton {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function cycleAudioOutput() {
|
function cycleAudioOutputDirection(forward) {
|
||||||
const sinks = getAvailableSinks();
|
const sinks = getAvailableSinks();
|
||||||
if (sinks.length < 2)
|
if (sinks.length < 2)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
const currentName = root.sink?.name ?? "";
|
const currentName = root.sink?.name ?? "";
|
||||||
const currentIndex = sinks.findIndex(s => s.name === currentName);
|
const currentIndex = sinks.findIndex(s => s.name === currentName);
|
||||||
const nextIndex = (currentIndex + 1) % sinks.length;
|
let nextIndex;
|
||||||
|
if (forward) {
|
||||||
|
nextIndex = (currentIndex + 1) % sinks.length;
|
||||||
|
} else {
|
||||||
|
nextIndex = (currentIndex - 1 + sinks.length) % sinks.length;
|
||||||
|
}
|
||||||
const nextSink = sinks[nextIndex];
|
const nextSink = sinks[nextIndex];
|
||||||
setDefaultSinkByName(nextSink.name);
|
setDefaultSinkByName(nextSink.name);
|
||||||
const name = displayName(nextSink);
|
const name = displayName(nextSink);
|
||||||
@@ -171,6 +178,10 @@ Singleton {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cycleAudioOutput() {
|
||||||
|
return cycleAudioOutputDirection(true);
|
||||||
|
}
|
||||||
|
|
||||||
function getDeviceAlias(nodeName) {
|
function getDeviceAlias(nodeName) {
|
||||||
if (!nodeName)
|
if (!nodeName)
|
||||||
return null;
|
return null;
|
||||||
@@ -833,6 +844,28 @@ EOFCONFIG
|
|||||||
return root.sink.audio.muted ? "Audio muted" : "Audio unmuted";
|
return root.sink.audio.muted ? "Audio muted" : "Audio unmuted";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleNodeVolumeWheel(node, wheelEvent) {
|
||||||
|
if (!node?.audio)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SessionData.suppressOSDTemporarily();
|
||||||
|
const delta = wheelEvent.angleDelta.y;
|
||||||
|
if (delta === 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const current = Math.round(node.audio.volume * 100);
|
||||||
|
const maxVol = getMaxVolumePercent(node);
|
||||||
|
const newVolume = delta > 0 ? Math.min(maxVol, current + root.wheelVolumeStep) : Math.max(0, current - root.wheelVolumeStep);
|
||||||
|
|
||||||
|
node.audio.muted = false;
|
||||||
|
node.audio.volume = newVolume / 100;
|
||||||
|
|
||||||
|
if (node === sink) {
|
||||||
|
playVolumeChangeSoundIfEnabled();
|
||||||
|
}
|
||||||
|
wheelEvent.accepted = true;
|
||||||
|
}
|
||||||
|
|
||||||
function setMicVolume(percentage) {
|
function setMicVolume(percentage) {
|
||||||
if (!root.source?.audio) {
|
if (!root.source?.audio) {
|
||||||
return "No audio source available";
|
return "No audio source available";
|
||||||
|
|||||||
Reference in New Issue
Block a user