Skip to content

Instantly share code, notes, and snippets.

@axwax
Created August 6, 2023 19:19
Show Gist options
  • Save axwax/a4a94e5d4a423b1c125124b9c68948ad to your computer and use it in GitHub Desktop.
Save axwax/a4a94e5d4a423b1c125124b9c68948ad to your computer and use it in GitHub Desktop.
NML to CSV (artist, title, filename)
# slightly modified version of
# https://github.com/iond2v/NML-parser
import os
import re
import html #for converting string codes
import sys
def process_folder(folder_name):
entries = os.listdir(folder_name)
text_files = []
nml_files = []
text_files_wo_extension = []
nml_files_wo_extension = []
for entry in entries:
if entry.endswith('.txt'):
text_files.append(entry)
text_files_wo_extension.append(entry[0:-4])
elif entry.endswith('.nml'):
nml_files.append(entry)
nml_files_wo_extension.append(entry[0:-4])
for file in nml_files_wo_extension:
if file not in text_files_wo_extension:
create_txt(file)
else:
print(file + " already has txt playlist file.")
def create_txt(file):
print("Creating text playlist file for " + file +".")
with open(file + '.nml', 'r', encoding='utf-8') as f:
lines = f.readlines()
items = []
playlist = []
ordered_items = []
#read entries
for line in lines:
title_result = re.match('.*<ENTRY.*TITLE="(.*?)".*', line)
artist_result = re.match('.*<ENTRY.*ARTIST="(.*?)".*', line)
file_result = re.match('.*<LOCATION.*FILE="(.*?)".*', line)
#at least one is not None - matching happened - we are on a line of interest..
if(title_result is not None or artist_result is not None or file_result is not None):
if(title_result is None):
title = "EMPTY TITLE"
print("EMPTY TITLE")
else:
title = title_result.group(1)
if(artist_result is None):
artist = "EMPTY ARTIST"
print("EMPTY ARTIST")
else:
artist = artist_result.group(1)
filename = file_result.group(1)
items.append((artist, title, filename))
#print(items)
#read playlist
for line in lines:
playlist_result = re.match('.*<PRIMARYKEY TYPE="TRACK" KEY="(.*?)".*', line)
if(playlist_result is not None):
key = playlist_result.group(1)
delimiter_location = key.rfind(":")
filename = key[delimiter_location + 1:]
playlist.append(filename)
#match playlist to items to order them
for playlist_filename in playlist:
result = [item for item in items if item[2] == playlist_filename].pop()
ordered_items.append(result)
#fix the html strings
result_items = []
for item in ordered_items:
result_items.append((html.unescape(item[0]), html.unescape(item[1]), html.unescape(item[2])))
#write the results to a CSV file
result_file = open(file + ".csv", 'w', encoding='utf-8')
for item in tuple(result_items):
artist_name_final = item[0]
original_track_name = item[1]
filename = item[2]
track_no_bpm_result = re.match('^(.*?)(( (- )?)[\(\[]?(\d\d\d)?[bBpPmM]*?[\)\]]?)*$', original_track_name)
track_name_final = track_no_bpm_result.group(1)
# this is the CSV row - each field has double-quotes around it
result_file.write('"' + artist_name_final + '","' + track_name_final + '","' + filename + '"\n')
result_file.close()
if __name__ == "__main__":
folder_name = "./"
if len(sys.argv) == 2:
folder_name = sys.argv[1]
process_folder(folder_name)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment