Exemple #1
0
class MusicBrainzProvider:
    def __init__(self):
        self.__musicbrainz_query__ = Query()
        self.__escape_list__ = ["+", "-", "=", "*", "\/", "\\", "(", ")", "&", "*", "^", "%", "$", "#", "@", "!"]
    def FetchTrackListByArtistRelease(self, string_artist_name, string_release_name):
      musicbrainz_query = Query()
      try:
        # Search for all releases matching the given name. Limit the results
        # to the first best matches.

        string_release_id = ""
        string_release_title = ""

        musicbrainz_release_filter = ReleaseFilter(title=string_release_name, artistName=string_artist_name, limit=1)
        musicbrainz_release_results = musicbrainz_query.getReleases(musicbrainz_release_filter)
        if musicbrainz_release_results is not None:
          if len(musicbrainz_release_results) > 0:
            string_release_id = musicbrainz_release_results[0].getRelease().getId()
            string_release_title = musicbrainz_release_results[0].getRelease().getTitle()
            include_info = ReleaseIncludes(artist=True, tracks=True)
            release = self.__musicbrainz_query__.getReleaseById(string_release_id, include_info)

            track_list = []

            for track in release.getTracks():
                track_title = track.getTitle()
                for escape_char in self.__escape_list__:
                    track_title = track_title.replace(escape_char, "")
                track_list.append(track_title)

        return string_release_title, track_list

      except WebServiceError, e:
          # print 'Error:', e
          return []
Exemple #2
0
def print_release(mbid):
	q = Query()
	i = ReleaseIncludes(
		artist=True,
		tracks=True,
		urlRelations=True
	)

	rel = q.getReleaseById(mbid, i)
	if not rel:
		print 'Not found :/'
		return

	print 'Title:  %s' % rel.title
	print 'Artist: %s' % rel.artist.name
	print ''
	for no, trk in enumerate(rel.tracks):
		print '	  %d. %s' % ((no+1), trk.title)
Exemple #3
0
def guess_release(folder, files):
	nfiles = []
	cache = musicdns.cache.MusicDNSCache()
	print "Fingerprinting..."
	for fn in files:
		try:
			puid, _ = cache.getpuid(fn, MUSICDNS_KEY)
		except IOError:
			puid = None
		track = filename_track_number(fn)
		nfiles += [(track, fn, puid)]
	nfiles.sort()

	matchrel = defaultdict(int)
	for i, (no, fn, puid) in enumerate(nfiles):
		print 'Asking MusicBrainz about ' + basename(fn)
		if puid is None:
			continue
		for tno, track, release in find_releases(puid):
			included = 0
			if no == tno:
				matchrel[release.id] += 1
				included = 1
			print u'	%d - %s - %s %s' % (tno, track.title, release.title, ' <=' if included else '')

	q = Query()
	i = ReleaseIncludes(
		artist=True,
		tracks=True,
		urlRelations=True
	)
	releaseids = sorted(matchrel.iteritems(), key=itemgetter(1), reverse=1)

	if not releaseids:
		return None

	releases = None
	while not releases:
		try:
			releases = [(q.getReleaseById(rid, i), freq) for rid, freq in releaseids]
		except WebServiceError, e:
			print '!! WebServiceError: ', e
			print '!! Retry in 5 seconds...'
			time.sleep(5)
Exemple #4
0
def show_release():
    from musicbrainz2.webservice import Query, ArtistFilter, WebServiceError

    import string
    import musicbrainz2.webservice as ws
    import musicbrainz2.model as m
    import musicbrainz2.utils as u
	
    q = Query()
    inc = ws.ReleaseIncludes(artist=True, releaseEvents=True, labels=True,
                                 discs=True, tracks=True)
    rid = u'http://musicbrainz.org/release/52ec1af7-28a1-42e3-896a-0eddc8e338d5.html'
    release = q.getReleaseById(rid, inc)
    tracks = release.tracks
    
    for t in tracks:
        #print dir(t)
        minutes,seconds = divmod(t.duration/1000,60)
        print t.title, '-', string.join([str(minutes),':',str(seconds)],'')
Exemple #5
0
    def guess_release(self, folder, files):
        nfiles = []
        print "Fingerprinting..."
        for fn in files:
            try:
                puid, _ = self.cache.getpuid(fn, self.musicdns_key)
            except IOError:
                puid = None
            track = filename_track_number(fn)
            nfiles += [(track, fn, puid)]
        nfiles.sort()

        matchrel = defaultdict(int)
        for i, (no, fn, puid) in enumerate(nfiles):
            print "Asking MusicBrainz about " + basename(fn)
            if puid is None:
                continue
            for tno, track, release in find_releases(puid):
                included = 0
                if no == tno:
                    matchrel[release.id] += 1
                    included = 1
                print u"    %d - %s - %s %s" % (tno, track.title, release.title, " <=" if included else "")

        service = get_service()
        q = Query(service)
        i = ReleaseIncludes(artist=True, tracks=True, urlRelations=True)
        releaseids = sorted(matchrel.iteritems(), key=itemgetter(1), reverse=1)

        if not releaseids:
            return None

        releases = None
        while not releases:
            try:
                releases = [(q.getReleaseById(rid, i), freq) for rid, freq in releaseids]
            except WebServiceError, e:
                print "!! WebServiceError: ", e
                print "!! Retry in 5 seconds..."
                time.sleep(5)
Exemple #6
0
    def main(self):
        if len(sys.argv) < 2:
            print "Usage:\n\t%s <archive|folder>" % sys.argv[0]
            sys.exit()

        s = os.path.abspath(sys.argv[1])
        try:
            shutil.rmtree(".brainwash-work")
        except:
            pass
        try:
            os.mkdir(".brainwash-work")
        except:
            pass
        os.chdir(".brainwash-work")

        if os.path.isdir(s):
            print "Creating working copy..."
            shutil.copytree(s, "work")
        else:
            subprocess.call(["unp", s])

        folders = find_music_folders(".")

        for folder in folders:
            music_files = myglob(folder[0], "*" + folder[1])
            if len(music_files) < 2:
                cue_files = myglob(folder[0], "*.cue")
                if len(cue_files) < 1:
                    # ask for mbid
                    # need to write cuesheet generation code!!!
                    # print "There is no cue file. To generate one I need the Release MBID."
                    # mbid = raw_input('Enter MBID: ').strip()
                    print "There is no cuesheet. please generate one yourself :P"
                    continue
                else:
                    cue_file = cue_files[0]

                wav_file = self.decode_to_wav(music_files[0])
                subprocess.call(["bchunk", "-w", wav_file, cue_file, folder[0] + "/tmp-brainwash-"])
                wav_files = myglob(folder[0], "tmp-brainwash-*.wav")
                music_files = []
                for wav_file in wav_files:
                    music_files += [self.encode_to_flac(wav_file)]
                folder[1] = "flac"

                # encode into a nice format
            if folder[1] not in formats_final:
                wav_files = []
                if folder[1] == ".wav":
                    wav_files = music_files[:]
                else:
                    for music_file in music_files:
                        wav_files += [self.decode_to_wav(music_file)]
                music_files = []
                for wav_file in wav_files:
                    music_files += [self.encode_to_flac(wav_file)]
                folder[1] = "flac"
                # take over the tags?

            print "Found: " + folder[0]
            try:
                mbid = file(folder[0] + "/.mbid").read().strip()
                print "Using existing mbid"
            except:
                release = self.guess_release(folder[0], music_files)
                if release is None:
                    # ask for mbid
                    print "Could not guess!"
                    mbid = raw_input("Enter MBID: ").strip()
                else:
                    # ask if guess is correct
                    tmp_mbid = release.id.split("/")[-1:][0]
                    print "Selected %s" % tmp_mbid
                    answer = raw_input("Correct? [Y|n]").strip()
                    if answer == "" or answer.lower() == "y":
                        mbid = tmp_mbid
                    else:
                        print str(answer.lower())
                        mbid = raw_input("Enter MBID: ").strip()

                file(join(folder[0], ".mbid"), "w").write(str(mbid))

            service = get_service()
            q = Query(service)
            i = ReleaseIncludes(artist=True, tracks=True, urlRelations=True, releaseEvents=True, discs=True)
            try:
                release = q.getReleaseById(mbid, i)
            except WebServiceError, e:
                print "Error: ", e
                continue

            dst = self.config["destination_dir"]

            year = 9999

            for event in release.releaseEvents:
                year = min(year, int(event.date[:4]))

            if year == 9999:
                year = int(raw_input("Enter Release Year: ").strip())

            release_title = self.clean_filename(release.title)

            if release.TYPE_SOUNDTRACK in release.getTypes():
                dst += "/_soundtracks/(%s) %s/" % (year, release_title)
            elif not release.artist:
                dst += "/_va/(%s) %s/" % (year, release_title)
            else:
                sort_char = release.artist.sortName[:1].lower()
                sort_char = unicodedata.normalize("NFKD", sort_char).encode("ASCII", "ignore")
                dst += "/%s/%s/(%s) %s/" % (
                    sort_char,
                    self.clean_filename(release.artist.sortName),
                    year,
                    release_title,
                )

            try:
                os.makedirs(dst)
            except:
                raw_input("Failed creating %s! Press Anykey" % dst)
            file(join(dst, ".mbid"), "w").write(str(mbid))

            for music_file in music_files:
                # fix permissions for broken archives
                os.chmod(music_file, (stat.S_IRUSR + stat.S_IWUSR + stat.S_IRGRP + stat.S_IROTH))
                track_number = filename_track_number(music_file)
                track = release.tracks[track_number - 1]
                if folder[1] == ".mp3":
                    # meta_file = MP3(music_file, ID3=EasyID3)
                    meta_file = EasyID3()
                elif folder[1] == ".ogg":
                    meta_file = OggVorbis(music_file)
                elif folder[1] == "flac":
                    meta_file = FLAC(music_file)
                else:
                    print "Uh oh, no meta-file for " + music_file
                    # if not meta_file.tags:
                    # 	meta_file.add_tags()
                artist = track.artist.name if track.artist else release.artist.name
                meta_file["title"] = track.title
                meta_file["artist"] = artist
                meta_file["album"] = release.title
                meta_file["tracknumber"] = str(track_number) + "/" + str(len(music_files))
                meta_file["genre"] = self.get_lastfm_tags(meta_file["artist"][0])
                meta_file.save(music_file)

                file_dst = dst + self.clean_filename(
                    "%02d-%s - %s%s%s"
                    % (track_number, artist, track.title, "." if folder[1] == "flac" else "", folder[1])
                )
                os.rename(music_file, file_dst)

                # cover art
            image_files = myglob(folder[0], "*.[jpg|png]")
            if len(image_files) > 1:
                for image_file in image_files:
                    os.rename(image_file, dst + basename(image_file))
            elif len(image_files) == 1:
                os.rename(image_files[0], dst + "cover." + image_files[0][-3:])
            else:
                # try downlaod from amazon
                if release.asin:
                    urllib.urlretrieve(
                        "http://images.amazon.com/images/P/" + release.asin + ".01.LZZZZZZZ.jpg", dst + "cover.jpg"
                    )
                    if os.path.getsize(dst + "cover.jpg") < 1000L:
                        os.remove(dst + "cover.jpg")
            print "Done: " + dst
Exemple #7
0
	sys.exit(1)

if len(sys.argv) > 2:
	artistResults = [artistResults[int(sys.argv[2])]]
else:
	artistResults = [artistResults[0]]
	
tracks_ids = []
for result in artistResults:
	artist_name = result.artist
	releases = []
	for rtype in [m.Release.TYPE_ALBUM, m.Release.TYPE_SINGLE, m.Release.TYPE_COMPILATION, m.Release.TYPE_REMIX]:
		artist = q.getArtistById(artist_name.id, ArtistIncludes(
				releases=(m.Release.TYPE_OFFICIAL, rtype),
				tags=True))
	
		releases.extend(artist.getReleases())

	for release in releases:
		sleep(1) # respect TOS
		release = q.getReleaseById(release.id, ReleaseIncludes(artist = True, tracks = True))
		for track in release.tracks:
			name = track.artist.name if track.artist else release.artist.name
			full_title = (name + u" — " + track.title).lower()
			if not full_title in tracks_ids:
				print name, track.title
				if not sys.stdout.isatty():
					print >> sys.stderr, full_title
				tracks_ids.append(full_title)
		sys.stdout.flush()
 def get_release(self, gid):
     q = Query(self.ws)
     inc = ReleaseIncludes(tracks=True, isrcs=True)
     return q.getReleaseById(gid, include=inc)
 def get_release(self, gid):
     q = Query(self.ws)
     inc = ReleaseIncludes(tracks=True, isrcs=True)
     return q.getReleaseById(gid, include=inc)
Exemple #10
0
    count = 0
    idxfound = -1
    releasesfound = []
    for i in releasearr:
        if len(re.findall(searchgeneral,i.title)) != 0:
            releasesfound.append(i)
    if len(releasesfound) == 0 :
        print "No matching releases were found..."
        sys.exit(1)

for release in releasesfound:
    rid = release.id
    try:
	inc = ws.ReleaseIncludes(artist=True, releaseEvents=True, labels=True,
                                 discs=True, tracks=True)
	release = q.getReleaseById(rid, inc)
    except ws.WebServiceError, e:
	print 'Error:', e
	sys.exit(1)
    import subprocess
    proc =subprocess.Popen('cat ufb_index.csv', shell = True, stdout=subprocess.PIPE)
    out = proc.communicate()[0]
    print "Tracks found on ", release.title, ":"
    print
    for track in release.tracks:
        searchstr = track.title
        targets = '[^a-zA-Z0-9]'
        searchstr = re.sub(targets,'.*',searchstr)
        searchstr = "^[^a-zA-Z0-9]" + searchstr + ".*"
        searchgeneral= re.compile(searchstr,re.I | re.M)
        searchresults= re.findall(searchgeneral, out)
Exemple #11
0
class Tagger(object):

    def __init__(self):
        self.query = Query()

    def guess_artist_and_disc(self, files):
        rel = files[0]
        abs = os.path.normpath(os.path.join(os.getcwdu(), rel))
        dir = os.path.basename(os.path.dirname(abs))

        parts = re.split('\s+-\s+', dir)
        if len(parts) >= 2:
            return parts[0], parts[1]
        elif len(parts) == 1:
            return "", parts[0]
        else:
            return "", ""

    def find_releases(self, artist, disc_title, track_count):
        query_limit = 100
        f = ReleaseFilter(artistName=artist, title=disc_title,
                          limit=query_limit)
        results = self.query.getReleases(f)

        if len(results) == query_limit:
            print """\

Woah! the specified artist/disc names were pretty vague
we weren't able to check all possible candiates.

Please try to be more specific if the correct album
isn't in the following list.
"""

        releases = []
        for result in results:
            # wrap result into our own structure
            release = Release(result.release, self.query)
            # only keep releases with correct amount of tracks
            if track_count < 0 or release.tracks_total == track_count:
                releases.append(release)

        releases.sort(key=lambda r: r.title)

        return releases

    def find_release_by_mbid(self, mbid, track_count):
        include = ReleaseIncludes(artist=True, tracks=True)
        try:
            result = self.query.getReleaseById(mbid, include)
        except ResourceNotFoundError:
            error("There is no Release with this Musicbrainz ID")

        release = Release(result, self.query, details_included=True)

        if release.tracks_total == track_count:
            return release
        else:
            error("Unexpected track count for '%s - %s' expected %i but was %i"
                  % (release.artist.name, release.title, track_count, release.tracks_total))


    def order_files(self, files, tracks):
        """Make self.files have the same order as the tracks."""

        ordered_files = []
        remaining_files = list(files)

        for track in tracks:

            def similarity(file):
                # Strip directories and extension
                file = os.path.splitext(os.path.basename(file))[0]
                file_parts  = distinctive_parts(file)
                track_parts = distinctive_parts(track.title) + [track.number]
                score = 0
                for part in track_parts:
                    if part in file_parts:
                        score += 1
                        file_parts.remove(part)
                return score

            most_similar = max(remaining_files, key=similarity)
            remaining_files.remove(most_similar)
            ordered_files.append(most_similar)

        return ordered_files

    def tag(self, files, release,
            genre=None, strip_existing_tags=False, progress=None):

        files_and_tracks = zip(files, release.tracks)
        for file, track in files_and_tracks:

            if strip_existing_tags:
                id3.delete(file)
                apev2.delete(file)

            try:
                tag = id3.ID3(file)
            except id3.ID3NoHeaderError:
                tag = id3.ID3()

            tag.add(id3.TPE1(3, track.artist.name))
            tag.add(id3.TALB(3, track.release.title))
            tag.add(id3.TIT2(3, track.title))
            tag.add(id3.TDRC(3, track.release.earliestReleaseDate))
            tag.add(id3.TRCK(3, track.number_str()))

            if track.release.album_artist is not None:
                tag.add(id3.TPE2(3, track.release.album_artist))

            discset = track.release.discset
            if discset:
                disc_num = discset.number_str()

                tag.add(id3.TPOS(3, disc_num))
                if discset.desc:
                    tag.delall('COMM')
                    tag.add(id3.COMM(3, text=discset.desc,
                                     desc='', lang='eng'))

            if genre is not None:
                tag.add(id3.TCON(3, genre))

            tag.add(id3.UFID(owner='http://musicbrainz.org', data=track.uuid))

            tag.save(file)
            if progress is not None:
                progress(file, track)

    def rename(self, files, release, progress=None):
        warnings = []
        for file, track in zip(files, release.tracks):

            filename = "%02i. %s.mp3" % (track.number, track.title)
            filename = make_fs_safe(filename)
            new_file = os.path.join(os.path.dirname(file), filename)

            if new_file == file:
                continue

            if os.path.exists(new_file):
                w = '"%s" already exists, not overwriting.' % new_file
                warnings.append(w)
                continue

            os.rename(file, new_file)

            if progress is not None:
                progress(file, track)

        return warnings
Exemple #12
0
    def __init__(self, releaseId):
        #self.ignoreMissing(True)
        super(MusicBrainz2AlbumInfo, self).__init__()
        if isinstance(releaseId, basestring):
            self.__releaseId = releaseId
            query = Query()
            include = ReleaseIncludes(artist=True, tracks=True,
                    releaseEvents=True)
            release = query.getReleaseById(releaseId, include)
        elif isinstance(releaseId, Release):
            release = releaseId
            self.__releaseId = release.id
        else:
            raise Exception(
                    "incorrect type parameter for MusicBrainz2AlbumInfo %s"
                    % releaseId)

        self.title = release.title
        # XXX: musicbrainz doesn't have genre info. what to do?
        #self.genre = 'Musicbrainz'
        self.artist = release.artist.name
        date = release.getEarliestReleaseDate()
        if not date:
            self.year = 0
        else:
            self.year = int(date[0:4])
        self.genre = ''
        tracks = []
        number = 0
        self.isVarious = False
        for track in release.tracks:
            number += 1
            # XXX: get rid of the overcomplicated validation scheme that makes
            # for these ugly hacks
            class MBTrackInfo(TrackInfo):
                '''Represent musicbrainz track information.'''
                def getPlayLength(self):
                    'getter'
                    return self.__playLength
                def setPlayLength(self, playLength):
                    'setter'
                    self.__playLength = playLength
                def __init__(self):
                    super(MBTrackInfo, self).__init__()
                playLength = property(getPlayLength, setPlayLength)

            track_info = MBTrackInfo()
            del track_info.validateProps[
                    track_info.validateProps.index('playLength')]
            track_info.number = number
            if track.duration:
                track_info.playLength = track.duration / 1000.0
            else:
                # XXX: make sure we don't use namebinder relying on track length
                track_info.playLength = 0
            if track.artist:
                track_info.artist = track.artist.name
                self.isVarious = True
            else:
                track_info.artist = release.artist.name
            track_info.title = track.title
            tracks.append(track_info)
        self.tracks = tracks