Been a while! Even though we added several features just after the previous release, this release had to wait because of a some pretty important changes. We now use sqlx instead of rustqlite, and this migration also made us do a partial library rewrite. There are a lot of exciting features and bug fixes in this release but first, let's thank @Commenter25 for providing Rufin a new icon! We also got a lot of new contributors; I'm thankful to them and to the people who tested our new features before the new release. The most time on this release was spent on app performance and UX: I also made some pragmatic choices for the sake of performance, one of them being removing row columns to be resizeable. This is definitely the biggest release ever, even the highlights list is quite big:
-
Onboarding is made faster. Artwork is now cached in background and local folder scan is made 3x~ times faster.
-
You can now drag songs or select multiple of them; move them into a playlist in the pins, download, or play them all!
-
Rufin can cast with UPnP or Chromecast. You can control relay settings or network interface you want to cast from under Privacy & Security.
-
Rating is now supported for all sources. Jellyfin natively supports 1-10 range; for OpenSubsonic and local folders which have ratings in 0-5 range we have a setting, where you can save partial ratings in Rufin and upload rounded up ratings as metadata. You can also configure rating menu to appear directly in the now playing bar.
-
Karaoke mode is made available for all sources, and we now have more power-user settings for lyrics; you can change edit lyrics inside the app including being able to preview changes with offsets, change font family and font sizes, make the save button directly to save to your source or let Rufin do automatically save fetched lyrics to your source as embeds or separate .lrc files.
-
You can configure playback speed and pitch from the new playback settings menu.
-
You can now put visualizer in the sidebar! You can also combine it with lyrics, to use it as a background. Visualizer animations are also updated.
-
New Smart Playlist templates for weekly, monthly, and yearly Most Played songs. You can also configure these further, these are still dynamic like all smart playlists.
-
Favorites route has Tracks/Artists/Albums tabs added.
-
A broad range of new keyboard shortcuts are added; from navigation to to various audio and queue settings. Shortcuts are also categorized.
-
In addition to the app icon change, icons we use in app are also changed. All of these icons are also bundled with Rufin for consistency on all installations.
-
Added API key login support for OpenSubsonic servers.
-
Rufin now selects Pipewire instead of PulseAudio if you have it available.
-
MacOS/Windows lose the menu and search icons that are put on the tray, and instead get them inside the app window so that they are accessible in fullscreen.
-
Polished overall widget spacing.
-
Compact sidebar also supports pins now.
-
Fixed a bug where repeatedly clicking on the same lyrics row could stop the playback.
-
Added Chezh and Traditional Chinese translations.
-
Added missing flake dependencies.
-
Fixed several bugs with repeat one state, most critical one being it seeking ahead at song start on its own.
-
Fixed a bug with text not wrapping correctly in fullscreen player for small window sizes.
-
Fixed an issue with right clicking to metadata lines at the bottom bar crashing the app.
-
Fixed an edge case where if a currently playing downloaded song was removed and tried to play again after listening another song in the queue it would not play.
Changelog
- fix(playback): keep repeat-one queue and seeking responsive by @screwys in #766
- fix(macos): use native Dock lifecycle by @screwys in #767
- fix(playback): avoid replaying repeated stream starts by @screwys in #768
- chore(i18n): update translations by @weblate, @aguhadug in #770
- refactor(playback): simplify source cutover shutdown by @screwys in #771
- chore(i18n): update translations by @weblate in #773
- chore(i18n): update translations by @weblate, @jakubcabal in #776
- fix(local): recover unavailable music folders by @screwys in #779
- chore(i18n): update translations by @weblate, @jakubcabal in #780
- fix(nix): add glib-networking to deps by @0xMRTT in #781
- feat(ratings): add quick ratings across sources by @screwys in #782
- fix(ui): align route surface spacing by @screwys in #783
- fix(player): align volume slider with pointer by @screwys in #784
- fix(nix): restore HTTPS playback in development shells by @screwys in #785
- fix(preferences): fit quality selectors on narrow screens by @screwys in #786
- feat(playback): add speed configuration and playback settings button by @screwys in #789
- chore(i18n): update translations by @weblate, @aguhadug in #787
- chore(deps): update rust crate rusqlite to v0.40.2 by @rufin-renovate in #790
- build: simplify packaging and cross-platform CI by @screwys in #791
- feat(ui): refine showcase metadata, icons, and context menus by @screwys in #794
- chore(i18n): update translations by @weblate, @aguhadug in #795
- fix(ui): refine lyrics and menu icon choices by @screwys in #796
- fix(lyrics): clean up Genius lyrics rendering by @screwys in #797
- feat(sidebar): add compact pins with stable menu hover by @screwys in #798
- fix: stop panicking on db mismatches and repeated seeks by @screwys in #793
- chore(i18n): update translations by @weblate, @aguhadug in #799
- feat(playback): add network casting and refine icons by @screwys in #805
- chore(i18n): update translations by @weblate in #807
- chore(docs): refine contributing docs by @screwys in #808
- fix(playback): recover casting stalls and queue layout by @screwys in #815
- feat(playback): add preserve pitch setting by @screwys in #816
- feat(ui): refresh Rufin icon and fallback artwork by @screwys in #817
- feat(subsonic): support API key authentication by @screwys in #818
- chore(readme): add translation credits by @screwys in #819
- feat(playback): support reliable audio output switching by @screwys in #820
- feat(desktop): support background close behavior by @screwys in #821
- fix(ui): sync sidebar icon on launch by @screwys in #822
- fix(playback): stabilize casting connections and controls by @screwys in #823
- fix(library): unify artist and metadata ownership by @screwys in #824
- chore(playback): trace cast relay requests by @screwys in #825
- fix(playback): keep UPnP renderers discoverable by @screwys in #826
- fix(ui): align platform window chrome by @screwys in #827
- chore(i18n): update translations by @weblate, @aguhadug, @houtarou-d in #828
- fix(ci): restore Cargo target caching by @screwys in #829
- fix(playback): improve UPnP handoff compatibility by @screwys in #830
- fix(ui): align macos accelerators with platform expectations by @fenbyte in #765
- fix(playback): use a conventional cast relay listener by @screwys in #831
- feat(ui): categorize keyboard shortcuts by @screwys in #769
- feat(playback): allow selecting the casting network by @screwys in #835
- chore(i18n): update translations by @weblate, @aguhadug in #836
- fix(macos): stabilize signing identity across builds by @screwys in #837
- feat(library): add a new toast for library scans by @screwys in #838
- feat(icons): use symbolic icon as fallback everywhere by @screwys in #839
- fix(ui): align sidebar end margins with window chrome by @an920107 in #842
- chore(i18n): update translations by @weblate, @aguhadug, @an920107 in #841
- chore(i18n): update translations by @weblate, @aguhadug, @an920107, @screwys in #843
- fix(macos): use the default keychain for local signing by @screwys in #840
- chore(i18n): update translations by @weblate, @jakubcabal, @an920107 in #846
- chore(i18n): update translations by @weblate, @an920107 in #850
- chore(i18n): update translations by @weblate, @an920107 in #851
- refactor: migrate from rustqlite to sqlx and optimize GTK lifecycles by @screwys in #852
- chore: expand contributing guidelines by @screwys in #854
- chore: add more explanation for PR workflow by @screwys in #856
- fix(playback): restore reliable casting handoffs by @screwys in #857
- fix(cast): restore UPnP transport startup lifecycle by @screwys in #859
- feat(playback): separate ReplayGain and EBU R128 normalization by @screwys in #860
- chore(i18n): update translations by @weblate in #855
- fix(cast): honor UPnP renderer capabilities by @screwys in #861
- feat(ui): refine ratings and playback controls by @screwys in #862
- fix: stabilize casting, startup, and playback controls by @screwys in #864
- fix(cast): bind relay to selected network by @screwys in #865
- feat(player): refine visualizer spectrum and lifecycle by @screwys in #866
- fix(queue): stabilize drag reordering by @screwys in #867
- chore(i18n): update translations by @weblate, @aguhadug in #863
- fix(playback): stabilize gapless loudness transitions by @screwys in #868
- fix(cast): route UPnP through selected network by @screwys in #869
- feat(lyrics): new lyrics features with save, editor, and typography settings by @TharukRenuja in #845
- chore(i18n): update translations by @weblate in #870
- fix(ui): reveal startup route after first allocation by @screwys in #871
- feat(ui): refine navigation and window chrome by @screwys in #872
- fix(deps): separate Renovate dependency updates by @screwys in #873
- chore(i18n): update translations by @weblate, @aguhadug in #874
- feat(selection): allow multiple selection and drag operations by @screwys in #877
- chore(i18n): update translations by @weblate, @aguhadug in #878
- fix(ui): stabilize fullscreen player and drag reordering by @screwys in #880
- fix(diagnostics): redact casting logs and add copy action by @screwys in #881
- fix(deps): restore Renovate update throughput by @screwys in #882
- chore(i18n): update translations by @weblate in #883
- fix(crash): implement bottom player title styling with simple css instead by @screwys in #884
- chore(issues): make main selectable as a version by @screwys in #885
- fix(schema): schema 40 -> 41 migration by @screwys in #890
- feat(delete): allow queue and playlist tracks to be removed with delete key by @screwys in #899
- fix(home): keep showcase album-only by @screwys in #901
- chore(i18n): update translations by @weblate, @aguhadug in #900
- feat(dragging): allow grids/now playing to be draggable and add drag previews by @screwys in #902
- fix(queue): align year column with window controls by @screwys in #903
- feat(ui): refine library table presentation by @screwys in #904
- feat(lyrics): fetch NetEase romaji to show correct furigana and romaji readings by @screwys in #905
- fix(ui): refine smart playlist and Explore refresh by @screwys in #906
- chore(i18n): update translations by @weblate, @aguhadug in #907
- fix(ui): stabilize track filtering by @screwys in #908
- chore(deps): update rust crate apple-native-keyring-store to v1.0.2 by @rufin-renovate, @screwys in #891
- chore(deps): update rust crate blake3 to v1.8.7 by @rufin-renovate, @screwys in #894
- fix(library): ignore unchanged source updates by @screwys in #909
- fix(ui): stabilize fullscreen and lyrics layout by @screwys in #910
- chore(deps): update actions/attest digest to 1e69f48 by @rufin-renovate, @screwys in #875
- feat(playlists): add ordering and polish playlist actions by @screwys in #911
- chore(deps): update swatinem/rust-cache action to v2.9.2 by @rufin-renovate, @screwys in #898
- feat(updates): show GitHub release history by @screwys in #912
- feat(lyrics): make source saving explicit by @screwys in #913
- fix(local): advance cue backing observations by @screwys in #915
- feat(queue): allow clearing the entire queue and add new keyboard shortcuts by @screwys in #916
- chore(i18n): update translations by @weblate, @aguhadug in #914
- docs: refresh project presentation by @screwys in #917
- feat(downloads): refine feedback and removal behavior by @screwys in #918
- fix typo in changelog by @fenbyte in #920
- fix(macos): build stable release with Bash 3.2 by @screwys in #922
- fix(packaging): validate release artifacts before publication by @screwys in #924
New Contributors
- @0xMRTT made their first contribution in #781
- @fenbyte made their first contribution in #765
- @an920107 made their first contribution in #842
- @TharukRenuja made their first contribution in #845
Full Changelog: v0.13.1...v0.14.0