Example #1
0
    def update(self, media):
        """Update the stack with the given media

        Update the stack with the art retrieved from the given media.
        :param Grl.Media media: The media object
        """
        self._active_child = self._stack.get_visible_child_name()

        art = Art(self._size, media, self._scale)
        self._handler_id = art.connect('finished', self._art_retrieved)
        art.lookup()
Example #2
0
    def _add_item(self, source, param, item, remaining=0, data=None):
        if data is None:
            return

        model, category = data

        self._items_found = (
            self.model.iter_n_children(self._head_iters[0])
            + self.model.iter_n_children(self._head_iters[1])
            + self.model.iter_n_children(self._head_iters[2])
            + self.model.iter_n_children(self._head_iters[3])
        )

        if (category == 'song'
                and self._items_found == 0
                and remaining == 0):
            if grilo.search_source:
                self.emit('no-music-found')

        # We need to remember the view before the search view
        emptysearchview = self._window.views[View.EMPTY_SEARCH]
        if (self._window.curr_view != emptysearchview
                and self._window.prev_view != emptysearchview):
            self.previous_view = self._window.prev_view

        if remaining == 0:
            self._window.notifications_popup.pop_loading()
            self._view.show()

        if not item or model != self.model:
            return

        self._offset += 1
        title = utils.get_media_title(item)
        item.set_title(title)
        artist = utils.get_artist_name(item)

        group = 3
        try:
            group = {'album': 0, 'artist': 1, 'song': 2}[category]
        except:
            pass

        _iter = None
        if category == 'album':
            _iter = self.model.insert_with_values(
                self._head_iters[group], -1, [0, 2, 3, 5, 9, 11],
                [str(item.get_id()), title, artist, item, 2,
                 category])
        elif category == 'song':
            # FIXME: source specific hack
            if source.get_id() != 'grl-tracker-source':
                fav = 2
            else:
                fav = item.get_favourite()
            _iter = self.model.insert_with_values(
                self._head_iters[group], -1, [0, 2, 3, 5, 9, 11],
                [str(item.get_id()), title, artist, item, fav,
                 category])
        else:
            if not artist.casefold() in self._artists:
                _iter = self.model.insert_with_values(
                    self._head_iters[group], -1, [0, 2, 5, 9, 11],
                    [str(item.get_id()), artist, item, 2,
                     category])
                self._artists[artist.casefold()] = {
                    'iter': _iter,
                    'albums': []
                }
            self._artists[artist.casefold()]['albums'].append(item)

        # FIXME: Figure out why iter can be None here, seems illogical.
        if _iter is not None:
            scale = self._view.get_scale_factor()
            art = Art(Art.Size.SMALL, item, scale)
            self.model[_iter][13] = art.surface
            art.connect(
                'finished', self._retrieval_finished, self.model, _iter)
            art.lookup()

        if self.model.iter_n_children(self._head_iters[group]) == 1:
            path = self.model.get_path(self._head_iters[group])
            path = self._filter_model.convert_child_path_to_path(path)
            self._view.get_generic_view().expand_row(path, False)
Example #3
0
class CoverStack(Gtk.Stack):
    """Provides a smooth transition between image states

    Uses a Gtk.Stack to provide an in-situ transition between an image
    state. Either between the 'loading' state versus the 'loaded' state
    or in between songs.
    """

    __gtype_name__ = 'CoverStack'

    __gsignals__ = {'updated': (GObject.SignalFlags.RUN_FIRST, None, ())}

    _default_icon = DefaultIcon()

    def __repr__(self):
        return '<CoverStack>'

    @log
    def __init__(self, size=Art.Size.MEDIUM):
        """Initialize the CoverStack

        :param Art.Size size: The size of the art used for the cover
        """
        super().__init__()

        self._art = None
        self._handler_id = None
        self._size = None
        self._timeout = None

        self._loading_cover = Gtk.Image()
        self._cover_a = Gtk.Image()
        self._cover_b = Gtk.Image()

        self.add_named(self._loading_cover, "loading")
        self.add_named(self._cover_a, "A")
        self.add_named(self._cover_b, "B")

        self.props.size = size
        self.props.transition_type = Gtk.StackTransitionType.CROSSFADE
        self.props.visible_child_name = "loading"

        self.show_all()

    @GObject.Property(type=object, flags=GObject.ParamFlags.READWRITE)
    def size(self):
        """Size of the cover

        :returns: The size used
        :rtype: Art.Size
        """
        return self._size

    @size.setter
    def size(self, value):
        """Set the cover size

        :param Art.Size value: The size to use for the cover
        """
        self._size = value

        icon = self._default_icon.get(DefaultIcon.Type.LOADING,
                                      self.props.size, self.props.scale_factor)
        self._loading_cover.props.surface = icon

    @log
    def update(self, coresong):
        """Update the stack with the given CoreSong

        Update the stack with the art retrieved from the given Coresong.
        :param CoreSong coresong: The CoreSong object
        """
        if self._handler_id and self._art:
            # Remove a possible dangling 'finished' callback if update
            # is called again, but it is still looking for the previous
            # art.
            self._art.disconnect(self._handler_id)
            # Set the loading state only after a delay to make between
            # song transitions smooth if loading time is negligible.
            self._timeout = GLib.timeout_add(100, self._set_loading_child)

        self._active_child = self.props.visible_child_name

        self._art = Art(self.props.size, coresong, self.props.scale_factor)
        self._handler_id = self._art.connect('finished', self._art_retrieved)
        self._art.lookup()

    @log
    def _set_loading_child(self):
        self.props.visible_child_name = "loading"
        self._active_child = self.props.visible_child_name
        self._timeout = None

        return GLib.SOURCE_REMOVE

    @log
    def _art_retrieved(self, klass):
        if self._timeout:
            GLib.source_remove(self._timeout)
            self._timeout = None

        if self._active_child == "B":
            self._cover_a.props.surface = klass.surface
            self.props.visible_child_name = "A"
        else:
            self._cover_b.props.surface = klass.surface
            self.props.visible_child_name = "B"

        self._active_child = self.props.visible_child_name
        self._art = None

        self.emit('updated')
Example #4
0
class ArtistArtStack(Gtk.Stack):
    """Provides a smooth transition between image states

    Uses a Gtk.Stack to provide an in-situ transition between an image
    state. Either between the "loading" state versus the "loaded" state
    or in between songs.
    """

    __gtype_name__ = "ArtistArtStack"

    _default_icon = DefaultIcon()

    def __repr__(self):
        return "ArtistArtStack"

    @log
    def __init__(self, size=Art.Size.MEDIUM):
        """Initialize the CoverStack

        :param Art.Size size: The size of the art used for the cover
        """
        super().__init__()

        self._art = None
        self._handler_id = None
        self._size = None
        self._timeout = None

        self._loading_cover = Gtk.Image()
        self._cover_a = Gtk.Image()
        self._cover_b = Gtk.Image()

        self.add_named(self._loading_cover, "loading")
        self.add_named(self._cover_a, "A")
        self.add_named(self._cover_b, "B")

        self._active_child = "loading"

        self.props.size = size
        self.props.transition_type = Gtk.StackTransitionType.CROSSFADE
        self.props.visible_child_name = "loading"

        self.show_all()

    @GObject.Property(type=object, flags=GObject.ParamFlags.READWRITE)
    def size(self):
        """Size of the cover

        :returns: The size used
        :rtype: Art.Size
        """
        return self._size

    @size.setter
    def size(self, value):
        """Set the cover size

        :param Art.Size value: The size to use for the cover
        """
        self._size = value

        icon = self._default_icon.get(DefaultIcon.Type.LOADING,
                                      self.props.size, self.props.scale_factor)
        self._loading_cover.props.surface = icon

    @GObject.Property(type=CoreArtist, default=None)
    def coreartist(self):
        return self._coreartist

    @coreartist.setter
    def coreartist(self, coreartist):
        self._coreartist = coreartist

        self._coreartist.connect("notify::cached-thumbnail-uri",
                                 self._on_thumbnail_changed)

        if self._coreartist.props.thumbnail is not None:
            self._on_thumbnail_changed(self._coreartist, None)

    def _on_thumbnail_changed(self, coreartist, uri):
        cache = ArtistCache(self.props.size, self.props.scale_factor)
        cache.connect("result", self._on_cache_result)

        cache.query(coreartist)

    def _on_cache_result(self, cache, surface):
        if self._active_child == "B":
            self._cover_a.props.surface = surface
            self.props.visible_child_name = "A"
        else:
            self._cover_b.props.surface = surface
            self.props.visible_child_name = "B"

    @log
    def update(self, coresong):
        """Update the stack with the given CoreSong

        Update the stack with the art retrieved from the given Coresong.
        :param CoreSong coresong: The CoreSong object
        """
        if self._handler_id and self._art:
            # Remove a possible dangling "finished" callback if update
            # is called again, but it is still looking for the previous
            # art.
            self._art.disconnect(self._handler_id)
            # Set the loading state only after a delay to make between
            # song transitions smooth if loading time is negligible.
            self._timeout = GLib.timeout_add(100, self._set_loading_child)

        self._active_child = self.props.visible_child_name

        self._art = Art(self.props.size, coresong, self.props.scale_factor)
        self._handler_id = self._art.connect("finished", self._art_retrieved)
        self._art.lookup()

    @log
    def _set_loading_child(self):
        self.props.visible_child_name = "loading"
        self._active_child = self.props.visible_child_name
        self._timeout = None

        return GLib.SOURCE_REMOVE

    @log
    def _art_retrieved(self, klass):
        if self._timeout:
            GLib.source_remove(self._timeout)
            self._timeout = None

        if self._active_child == "B":
            self._cover_a.props.surface = klass.surface
            self.props.visible_child_name = "A"
        else:
            self._cover_b.props.surface = klass.surface
            self.props.visible_child_name = "B"

        self._active_child = self.props.visible_child_name
        self._art = None
Example #5
0
class CoverStack(Gtk.Stack):
    """Provides a smooth transition between image states

    Uses a Gtk.Stack to provide an in-situ transition between an image
    state. Either between the 'loading' state versus the 'loaded' state
    or in between songs.
    """

    __gtype_name__ = 'CoverStack'

    __gsignals__ = {
        'updated': (GObject.SignalFlags.RUN_FIRST, None, ())
    }

    _default_icon = DefaultIcon()

    def __repr__(self):
        return '<CoverStack>'

    @log
    def __init__(self, size=Art.Size.MEDIUM):
        """Initialize the CoverStack

        :param Art.Size size: The size of the art used for the cover
        """
        super().__init__()

        self._art = None
        self._handler_id = None
        self._size = None
        self._timeout = None

        self._loading_cover = Gtk.Image()
        self._cover_a = Gtk.Image()
        self._cover_b = Gtk.Image()

        self.add_named(self._loading_cover, "loading")
        self.add_named(self._cover_a, "A")
        self.add_named(self._cover_b, "B")

        self.props.size = size
        self.props.transition_type = Gtk.StackTransitionType.CROSSFADE
        self.props.visible_child_name = "loading"

        self.show_all()

    @GObject.Property(type=object, flags=GObject.ParamFlags.READWRITE)
    def size(self):
        """Size of the cover

        :returns: The size used
        :rtype: Art.Size
        """
        return self._size

    @size.setter
    def size(self, value):
        """Set the cover size

        :param Art.Size value: The size to use for the cover
        """
        self._size = value

        icon = self._default_icon.get(
            DefaultIcon.Type.LOADING, self.props.size, self.props.scale_factor)
        self._loading_cover.props.surface = icon

    @log
    def update(self, media):
        """Update the stack with the given media

        Update the stack with the art retrieved from the given media.
        :param Grl.Media media: The media object
        """
        if self._handler_id and self._art:
            # Remove a possible dangling 'finished' callback if update
            # is called again, but it is still looking for the previous
            # art.
            self._art.disconnect(self._handler_id)
            # Set the loading state only after a delay to make between
            # song transitions smooth if loading time is negligible.
            self._timeout = GLib.timeout_add(100, self._set_loading_child)

        self._active_child = self.props.visible_child_name

        self._art = Art(self.props.size, media, self.props.scale_factor)
        self._handler_id = self._art.connect('finished', self._art_retrieved)
        self._art.lookup()

    @log
    def _set_loading_child(self):
        self.props.visible_child_name = "loading"
        self._active_child = self.props.visible_child_name
        self._timeout = None

        return GLib.SOURCE_REMOVE

    @log
    def _art_retrieved(self, klass):
        if self._timeout:
            GLib.source_remove(self._timeout)
            self._timeout = None

        if self._active_child == "B":
            self._cover_a.props.surface = klass.surface
            self.props.visible_child_name = "A"
        else:
            self._cover_b.props.surface = klass.surface
            self.props.visible_child_name = "B"

        self._active_child = self.props.visible_child_name
        self._art = None

        self.emit('updated')