Comments (41)
Full forked-daapd metadata pipe support added:
from librespot.
stdout support would provide file writing support "for free" because of the lovely concept of pipes (which work on both UNIX-likes and Windows cmd, AFAIK). I'd advocate implementing this for stdout first, making sure to move any current stdout prints during normal operation into stderr so the stream is free of non-metadata noise.
This feature would enable me to use librespot where I can't use it currently.
from librespot.
For anyone who is interested, I added the ability to bypass the internal soft volume control and export the volume via a metadata pipe which is compatible with forked-daapd.
Use arguments --linear-volume --mixer pipe --metadata-pipe </srv/music/librespot.metadata> to properly send the volume.
I am new to Rust... It would be appreciated if someone could help to review the code.
from librespot.
Fair enough. To be honest, compiling librespot is really not very difficult. One simply installs rustup, installs the latest rust version, makes sure portaudio is installed and runs cargo build. I would rather keep librespot fairly vanilla, and have the various features such as dns-sd over mdns, etc. that frankly most users are not going to care about as compile time flags, then have a separate project as you suggested which is the bells and whistles daemon. That way, the daemon repo can handle which features it wants when compiling librespot, and the daemon/standalone binary can have all of the metadata/webserver/etc stuff built in and toggleable by runtime flags. The daemon/standalone project could then be binary that gets distributed via PPAs and such, whilst librespot is kept thin for people using it as a library.
from librespot.
I think that was Paul's intention, that all the websocket server, piped metadata, etc. go in a separate project, and librespot is simply for core functionality.
from librespot.
I like this a lot, so just to check?
librespot | librespotd? | |
---|---|---|
Releases | No releases, the master is just the latest | Have a steady release cycle (monthly?) |
Compiling | Barebones (if we release binaries at all) | All options on by default at compile time |
Locations | Only on github | Create a ppa in addition? |
from librespot.
I would ask to consider dropping the "lib" on "librespotd" to avoid confusion. "lib" always implies some kind of non-runnable component that software has to consume via code; the intent of "librespotd" is the opposite.
So, maybe respotd?
Or maybe not; now that I think about it, there's precedent for leaving the "lib" in there...
As far as package names, on Debian/Ubuntu at least, there's a reasonable precedent for having packages associated with the same project but with executables in a -bin
package. So:
librespot-dev
would provide the Rust libraries for building your own programslibrespot-bin
would provide the daemon.
We could follow the model of libtool (libtool-bin
) and libvirt (libvirt-bin
) there. libtool
keeps the lib
on its main binary program; libvirt
has libvirtd
and virsh
.
from librespot.
...unless its name is not lib-respot, but libre-spot ;-)
from librespot.
I really like the organization with separate 'base' library and a bells-and-whistles daemon, keeps the separation of duties clean, this also enables writing the daemon in other languages against a stable API.
As for the piping, separating stdout for audio data and stderr for metadata is an option, easy to handle in both controlling daemons and scripts.
My main issue with a lot of media players is that they tend to add on metadata as an afterthought instead of offering it in the audio channel implementation, ex. Pulseaudio output implementations often do not set the metadata properties even though is is somewhat defined, even album art can be pushed there as a binary blob or url (although not well defined).
So, for pulseaudio set the properties, for process control use stdout/stderr, for alsa we probably need to put it somewhere but there the picture gets messy. (at least in my head)
As for presenting album art an image web service is probably a nice way to go, a controlling daemon could subscribe to the service and push it wherever we (like a Kodi addon). But, for the Linux desktop, playing librespot on a pulseaudio interface could offer metadata like the Mopidy player does which would display but, again, the album art part is not well defined.
My input for goals on metadata are:
- Integrate into Linux desktop environment, ie something like Mopidy/Pulseaudio (dbus can of worms)
- Enable integration to media centers or multi room solutions, ie stream metadata to controlling daemon
- Offer 'the rest' some consistent way to get hold of the metadata, probably audio output adapter dependent, ie push metadata to the audio output adapter in daemon.
I.E. Command line flags select audio output devices with metadata. Then an option to start the web service.
So, for me this leaves the question, should we modify the audio output adapter interface in the base library? Open it for the bells-and-whistles daemon to extend it with metadata or move the functionality there?
Nice work setting up the org π
Almost forgot, json, encoding (album art), tag standards (Vorbis?)... probably more to think about here.
But, standardize on something open and language/protocol independent...
Ops, almost forgot more, as we can not possibly push everything Spotify provides or any1 could possibly want we should add a tag for song Spotify reference, enables lookup for further info. Also, if librespot http service is enabled a reference to this.
from librespot.
Hi @frafall I agree, I'm doing some research on it now.
This is a good read as you know.
More for reference this is the web API track object. I feel this may be easier to use if there is an easy way to authenticate with the API (So far I've found it a pain)
As in the above issue I would also say that writing to file may be the best way as it is somewhat easy to get information from. Of course other ways could be added but I would say that write to file should be the first focus.
from librespot.
Some issues with file writes, u never know if the data is current or some leftover from earlier runs, it's localized inside a docker image or VM (unless exported explicitly) and pushing new data is a hassle as u either have to add new data at end or re-write file and leave it to the client to poll this. I like push options.
My ideal solution would be opening a socket to libreelec where it pushed data, kinda similar to listening to stderr or a pipe if you have control of the process. I kinda dislike pipes due to the locality (single machine) and single reader things.
But, for now I've been happy reading the stdout output, rather that than a file.
from librespot.
I see where you're coming from with writing to file, however its sometimes the only way to feed from other programs the information. Usually by polling said file, containing only now playing metadata. (I don't like it either).
I think like you some sort of push service were other devices listen would be best, but I feel that should be as a secondary objective.
Also not everyone will want metadata so I think it should be an option, views?
I think stout should be a priority as it would be one of the easiest get a proof as concept.
from librespot.
I did implement a (dodgy) websockets server a little while back in an earlier version of librespot that pumped out metadata to clients on various changes, though it wasn't merged as Paul wanted to keep librespot relatively minimal. With regards to metadata format, do we think JSON would be suitable? I only suggest that so that those who choose to interact with the Web API as well don't have to think about multiple data formats.
Also, I agree that the metadata output should be optional, some people just dont need it if they integrate with librespot directly. Perhaps a compile time flag if people want metadata output?
from librespot.
I would prefer a meta-data pipe. That would be compatible with forked-daapd.
from librespot.
See here: owntone/owntone-server#278
from librespot.
Well, maybe it's just because I'm curmudgeonly, but I'd prefer not to have to write any code in Rust. What I'd like is for the example Spotify Connect daemon that comes with librespot to offer a metadata to stdout flag. You could implement similar backends for other protocols too, even HTTP. With the new librespot-org we don't have to worry about if Paul wants to keep the thing minimal if the current maintainers don't feel that way ;)
Since librespot has PulseAudio output, you can kinda see where I'm going with my design if you look at what Tribblify can do... Keeping in mind that all sinks have a source named sinkname.monitor
in PulseAudio... ;)
As far as data format, any of the following would work for my purposes:
- JSON
- XML
- CSV
- URL encoded param string (like
artist=foo&song=Benny & the Jets
)
What probably wouldn't work is having the format be Artist - Song Title
, because then how would you parse a string like: Andrea Bocelli - Live - Phantom of the Opera - Venice
? Where is the delimiter between artist and song title? I have this current limitation with my parsing of the Spotify window title, so switching to librespot would be a marked improvement there. Plus it'd be headless.
from librespot.
I get where you're coming from, I'm not a huge fan of rust either. However, in the interests of maintainability, I do think he was right not to allow things like a websockets server to be baked in to librespot with no way to turn it off. However, compile-time feature flags are our friend here, to a certain extent, in that any pipe/websocket/etc. solution can be selectively enabled at compile time. I.e. those who don't want a bigger executable can just build without the features they don't need. I do agree with you though, in that whilst librespot is technically a library, I get the feeling that most people are using it as a daemon/standalone program, thus not having metadata easily available in daemon mode is a pain.
from librespot.
Perhaps a separate GH project entirely for the daemon that's actually featureful? That would be amazing! :) It could go under librespot-org, too...
from librespot.
The only reason I get a little nervous about compile-time flags is that, if actually compiling the thing is a nightmare (which could happen if we keep super up to date with the latest Rust stuff and you're running, say, Ubuntu 16.04 with 2 year old Rust), and binaries happen to be conveniently available from distro packages or a PPA, then we'd want to make sure that distros ship with all possible options enabled at compile-time, and just have them be runtime flags.
I agree with you that having a web server enabled by default is way overkill, but I think all the possible features of the daemon should be there in a default compile, and encourage anyone packaging binaries, whether it be Ubuntu or a PPA maintainer or some other distro, to enable all options. Everything that's a compile-time flag should also be disabled by default in the daemon if you just run it with only the minimum required arguments to establish a Spotify connection; to get extra features like metadata, it's fine to expect the user to have to pass a command-line argument.
I don't think code size is an issue even on a Raspberry Pi, because the storage capacity of MicroSD cards is ridiculous these days. Compiling in Rust code for a web server may add a megabyte to the code; it may add five megabytes... I can't bring myself to care at all on any platforms that would have the cycles to run librespot in the first place.
from librespot.
That way, the daemon repo can handle which features it wants when compiling librespot, and the daemon/standalone binary can have all of the metadata/webserver/etc stuff built in and toggleable by runtime flags. The daemon/standalone project could then be binary that gets distributed via PPAs and such, whilst librespot is kept thin for people using it as a library.
Yeah, that sounds like a great plan.
from librespot.
Yeah, that sounds about right.
from librespot.
As for piping out metadata to stdout: this would become difficult if librespot was set up to pipe the audio data to stdout. Which is part of the options now, and which I do indeed use in my case.
from librespot.
Just so as to not clutter this issue continued discussion of librespotd (or whatever we call it) should continue here: #20
from librespot.
For reference, #25 is semi-related.
from librespot.
Search functionality: #23
from librespot.
Any chance this gets merged?
from librespot.
If he opens a PR and then once it's reviewed, sure.
from librespot.
#214 PR created.
from librespot.
This is brilliant. I'll give your repo a clone while we wait for the daemon. Thanks @billsq !
from librespot.
So I cloned the rep to get this fix. Compiling was successful and the client runs.
The pipe.metadata file has the same name as the pipe and is in the same dir. It is readable and writable.
However forked-daapd is not picking up any metadata. It plays the source fine, but volume changes do not work.
No other metadata about the sourve is displayed.
from librespot.
@chimpy Does your pipe.metadata have the same permission as your pipe file? Did you run librespot with the arguments I mentioned above? Did you restart your forked-daapd?
from librespot.
Hi @billsq ! Thanks for the reply. Details below:
chimpy@hassbox:/opt/music$ ls -lh
total 4.0K
prw-r--r-- 1 root root 0 Aug 1 21:24 spotify
-rw-r--r-- 1 root root 135 Aug 1 21:24 spotify.metadata
librespot -n "House Speakers" -b 320 -c /var/cache/spotify --initial-volume 30 --device-type avr -u chimpy -p "redacted" --backend pipe --device /opt/music/spotify --linear-volume --mixer pipe --metadata-pipe /opt/music/spotify.metadata
I have restarted forked-daapd before using your fork, no change. If I do a tail -f
on the metadata file when adjusting volume, playing and changing a song I see it updating, but no change on forked-daapd's side.
Ah, this gets mentioned in forked-daapd's log:
forked-daapd[19611]: [ LOG] player: Source type is pipe, but path is not a fifo: /opt/music/spotify.metadata
OK, so I realised that maybe spotify.metadata
should be a pipe as well. I did a mkfifo /opt/music/spotify.metadata
and restarted forked-daapd but now librespot authenticates and then hangs. It does not appear in the client list.
from librespot.
Try restarting librespot. spotify.metadata
should be a pipe.
from librespot.
Hey bill, not sure if you saw my edited comment, but I did that. I did mkfifo spotify.metadata. When I restart librespot it hangs after authenticating my user but before showing the country code.
from librespot.
It happens to me with stock librespot sometimes. Just try to restart it. I donβt think it has anything to do with the pipe code.
from librespot.
from librespot.
@billsq Everything still working for you? The problem above has back for me with a vengeance. After a about 40 start/stops, it's still hanging before getting the country code.
from librespot.
It is working as usual.
from librespot.
Has this been merged? Using --mixer pipe --metadata-pipe /srv/music/spotify.metadata
gives me error: Unrecognized option: 'metadata-pipe'
on what I built from source yesterday
from librespot.
from librespot.
@chimpy Finally found the root cause or your issue. It is due to forked-daapd doesn't open metadata pipe by default. Now should be working fine.
from librespot.
Related Issues (20)
- Excessive onevent "playing" notifications HOT 1
- OpenVPN interference with Librespot's Spotify Connect feature HOT 1
- Gapless play and next button HOT 11
- Track not available on librespot 0.4.2 HOT 6
- Play example needs to be updated HOT 2
- librespot/snapcast sometimes plays like /dev/random :fearful: HOT 3
- librespot crashes if volume is not changed first HOT 3
- Configurable MINIMUN_DOWNLOAD_SIZE / audio fetch parameters HOT 3
- `Could not get Alsa softvol dB range` when trying to control PipeWire volume via ALSA HOT 2
- error audio key, unable to load key
- called `Result::unwrap()` on an `Err` value: AuthenticationError(LoginFailed(PremiumAccountRequired)) HOT 1
- Music stops abruptly when playing long playlists HOT 1
- librespot / SPIRC crashed in the middle of the night HOT 4
- [Feature Request] Allow downloading of playlists for listening offline HOT 2
- Authentication on all desktop platforms is broken HOT 1
- Android Hashcash Not working? HOT 1
- New Stream reporting payload (Mercury)
- support for setting volume directly in addition to volume up/down HOT 1
- Librespot instance not shown in latest android/web spotify app HOT 5
- High CPU usage and stutter for some songs HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from librespot.