mirror of
https://github.com/navidrome/navidrome.git
synced 2025-04-13 02:37:18 +03:00
Jukebox cleanup (#2554)
* Fixing typo FFmpegPath -> MPVPath * Fixing panic by applying afontenot patch * Using mpv audio-device flag and naming for config and playback
This commit is contained in:
parent
2cd4358172
commit
59f0c487e7
@ -24,7 +24,6 @@ type PlaybackDevice struct {
|
||||
Default bool
|
||||
User string
|
||||
Name string
|
||||
Method string
|
||||
DeviceName string
|
||||
PlaybackQueue *Queue
|
||||
Gain float32
|
||||
@ -60,12 +59,11 @@ func (pd *PlaybackDevice) getStatus() DeviceStatus {
|
||||
// NewPlaybackDevice creates a new playback device which implements all the basic Jukebox mode commands defined here:
|
||||
// http://www.subsonic.org/pages/api.jsp#jukeboxControl
|
||||
// Starts the trackSwitcher goroutine for the device.
|
||||
func NewPlaybackDevice(playbackServer PlaybackServer, name string, method string, deviceName string) *PlaybackDevice {
|
||||
func NewPlaybackDevice(playbackServer PlaybackServer, name string, deviceName string) *PlaybackDevice {
|
||||
return &PlaybackDevice{
|
||||
ParentPlaybackServer: playbackServer,
|
||||
User: "",
|
||||
Name: name,
|
||||
Method: method,
|
||||
DeviceName: deviceName,
|
||||
Gain: DefaultGain,
|
||||
PlaybackQueue: NewQueue(),
|
||||
@ -146,12 +144,12 @@ func (pd *PlaybackDevice) Skip(ctx context.Context, index int, offset int) (Devi
|
||||
pd.ActiveTrack.Pause()
|
||||
}
|
||||
|
||||
if index != pd.PlaybackQueue.Index {
|
||||
if pd.ActiveTrack != nil {
|
||||
pd.ActiveTrack.Close()
|
||||
pd.ActiveTrack = nil
|
||||
}
|
||||
if index != pd.PlaybackQueue.Index && pd.ActiveTrack != nil {
|
||||
pd.ActiveTrack.Close()
|
||||
pd.ActiveTrack = nil
|
||||
}
|
||||
|
||||
if pd.ActiveTrack == nil {
|
||||
err := pd.switchActiveTrackByIndex(index)
|
||||
if err != nil {
|
||||
return pd.getStatus(), err
|
||||
@ -278,7 +276,7 @@ func (pd *PlaybackDevice) switchActiveTrackByIndex(index int) error {
|
||||
return fmt.Errorf("could not get current track")
|
||||
}
|
||||
|
||||
track, err := mpv.NewTrack(pd.PlaybackDone, *currentTrack)
|
||||
track, err := mpv.NewTrack(pd.PlaybackDone, pd.DeviceName, *currentTrack)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ import (
|
||||
|
||||
// mpv --no-audio-display --pause 'Jack Johnson/On And On/01 Times Like These.m4a' --input-ipc-server=/tmp/gonzo.socket
|
||||
const (
|
||||
mpvComdTemplate = "mpv --no-audio-display --pause %f --input-ipc-server=%s"
|
||||
mpvComdTemplate = "mpv --audio-device=%d --no-audio-display --pause %f --input-ipc-server=%s"
|
||||
)
|
||||
|
||||
func start(args []string) (Executor, error) {
|
||||
@ -81,9 +81,10 @@ func (j *Executor) wait() {
|
||||
}
|
||||
|
||||
// Path will always be an absolute path
|
||||
func createMPVCommand(cmd, filename string, socketName string) []string {
|
||||
func createMPVCommand(cmd, deviceName string, filename string, socketName string) []string {
|
||||
split := strings.Split(fixCmd(cmd), " ")
|
||||
for i, s := range split {
|
||||
s = strings.ReplaceAll(s, "%d", deviceName)
|
||||
s = strings.ReplaceAll(s, "%f", filename)
|
||||
s = strings.ReplaceAll(s, "%s", socketName)
|
||||
split[i] = s
|
||||
@ -110,7 +111,7 @@ func fixCmd(cmd string) string {
|
||||
func mpvCommand() (string, error) {
|
||||
mpvOnce.Do(func() {
|
||||
if conf.Server.MPVPath != "" {
|
||||
mpvPath = conf.Server.FFmpegPath
|
||||
mpvPath = conf.Server.MPVPath
|
||||
mpvPath, mpvErr = exec.LookPath(mpvPath)
|
||||
} else {
|
||||
mpvPath, mpvErr = exec.LookPath("mpv")
|
||||
|
@ -24,7 +24,7 @@ type MpvTrack struct {
|
||||
CloseCalled bool
|
||||
}
|
||||
|
||||
func NewTrack(playbackDoneChannel chan bool, mf model.MediaFile) (*MpvTrack, error) {
|
||||
func NewTrack(playbackDoneChannel chan bool, deviceName string, mf model.MediaFile) (*MpvTrack, error) {
|
||||
log.Debug("loading track", "trackname", mf.Path, "mediatype", mf.ContentType())
|
||||
|
||||
if _, err := mpvCommand(); err != nil {
|
||||
@ -33,7 +33,7 @@ func NewTrack(playbackDoneChannel chan bool, mf model.MediaFile) (*MpvTrack, err
|
||||
|
||||
tmpSocketName := TempFileName("mpv-ctrl-", ".socket")
|
||||
|
||||
args := createMPVCommand(mpvComdTemplate, mf.Path, tmpSocketName)
|
||||
args := createMPVCommand(mpvComdTemplate, deviceName, mf.Path, tmpSocketName)
|
||||
exe, err := start(args)
|
||||
if err != nil {
|
||||
log.Error("error starting mpv process", "error", err)
|
||||
|
@ -46,8 +46,11 @@ func (ps *playbackServer) Run(ctx context.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Info(ctx, fmt.Sprintf("%d audio devices found", len(conf.Server.Jukebox.Devices)))
|
||||
log.Info(ctx, "Using default audio device: "+conf.Server.Jukebox.Default)
|
||||
log.Info(ctx, fmt.Sprintf("%d audio devices found", len(devices)))
|
||||
|
||||
defaultDevice, _ := ps.getDefaultDevice()
|
||||
|
||||
log.Info(ctx, "Using audio device: "+defaultDevice.DeviceName)
|
||||
|
||||
ps.ctx = &ctx
|
||||
|
||||
@ -61,15 +64,37 @@ func (ps *playbackServer) GetCtx() *context.Context {
|
||||
}
|
||||
|
||||
func (ps *playbackServer) initDeviceStatus(devices []conf.AudioDeviceDefinition, defaultDevice string) ([]PlaybackDevice, error) {
|
||||
pbDevices := make([]PlaybackDevice, len(devices))
|
||||
pbDevices := make([]PlaybackDevice, max(1, len(devices)))
|
||||
defaultDeviceFound := false
|
||||
|
||||
for idx, audioDevice := range devices {
|
||||
if len(audioDevice) != 3 {
|
||||
return []PlaybackDevice{}, fmt.Errorf("audio device definition ought to contain 3 fields, found: %d ", len(audioDevice))
|
||||
if defaultDevice == "" {
|
||||
// if there are no devices given and no default device, we create a sythetic device named "auto"
|
||||
if len(devices) == 0 {
|
||||
pbDevices[0] = *NewPlaybackDevice(ps, "auto", "auto")
|
||||
}
|
||||
|
||||
pbDevices[idx] = *NewPlaybackDevice(ps, audioDevice[0], audioDevice[1], audioDevice[2])
|
||||
// if there is but only one entry and no default given, just use that.
|
||||
if len(devices) == 1 {
|
||||
if len(devices[0]) != 2 {
|
||||
return []PlaybackDevice{}, fmt.Errorf("audio device definition ought to contain 2 fields, found: %d ", len(devices[0]))
|
||||
}
|
||||
pbDevices[0] = *NewPlaybackDevice(ps, devices[0][0], devices[0][1])
|
||||
}
|
||||
|
||||
if len(devices) > 1 {
|
||||
return []PlaybackDevice{}, fmt.Errorf("number of audio device found is %d, but no default device defined. Set Jukebox.Default", len(devices))
|
||||
}
|
||||
|
||||
pbDevices[0].Default = true
|
||||
return pbDevices, nil
|
||||
}
|
||||
|
||||
for idx, audioDevice := range devices {
|
||||
if len(audioDevice) != 2 {
|
||||
return []PlaybackDevice{}, fmt.Errorf("audio device definition ought to contain 2 fields, found: %d ", len(audioDevice))
|
||||
}
|
||||
|
||||
pbDevices[idx] = *NewPlaybackDevice(ps, audioDevice[0], audioDevice[1])
|
||||
|
||||
if audioDevice[0] == defaultDevice {
|
||||
pbDevices[idx].Default = true
|
||||
|
Loading…
x
Reference in New Issue
Block a user