Created
May 8, 2021 16:30
-
-
Save blairdrummond/f022f7215fb92a20289c9752746c0888 to your computer and use it in GitHub Desktop.
Print mpd.db database file into jsonlines (for jq, or sqlite-utils --nl)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/python3 | |
# Convert an mpd.db file into jsonlines. | |
# Example usage: | |
# | |
# > parse-mpd.py /nfs/music | sqlite-utils insert --alter --nl music mpd.sqlite3 music - | |
# | |
# Based on: https://github.com/Delapouite/mpdump | |
# | |
# NOTE: If your Artist, Album, or Track names start/end with " ", | |
# then expect the script to fail. (This is fixable, but probably better to just | |
# clean up the file names) | |
import gzip | |
import json | |
from os.path import join, exists | |
import argparse | |
parser = argparse.ArgumentParser(description='Jsonify an mpd database.') | |
parser.add_argument('music_folder', type=str, help='Root Directory of music library') | |
parser.add_argument('database', type=str, help='MPD Database') | |
args = parser.parse_args() | |
# The database is just a gzipped text file with a specific format | |
with gzip.open(args.database, "rb") as f: | |
# bytes -> str | |
lines = ( | |
x.decode('utf-8').strip() | |
for x in f.readlines() | |
) | |
def split(line): | |
""" Get key-value pair from line """ | |
blocks = line.strip().split(': ') | |
assert len(blocks) > 1 | |
return blocks[0], ': '.join(blocks[1:]) | |
def consume(stream, acc={}): | |
""" Read until song_end tag """ | |
head = next(stream) | |
if head == 'song_end': | |
return acc | |
else: | |
k, v = split(head) | |
acc[k] = v | |
return consume(stream, acc) | |
directory = [] | |
try: | |
while True: | |
line = next(lines) | |
if line.startswith('directory:'): | |
_, d = split(line) | |
directory.append(d) | |
elif directory and line.startswith('end: ' + join(*directory)): | |
directory.pop() | |
elif line.startswith('song_begin:'): | |
_, track = split(line) | |
song = consume(lines, acc={'File': join(args.music_folder, *(directory+[track]))}) | |
try: | |
assert exists(song['File']) | |
except: | |
print("~%s~" % song['File']) | |
raise FileNotFoundError() | |
print(json.dumps(song)) | |
except StopIteration: | |
pass |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment