Exemple #1
0
    def _setTagsForMp3File(self, audioFileTags):
        '''
        Sets the Mp3 file's tags to that of the AudioFileTags object given.
        '''
        # Use the EasyId3 interface for setting the standard Mp3 tags
        mutagenInterface = EasyID3(self.audioFilepath)

        mutagenInterface['title'] = audioFileTags.title
        mutagenInterface['artist'] = audioFileTags.artist
        mutagenInterface['album'] = audioFileTags.album
        mutagenInterface['albumartist'] = audioFileTags.albumArtist
        mutagenInterface['genre'] = audioFileTags.genre

        mutagenInterface.save()

        # Use the ID3 interface for setting the nonstandard Mp3 tags
        mutagenInterface = ID3(self.audioFilepath, v2_version=3)

        mutagenInterface['TXXX:DATE_ALL_PLAYS'] = TXXX(
            3, desc='DATE_ALL_PLAYS', text=audioFileTags.dateAllPlays)
        mutagenInterface['TXXX:DATE_LAST_PLAYED'] = TXXX(
            3, desc='DATE_LAST_PLAYED', text=audioFileTags.dateLastPlayed)
        mutagenInterface['TXXX:PLAY_COUNT'] = TXXX(
            3, desc='PLAY_COUNT', text=audioFileTags.playCount)
        mutagenInterface['TXXX:VOTES'] = TXXX(3,
                                              desc='VOTES',
                                              text=audioFileTags.votes)
        mutagenInterface['TXXX:RATING'] = TXXX(3,
                                               desc='RATING',
                                               text=audioFileTags.rating)

        mutagenInterface.save(v2_version=3)
    def test_TXXX(self):
        from mutagen.id3 import TXXX
        self.assert_(isinstance(TXXX(desc='d', text='text'), TXXX))

        frame = TXXX(encoding=0, desc="d", text=[])
        self.assertEqual(frame.HashKey, "TXXX:d")
        frame._pprint()
Exemple #3
0
    def test_TXXX(self):
        from mutagen.id3 import TXXX
        self.assert_(isinstance(TXXX(desc='d', text='text'), TXXX))

        frame = TXXX(encoding=0, desc="d", text=[])
        self.assertEqual(frame.HashKey, "TXXX:d")
        frame._pprint()
    def test_hash(self):
        frame = TXXX(encoding=0, desc="d", text=[])
        self.assertEqual(frame.HashKey, "TXXX:d")
        frame._pprint()

        self.assertEquals(TXXX(text="a").HashKey, TXXX(text="b").HashKey)
        self.assertNotEquals(TXXX(desc="a").HashKey, TXXX(desc="b").HashKey)
def tagFoundButUnratedFile(srcCompleteFileName, toolName, toolOptions,
                           foundNoRating, foundWithRating,
                           foundWithUpperCaseRating):
    """
    This method adds FMPS_RATING to all files given. It adds a default rating of 0.4 if no FMPS_RATING is found.
    In addition it computes POPM (e.g Windows Media Player) and RATING (e.g. xbmc) tags to files     
    """
    os.chdir(os.path.dirname(srcCompleteFileName))
    f = taglib.File(srcCompleteFileName)
    mutID3 = ID3(srcCompleteFileName)
    logging.debug("working dir: " + os.getcwd())
    rating = '0.4'
    if 'FMPS_RATING' in f.tags:
        logging.debug("Rating with wrong case set for " + srcCompleteFileName)
        rating = f.tags['FMPS_RATING'][0]
        logging.debug(str(f.tags['FMPS_RATING']) + str(f.tags))
        new_entry = {
            'srcCompleteFileName': srcCompleteFileName,
            'TAGS': f.tags
        }
        foundWithUpperCaseRating.append(new_entry)
        # pytaglib can only write  tags in uppercase so these 2 lines below do not work
        del f.tags['FMPS_RATING']
        mutID3.delall('TXXX:FMPS_RATING')
        mutID3.add(TXXX(encoding=3, desc='FMPS_Rating', text=rating))
        # add xbmcratings see http://kodi.wiki/view/Adding_music_to_the_library#Ratings_in_ID3_tags
    elif 'FMPS_Rating' in f.tags:
        logging.debug("Rating set for " + srcCompleteFileName)
        logging.debug(str(f.tags['FMPS_Rating']) + str(f.tags))
        foundWithRating.append(new_entry)
        rating = f.tags['FMPS_Rating'][0]
    else:
        logging.debug("No Rating set for " + srcCompleteFileName)
        new_entry = {
            'srcCompleteFileName': srcCompleteFileName,
            'TAGS': f.tags
        }
        foundNoRating.append(new_entry)
        mutID3.add(TXXX(encoding=3, desc='FMPS_Rating', text=u'0.4'))
    xbmc_rating = math.trunc(float(rating) * 5)
    mutID3.add(TXXX(encoding=3, desc='RATING', text=str(xbmc_rating)))
    popm_rating = math.trunc(float(rating) * 255)
    mutID3.add(POPM(rating=popm_rating))
    MP3CARidx = srcCompleteFileName.find('MP3CAR')
    szCarDir = srcCompleteFileName[MP3CARidx - 3:MP3CARidx]
    mutID3.add(TXXX(encoding=3, desc='SZ_CarDir', text=szCarDir))
    #f.tags['SZ_CarDir']=szCarDir
    mutID3.save()
Exemple #6
0
def write2tag(tag, lyric):
    '''
    :param tag: object created by 'ID3(file)'
    '''

    arr = parse_synced_lyric(lyric)
    if len(arr) > 0:
        #synced lyric
        """
        'SYLT' is not displayed.
        
        if len(tag.getall('SYLT'))>0:
            tag.delall('SYLT')
        tag.add(
            SYLT(encoding=3,lang=u'eng',desc=u'desc', 
                format=2,    #time format=mill seconds
                type=1,      #type=lyric
                text=arr    #[(text of lyric,start_time)]
            )
        )
        """
        if len(tag.getall('TXXX:LIRICS')) > 0:
            tag.delall('TXXX:LIRICS')
        tag.add(TXXX(encoding=3, desc='LYRICS', text=[lyric]))
    else:
        #save tag to unsynced lyric
        if len(tag.getall('USLT')) > 0:
            tag.delall('USLT')
        tag.add(USLT(encoding=3, lang='eng', desc='desc', text=lyric))
    try:
        tag.save()
    except Exception as e:
        msg = "error at saving mp3.:" + str(e)
        print(msg)
        logging.error(msg)
    def ok_pressed():
        try:
            tags = ID3(_dir + "/" + __dir)
        except:
            print("Adding ID3 header;")
            tags = ID3()

        tags['TRCK'] = TRCK(encoding=3, text=edit_entry_list[TRACK_ID].get())
        tags['TIT2'] = TIT2(encoding=3, text=edit_entry_list[TITLE_ID].get())
        tags['TPE1'] = TPE1(encoding=3, text=edit_entry_list[ARTIST_ID].get())
        tags['TALB'] = TALB(encoding=3, text=edit_entry_list[ALBUM_ID].get())
        tags['TDRC'] = TDRC(encoding=3, text=edit_entry_list[YEAR_ID].get())
        tags['TCOM'] = TCOM(encoding=3,
                            text=edit_entry_list[COMPOSER_ID].get())
        tags['TEXT'] = TEXT(encoding=3,
                            text=edit_entry_list[LYRICIST_ID].get())
        tags['TXXX:PERFORMER'] = TXXX(encoding=3,
                                      desc='PERFORMER',
                                      text=edit_entry_list[PERFORMER_ID].get())

        try:
            tags.save(_dir + "/" + __dir)
        except:
            print("denied")

        new_val = list(tree.item(right_row)['values'])
        for in_id in edit_id:
            if new_val[in_id] != edit_entry_list[in_id].get():
                new_val[in_id] = edit_entry_list[in_id].get()

        tree.item(right_row, values=new_val)

        win.destroy()
Exemple #8
0
    def setID3Tag(self, tag, tagVal):
        if self.tagsID3 is None:
            self.findID3Tags()

        if self.tagsID3 is None:
            if self.debug:
                print("Could not set ID3 tag because tags are None")
            return

        if tag == "TXXX":
            try:
                self.tagsID3.add(TXXX(encoding=3, text=tagVal))
            except:
                raise ValueError(
                    "Could not set ID3 tag [{0}] to [{1}] for [{2}]".format(
                        tag, tagVal, self.mp3))
        else:
            try:
                self.tagsID3.getall(tag)[0].text[0] = tagVal
            except:
                raise ValueError(
                    "Could not set ID3 tag [{0}] to [{1}] for [{2}]".format(
                        tag, tagVal, self.mp3))

        if self.test is True:
            print("Not saving because test flag is True")
        else:
            try:
                self.tagsID3.save()
            except:
                raise ValueError("Could not save ID3 tags to {0}".format(
                    self.mp3))
Exemple #9
0
def add_mp3_tags(fileobj,
                 tags,
                 cover=None,
                 lyrics=None,
                 image_mimetype='image/png'):
    handle = MP3(fileobj=fileobj)
    if 'artist' in tags:
        handle['TPE1'] = TPE1(text=tags['artist'])
    if 'title' in tags:
        handle['TIT2'] = TIT2(text=tags['title'])
    if 'album' in tags:
        handle['TALB'] = TALB(text=tags['album'])
    if 'albumartist' in tags:
        handle['TPE2'] = TPE2(text=tags['albumartist'])
    if 'genre' in tags:
        handle['TCON'] = TCON(genres=[tags['genre']])
    if 'tracknumber' in tags:
        handle['TRCK'] = TRCK(text=tags['tracknumber'])
    if 'year' in tags:
        handle['TYER'] = TYER(text=tags['year'])
    if 'date' in tags:
        handle['TDAT'] = TDAT(text=tags['date'])
    if 'bpm' in tags:
        handle['TBPM'] = TBPM(text=tags['bpm'])
    if 'isrc' in tags:
        handle['TSRC'] = TSRC(text=tags['isrc'])
    if 'explicit' in tags:
        handle['TXXX'] = TXXX(text=tags['explicit'])
    if lyrics:
        handle['USLT'] = USLT(text=lyrics)
    if cover:
        handle['APIC'] = APIC(data=cover, mime=image_mimetype)
    handle.save(fileobj)
    fileobj.seek(0)
def testMutagen(logging, srcCompleteFileName):
    audio = MP3(srcCompleteFileName, ID3=EasyID3)
    logging.debug(audio.pprint())
    #         MPEG 1 layer 3, 160000 bps, 44100 Hz, 270.63 seconds (audio/mp3)
    #         album=Odyssey
    #         artist=Yngwie J. Malmsteen's Rising Force
    #         date=1988
    #         genre=Hard Rock
    #         length=270628
    #         media=DIG
    #         title=Faster Than The Speed Of Light
    #         tracknumber=10/12
    audio2 = ID3(srcCompleteFileName)
    #          {'TALB': TALB(encoding=3, text=['Odyssey']),
    #           'TMED': TMED(encoding=0, text=['DIG']),
    #           'TXXX:SZ_CARDIR': TXXX(encoding=3, desc='SZ_CARDIR', text=['001']),
    #           'TDRC': TDRC(encoding=3, text=['1988']),
    #           'TLEN': TLEN(encoding=0, text=['270628']),
    #           'TCON': TCON(encoding=3, text=['Hard Rock']),
    #           'TXXX:FMPS_RATING': TXXX(encoding=3, desc='FMPS_RATING', text=['0.4']),
    #           'TIT2': TIT2(encoding=3, text=['Faster Than The Speed Of Light']),
    #           'TPE1': TPE1(encoding=3, text=["Yngwie J. Malmsteen's Rising Force"]),
    #           'TRCK': TRCK(encoding=3, text=['10/12']) }
    #audio.add(TIT2(encoding=3, text=u"An example"))
    audio2.add(TXXX(encoding=3, desc='FMPS_Rating', text=u'0.4'))
    audio2.save()
    logging.info(audio2)
Exemple #11
0
    def tag(self, flac_filename, mp3_filename):
        flac = FLAC(flac_filename)
        id3 = ID3()
        involved_people = []
        for tag, value in flac.iteritems():
            if tag in self.tag_map:
                id3.add(self.tag_map[tag](encoding=3, text=value))
            elif tag in self.text_tag_map:
                id3.add(
                    TXXX(encoding=3, desc=self.text_tag_map[tag], text=value))
            elif tag == 'tracknumber':
                value[0] += self._total(flac, ['tracktotal', 'totaltracks'])
                id3.add(TRCK(encoding=3, text=value))
            elif tag == 'discnumber':
                value[0] += self._total(flac, ['disctotal', 'totaldiscs'])
                id3.add(TPOS(encoding=3, text=value))
            elif tag == 'musicbrainz_trackid':
                id3.add(UFID(u'http://musicbrainz.org', value[0]))
            elif tag in ('producer', 'engineer', 'arranger'):
                involved_people.extend((unicode(tag), v) for v in value)
            elif tag == 'mixer':
                involved_people.extend((u'mix', v) for v in value)
            elif tag == 'performer':
                id3.add(TMCL(encoding=3, people=self._performers(value)))
            elif tag not in [
                    'tracktotal',
                    'totaltracks',
                    'disctotal',
                    'totaldiscs',
                    'replaygain_album_gain',
                    'replaygain_album_peak',
                    'replaygain_track_gain',
                    'replaygain_track_peak',
                    # Don't know what to do with reference loudness - ignore it
                    'replaygain_reference_loudness',
                    # No mapping for mp3 - https://picard.musicbrainz.org/docs/mappings/
                    'originalyear',
                    # Drop CDDB disc id
                    'discid'
            ]:
                raise UnknownTag("%s=%s" % (tag, value))

        if involved_people:
            id3.add(TIPL(encoding=3, people=involved_people))

        self._replaygain(flac, id3, 'album')
        self._replaygain(flac, id3, 'track')

        for pic in flac.pictures:
            tag = APIC(encoding=3,
                       mime=pic.mime,
                       type=pic.type,
                       desc=pic.desc,
                       data=pic.data)
            id3.add(tag)

        id3.save(mp3_filename)
Exemple #12
0
    def _copy_replaygain_tag(self, ape, id3, tag_name, converter):
        if callable(converter):
            try:
                value = converter(str(ape[tag_name]))
            except ValueError:
                raise
        else:
            value = str(ape[tag_name])

        id3.add(TXXX(encoding=Id3Encoding.UTF8, desc=tag_name, text=value))
Exemple #13
0
 def writemd5(self):
     if self.fname and self.fsum:
         try:
             mp3 = ID3(self.fname)
             mp3.add(TXXX(encoding=3, desc=u'MD5', text=[self.fsum]))
             mp3.save()
         except mutagen.id3.ID3NoHeaderError:
             print "No Header Error: %s" % self.fname
             pass
         except IOError:
             print "Couldn't write header."
             pass
def syncMP3Ratings(mutID3, newFMPSRating):
    """
  This method resyncs FMPS_RATING to all files given. 
  It resyncs POPM (e.g Windows Media Player) and RATING (e.g. xbmc) tags to files 
  it is given that FMPS_RATING is set
  """
    changedTag = False
    newPopmRating = math.trunc(newFMPSRating * 255)
    try:
        curPOPMRating = mutID3.getall('POPM')[0].rating
        if curPOPMRating != newPopmRating:
            mutID3.delall('POPM')
            mutID3.add(POPM(rating=newPopmRating))
            changedTag = True
        else:
            logging.debug("POPM tag found and already synced: ")
    except (KeyError, IndexError) as e:
        logging.debug('POPM rating did not exist:  adding ... it')
        mutID3.add(POPM(rating=newPopmRating))
        changedTag = True

    # handle RATING
    newRATING = math.trunc(newFMPSRating * 5)
    try:
        curRATINGStr = mutID3.getall('TXXX:RATING')[0].text[0]
        curRATING = float(curRATINGStr)
        if curRATING != newRATING:
            mutID3.add(TXXX(encoding=3, desc='RATING', text=str(newRATING)))
            changedTag = True
        else:
            logging.debug("RATING found and already synced: ")
    except (KeyError, IndexError) as e:
        logging.debug('RATING rating did not exist:  adding ... it')
        mutID3.add(TXXX(encoding=3, desc='RATING', text=str(newRATING)))
        changedTag = True
    if changedTag:
        mutID3.save()
Exemple #15
0
 def copy_replaygain_tag(self, apev2, id3, name, converter=None):
     self.log.debug("processing '%s' tag" % name)
     if name not in apev2:
         self.log.info("no APEv2 '%s' tag found, skipping tag" % name)
         return False
     if not self.force and ("TXXX:%s" % name) in id3:
         self.log.info("ID3 '%s' tag already exists, skpping tag" % name)
         return False
     value = str(apev2[name])
     if callable(converter):
         self.log.debug("converting APEv2 '%s' tag from '%s'" %
                        (name, value))
         try:
             value = converter(value)
         except ValueError:
             self.log.warning("invalid value for APEv2 '%s' tag" % name)
             return False
         self.log.debug("converted APEv2 '%s' tag to '%s'" % (name, value))
     id3.add(TXXX(encoding=1, desc=name, text=value))
     self.log.info("added ID3 '%s' tag with value '%s'" % (name, value))
     return True
def setRatingForFiles(filesToProcessDict, newFMPSRating):
    for curFile in filesToProcessDict:
        logging.info("set rating for " + curFile['srcCompleteFileName'] +
                     " to " + str(newFMPSRating))
        mutID3 = ID3(curFile['srcCompleteFileName'])
        changedTag = False
        curFMPSRating = mutID3.get(u'TXXX:FMPS_Rating')
        if curFMPSRating == None:
            # No existing tag TXXX for FMPS has been found, so create one...
            logging.debug("no FMPS_RATING found: " +
                          os.path.basename(curFile['srcCompleteFileName']))
            mutID3.add(
                TXXX(encoding=3,
                     desc=u"FMPS_Rating",
                     text=[str(newFMPSRating)]))
            changedTag = True
        else:
            newFMPSRating = float(curFMPSRating[0])
        syncMP3Ratings(mutID3, newFMPSRating)
        if changedTag:
            mutID3.save()
Exemple #17
0
    def metadata_mp3_mutagen(self, path, media):

        from mutagen.mp3 import MP3
        from mutagen.id3 import ID3, TRCK, TIT2, TPE1, TALB, TCON, TXXX, UFID, TSRC, TPUB, TMED, TRCK, TDRC, APIC

        try:
            tags = ID3(path)
        except Exception:
            """
            kindf of hackish - mutagen does complain if no id3 headers - so just create some
            """
            audio = MP3(path)
            audio["TIT2"] = TIT2(encoding=3, text=["Empty Title"])
            audio.save()
            tags = ID3(path)

        # reset tags
        tags.delete()

        # user data
        if INCLUDE_USER and self.user:
            tags.add(
                TXXX(encoding=3,
                     desc='open broadcast user',
                     text=u'%s' % self.user.email))

        # track-level metadata
        tags.add(TIT2(encoding=3, text=u'%s' % media.name))
        tags.add(
            UFID(encoding=3,
                 owner='https://openbroadcast.org',
                 data=u'%s' % media.uuid))

        tags.add(
            TXXX(encoding=3,
                 desc='open broadcast API',
                 text=u'https://%s%s' %
                 (self.current_site.domain, media.get_api_url())))
        # remove genre
        tags.add(TCON(encoding=3, text=u''))
        tags.add(TMED(encoding=3, text=u'Digital Media'))
        if media.tracknumber:
            tags.add(TRCK(encoding=3, text=u'%s' % media.tracknumber))
        if media.isrc:
            tags.add(TSRC(encoding=3, text=u'%s' % media.isrc))

        if uuid_by_object(media, 'musicbrainz'):
            tags.add(
                UFID(encoding=3,
                     owner='http://musicbrainz.org',
                     data=u'%s' % uuid_by_object(media, 'musicbrainz')))

        # release-level metadata
        if media.release:
            tags.add(TALB(encoding=3, text=u'%s' % media.release.name))
            if media.release.catalognumber:
                tags.add(
                    TXXX(encoding=3,
                         desc='CATALOGNUMBER',
                         text=u'%s' % media.release.catalognumber))
            if media.release.releasedate:
                tags.add(
                    TDRC(encoding=3,
                         text=u'%s' % media.release.releasedate.year))
            if media.release.release_country:
                tags.add(
                    TXXX(encoding=3,
                         desc='MusicBrainz Album Release Country',
                         text=u'%s' % media.release.release_country.iso2_code))
            if media.release.totaltracks and media.tracknumber:
                tags.add(
                    TRCK(encoding=3,
                         text=u'%s/%s' %
                         (media.tracknumber, media.release.totaltracks)))
            if media.release.releasedate:
                tags.add(
                    TDRC(encoding=3,
                         text=u'%s' % media.release.releasedate.year))
            if uuid_by_object(media.release, 'musicbrainz'):
                tags.add(
                    TXXX(encoding=3,
                         desc='MusicBrainz Album Id',
                         text=u'%s' %
                         uuid_by_object(media.release, 'musicbrainz')))

            if media.release and media.release.main_image and os.path.exists(
                    media.release.main_image.path):

                opt = dict(size=(300, 300), crop=True, bw=False, quality=80)

                try:
                    image = get_thumbnailer(
                        media.release.main_image).get_thumbnail(opt)
                    tags.add(
                        APIC(encoding=3,
                             mime='image/jpeg',
                             type=3,
                             desc=u'Cover',
                             data=open(image.path).read()))
                except:
                    pass

        # artist-level metadata
        if media.artist:
            tags.add(TPE1(encoding=3, text=u'%s' % media.artist.name))
            if uuid_by_object(media.artist, 'musicbrainz'):
                tags.add(
                    TXXX(encoding=3,
                         desc='MusicBrainz Artist Id',
                         text=u'%s' %
                         uuid_by_object(media.artist, 'musicbrainz')))

        # label-level metadata
        if media.release and media.release.label:
            tags.add(TPUB(encoding=3, text=u'%s' % media.release.label.name))

        tags.save(v1=0)

        return
Exemple #18
0
    def _save_db_to_id3v2(self, pathSong, dbrating, dbcount):
        """ Save rating and playcount from Rhythmbox db to standard ID3v2 tags
        
        POPM stand for Popularimeter, we use Banshee ratings standard (which is also an ID3v2 standard,
        meaning a value between 0 and 255). (should eventually be deprecated)
        (see http://www.id3.org/id3v2.4.0-frames section 4.16 )
        
        TXXX:FMPS_Rating and TXXX:FMPS_Playcount are from the FMPS freedesktop specs
        (see  http://www.freedesktop.org/wiki/Specifications/free-media-player-specs)
        
        """
        audio = ID3(pathSong)
        # Instead of having two I/O operations each time,
        # we can get only one I/O operation when rating AND playcount haven't changed
        # We use needsave boolean to do that
        needsave = False

        if self.ratingsenabled:
            if dbrating > 0:
                # First we store it in POPM format

                ########### POPM (will be deprecated eventually) #######
                popmrating = audio.get('POPM:Banshee')
                if popmrating == None:
                    # No existing tag POPM has been found, so create one...
                    audio.add(POPM(email=u'Banshee',
                                   rating=int(51 * dbrating)))
                    needsave = True
                else:
                    # An existing tag POPM has been found, let's check if the rating has changed
                    if self._convert_ID3v2_rating_to_rhythmbdb_rating(
                            popmrating.rating) != dbrating:
                        # If it has, erase the value of the file an replace it with the db value (converted)
                        audio.delall('POPM:Banshee')
                        audio.add(
                            POPM(email=u'Banshee', rating=int(51 * dbrating)))
                        needsave = True
                ####################################################

                ############# TXXX #################################
                fmpsrating = audio.get(u'TXXX:FMPS_Rating')
                if fmpsrating == None:
                    # No existing tag TXXX for FMPS has been found, so create one...
                    audio.add(
                        TXXX(encoding=3,
                             desc=u"FMPS_Rating",
                             text=[unicode(0.2 * dbrating)]))
                    needsave = True
                else:
                    # An existing tag TXXX for FMPS has been found, let's check if the rating has changed
                    if self._convert_fmps_rating_to_rhythmbdb_rating(
                            fmpsrating.text[0]) != dbrating:
                        # If it has, erase the value of the file and replace it with the db value (converted)
                        audio.delall(u'TXXX:FMPS_Rating')
                        audio.add(
                            TXXX(encoding=3,
                                 desc=u"FMPS_Rating",
                                 text=[unicode(0.2 * dbrating)]))
                        needsave = True
                #######################################################

        if self.playcountsenabled:
            if dbcount > 0:

                ######### TXXX ############
                fmpsplaycount = audio.get(u'TXXX:FMPS_Playcount')
                if fmpsplaycount == None:
                    # No existing tag TXXX for FMPS has been found, so create one...
                    audio.add(
                        TXXX(encoding=3,
                             desc=u"FMPS_Playcount",
                             text=[unicode(1.0 * dbcount)]))
                    needsave = True
                else:
                    # An existing tag TXXX for FMPS has been found, let's check if the playcount has changed
                    if float(fmpsplaycount.text[0]) != dbcount:
                        # If it has, erase the value of the file and replace it with the db value (converted)
                        audio.delall(u'TXXX:FMPS_Playcount')
                        audio.add(
                            TXXX(encoding=3,
                                 desc=u"FMPS_Playcount",
                                 text=[unicode(1.0 * dbcount)]))
                        needsave = True
                ############################

        if needsave:
            # save to file only if needed
            audio.save()
            self.num_saved += 1
        else:
            self.num_already_done += 1
Exemple #19
0
 def test_multi_TXXX(self):
     from mutagen.id3 import TXXX
     self.assertEquals(TXXX(encoding=0, text="a").HashKey, TXXX(encoding=0, text="b").HashKey)
     self.assertNotEquals(TXXX(encoding=0, desc="a").HashKey, TXXX(encoding=0, desc="b").HashKey)
Exemple #20
0
    # ---------------
    # Alter metadata.
    # ---------------
    if not arguments.test:
        track, tracks = 0, len(collection)  # type: int, int
        for file in collection:
            if file.album:
                path = arguments.parent / arguments.repository.capitalize(
                ) / file.dst
                if path.exists():
                    audio_file = File(path)
                    tag = audio_file.tags
                    track += 1

                    if arguments.extension == "flac":
                        tag["album"] = file.album
                        tag["tracknumber"] = str(track)
                        tag["tracktotal"] = str(tracks)
                        with suppress(MutagenError):
                            audio_file.save()

                    elif arguments.extension == "mp3":
                        tag.add(TALB(text=file.album))
                        tag.add(TRCK(text=str(track)))
                        tag.add(
                            TXXX(description="TOTALTRACKS", text=str(tracks)))
                        with suppress(MutagenError):
                            audio_file.save()

    sys.exit(count)
Exemple #21
0
 def __init_id3_tags(id3, major=3):
     """
     Attributes:
         id3 ID3 Tag object
         major ID3 major version, e.g.: 3 for ID3v2.3
     """
     from mutagen.id3 import TRCK, TPOS, TXXX, TPUB, TALB, UFID, TPE2, \
         TSO2, TMED, TIT2, TPE1, TSRC, IPLS, TORY, TDAT, TYER
     id3.add(TRCK(encoding=major, text="1/10"))
     id3.add(TPOS(encoding=major, text="1/1"))
     id3.add(
         TXXX(encoding=major,
              desc="MusicBrainz Release Group Id",
              text="e00305af-1c72-469b-9a7c-6dc665ca9adc"))
     id3.add(TXXX(encoding=major, desc="originalyear", text="2011"))
     id3.add(
         TXXX(encoding=major, desc="MusicBrainz Album Type", text="album"))
     id3.add(
         TXXX(encoding=major,
              desc="MusicBrainz Album Id",
              text="e7050302-74e6-42e4-aba0-09efd5d431d8"))
     id3.add(TPUB(encoding=major, text="J&R Adventures"))
     id3.add(TXXX(encoding=major, desc="CATALOGNUMBER", text="PRAR931391"))
     id3.add(TALB(encoding=major, text="Don\'t Explain"))
     id3.add(
         TXXX(encoding=major,
              desc="MusicBrainz Album Status",
              text="official"))
     id3.add(TXXX(encoding=major, desc="SCRIPT", text="Latn"))
     id3.add(
         TXXX(encoding=major,
              desc="MusicBrainz Album Release Country",
              text="US"))
     id3.add(TXXX(encoding=major, desc="BARCODE", text="804879313915"))
     id3.add(
         TXXX(encoding=major,
              desc="MusicBrainz Album Artist Id",
              text=[
                  "3fe817fc-966e-4ece-b00a-76be43e7e73c",
                  "984f8239-8fe1-4683-9c54-10ffb14439e9"
              ]))
     id3.add(TPE2(encoding=major, text="Beth Hart & Joe Bonamassa"))
     id3.add(TSO2(encoding=major, text="Hart, Beth & Bonamassa, Joe"))
     id3.add(TXXX(encoding=major, desc="ASIN", text="B005NPEUB2"))
     id3.add(TMED(encoding=major, text="CD"))
     id3.add(
         UFID(encoding=major,
              owner="http://musicbrainz.org",
              data=b"f151cb94-c909-46a8-ad99-fb77391abfb8"))
     id3.add(TIT2(encoding=major, text="Sinner's Prayer"))
     id3.add(
         TXXX(encoding=major,
              desc="MusicBrainz Artist Id",
              text=[
                  "3fe817fc-966e-4ece-b00a-76be43e7e73c",
                  "984f8239-8fe1-4683-9c54-10ffb14439e9"
              ]))
     id3.add(TPE1(encoding=major, text=["Beth Hart & Joe Bonamassa"]))
     id3.add(
         TXXX(encoding=major,
              desc="Artists",
              text=["Beth Hart", "Joe Bonamassa"]))
     id3.add(TSRC(encoding=major, text=["NLB931100460", "USMH51100098"]))
     id3.add(
         TXXX(encoding=major,
              desc="MusicBrainz Release Track Id",
              text="d062f484-253c-374b-85f7-89aab45551c7"))
     id3.add(
         IPLS(encoding=major,
              people=[["engineer", "James McCullagh"],
                      ["engineer",
                       "Jared Kvitka"], ["arranger", "Jeff Bova"],
                      ["producer", "Roy Weisman"], ["piano", "Beth Hart"],
                      ["guitar", "Blondie Chaplin"],
                      ["guitar", "Joe Bonamassa"],
                      ["percussion", "Anton Fig"], ["drums", "Anton Fig"],
                      ["keyboard", "Arlan Schierbaum"],
                      ["bass guitar", "Carmine Rojas"],
                      ["orchestra", "The Bovaland Orchestra"],
                      ["vocals", "Beth Hart"], ["vocals",
                                                "Joe Bonamassa"]])),
     id3.add(TORY(encoding=major, text="2011"))
     id3.add(TYER(encoding=major, text="2011"))
     id3.add(TDAT(encoding=major, text="2709"))
Exemple #22
0
 def test_TXXX(self):
     from mutagen.id3 import TXXX
     self.assert_(isinstance(TXXX(encoding=0, desc='d',text='text'), TXXX))
Exemple #23
0
    lambda amsong: TALB(text=amsong.album_name),
    "isrc":
    lambda amsong: TSRC(text=amsong.isrc),
    "record_label":
    lambda amsong: TPUB(text=amsong.album.record_label)
    if amsong.album.record_label else None,
    "copyright":
    lambda amsong: TCOP(text=amsong.album.copyright),
    "genre":
    lambda amsong: TCON(text=amsong.genres[0]),
    "album_artist":
    lambda amsong: TPE2(text=amsong.album.artist_name),
    "song_artist":
    lambda amsong: TPE1(text=amsong.artist_name),
    "itunes_advisory":
    lambda amsong: TXXX(desc="ITUNESADVISORY", text="1")
    if amsong.is_explicit else None,
    "release_date":
    lambda amsong: TDRC(text=amsong.release_date),
    "artwork":
    lambda amsong: APIC(mime='image/jpeg',
                        desc='cover',
                        data=amsong.get_artwork(prefer_album=True)),
    "disc_position":
    lambda amsong: TPOS(text=amsong.disc_number)
    if '/' in str(amsong.disc_number) else None,
    "track_position":
    lambda amsong: TRCK(text=
                        f"{amsong.track_number}/{amsong.album.track_count}")
}
ERROR_MSG = "--> For '{song}' failed tagging: {tags}"
Exemple #24
0
    def update_id3(self, path: str, track: beatport.Track):
        #AIFF Check
        aiff = None
        if path.endswith('.aiff') or path.endswith('.aif'):
            aiff = AIFF(path)
            f = aiff.tags
        else:
            f = ID3()
            f.load(path, v2_version=3, translate=True)

        #Update tags
        if UpdatableTags.title in self.config.update_tags and self.config.overwrite:
            f.setall('TIT2', [TIT2(text=track.title)])
        if UpdatableTags.artist in self.config.update_tags and self.config.overwrite:
            f.setall('TPE1', [
                TPE1(text=self.config.artist_separator.join(
                    [a.name for a in track.artists]))
            ])
        if UpdatableTags.album in self.config.update_tags and (
                self.config.overwrite or len(f.getall('TALB')) == 0):
            f.setall('TALB', [TALB(text=track.album.name)])
        if UpdatableTags.label in self.config.update_tags and (
                self.config.overwrite or len(f.getall('TPUB')) == 0):
            f.setall('TPUB', [TPUB(text=track.label.name)])
        if UpdatableTags.bpm in self.config.update_tags and (
                self.config.overwrite or len(f.getall('TBPM')) == 0):
            f.setall('TBPM', [TBPM(text=str(track.bpm))])
        if UpdatableTags.genre in self.config.update_tags and (
                self.config.overwrite or len(f.getall('TCON')) == 0):
            f.setall('TCON',
                     [TCON(text=', '.join([g.name for g in track.genres]))])

        #Dates
        if UpdatableTags.date in self.config.update_tags:
            #ID3 v2.3
            if self.config.id3v23 and (self.config.overwrite or
                                       (len(f.getall('TYER')) == 0
                                        and len(f.getall('TDAT')) == 0)):
                date = track.release_date.strftime('%d%m')
                f.setall('TDRC', [])
                f.setall('TDAT', [TDAT(text=date)])
                f.setall('TYER', [TYER(text=str(track.release_date.year))])
            #ID3 v2.4
            if not self.config.id3v23 and (self.config.overwrite
                                           or len(f.getall('TDRC')) == 0):
                date = track.release_date.strftime('%Y-%m-%d')
                f.setall('TDAT', [])
                f.setall('TYER', [])
                f.setall('TDRC', [TDRC(text=date)])

        if UpdatableTags.key in self.config.update_tags and (
                self.config.overwrite or len(f.getall('TKEY')) == 0):
            f.setall('TKEY', [TKEY(text=track.id3key())])
        if UpdatableTags.publishdate in self.config.update_tags and (
                self.config.overwrite or len(f.getall('TDRL')) == 0):
            # f.setall('TORY', [TORY(text=str(track.publish_date.year))])
            if not self.config.id3v23:
                date = track.publish_date.strftime('%Y-%m-%d')
                f.setall('TDRL', [TDRL(text=date)])

        #Other keys
        if UpdatableTags.other in self.config.update_tags:
            f.add(TXXX(desc='WWWAUDIOFILE', text=track.url()))
            f.add(TXXX(desc='WWWPUBLISHER', text=track.label.url('label')))

        #Redownlaod cover
        if self.config.replace_art:
            try:
                url = track.art(self.config.art_resolution)
                r = requests.get(url)
                data = APIC(encoding=3,
                            mime='image/jpeg',
                            type=3,
                            desc=u'Cover',
                            data=r.content)
                f.delall('APIC')
                f['APIC:cover.jpg'] = data

            except Exception:
                logging.warning('Error downloading cover for file: ' + path)

        if aiff == None:
            if self.config.id3v23:
                f.save(path, v2_version=3, v1=0)
            else:
                f.save(path, v2_version=4, v1=0)
        else:
            aiff.save()
def TaggerWriteData(files, discogs):

    # label
    label = discogs['json'].get('labels')[0]['name']

    # country
    country = discogs['json'].get('country')

    if country is None:
        country = ''

    # date
    date = discogs['json'].get('released')

    if date is not None:
        date = [date.replace('-', '/').replace('/00', '/01')]

    # genres
    genres = UtilsArrayToString(discogs['json'].get('genres'))

    # styles
    styles = UtilsArrayToString(discogs['json'].get('styles'))

    for file in files:
        try:
            file_extension = file.rsplit('.', 1)[1]

            if file_extension == 'flac':
                f = FLAC(file)

                f['organization'] = label
                f['composer'] = genres
                f['genre'] = styles
                if date is not None: f['date'] = date
                f['country'] = country
                f['custom'] = ENV_TAGGING_DONE + ' ' + f['custom'][0]

                f.save()

                print(f['tracknumber'][0] + ' done')

            if file_extension == 'mp3':
                f = EasyID3(file)

                f['organization'] = label
                f['composer'] = genres
                f['genre'] = styles
                if date is not None: f['date'] = date

                f.save()

                f2 = ID3(file)

                f2.add(TXXX(
                    desc=u'country',
                    text=[country],
                ))

                f2.add(
                    TXXX(desc=u'Custom',
                         text=[
                             str(ENV_TAGGING_DONE + ' ' +
                                 str(f2.get('TXXX:Custom')))
                         ]))

                f2.save()

                print(f['tracknumber'][0] + ' done')
        except:
            print(style.red(ENV_ERROR_TAGGING))
            continue
Exemple #26
0
def CopyTagsToTranscodedFileMp3(losslessFile, lossyFile):  
    # Because the input flac file is decoded to wav, all metadata is lost. We have to extract this metadata from 
    # the flac file and put it directly into the generated mp3 file.
    from mutagen.flac import FLAC
    from mutagen.id3 import ID3   
    
    flacFile = FLAC(losslessFile)
    flacFileTags = flacFile.tags 
          
    mp3File = ID3(lossyFile)    
    mp3File.delete()    
        
    for key,value in flacFileTags.items():
        if key == 'title': 
            from mutagen.id3 import TIT2
            mp3File.add(TIT2(encoding=3, text=value)) 
        elif key == 'album': 
            from mutagen.id3 import TALB
            mp3File.add(TALB(encoding=3, text=value))
        elif key == 'artist': 
            from mutagen.id3 import TPE1
            mp3File.add(TPE1(encoding=3, text=value)) 
        elif key == 'tracknumber': 
            from mutagen.id3 import TRCK
            mp3File.add(TRCK(encoding=3, text=value))
        elif key == 'date': 
            from mutagen.id3 import TDRC
            mp3File.add(TDRC(encoding=3, text=value))
        elif key == 'genre': 
            from mutagen.id3 import TCON
            mp3File.add(TCON(encoding=3, text=value))
        elif key == 'discnumber': 
            from mutagen.id3 import TPOS
            mp3File.add(TPOS(encoding=3, text=value))
        elif key == 'composer': 
            from mutagen.id3 import TCOM
            mp3File.add(TCOM(encoding=3, text=value))
        elif key == 'conductor': 
            from mutagen.id3 import TPE3
            mp3File.add(TPE3(encoding=3, text=value))
        elif key == 'ensemble': 
            from mutagen.id3 import TPE2
            mp3File.add(TPE2(encoding=3, text=value))      
        elif key == 'comment': 
            from mutagen.id3 import COMM
            mp3File.add(COMM(encoding=3, text=value))
        elif key == 'publisher': 
            from mutagen.id3 import TPUB
            mp3File.add(TPUB(encoding=3, text=value))
        elif key == 'opus': 
            from mutagen.id3 import TIT3
            mp3File.add(TIT3(encoding=3, text=value))
        elif key == 'sourcemedia': 
            from mutagen.id3 import TMED
            mp3File.add(TMED(encoding=3, text=value))
        elif key == 'isrc': 
            from mutagen.id3 import TSRC
            mp3File.add(TSRC(encoding=3, text=value))
        elif key == 'license': 
            from mutagen.id3 import TOWN
            mp3File.add(TOWN(encoding=3, text=value))
        elif key == 'copyright': 
            from mutagen.id3 import WCOP
            mp3File.add(WCOP(encoding=3, text=value))
        elif key == 'encoded-by': 
            from mutagen.id3 import TENC
            mp3File.add(TENC(encoding=3, text=value))
        elif (key == 'part' or key == 'partnumber'): 
            from mutagen.id3 import TIT3
            mp3File.add(TIT3(encoding=3, text=value))
        elif (key == 'lyricist' or key == 'textwriter'): 
            from mutagen.id3 import TIT3
            mp3File.add(TIT3(encoding=3, text=value))
        else: 
            from mutagen.id3 import TXXX
            mp3File.add(TXXX(encoding=3, text=value, desc=key))        
      
        mp3File.update_to_v24()
        mp3File.save() 
      
    return
Exemple #27
0
def one_to_one_conversion_txxx(flac_frame_name, desc):
    return (flac_frame_name, lambda mp3, flac: mp3.text[0] == flac,
            lambda str: [TXXX(encoding=3, desc=desc, text=str)])
Exemple #28
0
def _audio_txxx(atuple):
    audio, atag, _, _ = atuple
    param = ast.literal_eval(atag)
    audio.add(TXXX(param[0], param[1], param[2]))
Exemple #29
0
def copyTagsToTranscodedFileMp3(losslessFile, lossyFile):
    #
    # Copy the tags from the losslessFile (.flac) to the lossyFile.
    # All previous tags from the lossyFile will be deleted before the
    # tags from the losslessFile are copied.
    #
    from mutagen.flac import FLAC
    from mutagen.id3 import ID3

    # Read all tags from the flac file
    flacFile = FLAC(losslessFile)
    flacFileTags = flacFile.tags  # Returns a dictionary containing the flac tags

    # Only mp3 files with ID3 headers can be openend.
    # So be sure to add some tags during encoding .wav. to mp3

    # Mapping from Vorbis comments field recommendations to id3v2_4_0
    # For more information about vorbis field recommendations: http://reactor-core.org/ogg-tagging.html
    # For more information about id3v2_4_0 frames: http://www.id3.org/id3v2.4.0-frames
    #
    # Single value tags:
    #  ALBUM              -> TALB
    #  ARTIST             -> TPE1
    #  PUBLISHER          -> TPUB
    #  COPYRIGHT          -> WCOP
    #  DISCNUMBER         -> TPOS
    #  ISRC               -> TSRC
    #  EAN/UPN
    #  LABEL
    #  LABELNO
    #  LICENSE             -> TOWN
    #  OPUS                -> TIT3
    #  SOURCEMEDIA         -> TMED
    #  TITLE               -> TIT2
    #  TRACKNUMBER         -> TRCK
    #  VERSION
    #  ENCODED-BY          -> TENC
    #  ENCODING
    # Multiple value tags:
    #  COMPOSER            -> TCOM
    #  ARRANGER
    #  LYRICIST            -> TEXT
    #  AUTHOR              -> TEXT
    #  CONDUCTOR           -> TPE3
    #  PERFORMER           ->
    #  ENSEMBLE            -> TPE2
    #  PART                -> TIT1
    #  PARTNUMBER          -> TIT1
    #  GENRE               -> TCON
    #  DATE                -> TDRC
    #  LOCATION
    #  COMMENT             -> COMM
    # Other vorbis tags are mapped to TXXX tags

    mp3File = ID3(lossyFile)
    mp3File.delete()

    for key, value in flacFileTags.items():
        if key == 'title':
            # Map to TIT2 frame
            from mutagen.id3 import TIT2
            mp3File.add(TIT2(encoding=3, text=value))
        elif key == 'album':
            # Map to TALB frame
            from mutagen.id3 import TALB
            mp3File.add(TALB(encoding=3, text=value))
        elif key == 'artist':
            # Map to TPE1 frame
            from mutagen.id3 import TPE1
            mp3File.add(TPE1(encoding=3, text=value))
        elif key == 'tracknumber':
            # Map to TRCK frame
            from mutagen.id3 import TRCK
            mp3File.add(TRCK(encoding=3, text=value))
        elif key == 'date':
            # Map to TDRC frame
            from mutagen.id3 import TDRC
            mp3File.add(TDRC(encoding=3, text=value))
        elif key == 'genre':
            # Map to TCON frame
            from mutagen.id3 import TCON
            mp3File.add(TCON(encoding=3, text=value))
        elif key == 'discnumber':
            # Map to TPOS frame
            from mutagen.id3 import TPOS
            mp3File.add(TPOS(encoding=3, text=value))
        elif key == 'composer':
            # Map to TCOM frame
            from mutagen.id3 import TCOM
            mp3File.add(TCOM(encoding=3, text=value))
        elif key == 'conductor':
            # Map to TPE3 frame
            from mutagen.id3 import TPE3
            mp3File.add(TPE3(encoding=3, text=value))
        elif key == 'ensemble':
            # Map to TPE2 frame
            from mutagen.id3 import TPE2
            mp3File.add(TPE2(encoding=3, text=value))
        elif key == 'comment':
            # Map to COMM frame
            from mutagen.id3 import COMM
            mp3File.add(COMM(encoding=3, text=value))
        elif key == 'publisher':
            # Map to TPUB frame
            from mutagen.id3 import TPUB
            mp3File.add(TPUB(encoding=3, text=value))
        elif key == 'opus':
            # Map to TIT3 frame
            from mutagen.id3 import TIT3
            mp3File.add(TIT3(encoding=3, text=value))
        elif key == 'sourcemedia':
            # Map to TMED frame
            from mutagen.id3 import TMED
            mp3File.add(TMED(encoding=3, text=value))
        elif key == 'isrc':
            # Map to TSRC frame
            from mutagen.id3 import TSRC
            mp3File.add(TSRC(encoding=3, text=value))
        elif key == 'license':
            # Map to TOWN frame
            from mutagen.id3 import TOWN
            mp3File.add(TOWN(encoding=3, text=value))
        elif key == 'copyright':
            # Map to WCOP frame
            from mutagen.id3 import WCOP
            mp3File.add(WCOP(encoding=3, text=value))
        elif key == 'encoded-by':
            # Map to TENC frame
            from mutagen.id3 import TENC
            mp3File.add(TENC(encoding=3, text=value))
        elif (key == 'part' or key == 'partnumber'):
            # Map to TIT3 frame
            from mutagen.id3 import TIT3
            mp3File.add(TIT3(encoding=3, text=value))
        elif (key == 'lyricist' or key == 'textwriter'):
            # Map to TEXT frame
            from mutagen.id3 import TIT3
            mp3File.add(TIT3(encoding=3, text=value))
        else:  #all other tags are mapped to TXXX frames
            # Map to TXXX frame
            from mutagen.id3 import TXXX
            mp3File.add(TXXX(encoding=3, text=value, desc=key))

        mp3File.update_to_v24()
        mp3File.save()

    return