예제 #1
0
    def run(self):
        total = float(len(self.import_collection))

        # to import, all essential fields should be identical!
        fields = [
            '__length', 'artist', 'album', 'title', 'genre', 'tracknumber'
        ]

        logger.info("Finding matches for %s imported tracks" %
                    len(self.import_collection))

        exact_dups = 0
        no_change = 0

        # determine which tracks in this collection match existing
        # tracks in the exaile collection. grab the groups from them
        for i, track in enumerate(self.import_collection):

            # search for a matching track
            # -> currently exaile doesn't index tracks, and linear searches
            #    for the track instead. Oh well.

            matchers = map(lambda t: TracksMatcher(track.get_tag_search(t)),
                           fields)
            matched_tracks = [
                r.track for r in search_tracks(self.user_collection, matchers)
            ]

            # if there are matches, add the data to the track data
            for matched_track in matched_tracks:

                # ignore exact duplicates
                if track is matched_track:
                    exact_dups += 1
                    continue

                old_group_str = ' '.join(get_track_groups(matched_track))
                newgroups = get_track_groups(track)
                new_group_str = ' '.join(newgroups)

                if old_group_str == new_group_str:
                    no_change += 1
                    continue

                self.track_data.append(
                    (old_group_str, new_group_str, matched_track, newgroups))

            glib.idle_add(self.emit, 'progress-update',
                          int(((i + 1) / total) * 100))

            if self.do_stop:
                return

        logger.info(
            "Match information: %s exact dups, %s no change, %s differing tracks"
            % (exact_dups, no_change, len(self.track_data)))

        glib.idle_add(self.emit, 'done')
예제 #2
0
def track_import_thread(import_collection, user_collection, track_data):
    '''
        Reads grouping information from tracks in a collection, and matches
        them with tracks contained in a separate collection.
    '''

    total = float(len(import_collection))

    # to import, all essential fields should be identical!
    fields = ['__length', 'artist', 'album', 'title', 'genre', 'tracknumber']

    logger.info("Finding matches for %s imported tracks",
                len(import_collection))

    exact_dups = 0
    no_change = 0

    # determine which tracks in this collection match existing
    # tracks in the exaile collection. grab the groups from them
    for i, track in enumerate(import_collection):

        # search for a matching track
        # -> currently exaile doesn't index tracks, and linear searches
        #    for the track instead. Oh well.

        matchers = map(lambda t: TracksMatcher(track.get_tag_search(t)),
                       fields)
        matched_tracks = [
            r.track for r in search_tracks(user_collection, matchers)
        ]

        # if there are matches, add the data to the track data
        for matched_track in matched_tracks:

            # ignore exact duplicates
            if track is matched_track:
                exact_dups += 1
                continue

            old_group_str = ' '.join(get_track_groups(matched_track))
            newgroups = get_track_groups(track)
            new_group_str = ' '.join(newgroups)

            if old_group_str == new_group_str:
                no_change += 1
                continue

            track_data.append(
                (old_group_str, new_group_str, matched_track, newgroups))

        yield (i, total)

    logger.info(
        "Match information: %s exact dups, %s no change, %s differing tracks",
        exact_dups,
        no_change,
        len(track_data),
    )
예제 #3
0
 def _find_tracks(self, iter):
     """
         finds tracks matching a given iter.
     """
     self.load_subtree(iter)
     search = self.get_node_search_terms(iter)
     matcher = trax.TracksMatcher(search)
     srtrs = trax.search_tracks(self.tracks, [matcher])
     return [ x.track for x in srtrs ]
예제 #4
0
 def _find_tracks(self, iter):
     """
         finds tracks matching a given iter.
     """
     self.load_subtree(iter)
     search = self.get_node_search_terms(iter)
     matcher = trax.TracksMatcher(search)
     srtrs = trax.search_tracks(self.tracks, [matcher])
     return [x.track for x in srtrs]
예제 #5
0
 def get_tracks_for_path(self, path):
     """
         Get tracks for a path from model (expand item)
         :param path: Gtk.TreePath
         :return: list of tracks [xl.trax.Track]
     """
     it = self.get_model().get_iter(path)
     search = self.container.get_node_search_terms(it)
     matcher = trax.TracksMatcher(search)
     for i in trax.search_tracks(self.container.tracks, [matcher]):
         yield i.track
예제 #6
0
파일: gt_import.py 프로젝트: exaile/exaile
def track_import_thread(import_collection, user_collection, track_data):
    '''
        Reads grouping information from tracks in a collection, and matches
        them with tracks contained in a separate collection.
    '''

    total = float(len(import_collection))

    # to import, all essential fields should be identical!
    fields = ['__length', 'artist', 'album', 'title', 'genre', 'tracknumber']

    logger.info("Finding matches for %s imported tracks", len(import_collection))

    exact_dups = 0
    no_change = 0

    # determine which tracks in this collection match existing
    # tracks in the exaile collection. grab the groups from them
    for i, track in enumerate(import_collection):

        # search for a matching track
        # -> currently exaile doesn't index tracks, and linear searches
        #    for the track instead. Oh well.

        matchers = map(lambda t: TracksMatcher(track.get_tag_search(t)), fields)
        matched_tracks = [r.track for r in search_tracks(user_collection, matchers)]

        # if there are matches, add the data to the track data
        for matched_track in matched_tracks:

            # ignore exact duplicates
            if track is matched_track:
                exact_dups += 1
                continue

            old_group_str = ' '.join(get_track_groups(matched_track))
            newgroups = get_track_groups(track)
            new_group_str = ' '.join(newgroups)

            if old_group_str == new_group_str:
                no_change += 1
                continue

            track_data.append((old_group_str, new_group_str, matched_track, newgroups))

        yield (i, total)

    logger.info(
        "Match information: %s exact dups, %s no change, %s differing tracks",
        exact_dups,
        no_change,
        len(track_data),
    )
예제 #7
0
 def run(self):
     total = float(len(self.import_collection))
     
     # to import, all essential fields should be identical!
     fields =  ['__length', 'artist', 'album', 'title', 'genre', 'tracknumber']
     
     logger.info("Finding matches for %s imported tracks" % len(self.import_collection))
     
     exact_dups = 0
     no_change = 0
     
     # determine which tracks in this collection match existing
     # tracks in the exaile collection. grab the groups from them
     for i, track in enumerate(self.import_collection):
         
         # search for a matching track 
         # -> currently exaile doesn't index tracks, and linear searches
         #    for the track instead. Oh well.
         
         matchers = map(lambda t: TracksMatcher(track.get_tag_search(t)), fields)
         matched_tracks = [r.track for r in search_tracks(self.user_collection, matchers)]
         
         # if there are matches, add the data to the track data
         for matched_track in matched_tracks:
         
             # ignore exact duplicates
             if track is matched_track:
                 exact_dups += 1
                 continue
         
             old_group_str = ' '.join(get_track_groups(matched_track))
             newgroups = get_track_groups(track)
             new_group_str = ' '.join(newgroups)
             
             if old_group_str == new_group_str:
                 no_change += 1
                 continue
         
             self.track_data.append((old_group_str, new_group_str, matched_track, newgroups))
     
         glib.idle_add(self.emit, 'progress-update', int(((i+1)/total)*100))
         
         if self.do_stop:
             return
         
     logger.info("Match information: %s exact dups, %s no change, %s differing tracks" % (exact_dups, no_change, len(self.track_data)))
     
     glib.idle_add(self.emit, 'done')    
예제 #8
0
    def load_subtree(self, parent):
        """
            Loads all the sub nodes for a specified node

            @param node: the node
        """
        previously_loaded = False # was the subtree already loaded
        iter_sep = None
        if parent == None:
            depth = 0
        else:
            if self.model.iter_n_children(parent) != 1 or \
                self.model.get_value(
                    self.model.iter_children(parent), 1) != None:
                previously_loaded = True
            iter_sep = self.model.iter_children(parent)
            depth = self.model.iter_depth(parent) + 1
        if previously_loaded:
            return

        search = self.get_node_search_terms(parent)

        try:
            tags = self.order.get_sort_tags(depth)
            matchers = [trax.TracksMatcher(search)]
            srtrs = trax.search_tracks(self.tracks, matchers)
            # sort only if we are not on top level, because tracks are 
            # already sorted by fist order
            if depth > 0:
                srtrs = trax.sort_result_tracks(tags, srtrs)
        except IndexError:
            return # at the bottom of the tree
        try:
            image = getattr(self, "%s_image"%tags[-1])
        except:
            image = None
        bottom = False
        if depth == len(self.order)-1:
            bottom = True


        display_counts = settings.get_option('gui/display_track_counts', True)
        draw_seps = settings.get_option('gui/draw_separators', True)
        last_char = ''
        last_val = ''
        last_dval = ''
        last_matchq = ''
        count = 0
        first = True
        path = None
        expanded = False
        to_expand = []

        for srtr in srtrs:
            stagvals = [unicode(srtr.track.get_tag_sort(x, artist_compilations=True)) for x in tags]
            stagval = " ".join(stagvals)
            if (last_val != stagval or bottom):
                tagval = self.order.format_track(depth, srtr.track)
                match_query = " ".join([
                    srtr.track.get_tag_search(t, format=True, artist_compilations=True) for t in tags])
                if bottom:
                    match_query += " " + \
                            srtr.track.get_tag_search("__loc", format=True, artist_compilations=True)

                # Different *sort tags can cause stagval to not match
                # but the below code will produce identical entries in
                # the displayed tree.  This condition checks to ensure
                # that new entries are added if and only if they will
                # display different results, avoiding that problem.
                if match_query != last_matchq or tagval != last_dval or bottom:
                    if display_counts and path and not bottom:
                        iter = self.model.get_iter(path)
                        val = self.model.get_value(iter, 1)
                        val = "%s (%s)"%(val, count)
                        self.model.set_value(iter, 1, val)
                        count = 0

                    last_val = stagval
                    last_dval = tagval
                    if depth == 0 and draw_seps:
                        val = srtr.track.get_tag_sort(tags[0], artist_compilations=True)
                        char = first_meaningful_char(val)
                        if first:
                            last_char = char
                        else:
                            if char != last_char and last_char != '':
                                self.model.append(parent, [None, None, None])
                            last_char = char
                    first = False

                    last_matchq = match_query
                    iter = self.model.append(parent, 
                        [image, tagval, match_query])
                    path = self.model.get_path(iter)
                    expanded = False
                    if not bottom:
                        self.model.append(iter, [None, None, None])
            count += 1
            if not expanded:
                alltags = []
                for i in range(depth+1, len(self.order)):
                    alltags.extend(self.order.get_sort_tags(i))
                for t in alltags:
                    if t in srtr.on_tags:
                        # keep original path intact for following block
                        newpath = path
                        if depth > 0:
                            # for some reason, nested iters are always
                            # off by one in the terminal entry.
                            newpath = Gtk.TreePath.new_from_indices(newpath[:-1] + [newpath[-1]-1])
                        to_expand.append(newpath)
                        expanded = True

        if display_counts and path and not bottom:
            iter = self.model.get_iter(path)
            val = self.model.get_value(iter, 1)
            val = "%s (%s)"%(val, count)
            self.model.set_value(iter, 1, val)
            count = 0

        if settings.get_option("gui/expand_enabled", True) and \
            len(to_expand) < \
                    settings.get_option("gui/expand_maximum_results", 100) and \
            len(self.keyword.strip()) >= \
                    settings.get_option("gui/expand_minimum_term_length", 2):
            for row in to_expand:
                GLib.idle_add(self.tree.expand_row, row, False)

        if iter_sep is not None:
            self.model.remove(iter_sep)
예제 #9
0
    def load_subtree(self, parent):
        """
            Loads all the sub nodes for a specified node

            @param node: the node
        """
        previously_loaded = False  # was the subtree already loaded
        iter_sep = None
        if parent is None:
            depth = 0
        else:
            if self.model.iter_n_children(parent) != 1 or \
                self.model.get_value(
                    self.model.iter_children(parent), 1) is not None:
                previously_loaded = True
            iter_sep = self.model.iter_children(parent)
            depth = self.model.iter_depth(parent) + 1
        if previously_loaded:
            return

        search = self.get_node_search_terms(parent)

        try:
            tags = self.order.get_sort_tags(depth)
            matchers = [trax.TracksMatcher(search)]
            srtrs = trax.search_tracks(self.tracks, matchers)
            # sort only if we are not on top level, because tracks are
            # already sorted by fist order
            if depth > 0:
                srtrs = trax.sort_result_tracks(tags, srtrs)
        except IndexError:
            return  # at the bottom of the tree
        try:
            image = getattr(self, "%s_image" % tags[-1])
        except Exception:
            image = None
        bottom = False
        if depth == len(self.order) - 1:
            bottom = True

        display_counts = settings.get_option('gui/display_track_counts', True)
        draw_seps = settings.get_option('gui/draw_separators', True)
        last_char = ''
        last_val = ''
        last_dval = ''
        last_matchq = ''
        count = 0
        first = True
        path = None
        expanded = False
        to_expand = []

        for srtr in srtrs:
            stagvals = [unicode(srtr.track.get_tag_sort(x)) for x in tags]
            stagval = " ".join(stagvals)
            if (last_val != stagval or bottom):
                tagval = self.order.format_track(depth, srtr.track)
                match_query = " ".join([
                    srtr.track.get_tag_search(t, format=True) for t in tags])
                if bottom:
                    match_query += " " + \
                        srtr.track.get_tag_search("__loc", format=True)

                # Different *sort tags can cause stagval to not match
                # but the below code will produce identical entries in
                # the displayed tree.  This condition checks to ensure
                # that new entries are added if and only if they will
                # display different results, avoiding that problem.
                if match_query != last_matchq or tagval != last_dval or bottom:
                    if display_counts and path and not bottom:
                        iter = self.model.get_iter(path)
                        val = self.model.get_value(iter, 1)
                        val = "%s (%s)" % (val, count)
                        self.model.set_value(iter, 1, val)
                        count = 0

                    last_val = stagval
                    last_dval = tagval
                    if depth == 0 and draw_seps:
                        val = srtr.track.get_tag_sort(tags[0])
                        char = first_meaningful_char(val)
                        if first:
                            last_char = char
                        else:
                            if char != last_char and last_char != '':
                                self.model.append(parent, [None, None, None])
                            last_char = char
                    first = False

                    last_matchq = match_query
                    iter = self.model.append(parent,
                                             [image, tagval, match_query])
                    path = self.model.get_path(iter)
                    expanded = False
                    if not bottom:
                        self.model.append(iter, [None, None, None])
            count += 1
            if not expanded:
                alltags = []
                for i in range(depth + 1, len(self.order)):
                    alltags.extend(self.order.get_sort_tags(i))
                for t in alltags:
                    if t in srtr.on_tags:
                        # keep original path intact for following block
                        newpath = path
                        if depth > 0:
                            # for some reason, nested iters are always
                            # off by one in the terminal entry.
                            newpath = Gtk.TreePath.new_from_indices(newpath[:-1] + [newpath[-1] - 1])
                        to_expand.append(newpath)
                        expanded = True

        if display_counts and path and not bottom:
            iter = self.model.get_iter(path)
            val = self.model.get_value(iter, 1)
            val = "%s (%s)" % (val, count)
            self.model.set_value(iter, 1, val)
            count = 0

        if settings.get_option("gui/expand_enabled", True) and \
                len(to_expand) < \
                settings.get_option("gui/expand_maximum_results", 100) and \
                len(self.keyword.strip()) >= \
                settings.get_option("gui/expand_minimum_term_length", 2):
            for row in to_expand:
                GLib.idle_add(self.tree.expand_row, row, False)

        if iter_sep is not None:
            self.model.remove(iter_sep)