Exemple #1
0
 def printDistinctLocalTags(self):
     if (len(self.localTagLibrary) == 0):
         return
     disptags = []
     for localtag in self.localTagLibrary:
         disptags.append((self.localTagLibrary[localtag]['disp'], self.localTagLibrary[localtag]['localhits']))
     common.safeStdout('\nDistinct Update-stream Tags (most to least frequent, in your library): \n\t'+'\n\t'.join(map(lambda pair: pair[0]+' ('+str(pair[1])+')', common.sortWeightedTagTuples(disptags))))
Exemple #2
0
 def printDistinctLastTags(self):
     if (len(self.lastTagLibrary) == 0):
         return
     disptags = []
     for lasttag in self.lastTagLibrary:
         disptags.append((lasttag, self.lastTagLibrary[lasttag]))
     common.safeStdout('\nDistinct In-library LastFM Tags (most to least popular, on LastFM): \n\t'+'\n\t'.join(map(lambda pair: pair[0]+' ('+str(pair[1])+')', common.sortWeightedTagTuples(disptags))))
Exemple #3
0
 def fetchTrackTags(self, lastfm):
     verbose = self.config.getboolean('verbose')
     refetch = self.config.getboolean('refetchCachedTags')
     minWeight = self.config.getint('minTrackTagWeight')
     niceness = self.config.getint('niceness') / 1000
     maxTagsToSave = self.config.getint('getTrackTags')
     if (maxTagsToSave <= 0):
         return
     
     print 'Fetching track tags from LastFM'
     for artist in sorted(self.mediaLibrary):
         for album in sorted(self.mediaLibrary[artist]['albums']):
             for track in sorted(self.mediaLibrary[artist]['albums'][album]['tracks']):
                 tagpairs = self.mediaLibrary[artist]['albums'][album]['tracks'][track]['tags']
                 if (tagpairs is not None and refetch is False):                    
                     if (verbose):
                         common.safeStdout('\tSkipping already-tagged track ['+artist+':'+track+']')
                     continue
                 tagpairs = lastfm.fetchTrackTags(artist, track, maxTagsToSave, minWeight)
                 if (tagpairs is not None):
                     map(self.addToLastFMTagLibrary, map(lambda pair: pair[0], tagpairs))
                     if (verbose):
                         common.safeStdout('\tFetched ['+artist+':'+track+'] ('+', '.join(map(lambda pair: pair[0], tagpairs))+')')
                 self.mediaLibrary[artist]['albums'][album]['tracks'][track]['tags'] = tagpairs 
                 time.sleep(niceness)
Exemple #4
0
    def updateTags(self, filename, tagPayload):
        try:
            mediawrapper = self.getMediawrapper(filename)

            for bucket in tagPayload:
                tagPayload[bucket] = self.tagSep.join(
                    tagPayload[bucket][0:self.maxTags[bucket]])

            if (isinstance(mediawrapper, ID3)):
                return self.updateTagsHelperID3(mediawrapper, tagPayload,
                                                self.formatFieldMap['id3'])
            elif (isinstance(mediawrapper, MP4)):
                return self.updateTagsHelper(mediawrapper, tagPayload,
                                             self.formatFieldMap['mp4'])
            elif (isinstance(mediawrapper, OggVorbis)):
                return self.updateTagsHelper(mediawrapper, tagPayload,
                                             self.formatFieldMap['oggvorbis'])
            elif (isinstance(mediawrapper, FLAC)):
                return self.updateTagsHelper(mediawrapper, tagPayload,
                                             self.formatFieldMap['flac'])
            else:
                common.safeStdout(
                    'Skipping unknown/incompatible media file type [' +
                    filename + ']')
        except Exception, err:
            common.safeStderr('Error seen during update processing: ' +
                              str(err))
Exemple #5
0
    def extractMetadata(self, filename):
        try:
            mediawrapper = self.getMediawrapper(filename)

            if (isinstance(mediawrapper, ID3)):
                return self.extractMetadataHelper(mediawrapper,
                                                  self.formatFieldMap['id3'],
                                                  filename)
            elif (isinstance(mediawrapper, MP4)):
                return self.extractMetadataHelper(mediawrapper,
                                                  self.formatFieldMap['mp4'],
                                                  filename)
            elif (isinstance(mediawrapper, OggVorbis)):
                return self.extractMetadataHelper(
                    mediawrapper, self.formatFieldMap['oggvorbis'], filename)
            elif (isinstance(mediawrapper, FLAC)):
                return self.extractMetadataHelper(mediawrapper,
                                                  self.formatFieldMap['flac'],
                                                  filename)
            else:
                if (self.config.getboolean('verbose')):
                    common.safeStdout(
                        '\tSkipping unknown/incompatible media file type [' +
                        filename + ']')
        except Exception, err:
            common.safeStderr('Error seen during media reading: ' + str(err))
Exemple #6
0
 def readMedia(self):
     mediadir = self.config.get('mediaDir')
     verbose = self.config.getboolean('verbose')
     skipExtensions = map(lambda x: '.'+x.lower().strip(), self.config.get('skipExtensions').split(','))
     
     common.safeStdout('Reading existing metadata from ['+mediadir+']')
     numfiles = 0
     for root, dirs, files in os.walk(mediadir):
         for filename in files:
             fname, ext = os.path.splitext(filename.lower())
             if (ext is not None and ext in skipExtensions):
                 continue                
             metadata = self.mediaHelper.extractMetadata(os.path.join(root, filename))
             if (metadata is None or len(metadata['artists']) == 0 or metadata['album'] is None or metadata['track'] is None):
                 continue
             for artist in metadata['artists']:                        
                 self.addToMediaLibrary(artist, metadata['album'], metadata['track'])
             numfiles += 1
             if (verbose):
                 common.safeStdout('\tProcessed: '+os.path.join(root, filename))
     print 'Read ['+str(numfiles)+'] media files'            
Exemple #7
0
 def printLibrary(self):
     for artist in self.mediaLibrary:
         print common.safeStdout(artist + ' ('+ ', '.join(map(lambda pair: pair[0], self.mediaLibrary[artist]['tags'] or [])) + ')')
         for album in self.mediaLibrary[artist]['albums']:
             print common.safeStdout('\t'+album)
             for track in self.mediaLibrary[artist]['albums'][album]['tracks']:
                 print common.safeStdout('\t\t'+track + ' ('+ ', '.join(map(lambda pair: pair[0], self.mediaLibrary[artist]['albums'][album]['tracks'][track]['tags'] or [])) + ')')                        
Exemple #8
0
    def updateTags(self):
        ''' This pushes the tags back into the underlying media files '''
        verbose             = self.config.getboolean('verbose')
        mediadir            = self.config.get('mediaDir')
        startDelim          = self.config.get('tagStartDelim')
        endDelim            = self.config.get('tagEndDelim')
        artistTagFields     = set(map(string.strip, self.config.get('artistTagFields').lower().split(',')))
        trackTagFields      = set(map(string.strip, self.config.get('trackTagFields').lower().split(',')))
        touchedFields       = artistTagFields.union(trackTagFields)
        skipExtensions      = map(lambda x: '.'+x.lower().strip(), self.config.get('skipExtensions').split(','))
        writeUntaggedArtist = (self.config.get('writeUntaggedTag').lower() == 'artist' or self.config.get('writeUntaggedTag').lower() == 'both')
        writeUntaggedTrack  = (self.config.get('writeUntaggedTag').lower() == 'track' or self.config.get('writeUntaggedTag').lower() == 'both')
        
        if (touchedFields is None or len(touchedFields) == 0):
            common.safeStderr('Perhaps you should configure a destination field...')
            return
        
        self.loadSynonyms()
        self.generateLocalTags()
        
        common.safeStdout('Updating tags in ['+mediadir+']')
        numfiles = 0
        for root, dirs, files in os.walk(mediadir):
            for filename in files:
                fname, ext = os.path.splitext(filename.lower())
                if (ext is not None and ext in skipExtensions):
                    continue

                metadata = self.mediaHelper.extractMetadata(os.path.join(root, filename))
                if (metadata is None or len(metadata['artists']) == 0 or metadata['album'] is None or metadata['track'] is None):
                    continue
                album, track = metadata['album'].lower(), metadata['track'].lower()
                
                artistTags = []
                trackTags = []
                for artist in map(string.lower, metadata['artists']):                                           
                    if (artist not in self.mediaLibrary or 
                        album not in self.mediaLibrary[artist]['albums'] or 
                        track not in self.mediaLibrary[artist]['albums'][album]['tracks']):
                        common.safeStderr('Entry not found in library: ['+artist+']['+album+']['+track+']')
                        continue
                    artistTags.extend(self.mediaLibrary[artist]['tags'] or [])
                    trackTags.extend(self.mediaLibrary[artist]['albums'][album]['tracks'][track]['tags'] or [])
                                 
                localArtistTags = self.lastTagsToLocalTags(artistTags)
                localTrackTags = self.lastTagsToLocalTags(trackTags)
                
                # Use untagged tags, if requested and appropriate
                if (len(localArtistTags) == 0 and writeUntaggedArtist):  localArtistTags = [(u'untagged artist', 0)]
                if (len(localTrackTags) == 0 and writeUntaggedTrack):    localTrackTags = [(u'untagged track', 0)]
                
                tagPayload = {}
                for touchedField in touchedFields:
                    if (touchedField in artistTagFields and touchedField in trackTagFields):
                        fieldTags = common.distinctTagSeq(localArtistTags + localTrackTags)
                    elif (touchedField in artistTagFields):
                        fieldTags = localArtistTags
                    else:
                        fieldTags = localTrackTags

                    if (fieldTags is None or len(fieldTags) == 0) : 
                        continue

                    # The following section is mostly to deal with multi-column sorting
                    
                    # Store the record weights somewhere we can look them up (the list should already be distinct)
                    recordWeights = {}
                    for tagpair in fieldTags:
                        recordWeights[tagpair[0].lower()] = tagpair[1]

                    # Pull out just the tag names as singleton tuples, we'll tack on sort weights next                                        
                    tagWeightsList = map(lambda tuple: (tuple[0],), fieldTags)
                                        
                    # Pull out the list of sort rules (e.g. record, library) and append each appropriate weight to the tuple list, in succession
                    sortRules = map(string.strip, self.config.get(touchedField + 'Sort').lower().split(','))                    
                    for sortRule in sortRules:
                        if (sortRule == 'record'):      tagWeightsList = map(lambda tagtuple: tagtuple + (recordWeights[tagtuple[0].lower()],), tagWeightsList)
                        elif (sortRule == 'library'):   tagWeightsList = map(lambda tagtuple: tagtuple + (self.getLibraryWeight(tagtuple[0].lower()),), tagWeightsList)
                        elif (sortRule == 'popularity'):tagWeightsList = map(lambda tagtuple: tagtuple + (self.getPopularityWeight(tagtuple[0].lower()),), tagWeightsList)
                    
                    common.sortWeightedTagTuples(tagWeightsList)
                    
                    tagPayload[touchedField] = self.formattedTagList(tagWeightsList, startDelim, endDelim)
                        
                if (self.mediaHelper.updateTags(os.path.join(root, filename), tagPayload)):                                                                      
                    numfiles += 1
                    if (verbose):
                        common.safeStdout('\tUpdated: '+os.path.join(root, filename))
                elif (verbose):
                    common.safeStdout('\tSkipped: '+os.path.join(root, filename)+' (nothing to update)')
        print 'Updated ['+str(numfiles)+'] media files'