Repository navigation
Release v3.0.0 - #46
Merged
Merged
Conversation
tauri-build regenerates src/app/gen/ on every build, and .gitignore already lists it, but these schema files were committed before that rule existed, so every build left them modified. Nothing reads them from the repo: capabilities/default.json points at the online $schema URL.
23 source, config and lock files were committed as 100755, including Cargo.lock, package.json, lib.rs and SettingsPage.tsx. None of them is meant to be executed. Only the mode changes here; file contents are untouched, so later commits show content changes alone.
- rust-toolchain.toml pins the stable channel with rustfmt and clippy. - clippy.toml raises the too-many-arguments threshold to 9. - .gitattributes stores text files with LF line endings and marks images, fonts, PDFs and the Widevine .wvd device file as binary. - .vscode/extensions.json recommends the Tauri, Rust, ESLint, Prettier and Tailwind extensions the project is set up for. - .gitignore now also skips Flatpak build dirs, macOS ._ files, the Microsoft Store icon sizes, local .claude/ state and local debugging scripts. src/core/Cargo.lock is removed: src/core is a workspace member, so cargo only ever reads the root Cargo.lock. The crate-level lockfile was a stale leftover that nothing kept up to date.
Unmodified crates.io sources (both checksums match the crates.io index), trimmed to Cargo.toml, LICENSE and src/. Upstream's tests, benches, docs and changelogs are not vendored, so the manifests drop the 38 [[test]] entries in oxideav-aac and the [[test]]/[[bench]] pair in oxideav-core; cargo refuses a manifest that points at missing files. Nothing else in either manifest changes. The root Cargo.toml wires both crates in through [patch.crates-io] and excludes them from the workspace, so workspace-wide commands don't build or test them. The patch applies once mediaharbor-core depends on the crates. The next commit carries the change that vendoring exists for.
Upstream evaluates the IMDCT and the SBR QMF analysis and synthesis banks as the direct O(N^2) sums from the spec, which decodes HE-AAC at about 1.25x realtime. Each is now a single FFT: the phase terms fold into pre- and post-twiddles, leaving a plain DFT that rustfft evaluates. The output matches the direct sums to floating-point noise, while a long IMDCT window drops roughly two million cosine evaluations for one transform. FFT plans are cached per length, since AAC only uses a few. Adds rustfft 6 as a dependency of the vendored oxideav-aac.
Every service now lives in services/<name>/ and plugs into three shared traits in services/common: SearchProvider, DownloadProvider and PlaybackProvider. BackendState dispatches through them instead of matching on the platform inside lib.rs, which is where most of that file's removed code came from. - services/common is the shared layer: the download pipeline (orchestrator, downloader, converter, tagger), one subprocess driver for gamdl, votify, yt-dlp and OrpheusDL, and search, lyrics, share-link and HTTP helpers. - drm/ replaces crypto/ with a Widevine CDM and a pure-Rust mp4decrypt. - apis/, streamrip/, meta/ and crypto/ are gone; their code moved into the service directories. - Settings are stored nested and versioned (schema 5), with a migration from the flat 2.x file. gamdl and votify INI files are written from a whitelist of keys. - Tauri commands are generated by tauri_delegates! from BackendState methods. The files in this commit call tauriAPI directly; the window.electron shim stays until its last caller moves over. - Frontend: typed settings, a download dialog with per-service quality options, per-item progress and download summaries, and the settings page rebuilt on typed field components. - Rust dependencies move to reqwest 0.13, axum 0.8, zip 8 and thiserror 2, and add what the following commits build on (cpal, symphonia, rusqlite, souvlaki, tauri-plugin-updater). Cargo.lock is committed whole with them. Some lines ride along in whole files: App.tsx already wires hooks from the player, library, auth and updater changes, and the settings schema carries their keys. BREAKING CHANGE: native Spotify and Apple Music downloads are AAC-only (Widevine L3); the PlayPlay and FairPlay-ALAC paths are removed. mh-settings.json is now stored nested and versioned (schema 5). A 2.x file is migrated on first launch and kept as mh-settings.json.bak, and 2.x builds do not understand the new layout.
A notification can carry up to two action buttons and a dedupe key; a new notification with the same key replaces the old one instead of stacking. Toasts lay the actions out under the message. The player, credential health and update prompts use this in later commits.
Playback moves out of <audio> elements and the Web Audio crossfade in the WebView into a Rust engine in core/src/player: - decoding with symphonia, the oxideav decoders (AAC/HE-AAC, APE, Musepack, Speex, TTA, Ogg) and rusty-opus - resampling, crossfade and replay gain - output through cpal (PipeWire, PulseAudio, ALSA, WASAPI, CoreAudio) with device selection - a spectrum analyser that feeds the visualizers OS media controls (MPRIS and Windows SMTC via souvlaki, macOS Now Playing directly) live in app/src/media_controls.rs. The player store, Player and NowPlaying drive the engine over IPC; the frontend adds a seek bar, autoplay continuation, stream prefetch and reports for streams that cannot be decoded. Panics are appended to the log file, since playback threads otherwise die silently. AudioCrossfadeEngine.ts is removed.
Release builds strip symbols, use thin LTO with one codegen unit and keep overflow checks on. Dev builds optimise the audio decoders, which are slower than realtime at -O0.
Local music is indexed into library.sqlite by a scanner and file watcher with a cover cache, instead of being rescanned on every visit; media/library replaces media/scanner.rs and media/file_watcher.rs. It adds local playlists with M3U import and export, tag writing, play history and a library radio. The library view also shows each streaming service's saved albums, artists, playlists, follows and home shelves. Saving, following and playlist edits are written back to the service. Search results open the same album, artist and playlist views, so the search page's old detail modal and views are removed. Alt+Left and the mouse back button navigate back.
A Radio page backed by services/radio: - search and browse Radio Browser, SomaFM and the Icecast directory - favourites, recents and custom station lists - import from a stream URL, a playlist file, an Icecast server or a pasted curl command - a station editor with overrides and custom covers - now-playing titles from ICY metadata Stations are stored in library.sqlite. The sidebar gains the Radio entry and swaps react-icons' Discord glyph for an inline SVG, so react-icons can be dropped from the dependencies.
Saved credentials for each service are checked at startup, every 15 minutes and after an auth error, and the result shows as a status pill on that service's settings tab. Qobuz and Tidal can sign in through an in-app login window, and a Tidal token can be imported as JSON. credentials.json can override the bundled API keys. apis/credentials.rs moves to auth/credentials.rs, and auth/netscape.rs reads cookie files.
The dependencies page can install aria2c (yt-dlp's external downloader), Deno (yt-dlp's JavaScript runtime) and N_m3u8DL-RE (gamdl's HLS downloader) into a managed bin directory that is put on PATH. Tools are resolved from that directory, the Python venv or the system; pip dependencies are matched by exact package name, and an install can be forced. Onboarding gains a step for choosing which services to enable. The tour also gets its Radio step here.
Uses the Tauri updater plugin. The Updates page checks the signed latest.json, can download in the background and installs with a restart. Only installs that can replace themselves update in-app (AppImage, deb, rpm, NSIS, MSI and the macOS app); Flatpak, Snap, AUR and source builds are pointed at their own channel. The window.electron shim is removed, since nothing calls it any more.
Removes the MSIX manifest and the Microsoft Store icon sizes. The release workflow stops building the package in the CI commit. BREAKING CHANGE: the MSIX package for the Microsoft Store is no longer built. Windows users should install the NSIS (.exe) or MSI release; both update in-app (windows-x86_64-nsis/msi in latest.json).
- Tailwind v4's Vite plugin already adds vendor prefixes, so PostCSS and autoprefixer go; tailwindcss-animate is replaced by tw-animate-css. - Packages left over from the Electron app are removed (axios, cheerio, chokidar, sharp, ffmpeg-static, librespot, re-unplayplay, ytmusic-api and others), along with the postinstall step that patched librespot. - ESLint 10, Vite 8.2 and Node >= 22. Vite resolves the path aliases from tsconfig and carries the Vitest config. - Local tauri:build scripts pass --no-sign. - Adds @tanstack/react-virtual and the Radix context-menu and popover packages. ui/popover.tsx and ui/tabs.tsx are added but not used yet.
Formatting and lint fixes only, with no behaviour change: Prettier on files that had no other changes, eslint-disable comments the new ESLint config no longer needs, and rustfmt plus a redundant closure in update_checker.rs.
src/style.css and src/pages/placeholder.png were not referenced anywhere in 2.2. scripts/patch-librespot.js patched the npm librespot package, which is gone.
The logo SVG gets a solid fill and padding. The app icons are regenerated from it (about half their old size), along with the Snap icon, the README banner and the favicon.
The GPG public key of MediaHarbor Release Signing:
4E7E D764 DFB4 F1B6 59C1 C570 DD7A E5F9 C20A 4047
The release workflow signs SHA256SUMS.txt and the RPM with the private
key, and the README explains how to verify.
ci.yml runs lint, the typecheck and build, Vitest and cargo test on every push and pull request; rustfmt and clippy are advisory. tauri-build.yml: - builds updater artifacts and publishes latest.json with per-installer keys - GPG-signs SHA256SUMS.txt and the RPM, and attests build provenance - regenerates the Flatpak cargo sources from Cargo.lock - writes release notes with install and verification steps - drops the MSIX job
- PipeWire and ALSA runtime libraries for native audio, and clang for the pipewire bindgen build. - N_m3u8DL-RE bundled in the Flatpak and Snap, where the sandbox blocks downloading it at runtime. - ffmpeg and Python for the Snap and AUR packages. - Flatpak: offline sources regenerated, patch-package steps removed, PulseAudio cookie and PipeWire socket access. - AUR: desktop file capitalised to match the Tauri bundles; .SRCINFO pkgdesc synced with PKGBUILD. - metainfo: new summary, branding colours and screenshot list.
The README gains "Verifying a Release" (checksums, GPG, the RPM signature and build provenance) and first-launch notes for macOS and Windows. The bug report template asks for OS, version and install type, and says where the log file lives on each platform.
package.json, tauri.conf.json, PKGBUILD, .SRCINFO (including its stale source URL) and the metainfo release entry. Cargo.toml, Cargo.lock and package-lock.json already carry 3.0.0, because they were committed whole with their dependency changes.
Tool installs were blocked inside the Flatpak. They go into the app's data folder again, like in 2.x, so the ffmpeg extension and the bundled N_m3u8DL-RE are removed from the manifests.
Also updates the release date in the Flatpak metainfo.
Falls back to commit subjects when the version has no entry.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
v3.0.0 replaces WebView playback with a native audio engine, moves the local library to a SQLite index, and adds native Spotify and Apple Music downloaders, internet radio and in-app updates.
The complete list of changes is in CHANGELOG.md.
Notes
mh-settings.json.bak..wvd) and, for now, pywidevine. That requirement will go away once Widevine is handled natively in Rust.Issues
Fixed in this release: fixes #30, fixes #36, fixes #38, fixes #41, fixes #43, fixes #44.