def test_selective_modified_album_metadata_not_moved(self): mf = MediaFile(syspath(self.i.path)) mf.album = u'differentAlbum' mf.genre = u'differentGenre' mf.save() self._update(move=True, fields=['genre']) item = self.lib.items().get() self.assertTrue(b'differentAlbum' not in item.path) self.assertEqual(item.genre, u'differentGenre')
def test_selective_modified_metadata_moved(self): mf = MediaFile(syspath(self.i.path)) mf.title = u'differentTitle' mf.genre = u'differentGenre' mf.save() self._update(move=True, fields=['title']) item = self.lib.items().get() self.assertTrue(b'differentTitle' in item.path) self.assertNotEqual(item.genre, u'differentGenre')
def tagger(conf, destination, releaseid, source): _log = init_logging(conf) if not destination: destination = source cfg = TaggerConfig(source, destination, conf) if cfg.id_tag in cfg.release_tags: releaseid = cfg.release_tags[cfg.id_tag].strip() if releaseid: release_id = releaseid if not releaseid: click.echo('Please specify the discogs.com releaseid ("-r")') sys.exit(1) _log.info('Attempting to tag files from target destination={0}'.format(destination)) discogs_release = DiscogsAlbum(DiscogsWrapper().discogs, release_id, cfg.split_artists, cfg.split_genres_and_styles) release = TaggerUtils(discogs_release, cfg) # ensure we were able to map the release appropriately. if not release.tag_map: _log.fatal("Unable to map available audio files to the number of tracks in the Discogs release '{0}'. Exiting".format( release_id)) sys.exit(1) artist = cfg.split_artists.join(release.album.artists) artist = release.album.clean_name(artist) _log.info("Tagging album '{0} - {1}'".format(artist, release.album.title)) dest_dir_name = release.dest_dir_name if os.path.exists(dest_dir_name): _log.fatal('Destination directory already exists. directory={0}. Aborting operation'.format(dest_dir_name)) sys.exit(1) else: _log.info("Creating destination directory '{0}'".format(dest_dir_name)) mkdir_p(dest_dir_name) _log.info("Downloading and storing images") release.album.get_images(dest_dir_name, cfg.images_format, cfg.first_image_name) disc_names = dict() folder_names = dict() if release.album.disctotal > 1 and cfg.split_discs_folder: _log.debug("Creating disc structure") for i in range(1, release.album.disctotal + 1): folder_name = "%s%.d" % (release.album_folder_name, i) disc_dir_name = os.path.join(dest_dir_name, folder_name) mkdir_p(disc_dir_name) # This is duplicate, remove one of the following statements disc_names[i] = disc_dir_name folder_names[i] = folder_name else: folder_names[1] = "" for track in release.tag_map: # copy old file into new location if release.album.disctotal > 1 and cfg.split_discs_folder: target_folder = disc_names[int(track['discnumber'])] else: target_folder = dest_dir_name _log.debug("Source file {0}".format(os.path.join(source, track['orig_file']))) _log.info("Writing file {0}".format(os.path.join(target_folder, track['new_file']))) _log.debug("metadata -> {0:2d} {1} - {2}".format(track['tracknumber'], track['artist'], track['title'])) _log.debug("----------> {0}".format(track['new_file'])) shutil.copyfile(track['orig_file'], os.path.join(target_folder, track['new_file'])) # load metadata information metadata = MediaFile(os.path.join(target_folder, track['new_file'])) # read already existing (and still wanted) properties keep_tags = {} if cfg.keep_tags: for name in cfg.keep_tags.split(","): try: getattr(metadata, name) except AttributeError: _log.warn('Unable to keep_tag. tag={0}'.format(name)) continue keep_tags[name] = getattr(metadata, name) # remove current metadata metadata.delete() # set album metadata metadata.album = release.album.title if cfg.split_discs_folder and release.album.disctotal > 1: # the fileext should be stored on the album/track as well fileext = os.path.splitext(track['orig_file'])[1] disc_title_extension = release._value_from_tag_format(cfg.split_discs_extension, track['tracknumber'], track['position'] - 1, fileext) metadata.album = "{0}{1}".format(metadata.album, disc_title_extension) metadata.composer = artist metadata.albumartist = artist metadata.albumartist_sort = release.album.sort_artist metadata.label = release.album.label metadata.year = release.album.year metadata.country = release.album.country metadata.url = release.album.url # add styles to the grouping tag (right now, we can just use one) metadata.grouping = release.album.styles # adding two as there is no standard. discogstagger pre v1 # used (TXXX desc="Catalog #") # mediafile uses TXXX desc="CATALOGNUMBER" metadata.catalognum = release.album.catno metadata.catalognumber = release.album.catno # use the correct genre field, on config use the first style genre = release.album.genres if cfg.use_style: genre = release.album.style metadata.genre = genre metadata.discogs_id = release_id if release.album.disctotal and release.album.disctotal > 1 and track['discnumber']: _log.debug("writing disctotal and discnumber") metadata.disc = track['discnumber'] metadata.disctotal = release.album.disctotal if release.album.is_compilation: metadata.comp = True metadata.comments = release.album.note # encoder if cfg.encoder_tag is not None: metadata.encoder = cfg.encoder_tag # if track.discsubtotal: # metadata.discsubtotal = track.discsubtotal # set track metadata metadata.title = track['title'] metadata.artist = track['artist'] metadata.artist_sort = track['sortartist'] metadata.track = track['tracknumber'] # the following value will be wrong, if the disc has a name or is a multi # disc release --> fix it metadata.tracktotal = release.album.tracktotal_on_disc(track['discnumber']) # it does not make sense to store this in the "common" configuration, but only in the # id.txt. we use a special naming convention --> most probably we should reuse the # configuration parser for this one as well, no? for name, value in list(cfg.release_tags.items()): if name.startswith("tag:"): name = name.split(":") name = name[1] setattr(metadata, name, value) first_image_name = cfg.first_image_name # this should be done in a cleaner way to avoid multiple images in different # folders (use the dest_dir again....) if cfg.embed_coverart and os.path.exists(os.path.join(dest_dir_name, first_image_name)): imgdata = open(os.path.join(dest_dir_name, first_image_name), 'rb').read() imgtype = imghdr.what(None, imgdata) if imgtype in ("jpeg", "png"): _log.debug("Embedding album art.") metadata.art = imgdata if keep_tags is not None: for name in keep_tags: setattr(metadata, name, keep_tags[name]) metadata.save() # start supplementary actions if cfg.write_nfo: _log.info("Generating .nfo file") release.create_nfo() # adopt for multi disc support if cfg.write_m3u: _log.info("Generating .m3u file") release.create_m3u(folder_names) # copy "other files" on request if cfg.copy_other_files and len(release.copy_files) > 0: _log.info("copying files from source directory") copy_files = release.copy_files dir_list = os.listdir(source) _log.debug("start_dir: {0}".format(source)) _log.debug("dir list: {0}".format(dir_list)) file_list = [os.path.join(source, x) for x in dir_list if not x.lower().endswith(TaggerUtils.FILE_TYPE) and os.path.isfile(os.path.join(source, x))] copy_files.extend(file_list) for fname in copy_files: if not fname.endswith(".m3u"): _log.debug("source: {0}".format(fname)) _log.debug("target: {0}".format(os.path.join(dest_dir_name, os.path.basename(fname)))) shutil.copyfile(fname, os.path.join(dest_dir_name, os.path.basename(fname))) # remove source directory, if configured as such. if not cfg.keep_original: _log.info("Deleting source directory '{0}'".format(source)) shutil.rmtree(source) _log.info("Tagging complete.")
def write_tags(filename, tags): f1 = MediaFile(filename) writeTags = "y" showMoreOptions = "n" date = tags["release_date"].split("-") if not "-A" in OPTIONS: writeTags = input("\nWrite tags? (y/n): ") if writeTags == "y": print("\nWriting tags...") # Deletes current tags from the song f1.delete() date = tags["release_date"].split("-") f1.title = tags["title"] f1.album = tags["album_title"] # f1.artist = tags["artists"] f1.day = date[0] f1.month = date[1] f1.year = date[2] # f1.track = tags["track_number"] # f1.tracktotal = tags["total_tracks"] # f1.disc = f"{tags["disc_number"]} # f1.disctotal = tags["total_discs"] f1.genre = tags["genre"] f1.albumartist = tags["album_artist"] # Drops "Album Artist" Tag f1.__dict__["mgfile"].pop("album artist") file_dir = os.path.dirname(filename) if (file_dir != ""): os.chdir(file_dir) if not "-p" in OPTIONS: f1.art = get_artwork(filename, (tags["album_title"], tags["album_artist"])) f1.save() f2 = FLAC(filename) f2["Artist"] = tags["artists"] f2["tracknumber"] = [f"{tags['track_number']}"] f2["discnumber"] = [f"{tags['disc_number']}"] f2.save() print("Tags written successfully!") filename_ext = os.path.splitext(filename)[1] title = f1.title + " - " + f1.albumartist + filename_ext if not os.path.isfile(title): os.rename(filename, title) if os.path.isfile("./cover.jpg"): os.remove("./cover.jpg") if len(OUTPUT) != 0: dest = os.path.join(OUTPUT[0], os.path.basename(filename)) if os.path.exists(dest): os.remove(dest) if os.path.exists(filename): shutil.move(filename, OUTPUT[0]) elif os.path.exists(title): shutil.move(title, OUTPUT[0]) if writeTags == "n" and not "-A" in OPTIONS: showMoreOptions = input("Show more options? (y/n): ") return showMoreOptions
def tagger(conf, destination, releaseid, source): _log = init_logging(conf) if not destination: destination = source cfg = TaggerConfig(source, destination, conf) if cfg.id_tag in cfg.release_tags: releaseid = cfg.release_tags[cfg.id_tag].strip() if releaseid: release_id = releaseid if not releaseid: click.echo('Please specify the discogs.com releaseid ("-r")') sys.exit(1) _log.info('Attempting to tag files from target destination={0}'.format( destination)) discogs_release = DiscogsAlbum(DiscogsWrapper().discogs, release_id, cfg.split_artists, cfg.split_genres_and_styles) release = TaggerUtils(discogs_release, cfg) # ensure we were able to map the release appropriately. if not release.tag_map: _log.fatal( "Unable to map available audio files to the number of tracks in the Discogs release '{0}'. Exiting" .format(release_id)) sys.exit(1) artist = cfg.split_artists.join(release.album.artists) artist = release.album.clean_name(artist) _log.info("Tagging album '{0} - {1}'".format(artist, release.album.title)) dest_dir_name = release.dest_dir_name if os.path.exists(dest_dir_name): _log.fatal( 'Destination directory already exists. directory={0}. Aborting operation' .format(dest_dir_name)) sys.exit(1) else: _log.info("Creating destination directory '{0}'".format(dest_dir_name)) mkdir_p(dest_dir_name) _log.info("Downloading and storing images") release.album.get_images(dest_dir_name, cfg.images_format, cfg.first_image_name) disc_names = dict() folder_names = dict() if release.album.disctotal > 1 and cfg.split_discs_folder: _log.debug("Creating disc structure") for i in range(1, release.album.disctotal + 1): folder_name = "%s%.d" % (release.album_folder_name, i) disc_dir_name = os.path.join(dest_dir_name, folder_name) mkdir_p(disc_dir_name) # This is duplicate, remove one of the following statements disc_names[i] = disc_dir_name folder_names[i] = folder_name else: folder_names[1] = "" for track in release.tag_map: # copy old file into new location if release.album.disctotal > 1 and cfg.split_discs_folder: target_folder = disc_names[int(track['discnumber'])] else: target_folder = dest_dir_name _log.debug("Source file {0}".format( os.path.join(source, track['orig_file']))) _log.info("Writing file {0}".format( os.path.join(target_folder, track['new_file']))) _log.debug("metadata -> {0:2d} {1} - {2}".format( track['tracknumber'], track['artist'], track['title'])) _log.debug("----------> {0}".format(track['new_file'])) shutil.copyfile(track['orig_file'], os.path.join(target_folder, track['new_file'])) # load metadata information metadata = MediaFile(os.path.join(target_folder, track['new_file'])) # read already existing (and still wanted) properties keep_tags = {} if cfg.keep_tags: for name in cfg.keep_tags.split(","): try: getattr(metadata, name) except AttributeError: _log.warn('Unable to keep_tag. tag={0}'.format(name)) continue keep_tags[name] = getattr(metadata, name) # remove current metadata metadata.delete() # set album metadata metadata.album = release.album.title if cfg.split_discs_folder and release.album.disctotal > 1: # the fileext should be stored on the album/track as well fileext = os.path.splitext(track['orig_file'])[1] disc_title_extension = release._value_from_tag_format( cfg.split_discs_extension, track['tracknumber'], track['position'] - 1, fileext) metadata.album = "{0}{1}".format(metadata.album, disc_title_extension) metadata.composer = artist metadata.albumartist = artist metadata.albumartist_sort = release.album.sort_artist metadata.label = release.album.label metadata.year = release.album.year metadata.country = release.album.country metadata.url = release.album.url # add styles to the grouping tag (right now, we can just use one) metadata.grouping = release.album.styles # adding two as there is no standard. discogstagger pre v1 # used (TXXX desc="Catalog #") # mediafile uses TXXX desc="CATALOGNUMBER" metadata.catalognum = release.album.catno metadata.catalognumber = release.album.catno # use the correct genre field, on config use the first style genre = release.album.genres if cfg.use_style: genre = release.album.style metadata.genre = genre metadata.discogs_id = release_id if release.album.disctotal and release.album.disctotal > 1 and track[ 'discnumber']: _log.debug("writing disctotal and discnumber") metadata.disc = track['discnumber'] metadata.disctotal = release.album.disctotal if release.album.is_compilation: metadata.comp = True metadata.comments = release.album.note # encoder if cfg.encoder_tag is not None: metadata.encoder = cfg.encoder_tag # if track.discsubtotal: # metadata.discsubtotal = track.discsubtotal # set track metadata metadata.title = track['title'] metadata.artist = track['artist'] metadata.artist_sort = track['sortartist'] metadata.track = track['tracknumber'] # the following value will be wrong, if the disc has a name or is a multi # disc release --> fix it metadata.tracktotal = release.album.tracktotal_on_disc( track['discnumber']) # it does not make sense to store this in the "common" configuration, but only in the # id.txt. we use a special naming convention --> most probably we should reuse the # configuration parser for this one as well, no? for name, value in list(cfg.release_tags.items()): if name.startswith("tag:"): name = name.split(":") name = name[1] setattr(metadata, name, value) first_image_name = cfg.first_image_name # this should be done in a cleaner way to avoid multiple images in different # folders (use the dest_dir again....) if cfg.embed_coverart and os.path.exists( os.path.join(dest_dir_name, first_image_name)): imgdata = open(os.path.join(dest_dir_name, first_image_name), 'rb').read() imgtype = imghdr.what(None, imgdata) if imgtype in ("jpeg", "png"): _log.debug("Embedding album art.") metadata.art = imgdata if keep_tags is not None: for name in keep_tags: setattr(metadata, name, keep_tags[name]) metadata.save() # start supplementary actions if cfg.write_nfo: _log.info("Generating .nfo file") release.create_nfo() # adopt for multi disc support if cfg.write_m3u: _log.info("Generating .m3u file") release.create_m3u(folder_names) # copy "other files" on request if cfg.copy_other_files and len(release.copy_files) > 0: _log.info("copying files from source directory") copy_files = release.copy_files dir_list = os.listdir(source) _log.debug("start_dir: {0}".format(source)) _log.debug("dir list: {0}".format(dir_list)) file_list = [ os.path.join(source, x) for x in dir_list if not x.lower().endswith(TaggerUtils.FILE_TYPE) and os.path.isfile(os.path.join(source, x)) ] copy_files.extend(file_list) for fname in copy_files: if not fname.endswith(".m3u"): _log.debug("source: {0}".format(fname)) _log.debug("target: {0}".format( os.path.join(dest_dir_name, os.path.basename(fname)))) shutil.copyfile( fname, os.path.join(dest_dir_name, os.path.basename(fname))) # remove source directory, if configured as such. if not cfg.keep_original: _log.info("Deleting source directory '{0}'".format(source)) shutil.rmtree(source) _log.info("Tagging complete.")