Files
MujicaUI/device_selector.go
T

79 lines
2.5 KiB
Go

package mujica
import (
"log/slog"
"github.com/egoist/mygo/ui"
"mujicaui/theme"
)
// MediaDevice is one device; IDs are unique within a kind.
type MediaDevice struct {
ID, Name string
}
// MediaDevices are the caller's lists; nil hides that kind.
type MediaDevices struct {
Microphones, Cameras, Speakers []MediaDevice
}
// DeviceSelection holds each kind's chosen ID; empty is none.
type DeviceSelection struct {
Microphone, Camera, Speaker string
}
// DeviceSelectorOptions configure a DeviceSelector.
type DeviceSelectorOptions struct {
Disabled bool
}
// DeviceSelector chooses a microphone, camera and speaker.
func DeviceSelector(c *ui.Context, sel *DeviceSelection, devices MediaDevices, opts DeviceSelectorOptions) ChoiceResult {
old := *sel
k := Tokens(c)
u := Density(c).Unit()
col := ui.Column(c).Gap(u * 3).Role(ui.RoleGroup).Label(msg(c, "device_selector.label")).Disabled(opts.Disabled)
col.Children(func() {
deviceRow(c, k, mediaMic, "device_selector.microphone", &sel.Microphone, devices.Microphones, opts.Disabled)
deviceRow(c, k, mediaCamera, "device_selector.camera", &sel.Camera, devices.Cameras, opts.Disabled)
deviceRow(c, k, mediaSpeaker, "device_selector.speaker", &sel.Speaker, devices.Speakers, opts.Disabled)
})
changed := *sel != old
if changed {
slog.Debug("mujica: device_selector changed", "selection", *sel)
}
return ChoiceResult{Element: col, changed: changed}
}
func deviceRow(c *ui.Context, k theme.Tokens, icon *ui.SVG, key string, id *string, list []MediaDevice, disabled bool) {
if list == nil {
return
}
options := make([]SelectOption[string], len(list))
for i, d := range list {
if d.ID == "" {
panic("mujica: DeviceSelector device without an ID")
}
for _, o := range options[:i] {
if o.Value == d.ID {
panic("mujica: DeviceSelector duplicate device ID " + d.ID)
}
}
options[i] = SelectOption[string]{Value: d.ID, Label: d.Name}
}
if _, ok := selectLabel(options, *id); *id != "" && !ok {
panic("mujica: DeviceSelector selection " + *id + " is not in its list")
}
ui.Row(c).Gap(Density(c).Unit() * 2).AlignItems(ui.Center).Children(func() {
ui.Icon(c, icon).Size(16, 16).TextColor(k.TextMuted)
ui.Text(c, msg(c, key)).Width(96).SingleLine()
hint := msg(c, "device_selector.choose")
if len(list) == 0 {
hint = msg(c, "device_selector.none")
}
Select(c, id, options, SelectOptions{Disabled: disabled || len(list) == 0, Label: msg(c, key),
Placeholder: hint, Empty: msg(c, "device_selector.none")}).Element.Grow(1)
})
}