Skip to content

Conversation

iVolt1
Copy link

@iVolt1 iVolt1 commented Sep 7, 2025

Add metadata to fifo pipe output as requested in: Add metadata output to a pipe as it is in librespot-java #157

Functionally this works very well showing track info, duration and timing, and artwork when piped into owntone and the Home Assistant dashboard when running when running in an addon.

I used AI to help write it and don't see any issues at this point. This is my first pull request so I expect there will be nits and other issues, but I will do will what I can to help push this forward.

@iVolt1
Copy link
Author

iVolt1 commented Sep 7, 2025

This is the config.yml I have been using:

zeroconf_enabled: true # Whether to keep the device discoverable at all times, even if authenticated via other means
zeroconf_port: 0 # The port to use for Zeroconf, 0 for random
credentials:
  type: zeroconf
  zeroconf:
    persist_credentials: true # Whether to persist zeroconf user credentials even after disconnecting
server:
  enabled: true
  address: '0.0.0.0' #localhost # Which address to bind to
  port: 3678 #24879 #3678 # The server port
  allow_origin: '192.168.1.123' # Value for the Access-Control-Allow-Origin header
  cert_file: '' # Path to certificate file for TLS
  key_file: '' # Path to key file for TLS  
log_level: info # Log level configuration (trace, debug, info, warn, error)
device_id: '' # Spotify device ID (auto-generated)
device_name: 'Spotify Go' # Spotify device name
device_type: computer # Spotify device type (icon)
audio_backend: pipe # alsa # Audio backend to use (alsa, pipe, pulseaudio)
audio_output_pipe: '/media/music/librespot-java' # Path to a named pipe for audio output
audio_output_pipe_format: s16le # Audio output pipe format (s16le, s32le, f32le)
audio_buffer_time: 100
bitrate: 320 # Playback bitrate (96, 160, 320)
volume_steps: 100 # Volume steps count
initial_volume: 100 # Initial volume in steps (not applied to the mixer device)
external_volume: true # Whether volume is controlled externally 
disable_autoplay: false # Whether autoplay of more songs should be disabled
metadata_pipe:
  enabled: true
  path: '/media/music/librespot-java.metadata' # Audio pipe + .metadata
  format: "xml"
  buffer_size: 100
  

Copy link
Owner

@devgianlu devgianlu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First review, I did not test it and generally glazed over some things.

Thank you for your effort!

"google.golang.org/protobuf/proto"
)

// Update extractMetadataFromStream method signature:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tautological comment

}
}

return title, artist, album, trackID, duration, artworkURL, artworkData
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not be returning that many values

Comment on lines +167 to +173
/*
if p.primaryStream != nil {
title, artist, album, trackID, duration, artworkURL := p.extractMetadataFromStream(p.primaryStream)
p.app.log.Debugf("Sending metadata: %s by %s", title, artist)
p.UpdateTrack(title, artist, album, trackID, duration, true, artworkURL) // true = playing
}
*/
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be definitely removed?


p.UpdatePlayingState(true)

// Add this line to update position on resume
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tautological comment


p.sess.Events().PostPrimaryStreamLoad(p.primaryStream, paused)

// In loadCurrentTrack method:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tautological comment

drop bool
}

// Update MetadataCallback interface:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tautological comment

Comment on lines +10 to +11
/daemon
/go-librespot
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess these are because you are cross-compiling, but they are a bit misleading


_, err := fm.pipe.Write(data)
if err != nil {
// Close and attempt to reopen on error
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't seem reconnection happens on error

Comment on lines +98 to +105
switch fm.format {
// case "json":
// data = metadata.ToJSONFormat()
case "xml": // ADD THIS CASE
data = metadata.ToXMLFormat()
//default: // "dacp"
// data = metadata.ToDACPFormat()
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be supported right?

}

// Update UpdateTrack method signature:
func (pm *PlayerMetadata) UpdateTrack(title, artist, album, trackID string, duration time.Duration, playing bool, artworkURL string, artworkData []byte) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we can use a struct here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add metadata output to a pipe as it is in librespot-java
2 participants