sideright: add audio device picker

This commit is contained in:
end-4
2024-05-05 00:28:29 +07:00
parent fe62da6b2c
commit c209760d23
3 changed files with 110 additions and 24 deletions
@@ -1,6 +1,7 @@
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
import Audio from 'resource:///com/github/Aylur/ags/service/audio.js';
const { Box, Button, Icon, Label, Scrollable, Slider, Stack } = Widget;
import Variable from 'resource:///com/github/Aylur/ags/variable.js';
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
const { Box, Button, Icon, Label, Revealer, Scrollable, Slider, Stack } = Widget;
import { MaterialIcon } from '../../.commonwidgets/materialicon.js';
import { setupCursorHover } from '../../.widgetutils/cursorhover.js';
@@ -59,6 +60,96 @@ const AppVolume = (stream) => Box({
]
});
const AudioDevices = (input = false) => {
const dropdownShown = Variable(false);
const DeviceStream = (stream) => Button({
child: Box({
className: 'txt spacing-h-10',
children: [
Icon({
className: 'txt-norm symbolic-icon',
icon: stream.iconName,
}),
Label({
hexpand: true,
xalign: 0,
className: 'txt-small',
truncate: 'end',
maxWidthChars: 10,
label: stream.description,
}),
],
}),
onClicked: (self) => {
if (input) Audio.microphone = stream;
else Audio.speaker = stream;
dropdownShown.value = false;
},
setup: setupCursorHover,
})
const activeDevice = Button({
onClicked: () => { dropdownShown.value = !dropdownShown.value; },
child: Box({
className: 'txt spacing-h-10',
children: [
MaterialIcon(input ? 'mic_external_on' : 'media_output', 'norm'),
Label({
hexpand: true,
xalign: 0,
className: 'txt-small',
truncate: 'end',
maxWidthChars: 10,
label: `${input ? '[In]' : '[Out]'}`,
setup: (self) => self.hook(Audio, (self) => {
self.label = `${input ? '[In]' : '[Out]'} ${input ? Audio.microphone.description : Audio.speaker.description}`;
})
}),
Label({
className: `icon-material txt-norm`,
setup: (self) => self.hook(dropdownShown, (self) => {
self.label = dropdownShown.value ? 'expand_less' : 'expand_more';
})
})
],
}),
setup: setupCursorHover,
});
const deviceSelector = Revealer({
transition: 'slide_down',
revealChild: dropdownShown.bind("value"),
transitionDuration: userOptions.animations.durationSmall,
child: Box({
vertical: true,
children: [
Box({ className: 'separator-line margin-top-5 margin-bottom-5' }),
Box({
vertical: true,
className: 'spacing-v-5 margin-top-5',
attribute: {
'updateStreams': (self) => {
const streams = input ? Audio.microphones : Audio.speakers;
self.children = streams.map(stream => DeviceStream(stream));
},
},
setup: (self) => self
.hook(Audio, self.attribute.updateStreams, 'stream-added')
.hook(Audio, self.attribute.updateStreams, 'stream-removed')
,
}),
]
})
})
return Box({
hpack: 'fill',
className: 'sidebar-volmixer-deviceselector',
vertical: true,
children: [
activeDevice,
deviceSelector,
]
})
}
export default (props) => {
const emptyContent = Box({
homogeneous: true,
@@ -95,26 +186,14 @@ export default (props) => {
,
})
})
const status = Box({
className: 'sidebar-volmixer-status spacing-h-5',
const devices = Box({
vertical: true,
className: 'spacing-v-5',
children: [
Label({
className: 'txt-small margin-top-5 margin-bottom-8',
attribute: { headphones: undefined },
setup: (self) => {
const updateAudioDevice = (self) => {
const usingHeadphones = (Audio.speaker?.stream?.port)?.toLowerCase().includes('headphone');
if (self.attribute.headphones === undefined ||
self.attribute.headphones !== usingHeadphones) {
self.attribute.headphones = usingHeadphones;
self.label = `Output: ${usingHeadphones ? 'Headphones' : 'Speakers'}`;
}
}
self.hook(Audio, updateAudioDevice);
}
})
AudioDevices(false),
AudioDevices(true),
]
});
})
const mainContent = Stack({
children: {
'empty': emptyContent,
@@ -130,7 +209,7 @@ export default (props) => {
vertical: true,
children: [
mainContent,
status,
devices,
]
});
}
+3 -3
View File
@@ -16,7 +16,7 @@ import {
ModuleRawInput
} from "./quicktoggles.js";
import ModuleNotificationList from "./centermodules/notificationlist.js";
import ModuleVolumeMixer from "./centermodules/volumemixer.js";
import ModuleAudioControls from "./centermodules/audiocontrols.js";
import ModuleWifiNetworks from "./centermodules/wifinetworks.js";
import ModuleBluetooth from "./centermodules/bluetooth.js";
import ModuleConfigure from "./centermodules/configure.js";
@@ -33,9 +33,9 @@ const centerWidgets = [
contentWidget: ModuleNotificationList(),
},
{
name: 'Volume mixer',
name: 'Audio controls',
materialIcon: 'volume_up',
contentWidget: ModuleVolumeMixer(),
contentWidget: ModuleAudioControls(),
},
{
name: 'Bluetooth',
+7
View File
@@ -913,6 +913,13 @@ $waifu_image_overlay_transparency: 0.7;
margin: 0rem 0.682rem;
}
.sidebar-volmixer-deviceselector {
@include small-rounding;
padding: 0.477rem 0.682rem;
background-color: $surfaceContainerHigh;
color: $onSurfaceVariant;
}
.sidebar-bluetooth-device {
padding: 0.682rem;
@include normal-rounding;