I think this worked before but must have regressed. The value `is_playable` was
not taken into account and instead overshadowed by a dummy method.
Fixes#1552
* chore(deps): `cargo update`
* chore: update to Rust edition 2024 and apply fixes
Update the Rust edition and apply changes required in the new edition.
Also update the Cargo manifests to reflect the edition change, and
ensure changes automatically apply to workspace members in the future.
* chore: format all code with `rustfmt`
The new Rust edition comes with some new formatting defaults, which need
to be applied since the edition was increased.
* style: change suggested matches back to `if let`
There has been a breaking change in Rust edition 2024 that changed the
behavior of `if let` statements slightly. The new behavior is more in
line with what users would expect, but could lead to problems in
existing code. The automatic edition update therefore changed such `if
let` statements to match statements instead. That lead to deeply nested
code which was hard to reason about.
This changes most of them back to regular `if let` chains, as the new
behavior shouldn't cause problems for these cases.
---------
Co-authored-by: Henrik Friedrichsen <henrik@affekt.org>
With the OAuth2 flow being default now the logic to fetch login credentials via
external programs (i.e. `pass`) has become obsolote.
This change removes documentation/config leftovers.
With librespot 0.5 the `PlayerEvent` behavior for track seeking seems to have
changed slightly and there is now a dedicated event. This broke seeking in
tracks.
With this change the dedicated event is processed and track position changes
should be picked up again.
* Add Seeked signal to Mpris interface
The Mpris2 spec includes a `Seeked` signal which should be fired when
the track position changes in an unexpected way i.e. when the user
seeks to a different part of the track.
This PR implements this signal on seek events and also when a new track
begins. The latter is not strictly required but has been observed in
other players (e.g. VLC).
Closes#1492
* chore: Use `send_mpris()` and `Duration` for conversion
* doc: Update CHANGELOG
---------
Co-authored-by: Henrik Friedrichsen <henrik@affekt.org>
* MPRIS: Restructured existing implementation
My pr addresses some of the inconsistencies in ncspot's mpris
implementation. While the previous logic was technically good enough, it
was inflexible and reported redundant information.
This will make it easier for software, that processes mpris events in
some way, to accurately react to player updates.
- 'Metadata' and 'Playback' updates have been separated into there own
command
- Mpris commands are only emitted from within spotify.rs
- Some parts of the application creation logic has been
restructured to allow for mpris events to be emitted upon startup
- The initial song loading code has been moved from 'Queue::new'
into 'Application::new'.
* MPRIS: implemented most clippy suggestions
* Fix: applied clippy suggestions + format
* MPRIS: Renamed MprisCommands to be more resonable
I've added a clippy exception so it does not complain to us about enum
variants starting with the same prefix.
---------
Co-authored-by: haruInDisguise <--help>
* added support for ap-port conf
* chore: Reindent table
* feat: Only set `ap_port` in session config if supplied by user
* docs: Update CHANGELOG
---------
Co-authored-by: Henrik Friedrichsen <henrik@affekt.org>
* fix a panic when token update fails
sometimes we get an `Err` from `token_rx.recv()`, shouldn't panic in such cases
* chore(docs): Update Changelog
---------
Co-authored-by: Henrik Friedrichsen <henrik@affekt.org>
1. `None` from `update_token` should only mean "no update needed", should not be used for errors. We now panic when worker channel is not set
2. Callers should correctly handle `None` result
* attempt to fix https://github.com/hrkfdn/ncspot/issues/1358
mpris runs inside `tokio::runtime.spawn`. At some point it hits `metadata_changed->WebApi::track->api_with_retry`, which gets 401 response and tries to update the token.
This goes into `update_token`, which at a certain point calls *blocking* `token_rx.recv()`. Tokio runtime is not happy about that, as it uses the same thread for the `run_loop` in the worker. That's why `tokio::select!` doesn't work, we're essentially deadlocking, so the worker never pick up `RequestToken` command and `update_token` block forever.
Here I'm changing `update_token` to wrap `recv` in `spawn_blocking`, which makes `update_token` return a `JoinHandle`, on which the caller has to await. This doesn't work nicely in case of mpris though, as it is not an async function, and I don't know how to make it async as it goes through the dbus `metadata_changed` interface. My best effort here is to do `and_then`, which seems to work, but I'm not confident that's the right approach.
* fmt
* move token_rx.recv inside spawn_blocking
- Remove `expect` in favor of `unwrap` when the `Result`'s error variant
contains the info in the `expect` anyway (eg. when locking things).
The line number/context are given by the backtrace.
- Remove over-specification of types (`&T` instead of
`&RWReadLockGuard`)
- Put reused values into constants
- `FromStr` instead of manual function
- Change `if let Some(()) = ...` to `if T.is_some()`
* docs: small overall documentation improvements
- Add documentation comments to various items
- Change web API return types from bool/Option to Result
- Create helper functions with descriptive names instead of comments
- Remove redundant/confusing types
- Fix some documentation comments as instructed by `cargo doc`
- Rename variables to clear names
* docs: small fixes to the documentation update
Lots of small fixes to the APIs and functions in the `library` module,
mostly following best practices outlined in the Rust library guidelines.
Changes outside the `library` module were mostly required changes after
changing function signatures.
Move the Rust and Clippy linting options into the Cargo manifest and
share them with all the packages in the workspace. This ensures a
consistent style in all packages.
* chore: remove unnecessary asynchronous channel
The channel does not need to be asynchronous as the receiving end is
used in a blocking manner and the sending end of a regular channel never
blocks.
* Fix broken merge
---------
Co-authored-by: Henrik Friedrichsen <henrik@affekt.org>
Instead of crashing on Termux, no IPC socket is created. This is a
temporary solution until a suitable runtime directory for the Termux
platform can be found.
Tabs relied heavily on `ViewExt`'s `title()` function, while also
requiring a separate `id`. The `id`, if used, should be an internal part
of the struct and not part of its API. This also removes the hashmap as
it will never be faster than sequentially looking up all the names,
since there will most likely never be that many tabs in a `TabbedView`.
Cleans up the error messages generated when errors are encountered in
the configuration file. Instead of showing the raw error message, give
clear information about the problem.