diff --git a/scores2json.py b/scores2json.py new file mode 100755 index 0000000..f6abeb3 --- /dev/null +++ b/scores2json.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python3 +# vim: fdm=marker noet ts=4 + +# Generate a JSON array of all the pipeband scores +#+ see bottom for script execution + +#{{{ Functions +import os + +def walk_through_files(path, file_extension='.ly'): + for (dirpath, dirnames, filenames) in os.walk(path): + if file_extension: + for filename in filenames: + if filename.endswith(file_extension): + yield os.path.join(dirpath, filename) + else: + yield os.path.join(dirpath, filename) + +def rreplace(s, old, new, occurrence): + li = s.rsplit(old, occurence) + return new.join(li) + + +def read_config(config_path): + ''' return a dict created from the configfile ''' + import re + config = {} + + textsearches = ['title', 'meter'] + with open(config_path, 'r') as fh: + for line in fh: + if line.startswith('\\version'): + continue + + if line.startswith('%'): + continue + + for t in textsearches: + if not t in config: + result = re.search(t +' = (?P[\'\"])(.*?)(?P=quote)', line) + if result: + config[t] = result.group(2) + + for keyword in ['\\\\tempo', '\\\\time', '\\\\partial']: + if not keyword in config: + result = re.search(keyword+'\s*(.*)', line) + + if result: + config[keyword.replace('\\','')] = result.group(1).strip() + return config + +def analyse_tune_ly(tune_file): + ''' return a dict created from the tune file''' + data = read_lilypond(tune_file) + + data['path'] = tune_file + + return data + +def read_lilypond(fname): + ''' return a dict from file''' + data = {} + + if not os.path.exists(fname): + return data + + return data + +def merge_data_and_config(data, config): + if 'title' in data and '\\title' in data['title'] and 'title' in config: + data['title'].replace('\\title',config['title']) + + newdata = { **config, **data } + + return newdata + +def config_from_lypath(lypath): + ''' return the configpath belonging to the lypath ''' + li = lypath.rsplit("/", 1)[0] + return os.path.join(li,"config.ily") + +def read_path(music_paths): + tunes = {} + + # Music Directory to work on + if isinstance(music_paths, str): + music_paths = [music_paths] + + for path in music_paths: + for f in walk_through_files(path, '.ly'): + if os.path.basename(os.path.dirname(f)) == 'template': + continue; + + data = analyse_tune_ly(f) + config_path = config_from_lypath(f) + + if os.path.exists(config_path): + config = read_config(config_path) + # merge them + data = merge_data_and_config(data, config) + + data['instrument'] = os.path.splitext(os.path.basename(f))[0] + data['files'] = {} + data['files']['lilypond'] = f.replace(path,'',1) + for ext in ['pdf', 'midi', 'preview.pdf', 'preview.png']: + sfile = os.path.splitext(f)[0] + '.' + ext + + if os.path.isfile(sfile): + data['files'][ext] = sfile.replace(path,'',1) + + if 'title' in data: + tune_key = data['title'] + else: + tune_key = data['path'] + + if not tune_key in tunes: + tunes[tune_key] = [data] + else: + tunes[tune_key].append(data) + + return tunes +#}}} End of functions + +# ================================================================ +# Alright, lets see if it works... +# ================================================================ +if __name__ == "__main__": + import argparse + + import json + + parser = argparse.ArgumentParser(description="Read a music directory into a JSON file") + parser.add_argument('music_paths', nargs="*", type=str, default=".") + + args = parser.parse_args() + + print(json.dumps(read_path( args.music_paths )))