def test_hash(self): frame = POPM(email="e", rating=42) self.assertEqual(frame.HashKey, "POPM:e") frame._pprint() self.assertEquals(POPM(count=1).HashKey, POPM(count=2).HashKey) self.assertNotEquals(POPM(email="a").HashKey, POPM(email="b").HashKey)
def test_write_popm_long_counter(self): f = ID3(self.filename) f.add(POPM(email="*****@*****.**", rating=125, count=2**32 + 1)) f.save() f = ID3(self.filename) self.failUnless("POPM:[email protected]" in f) self.failUnless("POPM:Windows Media Player 9 Series" in f) popm = f["POPM:[email protected]"] self.assertEquals(popm.rating, 125) self.assertEquals(popm.count, 2**32 + 1)
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()
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()
def _audio_popm(atuple): audio, atag, _, _, _ = atuple param = ast.literal_eval(atag) audio.add(POPM(param[0], param[1])) #, param[2]))
def test_POPM(self): from mutagen.id3 import POPM frame = POPM(email="e", rating=42) self.assertEqual(frame.HashKey, "POPM:e") frame._pprint()
def _get_default_popm(self): r = POPM(rating=Stars(3).to_bytes(), email=u"MusicBee") r.count = 0 return r
def test_multi_POPM(self): from mutagen.id3 import POPM self.assertEquals(POPM(count=1).HashKey, POPM(count=2).HashKey) self.assertNotEquals(POPM(email="a").HashKey, POPM(email="b").HashKey)
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