def on_action_hovered(self, action):
        """
        Fetch song.artists when artists_action is hovered. If it is
        already fetched, ignore.
        """
        data = action.data()
        if data is None:  # submenu action
            return

        def artists_fetched_cb(future):
            self._fetching_artists = False
            artists = future.result()  # ignore the potential exception
            if artists:
                for artist in artists:
                    artist_action = action.menu().addAction(artist.name)
                    # create a closure to bind variable artist
                    artist_action.triggered.connect(
                        (lambda x: lambda: self._app.browser.goto(model=x)
                         )(artist))
            data['artists'] = artists or []
            action.setData(data)

        # the action is artists_action
        if 'artists' in data:
            # artists value has not been fetched
            if data['artists'] is None and self._fetching_artists is False:
                logger.debug('fetch song.artists for actions')
                song = data['song']
                self._fetching_artists = True
                task = aio.run_in_executor(None, lambda: song.artists)
                task.add_done_callback(artists_fetched_cb)
Exemple #2
0
    async def a_search(self,
                       keyword,
                       source_in=None,
                       timeout=None,
                       type_in=None,
                       **kwargs):
        """async version of search

        TODO: add Happy Eyeballs requesting strategy if needed
        """
        type_in = SearchType.batch_parse(type_in) if type_in else [
            SearchType.so
        ]

        fs = []  # future list
        for provider in self._filter(identifier_in=source_in):
            for type_ in type_in:
                future = aio.run_in_executor(
                    None, partial(provider.search, keyword, type_=type_))
                fs.append(future)

        results = []
        # TODO: use async generator when we only support Python 3.6 or above
        for future in aio.as_completed(fs, timeout=timeout):
            try:
                result = await future
            except Exception as e:
                logger.exception(str(e))
            else:
                if result is not None:
                    results.append(result)
        return results
Exemple #3
0
    def on_song_changed(self, song):
        """bind song changed signal with this"""
        if song is None:
            self._set_lyric(None)
            return

        def cb(future):
            try:
                lyric = future.result()
            except:  # noqa
                logger.exception('get lyric failed')
                lyric = None
            self._set_lyric(lyric)

        # TODO: use app.task_mgr instead
        future = aio.run_in_executor(None, lambda: song.lyric)
        future.add_done_callback(cb)
Exemple #4
0
    async def a_search(self, keyword, source_in=None, timeout=None, **kwargs):
        """async version of search

        TODO: add Happy Eyeballs requesting strategy if needed
        """
        fs = []  # future list
        for provider in self._filter(identifier_in=source_in):
            future = aio.run_in_executor(None, provider.search, keyword)
            fs.append(future)
        result = []

        # TODO: use async generator when we only support Python 3.6 or above
        for future in aio.as_completed(fs, timeout=timeout):
            try:
                result.append(await future)
            except Exception as e:
                logger.exception(str(e))
        return result