Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NokiPod

A dark desktop companion for a Rockbox iPod, built with PyQt6.

Plug the iPod in and NokiPod finds it, scans its music, scrobbles what you listened to on the go, fixes your tags, fetches your lyrics and evens out your volume. The window is one screen: Now Playing on the left, and on the right a cascade of tiles that falls away along an arc. The library, your playlists and the play queue are all levels of that same cascade.

This app is designed around music players (not just iPods!) running Rockbox to add a little more convenience and ease-of-use. It is NOT designed for your local music library. That may come later.

NokiPod playing a track

v0.1.1 is the upcoming public beta for Linux and Windows. It is prepared as the first release with a Windows installer, but has not been tagged or published yet. The local candidate passed the full Linux and Windows test/UI loops plus a fresh install and a same-version reinstall over deliberately stale payloads under Wine; the exact workflow still needs its first hosted run, and native Windows with a physical iPod remains a smaller evidence set than Linux. Expect rough edges and please report them.

What it does

Tool What it does
Library Browse the iPod's music (Artists, Albums, Songs) as tiles colored from the real cover art, with arrow keys or the mouse, and play it through your computer. Playing a track queues the rest of the list behind it.
Search Pretty self-explanatory
Queue and lyrics The queue is a level of the cascade: history above, the playing track centred, upcoming below, drag the grip to reorder. The lyrics panel reads a .lrc sidecar or an embedded lyrics tag and follows the timestamps.
Scrobbler Auto-scrobbles new plays from the iPod's .scrobbler.log to Last.fm the moment the device connects, with today and all-time counts and a recent-plays feed.
ReplayGain Runs rsgain over the Music folder on the music player running Rockbox with your chosen target loudness and album or track mode, reporting per-track gain and peak.
Playlists Reads the device's .m3u and .m3u8 playlists, shows them as song tiles you can reorder by dragging, and builds new ones by ticking songs.
Tags A batch tag editor: edit title, artist, album, year and genre across the library, flag what is missing, and embed album art. Fix for Me fills the gaps from MusicBrainz and downloads cover art.
Settings Volume and fades, repeat, auto-queue, resume where you left off, device info and eject, the interface click voice, whether to copy your play history to the iPod (off unless you turn it on), and live sliders over the interface's own colour, tile and motion values.

Screenshots

The library, with the cascade of tiles on the right:

The library

Artists:

The artist list

An artist's albums, each tile coloured from its own cover art:

An artist's albums

Searching the whole library at once, with songs, albums and artists grouped under labelled dividers:

Whole-library search

The queue, with history above the playing track and upcoming below:

The queue

Lyrics, following the song as it plays:

Lyrics

The Scrobbler sheet:

The scrobbler

The Tags editor, and its bulk grid:

The tags editor

The bulk tag grid

ReplayGain and Settings:

ReplayGain

Settings

Install

Windows

Download NokiPod-Setup-*.exe from the latest release (Windows installers ship from v0.1.1 onwards) and run it. NokiPod requires an x64-compatible Windows 10 version 1809 (build 17763) or later, or Windows 11. It installs strictly per-user — no administrator prompt — puts NokiPod in the Start menu, and bundles rsgain, so ReplayGain works out of the box. The workflow builds that scanner from an exact rsgain source commit and a pinned vcpkg snapshot using FFmpeg 9.0.1; FFmpeg and the other copyleft libraries are replaceable DLLs beside rsgain.exe. Their notices, binary hashes, exact source provenance, rebuild instructions, and source offer are installed in the rsgain folder. The same folder includes the Windows frozen/runtime CycloneDX SBOM; a separately named release SBOM inventories the locked Python packages. The workflow also replaces CPython's superseded OpenSSL 3.0.21 DLLs with a source-built, hash-pinned OpenSSL 3.0.22 security release and verifies real certificate-checked HTTPS; Qt uses the native Windows Schannel backend. The installer/compile targets and reviewed DLL-import allowlist are set for Windows 10, but the final installer still needs its first smoke run on a native Windows 10 1809 VM. The installer is not code-signed: SmartScreen will warn on a fresh download, and "More info → Run anyway" is expected. SECURITY.md describes how to check the download against SHA256SUMS.txt and the build provenance attestation first. Provenance and platform code signing provide different assurances; the installer does not yet have the latter.

Linux

Download NokiPod-*-x86_64.AppImage from the latest release, make it executable, and run it:

chmod +x NokiPod-*-x86_64.AppImage
./NokiPod-*-x86_64.AppImage

An AppImage is a single self-contained file. Python and Qt are bundled inside it, nothing is installed, and it runs from wherever you put it.

From a source checkout, the integration helper can add the AppImage to your application menu. It records wherever the AppImage actually lives, so it works no matter where you put it:

packaging/install.sh                      # or: install.sh /path/to/NokiPod-*.AppImage
packaging/install.sh --uninstall          # to remove the entry

A tool like Gear Lever can handle AppImage integration for you instead.

Updating

NokiPod never checks for or installs an update by itself. Release AppImages intentionally contain no embedded update URL, and the release publishes no .zsync sidecar, so the unverified AppImage delta-update path is not supported. Download each new AppImage or Windows installer from the releases page and verify it the way SECURITY.md describes before running it.

Optional extras

Neither is needed for scrobbling.

  • ReplayGain needs rsgain. The Windows installer bundles it; on Linux put it on your PATH: sudo pacman -S rsgain or apt install rsgain.
  • Fingerprint tag matching (accurate even when the existing tags are wrong) needs fpcalc from Chromaprint (pacman -S chromaprint, apt install libchromaprint-tools, or on Windows the fpcalc.exe from acoustid.org/chromaprint) plus a free AcoustID key entered in the app. On Windows, put fpcalc.exe beside the installed NokiPod.exe or somewhere on your PATH. A copy found only in an unrelated folder NokiPod was launched from is deliberately ignored. Plain text matching works without either extra.

Run from source

pip install -r requirements.txt      # PyQt6 + mutagen
python3 nokipod.py                   # or ./run.sh

How it finds your iPod

Automatically. Every mount point is scored for Rockbox and iPod markers (.scrobbler.log, .rockbox, iPod_Control, Music), and the best candidate wins. A folder called Music on its own is never enough, so an ordinary USB stick is not mistaken for a device.

That means it works on any Rockbox iPod, not just one that has been set up a particular way: a fresh Rockbox install, an iPod with no music on it yet, one using the Apple iPod_Control/Music layout, and even a non-iPod Rockbox player are all recognised. TO BE CLEAR: I HAVE NOT TESTED THIS SOFTWARE ON ANY iPOD THAT DOESN'T RUN ROCKBOX.

Nothing to configure. Plug it in and the status dot in the top bar turns green while the library is scanned behind the launch screen. If you mount your device somewhere unusual, NOKIPOD_FORCE_MOUNT=/path/to/mount overrides the search.

How scrobbling works

  • Source: <iPod>/.scrobbler.log, Rockbox's tab-separated play log.
  • History archive: a cumulative record of every entry ever uploaded, in the same format, kept in ~/.local/share/nokipod. Created automatically.
  • Duplicate rule: an entry is a duplicate when its artist, title and timestamp all match something already in the history. The same song heard again at a different time is not a duplicate, so it scrobbles again.
  • Tracks rated S (skipped on the iPod) are never uploaded.
  • Timestamps: Rockbox logs either UTC (#TZ/UTC) or the device's local wall-clock time (#TZ/UNKNOWN). Local times are converted using your computer's timezone, DST-aware, per timestamp, with no hardcoded offset.
  • Uploads go in batches of 50. Each accepted batch is archived immediately, so a failure part way through never re-scrobbles earlier batches. Tracks Last.fm ignores (a timestamp too old, say) are archived too, so they are not retried forever.
  • The original .scrobbler.log is left on the iPod. Duplicate detection makes re-reading it harmless.

How lyrics work

Press Lyrics (or L) while a song is playing. NokiPod reads a .lrc sidecar next to the track, or a lyrics tag inside it, and highlights the live line as the song plays.

If a song has none, the panel offers to fetch them from LRCLIB, a free and open lyrics database that needs no account and no API key. You can do the one song or the whole library, and Automatically add lyrics to new songs keeps anything you add later topped up. Lyrics are saved as .lrc files beside the audio, the same format LRCGET uses, so a library built by either tool works in both.

Songs LRCLIB has nothing for are remembered so the automatic sweep stops asking. Add for every song deliberately retries them, which is what you want after correcting a track's tags. Matching is by artist, title, album and duration, so tracks with missing tags will not match. Run the Tags editor first.

How tag fixing works

Fix for Me matches your files against the free MusicBrainz web service, filling missing title, artist, album, year and genre, and embedding cover art from the Cover Art Archive. No account or key is needed.

MusicBrainz genre data is thin outside well-known releases, so when it has no genre for a track NokiPod falls back to Last.fm's crowd tags. That uses only the API key you already entered for scrobbling. With no key it simply skips that step.

In the Tags overview, clicking a count such as Missing genre opens exactly those tracks.

How ReplayGain works

rsgain easy --skip-existing "<iPod>/Music"

rsgain is resolved from your PATH. --skip-existing means re-runs only touch files that have no ReplayGain tags yet.

Last.fm authentication

You connect with your own free Last.fm API account, and the wizard walks you through creating one. NokiPod stores the API key, shared secret and the session key it obtains in config.json inside ~/.local/share/nokipod. Session keys do not expire. If Last.fm ever invalidates one, NokiPod clears it and offers the wizard again.

Privacy

NokiPod has no account of its own, no telemetry and no update check. It talks to four services, each one only when you use the feature that needs it.

Goes to What it sends When
Last.fm The artist, title, album, track number, duration and timestamp of each play, signed with your session key. Your username, to read back your public play count and recent plays. An artist and title, to look up crowd tags when MusicBrainz has no genre. Scrobbling, and the genre fallback in Fix for Me
LRCLIB Artist, title, album and duration, as a search query. No account, no key. Fetching lyrics
MusicBrainz and the Cover Art Archive Artist, title and album as a search query, then the release it matched, to read genre and download cover art. Fix for Me
AcoustID The acoustic fingerprint fpcalc computes from the audio, its duration, and your AcoustID key. Not the file, not its name, not its path. Fix for Me, and only if you entered an AcoustID key

Nothing else leaves the machine, and no audio is ever uploaded.

What is kept on your computer

Everything NokiPod remembers is in ~/.local/share/nokipod (or $XDG_DATA_HOME/nokipod if you have set that). NokiPod asks for 0700 on the folder and 0600 on these files, so on an ordinary Linux or macOS home directory no other account on the machine can read them.

Whether that holds depends on the filesystem the folder sits on. FAT, exFAT, NTFS mounted without permissions, and most network shares have nowhere to keep a permission bit, so chmod on them reports success and changes nothing. If your home directory or your $XDG_DATA_HOME is on one of those, your Last.fm keys and your listening history are readable by anyone with an account on the machine.

So NokiPod does not trust chmod. Every time it starts it reads the modes back off the disk, and if the folder or config.json did not end up private it shows you one notice saying so and naming the path. Once, at startup, not on every action. It still runs: not being able to protect the file is no reason to lock you out of your own music player. On Windows the folder is %APPDATA%\NokiPod and it is your Windows profile, not a mode, that keeps other accounts out, so there is nothing to check and nothing is shown.

File What is in it
config.json Your Last.fm API key, shared secret and session key, your username, your AcoustID key if you entered one, and every setting from the Settings tool
scrobble-history.log Every play ever uploaded. This is the file duplicate detection reads
app-plays.log Plays made through NokiPod itself rather than on the iPod
scrobble-log-export.log The two above merged with the device's log
playback-archive-<date>.log A copy of the device's raw playback.log, taken before NokiPod resets it
lyrics-misses.json Tracks LRCLIB had nothing for, so a sweep stops asking
scan-cache.json The scan cache: the path and tags of each file on the device, so a rescan is quick

Copying your play history to the iPod

Off by default. Settings has a Copy play history to iPod toggle, and while it is off nothing about your listening is written to the device. The merged log is still built in your data folder either way, as scrobble-log-export.log in the table above.

Turn it on and NokiPod writes that same merged log to scrobble-log-export.log in the root of the iPod: when the device is plugged in and its scan finishes, after every batch Last.fm accepts, and when you press Export & sync now. It is the whole archive rather than the new plays, so it grows for the life of the install.

Worth knowing what that means before you turn it on. An iPod is FAT formatted, and FAT has no permission bits, so this copy cannot be protected the way the one in your data folder is. It is your full listening history, readable, in the root of a removable drive that plugs into any computer.

Turning the toggle back off stops NokiPod writing the file again, but it does not remove a copy already sitting on the device. Delete it from the iPod, the button next to the toggle in Settings, does that, with the iPod plugged in. The two are independent, so turn the toggle off first: delete it while copying is still on and the next sync writes it straight back. NokiPod says so when that is the situation. You can also delete scrobble-log-export.log from the device's root yourself.

If you have used an earlier build of NokiPod, assume the file is already on your iPod. Every version before this one wrote it on every sync with no setting to stop it.

Disconnecting Last.fm

There is no disconnect button yet. Settings shows Last.fm authorisation · Re-link account, but that only runs the wizard again and overwrites the stored credentials with a new set. To remove them, quit NokiPod first, because a running copy holds the settings in memory and writes them back, then delete the file:

rm ~/.local/share/nokipod/config.json

That takes the API key, the shared secret and the session key with it, and NokiPod starts up unlinked and offers the wizard. It clears your other settings too, since they live in the same file.

One caveat if you have upgraded from an older build: some installs carry a config.json.bak-tz next to it, left by a version that is no longer in the code, and it holds the same secrets. Check with ls ~/.local/share/nokipod and delete anything that starts with config.json, or use the command below, which covers it.

To drop the listening history as well, remove the whole folder:

rm -r ~/.local/share/nokipod

Deleting the session key stops NokiPod using it, but does not revoke it at Last.fm's end. Revoke NokiPod there through your Last.fm account's own settings for applications you have granted access to.

Development

python -m unittest discover -s tests                       # core tests, no GUI needed
QT_QPA_PLATFORM=offscreen python3 nokipod.py --selftest    # GUI smoke test
python3 tests/harness_ui.py                                # behavioural UI harness

Releases are built by GitHub Actions (.github/workflows/build.yml) from a PyInstaller one-folder build. Linux assembles an AppDir with appimagetool; Windows wraps the frozen app and a source-built, pinned rsgain/FFmpeg native payload in an Inno Setup installer. The Linux job runs on Ubuntu 24.04 while building inside a digest-pinned Ubuntu 22.04 container for broad glibc compatibility. Pushing a strict v* tag that matches APP_VERSION in nokipod.py publishes both platform artifacts to a GitHub release only after their tests and security gates pass.

The release attestation records which workflow and commit produced the published bytes; it is provenance, not a guarantee of bit-for-bit reproducible builds. The packaged Python runtime is pinned to 3.13.15, and the rsgain and vcpkg source archives are pinned by commit and verified by SHA-256. Their transitive native source recipes carry hashes as well. The exact vcpkg tool asset is also SHA-256-pinned and Microsoft Authenticode-verified before its first execution. OpenSSL 3.0.22 is built from its exact source archive with a checked CPython DLL-name patch; its source, patch, configuration, binary hashes, and licence are recorded with the native payload. FFmpeg n9.0.1 is also checked at source level for the four published fixes associated with CVE-2026-8461 and CVE-2026-30999 rather than treated as safe by version number alone. The hosted Windows job's maintained windows-2022 runner image (pinned to match Visual Studio 2022) and Ubuntu packages selected from the base image's signed repositories can still change between otherwise identical workflow runs.

Building the Windows native ReplayGain payload directly requires PowerShell 7 or later (pwsh) and Visual Studio 2022 with the x64 C++ tools:

pwsh -File packaging/build-rsgain-windows.ps1

To build one locally:

pip install -r requirements.txt pyinstaller
packaging/build-appimage.sh    # -> dist-appimage/NokiPod-<version>-x86_64.AppImage

appimagetool is downloaded automatically on first run. Note that a local build bundles whatever Qt libraries your desktop happens to have, so it can be considerably larger than the release build. Build on the oldest glibc you need to support for the widest compatibility.

Third-party

  • Comfortaa, the interface typeface, bundled in assets/fonts so NokiPod looks the same on a machine that does not have it installed. Copyright 2011 The Comfortaa Project Authors, with Reserved Font Name "Comfortaa", licensed under the SIL Open Font License 1.1. The full licence travels with the font in assets/fonts/OFL.txt. Three static weights are bundled (Regular, SemiBold, Bold), the weights the interface actually asks for. If loading them ever fails, NokiPod falls back through Quicksand, Varela Round, Nunito and Rubik, and says so on the console. Settings then shows which face is really in use.
  • LRCLIB, the lyrics database behind the Add lyrics buttons. Free and open, no account and no API key.
  • rsgain, the ReplayGain scanner. The Windows payload is built from the commit recorded in packaging/build-rsgain-windows.ps1, with FFmpeg 9.0.1 and without the nonfree FDK AAC fallback. Native licence texts, source provenance, and the rebuild/source offer travel inside the installer's rsgain folder.
  • MusicBrainz and the Cover Art Archive, behind Fix for Me.
  • The library, tag reads and writes, and album-art embedding use mutagen. Playback uses Qt Multimedia, and degrades gracefully if no audio backend is present.
  • TO BE CLEAR: This software was made almost entirely with Claude Design, Claude Code, and a little bit of ChatGPT Codex. I still use Claude Design for my creative direction, and this project has still taken months to get to a point I'm ready to release it. I hope you'll like it.

Licence

NokiPod is free software under the GNU General Public License v3.0 only (GPL-3.0-only). See LICENSE. You may use, study, share and modify it. If you distribute a modified version, it has to stay under the GPL too.

Not "or later", which is what this said before. NokiPod links PyQt6, and PyQt6's GPL option is GPL-3.0-only, so the combined work can only be conveyed under GPL-3.0 and nobody downstream gets to relicense it under a later GPL. That applies to the AppImage, which bundles PyQt6, and to a source checkout the moment you pip install -r requirements.txt. mutagen is GPL-2.0-or-later, which upgrades into GPL-3.0 without a problem.

The third-party pieces above keep their own licences, including Comfortaa under the SIL Open Font License 1.1.

NokiPod is not affiliated with Apple, Rockbox, Last.fm, MusicBrainz or LRCLIB. "iPod" is a trademark of Apple Inc.

About

Desktop companion for Rockbox music players. Rhythm-game-style library browsing, automatic Last.fm scrobbling, ReplayGain via rsgain, and MusicBrainz tag fixing.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages