def generate_from_metadata(file, num_tracks): """Return track id's by looking up the name on music brainz Args: fname: The file containing the track in question. Yields: A set of track_id, by querying based on id3 tags """ album = file.getMDAlbumTitle() title = file.getMDTrackTitle() artist = file.getMDTrackArtist() if album is None or title is None or artist is None: return # Can't get metadata util.update_progress("Searching albums by text lookup: " + ` album ` + " " + ` artist `) for i in flatten( util.combinations(lookups.get_releases_by_cdtext, album, artist, num_tracks)): release = lookups.get_release_by_releaseid(i.release.id) util.update_progress("Trying " + release.title + " by text lookup") for trackind in range(len(release.tracks)): rtrackname = release.tracks[trackind].title if type(title) != type([]): title = [title] for t in title: if util.comp_name(rtrackname, t): print "Using album based text comparison for", artist.strip( ), album.strip(), "'s track", trackind + 1, ` rtrackname ` yield lookups.get_track_by_id(release.tracks[trackind].id) else: print "Failed text lookup for %s" % t
def generate_track_name_possibilities(file, fileid, possible_releases): """Return all track ids matching the tracks. Args: fname: The file containing the track in question. track: A list of tracks to match against. possible_releases: Dictionary containing releases under consideration. Yields: All releated track_ids. Looks at all track names in the releases under consideration and case insensitively compares the tracks, returning any matches. """ ftrackname = file.getMDTrackTitle() for (rid, v) in possible_releases.items(): release = lookups.get_release_by_releaseid(rid) for trackind in range(len(release.tracks)): rtrackname = release.tracks[trackind].title # Don't bother if we've already found this track! if trackind + 1 in v: continue if any(util.combinations(util.comp_name, rtrackname, ftrackname)): print "Using text based comparison for track", trackind + 1, ` rtrackname `, "(", repr( ftrackname), ")" yield lookups.get_track_by_id(release.tracks[trackind].id)
def generate_from_metadata(file, num_tracks): """Return track id's by looking up the name on music brainz Args: fname: The file containing the track in question. Yields: A set of track_id, by querying based on id3 tags """ album = file.getMDAlbumTitle() title = file.getMDTrackTitle() artist = file.getMDTrackArtist() if album is None or title is None or artist is None: return # Can't get metadata util.update_progress("Searching albums by text lookup: "+`album`+" "+`artist`) for i in flatten(util.combinations(lookups.get_releases_by_cdtext,album, artist, num_tracks)): release = lookups.get_release_by_releaseid(i.release.id) util.update_progress("Trying "+release.title+" by text lookup") for trackind in range(len(release.tracks)): rtrackname = release.tracks[trackind].title if type(title) != type([]): title=[title] for t in title: if util.comp_name(rtrackname,t): print "Using album based text comparison for",artist.strip(),album.strip(),"'s track",trackind+1,`rtrackname` yield lookups.get_track_by_id(release.tracks[trackind].id) else: print "Failed text lookup for %s" % t
def get_puids_for_release(releaseid): puids=[] release = lookups.get_release_by_releaseid(releaseid) for track in release.tracks: track = lookups.get_track_by_id(track.id) puids = puids + track.puids return puids
def generate_track_name_possibilities(file, fileid, possible_releases): """Return all track ids matching the tracks. Args: fname: The file containing the track in question. track: A list of tracks to match against. possible_releases: Dictionary containing releases under consideration. Yields: All releated track_ids. Looks at all track names in the releases under consideration and case insensitively compares the tracks, returning any matches. """ ftrackname = file.getMDTrackTitle() for (rid,v) in possible_releases.items(): release = lookups.get_release_by_releaseid(rid) for trackind in range(len(release.tracks)): rtrackname = release.tracks[trackind].title # Don't bother if we've already found this track! if trackind+1 in v: continue if any(util.combinations(util.comp_name, rtrackname, ftrackname)): print "Using text based comparison for track",trackind+1,`rtrackname`,"(",repr(ftrackname),")" yield lookups.get_track_by_id(release.tracks[trackind].id)
def get_puids_for_release(releaseid): puids = [] release = lookups.get_release_by_releaseid(releaseid) for track in release.tracks: track = lookups.get_track_by_id(track.id) puids = puids + track.puids return puids
def test(self, tracknum, file): #print "file",file (trackname, artist, puid) = self.calcpuid(file) if puid is None: return self.puid = puid #print "puid",puid,"trackname",trackname,"dur",(dur/1000) track = lookups.get_track_by_id(self.release.tracks[tracknum].id) #print "track len",(track.duration/1000) #print "puids",track.puids puidtracks = lookups.get_tracks_by_puid(puid) releaseToTrack = {} for pt in puidtracks: relId = pt.releases[0].id if relId not in releaseToTrack: releaseToTrack[relId] = [pt.id] else: releaseToTrack[relId].append(pt.id) if self.release.id not in releaseToTrack: self.l.write("puid http://musicbrainz.org/show/puid/?puid=%s is not on track %s.html Might just have not been submitted" % (puid, track.id)) elif len(releaseToTrack[self.release.id]) > 1: self.l.write("Track %d (%s.html)" % (tracknum+1, track.id)) self.l.write("Puid http://musicbrainz.org/show/puid/?puid=%s" % puid) self.l.write(" This puid links to more than 1 track on the same release") for t in releaseToTrack[self.release.id]: if t != track.id: self.crossref(t) elif len(releaseToTrack[self.release.id]) == 1: relTrack = os.path.basename(releaseToTrack[self.release.id][0]) tagTrack = self.fileTags[tracknum][tag.TRACK_ID] if relTrack != tagTrack: self.l.write("Track %d (%s.html)" % (tracknum+1, track.id)) self.l.write(" Based on the puid, this should be track %s, but it's %s" % (relTrack, tagTrack))
def find_more_tracks(tracks): # There is a n:n mapping of puid's to tracks. # All puid's that match a track should be the same song. # Thus if PUIDa maps to TrackA, which also has PUIDb # and PUIDb maps to TrackB too, then PUIDa should map to # TrackB too... tracks=tracks[:] donetracks=[] donepuids=[] donetrackids=[] paths={} while tracks!=[]: t=tracks.pop() donetracks.append(t) yield t newt = lookups.get_track_by_id(t.id) for p in newt.puids: if p in donepuids: continue donepuids.append(p) ts = lookups.get_tracks_by_puid(p) for u in ts: if u.id in donetrackids: continue tracks.append(u) donetrackids.append(u.id) #print u.id,[y.title for y in u.releases] if t.id in paths: path=paths[t.id] else: path=[] path=path+[u.releases[0].title] #print path paths[u.id]=path
def crossref(self, trackid): i=0 for track in self.release.tracks: if trackid == track.id: self.l.write(" * also on track %d (%s)" % (i+1, track.title)) (trackname, artist, thispuid) = self.calcpuid(os.path.join(self.dirname, self.files[i])) if self.puid != thispuid: self.l.write(" - but I don't think the puid is correct - remove this track") thistrack = lookups.get_track_by_id(trackid) if thispuid in thistrack.puids: self.l.write(" (I'm doubly sure, because the puid of this file is also in mb for the correct track)") i+=1
def add_new_track(release, possible_releases, fileid, track, trackinfo, impossible_releases): releaseid = release.id found_tracknumber = lookups.track_number(release.tracks, track) if releaseid in possible_releases: assert found_tracknumber not in possible_releases[releaseid] assert fileid not in possible_releases[releaseid].values(), ( fileid, possible_releases[releaseid]) possible_releases[releaseid][found_tracknumber] = fileid print "Found track", found_tracknumber, "(", release.tracks[ found_tracknumber - 1].title, ")", "of", release.title, ":", os.path.basename( fileid), "(tracks found: %s)\x1b[K" % (util.output_list( possible_releases[releaseid].keys())) return else: possible_releases[releaseid] = {found_tracknumber: fileid} util.update_progress( "Considering new %s - %s (found track %d)" % (release.artist.name, release.title, found_tracknumber)) # Right, lets see if we can find some other tracks quick smart for trackind in range(len(release.tracks)): # Don't waste time on things we've already found if (trackind + 1) in possible_releases[releaseid]: continue track = lookups.get_track_by_id(release.tracks[trackind].id) for fileid in trackinfo: if fileid in possible_releases[releaseid].values(): continue if trackinfo[fileid].getPUID() in track.puids: # yay, found one. if verify_track(release, possible_releases, impossible_releases, trackinfo, fileid, track): possible_releases[releaseid][trackind + 1] = fileid util.update_progress( " Also found track %02d: %s" % (trackind + 1, release.tracks[trackind].title)) break print " Found tracks: %s" % (util.output_list( possible_releases[releaseid].keys())), if util.list_difference(range(1, len(release.tracks) + 1), possible_releases[releaseid].keys()): print " Missing tracks: %s" % (util.output_list( util.list_difference(range(1, len(release.tracks) + 1), possible_releases[releaseid].keys()))) else: print
def generate_from_metadata(file): """Return track id's by looking up the name on music brainz Args: musicfile: The file containing the track in question. Yields: A set of track_id, by querying based on metadata tags """ trackid=file.getMDTrackID() if trackid: try: yield lookups.get_track_by_id(trackid) except Exception, e: util.report("WARNING: Unexpected exception when looking up mbtrackid %s: %s" % (trackid, e))
def add_new_track(release, possible_releases, fileid, track, trackinfo, impossible_releases): releaseid = release.id found_tracknumber=lookups.track_number(release.tracks, track) if releaseid in possible_releases: assert found_tracknumber not in possible_releases[releaseid] assert fileid not in possible_releases[releaseid].values(),(fileid,possible_releases[releaseid]) possible_releases[releaseid][found_tracknumber]=fileid print "Found track",found_tracknumber,"(",release.tracks[found_tracknumber-1].title,")","of",release.title,":",os.path.basename(fileid),"(tracks found: %s)\x1b[K" % (util.output_list(possible_releases[releaseid].keys())) return else: possible_releases[releaseid]={found_tracknumber:fileid} util.update_progress("Considering new %s - %s (found track %d)" % ( release.artist.name, release.title, found_tracknumber)) # Right, lets see if we can find some other tracks quick smart for trackind in range(len(release.tracks)): # Don't waste time on things we've already found if (trackind+1) in possible_releases[releaseid]: continue track = lookups.get_track_by_id(release.tracks[trackind].id) for fileid in trackinfo: if fileid in possible_releases[releaseid].values(): continue if trackinfo[fileid].getPUID() in track.puids: # yay, found one. if verify_track(release, possible_releases, impossible_releases, trackinfo, fileid, track): possible_releases[releaseid][trackind+1]=fileid util.update_progress(" Also found track %02d: %s" % (trackind+1,release.tracks[trackind].title)) break print " Found tracks: %s" % ( util.output_list(possible_releases[releaseid].keys())), if util.list_difference(range(1,len(release.tracks)+1), possible_releases[releaseid].keys()): print " Missing tracks: %s"% ( util.output_list( util.list_difference(range(1,len(release.tracks)+1), possible_releases[releaseid].keys()))) else: print
def generate_from_metadata(file): """Return track id's by looking up the name on music brainz Args: musicfile: The file containing the track in question. Yields: A set of track_id, by querying based on metadata tags """ trackid = file.getMDTrackID() if trackid: try: yield lookups.get_track_by_id(trackid) except Exception, e: util.report( "WARNING: Unexpected exception when looking up mbtrackid %s: %s" % (trackid, e))
def crossref(self, trackid): i = 0 for track in self.release.tracks: if trackid == track.id: self.l.write(" * also on track %d (%s)" % (i + 1, track.title)) (trackname, artist, thispuid) = self.calcpuid( os.path.join(self.dirname, self.files[i])) if self.puid != thispuid: self.l.write( " - but I don't think the puid is correct - remove this track" ) thistrack = lookups.get_track_by_id(trackid) if thispuid in thistrack.puids: self.l.write( " (I'm doubly sure, because the puid of this file is also in mb for the correct track)" ) i += 1
def test(self, tracknum, file): #print "file",file (trackname, artist, puid) = self.calcpuid(file) if puid is None: return self.puid = puid #print "puid",puid,"trackname",trackname,"dur",(dur/1000) track = lookups.get_track_by_id(self.release.tracks[tracknum].id) #print "track len",(track.duration/1000) #print "puids",track.puids puidtracks = lookups.get_tracks_by_puid(puid) releaseToTrack = {} for pt in puidtracks: relId = pt.releases[0].id if relId not in releaseToTrack: releaseToTrack[relId] = [pt.id] else: releaseToTrack[relId].append(pt.id) if self.release.id not in releaseToTrack: self.l.write( "puid http://musicbrainz.org/show/puid/?puid=%s is not on track %s.html Might just have not been submitted" % (puid, track.id)) elif len(releaseToTrack[self.release.id]) > 1: self.l.write("Track %d (%s.html)" % (tracknum + 1, track.id)) self.l.write("Puid http://musicbrainz.org/show/puid/?puid=%s" % puid) self.l.write( " This puid links to more than 1 track on the same release") for t in releaseToTrack[self.release.id]: if t != track.id: self.crossref(t) elif len(releaseToTrack[self.release.id]) == 1: relTrack = os.path.basename(releaseToTrack[self.release.id][0]) tagTrack = self.fileTags[tracknum][tag.TRACK_ID] if relTrack != tagTrack: self.l.write("Track %d (%s.html)" % (tracknum + 1, track.id)) self.l.write( " Based on the puid, this should be track %s, but it's %s" % (relTrack, tagTrack))
def generate_track_puid_possibilities(tracks): """Return all track ids with matching the tracks. Args: track: A list of tracks to match against. Yields: All releated track_ids. There is a n:n mapping of puid's to tracks. Therefore all puid's that match a track should be the same song. Thus if PUIDa maps to TrackA, which also has PUIDb and PUIDb maps to TrackB too, then PUIDa should map to TrackB too... """ tracks = tracks[:] done_track_ids = set() done_puids=set() # Don't return the tracks that were passed in. for track in tracks: done_track_ids.add(track.id) while tracks: t = tracks.pop() #print "Looking for any tracks related to %s" % t.title if not t.puids: track = lookups.get_track_by_id(t.id) for puid in track.puids: if puid in done_puids: continue done_puids.add(puid) tracks2 = lookups.get_tracks_by_puid(puid) for t2 in tracks2: if t2.id in done_track_ids: continue done_track_ids.add(t2.id) yield t2 tracks.append(t2)
def verify_track(release, possible_releases, impossible_releases, trackinfo, fileid, track): # Step One: Has this file already been found on this release? releaseid = release.id if releaseid in possible_releases and fileid in possible_releases[releaseid].values(): util.update_progress("Already found on this release:" + fileid ) return False # Step Two: Check for the right number of tracks if len(release.tracks) != len(trackinfo): # Ignore release -- wrong number of tracks util.update_progress(release.title.encode("ascii","ignore")[:40]+": wrong number of tracks (%d not %d)" % (len(release.tracks),len(trackinfo))) impossible_releases.append(releaseid) return False # Step Three: Have we found a file for this track on this release? tracknum = lookups.track_number(release.tracks, track) if releaseid in possible_releases and tracknum in possible_releases[releaseid]: util.update_progress("Already found a file for track %02d: %s" % (tracknum,possible_releases[releaseid][tracknum])) return False # Step Four: (optionally) Check that track 'n' maps to file 'n'. if FORCE_ORDER: found_tracknumber=lookups.track_number(release.tracks, track) file_ids = trackinfo.keys() file_ids = sort.sorted_list(file_ids) if found_tracknumber != file_ids.index(fileid)+1: util.update_progress(release.title[:40]+": track at wrong position") return False # Step Five: Make sure if there is another mapping on this album # that we don't accept this one. if trackinfo[fileid].getPUID() in get_puids_for_release(releaseid): if trackinfo[fileid].getPUID() not in lookups.get_track_by_id(track.id).puids: print "Track exists elsewhere on this release" print "",fileid print "",track.title for ntrackind,ntrack in enumerate(release.tracks): ntrack = lookups.get_track_by_id(ntrack.id) if trackinfo[fileid].getPUID() in ntrack.puids: print " should be:",ntrack.title return False # Step Six: Make sure the song is within 10% of the length of the # track we expect it to be. track = lookups.get_track_by_id(track.id) if track.getDuration() is not None: dur_ratio = track.getDuration() * 1.0 / trackinfo[fileid].getDuration() if dur_ratio < .9 or dur_ratio > 1.1: print "Track lengths differ" print " (%s) %s" % ( duration_to_string(trackinfo[fileid].getDuration()), trackinfo[fileid].getFilename(), ) print " (%s) %s" % ( duration_to_string(track.getDuration()), track.title, ) return False # Well, after passing through that gauntlet, we might consider this track! return True
def verify_track(release, possible_releases, impossible_releases, trackinfo, fileid, track): # Step One: Has this file already been found on this release? releaseid = release.id if releaseid in possible_releases and fileid in possible_releases[ releaseid].values(): util.update_progress("Already found on this release:" + fileid) return False # Step Two: Check for the right number of tracks if len(release.tracks) != len(trackinfo): # Ignore release -- wrong number of tracks util.update_progress( release.title.encode("ascii", "ignore")[:40] + ": wrong number of tracks (%d not %d)" % (len(release.tracks), len(trackinfo))) impossible_releases.append(releaseid) return False # Step Three: Have we found a file for this track on this release? tracknum = lookups.track_number(release.tracks, track) if releaseid in possible_releases and tracknum in possible_releases[ releaseid]: util.update_progress( "Already found a file for track %02d: %s" % (tracknum, possible_releases[releaseid][tracknum])) return False # Step Four: (optionally) Check that track 'n' maps to file 'n'. if FORCE_ORDER: found_tracknumber = lookups.track_number(release.tracks, track) file_ids = trackinfo.keys() file_ids = sort.sorted_list(file_ids) if found_tracknumber != file_ids.index(fileid) + 1: util.update_progress(release.title[:40] + ": track at wrong position") return False # Step Five: Make sure if there is another mapping on this album # that we don't accept this one. if trackinfo[fileid].getPUID() in get_puids_for_release(releaseid): if trackinfo[fileid].getPUID() not in lookups.get_track_by_id( track.id).puids: print "Track exists elsewhere on this release" print "", fileid print "", track.title for ntrackind, ntrack in enumerate(release.tracks): ntrack = lookups.get_track_by_id(ntrack.id) if trackinfo[fileid].getPUID() in ntrack.puids: print " should be:", ntrack.title return False # Step Six: Make sure the song is within 10% of the length of the # track we expect it to be. track = lookups.get_track_by_id(track.id) if track.getDuration() is not None and trackinfo[fileid].getDuration(): dur_ratio = track.getDuration() * 1.0 / trackinfo[fileid].getDuration() if dur_ratio < .9 or dur_ratio > 1.1: print "Track lengths differ" print " (%s) %s" % ( duration_to_string(trackinfo[fileid].getDuration()), trackinfo[fileid].getFilename(), ) print " (%s) %s" % ( duration_to_string(track.getDuration()), track.title, ) return False # Well, after passing through that gauntlet, we might consider this track! return True