music-assistant-server.git
2 months agoAdd debug logging for scrobbled tracks (#3091)
Monkey Do [Thu, 5 Feb 2026 13:27:27 +0000 (14:27 +0100)]
Add debug logging for scrobbled tracks (#3091)

There is a debug trace for playing-now listens, but not for full scrobbles, making it harder to diagnose potential issues

2 months agoFix Yandex Music provider for lossless streaming support (#3093)
Mikhail Nevskiy [Thu, 5 Feb 2026 13:25:29 +0000 (16:25 +0300)]
Fix Yandex Music provider for lossless streaming support (#3093)

* yandex_music: Add lossless streaming via get-file-info API and unit tests

Improve Yandex Music provider with proper lossless (FLAC) streaming support
and comprehensive test coverage.

## Changes

### Lossless Streaming (api_client.py, streaming.py)
- Add `get_track_file_info_lossless()` API method using `/get-file-info`
  endpoint with quality=lossless parameter
- Prefer flac-mp4/aac-mp4 codecs (Yandex API 2025 format)
- Implement retry logic: try transports=encraw first, fallback to
  transports=raw on 401 Unauthorized
- When lossless requested, try get-file-info first (returns FLAC),
  fallback to download-info if unavailable

### Provider improvements (provider.py)
- Minor variable naming fix in get_track()

### Documentation (README.md)
- Add provider README with OAuth token instructions
- Document audio quality settings and lossless troubleshooting

### Tests
- Add unit tests for parsers (artists, albums, tracks, playlists)
- Add unit tests for streaming quality selection logic
- Add snapshot tests for consistent parsing output
- Add fixtures and stubs in conftest.py
- Add integration and e2e test scaffolding

https://claude.ai/code/session_01S4Eth5mUC7hLd3K3JxX7Cy

* Delete tests/providers/yandex_music/test_e2e_server.py

* Update Yandex Music documentation URL

---------

Co-authored-by: Claude <noreply@anthropic.com>
2 months agoAdd album year to track SQL query (#3085)
Dionysis Fortis [Thu, 5 Feb 2026 13:04:04 +0000 (15:04 +0200)]
Add album year to track SQL query (#3085)

* Add album year to track SQL query

* Bump models to 1.1.96 and update snapshots

2 months agofix: cache check for expire (#3087)
relic664 [Thu, 5 Feb 2026 10:24:18 +0000 (05:24 -0500)]
fix: cache check for expire (#3087)

* fix: cache check for expire

* fixed formatting

2 months agoApple Music: Limit get_library_tracks to 150 songs per batch (#3094)
MizterB [Thu, 5 Feb 2026 09:32:59 +0000 (04:32 -0500)]
Apple Music: Limit get_library_tracks to 150 songs per batch (#3094)

Reduce max_limit to 150

2 months ago⬆️ Update music-assistant-frontend to 2.17.80 (#3097)
music-assistant-machine [Thu, 5 Feb 2026 03:42:16 +0000 (04:42 +0100)]
⬆️ Update music-assistant-frontend to 2.17.80 (#3097)

Co-authored-by: marcelveldt <6389780+marcelveldt@users.noreply.github.com>
2 months ago⬆️ Update music-assistant-frontend to 2.17.79 (#3089)
music-assistant-machine [Wed, 4 Feb 2026 03:41:30 +0000 (04:41 +0100)]
⬆️ Update music-assistant-frontend to 2.17.79 (#3089)

Co-authored-by: marcelveldt <6389780+marcelveldt@users.noreply.github.com>
2 months agoChore(deps): Bump ytmusicapi from 1.11.3 to 1.11.5 (#3081)
dependabot[bot] [Tue, 3 Feb 2026 10:18:48 +0000 (10:18 +0000)]
Chore(deps): Bump ytmusicapi from 1.11.3 to 1.11.5 (#3081)

* Chore(deps): Bump ytmusicapi from 1.11.3 to 1.11.5

Bumps [ytmusicapi](https://github.com/sigma67/ytmusicapi) from 1.11.3 to 1.11.5.
- [Release notes](https://github.com/sigma67/ytmusicapi/releases)
- [Commits](https://github.com/sigma67/ytmusicapi/compare/1.11.3...1.11.5)

---
updated-dependencies:
- dependency-name: ytmusicapi
  dependency-version: 1.11.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
* Also bump the provider manifest.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Marvin Schenkel <marvinschenkel@gmail.com>
2 months agoChore(deps-dev): Bump pre-commit from 4.5.0 to 4.5.1 (#3082)
dependabot[bot] [Tue, 3 Feb 2026 07:39:45 +0000 (08:39 +0100)]
Chore(deps-dev): Bump pre-commit from 4.5.0 to 4.5.1 (#3082)

Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 4.5.0 to 4.5.1.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v4.5.0...v4.5.1)

---
updated-dependencies:
- dependency-name: pre-commit
  dependency-version: 4.5.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2 months agoChore(deps): Bump mashumaro from 3.17 to 3.18 (#3083)
dependabot[bot] [Tue, 3 Feb 2026 07:39:31 +0000 (08:39 +0100)]
Chore(deps): Bump mashumaro from 3.17 to 3.18 (#3083)

Bumps [mashumaro](https://github.com/Fatal1ty/mashumaro) from 3.17 to 3.18.
- [Release notes](https://github.com/Fatal1ty/mashumaro/releases)
- [Commits](https://github.com/Fatal1ty/mashumaro/compare/v3.17...v3.18)

---
updated-dependencies:
- dependency-name: mashumaro
  dependency-version: '3.18'
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2 months agoAllow all special characters in passwords (#3072)
OzGav [Mon, 2 Feb 2026 13:12:55 +0000 (00:12 +1100)]
Allow all special characters in passwords (#3072)

* fix-commas-in-passwords

* shorten comment

2 months ago⬆️ Update music-assistant-frontend to 2.17.78 (#3075)
music-assistant-machine [Mon, 2 Feb 2026 12:58:32 +0000 (13:58 +0100)]
⬆️ Update music-assistant-frontend to 2.17.78 (#3075)

Co-authored-by: MarvinSchenkel <17671719+MarvinSchenkel@users.noreply.github.com>
2 months agohass_players: Show now playing info from external playback (#3015)
Ulrich Lichtenegger [Mon, 2 Feb 2026 11:48:21 +0000 (12:48 +0100)]
hass_players: Show now playing info from external playback (#3015)

* HASS Provider: Show now-playing information if playback is steered externally

* Fix: Prev/Next action availability not updated in hass player

2 months agoChore(deps): Bump pylast from 6.0.0 to 7.0.2 (#2994)
dependabot[bot] [Mon, 2 Feb 2026 10:43:39 +0000 (11:43 +0100)]
Chore(deps): Bump pylast from 6.0.0 to 7.0.2 (#2994)

* Chore(deps): Bump pylast from 6.0.0 to 7.0.2

Bumps [pylast](https://github.com/pylast/pylast) from 6.0.0 to 7.0.2.
- [Release notes](https://github.com/pylast/pylast/releases)
- [Changelog](https://github.com/pylast/pylast/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pylast/pylast/compare/6.0.0...7.0.2)

---
updated-dependencies:
- dependency-name: pylast
  dependency-version: 7.0.2
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
* Also bump the provider manifest.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Marvin Schenkel <marvinschenkel@gmail.com>
Co-authored-by: OzGav <gavnosp@hotmail.com>
2 months agoAdd auto discovery to HEOS (#3056)
Tom Matheussen [Mon, 2 Feb 2026 10:28:08 +0000 (11:28 +0100)]
Add auto discovery to HEOS (#3056)

* Adjust player registration and availability state

* Discover controller via mDNS

* Add some logging, fix possible None references

* Review adjustments

* Minor docstring update

* Move manual config to advanced section

2 months agoFix players/get_by_name not always returning a result (#2945)
OzGav [Mon, 2 Feb 2026 09:23:33 +0000 (20:23 +1100)]
Fix players/get_by_name not always returning a result (#2945)

* fix: Improve player name matching in get_by_name API

The players/get_by_name API was failing to find some players because it only
performed exact matching on the player's name property. This commit enhances
the matching logic to:

- Match against both player.name and player.display_name (which may differ
  if users have customized the player name in config)
- First attempt exact match (case-sensitive)
- Fall back to case-insensitive, whitespace-trimmed matching if exact match fails

This fixes the issue where players like "Alfresco", "Sonos Roaming", and
"pCP-Airplay Test" were returning NULL from the API despite being available
in the players/all endpoint.

* Improve duplicate player name handling in get_by_name

Enhances the get_player_by_name method to handle the edge case where
multiple players might have the same display_name:

- Collects all matching players instead of returning first match immediately
- Logs a warning when multiple players match the same name, including
  the player_ids of all matches
- Guides users to use player_id for unambiguous lookups
- Maintains backward compatibility by returning the first match

This improves debuggability when users have players with duplicate names
(e.g., multiple identical devices with default names or custom config
that creates name collisions).

* Clarify warning message for duplicate player names

Improves the warning message when multiple players match the same name:
- Now shows which player_id was actually returned (first match)
- Explicitly mentions "players/get API" instead of vague "use player_id"
- Makes it clear users should use a different API endpoint for
  unambiguous lookups, not try to pass player_id to get_by_name

This addresses confusion about how to resolve duplicate name lookups.

* Include API endpoint name in duplicate player warning

Prefixes the warning message with "players/get_by_name:" to make it
immediately clear which API call triggered the warning. This helps users
debug their automations and integrations when they see the warning in logs.

Warning now reads:
"players/get_by_name: Multiple players found with name 'X': [...] -
returning first match (Y). Consider using the players/get API..."

* Simplify to single-pass case-insensitive matching

Removes the two-pass approach (exact match first, then case-insensitive)
in favor of a simpler single-pass case-insensitive search.

Benefits:
- Single iteration through players (better performance)
- Simpler, more readable code
- More predictable behavior (always case-insensitive)
- Still handles all real-world use cases

The two-pass approach was protecting against the extremely unlikely
scenario of having players "Kitchen" and "kitchen" simultaneously,
which would generate a duplicate warning anyway.

* Remove redundant text from docstring return statement

* Fix line length to comply with E501 linting rule

* Use player.state.name for matching instead of multiple properties

Simplifies the matching logic to check only player.state.name instead of
checking both player.name and player.display_name. The state.name already
contains the final player name as visible in clients and the API, making
it the single source of truth for player name matching.

As suggested by head dev review.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2 months agoBandcamp Rate Limiting (#3069)
Alexey ALERT Rubashёff [Mon, 2 Feb 2026 09:11:40 +0000 (11:11 +0200)]
Bandcamp Rate Limiting (#3069)

feat(bandcamp): add rate limiting and retry logic to all API methods

- Upgrade bandcamp-async-api to 0.0.7
- Add BandcampRateLimitError import and handling throughout
- Configure ThrottlerManager with 50 req/10s rate limit and 10 retry attempts
- Add @throttle_with_retries decorator to: get_artist, get_album, get_track,
  get_album_tracks, get_artist_albums, get_artist_toptracks
- Add throttler.acquire() context manager to async generator methods:
  get_library_artists, get_library_albums
- Add proper BandcampRateLimitError handling converting to
  ResourceTemporarilyUnavailable with backoff_time
- Remove redundant exception handlers from get_library_tracks,
  get_stream_details, get_artist_toptracks (called methods handle exceptions)
- Update tests for new default_retry_after parameter

2 months agoRemove legacy logic for radiobrowser item copying (#3058)
OzGav [Mon, 2 Feb 2026 09:07:25 +0000 (20:07 +1100)]
Remove legacy logic for radiobrowser item copying (#3058)

* Remove legacy logic for radiobrowser item copying

Removed outdated logic for copying radiobrowser items added to the library, which is marked for removal after version 2.3.0.

* Fix indentation in RadioBrowser provider

2 months agoAllow Emoji in folder names (#3071)
OzGav [Mon, 2 Feb 2026 09:05:18 +0000 (20:05 +1100)]
Allow Emoji in folder names (#3071)

* Allow Emoji in folder names

* Shorten comment

2 months agoFix track import with multiple artists and mixed separators (#3065)
OzGav [Mon, 2 Feb 2026 08:37:27 +0000 (19:37 +1100)]
Fix track import with multiple artists and mixed separators (#3065)

* Fix metadata with triple artist track

* Increase robustness of artist name parsing logic

* Add TODO comment

2 months agochore: update bandcamp API library dependency (#3066)
Alexey ALERT Rubashёff [Mon, 2 Feb 2026 08:22:07 +0000 (10:22 +0200)]
chore: update bandcamp API library dependency (#3066)

chore: update bandcamp dependencies

- Update Bandcamp provider dependency to version 0.0.5.
- Update `bandcamp-async-api` to version 0.0.5.

2 months agofix(tidal): ensure no @ symbol in tidal recommendation rows (#3070)
Jozef Kruszynski [Mon, 2 Feb 2026 08:20:03 +0000 (09:20 +0100)]
fix(tidal): ensure no @ symbol in tidal recommendation rows (#3070)

* fix(tidal): ensure no @ symbol in tidal recommendation rows

Closes 4295

* test(tidal): add test for @ symbol removal

2 months agoFix type error in load_provider_config (#3073)
OzGav [Mon, 2 Feb 2026 08:09:57 +0000 (19:09 +1100)]
Fix type error in load_provider_config (#3073)

2 months agoAdd update_provider_mapping function (#3037)
Jozef Kruszynski [Sun, 1 Feb 2026 11:00:29 +0000 (12:00 +0100)]
Add update_provider_mapping function (#3037)

2 months agoChore(deps): Bump peter-evans/repository-dispatch from 3 to 4 (#3055)
dependabot[bot] [Sat, 31 Jan 2026 08:45:05 +0000 (09:45 +0100)]
Chore(deps): Bump peter-evans/repository-dispatch from 3 to 4 (#3055)

Bumps [peter-evans/repository-dispatch](https://github.com/peter-evans/repository-dispatch) from 3 to 4.
- [Release notes](https://github.com/peter-evans/repository-dispatch/releases)
- [Commits](https://github.com/peter-evans/repository-dispatch/compare/v3...v4)

---
updated-dependencies:
- dependency-name: peter-evans/repository-dispatch
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2 months agoFix deprecation warnings for asyncio.iscoroutinefunction (#3054)
Marvin Schenkel [Sat, 31 Jan 2026 08:14:06 +0000 (09:14 +0100)]
Fix deprecation warnings for asyncio.iscoroutinefunction (#3054)

Fix deprecation warnings for asyncio.iscoroutinefunciton.

2 months ago⬆️ Update music-assistant-frontend to 2.17.77 (#3062)
music-assistant-machine [Sat, 31 Jan 2026 08:10:12 +0000 (09:10 +0100)]
⬆️ Update music-assistant-frontend to 2.17.77 (#3062)

Co-authored-by: marcelveldt <6389780+marcelveldt@users.noreply.github.com>
Co-authored-by: Marvin Schenkel <marvinschenkel@gmail.com>
2 months agoAdd album year from Deezer release_date (#3063)
Dionysis Fortis [Sat, 31 Jan 2026 08:09:12 +0000 (10:09 +0200)]
Add album year from Deezer release_date (#3063)

Co-authored-by: Marvin Schenkel <marvinschenkel@gmail.com>
2 months agoFix mypy jwt
Marvin Schenkel [Sat, 31 Jan 2026 08:05:42 +0000 (09:05 +0100)]
Fix mypy jwt

2 months agoFix issue where Sonos would sometimes skip a smart fade (#3057)
Marvin Schenkel [Fri, 30 Jan 2026 23:13:52 +0000 (00:13 +0100)]
Fix issue where Sonos would sometimes skip a smart fade (#3057)

2 months agoFix AirPlay devices that need pairing not visible in the config (#3060)
Marcel van der Veldt [Fri, 30 Jan 2026 19:49:32 +0000 (20:49 +0100)]
Fix AirPlay devices that need pairing not visible in the config (#3060)

2 months agoRename audio category to playback
Marcel van der Veldt [Fri, 30 Jan 2026 14:33:58 +0000 (15:33 +0100)]
Rename audio category to playback

2 months agoUse advanced flag on config entries
Marcel van der Veldt [Fri, 30 Jan 2026 13:41:21 +0000 (14:41 +0100)]
Use advanced flag on config entries

2 months ago⬆️ Update music-assistant-models to 1.1.95 (#3059)
music-assistant-machine [Fri, 30 Jan 2026 13:21:56 +0000 (14:21 +0100)]
⬆️ Update music-assistant-models to 1.1.95 (#3059)

Co-authored-by: marcelveldt <6389780+marcelveldt@users.noreply.github.com>
2 months agoAdd YouSee Musik provider (#3043)
Mathias R [Fri, 30 Jan 2026 07:20:52 +0000 (08:20 +0100)]
Add YouSee Musik provider (#3043)

* YouSee Musik provider

* Fix lint

* Restructuring the provider

* Change log level + fix auth invalidation

* Fix bitrate, simplify playbackContext

* Improve recommendations readability

* Lyrics support

* Apply suggestion from @MarvinSchenkel

Co-authored-by: Marvin Schenkel <marvinschenkel@gmail.com>
* cleanup

* Made quality configurable

* icons

---------

Co-authored-by: Mathias Rasmussen <mra@ordbogen.com>
Co-authored-by: Marvin Schenkel <marvinschenkel@gmail.com>
2 months agoAdd claude instructions about comment usage.
Marvin Schenkel [Thu, 29 Jan 2026 13:39:28 +0000 (14:39 +0100)]
Add claude instructions about comment usage.

2 months agoFix announcement loops for Sonos S1 (#3053)
Marvin Schenkel [Thu, 29 Jan 2026 12:53:12 +0000 (13:53 +0100)]
Fix announcement loops for Sonos S1 (#3053)

Fix announcement loops for Sonos S1.

2 months agoRemove corrupt player configurations (#3051)
Marcel van der Veldt [Thu, 29 Jan 2026 11:57:04 +0000 (12:57 +0100)]
Remove corrupt player configurations (#3051)

Remove corrupt player configurations that are missing the required 'provider' key

2 months agoImprovements and bugfixes for player and provider config entry handling (#3049)
Marcel van der Veldt [Thu, 29 Jan 2026 11:15:04 +0000 (12:15 +0100)]
Improvements and bugfixes for player and provider config entry handling (#3049)

2 months ago⬆️ Update music-assistant-models to 1.1.94 (#3048)
music-assistant-machine [Thu, 29 Jan 2026 10:44:19 +0000 (11:44 +0100)]
⬆️ Update music-assistant-models to 1.1.94 (#3048)

Co-authored-by: marcelveldt <6389780+marcelveldt@users.noreply.github.com>
2 months ago⬆️ Update music-assistant-models to 1.1.93 (#3047)
music-assistant-machine [Thu, 29 Jan 2026 08:52:46 +0000 (09:52 +0100)]
⬆️ Update music-assistant-models to 1.1.93 (#3047)

Co-authored-by: marcelveldt <6389780+marcelveldt@users.noreply.github.com>
2 months agoAdd update frontend PWA to release action
Marcel van der Veldt [Thu, 29 Jan 2026 08:28:10 +0000 (09:28 +0100)]
Add update frontend PWA to release action

2 months agoRadio Paradise. Switch to simple API (#3046)
OzGav [Thu, 29 Jan 2026 07:16:41 +0000 (18:16 +1100)]
Radio Paradise. Switch to simple API (#3046)

Switch to simple API

2 months agoImplement Apple Music playlist browsing with folders (#3008)
MizterB [Thu, 29 Jan 2026 06:53:58 +0000 (01:53 -0500)]
Implement Apple Music playlist browsing with folders (#3008)

* Implement Apple Music playlist browsing with folders

* Update music_assistant/providers/apple_music/__init__.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Separate browse logic and handle catalog/library edge cases

* Resolve copilot feedback

* Revert & repair get_playlist

---------

Co-authored-by: Marvin Schenkel <marvinschenkel@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2 months agoAdds date_added field to Tidal provider (#2969)
FL550 [Thu, 29 Jan 2026 06:48:33 +0000 (07:48 +0100)]
Adds date_added field to Tidal provider (#2969)

* feat: adds date_added to tidal provider

* applied copilot suggestions

* Update snapshot

---------

Co-authored-by: FL550 <glacial0124@posteo.com>
2 months agoDon't force reload on all config changes (#3045)
apophisnow [Wed, 28 Jan 2026 23:26:24 +0000 (15:26 -0800)]
Don't force reload on all config changes (#3045)

2 months agoChore(deps): Bump docker/login-action from 3.6.0 to 3.7.0 (#3044)
dependabot[bot] [Wed, 28 Jan 2026 23:25:56 +0000 (00:25 +0100)]
Chore(deps): Bump docker/login-action from 3.6.0 to 3.7.0 (#3044)

Bumps [docker/login-action](https://github.com/docker/login-action) from 3.6.0 to 3.7.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v3.6.0...v3.7.0)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: 3.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2 months agoUse streams server bind ip as spotify connect zeroconf bind interface (#3042)
Marvin Schenkel [Wed, 28 Jan 2026 20:07:33 +0000 (21:07 +0100)]
Use streams server bind ip as spotify connect zeroconf bind interface (#3042)

2 months agoFix not being able to ungroup dynamic group members (#3040)
Marvin Schenkel [Wed, 28 Jan 2026 19:33:24 +0000 (20:33 +0100)]
Fix not being able to ungroup dynamic group members (#3040)

Fix not being able to ungroup dynamic group members.

2 months agoFix Sqeezelite playing next enqueued song after announcement. (#3039)
Marvin Schenkel [Wed, 28 Jan 2026 14:59:34 +0000 (15:59 +0100)]
Fix Sqeezelite playing next enqueued song after announcement. (#3039)

2 months agoAdd Yandex Music provider (#3002)
Mikhail Nevskiy [Wed, 28 Jan 2026 12:30:23 +0000 (15:30 +0300)]
Add Yandex Music provider (#3002)

* Add Yandex Music provider

Implement a new music provider for Yandex Music streaming service using the
unofficial yandex-music-api library. Features include:

- Library sync (artists, albums, tracks, playlists)
- Library editing (add/remove tracks, albums, artists)
- Search across all media types
- Artist albums and top tracks
- HTTP streaming with quality selection (320kbps MP3 / FLAC)
- Token-based authentication

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix Yandex Music provider config entries

Remove duplicate token field that was causing the Save button to remain
disabled during provider setup.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix Yandex Music provider based on PR review feedback

- Move SUPPORTED_FEATURES to __init__.py and pass to setup()
- Remove code duplication in get_config_entries
- Remove label_instructions (use documentation instead)
- Replace RuntimeError with ProviderUnavailableError
- Replace generic Exception catches with InvalidDataError
- Remove non-existent AlbumType.PODCAST
- Fix audio_format to respect quality config setting (MP3/FLAC)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add yandex-music to requirements_all.txt

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Update manifest.json

* Improve Yandex Music provider based on PR review

- Use ContentType.UNKNOWN for unknown codecs instead of assuming MP3
- Add PLAYLIST_ID_SPLITTER constant and remove unused cache TTL constants
- Optimize search to use specific type when only one media type requested
- Remove unused imports

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix mypy type errors in Yandex Music provider

- Add cast for users_playlists_list return type in api_client.py
- Add type annotations for _select_best_quality method in streaming.py
- Convert quality config value to str | None before passing to method
- Remove non-existent MediaItemMetadata attributes (track_count, has_lyrics)
- Use spread operator instead of append for Sequence types in search results

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Enable CI workflow for feature branches

Allow test workflow to run on feature/* branches to validate changes
before pushing to upstream PR.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix ruff TC006 error - use list() instead of cast()

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Remove CI workflow changes unrelated to Yandex Music provider

Reverts changes to .github/workflows/test.yml as requested in PR review.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add Yandex Music provider icons

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Update music_assistant/providers/yandex_music/manifest.json

Co-authored-by: OzGav <gavnosp@hotmail.com>
---------

Co-authored-by: Михаил Невский <renso@MacBook-Pro-Mihail.local>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Marvin Schenkel <marvinschenkel@gmail.com>
Co-authored-by: OzGav <gavnosp@hotmail.com>
2 months agoFix IndexError when Deezer track has no media available (#3038)
Dionysis Fortis [Wed, 28 Jan 2026 08:11:39 +0000 (10:11 +0200)]
Fix IndexError when Deezer track has no media available (#3038)

Raise MediaNotFoundError instead of crashing with IndexError when the
Deezer API returns an empty media list. This allows the player queue
to gracefully skip unavailable tracks instead of stopping playback.

Fixes music-assistant/support#4860

2 months agoAdd JWT-based authentication with backward compatibility (#2891)
Ztripez [Wed, 28 Jan 2026 07:58:34 +0000 (08:58 +0100)]
Add JWT-based authentication with backward compatibility (#2891)

* Add JWT-based authentication with backward compatibility

Migrates from hash-based tokens to JWT (JSON Web Tokens) while maintaining
full backward compatibility with existing tokens. This enables stateless
authentication with embedded user claims for better integration with
external systems and OAuth2/OIDC compliance.

JWT Claims Structure:
- Standard claims: sub (user_id), jti (token_id), iat, exp
- Custom claims: username, role, player_filter, provider_filter,
  token_name, is_long_lived

Token Types:
- Short-lived (30 days, auto-renewing on use, sliding window)
- Long-lived (10 years, no auto-renewal for API integrations)

Implementation:
- JWTHelper class for encoding/decoding with HS256 algorithm
- JWT secret key generated and stored in auth.db settings table
- Token verification tries JWT first, falls back to legacy hash lookup
- Database still stores tokens for revocation checking

Benefits:
- Stateless authentication (user info embedded in token)
- Permission scopes available without database lookup
- OAuth2/OIDC compatibility for external integrations
- Standard JWT format for third-party verification

Migration Strategy:
- Automatic: Old tokens work until expiration
- New logins get JWT tokens automatically
- No breaking changes for existing clients

* Fix JWT token expiration check to honor database expiration

Database expiration is the source of truth for token validity, not just
the JWT expiration claim. This ensures manual token expiration (via
database update) works correctly even when JWT exp is still valid.

* Add documentation for future OIDC support

Notes on consuming external OIDC vs acting as OIDC provider, and
refresh token requirements for the latter.

* Clean up JWT implementation: remove dead code and verbose comments

- Remove unused methods: refresh_short_lived_token(), get_user_from_token()
- Remove unused imports: timedelta, UserRole
- Move User import to TYPE_CHECKING block
- Remove TODO comment about refresh tokens (not implementing)
- Simplify inline comments and reduce verbosity
- All tests still passing (36/36)

* Remove player_filter and provider_filter from JWT claims

These values can be dynamically updated, so storing them in the token
would result in stale data. The current values are available from the
database lookup during token validation.

---------

Co-authored-by: Ztripez von Matérn <ztripez@bobby.se>
2 months agoRaise AudioException if ffmpeg encounters a demuxing error (#3035)
Fabian Munkes [Tue, 27 Jan 2026 19:39:45 +0000 (20:39 +0100)]
Raise AudioException if ffmpeg encounters a demuxing error (#3035)

2 months ago⬆️ Update music-assistant-frontend to 2.17.76 (#3036)
music-assistant-machine [Tue, 27 Jan 2026 19:35:14 +0000 (20:35 +0100)]
⬆️ Update music-assistant-frontend to 2.17.76 (#3036)

Co-authored-by: marcelveldt <6389780+marcelveldt@users.noreply.github.com>
2 months agoFix Sonos looping announcements (#3032)
Marvin Schenkel [Tue, 27 Jan 2026 14:42:39 +0000 (15:42 +0100)]
Fix Sonos looping announcements (#3032)

Fix Sonos looping announcements.

2 months ago⬆️ Update music-assistant-frontend to 2.17.75 (#3033)
music-assistant-machine [Tue, 27 Jan 2026 14:14:17 +0000 (15:14 +0100)]
⬆️ Update music-assistant-frontend to 2.17.75 (#3033)

Co-authored-by: MarvinSchenkel <17671719+MarvinSchenkel@users.noreply.github.com>
2 months agoDon't filter unavailable player configs by default (#3031)
Marcel van der Veldt [Tue, 27 Jan 2026 11:50:29 +0000 (12:50 +0100)]
Don't filter unavailable player configs by default (#3031)

* Don't filter unavailable player configs by default

* Add additional param to filter out disabled players

2 months agoFix player sources in Sonos S1 (#3030)
Marvin Schenkel [Tue, 27 Jan 2026 10:24:03 +0000 (11:24 +0100)]
Fix player sources in Sonos S1 (#3030)

* Set active source to Line in source when selected.

* Add PlayerSources for S1.

* Add PlayerSources for S1.

* Disable media when linein is active. Switch back to MA on stop.

2 months agoChore(deps): Bump alexapy from 1.29.14 to 1.29.15 (#3022)
dependabot[bot] [Tue, 27 Jan 2026 08:17:29 +0000 (08:17 +0000)]
Chore(deps): Bump alexapy from 1.29.14 to 1.29.15 (#3022)

* Chore(deps): Bump alexapy from 1.29.14 to 1.29.15

Bumps [alexapy](https://gitlab.com/keatontaylor/alexapy) from 1.29.14 to 1.29.15.
- [Release notes](https://gitlab.com/keatontaylor/alexapy/tags)
- [Changelog](https://gitlab.com/keatontaylor/alexapy/blob/dev/CHANGELOG.md)
- [Commits](https://gitlab.com/keatontaylor/alexapy/compare/v1.29.14...v1.29.15)

---
updated-dependencies:
- dependency-name: alexapy
  dependency-version: 1.29.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
* Also bump the provider manifest.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Marvin Schenkel <marvinschenkel@gmail.com>
2 months agoChore(deps): Bump py-opensonic from 8.0.1 to 8.1.1 (#3023)
dependabot[bot] [Tue, 27 Jan 2026 08:16:46 +0000 (08:16 +0000)]
Chore(deps): Bump py-opensonic from 8.0.1 to 8.1.1 (#3023)

* Chore(deps): Bump py-opensonic from 8.0.1 to 8.1.1

Bumps [py-opensonic](https://github.com/khers/py-opensonic) from 8.0.1 to 8.1.1.
- [Release notes](https://github.com/khers/py-opensonic/releases)
- [Changelog](https://github.com/khers/py-opensonic/blob/master/CHANGELOG.md)
- [Commits](https://github.com/khers/py-opensonic/compare/v8.0.1...v8.1.1)

---
updated-dependencies:
- dependency-name: py-opensonic
  dependency-version: 8.1.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
* Also bump the provider manifest.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Marvin Schenkel <marvinschenkel@gmail.com>
2 months agoYTMusic: Implement more aggressive caching (#3029)
Marvin Schenkel [Tue, 27 Jan 2026 08:04:06 +0000 (09:04 +0100)]
YTMusic: Implement more aggressive caching (#3029)

* Implement more aggresive caching for YTM.

* Cleanup.

2 months ago⬆️ Update music-assistant-frontend to 2.17.74 (#3028)
music-assistant-machine [Tue, 27 Jan 2026 00:31:02 +0000 (01:31 +0100)]
⬆️ Update music-assistant-frontend to 2.17.74 (#3028)

Co-authored-by: marcelveldt <6389780+marcelveldt@users.noreply.github.com>
2 months agoFix players unavailable of cast and bluesound provider (#3027)
Marcel van der Veldt [Mon, 26 Jan 2026 23:23:19 +0000 (00:23 +0100)]
Fix players unavailable of cast and bluesound provider (#3027)

2 months agoAuto whitelist sendspin webplayer (jnstead of modifying player fiter) (#3026)
Marcel van der Veldt [Mon, 26 Jan 2026 23:04:10 +0000 (00:04 +0100)]
Auto whitelist sendspin webplayer (jnstead of modifying player fiter) (#3026)

2 months agocleanup redundant requires_flow_mode
Marcel van der Veldt [Mon, 26 Jan 2026 21:55:10 +0000 (22:55 +0100)]
cleanup redundant requires_flow_mode

2 months agoFix player lifecycle (enabling/disabling and config updates) (#3024)
Marcel van der Veldt [Mon, 26 Jan 2026 21:47:40 +0000 (22:47 +0100)]
Fix player lifecycle (enabling/disabling and config updates) (#3024)

2 months agoAdd fallback player config
Marcel van der Veldt [Mon, 26 Jan 2026 19:32:34 +0000 (20:32 +0100)]
Add fallback player config

2 months agoConfig handling improvements (#3021)
Marcel van der Veldt [Mon, 26 Jan 2026 19:23:03 +0000 (20:23 +0100)]
Config handling improvements (#3021)

2 months ago⬆️ Update music-assistant-models to 1.1.92 (#3019)
music-assistant-machine [Mon, 26 Jan 2026 16:37:01 +0000 (17:37 +0100)]
⬆️ Update music-assistant-models to 1.1.92 (#3019)

* ⬆️ Update music-assistant-models to 1.1.92

* tweak

---------

Co-authored-by: marcelveldt <6389780+marcelveldt@users.noreply.github.com>
Co-authored-by: Marcel van der Veldt <m.vanderveldt@outlook.com>
2 months agoSqeezelite: Only use low latency threshold values when a plugin is active (#3018)
Marvin Schenkel [Mon, 26 Jan 2026 14:09:40 +0000 (15:09 +0100)]
Sqeezelite: Only use low latency threshold values when a plugin is active (#3018)

Only use low latency threshold values when a plugin is active.

2 months agoAdd AAC/M4A support to tag parsing (#3004)
OzGav [Mon, 26 Jan 2026 11:39:22 +0000 (22:39 +1100)]
Add AAC/M4A support to tag parsing (#3004)

Fix AAC/M4A tag parsing in parse_tags_mutagen

Add comprehensive MP4/AAC tag parsing support to the mutagen fallback parser.
Previously only ID3 tags were handled, leaving M4A/AAC files with missing metadata.

Changes:
- Add _parse_mp4_tags() function to handle MP4Tags format
- Support basic tags: title, artist, album, albumartist, genre
- Support sort tags: titlesort, artistsort, albumsort, albumartistsort
- Support MusicBrainz IDs via freeform tags (----:com.apple.iTunes:*)
- Support track/disc numbers with totals stored separately
- Support date, lyrics, compilation flag, album type, and ReplayGain tags
- Add helper functions for decoding MP4 freeform tags (bytes to strings)
- Add M4A test fixture and test_parse_metadata_from_mp4tags test

Co-authored-by: Claude <noreply@anthropic.com>
2 months agoIncrease cache for local playlist tracks (#3007)
Marvin Schenkel [Mon, 26 Jan 2026 10:20:00 +0000 (11:20 +0100)]
Increase cache for local playlist tracks (#3007)

* Increase cache for local playlist tracks + invalidate during sync.

* Deserialize Track data from cache

* Also handle memory cache

2 months agoFix linter for new models
Marvin Schenkel [Mon, 26 Jan 2026 08:19:43 +0000 (09:19 +0100)]
Fix linter for new models

2 months agoFix Pandora authentication failures (#2949)
OzGav [Mon, 26 Jan 2026 06:59:56 +0000 (17:59 +1100)]
Fix Pandora authentication failures (#2949)

* fix: Pandora auth token expiry during long listening sessions

Implemented automatic re-authentication mechanism for Pandora provider
to prevent auth token expiry during extended listening sessions.

- Added token expiration tracking with AUTH_TOKEN_LIFETIME (50 minutes)
- Added ensure_valid_auth() method to proactively re-authenticate before
  token expiration (with 5 minute buffer)
- Updated _api_request() to call ensure_valid_auth() before all API calls
- Added retry logic for 401 errors to handle reactive re-authentication

This follows the same pattern used by the Tidal provider for maintaining
valid authentication tokens during long-running sessions.

Fixes issue where users reported authentication expiring while listening
to Pandora stations.

* improvement: Check for explicit token expiry from Pandora API

Updated authentication to check if Pandora returns expiry information
(expiresIn or expires_in fields) and use it if available, rather than
always assuming a hardcoded lifetime.

- Checks for expiry fields in authentication response
- Uses actual expiry if provided by API
- Falls back to conservative 50-minute estimate if not
- Added logging to show which approach is being used

This makes the implementation more robust and will automatically adapt
if Pandora provides expiry information in their response.

* refactor: Switch to reactive-only auth handling for Pandora

Changed from proactive time-based re-authentication to reactive
401-error handling only. This is a better approach because:

1. User reports show auth failures occurring anywhere from 5 minutes
   to several hours, indicating it's NOT a simple token timeout
2. Proactive re-auth would mask the real issue and prevent diagnosis
3. Reactive handling will log actual failure patterns to help identify
   the root cause (concurrent logins, IP changes, rate limiting, etc.)

Changes:
- Removed AUTH_TOKEN_LIFETIME and AUTH_REFRESH_BUFFER constants
- Removed ensure_valid_auth() proactive check method
- Removed _auth_expires_at expiry tracking
- Added _auth_time to track when authentication occurred
- Enhanced 401 error handling to log how long tokens lasted
- Simplified to reactive-only approach: retry on 401 with fresh auth

This will help diagnose the actual cause of auth expiry issues while
still preventing playback interruption by automatically re-authenticating
when needed.

* chore: Change Pandora auth log messages to debug level

Changed authentication success and token expiry messages from info/warning
to debug level to reduce log noise for routine operations.

* chore: Remove diagnostic timing code from Pandora auth

Removed _auth_time tracking and associated debug logging that calculated
token lifetime. Fix is confirmed working, diagnostic code no longer needed.

* chore: Change authentication success log back to info level

* fix: Remove duplicate type annotation to fix mypy error

* fix: Handle network errors gracefully in Pandora stream handler

Added ProviderUnavailableError handling to _handle_stream_request to
prevent crashes when network errors (DNS timeouts, connection failures)
occur during fragment fetching.

- Wrapped all _get_fragment_data calls in try-except block
- Added ProviderUnavailableError exception handler
- Returns 503 Service Unavailable instead of crashing
- Logs error for diagnostics

* refactor: Use recursive retry pattern for Pandora auth failures

Refactored _api_request to use recursive call instead of duplicating
error handling code in retry block.

- Added 'retry: bool = True' parameter to _api_request
- On 401 error, re-authenticate and recursively call with retry=False
- Eliminates ~20 lines of duplicate error handling code
- Cleaner and more maintainable

Credit: @MarvinSchenkel for the suggestion

* fix: Add type annotation to satisfy mypy no-any-return check

* style: Remove superfluous else after return (RET505)

Fixed ruff linting error - removed unnecessary else clause after
return statement in retry logic.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2 months agoAdd HEOS Player provider (#2986)
Tom Matheussen [Mon, 26 Jan 2026 06:51:09 +0000 (07:51 +0100)]
Add HEOS Player provider (#2986)

* Initial commit, ability to connect to a HEOS system and play URL

* Added more function handling

* Some code improvements, fix disconnection done too late

* Map music sources to inputs

* Make sure players are registered, even when they are marked as unavailable

* Build proper source list

* Keep internal heos reference in player

* Set dynamic attributes after player setup

* Implement grouping

* Grab group information when players are set up

* Handle group change events

* Build source list in provider

* Minor rearrangement

* Make sure player update event is cleaned up

* Some cleanup

* Remove some leftover logging

* Handle controller event in provider

* Split player updating into dedicated events

* Populate current_media when we're not playing

* Set sample rate configs

* Handle connection errors

* Temp troubleshooting commit

* Clean up some code and comments, adjusted some minor things

* Use fallbacks on mappings

* Disable player re-enabling for now

* Handle AUX inputs

* Handle player change event from HEOS

* address PR review comments

* Reduce safe max sample rate and bit depth for older devices

* Don't need to set credentials, unused right now

2 months ago⬆️ Update music-assistant-models to 1.1.91 (#3016)
music-assistant-machine [Sun, 25 Jan 2026 15:05:01 +0000 (16:05 +0100)]
⬆️ Update music-assistant-models to 1.1.91 (#3016)

* ⬆️ Update music-assistant-models to 1.1.91

* Adjustments for models change

---------

Co-authored-by: marcelveldt <6389780+marcelveldt@users.noreply.github.com>
Co-authored-by: Marcel van der Veldt <m.vanderveldt@outlook.com>
2 months agoRemove lock from regular player commands
Marcel van der Veldt [Sat, 24 Jan 2026 00:46:43 +0000 (01:46 +0100)]
Remove lock from regular player commands

2 months agoFix chime validation for player groups (#3013)
Marvin Schenkel [Sat, 24 Jan 2026 00:27:28 +0000 (01:27 +0100)]
Fix chime validation for player groups (#3013)

2 months agoFixes for the AirPlay provider (#3014)
Marcel van der Veldt [Sat, 24 Jan 2026 00:26:40 +0000 (01:26 +0100)]
Fixes for the AirPlay provider (#3014)

2 months agoChore(deps): Bump actions/setup-python from 6.1.0 to 6.2.0 (#3010)
dependabot[bot] [Fri, 23 Jan 2026 12:48:50 +0000 (13:48 +0100)]
Chore(deps): Bump actions/setup-python from 6.1.0 to 6.2.0 (#3010)

Bumps [actions/setup-python](https://github.com/actions/setup-python) from 6.1.0 to 6.2.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v6.1.0...v6.2.0)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: 6.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2 months ago⬆️ Update music-assistant-frontend to 2.17.73 (#3012)
music-assistant-machine [Fri, 23 Jan 2026 09:27:50 +0000 (10:27 +0100)]
⬆️ Update music-assistant-frontend to 2.17.73 (#3012)

Co-authored-by: marcelveldt <6389780+marcelveldt@users.noreply.github.com>
Co-authored-by: Marvin Schenkel <marvinschenkel@gmail.com>
2 months ago⬆️ Update music-assistant-models to 1.1.90 (#3011)
music-assistant-machine [Fri, 23 Jan 2026 03:09:18 +0000 (04:09 +0100)]
⬆️ Update music-assistant-models to 1.1.90 (#3011)

Co-authored-by: marcelveldt <6389780+marcelveldt@users.noreply.github.com>
2 months agoFix announcement for Sonos Play:1's (#3009)
Marvin Schenkel [Thu, 22 Jan 2026 19:25:58 +0000 (20:25 +0100)]
Fix announcement for Sonos Play:1's (#3009)

2 months agofix(spotify_connect): ignore trailing sink event to prevent playback thrashing (...
Andrew Pryde [Thu, 22 Jan 2026 11:37:21 +0000 (11:37 +0000)]
fix(spotify_connect): ignore trailing sink event to prevent playback thrashing (#2976)

* fix(spotify_connect): ignore trailing sink event to prevent playback thrashing

The librespot daemon emits a trailing 'sink' event after disconnect.
MA was misinterpreting this as a new playback request, causing the
disconnecting player to immediately re-activate and steal the session back.

This adds a check to ignore 'sink' events if the session is not connected.

* Fix backport pipeline

---------

Co-authored-by: Marvin Schenkel <marvinschenkel@gmail.com>
2 months agoSyncGroupPlayer: Inherit MULTI_DEVICE_DSP feature from group members (#2999)
Mischa Siekmann [Thu, 22 Jan 2026 08:31:21 +0000 (09:31 +0100)]
SyncGroupPlayer: Inherit MULTI_DEVICE_DSP feature from group members (#2999)

* SyncGroupPlayer: Inherit MULTI_DEVICE_DSP feature from group members

* SyncGroupPlayer: use reference_player as variable name for the player to inherit the supported features from

2 months agofix: Add support for AAC streaming route for universal groups (#2990)
Rob Coleman [Thu, 22 Jan 2026 08:30:16 +0000 (00:30 -0800)]
fix: Add support for AAC streaming route for universal groups (#2990)

* Add support for AAC streaming route

* Add support for AAC audio format

Add a case to properly set to the audio format to AAC if the original format is AAC and the target format can't be determined from the player.

* Remove unnecessary special case for AAC

2 months agofix(Tidal): Remove unnecessary deduping of recomendation rows (#3006)
Jozef Kruszynski [Thu, 22 Jan 2026 07:31:02 +0000 (08:31 +0100)]
fix(Tidal): Remove unnecessary deduping of recomendation rows (#3006)

2 months agoAdd Spanish and Italian to Alexa language commands (#3005)
Sameer Alam [Thu, 22 Jan 2026 07:07:05 +0000 (01:07 -0600)]
Add Spanish and Italian to Alexa language commands (#3005)

Update language commands

Co-authored-by: Sameer Alam <alams154@users.noreply.github.com>
2 months ago⬆️ Update music-assistant-models to 1.1.89 (#3003)
music-assistant-machine [Wed, 21 Jan 2026 03:08:40 +0000 (04:08 +0100)]
⬆️ Update music-assistant-models to 1.1.89 (#3003)

Co-authored-by: marcelveldt <6389780+marcelveldt@users.noreply.github.com>
2 months ago⬆️ Update music-assistant-frontend to 2.17.72 (#3001)
music-assistant-machine [Tue, 20 Jan 2026 18:05:42 +0000 (19:05 +0100)]
⬆️ Update music-assistant-frontend to 2.17.72 (#3001)

Co-authored-by: MarvinSchenkel <17671719+MarvinSchenkel@users.noreply.github.com>
2 months agoAdd 24 and 32-bit audio support for Sendspin (#2977)
Maxim Raznatovski [Tue, 20 Jan 2026 18:01:06 +0000 (19:01 +0100)]
Add 24 and 32-bit audio support for Sendspin (#2977)

* feat: add 32-bit audio and mono output support for sendspin

* refactor: remove mono output conversion for per-player streams

The mono rendering with aiosendspin upmixing added complexity
without clear benefit. Reverting to direct output format usage.

2 months agoPlex connect: Improve queue loading performance (#2735)
Anatosun [Tue, 20 Jan 2026 17:09:14 +0000 (18:09 +0100)]
Plex connect: Improve queue loading performance (#2735)

* Plex connect: Improve queue loading performance

Start playback immediately with first track while loading remaining tracks
in background. This reduces perceived latency when playing queues from Plex.

Changes:
- Load and play first track immediately when queue is requested
- Fetch remaining tracks concurrently in background task
- Broadcast timeline update after first track starts

* Plex connect: applied copilot suggestion

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Plex connect: fixed task creation

* Plex Connect: added await clause on line 715

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Marvin Schenkel <marvinschenkel@gmail.com>
2 months agoFix linter
Marvin Schenkel [Tue, 20 Jan 2026 17:03:59 +0000 (18:03 +0100)]
Fix linter

2 months agoAdd RET505 mypy rule (#2962)
OzGav [Tue, 20 Jan 2026 15:34:46 +0000 (00:34 +0900)]
Add RET505 mypy rule (#2962)

2 months agoRevert "use instance_id instead of domain on provider level logging" (#3000)
Marvin Schenkel [Tue, 20 Jan 2026 14:51:48 +0000 (15:51 +0100)]
Revert "use instance_id instead of domain on provider level logging" (#3000)

Revert "use instance_id instead of domain on provider level logging (#2943)"

This reverts commit 7af16a90d8640bb4c0409a73237b9c64b7c2817c.

2 months agoBump aiosendspin to 3.0 (#2924)
Paulus Schoutsen [Tue, 20 Jan 2026 13:27:41 +0000 (08:27 -0500)]
Bump aiosendspin to 3.0 (#2924)

* Bump aiosendspin to 2.0

Adapt to breaking changes in aiosendspin:
- Change event listener callbacks from async to synchronous
- Change start_server advertise_host to advertise_addresses

* fix: handle client disconnect during pending unregister wait

Check if client still exists after waiting for pending unregister,
preventing player registration attempts for disconnected clients.

* chore(deps): bump aiosendspin to 3.0.0

---------

Co-authored-by: Maxim Raznatovski <nda.mr43@gmail.com>
2 months agoFix pre announce typing (#2998)
Artur Pragacz [Tue, 20 Jan 2026 13:19:21 +0000 (14:19 +0100)]
Fix pre announce typing (#2998)

2 months agoAlso ignore ASYNC110 and N818
Marvin Schenkel [Tue, 20 Jan 2026 11:00:17 +0000 (12:00 +0100)]
Also ignore ASYNC110 and N818

2 months agoAdd comment about ASYNC109 to project file
Marvin Schenkel [Tue, 20 Jan 2026 10:43:12 +0000 (11:43 +0100)]
Add comment about ASYNC109 to project file