def handleFile(self, f): parse_version = self.args.tag_version super(ClassicPlugin, self).handleFile(f, tag_version=parse_version) if not self.audio_file: return try: self.printHeader(f) printMsg("-" * 79) new_tag = False if (not self.audio_file.tag or self.handleRemoves(self.audio_file.tag)): # No tag, but there might be edit options coming. self.audio_file.tag = id3.Tag() self.audio_file.tag.file_info = id3.FileInfo(f) self.audio_file.tag.version = parse_version new_tag = True save_tag = (self.handleEdits(self.audio_file.tag) or self.args.force_update or self.args.convert_version) self.printAudioInfo(self.audio_file.info) if not save_tag and new_tag: printError("No ID3 %s tag found!" % id3.versionToString(self.args.tag_version)) return self.printTag(self.audio_file.tag) if save_tag: # Use current tag version unless a convert was supplied version = (self.args.convert_version or self.audio_file.tag.version) printWarning("Writing ID3 version %s" % id3.versionToString(version)) self.audio_file.tag.save(version=version, encoding=self.args.text_encoding, backup=self.args.backup) if self.args.rename_pattern: # Handle file renaming. from eyed3.id3.tag import TagTemplate template = TagTemplate(self.args.rename_pattern) name = template.substitute(self.audio_file.tag, zeropad=True) orig = self.audio_file.path self.audio_file.rename(name) printWarning("Renamed '%s' to '%s'" % (orig, self.audio_file.path)) printMsg("-" * 79) except exceptions.Exception as ex: log.error(traceback.format_exc()) if self.args.debug_pdb: import pdb pdb.set_trace() raise StopIteration()
def handleFile(self, f): parse_version = self.args.tag_version super(ClassicPlugin, self).handleFile(f, tag_version=parse_version) if not self.audio_file: return try: self.printHeader(f) printMsg("-" * 79) new_tag = False if (not self.audio_file.tag or self.handleRemoves(self.audio_file.tag)): # No tag, but there might be edit options coming. self.audio_file.tag = id3.Tag() self.audio_file.tag.file_info = id3.FileInfo(f) self.audio_file.tag.version = parse_version new_tag = True save_tag = (self.handleEdits(self.audio_file.tag) or self.args.force_update or self.args.convert_version) self.printAudioInfo(self.audio_file.info) if not save_tag and new_tag: printError("No ID3 %s tag found!" % id3.versionToString(self.args.tag_version)) return self.printTag(self.audio_file.tag) if save_tag: # Use current tag version unless a convert was supplied version = (self.args.convert_version or self.audio_file.tag.version) printWarning("Writing ID3 version %s" % id3.versionToString(version)) self.audio_file.tag.save(version=version, encoding=self.args.text_encoding, backup=self.args.backup) if self.args.rename_pattern: # Handle file renaming. from eyed3.id3.tag import TagTemplate template = TagTemplate(self.args.rename_pattern) name = template.substitute(self.audio_file.tag, zeropad=True) orig = self.audio_file.path self.audio_file.rename(name) printWarning("Renamed '%s' to '%s'" % (orig, self.audio_file.path)) printMsg("-" * 79) except exceptions.Exception as ex: printError("Error: %s" % ex) log.error(traceback.format_exc()) if self.args.debug_pdb: import pdb; pdb.set_trace() raise StopIteration()
def handleFile(self, f): parse_version = self.args.tag_version super(ClassicPlugin, self).handleFile(f, tag_version=parse_version) if not self.audio_file: return self.printHeader(f) printMsg("-" * 79) new_tag = False if (not self.audio_file.tag or self.handleRemoves(self.audio_file.tag)): self.audio_file.initTag(version=parse_version) new_tag = True save_tag = (self.handleEdits(self.audio_file.tag) or self.args.force_update or self.args.convert_version) self.printAudioInfo(self.audio_file.info) if not save_tag and new_tag: printError("No ID3 %s tag found!" % id3.versionToString(self.args.tag_version)) return self.printTag(self.audio_file.tag) if save_tag: # Use current tag version unless a convert was supplied version = (self.args.convert_version or self.audio_file.tag.version) printWarning("Writing ID3 version %s" % id3.versionToString(version)) self.audio_file.tag.save( version=version, encoding=self.args.text_encoding, backup=self.args.backup, preserve_file_time=self.args.preserve_file_time) if self.args.rename_pattern: # Handle file renaming. from eyed3.id3.tag import TagTemplate template = TagTemplate(self.args.rename_pattern) name = template.substitute(self.audio_file.tag, zeropad=True) orig = self.audio_file.path try: self.audio_file.rename(name) printWarning("Renamed '%s' to '%s'" % (orig, self.audio_file.path)) except IOError as ex: printError(ex.message) printMsg("-" * 79)
def _getTemplateKeys(): from eyed3.id3.tag import TagTemplate keys = list(TagTemplate("")._makeMapping(None, False).keys()) keys.sort() return ", ".join(["$%s" % v for v in keys])
def handleDirectory(self, directory, _): if not self._file_cache: return directory = os.path.abspath(directory) print("\n" + Style.BRIGHT + Fore.GREY + "Scanning directory%s %s" % (Style.RESET_ALL, directory)) def _path(af): return af.path self._handled_one = True # Make sure all of the audio files has a tag. for f in self._file_cache: if f.tag is None: f.initTag() audio_files = sorted(list(self._file_cache), key=_path) self._file_cache = [] edited_files = set() # Check for corrections to LP, EP, COMP if (self.args.dir_type in (LP_TYPE, COMP_TYPE) and len(audio_files) < EP_MAX_HINT): # Do you want EP? if prompt("Only %d audio files, process directory as an EP" % len(audio_files), default=True): self.args.dir_type = EP_TYPE elif (self.args.dir_type in (EP_TYPE, DEMO_TYPE) and len(audio_files) > EP_MAX_HINT): # Do you want LP? if prompt("%d audio files is large for type %s, process " "directory as an LP" % (len(audio_files), self.args.dir_type), default=True): self.args.dir_type = LP_TYPE last = defaultdict(lambda: None) album_artist = None artists = set() album = None if self.args.dir_type != SINGLE_TYPE: album_artist, artists = self._resolveArtistInfo(audio_files) print(Fore.BLUE + u"Album artist: " + Style.RESET_ALL + (album_artist or u"")) print(Fore.BLUE + "Artist" + ("s" if len(artists) > 1 else "") + ": " + Style.RESET_ALL + u", ".join(artists)) album = self._getAlbum(audio_files) print(Fore.BLUE + "Album: " + Style.RESET_ALL + album) rel_date, orel_date, rec_date = self._getDates(audio_files) for what, d in [("Release", rel_date), ("Original", orel_date), ("Recording", rec_date)]: print(Fore.BLUE + ("%s date: " % what) + Style.RESET_ALL + str(d)) num_audio_files = len(audio_files) track_nums = set([f.tag.track_num[0] for f in audio_files]) fix_track_nums = set(range(1, num_audio_files + 1)) != track_nums new_track_nums = [] dir_type = self.args.dir_type for f in sorted(audio_files, key=_path): print(Style.BRIGHT + Fore.GREEN + u"Checking" + Fore.RESET + Fore.GREY + (" %s" % os.path.basename(f.path)) + Style.RESET_ALL) if not f.tag: print("\tAdding new tag") f.initTag() edited_files.add(f) tag = f.tag if tag.version != ID3_V2_4: print("\tConverting to ID3 v2.4") tag.version = ID3_V2_4 edited_files.add(f) if (dir_type != SINGLE_TYPE and album_artist != tag.album_artist): print(u"\tSetting album artist: %s" % album_artist) tag.album_artist = album_artist edited_files.add(f) if not tag.artist and dir_type in (VARIOUS_TYPE, SINGLE_TYPE): # Prompt artist tag.artist = self.prompt("Artist name", default=last["artist"]) last["artist"] = tag.artist elif len(artists) == 1 and tag.artist != artists[0]: assert(dir_type != SINGLE_TYPE) print(u"\tSetting artist: %s" % artists[0]) tag.artist = artists[0] edited_files.add(f) if tag.album != album and dir_type != SINGLE_TYPE: print(u"\tSetting album: %s" % album) tag.album = album edited_files.add(f) orig_title = tag.title if not tag.title: tag.title = prompt("Track title") tag.title = tag.title.strip() if self.args.fix_case: tag.title = _fixCase(tag.title) if orig_title != tag.title: print(u"\tSetting title: %s" % tag.title) edited_files.add(f) if dir_type != SINGLE_TYPE: # Track numbers tnum, ttot = tag.track_num update = False if ttot != num_audio_files: update = True ttot = num_audio_files if fix_track_nums or not (1 <= tnum <= num_audio_files): tnum = None while tnum is None: tnum = int(prompt("Track #", type_=int)) if not (1 <= tnum <= num_audio_files): print(Fore.RED + "Out of range: " + Fore.RESET + "1 <= %d <= %d" % (tnum, num_audio_files)) tnum = None elif tnum in new_track_nums: print(Fore.RED + "Duplicate value: " + Fore.RESET + str(tnum)) tnum = None else: update = True new_track_nums.append(tnum) if update: tag.track_num = (tnum, ttot) print("\tSetting track numbers: %s" % str(tag.track_num)) edited_files.add(f) else: # Singles if tag.track_num != (None, None): tag.track_num = (None, None) edited_files.add(f) if dir_type != SINGLE_TYPE: # Dates if tag.recording_date != rec_date: print("\tSetting %s date (%s)" % ("recording", str(rec_date))) tag.recording_date = rec_date edited_files.add(f) if tag.release_date != rel_date: print("\tSetting %s date (%s)" % ("release", str(rel_date))) tag.release_date = rel_date edited_files.add(f) if tag.original_release_date != orel_date: print("\tSetting %s date (%s)" % ("original release", str(orel_date))) tag.original_release_date = orel_date edited_files.add(f) for fid in ("USER", "PRIV"): n = len(tag.frame_set[fid] or []) if n: print("\tRemoving %d %s frames..." % (n, fid)) del tag.frame_set[fid] edited_files.add(f) # Add TLEN tlen = tag.getTextFrame("TLEN") real_tlen = f.info.time_secs * 1000 if tlen is None or int(tlen) != real_tlen: print("\tSetting TLEN (%d)" % real_tlen) tag.setTextFrame("TLEN", unicode(real_tlen)) edited_files.add(f) # Add custom album type if special and otherwise not able to be # determined. curr_type = tag.album_type if curr_type != dir_type: if dir_type in (LP_TYPE, VARIOUS_TYPE): if curr_type is not None: print("\tClearing %s = %s" % (TXXX_ALBUM_TYPE, curr_type)) tag.album_type = None edited_files.add(f) # We don't set lp because it is the default, and various # can be determined. else: print("\tSetting %s = %s" % (TXXX_ALBUM_TYPE, dir_type)) tag.album_type = dir_type edited_files.add(f) if not self._checkCoverArt(directory, audio_files): if not prompt("Proceed without valid cover file", default=True): return # Determine other changes, like file and/or directory renames # so they can be reported before save confirmation. # File renaming file_renames = [] if self.args.file_rename_pattern: format_str = self.args.file_rename_pattern else: if dir_type == SINGLE_TYPE: format_str = SINGLE_FNAME_FORMAT elif dir_type == VARIOUS_TYPE: format_str = VARIOUS_FNAME_FORMAT else: format_str = NORMAL_FNAME_FORMAT for f in audio_files: orig_name, orig_ext = os.path.splitext(os.path.basename(f.path)) new_name = TagTemplate(format_str).substitute(f.tag, zeropad=True) if orig_name != new_name: printMsg(u"Rename file to %s%s" % (new_name, orig_ext)) file_renames.append((f, new_name, orig_ext)) # Directory renaming dir_rename = None if dir_type != SINGLE_TYPE: if self.args.dir_rename_pattern: dir_format = self.args.dir_rename_pattern else: if dir_type == LIVE_TYPE: dir_format = LIVE_DNAME_FORMAT else: dir_format = NORMAL_DNAME_FORMAT template = TagTemplate(dir_format, dotted_dates=self.args.dotted_dates) pref_dir = template.substitute(audio_files[0].tag, zeropad=True) if os.path.basename(directory) != pref_dir: new_dir = os.path.join(os.path.dirname(directory), pref_dir) printMsg("Rename directory to %s" % new_dir) dir_rename = (directory, new_dir) if not self.args.dry_run: confirmed = False if (edited_files or file_renames or dir_rename): confirmed = prompt("\nSave changes", default=True) if confirmed: for f in edited_files: print(u"Saving %s" % os.path.basename(f.path)) f.tag.save(version=ID3_V2_4, preserve_file_time=True) for f, new_name, orig_ext in file_renames: printMsg(u"Renaming file to %s%s" % (new_name, orig_ext)) f.rename(new_name, preserve_file_time=True) if dir_rename: printMsg("Renaming directory to %s" % dir_rename[1]) s = os.stat(dir_rename[0]) os.rename(dir_rename[0], dir_rename[1]) # With a rename use the origianl access time os.utime(dir_rename[1], (s.st_atime, s.st_atime)) else: printMsg("\nNo changes made (run without -n/--dry-run)")
def handleDirectory(self, directory, _): if not self._file_cache: return directory = os.path.abspath(directory) print("\n" + Style.BRIGHT + Fore.GREY + "Scanning directory%s %s" % (Style.RESET_ALL, directory)) def _path(af): return af.path self._handled_one = True # Make sure all of the audio files has a tag. for f in self._file_cache: if f.tag is None: f.initTag() audio_files = sorted(list(self._file_cache), key=_path) self._file_cache = [] edited_files = set() self._curr_dir_type = self.args.dir_type if self._curr_dir_type is None: types = set([a.tag.album_type for a in audio_files]) if len(types) == 1: self._curr_dir_type = types.pop() # Check for corrections to LP, EP, COMP if (self._curr_dir_type is None and len(audio_files) < EP_MAX_SIZE_HINT): # Do you want EP? if False in [a.tag.album_type == EP_TYPE for a in audio_files]: if prompt("Only %d audio files, process directory as an EP" % len(audio_files), default=True): self._curr_dir_type = EP_TYPE else: self._curr_dir_type = EP_TYPE elif (self._curr_dir_type in (EP_TYPE, DEMO_TYPE) and len(audio_files) > EP_MAX_SIZE_HINT): # Do you want LP? if prompt("%d audio files is large for type %s, process " "directory as an LP" % (len(audio_files), self._curr_dir_type), default=True): self._curr_dir_type = LP_TYPE last = defaultdict(lambda: None) album_artist = None artists = set() album = None if self._curr_dir_type != SINGLE_TYPE: album_artist, artists = self._resolveArtistInfo(audio_files) print(Fore.BLUE + u"Album artist: " + Style.RESET_ALL + (album_artist or u"")) print(Fore.BLUE + "Artist" + ("s" if len(artists) > 1 else "") + ": " + Style.RESET_ALL + u", ".join(artists)) album = self._getAlbum(audio_files) print(Fore.BLUE + "Album: " + Style.RESET_ALL + album) rel_date, orel_date, rec_date = self._getDates(audio_files) for what, d in [("Release", rel_date), ("Original", orel_date), ("Recording", rec_date)]: print(Fore.BLUE + ("%s date: " % what) + Style.RESET_ALL + str(d)) num_audio_files = len(audio_files) track_nums = set([f.tag.track_num[0] for f in audio_files]) fix_track_nums = set(range(1, num_audio_files + 1)) != track_nums new_track_nums = [] dir_type = self._curr_dir_type for f in sorted(audio_files, key=_path): print(Style.BRIGHT + Fore.GREEN + u"Checking" + Fore.RESET + Fore.GREY + (" %s" % os.path.basename(f.path)) + Style.RESET_ALL) if not f.tag: print("\tAdding new tag") f.initTag() edited_files.add(f) tag = f.tag if tag.version != ID3_V2_4: print("\tConverting to ID3 v2.4") tag.version = ID3_V2_4 edited_files.add(f) if (dir_type != SINGLE_TYPE and album_artist != tag.album_artist): print(u"\tSetting album artist: %s" % album_artist) tag.album_artist = album_artist edited_files.add(f) if not tag.artist and dir_type in (VARIOUS_TYPE, SINGLE_TYPE): # Prompt artist tag.artist = prompt("Artist name", default=last["artist"]) last["artist"] = tag.artist elif len(artists) == 1 and tag.artist != artists[0]: assert(dir_type != SINGLE_TYPE) print(u"\tSetting artist: %s" % artists[0]) tag.artist = artists[0] edited_files.add(f) if tag.album != album and dir_type != SINGLE_TYPE: print(u"\tSetting album: %s" % album) tag.album = album edited_files.add(f) orig_title = tag.title if not tag.title: tag.title = prompt("Track title") tag.title = tag.title.strip() if self.args.fix_case: tag.title = _fixCase(tag.title) if orig_title != tag.title: print(u"\tSetting title: %s" % tag.title) edited_files.add(f) if dir_type != SINGLE_TYPE: # Track numbers tnum, ttot = tag.track_num update = False if ttot != num_audio_files: update = True ttot = num_audio_files if fix_track_nums or not (1 <= tnum <= num_audio_files): tnum = None while tnum is None: tnum = int(prompt("Track #", type_=int)) if not (1 <= tnum <= num_audio_files): print(Fore.RED + "Out of range: " + Fore.RESET + "1 <= %d <= %d" % (tnum, num_audio_files)) tnum = None elif tnum in new_track_nums: print(Fore.RED + "Duplicate value: " + Fore.RESET + str(tnum)) tnum = None else: update = True new_track_nums.append(tnum) if update: tag.track_num = (tnum, ttot) print("\tSetting track numbers: %s" % str(tag.track_num)) edited_files.add(f) else: # Singles if tag.track_num != (None, None): tag.track_num = (None, None) edited_files.add(f) if dir_type != SINGLE_TYPE: # Dates if rec_date and tag.recording_date != rec_date: print("\tSetting %s date (%s)" % ("recording", str(rec_date))) tag.recording_date = rec_date edited_files.add(f) if rel_date and tag.release_date != rel_date: print("\tSetting %s date (%s)" % ("release", str(rel_date))) tag.release_date = rel_date edited_files.add(f) if orel_date and tag.original_release_date != orel_date: print("\tSetting %s date (%s)" % ("original release", str(orel_date))) tag.original_release_date = orel_date edited_files.add(f) for frame in list(tag.frameiter(["USER", "PRIV"])): print("\tRemoving %s frames: %s" % (frame.id, frame.owner_id if frame.id == b"PRIV" else frame.text)) tag.frame_set[frame.id].remove(frame) edited_files.add(f) # Add TLEN tlen = tag.getTextFrame("TLEN") real_tlen = f.info.time_secs * 1000 if tlen is None or int(tlen) != real_tlen: print("\tSetting TLEN (%d)" % real_tlen) tag.setTextFrame("TLEN", UnicodeType(real_tlen)) edited_files.add(f) # Add custom album type if special and otherwise not able to be # determined. curr_type = tag.album_type if curr_type != dir_type: print("\tSetting %s = %s" % (TXXX_ALBUM_TYPE, dir_type)) tag.album_type = dir_type edited_files.add(f) try: if not self._checkCoverArt(directory, audio_files): if not prompt("Proceed without valid cover file", default=True): return finally: self._dir_images = [] # Determine other changes, like file and/or directory renames # so they can be reported before save confirmation. # File renaming file_renames = [] if self.args.file_rename_pattern: format_str = self.args.file_rename_pattern else: if dir_type == SINGLE_TYPE: format_str = SINGLE_FNAME_FORMAT elif dir_type in (VARIOUS_TYPE, COMP_TYPE): format_str = VARIOUS_FNAME_FORMAT else: format_str = NORMAL_FNAME_FORMAT for f in audio_files: orig_name, orig_ext = os.path.splitext(os.path.basename(f.path)) new_name = TagTemplate(format_str).substitute(f.tag, zeropad=True) if orig_name != new_name: printMsg(u"Rename file to %s%s" % (new_name, orig_ext)) file_renames.append((f, new_name, orig_ext)) # Directory renaming dir_rename = None if dir_type != SINGLE_TYPE: if self.args.dir_rename_pattern: dir_format = self.args.dir_rename_pattern else: if dir_type == LIVE_TYPE: dir_format = LIVE_DNAME_FORMAT else: dir_format = NORMAL_DNAME_FORMAT template = TagTemplate(dir_format, dotted_dates=self.args.dotted_dates) pref_dir = template.substitute(audio_files[0].tag, zeropad=True) if os.path.basename(directory) != pref_dir: new_dir = os.path.join(os.path.dirname(directory), pref_dir) printMsg("Rename directory to %s" % new_dir) dir_rename = (directory, new_dir) # Cruft files to remove file_removes = [] if self._dir_files_to_remove: for f in self._dir_files_to_remove: print("Remove file: " + os.path.basename(f)) file_removes.append(f) self._dir_files_to_remove = set() if not self.args.dry_run: confirmed = False if (edited_files or file_renames or dir_rename or file_removes): confirmed = prompt("\nSave changes", default=True) if confirmed: for f in edited_files: print(u"Saving %s" % os.path.basename(f.path)) f.tag.save(version=ID3_V2_4, preserve_file_time=True) for f, new_name, orig_ext in file_renames: printMsg(u"Renaming file to %s%s" % (new_name, orig_ext)) f.rename(new_name, preserve_file_time=True) if file_removes: for f in file_removes: printMsg("Removing file %s" % os.path.basename(f)) os.remove(f) if dir_rename: printMsg("Renaming directory to %s" % dir_rename[1]) s = os.stat(dir_rename[0]) os.rename(dir_rename[0], dir_rename[1]) # With a rename use the origianl access time os.utime(dir_rename[1], (s.st_atime, s.st_atime)) else: printMsg("\nNo changes made (run without -n/--dry-run)")
def handleDirectory(self, directory, _): if not self._file_cache: return directory = os.path.abspath(directory) print("\n" + Style.bright + Fore.grey + "Scanning directory%s %s" % (Style.reset_all, directory)) def _path(af): return af.path audio_files = sorted(list(self._file_cache), key=_path) self._file_cache = [] edited_files = set() if (len(audio_files) < EP_MAX_HINT and self.args.dir_type not in (EP_TYPE, DEMO_TYPE, VARIOUS_TYPE)): if _prompt("Only %d audio files, process directory as an EP" % len(audio_files), default=True): self.args.dir_type = EP_TYPE elif self.args.dir_type == EP_TYPE and len(audio_files) > EP_MAX_HINT: if _prompt("%d audio files is large for an EP, process directory " "as an LP" % len(audio_files), default=True): self.args.dir_type = LP_TYPE elif (self.args.dir_type not in (VARIOUS_TYPE, COMP_TYPE, LIVE_TYPE) and len(audio_files) > LP_MAX_HINT): if _prompt("%d audio files is large for an LP, process directory " "as a compilation" % len(audio_files), default=True): self.args.dir_type = COMP_TYPE last = defaultdict(lambda: None) artist = self._getArtist(audio_files) print(Fore.BLUE + "Artist: " + Style.RESET_ALL + (artist or "Various Artists")) album = self._getAlbum(audio_files) print(Fore.BLUE + "Album: " + Style.RESET_ALL + album) rel_date, orel_date, rec_date = self._getDates(audio_files) for what, d in [("Release", rel_date), ("Original", orel_date), ("Recording", rec_date)]: print(Fore.BLUE + ("%s date: " % what) + Style.RESET_ALL + str(d)) num_audio_files = len(audio_files) track_nums = set([f.tag.track_num[0] for f in audio_files]) fix_track_nums = bool(set(range(1, num_audio_files + 1)) != track_nums) new_track_nums = [] for f in sorted(audio_files, key=_path): print(Style.bright + Fore.grey + u"Checking%s %s" % (Style.reset_all, os.path.basename(f.path))) if not f.tag: print("\tAdding new tag") f.initTag() edited_files.add(f) tag = f.tag if tag.version != ID3_V2_4: print("\tConverting to ID3 v2.4") tag.version = ID3_V2_4 edited_files.add(f) if self.args.dir_type == VARIOUS_TYPE: if not tag.artist: tag.artist = self._prompt("Artist name", default=last["artist"]) last["artist"] = tag.artist elif tag.artist != artist: print(u"\tSetting artist: %s" % artist) tag.artist = artist edited_files.add(f) if tag.album != album: print(u"\tSetting album: %s" % album) tag.album = album edited_files.add(f) orig_title = tag.title if not tag.title: tag.title = _prompt("Track title") if self.args.fix_case: tag.title = _fixCase(tag.title) if orig_title != tag.title: print(u"\tSetting title: %s" % tag.title) edited_files.add(f) # Track numbers tnum, ttot = tag.track_num update = False if ttot != num_audio_files: update = True ttot = num_audio_files if fix_track_nums or not (1 <= tnum <= num_audio_files): tnum = None while tnum is None: tnum = int(_prompt("Track #")) if not (1 <= tnum <= num_audio_files): print(Fore.red + "Out of range: " + Fore.reset + "1 <= %d <= %d" % (tnum, num_audio_files)) tnum = None elif tnum in new_track_nums: print(Fore.red + "Duplicate value: " + Fore.reset + str(tnum)) tnum = None else: update = True new_track_nums.append(tnum) if update: tag.track_num = (tnum, ttot) print("\tSetting track numbers: %s" % str(tag.track_num)) edited_files.add(f) # Dates if tag.recording_date != rec_date: print("\tSetting %s date (%s)" % ("recording", str(rec_date))) tag.recording_date = rec_date edited_files.add(f) if tag.release_date != rel_date: print("\tSetting %s date (%s)" % ("release", str(rel_date))) tag.release_date = rel_date edited_files.add(f) if tag.original_release_date != orel_date: print("\tSetting %s date (%s)" % ("original release", str(orel_date))) tag.original_release_date = orel_date edited_files.add(f) for fid in ("USER", "PRIV"): n = len(tag.frame_set[fid] or []) if n: print("\tRemoving %d %s frames..." % (n, fid)) del tag.frame_set[fid] edited_files.add(f) # Add TLEN tlen = tag.getTextFrame("TLEN") real_tlen = f.info.time_secs * 1000 if tlen is None or int(tlen) != real_tlen: print("\tSetting TLEN (%d)" % real_tlen) tag.setTextFrame("TLEN", unicode(real_tlen)) edited_files.add(f) # Add custom album type if special and otherwise not able to be # determined. curr_type = tag.user_text_frames.get(TXXX_ALBUM_TYPE) if curr_type is not None: curr_type = curr_type.text if curr_type != self.args.dir_type: if self.args.dir_type in (LP_TYPE, VARIOUS_TYPE): if curr_type is not None: print("\tClearing %s = %s" % (TXXX_ALBUM_TYPE, curr_type)) tag.user_text_frames.remove(TXXX_ALBUM_TYPE) edited_files.add(f) # We don't set lp because it is the default, and various # can be determined. else: print("\tSetting %s = %s" % (TXXX_ALBUM_TYPE, self.args.dir_type)) tag.user_text_frames.set(self.args.dir_type, TXXX_ALBUM_TYPE) edited_files.add(f) # Determine other changes, like file and/or duirectory renames # so they can be reported before save confirmation. file_renames = [] format_str = (NORMAL_FNAME_FORMAT if self.args.dir_type != VARIOUS_TYPE else VARIOUS_FNAME_FORMAT) for f in audio_files: orig_name, orig_ext = os.path.splitext(os.path.basename(f.path)) new_name = TagTemplate(format_str).substitute(f.tag, zeropad=True) if orig_name != new_name: printMsg(u"Rename file to %s%s" % (new_name, orig_ext)) file_renames.append((f, new_name, orig_ext)) dir_rename = None if self.args.dir_type == LIVE_TYPE: dir_format = LIVE_DNAME_FORMAT else: dir_format = NORMAL_DNAME_FORMAT template = TagTemplate(dir_format, dotted_dates=self.args.dotted_dates) pref_dir = template.substitute(audio_files[0].tag, zeropad=True) if os.path.basename(directory) != pref_dir: new_dir = os.path.join(os.path.dirname(directory), pref_dir) printMsg("Rename directory to %s" % new_dir) dir_rename = (directory, new_dir) if not self.args.dry_run: confirmed = False if (edited_files or file_renames or dir_rename): confirmed = _prompt("\nSave changes", default=True) if confirmed: for f in edited_files: print(u"Saving %s" % os.path.basename(f.path)) f.tag.save(version=ID3_V2_4) for f, new_name, orig_ext in file_renames: printMsg(u"Renaming file to %s%s" % (new_name, orig_ext)) f.rename(new_name) if dir_rename: printMsg("Renaming directory to %s" % dir_rename[1]) os.rename(dir_rename[0], dir_rename[1]) else: printMsg("\nNo changes made (run without -n/--dry-run)")
def handleFile(self, f): parse_version = self.args.tag_version super(ClassicPlugin, self).handleFile(f, tag_version=parse_version) if not self.audio_file: return self.printHeader(f) printMsg("-" * 79) new_tag = False if not self.audio_file.tag or self.handleRemoves(self.audio_file.tag): self.audio_file.initTag(version=parse_version) new_tag = True save_tag = ( self.handleEdits(self.audio_file.tag) or self.handlePadding(self.audio_file.tag) or self.args.force_update or self.args.convert_version ) self.printAudioInfo(self.audio_file.info) if not save_tag and new_tag: printError("No ID3 %s tag found!" % id3.versionToString(self.args.tag_version)) return self.printTag(self.audio_file.tag) if save_tag: # Use current tag version unless a convert was supplied version = self.args.convert_version or self.audio_file.tag.version printWarning("Writing ID3 version %s" % id3.versionToString(version)) # DEFAULT_MAX_PADDING is not set up as argument default, # because we don't want to rewrite the file if the user # did not trigger that explicitly: max_padding = self.args.max_padding if max_padding is True: max_padding = DEFAULT_MAX_PADDING self.audio_file.tag.save( version=version, encoding=self.args.text_encoding, backup=self.args.backup, preserve_file_time=self.args.preserve_file_time, max_padding=max_padding, ) if self.args.rename_pattern: # Handle file renaming. from eyed3.id3.tag import TagTemplate template = TagTemplate(self.args.rename_pattern) name = template.substitute(self.audio_file.tag, zeropad=True) orig = self.audio_file.path try: self.audio_file.rename(name) printWarning("Renamed '%s' to '%s'" % (orig, self.audio_file.path)) except IOError as ex: printError(ex.message) printMsg("-" * 79)