{"id":29854943,"url":"https://github.com/crossr/rockbox_db_py","last_synced_at":"2026-02-28T00:56:00.899Z","repository":{"id":306483815,"uuid":"1008895532","full_name":"CrossR/rockbox_db_py","owner":"CrossR","description":null,"archived":false,"fork":false,"pushed_at":"2025-07-25T22:34:42.000Z","size":201,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-26T01:26:52.256Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CrossR.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-26T08:59:42.000Z","updated_at":"2025-07-25T20:11:25.000Z","dependencies_parsed_at":"2025-07-26T01:27:25.286Z","dependency_job_id":"1cf3ec46-a85b-4f78-91aa-6e6760e2cf29","html_url":"https://github.com/CrossR/rockbox_db_py","commit_stats":null,"previous_names":["crossr/rockbox_db_py"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/CrossR/rockbox_db_py","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CrossR%2Frockbox_db_py","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CrossR%2Frockbox_db_py/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CrossR%2Frockbox_db_py/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CrossR%2Frockbox_db_py/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CrossR","download_url":"https://codeload.github.com/CrossR/rockbox_db_py/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CrossR%2Frockbox_db_py/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267771910,"owners_count":24142081,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-29T02:00:12.549Z","response_time":2574,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-07-29T22:20:17.660Z","updated_at":"2026-02-28T00:56:00.892Z","avatar_url":"https://github.com/CrossR.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RockBox DB Py\n\nAn implementation of the Rockbox database, in Python.\n\n\u003cp align=\"center\"\u003e\n\u003cimg width=\"601\" height=\"699\" alt=\"image\" src=\"https://github.com/user-attachments/assets/d903b3c5-aba8-4669-bf14-839daa23084a\" /\u003e\n\u003c/p\u003e\n\n# Features\n\nTwo main sets of features:\n\n#### RockBox DB Parsing Library\n\nA python re-implementation of the Rockbox database.\nThis comes with a bunch of advantages versus doing it on device:\n\n- Multi-threaded indexing of your music collection\n  - Should be much faster, especially on large collections, usually less than a\n    second per 1000 files.\n- Uses the `mediafile` library to read metadata from files, so it supports\n  a wide range of audio formats.\n  - Battle tested and used in `beets` and more.\n- Once your media files are indexed, you can make in-memory edits to their tags.\n  - I.e. you can change the title, artist, album, etc. of a file, just for\n    the Rockbox database, without messing with the actual file.\n  - This is REALLY useful for things like the genre, where you can \"canonicalize\"\n    a list of genres to a single genre, significantly reducing the entries\n    in the database.\n\n#### Sync GUI\n\nBuilding on the RockBox DB Parsing Library, there is a simple GUI app for all\nyour basic syncing needs.\n\nThat is:\n\n - Build a basic, on device DB for quick look-ups of your music collection.\n - Then, using that, sync over changes (new files, updated files, deletions).\n - Once the changes have been visually checked in the GUI, apply all the\n   updates to your device.\n - Finally, with the click of a button, build a new, updated rockbox DB\n   in a few seconds, copying over some of the useful playback stats etc,\n   and backing up the old DB.\n\nIdeally, you should be able to run the GUI, get your device in sync,\nand have an updated DB to start playback instantly, only limited by\nthe time it takes to sync your music, and then a few more seconds to\nbuild your DB, rather than the minutes it can take on-device.\n\n# Current Caveats\n\nThere is a few caveats to be aware of, as this is a work in progress:\n\n- Rockbox version support is 4.0 ONLY. I've not tested this with any other\n  version, and if you go far enough back and the DB changes (either in spec, or\n  in version number), it WILL NOT work.\n\n- We assume a little endian system, which works fine for iPods. If your device\n  isn't an iPod, it may not work. It could be as simple as changing\n  `ENDIANNESS_CHAR = \"\u003c\"` to `ENDIANNESS_CHAR = \"\u003e\"` in the\n  `utils/struct_helpers.py`, but it is not something I've tested.\n\n- This is a brand new database every time. There is basic copying of the\n  existing database metadata (play counts, ratings, etc.) to the new,\n  but it is not extensively tested, as it isn't something I've kept\n  very much track of in the past.\n\n  - This is mostly a design choice for now...I use last.fm etc to track those\n    things, so didn't see the point in trying to keep them around, but have\n    added some very basic support to `build_db.py` to copy them over.\n\n- The main `build_db.py` script currently assumes a 1:1 mapping between\n  the music files on your device and the files in your music collection.\n\n  - I.e. it assumes that if you have a file at `F:/Music/Artist/Album/Song.mp3`,\n    then that is the same file as `E:/Music/Artist/Album/Song.mp3` on your\n    device. You can have different parent folders (i.e. `F:/Media/Music` vs\n    `E:/Music/`), but once your music collection starts, the files should be in\n    the same order.\n  - If you have a more complex setup, you can potentially make changes to the\n    `build_db.py` script to handle that, but you will need to have some\n    programmatic way to keep the two in sync.\n\n- There isn't really any extensive testing done yet. I've used it, it works for\n  me and my music, but other setups may not work. If you find something that\n  doesn't work, please report it as an issue on GitHub, and I will try to fix it.\n\n- I'm not 100% sure my comment parsing code is working properly. The DB works on\n  my iPod Classic 5, but the comments values in some places (even in regular\n  Rockbox) are non-sensical. I don't care about comments, so I haven't looked\n  into it in a lot of detail, and the DB works fine, so it isn't a priority.\n\n# Using the GUI\n\nFirst, download a release from https://github.com/CrossR/rockbox_db_py/releases.\n\nThen, extract and run the executable inside.\n\nYou'll get a GUI, with hopefully intuitive options at the top, to select your 3\nfolders: Input Music Folder, Output Music Folder, where your rockbox DB files\nlive (i.e. your `.rockbox` folder on your device).\n\n\u003e [!WARNING]\n\u003e I'd REALLY suggest running this the first time on a test dataset. Don't\n\u003e point it at your full music folder. Point it at one artist, and set your\n\u003e output and rockbox folders to some fake folder in your Downloads or something\n\u003e with like 1 album from the artist in it.\n\u003e\n\u003e Verify it all works, nothing breaks, then move on to a real test.\n\u003e\n\u003e This shouldn't break your source files, since I'm using standard tools\n\u003e that well loved tools like `beets` use to manage music files...but\n\u003e best to be safe!\n\nFrom there, you basically follow the buttons along the bottom.\n\nIf this is your first time using the GUI, you'll first want to click \"Verify\nDevice Files\". This will make a little on device sync database, that the rest\nof the syncing will use. This should take a few seconds.\n\nOnce that is done, you can move to \"Get Changes\". This will essentially\ncompare the sync database to your input folder and identify any changes.\nThese changes will then be displayed in the relevant tabs in the GUI:\nTo Add, To Update, To Delete, along with a count of the changes.\n\nVerify the changes! If it says its going to delete everything or add\na bunch of rubbish, double check everything, or report an issue! Ideally,\nit should just show your new music and maybe some changes you've made.\nIf it doesn't look right, don't carry on!\n\nIf it does look right....you can now click \"Apply Changes\". It will\nalert you that its going to do the changes you've just seen,\nso confirm, and wait. This bit is still just as slow as manually dragging\nstuff over...since we are limited by USB / the device itself.\n\nWait, get a cup of tea (the progress timer is vaguely accurate at least),\nand come back when its done.\n\nFinally, your device is now in sync with your music folder! You can now\npress the \"Build Rockbox DB\" button. That will do as it says, and scan\nall your music and build a new DB, installing it in the location\nyou said at the top. It'll copy over basic stats (check the Caveats section\nabove for more info), and make a backup next to the original files.\nThat should take a few seconds, but should be much faster than your device\ndoing it!\n\nOnce that is complete, it will let you know in the log...and you are done!\n\n# Development Installation\n\nRight now....this is a work in progress / proof of concept, so this is really for\ndevelopers. I do plan to produce a full, pre-made release with a GUI and all that\nbut it makes sense to verify the core functionality first.\n\nBefore starting, you'll need a Python environment on you machine, and `uv` installed.\nInstructions for both of those can be found pretty easily online.\n\nOnce you have that, you can setup the project like this:\n\n```bash\ngit clone https://github.com/CrossR/rockbox_db_py.git\ncd rockbox_db_py\n\n# Setup the virtual environment and install the dependencies\nuv sync\n\n# Install rockbox_db_py in editable mode. I.e. setup this project so that you\n# can use it. \"editable mode\" just means if you make any changes to the code,\n# they will be reflected straight away, without needing to reinstall, which\n# is useful for development.\nuv pip install -e .\n```\n\n# CLI Usage (DB Building Only)\n\nOnce you have the project setup, the steps are as follows:\n\n1. Backup your existing database, if you have one. Ideally back it up twice!\n\n- If you don't do this, and the scripts here mess it up, you will lose\n  your existing database. That will mean waiting around for Rockbox to\n  re-index your music collection, which can take a long time.\n\n2. From the root of the project, run the first debugging script over the\n   folder you just backed up your database to:\n\n   ```bash\n   uv run python tools/print_db.py \"D:\\Path\\To\\Rockbox\\db\\backup\"\n   ```\n\n   This won't edit your database, but should print out the first 30 entries.\n   If this fails or goes weird...report it as an issue on GitHub, and stop here\n   most likely. There is some feature of your current DB that we can't handle,\n   so making a new DB will probably also fail. If it did work, you can also\n   mess with the other flags (check `print_db.py --help` for details) to print\n   other bits of info.\n\n3. If that did work....we can parse your DB! So, let's try something else.\n\n   ```bash\n   uv run python tools/copy_db.py \"D:\\Path\\To\\Rockbox\\db\\backup\" \"D:\\Path\\To\\Rockbox\\db\\copy\"\n   ```\n\n   This will fully parse your existing DB to memory, then write it out using the\n   python-based Rockbox DB format. Again, if this fails, report it as an issue\n   and stop here. You should also be able to run `print_db.py` on the new copy\n   to verify that it looks correct. If this works, we can both read and write\n   your Rockbox database, which is a good sign that we can make a new one.\n\n4. Okay, the final step. My code can parse your existing DB, so let's try to\n   make a new one.\n\n   ```bash\n   uv run python tools/build_db.py \"D:\\Media\\Music\" \"/Music/\" \"D:\\Path\\To\\Rockbox\\db\\new_db\"\n   ```\n\n   This command takes 3 arguments:\n\n   - The path to your music collection, which will be indexed. This should be on\n     your computer, NOT on your Rockbox device. You can potentially give it your\n     Rockbox device path...but I've never tested that, so it may not work, and it\n     will be much, much, much slower than indexing your computer. Your HDD / SSD\n     is so much faster, so use that!\n   - The path to the music collection as it should appear in the Rockbox DB.\n     I.e. if when you plugin over USB, your music collection is at `F:/Music`,\n     then this should be `/Music/`. This is used to make the paths in the DB.\n     This NEEDS to start with a `/`, and should end with a `/` as well, and\n     shouldn't have any drive letters or whatever in it. Looking at the\n     output from `print_db.py` on your original DB should help you figure\n     out what this should be.\n   - The folder where to write the new database to. This should be a folder\n     that does not already exist, as it will be created, and we will delete\n     the contexts of that folder before writing the new database to it.\n   - You can also check the help text for `build_db.py` to see what other\n     options are available, but the above 3 are the most important ones.  Other\n     options include things like whether to copy the existing metadata from the\n     old database, whether to use a progress bar, and \"genre\" canonicalization,\n     which is useful if you have a lot of different genres and want to reduce the\n     number of entries in the database.\n\n   You should see a progress bar as your music files are read, and then a brief\n   print out of the first music file we parse. After that, the script will write\n   out the new database with a second progress bar (though this is usually very\n   quick). After that point, you can run `print_db.py` on the new database to\n   verify that it looks correct. If it does look correct, and things like the\n   paths to the files match what your old database had, you can copy the new\n   database to your Rockbox device, to try it on your device.  I find a reboot\n   of the device after copying is best, just to ensure everything is reloaded\n   correctly.\n\n   Don't worry about there not being small differences in the printed output\n   between the old and new database. Little things, such as the order of songs\n   will almost certainly be different, so the first 30 entries will not be\n   identical. The important thing is that the paths to the files are correct,\n   and that the metadata for each file is correct. If you find any issues with\n   the metadata, please report it as an issue on GitHub, and I will try to\n   fix it.\n\n\n# TODO / Other Ideas\n\n - We can actually insert metadata from other sources...so we could somewhat\n   easily insert last.fm play counts, ratings, etc. into the database, via\n   some API calls.\n\n - Experiment with further changes to the database, alongside changes to the\n   Rockbox database config file. Much older versions of similar code makes\n   reference to enabling multiple values for some fields (i.e. multiple\n   artists, multiple genres for a song, etc.), which would be\n   interesting to experiment with. This would require changes to the Rockbox\n   user database config file though, to help it filter out the new duplicate\n   entries (or at least I believe that is the the case). This is\n   something I haven't looked into yet, but it would be interesting to\n   experiment with.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrossr%2Frockbox_db_py","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcrossr%2Frockbox_db_py","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrossr%2Frockbox_db_py/lists"}