soulsync 3.4.3: dev → main
this release rebuilds the import page into one inbox with a picard-style matcher and browser uploads, repairs the v1 api and gives the video side a public one, fixes a run of reported artist page and ui bugs, and closes profile and restart gaps on the audiobook and podcast sides. scope: commits since the 3.4.2 merge.
import page
- the page is one inbox and one matcher. the three tabs (auto / albums / singles) were three views of the same folder that did not know about each other, and a worker result that said "could not identify" had no way into the matcher. now every staging item is a row with its state and the actions it earns: approve, identify or fix in the matcher, retry, dismiss. needs attention is the default filter, everything and history are the other two. the strip under the header shows the folder, its size, the auto-import switch and a countdown to the next scan; the worker's settings live in a drawer behind the gear. old /import/auto|album|singles urls redirect.
- the matcher is picard's shape: release, candidates and search on the left, the tracklist on the right with each file's own length and bitrate beside the track, length mismatches flagged, drag or tap to assign. singles get the same page with track candidates. an import from the matcher records itself against the worker's history row.
- upload from the browser. drop files or folders onto the inbox (or Add files / Add a folder) and they land in the import folder with their folder names kept, so an album stays one item. uploads go in 8 MB pieces so a reverse proxy's body cap in front of a docker install cannot refuse a whole flac. audio only, never leaves the folder, never clobbers.
- see the import before it happens: the matcher shows the destination on your template and the tag changes per track, from the same builders the pipeline runs. tracks the library already has are badged with the format it has them in.
- identify by fingerprint. a folder whose tags and name say nothing can ask the audio itself: acoustid runs on the first three files and the matcher searches from the artist it names. says plainly when acoustid is not set up.
- an
import_needs_attentionautomation trigger fires when the worker leaves a folder for a person (needs review, could not identify, or failed), so a notification can reach you without opening the page. - retry a finished auto-import row (failed / needs identification / rejected used to be terminal until the files changed), resolve a row imported by hand so history stops saying "needs identification" about an album that is in the library, clear history from the history filter, ticked waiting singles go in from their own tags in one go, and keyboard: j/k move, x tick, a approve, d dismiss, enter opens.
- fixes found on the way: untagged files inside an album subfolder were split into singles so folder-name identification never ran on them (they are one album named by the folder now); an unreadable import folder says so with the PUID hint instead of reporting zero files (a truenas user with the dataset owned by another uid had nothing to go on); a fresh drop is not "needs attention" while auto-import is on and the worker has not had its turn yet.
public api
- the v1 endpoints for wishlist/process, watchlist/scan, playlist sync and search all 501'd since the web_server split moved the helpers they imported (#1259, wavio hit it). each now points at the module that owns the code: wishlist/process runs the same helper as the app's own button (200 started, 409 already running), watchlist/scan runs the scan handler in-process, playlist sync calls the sync start directly instead of forwarding itself over http to a hardcoded port. a test fails if anything under /api/v1 imports from web_server again.
- the video side had no public api at all.
/api/v1/video/*now covers library, search, wishlist, watchlist, scan, downloads, calendar and requests, documented in Support/API.md.
artist page
- a "Wrong match?" button beside DB Record opens one panel with every source match: what it is matched to, a link to check it, when it was last tried, and change / clear / auto per row, with the search inline under the row. the only way to fix a bad auto-match before was the enhanced view's header chips, which you had to know existed.
- Your library shows missing tracks again, so "I Have This" is reachable. the react port carried over the diff and the manage modal but nothing fetched the canonical tracklist on expand, so no album ever grew a missing row and the file-to-track import flow sat unreachable behind green tests.
- the Write Tags modals scroll so their buttons stay on screen (#1254), and they got their card back: the react port dropped the modal shell class so the card rendered see-through over the page. new kicker, album title, real track cards and pill toggles for the options.
- the bulk action bar floats above the mini player and the corner buttons instead of sitting under them (#1255).
- the source-match pills no longer inherit a global "error" style that blew the Lookup failed pill up to a blob.
ui and player
- native select menus paint dark (#1258). every select styled its closed box white-on-dark but never told the browser what scheme the popup list is in, so chromium drew the list light with our white text on top. one global rule fixes it, and the year-old black-option patch that now fought it is gone.
- a crossfaded track carries on where the fade left it instead of starting over. the fade played the next track on a second audio for six seconds, then the normal play path loaded the same track from zero: you heard the opening twice.
- the library filter bar is one 36px toolbar row (search, watched pills, source picker) with a stroked magnifier and a clear button; the cards start 245px down a 1280 viewport instead of 435. the sync page's playlist search no longer pulls its text under the glass.
scan and downloads
- a moved file no longer lists twice after the server re-ids it (#1257). plex does not track moves: reorganize repoints the row, plex trashes the item and mints a new one, and the next scan inserted a second row so every album listed each track twice. a plex item in the trash is never written, and every scan now folds rows the server no longer lists into the live row for the same file, keeping enrichment and play history. a row the server still lists is never touched.
- begin analysis marks tracks before it asks musicbrainz anything. the release preflight (up to eight full release fetches against a 1 req/s service) ran before a single ownership check, so the modal sat empty ten to thirty seconds on an album you may already own. it runs after the analysis now and only when there is something to download.
- scan-flagged library files no longer sit in the Downloads list as completed and unclearable (735 rows on one install); they are reviewed from the scanner's findings on the Tools page.
- a download batch no longer writes 0 over the sync's match count, which is what made the dashboard sync card say "0/240 in library" while the rows showed 236 matched.
- a MusicBrainz 503 during import no longer wipes every source id off the track. the recording-details call came back None, the release step read off it, and the crash aborted the whole tag write: no release id, no recording id, no Deezer or Spotify ids either ("Error embedding source IDs (non-fatal)" in the log). the track now keeps everything but the ISRC and genres that one call would have supplied.
- Fix Unknown Artists recognises every server's placeholder ([Unknown Artist] on navidrome and plex, unbracketed on jellyfin, "Unknown Artists" in some tag sets) and takes your own spellings in a new job setting.
chat
- jukebox links play again. oembed answers 401 for any video whose owner disallows embedding and that was read as "no link"; a failed title lookup is "no title yet" now. a jukebox search ranks official / Topic / VEVO up and reaction / karaoke / tutorial down instead of taking youtube's first five.
- optimistic messages no longer flicker or vanish on send, live room messages ingest the moment the buffer changes, the archive tail is merged with the live wire buffer so fresh messages are not dropped, and Now Playing and Wanted cards persist across a reload.
audiobooks
- the library is a page, /audiobooks/library, instead of a modal over browse: a url to link and reload, and escape no longer throws the view away.
- every wishlist write used to land on profile 1. for any other profile the row never moved off "wanted": no attempt counted, no backoff, the same book searched and grabbed on every pass, and a failed grab even re-added the book to profile 1's list. rows carry their profile now, a finished import is done for whoever wanted it, and a followed author's new books go to the profile that follows them.
- "Look again" puts a cancelled or not-found book back to wanted with the backoff waived. a library scan marks wanted books it finds as done at once. a download the client no longer has is given up on after ~3 minutes and the book goes back to the wishlist, instead of waiting for it forever; a client that is down keeps every book waiting rather than failing them all.
podcasts
- downloads wait their turn: a bounded semaphore (default 3) instead of a thread per episode the moment it was queued.
- a failed or cancelled auto-download, or a restart mid-download, was "done" forever because the row was written at queue time. only a row with a file counts now, so the scan retries it.
- the page knows which episodes are on disk after a restart, so a click does not fetch them a second time. retention never prunes an episode that never landed.