62 lines
2.0 KiB
Go
62 lines
2.0 KiB
Go
//go:build windows
|
|
|
|
package player
|
|
|
|
import (
|
|
"fmt"
|
|
"os/exec"
|
|
"strings"
|
|
)
|
|
|
|
// ListAudioDevices lists audio output devices via PowerShell on Windows.
|
|
func ListAudioDevices() ([]AudioDevice, error) {
|
|
// Use Get-CimInstance Win32_SoundDevice for basic sound card enumeration.
|
|
script := `Get-CimInstance Win32_SoundDevice | ForEach-Object { $_.Name + '|' + $_.DeviceID }`
|
|
out, err := exec.Command("powershell", "-NoProfile", "-Command", script).Output()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("powershell: %w", err)
|
|
}
|
|
|
|
var devices []AudioDevice
|
|
for i, line := range strings.Split(strings.TrimSpace(string(out)), "\n") {
|
|
line = strings.TrimSpace(line)
|
|
if line == "" {
|
|
continue
|
|
}
|
|
name, id, _ := strings.Cut(line, "|")
|
|
devices = append(devices, AudioDevice{
|
|
Index: i,
|
|
Name: strings.TrimSpace(id),
|
|
Description: strings.TrimSpace(name),
|
|
Active: false,
|
|
})
|
|
}
|
|
return devices, nil
|
|
}
|
|
|
|
// PrepareAudioDevice is a no-op on Windows — the system default output
|
|
// device is used. Returns a no-op cleanup.
|
|
func PrepareAudioDevice(device string) func() {
|
|
return func() {}
|
|
}
|
|
|
|
// SwitchAudioDevice changes the Windows system default output device.
|
|
// The running audio stream keeps its original device; the change
|
|
// takes full effect on the next app restart.
|
|
func SwitchAudioDevice(deviceName string) error {
|
|
script := fmt.Sprintf(
|
|
`Get-AudioDevice -PlaybackCommunication | Out-Null; `+
|
|
`Set-AudioDevice -ID '%s' -ErrorAction Stop`,
|
|
strings.ReplaceAll(deviceName, "'", "''"),
|
|
)
|
|
if out, err := exec.Command("powershell", "-NoProfile", "-Command", script).CombinedOutput(); err != nil {
|
|
// AudioDeviceCmdlets may not be installed; fall back to nircmd.
|
|
cmd := exec.Command("nircmd", "setdefaultsounddevice", deviceName)
|
|
if out2, err2 := cmd.CombinedOutput(); err2 != nil {
|
|
return fmt.Errorf("failed to set output device (install AudioDeviceCmdlets or nircmd): %s / %s",
|
|
strings.TrimSpace(string(out)), strings.TrimSpace(string(out2)))
|
|
}
|
|
}
|
|
return nil
|
|
}
|