Ex-NDE (Nullsoft Database Engine); Extract-NDE. Extricate your data from your Winamp Music Library database.
This (binary) crate includes logic as well as a small program for reading your Winamp Music Library database & dumping the contents to other (hopefully more convenient) formats. It does not attempt a full re-implementation of the Nullsoft Database Engine (see here for thoughts on that); it just reads the main table of the Music Library database & dumps the contents.
Not only is this is my first Rust crate, but the implementation is incomplete (see
e.g.), and the code is generally littered with assorted TODO comments marking things I'd like to
do better, or more elegantly, or at all. That said, the point to this crate is to get my data
out of an archaic format & into one I can use more readily. I've accomplished that, so I don't
know how much time I want to spend polishing the implementation. PRs, suggestions & complaints
Despite its name, the Nullsoft Database Engine is not a full-featured RDMS. True to the coding ethos that characterized Winamp generally, it was a tightly-coded, purpose-built implementation that produced extremely compact representations on disk.
A "table" in NDE parlance is a collection of records. On disk, it is described by two files:
the "data" file (
.dat) in which the table's records are serialized in a very space efficient manner
the "index" file (
.idx) which describes how to traverse the data file in various orders
The index file is described below. See
fields for details on the data file.
The top-level structure of the index file is:
+------------+-------------+-------------+-------------+ | "NDEINDEX" | no. records | primary idx | aux idx... | +------------+-------------+-------------+-------------+
The first element is a signature marking the file's purpose in the form of the string "NDEINDEX" in ASCII/UTF-8 format. The second is the number of records in the table (and hence the number of elements in each index), expressed as a 32-bit little-endian unsigned integer.
Each index has the following format:
+--------+--------------------+ | idx ID | record location... | +--------+--------------------+
The index ID is a 32-bit little-endian unsigned integer. The only significance to the ID I
could find in the code is that the required primary index has an ID of 255 (or
There is no "end-of-record" marker; since each record location is a constant size (eight bytes),
one simply reads the expected number of bytes seqeuntially after reading the number of records.
There is also no indication of how many indicies the file contains; one simply reads chunks of
no. records * 8 bytes until EoF is reached.
Each records is two 32-bit integers:
+--------+------+ | offset | ???? | +--------+------+
The first element is a 32-bit little-endian unsigned int giving the offset into the datafile of a record. The question marks for the second element are because I never figured out what this was for.
Dump the contents of a Winamp Music Library to stdout
transform your Winamp music library into an in-memory datastructure and serialize it to any variety of formats via Serde.
Read all indicies out of an index file; rdr is assumed to be pointing at the signature (i.e. byte zero if we're reading a .idx file)