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].songs = [] 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].songs.append(item) self._add_item(source, None, item, 0, [self.model, 'song'])
def _on_list_widget_type_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))
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('/eu/depau/GSub/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)
def _lookup_local(self, item, callback, itr, art_size): """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): 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_embedded(item, callback, itr, art_size)
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
def _lookup_embedded(self, item, callback, itr, art_size): """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, callback, itr, art_size) self._discoverer_items[item.get_url()] = [ item, callback, itr, art_size, cache_path ] self._discoverer.discover_uri_async(item.get_url())
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
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))
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)
def _discovered_cb(self, discoverer, info, error): item, callback, itr, art_size, 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, callback, itr, art_size)