Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ device_id: '' # Spotify device ID (auto-generated)
device_name: '' # Spotify device name
device_type: computer # Spotify device type (icon)
audio_backend: alsa # Audio backend to use (alsa, pipe, pulseaudio)
audio_backend_runtime_socket: '' # Audio backends' runtime socket to use, if backend is pulseaudio
audio_device: default # ALSA audio device to use for playback
mixer_device: '' # ALSA mixer device for volume synchronization
mixer_control_name: Master # ALSA mixer control name for volume synchronization
Expand Down Expand Up @@ -232,4 +233,4 @@ or using Go:

```shell
go generate ./...
```
```
10 changes: 6 additions & 4 deletions cmd/daemon/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,11 @@ func (app *App) newAppPlayer(ctx context.Context, creds any) (_ *AppPlayer, err

CountryCode: appPlayer.countryCode,

AudioBackend: app.cfg.AudioBackend,
AudioDevice: app.cfg.AudioDevice,
MixerDevice: app.cfg.MixerDevice,
MixerControlName: app.cfg.MixerControlName,
AudioBackend: app.cfg.AudioBackend,
AudioBackendRuntimeSocket: app.cfg.AudioBackendRuntimeSocket,
AudioDevice: app.cfg.AudioDevice,
MixerDevice: app.cfg.MixerDevice,
MixerControlName: app.cfg.MixerControlName,

AudioBufferTime: app.cfg.AudioBufferTime,
AudioPeriodCount: app.cfg.AudioPeriodCount,
Expand Down Expand Up @@ -393,6 +394,7 @@ type Config struct {
DeviceType string `koanf:"device_type"`
ClientToken string `koanf:"client_token"`
AudioBackend string `koanf:"audio_backend"`
AudioBackendRuntimeSocket string `koanf:"audio_backend_runtime_socket"`
AudioDevice string `koanf:"audio_device"`
MixerDevice string `koanf:"mixer_device"`
MixerControlName string `koanf:"mixer_control_name"`
Expand Down
5 changes: 5 additions & 0 deletions config_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@
],
"default": "alsa"
},
"audio_backend_runtime_socket": {
"type": "string",
"description": "The audio backend runtime socket, useful only with pulseaudio as a backend",
"default": ""
},
"audio_device": {
"type": "string",
"description": "Which audio device should be used for playback, leave empty for default",
Expand Down
15 changes: 11 additions & 4 deletions output/driver-pulseaudio.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,13 @@ func newPulseAudioOutput(opts *NewOutputOptions) (*pulseAudioOutput, error) {
// The device name is shown by PulseAudio volume controls (usually built
// into a desktop environment), so we might want to use device_name here.
// We could also maybe change the application icon name by device_type.
client, err := pulse.NewClient(pulse.ClientApplicationName("go-librespot"), pulse.ClientApplicationIconName("speaker"))
clientopts := []pulse.ClientOption{pulse.ClientApplicationName("go-librespot"), pulse.ClientApplicationIconName("speaker")}

if opts.RuntimeSocket != "" {
clientopts = append(clientopts, pulse.ClientServerString(opts.RuntimeSocket))
}

client, err := pulse.NewClient(clientopts...)
if err != nil {
return nil, err
}
Expand All @@ -43,11 +49,12 @@ func newPulseAudioOutput(opts *NewOutputOptions) (*pulseAudioOutput, error) {

// Create a new playback.
var channelOpt pulse.PlaybackOption
if opts.ChannelCount == 1 {
switch opts.ChannelCount {
case 1:
channelOpt = pulse.PlaybackMono
} else if opts.ChannelCount == 2 {
case 2:
channelOpt = pulse.PlaybackStereo
} else {
default:
return nil, fmt.Errorf("cannot play %d channels, pulse only supports mono and stereo", opts.ChannelCount)
}
volumeUpdates := make(chan proto.ChannelVolumes, 1)
Expand Down
7 changes: 6 additions & 1 deletion output/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,13 @@ type NewOutputOptions struct {

// Device specifies the audio device name.
//
// This feature is support only for the alsa backend.
// This feature is support only for the alsa and pulseaudio backend.
Device string
// RuntimeSocket specifies a prefixed with protocol (e.g. `unix:` or `tcp:`) path
// to a runtime socket of audio backend.
//
// This feature is support only for pulseaudio backend.
RuntimeSocket string

// Mixer specifies the audio mixer name.
//
Expand Down
9 changes: 7 additions & 2 deletions player/player.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,14 @@ type Options struct {

// AudioBackend specifies the audio backend to use (alsa, pulseaudio, etc).
AudioBackend string
// AudioBackendRuntimeSocket specifies a prefixed with protocol (e.g. `unix:` or `tcp:`) path
// to a runtime socket of audio backend.
//
// This feature is support only for the pulseaudio backend.
AudioBackendRuntimeSocket string
// AudioDevice specifies the audio device name.
//
// This feature is support only for the alsa backend.
// This feature is support only for the alsa and pulseaudio backend.
AudioDevice string
// MixerDevice specifies the audio mixer name.
//
Expand All @@ -126,7 +131,6 @@ type Options struct {
//
// This only works in combination with Mixer.
MixerControlName string

// AudioBufferTime is the buffer time in microseconds.
//
// This is only supported on the alsa backend.
Expand Down Expand Up @@ -178,6 +182,7 @@ func NewPlayer(opts *Options) (*Player, error) {
SampleRate: SampleRate,
ChannelCount: Channels,
Device: opts.AudioDevice,
RuntimeSocket: opts.AudioBackendRuntimeSocket,
Mixer: opts.MixerDevice,
Control: opts.MixerControlName,
InitialVolume: volume,
Expand Down
Loading