osd: add mic volume
Disabled by default
This commit is contained in:
parent
cdfc260f39
commit
4b9643a802
7 changed files with 116 additions and 39 deletions
|
|
@ -326,6 +326,7 @@ default, you must create it manually.
|
|||
"osd": {
|
||||
"enabled": true,
|
||||
"enableBrightness": true,
|
||||
"enableMicrophone": false,
|
||||
"hideDelay": 2000
|
||||
},
|
||||
"paths": {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ JsonObject {
|
|||
property bool enabled: true
|
||||
property int hideDelay: 2000
|
||||
property bool enableBrightness: true
|
||||
property bool enableMicrophone: false
|
||||
property Sizes sizes: Sizes {}
|
||||
|
||||
component Sizes: JsonObject {
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ Item {
|
|||
|
||||
clip: root.visibilities.session
|
||||
screen: root.screen
|
||||
visibility: root.visibilities.osd
|
||||
visibilities: root.visibilities
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
|
|
|
|||
|
|
@ -1,73 +1,123 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
|
||||
import qs.components
|
||||
import qs.components.controls
|
||||
import qs.services
|
||||
import qs.config
|
||||
import qs.utils
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
Column {
|
||||
Item {
|
||||
id: root
|
||||
|
||||
required property Brightness.Monitor monitor
|
||||
|
||||
padding: Appearance.padding.large
|
||||
required property var visibilities
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
|
||||
spacing: Appearance.spacing.normal
|
||||
implicitWidth: layout.implicitWidth + Appearance.padding.large * 2
|
||||
implicitHeight: layout.implicitHeight + Appearance.padding.large * 2
|
||||
|
||||
// Speaker volume
|
||||
CustomMouseArea {
|
||||
implicitWidth: Config.osd.sizes.sliderWidth
|
||||
implicitHeight: Config.osd.sizes.sliderHeight
|
||||
ColumnLayout {
|
||||
id: layout
|
||||
|
||||
onWheel: event => {
|
||||
if (event.angleDelta.y > 0)
|
||||
Audio.incrementVolume();
|
||||
else if (event.angleDelta.y < 0)
|
||||
Audio.decrementVolume();
|
||||
}
|
||||
anchors.centerIn: parent
|
||||
spacing: Appearance.spacing.normal
|
||||
|
||||
FilledSlider {
|
||||
anchors.fill: parent
|
||||
|
||||
icon: Icons.getVolumeIcon(value, Audio.muted)
|
||||
value: Audio.volume
|
||||
onMoved: Audio.setVolume(value)
|
||||
}
|
||||
}
|
||||
|
||||
// Brightness
|
||||
WrappedLoader {
|
||||
active: Config.osd.enableBrightness
|
||||
|
||||
sourceComponent: CustomMouseArea {
|
||||
// Speaker volume
|
||||
CustomMouseArea {
|
||||
implicitWidth: Config.osd.sizes.sliderWidth
|
||||
implicitHeight: Config.osd.sizes.sliderHeight
|
||||
|
||||
onWheel: event => {
|
||||
const monitor = root.monitor;
|
||||
if (!monitor)
|
||||
return;
|
||||
if (event.angleDelta.y > 0)
|
||||
monitor.setBrightness(monitor.brightness + 0.1);
|
||||
Audio.incrementVolume();
|
||||
else if (event.angleDelta.y < 0)
|
||||
monitor.setBrightness(monitor.brightness - 0.1);
|
||||
Audio.decrementVolume();
|
||||
}
|
||||
|
||||
FilledSlider {
|
||||
anchors.fill: parent
|
||||
|
||||
icon: `brightness_${(Math.round(value * 6) + 1)}`
|
||||
value: root.monitor?.brightness ?? 0
|
||||
onMoved: root.monitor?.setBrightness(value)
|
||||
icon: Icons.getVolumeIcon(value, Audio.muted)
|
||||
value: Audio.volume
|
||||
onMoved: Audio.setVolume(value)
|
||||
}
|
||||
}
|
||||
|
||||
// Microphone volume
|
||||
WrappedLoader {
|
||||
shouldBeActive: Config.osd.enableMicrophone && (!Config.osd.enableBrightness || !root.visibilities.session)
|
||||
|
||||
sourceComponent: CustomMouseArea {
|
||||
implicitWidth: Config.osd.sizes.sliderWidth
|
||||
implicitHeight: Config.osd.sizes.sliderHeight
|
||||
|
||||
onWheel: event => {
|
||||
if (event.angleDelta.y > 0)
|
||||
Audio.incrementSourceVolume();
|
||||
else if (event.angleDelta.y < 0)
|
||||
Audio.decrementSourceVolume();
|
||||
}
|
||||
|
||||
FilledSlider {
|
||||
anchors.fill: parent
|
||||
|
||||
icon: Icons.getMicVolumeIcon(value, Audio.sourceMuted)
|
||||
value: Audio.sourceVolume
|
||||
onMoved: Audio.setSourceVolume(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Brightness
|
||||
WrappedLoader {
|
||||
shouldBeActive: Config.osd.enableBrightness
|
||||
|
||||
sourceComponent: CustomMouseArea {
|
||||
implicitWidth: Config.osd.sizes.sliderWidth
|
||||
implicitHeight: Config.osd.sizes.sliderHeight
|
||||
|
||||
onWheel: event => {
|
||||
const monitor = root.monitor;
|
||||
if (!monitor)
|
||||
return;
|
||||
if (event.angleDelta.y > 0)
|
||||
monitor.setBrightness(monitor.brightness + 0.1);
|
||||
else if (event.angleDelta.y < 0)
|
||||
monitor.setBrightness(monitor.brightness - 0.1);
|
||||
}
|
||||
|
||||
FilledSlider {
|
||||
anchors.fill: parent
|
||||
|
||||
icon: `brightness_${(Math.round(value * 6) + 1)}`
|
||||
value: root.monitor?.brightness ?? 0
|
||||
onMoved: root.monitor?.setBrightness(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component WrappedLoader: Loader {
|
||||
required property bool shouldBeActive
|
||||
|
||||
Layout.preferredHeight: shouldBeActive ? Config.osd.sizes.sliderHeight : 0
|
||||
opacity: shouldBeActive ? 1 : 0
|
||||
active: opacity > 0
|
||||
asynchronous: true
|
||||
visible: active
|
||||
|
||||
Behavior on Layout.preferredHeight {
|
||||
Anim {
|
||||
easing.bezierCurve: Appearance.anim.curves.emphasized
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
Anim {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Item {
|
|||
id: root
|
||||
|
||||
required property ShellScreen screen
|
||||
required property bool visibility
|
||||
required property var visibilities
|
||||
|
||||
visible: width > 0
|
||||
implicitWidth: 0
|
||||
|
|
@ -16,7 +16,7 @@ Item {
|
|||
|
||||
states: State {
|
||||
name: "visible"
|
||||
when: root.visibility && Config.osd.enabled
|
||||
when: root.visibilities.osd && Config.osd.enabled
|
||||
|
||||
PropertyChanges {
|
||||
root.implicitWidth: content.implicitWidth
|
||||
|
|
@ -50,5 +50,6 @@ Item {
|
|||
id: content
|
||||
|
||||
monitor: Brightness.getMonitorForScreen(root.screen)
|
||||
visibilities: root.visibilities
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ Singleton {
|
|||
readonly property bool muted: !!sink?.audio?.muted
|
||||
readonly property real volume: sink?.audio?.volume ?? 0
|
||||
|
||||
readonly property bool sourceMuted: !!source?.audio?.muted
|
||||
readonly property real sourceVolume: source?.audio?.volume ?? 0
|
||||
|
||||
function setVolume(newVolume: real): void {
|
||||
if (sink?.ready && sink?.audio) {
|
||||
sink.audio.muted = false;
|
||||
|
|
@ -44,6 +47,21 @@ Singleton {
|
|||
setVolume(volume - (amount || Config.services.audioIncrement));
|
||||
}
|
||||
|
||||
function setSourceVolume(newVolume: real): void {
|
||||
if (source?.ready && source?.audio) {
|
||||
source.audio.muted = false;
|
||||
source.audio.volume = Math.max(0, Math.min(1, newVolume));
|
||||
}
|
||||
}
|
||||
|
||||
function incrementSourceVolume(amount: real): void {
|
||||
setSourceVolume(sourceVolume + (amount || Config.services.audioIncrement));
|
||||
}
|
||||
|
||||
function decrementSourceVolume(amount: real): void {
|
||||
setSourceVolume(sourceVolume - (amount || Config.services.audioIncrement));
|
||||
}
|
||||
|
||||
function setAudioSink(newSink: PwNode): void {
|
||||
Pipewire.preferredDefaultAudioSink = newSink;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -184,6 +184,12 @@ Singleton {
|
|||
return "volume_mute";
|
||||
}
|
||||
|
||||
function getMicVolumeIcon(volume: real, isMuted: bool): string {
|
||||
if (!isMuted && volume > 0)
|
||||
return "mic";
|
||||
return "mic_off";
|
||||
}
|
||||
|
||||
function getSpecialWsIcon(name: string): string {
|
||||
name = name.toLowerCase().slice("special:".length);
|
||||
if (name === "special")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue