from musicutil.utils.do_replaygain import do_replaygain from ..types import File from ..utils.scan_for_music import scan_for_music from ..utils.load_tag_information import load_tag_information from ..utils.substitutions import reduce_to_ascii_and_substitute from copy import deepcopy as deep_copy from os import rename as rename_file class ProcessCommandState: files: list[File] = [] class ProcessCommandArgs: src: str dry_run: bool replaygain: str def add_process_command(subparsers): process_parser = subparsers.add_parser('process') process_parser.add_argument( 'src', type=str, help='src base music directory') process_parser.add_argument( '--dry-run', action='store_true') process_parser.add_argument( '--replaygain', type=str, default="skip_existing", help="skip,skip_existing,force" ) def get_process_args(args) -> ProcessCommandArgs: command_args = ProcessCommandArgs() command_args.src = args.src command_args.dry_run = args.dry_run command_args.replaygain = args.replaygain return command_args class ProcessCommand(): def __init__(self, args: ProcessCommandArgs): self.args = args self.state = ProcessCommandState() def run(self): print("Renaming") self.scan_for_music() self.load_tag_information() self.rename_files() if not self.args.dry_run: if self.args.replaygain != "skip": self.add_replaygain_tags() def scan_for_music(self): print("Scanning For Music") self.state.files = scan_for_music(self.args.src) def load_tag_information(self): print("Loading Tag Information") for file in self.state.files: tags = load_tag_information(file) file.tags = tags def _rename_file(self, file: File) -> File: filename = file.filename artist = file.tags.artist.replace("\n", "") title = file.tags.title.replace("\n", "") proper_filename = reduce_to_ascii_and_substitute( f"{artist} - {title}") if filename != proper_filename: print(f"Renaming \"{filename}\"", "to " + f"\"{proper_filename}\"" + "\n") new_file = deep_copy(file) new_file.filename = proper_filename if not self.args.dry_run: rename_file( file.join_path_to(), new_file.join_path_to()) # so that other steps after read the new file and not # the orig pre-rename file when not dry run return new_file else: return file def rename_files(self): print("Renaming files") for file in self.state.files: index = self.state.files.index(file) self.state.files[index] = self._rename_file( file) def add_replaygain_tags(self): print("Adding ReplayGain Tags") for file in self.state.files: if self.args.replaygain == "skip_existing": if file.tags.has_replaygain: continue print( f"Adding ReplayGain Tags to \"{file.filename}.{file.extension}\"") do_replaygain(file)