multi value tag support

This commit is contained in:
quackerd 2023-06-06 18:26:52 -04:00
parent 0b8827c1b8
commit c2fdf3a779
3 changed files with 59 additions and 47 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 KiB

View File

@ -15,25 +15,25 @@ class MObject:
def get_bytes(self) -> bytes: def get_bytes(self) -> bytes:
return self._file_io.getbuffer() return self._file_io.getbuffer()
def get_title(self) -> str: def get_title(self) -> list[str]:
raise Exception("unimplemented") raise Exception("unimplemented")
def get_album(self) -> str: def get_album(self) -> list[str]:
raise Exception("unimplemented") raise Exception("unimplemented")
def get_artist(self) -> str: def get_artist(self) -> list[str]:
raise Exception("unimplemented") raise Exception("unimplemented")
def get_cover(self) -> bytes: def get_cover(self) -> bytes:
raise Exception("unimplemented") raise Exception("unimplemented")
def set_artist(self, val : str) -> None: def set_artist(self, val : list[str]) -> None:
raise Exception("unimplemented") raise Exception("unimplemented")
def set_album(self, val : str) -> None: def set_album(self, val : list[str]) -> None:
raise Exception("unimplemented") raise Exception("unimplemented")
def set_title(self, val : str) -> None: def set_title(self, val : list[str]) -> None:
raise Exception("unimplemented") raise Exception("unimplemented")
def set_cover(self, val : bytes, png : bool = False) -> None: def set_cover(self, val : bytes, png : bool = False) -> None:
@ -48,30 +48,30 @@ class MMP3Object(MObject):
self._id3.load(self._file_io, translate = True) self._id3.load(self._file_io, translate = True)
return return
def get_title(self) -> str: def get_title(self) -> list[str]:
return self._id3.get("TIT2", default = TIT2(text = "")) return self._id3.get("TIT2")
def set_title(self, val : str) -> None: def set_title(self, val : list[str]) -> None:
self._id3.delall("TIT2") self._id3.delall("TIT2")
self._id3.add(TIT2(text = val)) self._id3.add(TIT2(text = val))
self._file_io.seek(0) self._file_io.seek(0)
self._id3.save(self._file_io) self._id3.save(self._file_io)
def get_album(self) -> str: def get_album(self) -> list[str]:
return self._id3.get("TALB", default = TALB(text = "")) return self._id3.get("TALB")
def set_album(self, val : str) -> None: def set_album(self, val : list[str]) -> None:
self._id3.delall("TALB") self._id3.delall("TALB")
self._id3.add(TALB(text = val)) self._id3.add(TALB(text = val))
self._file_io.seek(0) self._file_io.seek(0)
self._id3.save(self._file_io) self._id3.save(self._file_io)
def get_artist(self) -> str: def get_artist(self) -> list[str]:
return self._id3.get("TPE1", default = TPE1(text = "")) return self._id3.get("TPE1")
def set_artist(self, val : str): def set_artist(self, val : list[str]):
self._id3.delall("TPE1") self._id3.delall("TPE1")
self._id3.add(TPE1(text = val)) self._id3.add(TPE1(text = val))
@ -100,28 +100,28 @@ class MFLACObject(MObject):
self._flac = FLAC(self._file_io) self._flac = FLAC(self._file_io)
return return
def get_title(self) -> str: def get_title(self) -> list[str]:
return self._flac.get("TITLE", default = None) return self._flac.get("TITLE")
def set_title(self, val : str) -> None: def set_title(self, val : list[str]) -> None:
self._flac["TITLE"] = val self._flac["TITLE"] = val[0]
self._file_io.seek(0) self._file_io.seek(0)
self._flac.save(self._file_io) self._flac.save(self._file_io)
def get_album(self) -> str: def get_album(self) -> list[str]:
return self._flac.get("ALBUM", default = None) return self._flac.get("ALBUM")
def set_album(self, val : str) -> None: def set_album(self, val : list[str]) -> None:
self._flac["ALBUM"] = val self._flac["ALBUM"] = val[0]
self._file_io.seek(0) self._file_io.seek(0)
self._flac.save(self._file_io) self._flac.save(self._file_io)
def get_artist(self) -> str: def get_artist(self) -> list[str]:
return self._flac.get("ARTIST", default = None) return self._flac.get("ARTIST")
def set_artist(self, val : str): def set_artist(self, val : list[str]):
self._flac["ARTIST"] = val self._flac["ARTIST"] = val
self._file_io.seek(0) self._file_io.seek(0)

View File

@ -1,7 +1,7 @@
import os import os
import getopt import getopt
import sys import sys
import shutil import pathlib
import mobject import mobject
@ -28,12 +28,12 @@ ALBUM_MATCH_SCORE = 100
TITLE_MATCH_SCORE = 1000 TITLE_MATCH_SCORE = 1000
# to get a > 0 score, each field either must match or the cover tuple is wildcare (None) # to get a > 0 score, each field either must match or the cover tuple is wildcare (None)
def calc_cover_score(artist: str, album: str, title: str, tup : tuple): def calc_cover_score(artist: list[str], album: list[str], title: list[str], tup : tuple) -> int:
score = 0 score = 0
if (tup[0] == artist): if (tup[0] == artist):
score += ARTIST_MATCH_SCORE score += ARTIST_MATCH_SCORE
elif (tup[0] == ""): elif (tup[0] == [""]):
score += WILDCARD_MATCH_SCORE score += WILDCARD_MATCH_SCORE
else: else:
# mismatched artist, discard # mismatched artist, discard
@ -41,7 +41,7 @@ def calc_cover_score(artist: str, album: str, title: str, tup : tuple):
if (tup[1] == album): if (tup[1] == album):
score += ALBUM_MATCH_SCORE score += ALBUM_MATCH_SCORE
elif (tup[1] == ""): elif (tup[1] == [""]):
score += WILDCARD_MATCH_SCORE score += WILDCARD_MATCH_SCORE
else: else:
# mismatched album, discard # mismatched album, discard
@ -49,7 +49,7 @@ def calc_cover_score(artist: str, album: str, title: str, tup : tuple):
if (tup[2] == title): if (tup[2] == title):
score += TITLE_MATCH_SCORE score += TITLE_MATCH_SCORE
elif (tup[2] == ""): elif (tup[2] == [""]):
score += WILDCARD_MATCH_SCORE score += WILDCARD_MATCH_SCORE
else: else:
# mismatched title, discard # mismatched title, discard
@ -59,7 +59,7 @@ def calc_cover_score(artist: str, album: str, title: str, tup : tuple):
# returns the idx into cover_arts array. # returns the idx into cover_arts array.
# < 0 means no match # < 0 means no match
def find_best_cover(artist: str, album: str, title: str): def find_best_cover(artist: list[str], album: list[str], title: list[str]) -> int:
best_idx = -1 best_idx = -1
best_score = 0 best_score = 0
for i in range(0, len(cover_arts)): for i in range(0, len(cover_arts)):
@ -70,17 +70,24 @@ def find_best_cover(artist: str, album: str, title: str):
return best_idx return best_idx
def plus_str_to_list(s : str) -> list[str]:
ss : list[str] = s.split("+")
ret = []
for sss in ss:
ret.append(sss)
return ret
def parse_triple(f: str): def parse_triple(f: str) -> tuple[list[str], list[str], list[str]]:
triple = os.path.splitext(os.path.basename(f))[0].split("_") triple = os.path.splitext(os.path.basename(f))[0].split("_")
album = "" album = ""
title = "" title = ""
artist = triple[0] artist = plus_str_to_list(triple[0])
if len(triple) >= 2: if len(triple) >= 2:
album = triple[1] album = plus_str_to_list(triple[1])
if len(triple) >= 3: if len(triple) >= 3:
title = triple[2] title = plus_str_to_list(triple[2])
return artist, album, title return (artist, album, title)
def load_cover_arts(): def load_cover_arts():
global cover_arts global cover_arts
@ -95,9 +102,14 @@ def load_cover_arts():
artist, album, title = parse_triple(f) artist, album, title = parse_triple(f)
f = os.path.join(cover_dir, f) f = os.path.join(cover_dir, f)
print("Processing cover art - " + f) print("Processing cover art - " + f)
fp = pathlib.Path(f)
if (fp.suffix.lower() == ".png"):
type = "PNG"
else:
type = "JPEG"
with open(f,'rb') as img: with open(f,'rb') as img:
cover_arts.append((artist, album, title, img.read(), os.path.basename(f), f)) cover_arts.append((artist, album, title, img.read(), type, f))
print(" Loading cover art - " + f + " Artist: " + artist + " Album: " + album + " Title: " + title) print(" Loading cover art - " + f + " Artist: " + str(artist) + " Album: " + str(album) + " Title: " + str(title) + " Type: " + type)
except Exception as e: except Exception as e:
print(" Skipping due to Exception - " + str(e)) print(" Skipping due to Exception - " + str(e))
print("") print("")
@ -122,11 +134,11 @@ def process_file(f: str, odir: str):
total_proc += 1 total_proc += 1
artist, album, title = parse_triple(f) artist, album, title = parse_triple(f)
if album == "": if len(album) == 0:
album = UNKNOWN_ALBUM_NAME album = [UNKNOWN_ALBUM_NAME]
if artist == "": if len(artist) == 0:
artist = UNKNOWN_ARTIST_NAME artist = [UNKNOWN_ARTIST_NAME]
if title == "": if len(title) == 0:
raise Exception("No title") raise Exception("No title")
mobj = mobject.create_mobject(f) mobj = mobject.create_mobject(f)
@ -142,7 +154,7 @@ def process_file(f: str, odir: str):
if (mobj.get_cover() == None or overwrite_cover): if (mobj.get_cover() == None or overwrite_cover):
cover_idx = find_best_cover(artist, album, title) cover_idx = find_best_cover(artist, album, title)
if (cover_idx >= 0): if (cover_idx >= 0):
mobj.set_cover(cover_arts[cover_idx][3]) mobj.set_cover(cover_arts[cover_idx][3], cover_arts[cover_idx][4] == "PNG")
print(f" Cover: <{'None' if mobj.get_cover() == None else 'Exists'}> -> \"{cover_arts[cover_idx][5]}\"") print(f" Cover: <{'None' if mobj.get_cover() == None else 'Exists'}> -> \"{cover_arts[cover_idx][5]}\"")
total_cover_written += 1 total_cover_written += 1
else: else:
@ -152,7 +164,7 @@ def process_file(f: str, odir: str):
print(" Cover: <Exists>") print(" Cover: <Exists>")
total_cover_exists += 1 total_cover_exists += 1
target_dir = os.path.join(odir, artist, album) target_dir = os.path.join(odir, "+".join(artist), "+".join(album))
os.makedirs(target_dir, exist_ok = True) os.makedirs(target_dir, exist_ok = True)
target_f = os.path.join(target_dir, os.path.basename(f)) target_f = os.path.join(target_dir, os.path.basename(f))