-
Notifications
You must be signed in to change notification settings - Fork 747
feat: Basic local file support #1595
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
feat: Basic local file support #1595
Conversation
Spotify Connect does not allow you to move playback of a local file to the librespot device as it says that it "can't play this track". Note that this is slightly inconsistent as Spotify allows you to switch to a local file if librespot is already playing a non-local file, which currently fails with an error. However, it is possible for the desktop and iOS client to accept playback of local files. In looking at the PUT request sent to `connect-state/v1/devices/<id>` from the iOS client, it can be seen that it includes `audio/local` as an entry in the `supported_types` capability field. This commit introduces this field to the capabilities that librespot sends. For now, it is a complete lie as we do not support local file playback, but it will make the ongoing development of this feature easier, as we will not have to queue up a non-local track and attempt to switch to a local one. Testing shows that with this flag the "can't play this track" message disappears and allows librespot to (attempt) to play a local file before erroring out.
9f8be59
to
d0efe21
Compare
} | ||
|
||
fn get_uri_from_file(audio_path: &Path, extension: &str) -> Result<SpotifyUri, Error> { | ||
let src = File::open(audio_path)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of my I/O for this feature is synchronous for now.
I tried using tokio::fs
APIs but they don't appear to play ball with Symphonia's MediaSource
trait bound, however maybe into_std()
which I have just found while writing this comment could help.
Additionally, we create this lookup inside player::new()
, I get that in Rust there are no constructors and new()
is not special, but something about my C# background makes me very hesitant to make new()
async, am I right to think this?
// If we can't get metadata from the container, fall back to other tags found by probing. | ||
// Note that this is only relevant for local files. | ||
if metadata.current().is_none() { | ||
if let Some(ref mut probe_metadata) = self.probed_metadata { | ||
if let Some(inner_probe_metadata) = probe_metadata.get() { | ||
metadata = inner_probe_metadata; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This part is new, I found calling self.format.metadata
returned empty metadata with the files I had, and found this snippet in Symphonia's player example: https://github.com/pdeljanov/Symphonia/blob/master/symphonia-play/src/main.rs#L533-L536
Discussed in #1525. Adds a basic level of support for playing back local files from a connect device. The
librespot
binary must be launched with--local-file-dir
/-l
flags specifying search paths for local files. If a request is received to play a local file, and a file match is made based on the file's artist, album, track title, and duration, thenlibrespot
will now be able to play it.This support has the following caveats:
spotify:local-files
which currently causes an error in the context handling code, aslibrespot
attempts to fetch it from the API and appears to get a 404. I tried to make this work, but it feels like an abstraction for context would be beneficial so we could generate context from the filesystem (currently I think we use the proto models which are obviously tightly coupled to the Spotify API). Also, I do not understand enough about the context handling code to do a good job 😅