music-assistant-server.git
6 weeks ago⬆️ Update music-assistant-frontend to 2.17.92 (#3203)
music-assistant-machine [Sat, 21 Feb 2026 03:35:01 +0000 (04:35 +0100)]
⬆️ Update music-assistant-frontend to 2.17.92 (#3203)

Co-authored-by: marcelveldt <6389780+marcelveldt@users.noreply.github.com>
6 weeks agoFix use playerid for http profile
Marcel van der Veldt [Fri, 20 Feb 2026 23:55:06 +0000 (00:55 +0100)]
Fix use playerid for http profile

6 weeks agoOpenSubsonic: Use server provided version tag if present (#3200)
Eric Munson [Fri, 20 Feb 2026 23:22:20 +0000 (18:22 -0500)]
OpenSubsonic: Use server provided version tag if present (#3200)

6 weeks agoFix DSP not applying for AirPlay and Sendspin players (#3191)
Maxim Raznatovski [Fri, 20 Feb 2026 23:21:43 +0000 (00:21 +0100)]
Fix DSP not applying for AirPlay and Sendspin players (#3191)

6 weeks agoFixes for active source and current media with linked protocols
Marcel van der Veldt [Fri, 20 Feb 2026 23:19:00 +0000 (00:19 +0100)]
Fixes for active source and current media with linked protocols

6 weeks agoFeat/genres-v2-implementation (#3164)
Jozef Kruszynski [Fri, 20 Feb 2026 17:04:41 +0000 (18:04 +0100)]
Feat/genres-v2-implementation (#3164)

* feat(genres): Core genre system

* feat(genres): add background scanner for metadata.genres

* refactor(genres): add genres to base

* test(genres): add test suite

* fix(genres): eixsting genres are not recreated at migration

* feat(genres): guard against infinite loops in scanner

* fix(genres): remove duplicate, improve tests

* fix(genres): limit genre tracks return

* refactor(genres): use logger rather than print

* refactor(genres): use asyncio.gather rather than sequential calls

* refactor(genres): various fixes after review comments

* refactor(genres): randomize selection, use asyncio gether

* refactor(genres): remove alias object

* fix(genres): fix n:n relationship, safeguard comparisons

* refactor(genres): address review comments

* fix(genres): fix issues after rebase

* test(genres): add missing param to library sync tests

6 weeks agoabs: fix: do not add cover url if no cover present (#3202)
Fabian Munkes [Fri, 20 Feb 2026 17:02:49 +0000 (18:02 +0100)]
abs: fix: do not add cover url if no cover present (#3202)

do not add cover url if path not present

6 weeks ago⬆️ Update music-assistant-models to 1.1.99 (#3201)
music-assistant-machine [Fri, 20 Feb 2026 16:36:59 +0000 (17:36 +0100)]
⬆️ Update music-assistant-models to 1.1.99 (#3201)

Co-authored-by: MarvinSchenkel <17671719+MarvinSchenkel@users.noreply.github.com>
6 weeks agoMore fixes for protocol linking
Marcel van der Veldt [Fri, 20 Feb 2026 14:20:15 +0000 (15:20 +0100)]
More fixes for protocol linking

6 weeks agoSmall fixes to grouped airplay playback and late joining
Marcel van der Veldt [Fri, 20 Feb 2026 14:14:05 +0000 (15:14 +0100)]
Small fixes to grouped airplay playback and late joining

6 weeks agoFix: remove rate limiting from single item streams
Marcel van der Veldt [Fri, 20 Feb 2026 13:05:22 +0000 (14:05 +0100)]
Fix: remove rate limiting from single item streams

6 weeks agoMerge branch 'dev' of https://github.com/music-assistant/server into dev
Marvin Schenkel [Fri, 20 Feb 2026 10:40:45 +0000 (11:40 +0100)]
Merge branch 'dev' of https://github.com/music-assistant/server into dev

6 weeks agoAdd debug logs to streamscontroller to debug smart fades sometimes skipping.
Marvin Schenkel [Fri, 20 Feb 2026 10:40:39 +0000 (11:40 +0100)]
Add debug logs to streamscontroller to debug smart fades sometimes skipping.

6 weeks agoFix RAOP password handling (#3197)
Brad Keifer [Fri, 20 Feb 2026 10:36:06 +0000 (21:36 +1100)]
Fix RAOP password handling (#3197)

6 weeks agoAdded AriaCast Receiver plugin for Music Assistant (#3061)
Lorenzo Imbastari [Fri, 20 Feb 2026 10:28:44 +0000 (11:28 +0100)]
Added AriaCast Receiver plugin for Music Assistant (#3061)

* Add AriaCast Receiver plugin for Music Assistant

- Implemented AriaCast Receiver plugin to stream audio from Android devices to Music Assistant players.
- Added README.md with features, installation, configuration, and usage instructions.
- Created configuration classes for audio and server settings.
- Developed metadata handling for AriaCast streams.
- Implemented UDP discovery and WebSocket server for audio and metadata streaming.
- Added helper functions for local IP retrieval and artwork downloading.
- Included SVG icon for the plugin.
- Updated manifest.json with documentation link and requirements.

* Update README to simplify installation instructions

Removed installation instructions and updated configuration step for clarity.

* fixed mypy and pre-commit problems for my provider

* Delete music_assistant/providers/ariacast_receiver/README.md

* fixed pre-commit problems x2

* fixed icon

* Merge remote-tracking branch 'origin/dev' into dev

* Fixed Metadata and media controls after refactoring

* copilot notes addressing

* Addressing more copilot notes

* Apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update music_assistant/providers/ariacast_receiver/__init__.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update music_assistant/providers/ariacast_receiver/__init__.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update music_assistant/providers/ariacast_receiver/__init__.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update music_assistant/providers/ariacast_receiver/__init__.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update music_assistant/providers/ariacast_receiver/__init__.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update music_assistant/providers/ariacast_receiver/__init__.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Addressing last notes

* Update music_assistant/providers/ariacast_receiver/__init__.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update music_assistant/providers/ariacast_receiver/__init__.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update music_assistant/providers/ariacast_receiver/__init__.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update music_assistant/providers/ariacast_receiver/__init__.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update music_assistant/providers/ariacast_receiver/__init__.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update music_assistant/providers/ariacast_receiver/__init__.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* fix: address code review feedback for ariacast_receiver

* fix(ariacast): add playback ready event for audio/player sync

- Add _playback_ready event to coordinate audio handler and player stream
- Audio handler waits up to 2s for player to become ready after starting playback
- get_audio_stream signals ready when it starts consuming frames
- Clear ready state on cleanup in _clear_active_player and stream end

This reduces audio frame loss during player setup by synchronizing
the audio receiver with the player's readiness to consume frames.

* Add multi-platform AriaCast receiver binaries (darwin/linux amd64/arm64/arm)

* renamed receiver name

* no redownload if same artwork

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update music_assistant/providers/ariacast_receiver/manifest.json

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update music_assistant/providers/ariacast_receiver/__init__.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update music_assistant/providers/ariacast_receiver/__init__.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* fix: use shared http_session for ariacast websocket connection

* Update music_assistant/providers/ariacast_receiver/__init__.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update music_assistant/providers/ariacast_receiver/__init__.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* fix in previous copilot commit messing up the way pipe was read (no loop)

* Update music_assistant/providers/ariacast_receiver/__init__.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update music_assistant/providers/ariacast_receiver/__init__.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* fixel last comments

* Change multi_instance setting to false

* Addressed latest comments after review

- Switched from pipe to stdout
- Dropped linux arm
- Moved _get_binary_path() to helpers.py

* Implemented stderr logging, robust WebSocket connection retries, improved artwork handling, and player switching control.

Updated Manifest

* Fix after PlayerController renamed all to all_players and players.get to get_player()

* Update music_assistant/providers/ariacast_receiver/__init__.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update music_assistant/providers/ariacast_receiver/__init__.py

Added suggested track change comments

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update documentation URL in manifest.json

* Added README for the binary of AriaCast Receiver

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
6 weeks agofix: gpodder: pass verify_ssl to web requests (#3195)
Fabian Munkes [Fri, 20 Feb 2026 09:34:48 +0000 (10:34 +0100)]
fix: gpodder: pass verify_ssl to web requests (#3195)

* pass verify_ssl in gpodder

* default is True

7 weeks ago⬆️ Update music-assistant-frontend to 2.17.91 (#3199)
music-assistant-machine [Fri, 20 Feb 2026 03:43:27 +0000 (04:43 +0100)]
⬆️ Update music-assistant-frontend to 2.17.91 (#3199)

Co-authored-by: marcelveldt <6389780+marcelveldt@users.noreply.github.com>
7 weeks agoFixes for sendspin web player
Marcel van der Veldt [Thu, 19 Feb 2026 21:05:11 +0000 (22:05 +0100)]
Fixes for sendspin web player

7 weeks agoFix grouping for for players whos native protocol is a protocol of other players...
Marvin Schenkel [Thu, 19 Feb 2026 19:35:40 +0000 (20:35 +0100)]
Fix grouping for for players whos native protocol is a protocol of other players (#3192)

7 weeks agoSmall tweak to merged players concept
Marcel van der Veldt [Thu, 19 Feb 2026 19:19:45 +0000 (20:19 +0100)]
Small tweak to merged players concept

7 weeks agoSimplify hidden_by_default
Marcel van der Veldt [Thu, 19 Feb 2026 17:27:07 +0000 (18:27 +0100)]
Simplify hidden_by_default

7 weeks agoUpdate protocol linking test
Marcel van der Veldt [Thu, 19 Feb 2026 12:41:37 +0000 (13:41 +0100)]
Update protocol linking test

7 weeks agoAdd a extensions.json file to .vscode (#3068)
David Anthoff [Thu, 19 Feb 2026 12:18:25 +0000 (04:18 -0800)]
Add a extensions.json file to .vscode (#3068)

* Add a extensions.json file to .vscode

* Update .vscode/extensions.json

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Add another extension to the VS Code recommended set

* Remove Python env extension from recommended extensions

* Adjust whitespacing

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
7 weeks agoFix universal player availability
Marcel van der Veldt [Thu, 19 Feb 2026 10:21:15 +0000 (11:21 +0100)]
Fix universal player availability

7 weeks agoFix for protocol matching with locally administered mac
Marcel van der Veldt [Thu, 19 Feb 2026 10:03:46 +0000 (11:03 +0100)]
Fix for protocol matching with locally administered mac

7 weeks agoReduce FFmpeg cover-art storms (#3109)
Łukasz Wawrzyk [Thu, 19 Feb 2026 09:03:14 +0000 (10:03 +0100)]
Reduce FFmpeg cover-art storms (#3109)

* fix(images): add in-memory cache and concurrency limit for image data

Add a TTL-based LRU memory cache (256 entries, 15min TTL) to
get_image_data() to avoid redundant fetches of the same image.
Deduplicate concurrent in-flight requests via task_id and limit
embedded image extractions to 2 concurrent ffmpeg processes
using a semaphore.

Includes unit tests for cache hits, TTL expiry, eviction, and
request deduplication.

* Revert "fix(images): add in-memory cache and concurrency limit for image data"

This reverts commit a676a2484d24df1de4d2631118f1f0315c503fc8.

* feat(images): add on-disk thumbnail cache to avoid repeated ffmpeg extractions

Implement a two-tier caching system for image thumbnails:

- On-disk cache: thumbnails stored as {sha256(provider/path)}_{size}.{ext}
  in a "thumbnails" subfolder of the cache directory, surviving restarts.
- In-memory FIFO cache: last 50 thumbnails for instant access on hot paths.
- In-flight deduplication: concurrent requests for the same thumbnail share
  a single generation task via create_task, preventing ffmpeg bursts.

This eliminates repeated ffmpeg spawns for embedded cover art extraction,
which caused high CPU usage and playback interruptions especially on
lower-powered hardware and network-mounted music libraries (e.g. SMB).

7 weeks agoAdd APEv2 tag parsing for WavPack/Musepack/Monkey's Audio (#3185)
OzGav [Thu, 19 Feb 2026 08:43:41 +0000 (18:43 +1000)]
Add APEv2 tag parsing for WavPack/Musepack/Monkey's Audio (#3185)

7 weeks ago⬆️ Update music-assistant-frontend to 2.17.90 (#3190)
music-assistant-machine [Thu, 19 Feb 2026 03:47:30 +0000 (04:47 +0100)]
⬆️ Update music-assistant-frontend to 2.17.90 (#3190)

Co-authored-by: marcelveldt <6389780+marcelveldt@users.noreply.github.com>
7 weeks agoAdd eager start to create_task helper
Marcel van der Veldt [Wed, 18 Feb 2026 20:47:32 +0000 (21:47 +0100)]
Add eager start to create_task helper

7 weeks agoFix library items not being deletes after providers have removed them (#3154)
Marvin Schenkel [Wed, 18 Feb 2026 18:38:49 +0000 (19:38 +0100)]
Fix library items not being deletes after providers have removed them (#3154)

7 weeks agoSwitch to MA MusicBrainz mirror (#3186)
Marvin Schenkel [Wed, 18 Feb 2026 18:04:47 +0000 (19:04 +0100)]
Switch to MA MusicBrainz mirror (#3186)

* Use MA Musicbrainz mirror and relax throttler.

* Use MA Musicbrainz mirror and relax throttler.

7 weeks agoFix: Don't merge player protocols for multiple software players on same host
Marcel van der Veldt [Wed, 18 Feb 2026 11:16:02 +0000 (12:16 +0100)]
Fix: Don't merge player protocols for multiple software players on same host

7 weeks ago⬆️ Update music-assistant-frontend to 2.17.89 (#3181)
music-assistant-machine [Wed, 18 Feb 2026 03:48:48 +0000 (04:48 +0100)]
⬆️ Update music-assistant-frontend to 2.17.89 (#3181)

Co-authored-by: marcelveldt <6389780+marcelveldt@users.noreply.github.com>
7 weeks agoFix: ignore invalid mac and ip addresses in protocol linking
Marcel van der Veldt [Tue, 17 Feb 2026 23:13:44 +0000 (00:13 +0100)]
Fix: ignore invalid mac and ip addresses in protocol linking

7 weeks agoUpdate Sendspin provider to version 4.0 with many improvements (#3158)
Maxim Raznatovski [Tue, 17 Feb 2026 21:46:52 +0000 (22:46 +0100)]
Update Sendspin provider to version 4.0 with many improvements (#3158)

7 weeks agoFix webplayer hide from UI by default
Marcel van der Veldt [Tue, 17 Feb 2026 20:20:51 +0000 (21:20 +0100)]
Fix webplayer hide from UI by default

7 weeks agoUse PlayerType player for sendspin web player
Marcel van der Veldt [Tue, 17 Feb 2026 18:48:59 +0000 (19:48 +0100)]
Use PlayerType player for sendspin web player

7 weeks agoFix player config entries
Marcel van der Veldt [Tue, 17 Feb 2026 18:47:00 +0000 (19:47 +0100)]
Fix player config entries

7 weeks agoFix: bind sendspin proxy to correct IP
Marcel van der Veldt [Tue, 17 Feb 2026 17:45:29 +0000 (18:45 +0100)]
Fix: bind sendspin proxy to correct IP

7 weeks agoFix: Add PlayerFeature.PLAY_MEDIA to HEOS provider
Marcel van der Veldt [Tue, 17 Feb 2026 17:20:22 +0000 (18:20 +0100)]
Fix: Add PlayerFeature.PLAY_MEDIA to HEOS provider

7 weeks agoUpdate readme of AirPlay provider about late joining
Marcel van der Veldt [Tue, 17 Feb 2026 17:18:01 +0000 (18:18 +0100)]
Update readme of AirPlay provider about late joining

7 weeks agoImprove AirPlay late joiner support
Marcel van der Veldt [Tue, 17 Feb 2026 13:34:46 +0000 (14:34 +0100)]
Improve AirPlay late joiner support

7 weeks agoSome small tweaks to the AirPlay provider
Marcel van der Veldt [Tue, 17 Feb 2026 12:40:24 +0000 (13:40 +0100)]
Some small tweaks to the AirPlay provider

7 weeks agoCap Apple Music artwork resolution to 1000x1000 (#3177)
OzGav [Tue, 17 Feb 2026 10:45:01 +0000 (20:45 +1000)]
Cap Apple Music artwork resolution to 1000x1000 (#3177)

Apple Music API returns artwork URLs with the maximum available resolution
(e.g. 6605x6605, 3000x3000) which causes excessive bandwidth usage, slower
page loads, and unnecessary memory consumption. Since Apple Music artwork
URLs support dynamic sizing via {w}x{h} placeholders, cap the requested
dimensions to 1000x1000 which is sufficient for all UI contexts. The
existing image proxy can further downscale for thumbnails as needed.

https://claude.ai/code/session_01AxXvTSeiZyCmnNqYLtfhLH

Co-authored-by: Claude <noreply@anthropic.com>
7 weeks agofeat(kion_music): add configurable My Mix settings and improvements (#3145)
Mikhail Nevskiy [Tue, 17 Feb 2026 09:27:53 +0000 (12:27 +0300)]
feat(kion_music): add configurable My Mix settings and improvements (#3145)

* feat(kion_music): add configurable My Mix settings and improvements

Add comprehensive configuration options for My Mix (radio) feature and
various provider improvements synchronized from Yandex Music provider.

## New Features

### My Mix Configuration
- `my_mix_max_tracks`: Maximum tracks for My Mix playlist (default: 150)
- `my_mix_batch_size`: API batch count for Browse/Discover (default: 3)
- `track_batch_size`: Track details batch size (default: 50)
- `discovery_initial_tracks`: Initial tracks in Discover section (default: 5)
- `browse_initial_tracks`: Initial tracks when browsing My Mix (default: 15)

### Feature Toggles (Advanced, disabled by default)
- `enable_recommendations`: Show My Mix in Discover/Recommendations
- `enable_my_mix_browse`: Show My Mix folder in Browse section
- `enable_my_mix_playlist`: Show My Mix as virtual playlist
- `enable_my_mix_radio`: Enable radio feedback (like/dislike)

### Base URL Configuration (Advanced)
- `base_url`: Configurable API endpoint (default: https://music.mts.ru/ya_proxy_api)
- Fixes connection issue from endpoint change (/ya_api → /ya_proxy_api)

## Provider Improvements

### API Client
- Add batching for liked albums/tracks fetching
- Add retry logic for network errors
- Add My Mix tracks fetching with batch_id support
- Add radio station feedback support
- Accept optional base_url parameter
- Use DEFAULT_BASE_URL constant

### Provider Features
- Add SIMILAR_TRACKS and RECOMMENDATIONS features
- Add My Mix as virtual playlist (playlist_id: "my_mix")
- Add radio feedback for track started/finished/like/dislike
- Add duplicate track filtering in My Mix
- Add locale-based browse folder names (Russian/English)
- Conditional feature enabling based on config

### Streaming
- Add quality selection logic for FLAC/AAC/MP3
- Add content type detection for audio formats
- Support for flac-mp4 and aac-mp4 formats

### Parsers
- Add radio track ID parsing (track_id@station_id format)
- Improve external URL generation for artists/albums/tracks/playlists
- Use music.mts.ru domain

## Testing
- Add test_streaming.py (7 tests for quality selection)
- Add test_my_mix.py (2 tests for radio ID parsing)
- Update test_api_client.py (8 tests for batching/retry/My Mix)
- Update test_parsers.py (16 tests with snapshots)
- All 44 tests pass ✅

## Constants
- Add My Mix configuration keys
- Add DEFAULT_BASE_URL constant
- Add ROTOR_STATION_MY_MIX constant
- Add MY_MIX_PLAYLIST_ID constant
- Add RADIO_TRACK_ID_SEP constant
- Add browse folder name dictionaries

This brings KION Music provider feature parity with Yandex Music provider
while maintaining MTS-specific branding and API endpoints.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(kion_music): use DEFAULT_BASE_URL when base_url not provided

Set self._base_url to DEFAULT_BASE_URL if base_url parameter is None
in KionMusicClient.__init__(). This ensures tests pass and the client
always has a valid base URL.

Fixes test_connect_sets_base_url failure in CI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Address PR #3145 review comments

- Remove all tuning/toggle config entries; use hardcoded constants with
  sane defaults (all features always enabled)
- Fix documentation URL (beta.music-assistant.io → music-assistant.io)
- Extract magic string to ROTOR_FEEDBACK_FROM constant with comment
- Switch from private client._request to public client.request
- Update docstrings: Yandex → KION / generic wording
- Fix test import path (yandex_music → kion_music)
- Refactor duplicated My Mix code into shared _fetch_my_mix_tracks()
  helper; browse(), _get_my_mix_playlist_tracks(), recommendations()
  are now thin wrappers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Increase Discovery initial tracks to 20 and cache to 10 minutes

Show more tracks in Discovery on Home and reduce API load by caching
recommendations for 10 minutes instead of 1 minute.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address Copilot review comments and improve robustness

- Use == instead of is for dict comparison (BROWSE_NAMES_RU)
- Remove dead _get_content_type stub in parsers.py, inline ContentType.UNKNOWN
- Add AAC variants (aac-mp4, he-aac, he-aac-mp4) to streaming content type mapping
- Fix cache key collision: normalize composite track IDs before caching
- Add retry with reconnect to get_track_file_info_lossless

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: trudenboy0 <trudenboy0@gmail.com>
7 weeks agofeat(deezer): Genre and mood flows (#3171)
Julian Daberkow [Tue, 17 Feb 2026 09:06:19 +0000 (10:06 +0100)]
feat(deezer): Genre and mood flows (#3171)

* Add basic mood and genre flow support for Deezer

* Fetch Deezer flows and their images dynamically

* Address PR review comments

- Narrow exception handling from `Exception` to `DeezerErrorResponse`
  for recommended albums/artists endpoints
- Parse GW track data directly via `_parse_gw_track()` instead of
  making individual REST API calls per track
- Add early return check in `get_user_radio` when data key is missing
- Remove unnecessary `:param: None` docstring in `get_home_flows`
- Add defensive `.get()` check for "sections" key in `get_home_flows`
  to prevent KeyError

* Shrink function documentation of _parse_gw_track

* Revert to previous approach of fetching gw tracks seperately

---------

Co-authored-by: jdaberkow <13017916+jdaberkow@users.noreply.github.com>
7 weeks agoChore(deps): Bump aioslimproto from 3.1.4 to 3.1.5 (#3176)
dependabot[bot] [Tue, 17 Feb 2026 08:25:21 +0000 (08:25 +0000)]
Chore(deps): Bump aioslimproto from 3.1.4 to 3.1.5 (#3176)

* Chore(deps): Bump aioslimproto from 3.1.4 to 3.1.5

Bumps aioslimproto from 3.1.4 to 3.1.5.

---
updated-dependencies:
- dependency-name: aioslimproto
  dependency-version: 3.1.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
* Also bump version in 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>
7 weeks agoFix RuntimeError from dict/set mutation during iteration (#3159)
David Bishop [Tue, 17 Feb 2026 07:36:57 +0000 (23:36 -0800)]
Fix RuntimeError from dict/set mutation during iteration (#3159)

* Fix RuntimeError from dict/set mutation during iteration

Several collections are iterated while concurrent callbacks can
modify them, causing "Set/dictionary changed size during iteration"
RuntimeErrors:

- mass.py: _subscribers set iterated in signal_event() while
  subscribe/unsubscribe callbacks modify it
- mass.py: _providers dict iterated in get_provider() and
  _on_mdns_service_state_change() while providers load/unload
- player_controller.py: _players dict iterated in get_players(),
  get_player_by_name(), and update_player_control() while players
  register/unregister
- music.py: in_progress_syncs list iterated while done-callbacks
  call .remove() on it

Snapshot via list() before iterating in all affected locations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix additional dict mutation during iteration in mass.py

Snapshot via list() in three more locations where self._providers
or self._tracked_tasks are iterated while concurrent callbacks can
modify them: get_providers(), get_providers_by_domain(), and stop().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix dict mutation during iteration in webserver dynamic routes

Snapshot self._dynamic_routes.items() via list() in _handle_catch_all()
to prevent RuntimeError when routes are registered or unregistered by
providers while a request is being matched against prefix routes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------

Co-authored-by: David Bishop <git@gnuconsulting.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
7 weeks ago⬆️ Update music-assistant-frontend to 2.17.88 (#3178)
music-assistant-machine [Tue, 17 Feb 2026 03:46:31 +0000 (04:46 +0100)]
⬆️ Update music-assistant-frontend to 2.17.88 (#3178)

Co-authored-by: marcelveldt <6389780+marcelveldt@users.noreply.github.com>
7 weeks agofix: adapt playlog for all users if no user present (#3169)
Fabian Munkes [Mon, 16 Feb 2026 18:24:01 +0000 (19:24 +0100)]
fix: adapt playlog for all users if no user present (#3169)

adapt playlog for all users

7 weeks agofix: add name back to abs/itunes recommendation folders (#3170)
Fabian Munkes [Mon, 16 Feb 2026 17:45:12 +0000 (18:45 +0100)]
fix: add name back to abs/itunes recommendation folders (#3170)

add name back to recommendation folders

7 weeks agoabs: report correct time_listened in sessions (#3163)
Fabian Munkes [Mon, 16 Feb 2026 17:30:04 +0000 (18:30 +0100)]
abs: report correct time_listened in sessions (#3163)

* abs sessions statistics

* small progress sync fix

7 weeks agoAuto cleanup cache db when it grows >= 2GB (#3174)
Marvin Schenkel [Mon, 16 Feb 2026 13:23:25 +0000 (14:23 +0100)]
Auto cleanup cache db when it grows >= 2GB (#3174)

Auto cleanup cachedb when it grows >= 2GB

7 weeks agoFix: restart playback when switching to other output protocol
Marcel van der Veldt [Mon, 16 Feb 2026 11:51:35 +0000 (12:51 +0100)]
Fix: restart playback when switching to other output protocol

7 weeks agoSome small follow-up fixes for protocols linking
Marcel van der Veldt [Mon, 16 Feb 2026 09:34:42 +0000 (10:34 +0100)]
Some small follow-up fixes for protocols linking

7 weeks agoFix index_in_buffer or current_index treating index 0 as unset (#3160)
David Bishop [Mon, 16 Feb 2026 09:08:35 +0000 (01:08 -0800)]
Fix index_in_buffer or current_index treating index 0 as unset (#3160)

index_in_buffer and current_index are int | None where 0 is a valid
value (first track in queue). Two locations use chained `or` to
select between them:

- set_shuffle: `queue.index_in_buffer or queue.current_index`
- play_media_from_queue: `queue.index_in_buffer or queue.current_index or 0`

When index_in_buffer is 0 (first track buffered), Python's `or`
treats it as falsy and falls through to current_index. This causes
shuffle reshuffling and queue insertion to use the wrong position.

Replace with explicit `is not None` checks in both locations.

Co-authored-by: David Bishop <git@gnuconsulting.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
7 weeks agoFix AttributeError when provider is temporarily unavailable (#3157)
David Bishop [Mon, 16 Feb 2026 08:24:19 +0000 (00:24 -0800)]
Fix AttributeError when provider is temporarily unavailable (#3157)

get_provider() can return None when a provider is temporarily
unavailable (e.g., during reload or network issues). Both
remove_item_from_library() and add_item_to_library() call
.library_edit_supported() on the result without a None check,
causing an AttributeError that surfaces as a 500 error.

Co-authored-by: David Bishop <git@gnuconsulting.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
7 weeks ago⬆️ Update music-assistant-frontend to 2.17.87 (#3172)
music-assistant-machine [Mon, 16 Feb 2026 03:52:05 +0000 (04:52 +0100)]
⬆️ Update music-assistant-frontend to 2.17.87 (#3172)

Co-authored-by: marcelveldt <6389780+marcelveldt@users.noreply.github.com>
7 weeks agoFix HTTP proxy URL parsing for wss:// WebSocket URLs (#3168)
Chris [Sun, 15 Feb 2026 17:32:54 +0000 (11:32 -0600)]
Fix HTTP proxy URL parsing for wss:// WebSocket URLs (#3168)

* Fix HTTP proxy URL parsing for wss:// WebSocket URLs

The HTTP proxy handler constructed the local HTTP URL by stripping
"ws://" from local_ws_url with a simple string replace. When the
server uses SSL, local_ws_url is "wss://..." which didn't match the
replace, producing a broken URL like "http://wss:/imageproxy?..." and
causing all proxy requests to fail with DNS resolution errors.

Use urllib.parse.urlparse instead, which correctly handles both ws://
and wss:// schemes.

* Move urlparse import to top-level to fix PLC0415 lint error

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
7 weeks agoMerge players with multiple protocols together (#3150)
Marcel van der Veldt [Sun, 15 Feb 2026 14:50:45 +0000 (15:50 +0100)]
Merge players with multiple protocols together (#3150)

* Base implementation of merging players through protocol linking

* Restore after merge conflict

* follow-up

* Fix config handling for players

* some tweaks

* Handle more (edge) cases

* bunch of fixes

* More fixes

* Some more tweaks

* Fix group_members calc

* A bunch of tweaks and refactoring

* more tweaks

* more follow-up

* Update controller.py

* refactoring groups

* more fixes for syncgroup

* fix readme nitpick

* revert frozen in uv run

* Add default providers conf

* fix tests

* more tweaks

* fixes for syncgroups

* More small tweaks

* more sync player tweaks

7 weeks agoFix typo in Sonos provider
Marcel van der Veldt [Sat, 14 Feb 2026 07:36:32 +0000 (08:36 +0100)]
Fix typo in Sonos provider

7 weeks ago⬆️ Update music-assistant-frontend to 2.17.86 (#3162)
music-assistant-machine [Sat, 14 Feb 2026 03:38:43 +0000 (04:38 +0100)]
⬆️ Update music-assistant-frontend to 2.17.86 (#3162)

Co-authored-by: marcelveldt <6389780+marcelveldt@users.noreply.github.com>
7 weeks agoFix typo in Airplay provider on setting new ip
Marcel van der Veldt [Sat, 14 Feb 2026 00:02:19 +0000 (01:02 +0100)]
Fix typo in Airplay provider on setting new ip

7 weeks agoFix NO_CONTENT error on Sonos playback
Marcel van der Veldt [Fri, 13 Feb 2026 23:17:47 +0000 (00:17 +0100)]
Fix NO_CONTENT error on Sonos playback

7 weeks agoHost streamserver by default on port 8097
Marcel van der Veldt [Fri, 13 Feb 2026 20:08:35 +0000 (21:08 +0100)]
Host streamserver by default on port 8097

7 weeks agoguard against invalid volume normalization values
Marcel van der Veldt [Fri, 13 Feb 2026 20:01:56 +0000 (21:01 +0100)]
guard against invalid volume normalization values

7 weeks agoFix for Spotify returning endless tracks from playlist (#3155)
Marvin Schenkel [Fri, 13 Feb 2026 12:25:51 +0000 (13:25 +0100)]
Fix for Spotify returning endless tracks from playlist (#3155)

* Fix for Spotify returning endless tracks from playlist

* Auto cleanup cache for Spotify

7 weeks agoAlways cleanup smart fades tmp files (#3143)
Marvin Schenkel [Fri, 13 Feb 2026 12:04:47 +0000 (13:04 +0100)]
Always cleanup smart fades tmp files (#3143)

* Always cleanup smart fades tmp files

* Cleanup

7 weeks agoChore(deps): Bump docker/build-push-action from 6.19.1 to 6.19.2 (#3148)
dependabot[bot] [Fri, 13 Feb 2026 09:54:16 +0000 (10:54 +0100)]
Chore(deps): Bump docker/build-push-action from 6.19.1 to 6.19.2 (#3148)

Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.19.1 to 6.19.2.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v6.19.1...v6.19.2)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-version: 6.19.2
  dependency-type: direct:production
  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>
7 weeks agoFix operator precedence and inverted dedup logic in audiobooks playlog (#3153)
David Bishop [Fri, 13 Feb 2026 09:53:46 +0000 (01:53 -0800)]
Fix operator precedence and inverted dedup logic in audiobooks playlog (#3153)

Two bugs in the audiobook resume/playlog tracking:

1. `int(media_item.resume_position_ms or 0 / 1000)` never divides by
   1000 because `/` binds tighter than `or`. The expression evaluates as
   `int(resume_position_ms or (0 / 1000))`, so non-zero values pass
   through as raw milliseconds instead of seconds.

2. The dedup check `abs(difference) > 2` skips the DB write when data
   HAS changed (difference > 2 seconds) and writes when it has NOT
   changed (difference <= 2 seconds). The comparison is inverted.

Co-authored-by: David Bishop <git@gnuconsulting.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
7 weeks agoFix M3U parser truncating EXTINF duration to single character (#3152)
David Bishop [Fri, 13 Feb 2026 09:48:06 +0000 (01:48 -0800)]
Fix M3U parser truncating EXTINF duration to single character (#3152)

The EXTINF duration parser used `info[0].strip()[0]` which takes only
the first character of the duration string. For multi-digit durations
like "120", this truncates to "1". Also, the `-1` check on line 79
compared against "-1" but could only ever see "-" (a single char),
so negative/unknown durations were never properly detected.

Remove the erroneous `[0]` index so the full duration string is used
and the `-1` sentinel is correctly recognized.

Co-authored-by: David Bishop <git@gnuconsulting.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
7 weeks agoFix case-sensitive comparison in compare_strings fuzzy matching (#3151)
David Bishop [Fri, 13 Feb 2026 09:33:02 +0000 (01:33 -0800)]
Fix case-sensitive comparison in compare_strings fuzzy matching (#3151)

In non-strict mode, compare_strings lowercases str1 but passes the
original-case str2 to SequenceMatcher on line 564. This causes fuzzy
matching to penalize case differences, making it fail to match strings
like "Track Feat. John" vs "TRACK FT. JOHN" that should be considered
equivalent.

Also fix the elif branch (line 559) to replace on str2_lower instead
of str2, so the result is consistently lowered.

Co-authored-by: David Bishop <git@gnuconsulting.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
8 weeks agoAdd save_as_playlist command to player queue controller (#3149)
Chris [Thu, 12 Feb 2026 20:24:47 +0000 (14:24 -0600)]
Add save_as_playlist command to player queue controller (#3149)

8 weeks agoFix sync group toggle (#3142)
OzGav [Thu, 12 Feb 2026 07:24:36 +0000 (17:24 +1000)]
Fix sync group toggle (#3142)

* Fix dynamic sync group toggle having no effect on member checkboxes

PR #3118 made _attr_static_group_members unconditionally populated for
both dynamic and static groups. Since the frontend uses
static_group_members to determine which players are non-removable
(greyed out, no checkbox), this caused all members to appear locked
regardless of the dynamic toggle setting.

Restore the conditional assignment: dynamic groups get an empty
static_group_members list (all members removable), static groups get
the configured members list (all members locked). Fix the power-off
reset to read configured members directly from config instead of
_attr_static_group_members, so dynamic groups preserve their member
list on power-off without needing them marked as static.

https://claude.ai/code/session_01VVeBMzkvqTrutpg53aMtBY

* Remove added comments

https://claude.ai/code/session_01VVeBMzkvqTrutpg53aMtBY

---------

Co-authored-by: Claude <noreply@anthropic.com>
8 weeks agoChore(deps): Bump docker/build-push-action from 6.18.0 to 6.19.1 (#3138)
dependabot[bot] [Wed, 11 Feb 2026 18:41:30 +0000 (19:41 +0100)]
Chore(deps): Bump docker/build-push-action from 6.18.0 to 6.19.1 (#3138)

Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.18.0 to 6.19.1.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v6.18.0...v6.19.1)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-version: 6.19.1
  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>
8 weeks agoChore(deps): Bump pillow from 12.1.0 to 12.1.1 (#3137)
dependabot[bot] [Wed, 11 Feb 2026 17:44:13 +0000 (18:44 +0100)]
Chore(deps): Bump pillow from 12.1.0 to 12.1.1 (#3137)

Bumps [pillow](https://github.com/python-pillow/Pillow) from 12.1.0 to 12.1.1.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/12.1.0...12.1.1)

---
updated-dependencies:
- dependency-name: pillow
  dependency-version: 12.1.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
8 weeks ago⬆️ Update music-assistant-frontend to 2.17.85 (#3136)
music-assistant-machine [Wed, 11 Feb 2026 16:47:53 +0000 (17:47 +0100)]
⬆️ Update music-assistant-frontend to 2.17.85 (#3136)

Co-authored-by: stvncode <25082266+stvncode@users.noreply.github.com>
8 weeks agoChore(deps): Bump cryptography from 46.0.4 to 46.0.5 (#3134)
dependabot[bot] [Wed, 11 Feb 2026 10:11:35 +0000 (11:11 +0100)]
Chore(deps): Bump cryptography from 46.0.4 to 46.0.5 (#3134)

Bumps [cryptography](https://github.com/pyca/cryptography) from 46.0.4 to 46.0.5.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/46.0.4...46.0.5)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-version: 46.0.5
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
8 weeks ago⬆️ Update music-assistant-frontend to 2.17.84 (#3135)
music-assistant-machine [Wed, 11 Feb 2026 03:58:56 +0000 (04:58 +0100)]
⬆️ Update music-assistant-frontend to 2.17.84 (#3135)

Co-authored-by: marcelveldt <6389780+marcelveldt@users.noreply.github.com>
8 weeks agoFix DLNA players not reconnecting (#3132)
Marvin Schenkel [Tue, 10 Feb 2026 18:10:43 +0000 (19:10 +0100)]
Fix DLNA players not reconnecting (#3132)

* Fix DLNA players not reconnecting

* Change to public method for availability

8 weeks agoYandex Music: My Wave Browse folder and locale-based names (#3122)
Mikhail Nevskiy [Tue, 10 Feb 2026 17:31:03 +0000 (20:31 +0300)]
Yandex Music: My Wave Browse folder and locale-based names (#3122)

* Yandex Music: add My Wave (Моя волна) Browse folder

- Add ROTOR_STATION_MY_WAVE constant (user:onyourwave)
- Add get_my_wave_tracks() to api_client using rotor_station_tracks API
- Add My Wave folder to Browse root (first in list)
- When opening My Wave, return tracks from Rotor API as Track items
- Order: Моя волна, Мои исполнители, Мои альбомы, Мне нравится, Мои плейлисты
- On API errors, log and return [] to keep Browse working

Co-authored-by: Cursor <cursoragent@cursor.com>
* Yandex Music: locale-based Browse folder names (EN/RU)

- Add BROWSE_NAMES_RU and BROWSE_NAMES_EN in constants (My Favorites for tracks)
- In browse(), use Russian names when locale starts with ru, else English
- Fallback to English if metadata.locale unavailable
- Test: assert first root folder name is from locale mapping

Co-authored-by: Cursor <cursoragent@cursor.com>
* fix: sort imports in yandex_music provider (I001)

Co-authored-by: Cursor <cursoragent@cursor.com>
* Yandex Music: My Wave — browse, recommendations, similar tracks, virtual playlist, rotor feedback

- My Wave in Browse: root folder (up to 3 batches) and Load more pagination
- Recommendations (Discover): My Wave section with first batch
- Similar tracks (radio mode): Rotor station track:{id} for radio queue
- Virtual playlist My Wave in library (get_playlist / get_playlist_tracks with page)
- My Wave listed first in get_library_playlists
- Rotor feedback: radioStarted, trackStarted, trackFinished, skip
- Reconnect and retry on Server disconnected in api_client

Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(yandex_music): resolve ruff/mypy — duplicate methods, line length, type for browse tracks

Co-authored-by: Cursor <cursoragent@cursor.com>
* refactor(yandex_music): use constants instead of string literals, extract locale helper

Replace all "my_wave" string literals with MY_WAVE_PLAYLIST_ID constant
and extract _get_browse_names() helper to deduplicate locale detection
logic across browse(), get_playlist(), and recommendations().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------

Co-authored-by: Михаил Невский <renso@MacBook-Pro-Mihail.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
8 weeks agoABS: Use playback sessions, and optionally allow HLS stream (#3079)
Fabian Munkes [Tue, 10 Feb 2026 17:30:04 +0000 (18:30 +0100)]
ABS: Use playback sessions, and optionally allow HLS stream (#3079)

* option to use abs sessions

* bump lib

* more useful exception

* use session progress if it is available

* add session helper

* playback hls

* bump

* remove redundant methods

* add media type

* more hls

* cleanup & session creation lock

* typo

* stream socket event

* bump lib

* edge case

8 weeks agoRadio Paradise revert to using enriched API endpoint (#3130)
OzGav [Tue, 10 Feb 2026 16:19:51 +0000 (02:19 +1000)]
Radio Paradise revert to using enriched API endpoint (#3130)

8 weeks agoAdd Emby Music Provider (#3096)
hatharry [Tue, 10 Feb 2026 13:48:47 +0000 (02:48 +1300)]
Add Emby Music Provider (#3096)

* Add Emby Music Provider

* Update constants, Error handling and Audio Format for Emby Music Provider

* Fix StreamDetails AudioFormat for Emby Music Provider

* Revert "Fix StreamDetails AudioFormat for Emby Music Provider"

This reverts commit 41ee5616ff6ee3216e5bc31df7426c8bc124f8de.

* Fix StreamDetails AudioFormat for Emby Music Provider

---------

Co-authored-by: Marcel van der Veldt <m.vanderveldt@outlook.com>
8 weeks agoAdd KION Music (MTS Music) provider (#3100)
Mikhail Nevskiy [Tue, 10 Feb 2026 13:42:45 +0000 (16:42 +0300)]
Add KION Music (MTS Music) provider (#3100)

* feat(kion_music): add KION Music (MTS Music) provider

Add a new music provider for KION Music (music.mts.ru), the MTS telecom
music streaming service. The provider adapts the Yandex Music API client
(yandex-music library) to work with KION's API endpoint at
music.mts.ru/ya_api.

Features:
- Search (tracks, albums, artists, playlists)
- Library access (liked artists, albums, tracks; user playlists)
- Add/remove library items (like/unlike)
- Streaming with quality selection (High 320kbps / Lossless FLAC)
- Lossless streaming via get-file-info API with flac-mp4 codec support
- Playlist track loading with pagination fix and batch fetching
- Retry on NetworkError to handle transient failures

The provider reuses the same yandex-music==2.2.0 dependency already
present for the Yandex Music provider — no new dependencies required.

Co-authored-by: Cursor <cursoragent@cursor.com>
* chore(kion_music): update documentation URL in manifest

Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(kion_music): fix missing album cover art in library

- In parse_track(), use parse_album() instead of ItemMapping so albums
  get full metadata (including cover_uri) when tracks are synced
- In get_liked_albums(), fetch full album details via client.albums()
  in batches of 50 (likes endpoint returns minimal data without cover_uri)
- Remove unused noqa in provider.py (ruff)

Co-authored-by: Cursor <cursoragent@cursor.com>
* Address PR #3100 review: fix base_url, performance, redundant condition, docstrings; add tests

- Pass KION_BASE_URL to ClientAsync in connect() so API calls go to music.mts.ru
- Use set(batch) for O(1) lookups in get_liked_albums() fallback path
- Remove redundant `track_count > 0` check already guaranteed by outer condition
- Replace "Yandex Music" with "KION Music" in docstrings/comments
- Add full test suite: 5 api_client unit tests, 18 parser tests, 11 integration tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------

Co-authored-by: Михаил Невский <renso@MacBook-Pro-Mihail.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
8 weeks agoFix filtering and sorting within Artist, Album and Track views (#3131)
Marvin Schenkel [Tue, 10 Feb 2026 10:08:20 +0000 (11:08 +0100)]
Fix filtering and sorting within Artist, Album and Track views (#3131)

Fix filtering and sorting within views

8 weeks agoFix adding an item to library from browse results (#3120)
Marvin Schenkel [Tue, 10 Feb 2026 07:53:38 +0000 (08:53 +0100)]
Fix adding an item to library from browse results (#3120)

* Fix adding an item from browse results to library

* Fix adding an item from browse results to library

* Change dict to ItemMapping

8 weeks agoChore(deps): Bump soco from 0.30.12 to 0.30.14 (#3125)
dependabot[bot] [Tue, 10 Feb 2026 07:38:23 +0000 (07:38 +0000)]
Chore(deps): Bump soco from 0.30.12 to 0.30.14 (#3125)

* Chore(deps): Bump soco from 0.30.12 to 0.30.14

Bumps [soco](https://github.com/SoCo/SoCo) from 0.30.12 to 0.30.14.
- [Release notes](https://github.com/SoCo/SoCo/releases)
- [Changelog](https://github.com/SoCo/SoCo/blob/master/doc/release_notes.rst)
- [Commits](https://github.com/SoCo/SoCo/compare/v0.30.12...v0.30.14)

---
updated-dependencies:
- dependency-name: soco
  dependency-version: 0.30.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
* Also bump 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>
8 weeks agoSnapcast: Fix elapsed time not updated issue (#3119)
Mischa Siekmann [Tue, 10 Feb 2026 07:09:05 +0000 (08:09 +0100)]
Snapcast: Fix elapsed time not updated issue (#3119)

snapcast: fix elapsed time not updated issue

8 weeks agoChore(deps): Bump cryptography from 46.0.3 to 46.0.4 (#3124)
dependabot[bot] [Tue, 10 Feb 2026 07:02:19 +0000 (08:02 +0100)]
Chore(deps): Bump cryptography from 46.0.3 to 46.0.4 (#3124)

Bumps [cryptography](https://github.com/pyca/cryptography) from 46.0.3 to 46.0.4.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/46.0.3...46.0.4)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-version: 46.0.4
  dependency-type: direct:production
  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>
8 weeks agoAdd Zvuk Music provider (#3090)
Mikhail Nevskiy [Tue, 10 Feb 2026 07:01:39 +0000 (10:01 +0300)]
Add Zvuk Music provider (#3090)

* Add zvuk_music provider scaffold (manifest, constants, icons)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add Zvuk Music API client wrapper

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add Zvuk Music model parsers

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add ZvukMusicProvider implementation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Update zvuk_music icons to official 2024 logo

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add Zvuk Music provider integration tests

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Replace Zvuk Music integration tests with unit tests

Remove integration tests that required real API tokens and a running MA
server. Add comprehensive unit tests for parsers using mock objects,
covering all parser functions (parse_artist, parse_album, parse_track,
parse_playlist) with various scenarios.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Address PR #3090 review: decorator, duration, allow_seek

- Refactor API error handling into @handle_zvuk_errors(not_found_return=...)
  decorator (api_client.py)
- Add duration from get_track() and allow_seek=True in get_stream_details
  (provider.py)

Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(zvuk): clarify why get_track is needed for duration in get_stream_details

Co-authored-by: Cursor <cursoragent@cursor.com>
---------

Co-authored-by: Михаил Невский <renso@MacBook-Pro-Mihail.local>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Marcel van der Veldt <m.vanderveldt@outlook.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
8 weeks agoAirplay stability fixes (#3121)
Marvin Schenkel [Tue, 10 Feb 2026 06:56:55 +0000 (07:56 +0100)]
Airplay stability fixes (#3121)

8 weeks agofeat(deezer): add Flow, Radios and Top Charts as recommendations (#3077)
Dionysis Fortis [Tue, 10 Feb 2026 06:56:01 +0000 (08:56 +0200)]
feat(deezer): add Flow, Radios and Top Charts as recommendations (#3077)

* feat(deezer): add Flow, Radios and Top Charts as dynamic playlists

Implements recommendations for Deezer provider:
- User's personalized Flow as a virtual playlist
- All available Deezer Radios (genres, moods, etc.)
- Top Charts by country

These appear under the Recommendations panel and use virtual
playlist objects (in_library=false) for dynamic content.

Tested on dev environment and working as expected.

* fix: add missing type annotations for mypy

* Extract virtual playlist IDs and radio IDs into module-level constants

8 weeks ago⬆️ Update music-assistant-frontend to 2.17.83 (#3129)
music-assistant-machine [Tue, 10 Feb 2026 04:01:00 +0000 (05:01 +0100)]
⬆️ Update music-assistant-frontend to 2.17.83 (#3129)

Co-authored-by: marcelveldt <6389780+marcelveldt@users.noreply.github.com>
8 weeks agoAdd back pressure to radio streams (#3116)
Marvin Schenkel [Mon, 9 Feb 2026 14:32:31 +0000 (15:32 +0100)]
Add back pressure to radio streams (#3116)

8 weeks agoFix sync groups with dynamic option losing members on power off (#3118)
OzGav [Mon, 9 Feb 2026 12:58:50 +0000 (22:58 +1000)]
Fix sync groups with dynamic option losing members on power off (#3118)

* Fix sync groups with dynamic option losing members on power off

* Remove comment

* Apply suggestion from @OzGav

8 weeks ago⬆️ Update music-assistant-models to 1.1.98 (#3117)
music-assistant-machine [Mon, 9 Feb 2026 11:28:36 +0000 (12:28 +0100)]
⬆️ Update music-assistant-models to 1.1.98 (#3117)

Co-authored-by: MarvinSchenkel <17671719+MarvinSchenkel@users.noreply.github.com>
8 weeks agoAdd PlayerOptions to backend and MusicCast (#3064)
Fabian Munkes [Mon, 9 Feb 2026 08:43:50 +0000 (09:43 +0100)]
Add PlayerOptions to backend and MusicCast (#3064)

8 weeks agofix(yandex_music): fix playlist loading and missing album cover art (#3099)
Mikhail Nevskiy [Mon, 9 Feb 2026 08:42:59 +0000 (11:42 +0300)]
fix(yandex_music): fix playlist loading and missing album cover art (#3099)

* fix(yandex_music): fix playlist tracks not loading in UI

- Return empty list for page > 0 since Yandex Music API returns all
  tracks in a single call; without this the controller pagination loop
  never terminates
- Add fetch_tracks_async() fallback when API returns playlist metadata
  without tracks
- Raise ResourceTemporarilyUnavailable instead of returning empty list
  when tracks are expected but unavailable, preventing cache of empty
  results
- Fetch full track details in batches of 50 to reduce timeout risk
- Retry get_tracks once on NetworkError in api_client
- Raise ResourceTemporarilyUnavailable on NetworkError in get_playlist
  to prevent caching None as empty result
- Suppress yandex_music library DEBUG logs to avoid huge API dumps

Co-authored-by: Cursor <cursoragent@cursor.com>
* chore: apply ruff fixes and update snapshot

- Remove unused noqa comment (RUF100) in provider.py
- Update test_parsers snapshot for upstream model changes (year/style fields)

Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(yandex_music): fix missing album cover art in library

- In parse_track(), use parse_album() instead of ItemMapping for the
  track's album reference so albums are created with full metadata
  (including cover_uri) when tracks are synced to the library
- In get_liked_albums(), fetch full album details via client.albums()
  in batches of 50, since the users_likes_albums endpoint returns
  minimal data without cover_uri

Co-authored-by: Cursor <cursoragent@cursor.com>
* chore(yandex_music): regenerate parser snapshots after models bump

Co-authored-by: Cursor <cursoragent@cursor.com>
* Update music_assistant/providers/yandex_music/api_client.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update music_assistant/providers/yandex_music/provider.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Add tests for api_client batching/retry and playlist edge cases

Cover the 3 unresolved Copilot review comments from PR #3099:
- get_liked_albums() batch fetching and NetworkError fallback
- get_tracks() retry-on-NetworkError logic
- get_playlist_tracks() page>0, fetch_tracks_async fallback, empty batch error

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------

Co-authored-by: Михаил Невский <renso@MacBook-Pro-Mihail.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
8 weeks agoApple Music: Fix syncing shared playlists (#3095)
MizterB [Mon, 9 Feb 2026 08:28:13 +0000 (03:28 -0500)]
Apple Music: Fix syncing shared playlists (#3095)

* Catch MediaNotFoundError in get_library_playlists

* Undo try/except, fix is_library_id

* Tests for is_library_id

---------

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