Releases: b0bbywan/odios
Release list
2026.7.0rc2
2026.7.0rc2
Supersedes 2026.7.0rc1, which failed halfway through the mpd role when upgrading. Everything rc1 carried is listed below.
🐛 Fixes
- mpd2mpris failed to enable when upgrading to 2026.7.0rc1: purging the old
mpdris2package removes its unit file, but the systemd user manager keeps the unit loaded, and with it the reservation onorg.mpris.MediaPlayer2.mpd. Enablingmpd2mpris.servicethen failed withTwo services allocated for the same bus name, and the run stopped in the middle of the mpd role. The user manager is now reloaded right after the purge. Affects upgrades from 2026.6.0b2 and earlier systemd_disable_useris idempotent when the unit is absent, and image builds drop the.wantssymlink instead of running a global disable
⚠️ If your upgrade to 2026.7.0rc1 already failed
The stale unit is still loaded on that box, and it will still be there when you retry. Clear it first, either by rebooting or with:
systemctl --user daemon-reloadThen apply this release. Boxes that never ran the rc1 upgrade need nothing special.
✨ Features
- Tracklist, end to end:
mpd2mpris0.13.0 exposes the MPRISTrackListinterface (spec 2.2), and odio-api 0.16.0 loads the tracklist into its player cache, keeps it live over D-Bus signals, and exposes it through/players/{player}/tracklistendpoints (goto, add, remove, edits gated on the player'sCanEditTracks) plus aplayer.tracklist.updatedSSE event. In practice that means MPD today, plus any Bluetooth source whose app exposes the interface - Tracklist view in the UI: the player card can swap its cover for the queue, current track highlighted, tap a row to jump, per-track remove when the player allows edits. Covers also zoom fullscreen
🏗️ Refactor
- The mpDris2 fork is now mpd2mpris: role tasks, config template and unit name follow (
mpd2mpris.servicereplacesmpDris2.service,mpd2mpris.confreplacesmpDris2.conf) - Dropped
upgrade_pinned_version:install.shno longer pins the upgrade unit to apr-*build
📦 Software updates
- mpd2mpris 0.13.0:
TrackListandPlaylistsinterfaces (MPRIS spec 2.2) - odio-api 0.16.0 + 0.16.1: tracklist backend and UI, then dedup of duplicate
TrackAddedsignals and a name fallback so clients registering an empty name (spotifyd) are displayed and addressable for mute and volume - mpd-discplayer 0.8.0: maintenance, go-disc-cuer v0.4.0 engine, no configuration or CLI change
Full changelog: 2026.6.0b2...2026.7.0rc2
Install:
curl -fsSL https://github.com/b0bbywan/odios/releases/download/2026.7.0rc2/install.sh | ODIOS_VERSION=2026.7.0rc2 bashUpgrade:
The update shows up in the odio web UI and in Home Assistant and applies itself from there. The CLI equivalent:
odio-upgrade apply --version="2026.7.0rc2"2026.7.0rc1
2026.7.0rc1
✨ Features
- Tracklist, end to end:
mpd2mpris0.13.0 adds the MPRISTrackListinterface (spec 2.2), and odio-api 0.16.0 loads the tracklist into its player cache, keeps it live over D-Bus signals, and exposes it through/players/{player}/tracklistendpoints (goto, add, remove, edits gated on the player'sCanEditTracks) plus aplayer.tracklist.updatedSSE event - Tracklist view in the UI: the player card can swap its cover for the queue, current track highlighted, tap a row to jump, per-track remove when the player allows edits. Covers also zoom fullscreen
🏗️ Refactor
- The mpDris2 fork is now mpd2mpris: role tasks, config template and unit name follow (
mpd2mpris.servicereplacesmpDris2.service,mpd2mpris.confreplacesmpDris2.conf) - Dropped
upgrade_pinned_version:install.shno longer pins the upgrade unit to apr-*build
🐛 Fixes
systemd_disable_useris idempotent when the unit is absent, and image builds drop the.wantssymlink instead of running a global disable
📦 Software updates
- mpd2mpris 0.13.0:
TrackListandPlaylistsinterfaces (MPRIS spec 2.2) - odio-api 0.16.0 + 0.16.1: tracklist backend and UI, then dedup of duplicate
TrackAddedsignals and a name fallback so clients registering an empty name (spotifyd) are displayed and addressable for mute and volume - mpd-discplayer 0.8.0: maintenance, go-disc-cuer v0.4.0 engine, no configuration or CLI change
Full changelog: 2026.6.0b2...2026.7.0rc1
Install:
curl -fsSL https://github.com/b0bbywan/odios/releases/download/2026.7.0rc1/install.sh | ODIOS_VERSION=2026.7.0rc1 bashUpgrade (from 2026.6.0b2):
This is the first release that can be applied from the odio web UI or from Home Assistant (requires odio-ha 0.11.0), using the upgrade backend shipped in 2026.6.0b2.
CLI equivalent:
odio-upgrade apply --version="2026.7.0rc1"PR #81 — 2026.7.0rc1-1-g6935335
PR #80 — 2026.7.0rc1-1-g6935335
2026.6.0b2
2026.6.0b2
✨ Features
- odio-api system upgrade: Upgrade from UI or Home Assistant,.
odio_progressover the unix socket: progress events stream over odio-api's unix socket ($XDG_RUNTIME_DIR/odio-api/upgrade.sock) as the live channel, dropping journal polling. Delivery is best-effort on a daemon thread and reconnects across an odio-api restart so theendevent still lands. Theendevent now also carries the failure cause (error+step)odio-upgrade --progressauto-enabled: the flag is turned on automatically when the odio-api socket is present, so the unit no longer has to pass it explicitlyodio-upgrade applyvia sudo: applied through sudo for unattended upgrades
🏗️ Refactor
- Dropped
--skip-odio-api-restart; upgrades let odio-api restart itself once the run returns
🐛 Fixes
- upgrade: missing
daemon-reloadafter the systemd user units are installed (user-scope reload, live mode only)
📦 Software updates
- odio-api 0.15.1: add upgrade backend.
Full changelog: 2026.6.0b1...2026.6.0b2
Install:
curl -fsSL https://github.com/b0bbywan/odios/releases/download/2026.6.0b2/install.sh | ODIOS_VERSION=2026.6.0b2 bashUpgrade (from 2026.4.2b1 or later):
odio-upgrade apply --version="2026.6.0b2"Upgrade (from earlier versions):
curl -fsSL https://github.com/b0bbywan/odios/releases/download/2026.6.0b2/odio_upgrade.py -o /tmp/odio-upgrade
chmod +x /tmp/odio-upgrade
/tmp/odio-upgrade2026.6.0b1
2026.6.0b1
✨ Features
- odio-api 0.14.0: Bluetooth audio output. Scan, connect, disconnect and list Bluetooth audio devices over BlueZ/D-Bus, exposed on the HTTP API with a new dashboard section (device list, scan toggle, connect spinner, pairing countdown), plus idle auto-power-off and a scan timeout
- mpd (mpDris2 0.11.0): remote cover-art sources. The cover pipeline grows from 5 to 7 steps: tagged tracks fall back to MusicBrainz/CAA, iTunes and Deezer, web radio to Radio Browser and myMPD WebradioDB. Covers are linked as
mpris:artUrl(no download or cache) and resolved off the critical path; desktop notifications and i18n are dropped. myMPD bumped to 25.1.1 odio-upgrade --progress: a newodio_progressAnsible callback emits structuredODIO_PROGRESSbegin/progress/end events to stdout (captured by journald) so odio-api can surface live upgrade progress. Theodio-upgrade.serviceunit passes itodio-upgrade --skip-odio-api-restart: suppresses both odio-api restart points for upgrades driven by odio-api itself, which would otherwise kill its own process mid-run; odio-api restarts itself once the run returnsodio-upgrade --reinstall: forces every selected role through a full first-install scaffold (bypassing the smart-upgrade skips) to repair an install changed out of band
🚀 Performance
- Install-vs-upgrade scaffold gating across every role: upgrades skip the first-install scaffolding and re-run only the roles that actually changed, cutting task count and time on slow armhf SD cards
- Shared
resolve_prior_versiontask drives the per-role gate from one place (odios_role_pre_scaffold) dpkgforce-unsafe-ioto skip fsync during package installs (faster apt on SD cards)gather_subsetlimited to the facts odios actually usesmitogen_linearstrategy for provision and tests (not install)
🏗️ Refactor
- Prior-state read moved into a dedicated
read_state.ymltask
🧪 Tests
odio_progresscallback covered in CI (unit tests plus anupgrade-from-image-progressintegration scenario)
🐛 Fixes
- Don't chown user unit files via the image-mode enable symlink
daemon-reloadmoved to the restart handler instead of enable
🙏 Acknowledgments
- Thanks to @pbattino for the preparatory work and inspiration behind the web radio covers
Full changelog: 2026.5.0b3...2026.6.0b1
Install:
curl -fsSL https://github.com/b0bbywan/odios/releases/download/2026.6.0b1/install.sh | ODIOS_VERSION=2026.6.0b1 bashUpgrade (from 2026.4.2b1 or later):
odio-upgrade apply --version="2026.6.0b1"Upgrade (from earlier versions):
curl -fsSL https://github.com/b0bbywan/odios/releases/download/2026.6.0b1/odio_upgrade.py -o /tmp/odio-upgrade
chmod +x /tmp/odio-upgrade
/tmp/odio-upgradeWhat's Changed
Full Changelog: 2026.5.0b3...2026.6.0b1
PR #67 — 2026.6.0b2-20-gf8953ac
PR #65 — 2026.6.0b1-13-geb3f36e
2026.5.0b3
2026.5.0b3
✨ Features
- odio-api 0.13.0: dashboard transport row (play/pause, seek, volume, shuffle, repeat, mute, sink picker) moved to HTMX with optimistic updates and toast errors; collapsible MPRIS player cards; dismissible PWA promo linking to
pwa.odio.love; Lucide-style inline SVG icons replace the emoji set. A stack of MPRIS fixes lands too — seeker no longer snaps back on Bluez/AVRCP, cover refresh works in Chrome, systemd state cache unsticks on transitional states, volume slider stays visible when muted - mpd — mpDris2 0.10.0: first stable release of the asyncio + dbus-fast rewrite. Single event loop, idle-driven refresh (no polling), 5-step async cover resolver (
readpicture→ filesystem regex →albumart→ CUE/cdda → XDG cache, no moremutagen), libnotify bubbles via dbus-fast (nodbus-python/notify2). INI config at~/.config/mpDris2/mpDris2.conf, D-Bus activated by default so it auto-starts on the first MPRIS call - snapclient — snapclientmpris 1.2.0: new MPRIS2 D-Bus bridge for the local snapcast client; surfaces stream metadata and forwards Play/Pause/Next/Previous to the snapserver source. Ships the
--discoverflag that the installer uses to resolve the snapweb URL at install time - mpd: support for an optional user-provided MPD config (drop-in)
- myMPD home shortcuts: Webradio, Artists, Albums + an Odio shortcut that resolves the host client-side via
/browse/pics/odio.html— works on any client without mDNS
🏗️ Refactor
- Conditional
becomeon odio user tasks (cleaner non-root install paths) - Standard MPD socket path across roles
🧪 Tests
- New
install-as-other-userscenario — runsinstall.shasbob(NOPASSWD sudoer) withTARGET_USER=odio, mirroring the existingupgrade-from-image-fetch-as-other-userpath
🐛 Fixes
- Timers and sockets now land in the proper systemd target folder
check_driftasserts the bump matches the next version
🛠️ CI / Tooling
- Bump GitHub Actions versions
image-builder: addyqdependencympd-discplayer: drop useless config backup
Full changelog: 2026.5.0b2...2026.5.0b3
Install:
curl -fsSL https://github.com/b0bbywan/odios/releases/download/2026.5.0b3/install.sh | ODIOS_VERSION=2026.5.0b3 bashUpgrade (from 2026.4.2b1 or later):
systemctl --user start odio-check-upgrade.service || systemctl --user start odio-upgrade.service
# or
odio-upgrade apply --version="2026.5.0b3"Upgrade (from earlier versions):
curl -fsSL https://github.com/b0bbywan/odios/releases/download/2026.5.0b3/odio_upgrade.py -o /tmp/odio-upgrade
chmod +x /tmp/odio-upgrade
/tmp/odio-upgradeWhat's Changed
Full Changelog: 2026.5.0b2...2026.5.0b3