Пример #1
0
    def _add_search_item(self, source, param, item, remaining=0, data=None):
        if not item:
            if grilo._search_callback_counter == 0 and grilo.search_source:
                self.emit('no-music-found')
            return

        if data != self.model:
            return

        artist = utils.get_artist_name(item)
        album = utils.get_album_title(item)
        composer = item.get_composer()

        key = '%s-%s' % (artist, album)
        if key not in self._albums:
            self._albums[key] = Grl.Media()
            self._albums[key].set_title(album)
            self._albums[key].add_artist(artist)
            self._albums[key].set_composer(composer)
            self._albums[key].set_source(source.get_id())
            self._albums[key].tracks = []
            self._add_item(source, None, self._albums[key], 0, [self.model, 'album'])
            self._add_item(source, None, self._albums[key], 0, [self.model, 'artist'])

        self._albums[key].tracks.append(item)
        self._add_item(source, None, item, 0, [self.model, 'song'])
Пример #2
0
    def _on_list_widget_album_render(self, coll, cell, model, _iter, data):
        if not model.iter_is_valid(_iter):
            return

        item = model[_iter][5]
        if item:
            cell.set_property('text', utils.get_album_title(item))
Пример #3
0
    def _add_to_blacklist(self):
        album = utils.get_album_title(self._media)
        artist = utils.get_artist_name(self._media)

        if artist not in self._blacklist:
            self._blacklist[artist] = []

        album_stripped = MediaArt.strip_invalid_entities(album)
        self._blacklist[artist].append(album_stripped)
Пример #4
0
    def _in_blacklist(self):
        album = utils.get_album_title(self._media)
        artist = utils.get_artist_name(self._media)
        album_stripped = MediaArt.strip_invalid_entities(album)

        if artist in self._blacklist:
            if album_stripped in self._blacklist[artist]:
                return True

        return False
Пример #5
0
    def _set_grilo_thumbnail_path(self):
        # TODO: This sets the thumbnail path for the Grilo Media object
        # to be used by MPRIS. However, calling this by default for
        # every cache hit is unnecessary.
        album = utils.get_album_title(self._media)
        artist = utils.get_artist_name(self._media)

        success, thumb_file = MediaArt.get_file(artist, album, "album")
        if success:
            self._media.set_thumbnail(
                GLib.filename_to_uri(thumb_file.get_path(), None))
Пример #6
0
    def __init__(self, media, player, model, header_bar,
                 selection_mode_allowed, size_group=None,
                 cover_size_group=None):
        super().__init__(self, orientation=Gtk.Orientation.HORIZONTAL)

        self._size_group = size_group
        self._cover_size_group = cover_size_group
        scale = self.get_scale_factor()
        self._cache = AlbumArtCache(scale)
        self._loading_icon_surface = DefaultIcon(scale).get(
            DefaultIcon.Type.loading,
            ArtSize.medium)

        self._media = media
        self._player = player
        self._artist = utils.get_artist_name(self._media)
        self._album_title = utils.get_album_title(self._media)
        self._model = model
        self._header_bar = header_bar
        self._selection_mode = False
        self._selection_mode_allowed = selection_mode_allowed

        self._songs = []

        self._header_bar._select_button.connect(
            'toggled', self._on_header_select_button_toggled)

        ui = Gtk.Builder()
        ui.add_from_resource('/org/gnome/Music/ArtistAlbumWidget.ui')

        self.cover = ui.get_object('cover')
        self.cover.set_from_surface(self._loading_icon_surface)

        self._disc_listbox = ui.get_object('disclistbox')
        self._disc_listbox.set_selection_mode_allowed(
            self._selection_mode_allowed)

        ui.get_object('title').set_label(self._album_title)
        creation_date = self._media.get_creation_date()
        if creation_date:
            year = creation_date.get_year()
            ui.get_object('year').set_markup(
                '<span color=\'grey\'>{}</span>'.format(year))

        if self._size_group:
            self._size_group.add_widget(ui.get_object('box1'))

        if self._cover_size_group:
            self._cover_size_group.add_widget(self.cover)

        self.pack_start(ui.get_object('ArtistAlbumWidget'), True, True, 0)

        GLib.idle_add(self._update_album_art)
        grilo.populate_album_songs(self._media, self._add_item)
Пример #7
0
    def _set_grilo_thumbnail_path(self):
        # TODO: This sets the thumbnail path for the Grilo Media object
        # to be used by MPRIS. However, calling this by default for
        # every cache hit is unnecessary.
        album = utils.get_album_title(self._media)
        artist = utils.get_artist_name(self._media)

        success, thumb_file = MediaArt.get_file(artist, album, "album")
        if success:
            self._media.set_thumbnail(
                GLib.filename_to_uri(thumb_file.get_path(), None))
Пример #8
0
    def query(self, media):
        """Start the remote query

        :param Grl.Media media: The media object to search art for
        """
        self._album = utils.get_album_title(media)
        self._artist = utils.get_artist_name(media)

        # FIXME: It seems this Grilo query does not always return,
        # especially on queries with little info.
        grilo.get_album_art_for_item(media, self._remote_album_art)
Пример #9
0
 def update(self, media: Grl.Media) -> None:
     self.props.media = media
     self.props.album = utils.get_album_title(media)
     self.props.album_disc_number = media.get_album_disc_number()
     self.props.artist = utils.get_artist_name(media)
     self.props.duration = media.get_duration()
     self.props.favorite = media.get_favourite()
     self.props.play_count = media.get_play_count()
     self.props.title = utils.get_media_title(media)
     self.props.track_number = media.get_track_number()
     self.props.url = media.get_url()
Пример #10
0
    def _on_child_activated(self, widget, child, user_data=None):
        if self.props.selection_mode:
            return

        item = child.props.media
        # Update and display the album widget if not in selection mode
        self._album_widget.update(item)

        self._headerbar.props.state = HeaderBar.State.CHILD
        self._headerbar.props.title = utils.get_album_title(item)
        self._headerbar.props.subtitle = utils.get_artist_name(item)
        self.set_visible_child(self._album_widget)
Пример #11
0
    def _get_metadata(self, media=None, index=None):
        song_dbus_path = self._get_song_dbus_path(media, index)
        if not self.player.props.current_song:
            return {'mpris:trackid': GLib.Variant('o', song_dbus_path)}

        if not media:
            media = self.player.props.current_song

        length = media.get_duration() * 1e6
        user_rating = 1.0 if media.get_favourite() else 0.0
        artist = utils.get_artist_name(media)

        metadata = {
            'mpris:trackid': GLib.Variant('o', song_dbus_path),
            'xesam:url': GLib.Variant('s', media.get_url()),
            'mpris:length': GLib.Variant('x', length),
            'xesam:trackNumber': GLib.Variant('i', media.get_track_number()),
            'xesam:useCount': GLib.Variant('i', media.get_play_count()),
            'xesam:userRating': GLib.Variant('d', user_rating),
            'xesam:title': GLib.Variant('s', utils.get_media_title(media)),
            'xesam:album': GLib.Variant('s', utils.get_album_title(media)),
            'xesam:artist': GLib.Variant('as', [artist]),
            'xesam:albumArtist': GLib.Variant('as', [artist])
        }

        genre = media.get_genre()
        if genre is not None:
            metadata['xesam:genre'] = GLib.Variant('as', [genre])

        last_played = media.get_last_played()
        if last_played is not None:
            last_played_str = last_played.format("%FT%T%:z")
            metadata['xesam:lastUsed'] = GLib.Variant('s', last_played_str)

        # If the media has already been part of an MPRIS playlist, its
        # thumbnail is already set. Otherwise, try to look for it in the
        # cache directory and set the media thumbnail for a future use.
        # The search is only through the cache to prevent any delayed
        # loading.
        # FIXME: The thumbnail retrieval should take place in the
        # player.
        art_url = media.get_thumbnail()
        if not art_url:
            thumb_file = lookup_art_file_from_cache(media)
            if thumb_file:
                art_url = GLib.filename_to_uri(thumb_file.get_path())
                media.set_thumbnail(art_url)

        if art_url:
            metadata['mpris:artUrl'] = GLib.Variant('s', art_url)

        return metadata
Пример #12
0
    def __init__(self, media, player, model, header_bar,
                 selection_mode_allowed, size_group=None,
                 cover_size_group=None):
        super().__init__(orientation=Gtk.Orientation.HORIZONTAL)

        self._size_group = size_group
        self._cover_size_group = cover_size_group

        self._media = media
        self._player = player
        self._artist = utils.get_artist_name(self._media)
        self._album_title = utils.get_album_title(self._media)
        self._model = model
        self._header_bar = header_bar
        self._selection_mode = False
        self._selection_mode_allowed = selection_mode_allowed

        self._songs = []

        self._header_bar._select_button.connect(
            'toggled', self._on_header_select_button_toggled)

        ui = Gtk.Builder()
        ui.add_from_resource('/org/gnome/Music/ArtistAlbumWidget.ui')

        self.cover = ui.get_object('cover')

        self.cover_stack = CoverStack(self.cover, Art.Size.MEDIUM)
        self.cover_stack.update(self._media)

        self._disc_listbox = ui.get_object('disclistbox')
        self._disc_listbox.set_selection_mode_allowed(
            self._selection_mode_allowed)

        ui.get_object('title').set_label(self._album_title)
        creation_date = self._media.get_creation_date()
        if creation_date:
            year = creation_date.get_year()
            ui.get_object('year').set_markup(
                '<span color=\'grey\'>{}</span>'.format(year))

        if self._size_group:
            self._size_group.add_widget(ui.get_object('box1'))

        if self._cover_size_group:
            self._cover_size_group.add_widget(self.cover_stack._stack)

        self.pack_start(ui.get_object('ArtistAlbumWidget'), True, True, 0)

        grilo.populate_album_songs(self._media, self._add_item)
Пример #13
0
def lookup_art_file_from_cache(media):
    """Lookup MediaArt cache art of an album or song.

    :param Grl.Media media: song or album
    :returns: a cache file
    :rtype: Gio.File
    """
    album = utils.get_album_title(media)
    artist = utils.get_artist_name(media)

    success, thumb_file = MediaArt.get_file(artist, album, "album")
    if (not success or not thumb_file.query_exists()):
        return None

    return thumb_file
Пример #14
0
 def _add_item_to_model(self, item, model):
     if not item:
         self._update_songs_count()
         if self.player.playlist:
             self.player._validate_next_track()
         self.emit('playlist-songs-loaded')
         return
     self._offset += 1
     title = utils.get_media_title(item)
     item.set_title(title)
     artist = utils.get_album_title(item)
     model.insert_with_valuesv(
         -1, [2, 3, 5, 9],
         [title, artist, item, bool(item.get_lyrics())])
     self.songs_count += 1
Пример #15
0
    def __init__(self,
                 media,
                 player,
                 model,
                 header_bar,
                 selection_mode_allowed,
                 size_group=None,
                 cover_size_group=None):
        super().__init__(orientation=Gtk.Orientation.HORIZONTAL)

        self._size_group = size_group
        self._cover_size_group = cover_size_group

        self._media = media
        self._player = player
        self._artist = utils.get_artist_name(self._media)
        self._album_title = utils.get_album_title(self._media)
        self._model = model
        self._header_bar = header_bar
        self._selection_mode = False
        self._selection_mode_allowed = selection_mode_allowed

        self._songs = []

        self._cover_stack.props.size = Art.Size.MEDIUM
        self._cover_stack.update(self._media)

        allowed = self._selection_mode_allowed
        self._disc_list_box.props.selection_mode_allowed = allowed

        self.bind_property(
            'selection-mode', self._disc_list_box, 'selection-mode',
            GObject.BindingFlags.BIDIRECTIONAL
            | GObject.BindingFlags.SYNC_CREATE)

        self._title.props.label = self._album_title
        year = utils.get_media_year(self._media)

        if year:
            self._year.props.label = year

        if self._size_group:
            self._size_group.add_widget(self._album_box)

        if self._cover_size_group:
            self._cover_size_group.add_widget(self._cover_stack)

        grilo.populate_album_songs(self._media, self._add_item)
Пример #16
0
    def query(self, media):
        """Start the cache query

        :param Grl.Media media: The media object to search art for
        """
        album = utils.get_album_title(media)
        artist = utils.get_artist_name(media)

        success, thumb_file = MediaArt.get_file(artist, album, "album")

        if (success and thumb_file.query_exists()):
            thumb_file.read_async(GLib.PRIORITY_LOW, None, self._open_stream,
                                  None)
            return

        self.emit('miss')
Пример #17
0
 def _add_item_to_model(self, item, model):
     if not item:
         self._update_songs_count()
         if self.player.playlist:
             self.player._validate_next_track()
         self.emit('playlist-songs-loaded')
         return
     self._offset += 1
     title = utils.get_media_title(item)
     item.set_title(title)
     artist = utils.get_album_title(item)
     model.insert_with_valuesv(
         -1,
         [2, 3, 5, 9],
         [title, artist, item, item.get_favourite()])
     self.songs_count += 1
Пример #18
0
    def query(self, media):
        """Start the remote query

        :param Grl.Media media: The media object to search art for
        """
        self._album = utils.get_album_title(media)
        self._artist = utils.get_artist_name(media)
        self._media = media

        if not grilo.props.cover_sources:
            self.emit('no-remote-sources')
            grilo.connect(
                'notify::cover-sources', self._on_grilo_cover_sources_changed)
        else:
            # FIXME: It seems this Grilo query does not always return,
            # especially on queries with little info.
            grilo.get_album_art_for_item(media, self._remote_album_art)
Пример #19
0
    def query(self, media):
        """Start the remote query

        :param Grl.Media media: The media object to search art for
        """
        self._album = utils.get_album_title(media)
        self._artist = utils.get_artist_name(media)
        self._media = media

        if not grilo.props.cover_sources:
            self.emit('no-remote-sources')
            grilo.connect('notify::cover-sources',
                          self._on_grilo_cover_sources_changed)
        else:
            # FIXME: It seems this Grilo query does not always return,
            # especially on queries with little info.
            grilo.get_album_art_for_item(media, self._remote_album_art)
Пример #20
0
    def query(self, media):
        """Start the cache query

        :param Grl.Media media: The media object to search art for
        """
        album = utils.get_album_title(media)
        artist = utils.get_artist_name(media)

        success, thumb_file = MediaArt.get_file(artist, album, "album")

        if (success
                and thumb_file.query_exists()):
            thumb_file.read_async(
                GLib.PRIORITY_LOW, None, self._open_stream, None)
            return

        self.emit('miss')
Пример #21
0
    def _lookup_embedded(self, item, art_size, callback, itr):
        """Lookup embedded cover

        Lookup embedded art through Gst.Discoverer. If found
        copy locally and call _lookup_local to finish retrieving
        suitable art, otherwise follow up with _lookup_remote.
        """
        album = utils.get_album_title(item)
        artist = utils.get_artist_name(item)

        success, cache_path = MediaArt.get_path(artist, album, "album")
        if not success:
            self._lookup_remote(item, art_size, callback, itr)

        self._discoverer_items[item.get_url()] = [
            item, art_size, callback, itr, cache_path
        ]
        self._discoverer.discover_uri_async(item.get_url())
Пример #22
0
    def _get_metadata(self, media=None, index=None):
        song_dbus_path = self._get_song_dbus_path(media, index)
        if not self.player.props.current_song:
            return {
                'mpris:trackid': GLib.Variant('o', song_dbus_path)
            }

        if not media:
            media = self.player.props.current_song

        length = media.get_duration() * 1e6
        user_rating = 1.0 if media.get_favourite() else 0.0
        artist = utils.get_artist_name(media)

        metadata = {
            'mpris:trackid': GLib.Variant('o', song_dbus_path),
            'xesam:url': GLib.Variant('s', media.get_url()),
            'mpris:length': GLib.Variant('x', length),
            'xesam:trackNumber': GLib.Variant('i', media.get_track_number()),
            'xesam:useCount': GLib.Variant('i', media.get_play_count()),
            'xesam:userRating': GLib.Variant('d', user_rating),
            'xesam:title': GLib.Variant('s', utils.get_media_title(media)),
            'xesam:album': GLib.Variant('s', utils.get_album_title(media)),
            'xesam:artist': GLib.Variant('as', [artist]),
            'xesam:albumArtist': GLib.Variant('as', [artist])
        }

        genre = media.get_genre()
        if genre is not None:
            metadata['xesam:genre'] = GLib.Variant('as', [genre])

        last_played = media.get_last_played()
        if last_played is not None:
            last_played_str = last_played.format("%FT%T%:z")
            metadata['xesam:lastUsed'] = GLib.Variant('s', last_played_str)

        art_url = media.get_thumbnail()
        if art_url is not None:
            metadata['mpris:artUrl'] = GLib.Variant('s', art_url)

        return metadata
Пример #23
0
    def query(self, media):
        """Start the local query

        :param Grl.Media media: The media object to search art for
        """
        if media.get_url() is None:
            self.emit('unavailable')
            return

        self._album = utils.get_album_title(media)
        self._artist = utils.get_artist_name(media)
        self._media = media

        try:
            discoverer = GstPbutils.Discoverer.new(Gst.SECOND)
        except GLib.Error as error:
            logger.warning("Error: {}, {}".format(error.domain, error.message))
            self._lookup_cover_in_directory()
            return

        discoverer.connect('discovered', self._discovered)
        discoverer.start()

        success, path = MediaArt.get_path(self._artist, self._album, "album")

        if not success:
            self.emit('unavailable')
            discoverer.stop()
            return

        self._path = path

        success = discoverer.discover_uri_async(self._media.get_url())

        if not success:
            logger.warning("Could not add url to discoverer.")
            self.emit('unavailable')
            discoverer.stop()
            return
Пример #24
0
    def query(self, media):
        """Start the local query

        :param Grl.Media media: The media object to search art for
        """
        if media.get_url() is None:
            self.emit('unavailable')
            return

        self._album = utils.get_album_title(media)
        self._artist = utils.get_artist_name(media)
        self._media = media

        try:
            discoverer = GstPbutils.Discoverer.new(Gst.SECOND)
        except GLib.Error as error:
            logger.warning("Error: {}, {}".format(error.domain, error.message))
            self._lookup_cover_in_directory()
            return

        discoverer.connect('discovered', self._discovered)
        discoverer.start()

        success, path = MediaArt.get_path(self._artist, self._album, "album")

        if not success:
            self.emit('unavailable')
            discoverer.stop()
            return

        self._path = path

        success = discoverer.discover_uri_async(self._media.get_url())

        if not success:
            logger.warning("Could not add url to discoverer.")
            self.emit('unavailable')
            discoverer.stop()
            return
Пример #25
0
    def update(self, album):
        """Update the album widget.

        :param Grl.Media album: The grilo media album
        """
        # reset view
        self._songs = []
        self._create_model()
        for widget in self._disc_listbox.get_children():
            self._disc_listbox.remove(widget)

        self._cover_stack.update(album)

        self._duration = 0

        self._album_name = utils.get_album_title(album)
        artist = utils.get_artist_name(album)

        self._title_label.props.label = self._album_name
        self._title_label.props.tooltip_text = self._album_name

        self._artist_label.props.label = artist
        self._artist_label.props.tooltip_text = artist

        year = utils.get_media_year(album)
        if not year:
            year = '----'
        self._released_info_label.props.label = year

        self._set_composer_label(album)

        self._album = album

        self._player.connect('song-changed', self._update_model)

        grilo.populate_album_songs(album, self.add_item)
Пример #26
0
 def _set_album_headerbar(self, album):
     self._headerbar.props.state = HeaderBar.State.CHILD
     self._headerbar.props.title = utils.get_album_title(album)
     self._headerbar.props.subtitle = utils.get_artist_name(album)
Пример #27
0
    def _lookup_remote(self, item, callback, itr, art_size):
        """Lookup remote art

        Lookup remote art through Grilo and if found copy locally. Call
        _lookup_local to finish retrieving suitable art.
        """
        album = utils.get_album_title(item)
        artist = utils.get_artist_name(item)

        @log
        def delete_cb(src, result, data):
            try:
                src.delete_finish(result)
            except Exception as err:
                logger.warn("Error: %s, %s", err.__class__, err)

        @log
        def splice_cb(src, result, data):
            tmp_file, iostream = data

            try:
                src.splice_finish(result)
            except Exception as err:
                logger.warn("Error: %s, %s", err.__class__, err)
                art_retrieved(False)
                return

            success, cache_path = MediaArt.get_path(artist, album, "album")
            try:
                # FIXME: I/O blocking
                MediaArt.file_to_jpeg(tmp_file.get_path(), cache_path)
            except Exception as err:
                logger.warn("Error: %s, %s", err.__class__, err)
                art_retrieved(False)
                return

            art_retrieved(True)

            tmp_file.delete_async(GLib.PRIORITY_LOW,
                                  None,
                                  delete_cb,
                                  None)

        @log
        def async_read_cb(src, result, data):
            try:
                istream = src.read_finish(result)
            except Exception as err:
                logger.warn("Error: %s, %s", err.__class__, err)
                art_retrieved(False)
                return

            try:
                [tmp_file, iostream] = Gio.File.new_tmp()
            except Exception as err:
                logger.warn("Error: %s, %s", err.__class__, err)
                art_retrieved(False)
                return

            ostream = iostream.get_output_stream()
            # FIXME: Passing the iostream here, otherwise it gets
            # closed. PyGI specific issue?
            ostream.splice_async(istream,
                                 Gio.OutputStreamSpliceFlags.CLOSE_SOURCE |
                                 Gio.OutputStreamSpliceFlags.CLOSE_TARGET,
                                 GLib.PRIORITY_LOW,
                                 None,
                                 splice_cb,
                                 [tmp_file, iostream])

        @log
        def album_art_for_item_cb(source, param, item, count, error):
            if error:
                logger.warn("Grilo error %s", error)
                art_retrieved(False)
                return

            thumb_uri = item.get_thumbnail()

            if thumb_uri is None:
                art_retrieved(False)
                return

            src = Gio.File.new_for_uri(thumb_uri)
            src.read_async(GLib.PRIORITY_LOW,
                           None,
                           async_read_cb,
                           None)

        @log
        def art_retrieved(result):
            if not result:
                if artist not in self.blacklist:
                    self.blacklist[artist] = []

                album_stripped = MediaArt.strip_invalid_entities(album)
                self.blacklist[artist].append(album_stripped)

            self.lookup(item, art_size, callback, itr)

        grilo.get_album_art_for_item(item, album_art_for_item_cb)
Пример #28
0
    def _lookup_local(self, item, callback, itr, art_size):
        """Checks if there is already a local art file, if not calls
        the remote lookup function"""
        album = utils.get_album_title(item)
        artist = utils.get_artist_name(item)

        def stream_open(thumb_file, result, arguments):
            try:
                stream = thumb_file.read_finish(result)
            except Exception as err:
                logger.warn("Error: %s, %s", err.__class__, err)
                do_callback(None)
                return

            GdkPixbuf.Pixbuf.new_from_stream_async(stream,
                                                   None,
                                                   pixbuf_loaded,
                                                   None)

        def pixbuf_loaded(stream, result, data):
            try:
                pixbuf = GdkPixbuf.Pixbuf.new_from_stream_finish(result)
            except Exception as err:
                logger.warn("Error: %s, %s", err.__class__, err)
                do_callback(None)
                return

            do_callback(pixbuf)
            return

        def do_callback(pixbuf):
            if not pixbuf:
                surface = DefaultIcon(self._scale).get(DefaultIcon.Type.music,
                                                       art_size)
            else:
                surface = _make_icon_frame(pixbuf, art_size, self._scale)

                # Sets the thumbnail location for MPRIS to use.
                item.set_thumbnail(GLib.filename_to_uri(thumb_file.get_path(),
                                                        None))

            GLib.idle_add(callback, surface, itr)
            return

        success, thumb_file = MediaArt.get_file(artist, album, "album")

        if (success
                and thumb_file.query_exists()):
            thumb_file.read_async(GLib.PRIORITY_LOW,
                                  None,
                                  stream_open,
                                  None)
            return

        stripped_album = MediaArt.strip_invalid_entities(album)
        if (artist in self.blacklist
                and stripped_album in self.blacklist[artist]):
            do_callback(None)
            return

        self._lookup_remote(item, callback, itr, art_size)
Пример #29
0
    def _lookup_remote(self, item, callback, itr, art_size):
        """Lookup remote art

        Lookup remote art through Grilo and if found copy locally. Call
        _lookup_local to finish retrieving suitable art.
        """
        album = utils.get_album_title(item)
        artist = utils.get_artist_name(item)

        @log
        def delete_cb(src, result, data):
            try:
                src.delete_finish(result)
            except Exception as err:
                logger.warn("Error: %s, %s", err.__class__, err)

        @log
        def splice_cb(src, result, data):
            tmp_file, iostream = data

            try:
                src.splice_finish(result)
            except Exception as err:
                logger.warn("Error: %s, %s", err.__class__, err)
                art_retrieved(False)
                return

            success, cache_path = MediaArt.get_path(artist, album, "album")
            try:
                # FIXME: I/O blocking
                MediaArt.file_to_jpeg(tmp_file.get_path(), cache_path)
            except Exception as err:
                logger.warn("Error: %s, %s", err.__class__, err)
                art_retrieved(False)
                return

            art_retrieved(True)

            tmp_file.delete_async(GLib.PRIORITY_LOW, None, delete_cb, None)

        @log
        def async_read_cb(src, result, data):
            try:
                istream = src.read_finish(result)
            except Exception as err:
                logger.warn("Error: %s, %s", err.__class__, err)
                art_retrieved(False)
                return

            try:
                [tmp_file, iostream] = Gio.File.new_tmp()
            except Exception as err:
                logger.warn("Error: %s, %s", err.__class__, err)
                art_retrieved(False)
                return

            ostream = iostream.get_output_stream()
            # FIXME: Passing the iostream here, otherwise it gets
            # closed. PyGI specific issue?
            ostream.splice_async(
                istream, Gio.OutputStreamSpliceFlags.CLOSE_SOURCE
                | Gio.OutputStreamSpliceFlags.CLOSE_TARGET, GLib.PRIORITY_LOW,
                None, splice_cb, [tmp_file, iostream])

        @log
        def album_art_for_item_cb(source, param, item, count, error):
            if error:
                logger.warn("Grilo error %s", error)
                art_retrieved(False)
                return

            thumb_uri = item.get_thumbnail()

            if thumb_uri is None:
                art_retrieved(False)
                return

            src = Gio.File.new_for_uri(thumb_uri)
            src.read_async(GLib.PRIORITY_LOW, None, async_read_cb, None)

        @log
        def art_retrieved(result):
            if not result:
                if artist not in self.blacklist:
                    self.blacklist[artist] = []

                album_stripped = MediaArt.strip_invalid_entities(album)
                self.blacklist[artist].append(album_stripped)

            self.lookup(item, art_size, callback, itr)

        grilo.get_album_art_for_item(item, album_art_for_item_cb)
Пример #30
0
 def _on_list_widget_type_render(self, coll, cell, model, itr, data):
     item = model[itr][5]
     if item:
         cell.set_property('text', utils.get_album_title(item))
Пример #31
0
 def _set_album_headerbar(self, album):
     self._headerbar.props.state = HeaderBar.State.CHILD
     self._headerbar.props.title = utils.get_album_title(album)
     self._headerbar.props.subtitle = utils.get_artist_name(album)
Пример #32
0
 def _on_list_widget_type_render(self, coll, cell, model, itr, data):
     item = model[itr][5]
     if item:
         cell.set_property('text', utils.get_album_title(item))
Пример #33
0
 def _on_list_widget_type_render(self, coll, cell, model, _iter, data):
     item = model.get_value(_iter, 5)
     if item:
         cell.set_property('text', utils.get_album_title(item))
Пример #34
0
    def _lookup_local(self, item, art_size, callback, itr):
        """Checks if there is already a local art file, if not calls
        the embedded lookup function"""
        album = utils.get_album_title(item)
        artist = utils.get_artist_name(item)

        def stream_open(thumb_file, result, arguments):
            try:
                stream = thumb_file.read_finish(result)
            except Exception as err:
                logger.warn("Error: %s, %s", err.__class__, err)
                do_callback(None)
                return

            GdkPixbuf.Pixbuf.new_from_stream_async(stream, None, pixbuf_loaded,
                                                   None)

        def pixbuf_loaded(stream, result, data):
            try:
                pixbuf = GdkPixbuf.Pixbuf.new_from_stream_finish(result)
            except Exception as err:
                logger.warn("Error: %s, %s", err.__class__, err)
                do_callback(None)
                return

            do_callback(pixbuf)
            return

        def do_callback(pixbuf):

            # Lookup finished, decrease the counter
            LookupQueue.pop()

            if not pixbuf:
                surface = DefaultIcon(self._scale).get(DefaultIcon.Type.music,
                                                       art_size)
            else:
                surface = _make_icon_frame(pixbuf, art_size, self._scale)

                # Sets the thumbnail location for MPRIS to use.
                item.set_thumbnail(
                    GLib.filename_to_uri(thumb_file.get_path(), None))

            GLib.idle_add(callback, surface, itr)
            return

        success, thumb_file = MediaArt.get_file(artist, album, "album")

        if (success and thumb_file.query_exists()):
            thumb_file.read_async(GLib.PRIORITY_LOW, None, stream_open, None)
            return

        stripped_album = MediaArt.strip_invalid_entities(album)
        if (artist in self.blacklist
                and stripped_album in self.blacklist[artist]):
            do_callback(None)
            return

        # When we reach here because it fails to retrieve the artwork,
        # do a long round trip (either through _lookup_embedded or
        # _lookup_remote) and call self.lookup() again. Thus, decrease
        # global lookup counter.
        LookupQueue.pop()

        self._lookup_embedded(item, art_size, callback, itr)
Пример #35
0
    def _discovered_cb(self, discoverer, info, error):
        item, art_size, callback, itr, cache_path = \
            self._discoverer_items[info.get_uri()]

        album = utils.get_album_title(item)
        artist = utils.get_artist_name(item)
        tags = info.get_tags()
        index = 0

        def art_retrieved(result):
            if not result:
                if artist not in self.blacklist:
                    self.blacklist[artist] = []

                album_stripped = MediaArt.strip_invalid_entities(album)
                self.blacklist[artist].append(album_stripped)

            self.lookup(item, art_size, callback, itr)

        # FIXME: tags should not return as None, but it sometimes is.
        # So as a workaround until we figure out what is wrong check
        # for it.
        # https://bugzilla.gnome.org/show_bug.cgi?id=780980
        if (error is not None or tags is None):
            art_retrieved(False)
            return

        while True:
            success, sample = tags.get_sample_index(Gst.TAG_IMAGE, index)
            if not success:
                break
            index += 1
            struct = sample.get_info()
            success, image_type = struct.get_enum('image-type',
                                                  GstTag.TagImageType)
            if not success:
                continue
            if image_type != GstTag.TagImageType.FRONT_COVER:
                continue

            buf = sample.get_buffer()
            success, map_info = buf.map(Gst.MapFlags.READ)
            if not success:
                continue

            try:
                mime = sample.get_caps().get_structure(0).get_name()
                MediaArt.buffer_to_jpeg(map_info.data, mime, cache_path)
                art_retrieved(True)
                return
            except Exception as err:
                logger.warn("Error: %s, %s", err.__class__, err)

        try:
            self._media_art.uri(MediaArt.Type.ALBUM,
                                MediaArt.ProcessFlags.NONE, item.get_url(),
                                artist, album, None)
            if os.path.exists(cache_path):
                art_retrieved(True)
                return
        except Exception as err:
            logger.warn("Trying to process misc albumart: %s, %s",
                        err.__class__, err)

        self._lookup_remote(item, art_size, callback, itr)
Пример #36
0
    def _get_metadata(self, media=None):
        if not media:
            media = self.player.get_current_media()
        if not media:
            return {}

        metadata = {
            'mpris:trackid': GLib.Variant('o', self._get_media_id(media)),
            'xesam:url': GLib.Variant('s', media.get_url())
        }

        try:
            length = media.get_duration() * 1000000
            assert length is not None
            metadata['mpris:length'] = GLib.Variant('x', length)
        except:
            pass

        try:
            trackNumber = media.get_track_number()
            assert trackNumber is not None
            metadata['xesam:trackNumber'] = GLib.Variant('i', trackNumber)
        except:
            pass

        try:
            useCount = media.get_play_count()
            assert useCount is not None
            metadata['xesam:useCount'] = GLib.Variant('i', useCount)
        except:
            pass

        try:
            userRating = media.get_rating()
            assert userRating is not None
            metadata['xesam:userRating'] = GLib.Variant('d', userRating)
        except:
            pass

        try:
            title = utils.get_media_title(media)
            assert title is not None
            metadata['xesam:title'] = GLib.Variant('s', title)
        except:
            pass


        album = utils.get_album_title(media)
        metadata['xesam:album'] = GLib.Variant('s', album)

        artist = utils.get_artist_name(media)
        metadata['xesam:artist'] = GLib.Variant('as', [artist])
        metadata['xesam:albumArtist'] = GLib.Variant('as', [artist])

        try:
            genre = media.get_genre()
            assert genre is not None
            metadata['xesam:genre'] = GLib.Variant('as', genre)
        except:
            pass

        try:
            lastUsed = media.get_last_played()
            assert lastUsed is not None
            metadata['xesam:lastUsed'] = GLib.Variant('s', lastUsed)
        except:
            pass

        try:
            artUrl = media.get_thumbnail()
            assert artUrl is not None
            metadata['mpris:artUrl'] = GLib.Variant('s', artUrl)
        except:
            pass

        return metadata
Пример #37
0
    def _get_metadata(self, media=None):
        if not media:
            media = self.player.props.current_song
        if not media:
            return {}

        song_dbus_path = self._get_song_dbus_path(media)
        metadata = {
            'mpris:trackid': GLib.Variant('o', song_dbus_path),
            'xesam:url': GLib.Variant('s', media.get_url())
        }

        try:
            length = media.get_duration() * 1000000
            assert length is not None
            metadata['mpris:length'] = GLib.Variant('x', length)
        except:
            pass

        try:
            trackNumber = media.get_track_number()
            assert trackNumber is not None
            metadata['xesam:trackNumber'] = GLib.Variant('i', trackNumber)
        except:
            pass

        try:
            useCount = media.get_play_count()
            assert useCount is not None
            metadata['xesam:useCount'] = GLib.Variant('i', useCount)
        except:
            pass

        try:
            userRating = media.get_rating()
            assert userRating is not None
            metadata['xesam:userRating'] = GLib.Variant('d', userRating)
        except:
            pass

        try:
            title = utils.get_media_title(media)
            assert title is not None
            metadata['xesam:title'] = GLib.Variant('s', title)
        except:
            pass

        album = utils.get_album_title(media)
        metadata['xesam:album'] = GLib.Variant('s', album)

        artist = utils.get_artist_name(media)
        metadata['xesam:artist'] = GLib.Variant('as', [artist])
        metadata['xesam:albumArtist'] = GLib.Variant('as', [artist])

        try:
            genre = media.get_genre()
            assert genre is not None
            metadata['xesam:genre'] = GLib.Variant('as', genre)
        except:
            pass

        try:
            lastUsed = media.get_last_played()
            assert lastUsed is not None
            metadata['xesam:lastUsed'] = GLib.Variant('s', lastUsed)
        except:
            pass

        try:
            artUrl = media.get_thumbnail()
            assert artUrl is not None
            metadata['mpris:artUrl'] = GLib.Variant('s', artUrl)
        except:
            pass

        return metadata