예제 #1
0
    def on_import_task_before_choice(self, task, session):
        if hasattr(task, '_badfiles_checks_failed'):
            ui.print_('{} one or more files failed checks:'.format(
                ui.colorize('text_warning', 'BAD')))
            for error in task._badfiles_checks_failed:
                for error_line in error:
                    ui.print_(error_line)

            ui.print_()
            ui.print_('What would you like to do?')

            sel = ui.input_options(['aBort', 'skip', 'continue'])

            if sel == 's':
                return importer.action.SKIP
            elif sel == 'c':
                return None
            elif sel == 'b':
                raise importer.ImportAbort()
            else:
                raise Exception('Unexpected selection: {}'.format(sel))
예제 #2
0
def choose_candidate(candidates,
                     singleton,
                     rec,
                     color,
                     timid,
                     cur_artist=None,
                     cur_album=None,
                     item=None):
    """Given a sorted list of candidates, ask the user for a selection
    of which candidate to use. Applies to both full albums and 
    singletons  (tracks). For albums, the candidates are `(dist, items,
    info)` triples and `cur_artist` and `cur_album` must be provided.
    For singletons, the candidates are `(dist, info)` pairs and `item`
    must be provided.

    Returns the result of the choice, which may SKIP, ASIS, TRACKS, or
    MANUAL or a candidate. For albums, a candidate is a `(info, items)`
    pair; for items, it is just a TrackInfo object.
    """
    # Sanity check.
    if singleton:
        assert item is not None
    else:
        assert cur_artist is not None
        assert cur_album is not None

    # Zero candidates.
    if not candidates:
        print_("No match found.")
        if singleton:
            opts = ('Use as-is', 'Skip', 'Enter search', 'enter Id', 'aBort')
        else:
            opts = ('Use as-is', 'as Tracks', 'Skip', 'Enter search',
                    'enter Id', 'aBort')
        sel = ui.input_options(opts, color=color)
        if sel == 'u':
            return importer.action.ASIS
        elif sel == 't':
            assert not singleton
            return importer.action.TRACKS
        elif sel == 'e':
            return importer.action.MANUAL
        elif sel == 's':
            return importer.action.SKIP
        elif sel == 'b':
            raise importer.ImportAbort()
        elif sel == 'i':
            return importer.action.MANUAL_ID
        else:
            assert False

    # Is the change good enough?
    bypass_candidates = False
    if rec != autotag.RECOMMEND_NONE:
        if singleton:
            dist, info = candidates[0]
        else:
            dist, items, info = candidates[0]
        bypass_candidates = True

    while True:
        # Display and choose from candidates.
        if not bypass_candidates:
            # Display list of candidates.
            if singleton:
                print_('Finding tags for track "%s - %s".' %
                       (item.artist, item.title))
                print_('Candidates:')
                for i, (dist, info) in enumerate(candidates):
                    print_('%i. %s - %s (%s)' %
                           (i + 1, info.artist, info.title,
                            dist_string(dist, color)))
            else:
                print_('Finding tags for album "%s - %s".' %
                       (cur_artist, cur_album))
                print_('Candidates:')
                for i, (dist, items, info) in enumerate(candidates):
                    line = '%i. %s - %s' % (i + 1, info.artist, info.album)

                    # Label and year disambiguation, if available.
                    label, year = None, None
                    if info.label:
                        label = info.label
                    if info.year:
                        year = unicode(info.year)
                    if label and year:
                        line += u' [%s, %s]' % (label, year)
                    elif label:
                        line += u' [%s]' % label
                    elif year:
                        line += u' [%s]' % year

                    line += ' (%s)' % dist_string(dist, color)

                    # Point out the partial matches.
                    if None in items:
                        warning = PARTIAL_MATCH_MESSAGE
                        if color:
                            warning = ui.colorize('yellow', warning)
                        line += u' %s' % warning

                    print_(line)

            # Ask the user for a choice.
            if singleton:
                opts = ('Skip', 'Use as-is', 'Enter search', 'enter Id',
                        'aBort')
            else:
                opts = ('Skip', 'Use as-is', 'as Tracks', 'Enter search',
                        'enter Id', 'aBort')
            sel = ui.input_options(opts,
                                   numrange=(1, len(candidates)),
                                   color=color)
            if sel == 's':
                return importer.action.SKIP
            elif sel == 'u':
                return importer.action.ASIS
            elif sel == 'e':
                return importer.action.MANUAL
            elif sel == 't':
                assert not singleton
                return importer.action.TRACKS
            elif sel == 'b':
                raise importer.ImportAbort()
            elif sel == 'i':
                return importer.action.MANUAL_ID
            else:  # Numerical selection.
                if singleton:
                    dist, info = candidates[sel - 1]
                else:
                    dist, items, info = candidates[sel - 1]
        bypass_candidates = False

        # Show what we're about to do.
        if singleton:
            show_item_change(item, info, dist, color)
        else:
            show_change(cur_artist, cur_album, items, info, dist, color)

        # Exact match => tag automatically if we're not in timid mode.
        if rec == autotag.RECOMMEND_STRONG and not timid:
            if singleton:
                return info
            else:
                return info, items

        # Ask for confirmation.
        if singleton:
            opts = ('Apply', 'More candidates', 'Skip', 'Use as-is',
                    'Enter search', 'enter Id', 'aBort')
        else:
            opts = ('Apply', 'More candidates', 'Skip', 'Use as-is',
                    'as Tracks', 'Enter search', 'enter Id', 'aBort')
        sel = ui.input_options(opts, color=color)
        if sel == 'a':
            if singleton:
                return info
            else:
                return info, items
        elif sel == 'm':
            pass
        elif sel == 's':
            return importer.action.SKIP
        elif sel == 'u':
            return importer.action.ASIS
        elif sel == 't':
            assert not singleton
            return importer.action.TRACKS
        elif sel == 'e':
            return importer.action.MANUAL
        elif sel == 'b':
            raise importer.ImportAbort()
        elif sel == 'i':
            return importer.action.MANUAL_ID
예제 #3
0
def choose_candidate(candidates,
                     singleton,
                     rec,
                     cur_artist=None,
                     cur_album=None,
                     item=None,
                     itemcount=None):
    """Given a sorted list of candidates, ask the user for a selection
    of which candidate to use. Applies to both full albums and
    singletons  (tracks). Candidates are either AlbumMatch or TrackMatch
    objects depending on `singleton`. for albums, `cur_artist`,
    `cur_album`, and `itemcount` must be provided. For singletons,
    `item` must be provided.

    Returns the result of the choice, which may SKIP, ASIS, TRACKS, or
    MANUAL or a candidate (an AlbumMatch/TrackMatch object).
    """
    # Sanity check.
    if singleton:
        assert item is not None
    else:
        assert cur_artist is not None
        assert cur_album is not None

    # Zero candidates.
    if not candidates:
        if singleton:
            print_("No matching recordings found.")
            opts = ('Use as-is', 'Skip', 'Enter search', 'enter Id', 'aBort')
        else:
            print_(
                "No matching release found for {0} tracks.".format(itemcount))
            print_('For help, see: '
                   'https://github.com/sampsyo/beets/wiki/FAQ#wiki-nomatch')
            opts = ('Use as-is', 'as Tracks', 'Skip', 'Enter search',
                    'enter Id', 'aBort')
        sel = ui.input_options(opts)
        if sel == 'u':
            return importer.action.ASIS
        elif sel == 't':
            assert not singleton
            return importer.action.TRACKS
        elif sel == 'e':
            return importer.action.MANUAL
        elif sel == 's':
            return importer.action.SKIP
        elif sel == 'b':
            raise importer.ImportAbort()
        elif sel == 'i':
            return importer.action.MANUAL_ID
        else:
            assert False

    # Is the change good enough?
    bypass_candidates = False
    if rec != recommendation.none:
        match = candidates[0]
        bypass_candidates = True

    while True:
        # Display and choose from candidates.
        require = rec <= recommendation.low

        if not bypass_candidates:
            # Display list of candidates.
            if singleton:
                print_('Finding tags for track "%s - %s".' %
                       (item.artist, item.title))
                print_('Candidates:')
                for i, match in enumerate(candidates):
                    print_('%i. %s - %s (%s)' %
                           (i + 1, match.info.artist, match.info.title,
                            dist_string(match.distance)))
            else:
                print_('Finding tags for album "%s - %s".' %
                       (cur_artist, cur_album))
                print_('Candidates:')
                for i, match in enumerate(candidates):
                    line = [
                        '%i. %s - %s (%s)' %
                        (i + 1, match.info.artist, match.info.album,
                         dist_string(match.distance))
                    ]

                    # Point out the partial matches.
                    if match.extra_items or match.extra_tracks:
                        line.append(
                            ui.colorize('yellow', PARTIAL_MATCH_MESSAGE))

                    # Sources other than MusicBrainz.
                    source = match.info.data_source
                    if source != 'MusicBrainz':
                        line.append(ui.colorize('turquoise', '(%s)' % source))

                    disambig = disambig_string(match.info)
                    if disambig:
                        line.append(ui.colorize('lightgray',
                                                '(%s)' % disambig))

                    print_(' '.join(line))

            # Ask the user for a choice.
            if singleton:
                opts = ('Skip', 'Use as-is', 'Enter search', 'enter Id',
                        'aBort')
            else:
                opts = ('Skip', 'Use as-is', 'as Tracks', 'Enter search',
                        'enter Id', 'aBort')
            sel = ui.input_options(opts, numrange=(1, len(candidates)))
            if sel == 's':
                return importer.action.SKIP
            elif sel == 'u':
                return importer.action.ASIS
            elif sel == 'e':
                return importer.action.MANUAL
            elif sel == 't':
                assert not singleton
                return importer.action.TRACKS
            elif sel == 'b':
                raise importer.ImportAbort()
            elif sel == 'i':
                return importer.action.MANUAL_ID
            else:  # Numerical selection.
                match = candidates[sel - 1]
                if sel != 1:
                    # When choosing anything but the first match,
                    # disable the default action.
                    require = True
        bypass_candidates = False

        # Show what we're about to do.
        if singleton:
            show_item_change(item, match)
        else:
            show_change(cur_artist, cur_album, match)

        # Exact match => tag automatically if we're not in timid mode.
        if rec == recommendation.strong and not config['import']['timid']:
            return match

        # Ask for confirmation.
        if singleton:
            opts = ('Apply', 'More candidates', 'Skip', 'Use as-is',
                    'Enter search', 'enter Id', 'aBort')
        else:
            opts = ('Apply', 'More candidates', 'Skip', 'Use as-is',
                    'as Tracks', 'Enter search', 'enter Id', 'aBort')
        default = config['import']['default_action'].as_choice({
            'apply': 'a',
            'skip': 's',
            'asis': 'u',
            'none': None,
        })
        if default is None:
            require = True
        sel = ui.input_options(opts, require=require, default=default)
        if sel == 'a':
            return match
        elif sel == 'm':
            pass
        elif sel == 's':
            return importer.action.SKIP
        elif sel == 'u':
            return importer.action.ASIS
        elif sel == 't':
            assert not singleton
            return importer.action.TRACKS
        elif sel == 'e':
            return importer.action.MANUAL
        elif sel == 'b':
            raise importer.ImportAbort()
        elif sel == 'i':
            return importer.action.MANUAL_ID
예제 #4
0
파일: commands.py 프로젝트: silky/beets
def choose_candidate(candidates,
                     singleton,
                     rec,
                     cur_artist=None,
                     cur_album=None,
                     item=None,
                     itemcount=None):
    """Given a sorted list of candidates, ask the user for a selection
    of which candidate to use. Applies to both full albums and
    singletons  (tracks). Candidates are either AlbumMatch or TrackMatch
    objects depending on `singleton`. for albums, `cur_artist`,
    `cur_album`, and `itemcount` must be provided. For singletons,
    `item` must be provided.

    Returns the result of the choice, which may SKIP, ASIS, TRACKS, or
    MANUAL or a candidate (an AlbumMatch/TrackMatch object).
    """
    # Sanity check.
    if singleton:
        assert item is not None
    else:
        assert cur_artist is not None
        assert cur_album is not None

    # Zero candidates.
    if not candidates:
        if singleton:
            print_("No matching recordings found.")
            opts = ('Use as-is', 'Skip', 'Enter search', 'enter Id', 'aBort')
        else:
            print_(
                "No matching release found for {0} tracks.".format(itemcount))
            print_('For help, see: '
                   'http://beets.readthedocs.org/en/latest/faq.html#nomatch')
            opts = ('Use as-is', 'as Tracks', 'Skip', 'Enter search',
                    'enter Id', 'aBort')
        sel = ui.input_options(opts)
        if sel == 'u':
            return importer.action.ASIS
        elif sel == 't':
            assert not singleton
            return importer.action.TRACKS
        elif sel == 'e':
            return importer.action.MANUAL
        elif sel == 's':
            return importer.action.SKIP
        elif sel == 'b':
            raise importer.ImportAbort()
        elif sel == 'i':
            return importer.action.MANUAL_ID
        else:
            assert False

    # Is the change good enough?
    bypass_candidates = False
    if rec != recommendation.none:
        match = candidates[0]
        bypass_candidates = True

    while True:
        # Display and choose from candidates.
        require = rec <= recommendation.low

        if not bypass_candidates:
            # Display list of candidates.
            print_(u'Finding tags for {0} "{1} - {2}".'.format(
                u'track' if singleton else u'album',
                item.artist if singleton else cur_artist,
                item.title if singleton else cur_album,
            ))

            print_(u'Candidates:')
            for i, match in enumerate(candidates):
                # Index, metadata, and distance.
                line = [
                    u'{0}.'.format(i + 1),
                    u'{0} - {1}'.format(
                        match.info.artist,
                        match.info.title if singleton else match.info.album,
                    ),
                    u'({0})'.format(dist_string(match.distance)),
                ]

                # Penalties.
                penalties = penalty_string(match.distance, 3)
                if penalties:
                    line.append(penalties)

                # Disambiguation
                disambig = disambig_string(match.info)
                if disambig:
                    line.append(ui.colorize('lightgray', '(%s)' % disambig))

                print_(' '.join(line))

            # Ask the user for a choice.
            if singleton:
                opts = ('Skip', 'Use as-is', 'Enter search', 'enter Id',
                        'aBort')
            else:
                opts = ('Skip', 'Use as-is', 'as Tracks', 'Enter search',
                        'enter Id', 'aBort')
            sel = ui.input_options(opts, numrange=(1, len(candidates)))
            if sel == 's':
                return importer.action.SKIP
            elif sel == 'u':
                return importer.action.ASIS
            elif sel == 'e':
                return importer.action.MANUAL
            elif sel == 't':
                assert not singleton
                return importer.action.TRACKS
            elif sel == 'b':
                raise importer.ImportAbort()
            elif sel == 'i':
                return importer.action.MANUAL_ID
            else:  # Numerical selection.
                match = candidates[sel - 1]
                if sel != 1:
                    # When choosing anything but the first match,
                    # disable the default action.
                    require = True
        bypass_candidates = False

        # Show what we're about to do.
        if singleton:
            show_item_change(item, match)
        else:
            show_change(cur_artist, cur_album, match)

        # Exact match => tag automatically if we're not in timid mode.
        if rec == recommendation.strong and not config['import']['timid']:
            return match

        # Ask for confirmation.
        if singleton:
            opts = ('Apply', 'More candidates', 'Skip', 'Use as-is',
                    'Enter search', 'enter Id', 'aBort')
        else:
            opts = ('Apply', 'More candidates', 'Skip', 'Use as-is',
                    'as Tracks', 'Enter search', 'enter Id', 'aBort')
        default = config['import']['default_action'].as_choice({
            'apply': 'a',
            'skip': 's',
            'asis': 'u',
            'none': None,
        })
        if default is None:
            require = True
        sel = ui.input_options(opts, require=require, default=default)
        if sel == 'a':
            return match
        elif sel == 'm':
            pass
        elif sel == 's':
            return importer.action.SKIP
        elif sel == 'u':
            return importer.action.ASIS
        elif sel == 't':
            assert not singleton
            return importer.action.TRACKS
        elif sel == 'e':
            return importer.action.MANUAL
        elif sel == 'b':
            raise importer.ImportAbort()
        elif sel == 'i':
            return importer.action.MANUAL_ID
예제 #5
0
def choose_candidate(candidates,
                     singleton,
                     rec,
                     color,
                     timid,
                     cur_artist=None,
                     cur_album=None,
                     item=None,
                     itemcount=None,
                     per_disc_numbering=False):
    """Given a sorted list of candidates, ask the user for a selection
    of which candidate to use. Applies to both full albums and
    singletons  (tracks). Candidates are either AlbumMatch or TrackMatch
    objects depending on `singleton`. for albums, `cur_artist`,
    `cur_album`, and `itemcount` must be provided. For singletons,
    `item` must be provided.

    Returns the result of the choice, which may SKIP, ASIS, TRACKS, or
    MANUAL or a candidate (an AlbumMatch/TrackMatch object).
    """
    # Sanity check.
    if singleton:
        assert item is not None
    else:
        assert cur_artist is not None
        assert cur_album is not None

    # Zero candidates.
    if not candidates:
        if singleton:
            print_("No matching recordings found.")
            opts = ('Use as-is', 'Skip', 'Enter search', 'enter Id', 'aBort')
        else:
            print_(
                "No matching release found for {0} tracks.".format(itemcount))
            print_('For help, see: '
                   'https://github.com/sampsyo/beets/wiki/FAQ#wiki-nomatch')
            opts = ('Use as-is', 'as Tracks', 'Skip', 'Enter search',
                    'enter Id', 'aBort')
        sel = ui.input_options(opts, color=color)
        if sel == 'u':
            return importer.action.ASIS
        elif sel == 't':
            assert not singleton
            return importer.action.TRACKS
        elif sel == 'e':
            return importer.action.MANUAL
        elif sel == 's':
            return importer.action.SKIP
        elif sel == 'b':
            raise importer.ImportAbort()
        elif sel == 'i':
            return importer.action.MANUAL_ID
        else:
            assert False

    # Is the change good enough?
    bypass_candidates = False
    if rec != autotag.RECOMMEND_NONE:
        match = candidates[0]
        bypass_candidates = True

    while True:
        # Display and choose from candidates.
        if not bypass_candidates:
            # Display list of candidates.
            if singleton:
                print_('Finding tags for track "%s - %s".' %
                       (item.artist, item.title))
                print_('Candidates:')
                for i, match in enumerate(candidates):
                    print_('%i. %s - %s (%s)' %
                           (i + 1, match.info.artist, match.info.title,
                            dist_string(match.distance, color)))
            else:
                print_('Finding tags for album "%s - %s".' %
                       (cur_artist, cur_album))
                print_('Candidates:')
                for i, match in enumerate(candidates):
                    line = '%i. %s - %s' % (i + 1, match.info.artist,
                                            match.info.album)

                    # Label and year disambiguation, if available.
                    label, year = None, None
                    if match.info.label:
                        label = match.info.label
                    if match.info.year:
                        year = unicode(match.info.year)
                    if label and year:
                        line += u' [%s, %s]' % (label, year)
                    elif label:
                        line += u' [%s]' % label
                    elif year:
                        line += u' [%s]' % year

                    line += ' (%s)' % dist_string(match.distance, color)

                    # Point out the partial matches.
                    if match.extra_items or match.extra_tracks:
                        warning = PARTIAL_MATCH_MESSAGE
                        if color:
                            warning = ui.colorize('yellow', warning)
                        line += u' %s' % warning

                    print_(line)

            # Ask the user for a choice.
            if singleton:
                opts = ('Skip', 'Use as-is', 'Enter search', 'enter Id',
                        'aBort')
            else:
                opts = ('Skip', 'Use as-is', 'as Tracks', 'Enter search',
                        'enter Id', 'aBort')
            sel = ui.input_options(opts,
                                   numrange=(1, len(candidates)),
                                   color=color)
            if sel == 's':
                return importer.action.SKIP
            elif sel == 'u':
                return importer.action.ASIS
            elif sel == 'e':
                return importer.action.MANUAL
            elif sel == 't':
                assert not singleton
                return importer.action.TRACKS
            elif sel == 'b':
                raise importer.ImportAbort()
            elif sel == 'i':
                return importer.action.MANUAL_ID
            else:  # Numerical selection.
                if singleton:
                    match = candidates[sel - 1]
                else:
                    match = candidates[sel - 1]
        bypass_candidates = False

        # Show what we're about to do.
        if singleton:
            show_item_change(item, match, color)
        else:
            show_change(cur_artist, cur_album, match, color,
                        per_disc_numbering)

        # Exact match => tag automatically if we're not in timid mode.
        if rec == autotag.RECOMMEND_STRONG and not timid:
            return match

        # Ask for confirmation.
        if singleton:
            opts = ('Apply', 'More candidates', 'Skip', 'Use as-is',
                    'Enter search', 'enter Id', 'aBort')
        else:
            opts = ('Apply', 'More candidates', 'Skip', 'Use as-is',
                    'as Tracks', 'Enter search', 'enter Id', 'aBort')
        sel = ui.input_options(opts, color=color)
        if sel == 'a':
            return match
        elif sel == 'm':
            pass
        elif sel == 's':
            return importer.action.SKIP
        elif sel == 'u':
            return importer.action.ASIS
        elif sel == 't':
            assert not singleton
            return importer.action.TRACKS
        elif sel == 'e':
            return importer.action.MANUAL
        elif sel == 'b':
            raise importer.ImportAbort()
        elif sel == 'i':
            return importer.action.MANUAL_ID
예제 #6
0
def choose_candidate(candidates,
                     singleton,
                     rec,
                     cur_artist=None,
                     cur_album=None,
                     item=None,
                     itemcount=None,
                     extra_choices=[]):
    """Given a sorted list of candidates, ask the user for a selection
    of which candidate to use. Applies to both full albums and
    singletons  (tracks). Candidates are either AlbumMatch or TrackMatch
    objects depending on `singleton`. for albums, `cur_artist`,
    `cur_album`, and `itemcount` must be provided. For singletons,
    `item` must be provided.

    `extra_choices` is a list of `PromptChoice`s, containg the choices
    appended by the plugins after receiving the `before_choose_candidate`
    event. If not empty, the choices are appended to the prompt presented
    to the user.

    Returns one of the following:
    * the result of the choice, which may be SKIP, ASIS, TRACKS, or MANUAL
    * a candidate (an AlbumMatch/TrackMatch object)
    * the short letter of a `PromptChoice` (if the user selected one of
    the `extra_choices`).
    """
    # Sanity check.
    assert not singleton
    assert cur_artist is not None
    assert cur_album is not None

    # Zero candidates.
    if not candidates:
        print_(u"No matching release found for {0} tracks.".format(itemcount))
        print_(u'For help, see: '
               u'http://beets.readthedocs.org/en/latest/faq.html#nomatch')
        opts = (u'Skip', u'Enter search', u'enter Id', u'aBort')
        sel = ui.input_options(opts)
        if sel == u'e':
            return importer.action.MANUAL
        elif sel == u's':
            return importer.action.SKIP
        elif sel == u'b':
            raise importer.ImportAbort()
        elif sel == u'i':
            return importer.action.MANUAL_ID
        else:
            assert False

    while True:
        # Display and choose from candidates.
        require = rec <= Recommendation.low

        # Display list of candidates.
        print_(u'Finding tags for {0} "{1} - {2}".'.format(
            u'album',
            cur_artist,
            cur_album,
        ))

        print_(u'Candidates:')
        for i, match in enumerate(candidates):
            # Index, metadata, and distance.
            line = [
                u'{0}.'.format(i + 1),
                u'{0} - {1}'.format(
                    match.info.artist,
                    match.info.album,
                ),
                u'({0})'.format(dist_string(match.distance)),
            ]

            # Penalties.
            penalties = penalty_string(match.distance, 3)
            if penalties:
                line.append(penalties)

            # Disambiguation
            disambig = disambig_string(match.info)
            if disambig:
                line.append(
                    ui.colorize('text_highlight_minor', u'(%s)' % disambig))

            print_(u' '.join(line))

        # Ask the user for a choice.
        opts = (u'Skip', u'Enter search', u'enter Id', u'aBort')
        sel = ui.input_options(opts, numrange=(1, len(candidates)))
        if sel == u's':
            return importer.action.SKIP
        elif sel == u'e':
            return importer.action.MANUAL
        elif sel == u'b':
            raise importer.ImportAbort()
        elif sel == u'i':
            return importer.action.MANUAL_ID
        else:  # Numerical selection.
            match = candidates[sel - 1]
            if sel != 1:
                # When choosing anything but the first match,
                # disable the default action.
                require = True

        # Show what we're about to do.
        show_change(cur_artist, cur_album, match)

        # Exact match => tag automatically.
        if rec == Recommendation.strong:
            return match

        # Ask for confirmation.
        opts = (u'Apply', u'More candidates', u'Skip', u'Enter search',
                u'enter Id', u'aBort')
        default = config['import']['default_action'].as_choice({
            u'apply': u'a',
            u'skip': u's',
            u'none': None,
        })
        if default is None:
            require = True
        sel = ui.input_options(opts, require=require, default=default)
        if sel == u'a':
            return match
        elif sel == u's':
            return importer.action.SKIP
        elif sel == u'e':
            return importer.action.MANUAL
        elif sel == u'b':
            raise importer.ImportAbort()
        elif sel == u'i':
            return importer.action.MANUAL_ID
예제 #7
0
def choose_candidate(candidates,
                     singleton,
                     rec,
                     color,
                     interactive_autotag,
                     cur_artist=None,
                     cur_album=None,
                     item=None):
    """Given a sorted list of candidates, ask the user for a selection
    of which candidate to use. Applies to both full albums and 
    singletons  (tracks). For albums, the candidates are `(dist, items,
    info)` triples and `cur_artist` and `cur_album` must be provided.
    For singletons, the candidates are `(dist, info)` pairs and `item`
    must be provided.

    Returns the result of the choice, which may SKIP, ASIS, TRACKS, or
    MANUAL or a candidate. For albums, a candidate is a `(info, items)`
    pair; for items, it is just an `info` dictionary.
    """
    # Sanity check.
    if singleton:
        assert item is not None
    else:
        assert cur_artist is not None
        assert cur_album is not None

    # Zero candidates.
    if not candidates:
        print_("No match found.")
        if singleton:
            opts = ('Use as-is', 'Skip', 'Enter search', 'aBort')
        else:
            opts = ('Use as-is', 'as Tracks', 'Skip', 'Enter search', 'aBort')
        sel = ui.input_options(opts)
        if sel == 'u':
            return importer.action.ASIS
        elif sel == 't':
            assert not singleton
            return importer.action.TRACKS
        elif sel == 'e':
            return importer.action.MANUAL
        elif sel == 's':
            return importer.action.SKIP
        elif sel == 'b':
            raise importer.ImportAbort()
        else:
            assert False

    # Is the change good enough?
    bypass_candidates = False
    if rec != autotag.RECOMMEND_NONE:
        if singleton:
            dist, info = candidates[0]
        else:
            dist, items, info = candidates[0]
        bypass_candidates = True

    while True:
        # Display and choose from candidates.
        if not bypass_candidates:
            # Display list of candidates.
            if singleton:
                print_('Finding tags for track "%s - %s".' %
                       (item.artist, item.title))
                print_('Candidates:')
                for i, (dist, info) in enumerate(candidates):
                    print_('%i. %s - %s (%s)' %
                           (i + 1, info['artist'], info['title'],
                            dist_string(dist, color)))
            else:
                print_('Finding tags for album "%s - %s".' %
                       (cur_artist, cur_album))
                print_('Candidates:')
                for i, (dist, items, info) in enumerate(candidates):
                    print_('%i. %s - %s (%s)' %
                           (i + 1, info['artist'], info['album'],
                            dist_string(dist, color)))

            # Ask the user for a choice.
            if singleton:
                opts = ('Skip', 'Use as-is', 'Enter search', 'aBort')
            else:
                opts = ('Skip', 'Use as-is', 'as Tracks', 'Enter search',
                        'aBort')
            sel = ui.input_options(opts, numrange=(1, len(candidates)))
            if sel == 's':
                return importer.action.SKIP
            elif sel == 'u':
                return importer.action.ASIS
            elif sel == 'e':
                return importer.action.MANUAL
            elif sel == 't':
                assert not singleton
                return importer.action.TRACKS
            elif sel == 'b':
                raise importer.ImportAbort()
            else:  # Numerical selection.
                if singleton:
                    dist, info = candidates[sel - 1]
                else:
                    dist, items, info = candidates[sel - 1]
        bypass_candidates = False

        # Show what we're about to do.
        if singleton:
            show_item_change(item, info, dist, color)
        else:
            show_change(cur_artist, cur_album, items, info, dist, color)

        # Exact match => tag automatically if no interactive tagging is requested.
        if rec == autotag.RECOMMEND_STRONG and not interactive_autotag:
            if singleton:
                return info
            else:
                return info, items

        # Ask for confirmation.
        if singleton:
            opts = ('Apply', 'More candidates', 'Skip', 'Use as-is',
                    'Enter search', 'aBort')
        else:
            opts = ('Apply', 'More candidates', 'Skip', 'Use as-is',
                    'as Tracks', 'Enter search', 'aBort')
        sel = ui.input_options(opts)
        if sel == 'a':
            if singleton:
                return info
            else:
                return info, items
        elif sel == 'm':
            pass
        elif sel == 's':
            return importer.action.SKIP
        elif sel == 'u':
            return importer.action.ASIS
        elif sel == 't':
            assert not singleton
            return importer.action.TRACKS
        elif sel == 'e':
            return importer.action.MANUAL
        elif sel == 'b':
            raise importer.ImportAbort()