Ejemplo n.º 1
0
def album_candidates(items, artist, album, va_likely):
    """Search for album matches. ``items`` is a list of Item objects
    that make up the album. ``artist`` and ``album`` are the respective
    names (strings), which may be derived from the item list or may be
    entered by the user. ``va_likely`` is a boolean indicating whether
    the album is likely to be a "various artists" release.
    """
    # Base candidates if we have album and artist to match.
    if artist and album:
        try:
            for candidate in mb.match_album(artist, album, len(items)):
                yield candidate
        except mb.MusicBrainzAPIError as exc:
            exc.log(log)

    # Also add VA matches from MusicBrainz where appropriate.
    if va_likely and album:
        try:
            for candidate in mb.match_album(None, album, len(items)):
                yield candidate
        except mb.MusicBrainzAPIError as exc:
            exc.log(log)

    # Candidates from plugins.
    for candidate in plugins.candidates(items, artist, album, va_likely):
        yield candidate
Ejemplo n.º 2
0
def album_candidates(items, artist, album, va_likely):
    """Search for album matches. ``items`` is a list of Item objects
    that make up the album. ``artist`` and ``album`` are the respective
    names (strings), which may be derived from the item list or may be
    entered by the user. ``va_likely`` is a boolean indicating whether
    the album is likely to be a "various artists" release.
    """
    out = []

    # Base candidates if we have album and artist to match.
    if artist and album:
        try:
            out.extend(mb.match_album(artist, album, len(items)))
        except mb.MusicBrainzAPIError as exc:
            exc.log(log)

    # Also add VA matches from MusicBrainz where appropriate.
    if va_likely and album:
        try:
            out.extend(mb.match_album(None, album, len(items)))
        except mb.MusicBrainzAPIError as exc:
            exc.log(log)

    # Candidates from plugins.
    out.extend(plugins.candidates(items, artist, album, va_likely))

    # Notify subscribed plugins about fetched album info
    for a in out:
        plugins.send('albuminfo_received', info=a)

    return out
Ejemplo n.º 3
0
    def test_match_album(self):
        mbid = "d2a6f856-b553-40a0-ac54-a321e8e2da99"
        with mock.patch("musicbrainzngs.search_releases") as sp:
            sp.return_value = {"release-list": [{"id": mbid}]}
            with mock.patch("musicbrainzngs.get_release_by_id") as gp:
                gp.return_value = {
                    "release": {
                        "title": "hi",
                        "id": mbid,
                        "medium-list": [
                            {
                                "track-list": [
                                    {"recording": {"title": "foo", "id": "bar", "length": 42}, "position": 9}
                                ],
                                "position": 5,
                            }
                        ],
                        "artist-credit": [{"artist": {"name": "some-artist", "id": "some-id"}}],
                        "release-group": {"id": "another-id"},
                    }
                }

                ai = list(mb.match_album("hello", "there"))[0]

                sp.assert_called_with(artist="hello", release="there", limit=5)
                gp.assert_called_with(mbid, mock.ANY)
                self.assertEqual(ai.tracks[0].title, "foo")
                self.assertEqual(ai.album, "hi")
Ejemplo n.º 4
0
    def candidates(self, items):
        last_artist, last_artist_id = get_cur_artist(items)

        # Search MusicBrainz based on Last.fm metadata.
        cands = list(mb.match_album(last_artist, '', len(items)))

        log.debug('Matched last candidates: %s' %
                  ', '.join([cand.album for cand in cands]))
        return cands
Ejemplo n.º 5
0
    def candidates(self, items):
        last_artist, last_artist_id = get_cur_artist(items)

        # Search MusicBrainz based on Last.fm metadata.
        cands = list(mb.match_album(last_artist, '', len(items)))

        log.debug('Matched last candidates: %s' %
                  ', '.join([cand.album for cand in cands]))
        return cands
Ejemplo n.º 6
0
def _album_candidates(items, artist, album, va_likely):
    """Search for album matches. ``items`` is a list of Item objects
    that make up the album. ``artist`` and ``album`` are the respective
    names (strings), which may be derived from the item list or may be
    entered by the user. ``va_likely`` is a boolean indicating whether
    the album is likely to be a "various artists" release.
    """
    out = []

    # Base candidates if we have album and artist to match.
    if artist and album:
        out.extend(mb.match_album(artist, album, len(items)))

    # Also add VA matches from MusicBrainz where appropriate.
    if va_likely and album:
        out.extend(mb.match_album(None, album, len(items)))

    # Candidates from plugins.
    out.extend(plugins.candidates(items))

    return out
Ejemplo n.º 7
0
def _album_candidates(items, artist, album, va_likely):
    """Search for album matches. ``items`` is a list of Item objects
    that make up the album. ``artist`` and ``album`` are the respective
    names (strings), which may be derived from the item list or may be
    entered by the user. ``va_likely`` is a boolean indicating whether
    the album is likely to be a "various artists" release.
    """
    out = []

    # Base candidates if we have album and artist to match.
    if artist and album:
        out.extend(mb.match_album(artist, album, len(items)))

    # Also add VA matches from MusicBrainz where appropriate.
    if va_likely and album:
        out.extend(mb.match_album(None, album, len(items)))

    # Candidates from plugins.
    out.extend(plugins.candidates(items))

    return out
Ejemplo n.º 8
0
    def test_match_album(self):
        mbid = 'd2a6f856-b553-40a0-ac54-a321e8e2da99'
        with mock.patch('musicbrainzngs.search_releases') as sp:
            sp.return_value = {
                'release-list': [{
                    'id': mbid,
                }],
            }
            with mock.patch('musicbrainzngs.get_release_by_id') as gp:
                gp.return_value = {
                    'release': {
                        'title':
                        'hi',
                        'id':
                        mbid,
                        'medium-list': [{
                            'track-list': [{
                                'id': 'baz',
                                'recording': {
                                    'title': 'foo',
                                    'id': 'bar',
                                    'length': 42,
                                },
                                'position': 9,
                                'number': 'A1',
                            }],
                            'position':
                            5,
                        }],
                        'artist-credit': [{
                            'artist': {
                                'name': 'some-artist',
                                'id': 'some-id',
                            },
                        }],
                        'release-group': {
                            'id': 'another-id',
                        }
                    }
                }

                ai = list(mb.match_album('hello', 'there'))[0]

                sp.assert_called_with(artist='hello', release='there', limit=5)
                gp.assert_called_with(mbid, mock.ANY)
                self.assertEqual(ai.tracks[0].title, 'foo')
                self.assertEqual(ai.album, 'hi')
Ejemplo n.º 9
0
    def test_match_album(self):
        mbid = 'd2a6f856-b553-40a0-ac54-a321e8e2da99'
        with mock.patch('musicbrainzngs.search_releases') as sp:
            sp.return_value = {
                'release-list': [{
                    'id': mbid,
                }],
            }
            with mock.patch('musicbrainzngs.get_release_by_id') as gp:
                gp.return_value = {
                    'release': {
                        'title': 'hi',
                        'id': mbid,
                        'medium-list': [{
                            'track-list': [{
                                'recording': {
                                    'title': 'foo',
                                    'id': 'bar',
                                    'length': 42,
                                },
                                'position': 9,
                                'number': 'A1',
                            }],
                            'position': 5,
                        }],
                        'artist-credit': [{
                            'artist': {
                                'name': 'some-artist',
                                'id': 'some-id',
                            },
                        }],
                        'release-group': {
                            'id': 'another-id',
                        }
                    }
                }

                ai = list(mb.match_album('hello', 'there'))[0]

                sp.assert_called_with(artist='hello', release='there', limit=5)
                gp.assert_called_with(mbid, mock.ANY)
                self.assertEqual(ai.tracks[0].title, 'foo')
                self.assertEqual(ai.album, 'hi')
Ejemplo n.º 10
0
 def test_match_album_empty(self):
     with mock.patch('musicbrainzngs.search_releases') as p:
         ail = list(mb.match_album(' ', ' '))
         self.assertFalse(p.called)
         self.assertEqual(ail, [])
Ejemplo n.º 11
0
 def test_match_album_empty(self):
     with mock.patch('musicbrainzngs.search_releases') as p:
         ail = list(mb.match_album(' ', ' '))
         self.assertFalse(p.called)
         self.assertEqual(ail, [])
Ejemplo n.º 12
0
def tag_album(items, search_artist=None, search_album=None):
    """Bundles together the functionality used to infer tags for a
    set of items comprised by an album. Returns everything relevant:
        - The current artist.
        - The current album.
        - A list of (distance, items, info) tuples where info is a
          dictionary containing the inferred tags and items is a
          reordered version of the input items list. The candidates are
          sorted by distance (i.e., best match first).
        - A recommendation, one of RECOMMEND_STRONG, RECOMMEND_MEDIUM,
          or RECOMMEND_NONE; indicating that the first candidate is
          very likely, it is somewhat likely, or no conclusion could
          be reached.
    If search_artist and search_album are provided, then they are used
    as search terms in place of the current metadata.
    May raise an AutotagError if existing metadata is insufficient.
    """
    # Get current metadata.
    cur_artist, cur_album = current_metadata(items)
    log.debug('Tagging %s - %s' % (cur_artist, cur_album))
    
    # The output result tuples (keyed by MB album ID).
    out_tuples = {}
    
    # Try to find album indicated by MusicBrainz IDs.
    id_info = match_by_id(items)
    if id_info:
        validate_candidate(items, out_tuples, id_info)
        if out_tuples:
            # If we have a very good MBID match, return immediately.
            # Otherwise, this match will compete against metadata-based
            # matches.
            rec = recommendation(out_tuples.values())
            if rec == RECOMMEND_STRONG:
                log.debug('ID match.')
                return cur_artist, cur_album, out_tuples.values(), rec
    
    # Search terms.
    if not (search_artist and search_album):
        # No explicit search terms -- use current metadata.
        search_artist, search_album = cur_artist, cur_album
    log.debug('Search terms: %s - %s' % (search_artist, search_album))
    
    # Get candidate metadata from search.
    if search_artist and search_album:
        candidates = mb.match_album(search_artist, search_album,
                                    len(items), MAX_CANDIDATES)
        candidates = list(candidates)
    else:
        candidates = []

    # Get candidates from plugins.
    candidates.extend(plugins.candidates(items))
    
    # Get the distance to each candidate.
    log.debug('Evaluating %i candidates.' % len(candidates))
    for info in candidates:
        validate_candidate(items, out_tuples, info)
    
    # Sort by distance.
    out_tuples = out_tuples.values()
    out_tuples.sort()
    
    rec = recommendation(out_tuples)
    return cur_artist, cur_album, out_tuples, rec
Ejemplo n.º 13
0
def tag_album(items, config, search_artist=None, search_album=None):
    """Bundles together the functionality used to infer tags for a
    set of items comprised by an album. Returns everything relevant:
        - The current artist.
        - The current album.
        - A list of (distance, items, info) tuples where info is a
          dictionary containing the inferred tags and items is a
          reordered version of the input items list. The candidates are
          sorted by distance (i.e., best match first).
        - A recommendation, one of RECOMMEND_STRONG, RECOMMEND_MEDIUM,
          or RECOMMEND_NONE; indicating that the first candidate is
          very likely, it is somewhat likely, or no conclusion could
          be reached.
    If search_artist and search_album are provided, then they are used
    as search terms in place of the current metadata.
    May raise an AutotagError if existing metadata is insufficient.
    """
    # Get current metadata.
    cur_artist, cur_album, artist_consensus = current_metadata(items)
    log.debug('Tagging %s - %s' % (cur_artist, cur_album))

    # The output result tuples (keyed by MB album ID).
    out_tuples = {}

    # Try to find album indicated by MusicBrainz IDs.
    id_info = match_by_id(items)
    if id_info:
        validate_candidate(items, out_tuples, id_info)
        if out_tuples:
            # If we have a very good MBID match, return immediately.
            # Otherwise, this match will compete against metadata-based
            # matches.
            rec = recommendation(out_tuples.values())
            if rec == RECOMMEND_STRONG and not config.interactive_autotag:
                log.debug('ID match.')
                return cur_artist, cur_album, out_tuples.values(), rec

    # Search terms.
    if not (search_artist and search_album):
        # No explicit search terms -- use current metadata.
        search_artist, search_album = cur_artist, cur_album
    log.debug(u'Search terms: %s - %s' % (search_artist, search_album))

    # Get candidate metadata from search.
    if search_artist and search_album:
        candidates = mb.match_album(search_artist, search_album, len(items),
                                    MAX_CANDIDATES)
        candidates = list(candidates)
    else:
        candidates = []

    # Possibly add "various artists" search.
    if search_album and ((not artist_consensus) or \
                         (search_artist.lower() in VA_ARTISTS) or \
                         any(item.comp for item in items)):
        log.debug(u'Possibly Various Artists; adding matches.')
        candidates.extend(
            mb.match_album(None, search_album, len(items), MAX_CANDIDATES))

    # Get candidates from plugins.
    candidates.extend(plugins.candidates(items))

    # Get the distance to each candidate.
    log.debug(u'Evaluating %i candidates.' % len(candidates))
    for info in candidates:
        validate_candidate(items, out_tuples, info)

    # Sort by distance.
    out_tuples = out_tuples.values()
    out_tuples.sort()

    rec = recommendation(out_tuples)
    return cur_artist, cur_album, out_tuples, rec