▲ 48 r/nullPlayer+7 crossposts

New nullPlayer release 0.27.0 -- New compact window, improvements and bugfixes - get it for macOS on github or homebrew

https://github.com/ad-repo/nullplayer/releases/tag/0.27.0

# one-time configuration 
brew tap ad-repo/nullplayer 

brew install --cask ad-repo/nullplayer/nullplayer 

or if already installed manually
brew install --cask --force ad-repo/nullplayer/nullplayer 

To upgrade to a new release: 
brew update 
brew upgrade --cask ad-repo/nullplayer/nullplayer

New Features

  • Compact Window adds a free-floating mini player — the Windows menu and main-window context menu now include Compact Window, which uses the same compact Library Browser mini-player as Compact Mode but keeps NullPlayer as a regular Dock/menu-bar app. It hides only the main window, leaves Playlist/EQ/Spectrum/Library/visualization windows where they are, uses normal window level unless Always on Top is enabled, can be dragged from both the player bar and browser area, remembers its frame, and restores across launches.
  • Balance control added to Playback menu — the Playback options now include a Balance submenu with a slider and common left/center/right presets, giving modern UI and menu-only workflows access to stereo balance without adding more controls to the player face.

Improvements

  • Modern and Metal UI now use a modern system font — the retro low-fi bitmap font (Departure Mono) has been replaced throughout the Modern and Metal windows — Library tabs and headers, the main window, playlist, EQ, and spectrum — with the crisp macOS system font. Time and track digits stay monospaced so they don't jitter. Skins that ship their own custom font still render it as before.
  • License and branding terms clarified — the project license notice and README now state GPL-3.0-only distribution terms and clarify that modified distributions must not reuse the NullPlayer name, icon, logo, bundle identity, or other branding without permission.
  • Compact Mode player bar reads like the main window — in Modern and Metal, the Compact Mode display now splits into two distinct LCD "windows" with a padded gap: a single elapsed/remaining time counter on the left and the scrolling track title on the right (previously the title sat left with a cramped "elapsed / total" reading pinned to the right). The counter matches the title's size and weight, and the transport buttons are slightly larger.
  • Larger Library tab and control fonts — the Library Browser's tab labels and control text render at a slightly larger size in non-compact mode for better legibility. Compact Mode is unchanged.

Changes

  • Window shade mode removed — double-clicking a window's title bar no longer collapses it to a title-bar-only strip ("windowshade"). This legacy Winamp feature was the source of recurring layout glitches when combined with Large UI, Compact Mode, and live UI-mode switching; removing it makes window sizing and position memory behave consistently across every window in Classic, Modern, and Metal.
  • Library source menu lists only sources — the Library Browser's source picker no longer injects local-library settings ("Manage Folders…" and the "Clear Local Library" submenu) when the local source is active. Those are settings, not sources, and already live in the Library menu-bar item, so the source menu now lists sources only.

Bug Fixes

  • Metal skin transport icons are now fully filled — the previous/next (and eject) icons in the Metal finishes no longer show a stray light vertical line: the icon bars now draw in the same transport-button color as the rest of the glyph instead of the skin's light primary color.
  • Plex Artists no longer show duplicate same-name rows — the Library Browser now groups Plex artist records with the same display name into one visible artist row in both classic and modern UI. Expanding, playing, or queueing that row still fans out across every underlying Plex ratingKey, so albums and tracks attached to duplicate server-side artist records remain accessible instead of being hidden.
  • Compact Mode art ratings fit the small UI — the modern Library Browser's art-view rating stars now shrink in Compact Mode, preventing them from crowding or overlapping the source/library picker row.
  • Compact Window no longer reopens the main window after Space switches — returning from another desktop or fullscreen app now focuses the floating compact mini-player instead of treating the hidden main window as something to restore, so Compact Window stays a one-window main-player replacement until you exit it.
  • Library window remembers where you put it — after unlocking the connected windows and moving the Library/browser window, it now reopens at the exact position and size you left it — across closing and reopening it (via the menu or the red close button) and across full app restarts, even when it was closed at quit. First-ever opens still dock to the right of the window stack, and the position survives Compact Mode. Playlist, EQ, and Spectrum still intentionally snap back into the column below the main window.
  • Classic Large UI toggles instantly — no restart — turning Large UI on or off in the classic skin now resizes the windows in place, matching the modern UI, instead of asking you to relaunch. The player, EQ, playlist, and other windows redraw crisply at the new size (no leftover "ghost" of the old size), and switching between Classic, Modern, and Metal while Large UI is on no longer distorts the new look.
  • ProjectM visualizer recovers from a preset that crashes mid-playback — a rare bug inside the MilkDrop preset engine could crash the app while a preset was on screen — including minutes into a track, not just when the preset first appeared. The crash-guard now watches a preset for its entire time on screen (previously only its first frame), so the offending preset is automatically skipped on the next launch and the crash never recurs. Normal quits never flag a good preset.
  • Metal playlist and Library highlights are now clearly visible — in Metal skins, the playlist's now-playing track and the Library Browser's selected/expanded row were indicated by text color alone, which several metal finishes render nearly identical to normal rows, so the active row was easy to miss. Both now draw a translucent green backlit-LCD highlight bar (matching the hi-fi display panels) as the cue. The metal playlist's row text is also unified at the Library window's brightness — previously it was dimmer — and the current track no longer recolors to the accent tone that clashed with the new highlight.
u/That-Acanthisitta536 — 13 hours ago

New release 0.26.1 has been uploaded with a few cleanup items. get it on github and homebrew

Bug Fixes

  • App icon no longer renders as a square on fresh installs — the Dock and Cmd-Tab app icon could appear as a hard square (with the rounded logo visible inside it) on Macs that hadn't already cached the icon, while staying correct on machines that had. The icon's rounded "squircle" shape is now baked into the build, so it looks right everywhere on a clean install.
  • Cue albums split correctly even when the audio file was renamed — library split-on-import now locates the backing audio by its same-named sibling when a .cue's internal FILE reference is stale (for example, when the .cue and its audio were renamed together), instead of importing the whole album as one track. Adding the backing audio file directly with Add Files… now triggers the split too.
reddit.com
u/That-Acanthisitta536 — 6 days ago
▲ 5 r/nullPlayer+1 crossposts

New nullPlayer relaase 0.26.0 - features youtube channel support, menubar compact mode, metal UI mode, new audio analysis window and lots more!

get it on homebrew or github!

brew upgrade --cask ad-repo/nullplayer/nullplayer  

https://github.com/ad-repo/nullplayer/releases/tag/0.26.0

New Features

  • Compact Mode — a menu-bar mini player — collapse NullPlayer into a single menu-bar app: the Dock icon and all the player windows disappear, and a status-bar item gives you one slim window — the Library Browser with a built-in player bar across the top (transport, seek and time, a scrolling title, and volume). Open it from the main window's right-click menu, the Windows menu, or the new CP button in the modern toolbar; click the status item to bring it back or exit. A playing video stays on screen, so you can keep watching while you browse. Works in both classic and modern UI.
  • Audio Analysis window — a real-time, multi-pane analyzer (inspired by Friture), opened from the Window menu, a right-click, or the new AA button in the modern toolbar. Switch between three views: a Scope oscilloscope of the live waveform, a Levels meter showing per-channel peak and RMS, and a scrolling Spectrogram waterfall. It docks and snaps with the other windows and remembers its position and selected view. Works in both classic and modern UI.
  • YouTube channels in the Radio tab — add YouTube channel links and browse each channel's uploads right in the Radio tab — no account or API key needed. Double-click a video to download its audio (FLAC or MP3) or video (720p/1080p) ad-free into a folder you choose; downloads play locally and cast to Sonos, Chromecast, and DLNA like any other track, and get their own YouTube entry in the Data tab. Quality and the download folder are set in the Library menu. Works in both classic and modern UI.
  • Metal mode — hi-fi faceplate finishes — a new metallic look, selectable from Skins → Metal, with seven finishes: Brushed Steel, Aluminum, Gunmetal, Anodized Black, Brass, Bronze, and Copper. Each finish restyles the whole player — chrome, panels, sliders, transport, and EQ — with a backlit-green LCD for the time and track displays and a spectrum analyzer matched to the finish.
  • Switch between Classic, Modern, and Metal instantly — no restart — changing UI mode, or picking a skin from a different mode, now happens live and in place. Playback, casting, the open playlist, the current track, and your play position all continue uninterrupted while the windows rebuild in the new look, reappearing where you left them. (Classic Large UI still relaunches, since it's a size change rather than a mode switch.)

Improvements

  • Visualization window renamed "Visualizations" — the window that hosts the ProjectM, Geiss, Tripex, and Met Museum visualizers is now labeled Visualizations everywhere.
  • Tidier Library tabs (classic & modern) — Library tab names now sit in rounded boxes sized to fit their labels, so every tab has room to breathe. The Shows tab is now TV, and the Radio and Search tabs have swapped places.
  • Modern toolbar refresh — clearer toolbar buttons in the modern main window, including the visualizer (VZ) toggle and the new AA (Audio Analysis) and CP (Compact Mode) buttons.
  • Titled utility windows (classic) — the Spectrum Analyzer, Waveform, Library, and Visualizations windows now show their names in the title bar.

Bug Fixes

  • Metal mode — Library Browser top bar no longer flickers darker — in Metal mode the Library Browser's top strip occasionally flashed the darker modern styling before correcting itself; it now stays consistent with the metal finish.

  • Library search now lands on the artist you picked (Plex) — choosing an artist from Library search results reliably switches to the Artists tab and selects that artist, in both classic and modern UI.

  • Cleartext http:// radio stations play again (#310) — after 0.25.0, many http:// Icecast/SHOUTcast stations connected but produced no sound (they sat stuck at 0:00); they now play again. https:// stations were unaffected.

  • "Test" button in Add Station no longer fails working stations (#310) — the station test now connects the same way the player does, so it stops reporting errors for stations that play perfectly.

  • Sample-rate (kHz) display now shows for streams without a visualization open (#285) — the classic skin's kHz readout stayed blank for some streaming tracks unless a visualization was open; it now appears as soon as playback starts.

  • Album-art mode no longer traps you after clearing the playlist (#283) — clearing the playlist while viewing album art now returns you to the normal browser, in both classic and modern UI.

  • Album-art mode exits when you change tab or source — switching Library tabs or sources now leaves the artwork view and restores the normal list, instead of leaving you stuck on the artwork.

  • Video no longer auto-casts in the classic UI — playing a video in classic UI no longer silently sends it to a Chromecast/DLNA TV; it opens in the local video player unless you've chosen a cast device.

  • Casting to a just-rebooted Sonos speaker now works on the first try — a Sonos cast that used to fail right after the speaker rebooted now recovers on its own and plays.

  • Sonos recovers when a speaker reboots mid-playback (#304) — if a Sonos speaker rebooted while casting, NullPlayer could end up playing from both the Mac and the speaker at once; it now cleanly ends the dead session so playback resumes correctly.

    brew tap ad-repo/nullplayer        # one-time configuration 

    brew install --cask ad-repo/nullplayer/nullplayer   or if already installed manually brew install --cask --force ad-repo/nullplayer/nullplayer

    To upgrade to a new release:   brew update   brew upgrade --cask ad-repo/nullplayer/nullplayer  

    To verify the tap is picking up the latest version:   brew livecheck --cask ad-repo/nullplayer/nullplayer  

    Notes from the cask:  

    • App is ad-hoc signed (not notarized). The cask's postflight runs xattr -cr to strip the quarantine bit so Gatekeeper allows first launch.  
    • Requires macOS Sonoma or newer.  
    • brew uninstall --cask --zap nullplayer removes app support/caches/prefs, but Keychain tokens (service com.nullplayer.app) must be removed manually: security

 

u/That-Acanthisitta536 — 7 days ago

Hey everyone version 0.25.0 is out - It has direct youtube ripping to the library, cue file support with file splitting, local library folder navigation view and a lot of other improvements and some crucial fixes pointed out by u/spacecowgoesmoo! nullPlayer is always free and open source

I have been pretty preoccupied with these amazing Rush shows goings on for the last week but being tied to youtube exposed a glaring need in the app - in app youtube ripping support for both audio and video!

get it on github or homebrew!

brew tap ad-repo/nullplayer        # one-time configuration  

brew install --cask ad-repo/nullplayer/nullplayer  

or if already installed manually

brew install --cask --force ad-repo/nullplayer/nullplayer 

https://github.com/ad-repo/nullplayer/releases/tag/0.25.0

New Features

  • .cue sheet playback — virtual split (#273) — opening a .cue file (via File → Open, drag-and-drop, or double-click), or opening an audio file that has a sibling .cue next to it, now plays the single backing file virtually split into its cue tracks: one row per track in the now-playing playlist, with the title, performer, and duration taken from the cue. Prev/Next move per cue track and seeking stays within the current track, while playback crosses track boundaries gaplessly — the backing file is scheduled as one continuous stream and a boundary detector advances the playlist row (updating title, seek bar, Now Playing, and history) without touching the audio. Gapless applies with shuffle and repeat-single off; in those modes boundaries still advance correctly but a small gap is expected. Nothing is written to disk and nothing is added to the Local Library; a missing/renamed backing file simply shows its rows as unplayable. The parser reads the first FILE entry (extra ones warn), prefers INDEX 01 (falling back to INDEX 00), and is the exact inverse of the Stream Ripper's chapter-.cue writer, so a rip's own cue round-trips. .cue is now also offered in the File → Open panel's file-type filter.
  • Split .cue albums on import (library, off by default) — a new Library → Split .cue Albums on Import toggle (default off) makes the Local Library scan physically split a single-file album into per-track files when it finds a .cue next to it. When on, each track is cut with ffmpeg and re-encoded to FLAC (re-encoding, not stream-copy, so cuts are sample-accurate) into a per-album subfolder named from the source file's own ALBUM/ARTIST tags (e.g. Artist - Album/), falling back to the cue's performer/title, then the cue filename. Each track inherits the source's metadata (date, genre, embedded cover art) with the title/track-number and album/album-artist set from the source tags; the split tracks are added to the library in the same scan and the original backing file is excluded. The split is idempotent (a re-scan does no work if the per-track files already exist) and filenames are sanitized and de-duplicated so they can't collide or escape the album folder. If ffmpeg isn't installed — or a write fails (permissions, read-only volume, out of space) — splitting is skipped with a one-time notice and the original file imports normally as a single track (it's only hidden once real split tracks exist). When the toggle is off.cue files are ignored by the scan entirely and the backing file imports as one normal track. Direct-play (above) is unaffected by this toggle. Changing the toggle takes effect on the next scan.
  • Local library reads FLAC/M4A album-artist and track/disc numbers — metadata parsing previously read album-artist and track/disc numbers only from MP3 ID3 frames (TPE2/TRCK/TPOS), so FLAC/OGG (Vorbis ALBUMARTIST/TRACKNUMBER/DISCNUMBER) and M4A (aART/trkn/disk) tracks came back without them — causing single albums to fragment by per-track artist and lose their track ordering. These tags are now read across all containers (handling the 1/10 track form).
  • Stream Ripper — download a URL to FLAC/MP3 or a video file — a new Output → Streaming → Rip URL… action opens a dialog where you paste a URL (auto-filled from the clipboard when it holds a web link) and choose an output type: Audio — FLAC (lossless)Audio — MP3, or video at a resolution/bitrate profile you pick (720p/2.5 Mbps, 1080p/4 Mbps recommended, 1080p/8 Mbps high quality, 1440p/16 Mbps, 4K/35 Mbps, Full/50 Mbps max). Ripping shells out to a system-installed yt-dlp (+ffmpeg); if either isn't found it shows an install hint (brew install yt-dlp ffmpeg) rather than failing silently. Quality is prioritized for audio (bestaudio, then lossless FLAC encode or top-VBR MP3). Video grabs the best source streams within the selected height cap (or no height cap for Full), then ffmpeg creates a playback-safe H.264/AAC MP4 with yuv420p pixels and fast-start metadata so the app and cast targets do not receive VLC-only files. The video source file is temporary ([source]) and is removed after the compatible MP4 is written; existing MP4s are not overwritten. Output is tagged with the source's metadata (title/artist/album/date) and, for audio, the thumbnail is embedded as cover art; the final file is named Artist - Title from that metadata into a folder you pick. If the source has chapter timestamps (common on album/mix uploads), a matching .cue sheet is written alongside the audio — one TRACK per chapter. Progress shows as a spinner + message band at the top of the main window for the duration of the rip (works in both classic and modern UI). When it finishes, a dialog offers Play Now (audio loads into the player; video opens in the video player window, cast-aware), Reveal in Finder, or Done.
  • Local .m3u/.pls playlists in the Plists tab (#269) — the local library browser's Plists tab now lists .m3u.m3u8, and .pls playlist files found on disk, matching what the Plex/Subsonic/Jellyfin/Emby sources already show there (previously the tab was always empty for the local source). Playlist files are discovered during the normal library scan and their locations persisted in a small library_playlists table — the track contents are not stored, but parsed lazily the first time you expand a playlist. Expanding shows each entry as a row: entries that match a file already in your library carry its metadata and duration, while unmatched paths still appear and remain playable. Double-clicking a playlist row loads and plays the whole list; double-clicking a single entry plays just that track; the disclosure triangle expands as usual. Removing a playlist file from disk drops it from the tab on the next scan, while a transiently unreachable network folder leaves the list intact (the same offline-volume safety guard used for tracks). Implemented identically in both the modern and classic library browsers. Pairs with the earlier "browse by folder structure" work under the same "organize by what's actually on disk" philosophy.
  • Remove Orphaned Entries (library maintenance) — new Library → Clear… → Remove Orphaned Entries… action removes library entries whose files are no longer inside any watched folder. These orphans are typically left behind by an older buggy removal that deleted the watch folder but not its entries, so they can't be cleared by removing a folder (none owns them). The action previews the count, auto-creates a backup first, deletes from both memory and the SQLite store (tracks, movies, episodes, playlists), and never touches files on disk. Path matching uses the resolved url.path so it stays fast on large libraries.
  • Browse local library by folder structure — the local library can now be browsed by its actual on-disk folder hierarchy instead of by Artist/Album/Playlist metadata. Rather than adding a ninth tab, the existing Plists tab slot doubles as a toggle: double-click it (local source only) to flip between Plists and Folders; single-click selects whichever the slot currently shows, and the choice persists across launches. The Folders view reflects what is actually on disk right now — including files that haven't been scanned into the library yet — read lazily one directory level at a time as folders are expanded; library metadata (title, duration) enriches a file row only when that file is in the database. Folders sort first, then files, case-insensitively; symlinked directories are skipped to avoid loops. Right-click a folder for Play / Play and Replace Queue / Play Next / Add to Queue / Show in Finder, which recursively collect every supported audio file beneath it. Filesystem enumeration and database lookups run off the main thread (with per-click cancellation and a loading spinner) so large network/NAS folders don't stall the UI. Implemented independently in both the modern and classic library browsers.

Improvements

  • Keychain credentials hardened (#253) — saved server credentials (Plex, Subsonic, Jellyfin, Emby) are now stored with the kSecAttrAccessibleWhenUnlockedThisDeviceOnly accessibility class, so they are only readable while the Mac is unlocked and never sync off the device. The previous permissive per-item ACL has been removed. Entries written by earlier versions are upgraded automatically and lazily the first time each one is read.

Bug Fixes

  • Main-window right-click menu simplified — the main window context menu no longer shows Sleep Timer or Remember State controls. Those settings remain available from the macOS menu bar, keeping the right-click menu focused on playback/window actions.
  • Removing a watch folder now actually deletes its tracks and persists — removing a watched folder removed its tracks/movies/episodes from the in-memory arrays but never deleted the rows from the SQLite store, and the folder row itself often failed to delete too. Because the library browser reads from the store (not the in-memory arrays), removed tracks kept appearing and never went away, and the "removed" folders reappeared on next launch. Two underlying bugs: (1) removeWatchFolder(removeEntries:) only updated memory and called store.deleteWatchFolder for the folder — it now also deletes the matching track/movie/episode rows via new chunked, transactional bulk deletes; (2) MediaLibraryStore.deleteWatchFolder reconstructed the folder URL with URL(fileURLWithPath:), which on an offline network volume can't stat the path to add the trailing slash that stored directory URLs carry (file:///Volumes/home/MUSIC/), so the WHERE clause matched nothing — it now matches the trailing-slash, no-slash, and raw-path forms so offline folders delete correctly. (Pre-existing orphans left by the old behavior aren't retroactively removed by removing a folder — use the new Remove Orphaned Entries… action to clean them.)
  • Watch-folder removal confirmation was invisible — the "Remove Watched Folder?" confirmation opened as a free-floating alert at the normal window level, below the Manage Watch Folders window (which sits at .modalPanel for issue #254) and below any always-on-top windows, so it was hidden off-screen-behind and could never be confirmed — clicking Remove… appeared to do nothing. It's now a window-modal sheet attached to the manager window: always visible, and it blocks the folder table beneath it (you can no longer select another row while it's open). This was the root cause behind "removing folders does nothing."
  • Removing a watch folder took ~20 seconds on large libraries — removalCountsForWatchFolder() and removeWatchFolder() called resolvingSymlinksInPath() once per track to normalize paths — roughly one filesystem call per library item (~60k on a large library). They now compare track.url.path directly (already resolved at scan time), the same optimization watchFolderSummaries() received, making removal near-instant.
  • Removing a watch folder no longer beachballs the app — in the Manage Watch Folders window, clicking Remove… ran removalCountsForWatchFolder() and removeWatchFolder() directly on the main thread. Both block on MediaLibrary's internal dataQueue.sync, and a running import scan (e.g. right after adding/rescanning a folder) holds that queue for many seconds — so the app froze with a spinning beachball until the scan finished. These calls now run off the main thread (only the confirmation alert stays on main, where it must), matching the pattern the window's folder-list reload already used. Also hardened the modern Library Browser's Folders view, which made the same blocking watchFolderSummaries() call on the main thread just before handing off to its background walk — that snapshot now happens inside the background task.
  • Popup dialogs no longer hide behind always-on-top windows (#254) — with Always on Top enabled, opening a popup dialog (e.g. Add Radio Station) appeared to do nothing: the dialog opened at the normal window level, below the main window which had been raised to the floating level, so it was completely obscured until the main window was dragged aside. These transient dialogs now open at the .modalPanel level so they always sit above the app's floating windows, matching the tag-editor and Plex link dialogs that already did this. Covers Add/Edit Radio Station, the Subsonic/Jellyfin/Emby link and server-list sheets, the watch-folder manager, and the auto-tag album candidate picker.
  • Non-Retina classic skin colors fixed (#256) — removed the blanket blue→grayscale conversion in SkinLoader.processForNonRetina() that ran on 1× displays, converting every blue-dominant pixel to gray across all classic skin sprites and stripping legitimate blue tones from every skin. The conversion never ran on Retina, which had masked the bug.
  • Non-Retina Data tab text/chart blur fixed (#257) — the modern Library Browser "Data" tab hosting view is now opaque (isOpaque = true with an opaque skin background, kept in sync on skin change). A clear, non-opaque layer had disabled AppKit font smoothing, blurring text and charts on 1× displays; it now mirrors the classic PlexBrowser twin.
  • Local library expand re-sort fixed (#262) — with a column sort active, double-clicking an Artist or Album to expand it no longer reshuffles the top-level list. The list shown before expanding came from the in-memory column sort (LibraryTextSorter: diacritic-insensitive, numeric, leading-article-aware), but expanding a row rebuilt it from the store's SQLite BINARY collation order and skipped re-sorting once nested rows were present — so the order silently snapped to the raw store order, most visibly around names with special characters, mixed case, or leading articles. The local-library views in ModernLibraryBrowserView and PlexBrowserView now re-sort top-level groups (each leader plus its expanded children) with the same comparator, keeping visible order stable through expand/collapse.
  • HTTP-only internet radio streams now play (#255) — adding a station whose stream URL is plain http:// (e.g. many Icecast/SHOUTcast servers on custom ports) silently failed to play: it sat buffering forever and never started. Internet radio plays through the AudioStreaming library, which fetches over URLSession, but the app's App Transport Security config only declared NSAllowsArbitraryLoadsForMedia — a key that exempts AVFoundation media loads, not URLSession — so cleartext connections were blocked by ATS. The reported ".mp3 links work, others don't" pattern was a coincidence: the working stations happened to be https://, and the real distinction was scheme, not file extension or audio format. Info.plist now sets NSAllowsArbitraryLoads so http stations connect.
u/That-Acanthisitta536 — 20 days ago