Package org.deepsymmetry.cratedigger.pdb
Class RekordboxPdb
- java.lang.Object
-
- io.kaitai.struct.KaitaiStruct
-
- org.deepsymmetry.cratedigger.pdb.RekordboxPdb
-
public class RekordboxPdb extends io.kaitai.struct.KaitaiStruct
This is a relational database format designed to be efficiently used by very low power devices (there were deployments on 16 bit devices with 32K of RAM). Today you are most likely to encounter it within the Pioneer Professional DJ ecosystem, because it is the format that their rekordbox software uses to write USB and SD media which can be mounted in DJ controllers and used to play and mix music. It has been reverse-engineered to facilitate sophisticated integrations with light and laser shows, videos, and other musical instruments, by supporting deep knowledge of what is playing and what is coming next through monitoring the network communications of the players. The file is divided into fixed-size blocks. The first block has a header that establishes the block size, and lists the tables available in the database, identifying their types and the index of the first of the series of linked pages that make up that table. Each table is made up of a series of rows which may be spread across any number of pages. The pages start with a header describing the page and linking to the next page. The rest of the page is used as a heap: rows are scattered around it, and located using an index structure that builds backwards from the end of the page. Each row of a given type has a fixed size structure which links to any variable-sized strings by their offsets within the page. As changes are made to the table, some records may become unused, and there may be gaps within the heap that are too small to be used by other data. There is a bit map in the row index that identifies which rows are actually present. Rows that are not present must be ignored: they do not contain valid (or even necessarily well-formed) data. The majority of the work in reverse-engineering this format was performed by @henrybetts and @flesniak, for which I am hugely grateful. @GreyCat helped me learn the intricacies (and best practices) of Kaitai far faster than I would have managed on my own.- See Also:
- Source
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
RekordboxPdb.AlbumRow
A row that holds an album name and ID.static class
RekordboxPdb.ArtistRow
A row that holds an artist name and ID.static class
RekordboxPdb.ArtworkRow
A row that holds the path to an album art image file and the associated artwork ID.static class
RekordboxPdb.ColorRow
A row that holds a color name and the associated ID.static class
RekordboxPdb.DeviceSqlLongAscii
An ASCII-encoded string preceded by a two-byte length field in a four-byte header.static class
RekordboxPdb.DeviceSqlLongUtf16le
A UTF-16LE-encoded string preceded by a two-byte length field in a four-byte header.static class
RekordboxPdb.DeviceSqlShortAscii
An ASCII-encoded string up to 127 bytes long.static class
RekordboxPdb.DeviceSqlString
A variable length string which can be stored in a variety of different encodings.static class
RekordboxPdb.GenreRow
A row that holds a genre name and the associated ID.static class
RekordboxPdb.HistoryEntryRow
A row that associates a track with a position in a history playlist.static class
RekordboxPdb.HistoryPlaylistRow
A row that holds a history playlist ID and name, linking to the track IDs captured during a performance on the player.static class
RekordboxPdb.KeyRow
A row that holds a musical key and the associated ID.static class
RekordboxPdb.LabelRow
A row that holds a label name and the associated ID.static class
RekordboxPdb.Page
A table page, consisting of a short header describing the content of the page and linking to the next page, followed by a heap in which row data is found.static class
RekordboxPdb.PageRef
An index which points to a table page (its offset can be found by multiplying the index by the `page_len` value in the file header).static class
RekordboxPdb.PageType
static class
RekordboxPdb.PlaylistEntryRow
A row that associates a track with a position in a playlist.static class
RekordboxPdb.PlaylistTreeRow
A row that holds a playlist name, ID, indication of whether it is an ordinary playlist or a folder of other playlists, a link to its parent folder, and its sort order.static class
RekordboxPdb.RowGroup
A group of row indices, which are built backwards from the end of the page.static class
RekordboxPdb.RowRef
An offset which points to a row in the table, whose actual presence is controlled by one of the bits in `row_present_flags`.static class
RekordboxPdb.Table
Each table is a linked list of pages containing rows of a single type.static class
RekordboxPdb.TrackRow
A row that describes a track that can be played, with many details about the music, and links to other tables like artists, albums, keys, etc.
-
Constructor Summary
Constructors Constructor Description RekordboxPdb(io.kaitai.struct.KaitaiStream _io)
RekordboxPdb(io.kaitai.struct.KaitaiStream _io, io.kaitai.struct.KaitaiStruct _parent)
RekordboxPdb(io.kaitai.struct.KaitaiStream _io, io.kaitai.struct.KaitaiStruct _parent, RekordboxPdb _root)
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description io.kaitai.struct.KaitaiStruct
_parent()
RekordboxPdb
_root()
long
_unnamed0()
Unknown purpose, perhaps an unoriginal signature, seems to always have the value 0.long
_unnamed4()
static RekordboxPdb
fromFile(String fileName)
byte[]
gap()
Only exposed until https://github.com/kaitai-io/kaitai_struct/issues/825 can be fixed.long
lenPage()
The database page size, in bytes.long
nextUnusedPage()
long
numTables()
Determines the number of table entries that are present.long
sequence()
ArrayList<RekordboxPdb.Table>
tables()
Describes and links to the tables present in the database.
-
-
-
Constructor Detail
-
RekordboxPdb
public RekordboxPdb(io.kaitai.struct.KaitaiStream _io)
-
RekordboxPdb
public RekordboxPdb(io.kaitai.struct.KaitaiStream _io, io.kaitai.struct.KaitaiStruct _parent)
-
RekordboxPdb
public RekordboxPdb(io.kaitai.struct.KaitaiStream _io, io.kaitai.struct.KaitaiStruct _parent, RekordboxPdb _root)
-
-
Method Detail
-
fromFile
public static RekordboxPdb fromFile(String fileName) throws IOException
- Throws:
IOException
-
_unnamed0
public long _unnamed0()
Unknown purpose, perhaps an unoriginal signature, seems to always have the value 0.
-
lenPage
public long lenPage()
The database page size, in bytes. Pages are referred to by index, so this size is needed to calculate their offset, and table pages have a row index structure which is built from the end of the page backwards, so finding that also requires this value.
-
numTables
public long numTables()
Determines the number of table entries that are present. Each table is a linked list of pages containing rows of a particular type.
-
nextUnusedPage
public long nextUnusedPage()
-
_unnamed4
public long _unnamed4()
-
sequence
public long sequence()
-
gap
public byte[] gap()
Only exposed until https://github.com/kaitai-io/kaitai_struct/issues/825 can be fixed.
-
tables
public ArrayList<RekordboxPdb.Table> tables()
Describes and links to the tables present in the database.
-
_root
public RekordboxPdb _root()
-
_parent
public io.kaitai.struct.KaitaiStruct _parent()
- Overrides:
_parent
in classio.kaitai.struct.KaitaiStruct
-
-