From 0003d7932408de1bec5cee4c5762b04e16f56133 Mon Sep 17 00:00:00 2001 From: Colin Date: Fri, 17 May 2024 09:41:50 +0000 Subject: [PATCH] sane-tag-music: add a `print-missing` subcommand --- .../sane-scripts/src/sane-tag-music | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/pkgs/additional/sane-scripts/src/sane-tag-music b/pkgs/additional/sane-scripts/src/sane-tag-music index 4149623f..b0bb71bc 100755 --- a/pkgs/additional/sane-scripts/src/sane-tag-music +++ b/pkgs/additional/sane-scripts/src/sane-tag-music @@ -323,9 +323,15 @@ class AudioFile: except Exception as e: logger.warning(f"failed to open {path_}: {e}") + def __repr__(self) -> str: + return self.path_ + @staticmethod - def new(path_: str) -> 'AudioFile': - f = AudioFile(path_) + def new(f: 'str | AudioFile | None') -> 'AudioFile | None': + if f is None: + return None + if not isinstance(f, AudioFile): + f = AudioFile(f) if f.muta is not None: return f @@ -365,7 +371,7 @@ class Tagger: self.force = force self.manual_tags = manual_tags - def show(self, path_: str) -> None: + def show(self, path_: str | AudioFile) -> None: file_ = AudioFile.new(path_) if not file_: logger.debug(f"skipping unsupported file: {path_}") @@ -375,6 +381,14 @@ class Tagger: logger.info(f"tags for {path_}:") logger.info(f" {tags}") + def is_sufficiently_tagged(self, file_: str | AudioFile) -> bool: + file_ = AudioFile.new(file_) + if not file_: + return False + tags = file_.tags_on_disk() + # N.B.: track number isn't wholly necessary; just a nice-to-have. + return (tags.artist or tags.albumartist) and tags.album and tags.title + def tag_file(self, path_: str) -> None: file_ = AudioFile.new(path_) if not file_: @@ -475,6 +489,10 @@ def main(): show_parser.set_defaults(subcommand="show") show_parser.add_argument("path", nargs="+", help="relative path to a file or directory to show") + print_missing_parser = subparsers.add_parser("print-missing") + print_missing_parser.set_defaults(subcommand="print_missing") + print_missing_parser.add_argument("path", nargs="+", help="relative path to a file or directory to validate tags for") + fix_tags_parser = subparsers.add_parser("fix-tags") fix_tags_parser.set_defaults(subcommand="fix_tags") fix_tags_parser.add_argument('--force', action='store_true', help="give higher credence to path-based and manual tags than any existing tags") @@ -507,6 +525,11 @@ def main(): if args.subcommand == "show": for p in files: tagger.show(p) + elif args.subcommand == "print_missing": + for p in files: + f = AudioFile.new(p) + if not tagger.is_sufficiently_tagged(f): + tagger.show(f) elif args.subcommand == "fix_tags": for p in files: tagger.tag_file(p) @@ -514,6 +537,8 @@ def main(): for p in files: print(p) tagger.fix_path(p) + else: + assert False, f"unrecognized command {args.subcommand}"