def set_content(self, prefix, content, image_url, suffix): """ populate widget with content @param prefix as str @param content as str @param image url as str @param suffix as str @thread safe """ try: data = None stream = None if content is not None: if image_url is not None: f = Lio.File.new_for_uri(image_url) (status, data, tag) = f.load_contents(self.__cancel) if status: stream = Gio.MemoryInputStream.new_from_data(data, None) else: data = None InfoCache.add(prefix, content, data, suffix) GLib.idle_add(self.__set_content, content, stream) except Exception as e: print("InfoContent::set_content: %s" % e)
def _on_button_clicked(self, button): """ Show file chooser @param button as Gtk.button """ dialog = Gtk.FileChooserDialog() dialog.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL) dialog.add_buttons(Gtk.STOCK_OPEN, Gtk.ResponseType.OK) dialog.set_transient_for(Lp().window) self.__close_popover() response = dialog.run() if response == Gtk.ResponseType.OK: try: f = Lio.File.new_for_path(dialog.get_filename()) (status, data, tag) = f.load_contents() if not status: raise if self.__album is not None: Lp().art.save_album_artwork(data, self.__album.id) else: for suffix in ["lastfm", "wikipedia", "spotify"]: InfoCache.uncache_artwork(self.__artist, suffix, button.get_scale_factor()) InfoCache.add(self.__artist, None, data, suffix) Lp().art.emit("artist-artwork-changed", self.__artist) self._streams = {} except Exception as e: print("ArtworkSearch::_on_button_clicked():", e) dialog.destroy()
def _on_button_clicked(self, button): """ Show file chooser @param button as Gtk.button """ dialog = Gtk.FileChooserDialog() dialog.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL) dialog.add_buttons(Gtk.STOCK_OPEN, Gtk.ResponseType.OK) dialog.set_transient_for(Lp().window) self.__close_popover() response = dialog.run() if response == Gtk.ResponseType.OK: try: f = Lio.File.new_for_path(dialog.get_filename()) (status, data, tag) = f.load_contents() if not status: raise if self.__album is not None: Lp().art.save_album_artwork(data, self.__album.id) else: for suffix in ["lastfm", "wikipedia", "spotify"]: InfoCache.uncache_artwork(self.__artist, suffix, button.get_scale_factor()) InfoCache.add(self.__artist, None, data, suffix) Lp().art.emit('artist-artwork-changed', self.__artist) self._streams = {} except Exception as e: print("ArtworkSearch::_on_button_clicked():", e) dialog.destroy()
def __on_search_activated(self, action, variant, artist): """ Switch to page @param action as SimpleAction @param variant as GVariant @param artist as str """ InfoCache.remove(artist, 'wikipedia') InfoContent.clear(self) self.set_visible_child_name('spinner') self._spinner.start() t = Thread(target=self.__load_page_content, args=(artist,)) t.daemon = True t.start()
def __really_update_coversize(self, widget): """ Update cover size @param widget as Gtk.Range """ self.__cover_tid = None value = widget.get_value() Lp().settings.set_value('cover-size', GLib.Variant('i', value)) Lp().art.update_art_size() for suffix in ["lastfm", "wikipedia", "spotify"]: for artist in Lp().artists.get([]): InfoCache.uncache_artwork(artist[1], suffix, widget.get_scale_factor()) Lp().art.emit('artist-artwork-changed', artist[1]) Lp().window.reload_view()
def _on_reset_confirm(self, button): """ Reset cover @param button as Gtk.Button """ self._infobar.hide() if self._album is not None: Lp().art.remove_album_artwork(self._album) Lp().art.clean_album_cache(self._album) Lp().art.emit('album-artwork-changed', self._album.id) else: for suffix in ["lastfm", "wikipedia", "spotify"]: InfoCache.uncache_artwork(self._artist, suffix, button.get_scale_factor()) Lp().art.emit('artist-artwork-changed', self._artist) self._close_popover()
def do_own_render(self, ctx, widget, cell_area, size): surface = None if self.rowid in self.__surfaces.keys(): surface = self.__surfaces[self.rowid] if surface is None: for suffix in ["lastfm", "deezer", "spotify", "wikipedia"]: uri = InfoCache.get_artwork(self.artist, suffix, size) if uri is not None: pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size( uri, size, size) surface = Gdk.cairo_surface_create_from_pixbuf( pixbuf, self.__scale_factor, None) del pixbuf self.__surfaces[self.rowid] = surface break if surface is None: surface = Gtk.IconTheme.get_default().load_surface( 'avatar-default-symbolic', ArtSize.ARTIST_SMALL, 1, widget.get_window(), 0) ctx.translate(cell_area.x, cell_area.y) ctx.new_sub_path() radius = ArtSize.ARTIST_SMALL / 2 ctx.arc(ArtSize.ARTIST_SMALL / 2, ArtSize.ARTIST_SMALL / 2, radius, 0, 2 * pi) ctx.set_source_rgb(1, 1, 1) ctx.fill_preserve() ctx.set_line_width(2) ctx.set_source_rgba(0, 0, 0, 0.3) ctx.stroke_preserve() ctx.set_source_surface(surface, 0, 0) del surface ctx.clip() ctx.paint()
def _on_activate(self, flowbox, child): """ Use pixbuf as cover Reset cache and use player object to announce cover change """ data = self._datas[child.get_child()] self._close_popover() if self._album is not None: Lp().art.save_album_artwork(data, self._album.id) Lp().art.clean_album_cache(self._album) Lp().art.album_artwork_update(self._album.id) else: for suffix in ["lastfm", "wikipedia", "spotify"]: InfoCache.uncache_artwork(self._artist, suffix, flowbox.get_scale_factor()) InfoCache.cache(self._artist, None, data, suffix) self._streams = {}
def _really_update_coversize(self, widget): """ Update cover size @param widget as Gtk.Range """ self._cover_tid = None value = widget.get_value() Lp().settings.set_value('cover-size', GLib.Variant('i', value)) ArtSize.BIG = value for suffix in ["lastfm", "wikipedia", "spotify"]: for artist in Lp().artists.get([]): InfoCache.uncache_artwork(artist[1], suffix, widget.get_scale_factor()) Lp().art.emit('artist-artwork-changed', artist[1]) # For a 200 album artwork, we want a 60 artist artwork ArtSize.ARTIST_SMALL = ArtSize.BIG * 60 / 200 Lp().window.reload_view()
def _on_reset_confirm(self, button): """ Reset cover @param button as Gtk.Button """ self._infobar.hide() if self.__album is not None: Lp().art.remove_album_artwork(self.__album) Lp().art.clean_album_cache(self.__album) Lp().art.emit("album-artwork-changed", self.__album.id) else: for suffix in ["lastfm", "wikipedia", "spotify", "deezer"]: InfoCache.uncache_artwork(self.__artist, suffix, button.get_scale_factor()) InfoCache.add(self.__artist, None, None, suffix) Lp().art.emit("artist-artwork-changed", self.__artist) self.__close_popover()
def _on_button_release(self, widget, event): """ Reload current view if autoload unchanged @param widget as Gtk.Widget @param event as Gdk.Event """ if self.__timeout_id is not None: GLib.source_remove(self.__timeout_id) self.__timeout_id = None visible_name = self.__stack.get_visible_child_name() # Clear cache if needed if visible_name in ['lastfm', 'wikipedia']: for artist in self.__current_track.artists: InfoCache.remove(artist, visible_name) # stack -> scrolled -> viewport -> grid self._on_child_unmap( self.__stack.get_visible_child().get_child().get_child()) self.__on_current_changed(Lp().player)
def __set_artwork(self): """ Set artist artwork """ artwork_height = 0 if Lp().settings.get_value("artist-artwork"): if len(self._artist_ids) == 1 and\ Lp().settings.get_value("artist-artwork"): artist = Lp().artists.get_name(self._artist_ids[0]) size = ArtSize.ARTIST_SMALL * 2 * self.__scale_factor for suffix in ["lastfm", "spotify", "wikipedia"]: uri = InfoCache.get_artwork(artist, suffix, size) if uri is not None: f = Gio.File.new_for_path(uri) (status, data, tag) = f.load_contents(None) if not status: continue bytes = GLib.Bytes(data) stream = Gio.MemoryInputStream.new_from_bytes(bytes) bytes.unref() pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale( stream, size, size, True, None) stream.close() surface = Gdk.cairo_surface_create_from_pixbuf( pixbuf, self.__scale_factor, None) self.__artwork.set_from_surface(surface) artwork_height = ArtSize.ARTIST_SMALL * 2 self.__artwork.get_style_context().remove_class( "artwork-icon") self.__artwork.show() self.__artwork_box.show() break # Add a default icon if len(self._artist_ids) == 1 and artwork_height == 0: self.__artwork.set_from_icon_name( "avatar-default-symbolic", Gtk.IconSize.DND) artwork_height = 32 self.__artwork.get_style_context().add_class("artwork-icon") self.__artwork.show() self.__artwork_box.show() # Create an self.__empty widget with header height ctx = self.__label.get_pango_context() layout = Pango.Layout.new(ctx) layout.set_text("a", 1) # Font scale 2 font_height = int(layout.get_pixel_size()[1]) * 2 if artwork_height > font_height: self.__empty.set_property("height-request", artwork_height) else: self.__empty.set_property("height-request", font_height)
def __set_artwork(self): """ Set artist artwork """ artwork_height = 0 if Lp().settings.get_value('artist-artwork'): if len(self._artist_ids) == 1 and\ Lp().settings.get_value('artist-artwork'): artist = Lp().artists.get_name(self._artist_ids[0]) size = ArtSize.ARTIST_SMALL * 2 * self.__scale_factor for suffix in ["lastfm", "spotify", "wikipedia"]: uri = InfoCache.get_artwork(artist, suffix, size) if uri is not None: f = Lio.File.new_for_path(uri) (status, data, tag) = f.load_contents(None) stream = Gio.MemoryInputStream.new_from_data(data, None) pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale( stream, size, size, True, None) stream.close() surface = Gdk.cairo_surface_create_from_pixbuf( pixbuf, self.__scale_factor, None) del pixbuf self.__artwork.set_from_surface(surface) del surface artwork_height = ArtSize.ARTIST_SMALL * 2 self.__artwork.get_style_context().remove_class( 'artwork-icon') self.__artwork.show() self.__artwork_box.show() break # Add a default icon if len(self._artist_ids) == 1 and artwork_height == 0: self.__artwork.set_from_icon_name( 'avatar-default-symbolic', Gtk.IconSize.DND) artwork_height = 32 self.__artwork.get_style_context().add_class('artwork-icon') self.__artwork.show() self.__artwork_box.show() # Create an self.__empty widget with header height ctx = self.__label.get_pango_context() layout = Pango.Layout.new(ctx) layout.set_text("a", 1) # Font scale 2 font_height = int(layout.get_pixel_size()[1]) * 2 if artwork_height > font_height: self.__empty.set_property('height-request', artwork_height) else: self.__empty.set_property('height-request', font_height)
def __init__(self): """ Init artists content """ Gtk.Stack.__init__(self) InfoCache.init() self._stop = False self.__cancel = Gio.Cancellable.new() self._artist = "" self.set_transition_duration(500) self.set_transition_type(Gtk.StackTransitionType.CROSSFADE) builder = Gtk.Builder() builder.add_from_resource('/org/gnome/Lollypop/InfoContent.ui') self.__content = builder.get_object('content') self.__image = builder.get_object('image') self._menu_found = builder.get_object('menu-found') self._menu_not_found = builder.get_object('menu-not-found') self.add_named(builder.get_object('widget'), 'widget') self.add_named(builder.get_object('notfound'), 'notfound') self._spinner = builder.get_object('spinner') self.add_named(self._spinner, 'spinner')
def __init__(self): """ Init artists content """ Gtk.Stack.__init__(self) InfoCache.init() self._stop = False self._cancel = Gio.Cancellable.new() self._artist = "" self.set_transition_duration(500) self.set_transition_type(Gtk.StackTransitionType.CROSSFADE) builder = Gtk.Builder() builder.add_from_resource('/org/gnome/Lollypop/InfoContent.ui') self._content = builder.get_object('content') self._image = builder.get_object('image') self._menu_found = builder.get_object('menu-found') self._menu_not_found = builder.get_object('menu-not-found') self.add_named(builder.get_object('widget'), 'widget') self.add_named(builder.get_object('notfound'), 'notfound') self._spinner = builder.get_object('spinner') self.add_named(self._spinner, 'spinner')
def __on_activate(self, flowbox, child): """ Use pixbuf as cover Reset cache and use player object to announce cover change """ try: data = self.__datas[child.get_child()] self.__close_popover() if self.__album is not None: Lp().art.save_album_artwork(data, self.__album.id) else: for suffix in ["lastfm", "wikipedia", "spotify"]: InfoCache.uncache_artwork(self.__artist, suffix, flowbox.get_scale_factor()) InfoCache.add(self.__artist, None, data, suffix) Lp().art.emit('artist-artwork-changed', self.__artist) self._streams = {} except: self._infobar_label.set_text(_("Reset artwork?")) self._infobar.show() # GTK 3.20 https://bugzilla.gnome.org/show_bug.cgi?id=710888 self._infobar.queue_resize()
def __init__(self): """ Init artists content """ Gtk.Stack.__init__(self) InfoCache.init() self._stop = False self.__cancel = Gio.Cancellable.new() self._artist = "" self.set_transition_duration(500) self.set_transition_type(Gtk.StackTransitionType.CROSSFADE) builder = Gtk.Builder() builder.add_from_resource("/org/gnome/Lollypop/InfoContent.ui") self.__content = builder.get_object("content") self.__image = builder.get_object("image") self._menu_found = builder.get_object("menu-found") self._menu_not_found = builder.get_object("menu-not-found") self.__error = builder.get_object("error") self.add_named(builder.get_object("widget"), "widget") self.add_named(builder.get_object("notfound"), "notfound") self._spinner = builder.get_object("spinner") self.add_named(self._spinner, "spinner")
def __on_activate(self, flowbox, child): """ Use pixbuf as cover Reset cache and use player object to announce cover change """ try: data = self.__datas[child.get_child()] self.__close_popover() if self.__album is not None: Lp().art.save_album_artwork(data, self.__album.id) else: for suffix in ["lastfm", "wikipedia", "spotify"]: InfoCache.uncache_artwork(self.__artist, suffix, flowbox.get_scale_factor()) InfoCache.add(self.__artist, None, data, suffix) Lp().art.emit("artist-artwork-changed", self.__artist) self._streams = {} except: self._infobar_label.set_text(_("Reset artwork?")) self._infobar.show() # GTK 3.20 https://bugzilla.gnome.org/show_bug.cgi?id=710888 self._infobar.queue_resize()
def _load_cache_content(self, prefix, suffix): """ Load from cache @param prefix as str @param suffix as str @return True if loaded """ (content, data) = InfoCache.get(prefix, suffix) if content is not None: stream = None if data is not None: stream = Gio.MemoryInputStream.new_from_data(data, None) GLib.idle_add(self.__set_content, content, stream) return True return False
def _set_artwork(self): """ Set artist artwork """ artwork_height = 0 if Lp().settings.get_value('artist-artwork'): if len(self._artist_ids) == 1 and\ Lp().settings.get_value('artist-artwork'): artist = Lp().artists.get_name(self._artist_ids[0]) for suffix in ["lastfm", "spotify", "wikipedia"]: uri = InfoCache.get_artwork( artist, suffix, ArtSize.ARTIST_SMALL * 2 * self._artwork.get_scale_factor()) if uri is not None: self._artwork.set_from_file(uri) artwork_height = ArtSize.ARTIST_SMALL * 2 self._artwork.get_style_context().remove_class( 'artwork-icon') self._artwork.show() self._artwork_box.show() break # Add a default icon if len(self._artist_ids) == 1 and artwork_height == 0: self._artwork.set_from_icon_name( 'avatar-default-symbolic', Gtk.IconSize.DND) artwork_height = 32 self._artwork.get_style_context().add_class('artwork-icon') self._artwork.show() self._artwork_box.show() # Create an self._empty widget with header height ctx = self._label.get_pango_context() layout = Pango.Layout.new(ctx) layout.set_text("a", 1) # Font scale 2 font_height = int(layout.get_pixel_size()[1]) * 2 if artwork_height > font_height: self._empty.set_property('height-request', artwork_height) else: self._empty.set_property('height-request', font_height)
def __cache_artists_info(self): """ Cache info for all artists """ # We create cache if needed InfoCache.init() # Then cache for lastfm/wikipedia/spotify/deezer/... for (artist_id, artist, sort) in Lp().artists.get([]): if not get_network_available() or\ InfoCache.exists(artist): continue artwork_set = False for (api, helper, unused) in InfoCache.WEBSERVICES: debug("Downloader::__cache_artists_info(): %s@%s" % (artist, api)) if helper is None: continue try: method = getattr(self, helper) (url, content) = method(artist) if url is not None: s = Lio.File.new_for_uri(url) (status, data, tag) = s.load_contents() if status: artwork_set = True InfoCache.add(artist, content, data, api) debug("Downloader::__cache_artists_info(): %s" % url) else: InfoCache.add(artist, None, None, api) except Exception as e: print("Downloader::__cache_artists_info():", e, artist) InfoCache.add(artist, None, None, api) if artwork_set: GLib.idle_add(Lp().art.emit, 'artist-artwork-changed', artist) self.__cache_artists_running = False
def __cache_artists_info(self): """ Cache info for all artists """ # We create cache if needed InfoCache.init() # Then cache for lastfm/wikipedia/spotify/deezer/... for (artist_id, artist) in Lp().artists.get([]): if not get_network_available() or\ InfoCache.exists(artist): continue artwork_set = False for (api, helper, unused) in InfoCache.WEBSERVICES: debug("Downloader::__cache_artists_info(): %s@%s" % (artist, api)) if helper is None: continue try: method = getattr(self, helper) (url, content) = method(artist) if url is not None: s = Lio.File.new_for_uri(url) (status, data, tag) = s.load_contents() if status: artwork_set = True InfoCache.add(artist, content, data, api) debug("Downloader::__cache_artists_info(): %s" % url) else: InfoCache.add(artist, None, None, api) except Exception as e: print("Downloader::__cache_artists_info():", e, artist) InfoCache.add(artist, None, None, api) if artwork_set: GLib.idle_add(Lp().art.emit, 'artist-artwork-changed', artist) self.__cache_artists_running = False
def do_own_render(self, ctx, widget, cell_area, size): surface = None alpha = False if self.rowid in self._surfaces.keys(): surface = self._surfaces[self.rowid] if surface is None: for suffix in ["lastfm", "spotify", "wikipedia"]: uri = InfoCache.get_artwork(self.artist, suffix, size) if uri is not None: pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(uri, size, size) surface = Gdk.cairo_surface_create_from_pixbuf( pixbuf, widget.get_scale_factor(), None) self._surfaces[self.rowid] = surface del pixbuf break if surface is None: alpha = True surface = Gtk.IconTheme.get_default().load_surface( 'media-optical-cd-audio-symbolic', ArtSize.ARTIST_SMALL, 1, widget.get_window(), 0) ctx.translate(cell_area.x, cell_area.y) ctx.new_sub_path() radius = ArtSize.ARTIST_SMALL / 2 ctx.arc(ArtSize.ARTIST_SMALL/2, ArtSize.ARTIST_SMALL/2, radius, 0, 2 * pi) ctx.set_source_rgb(1, 1, 1) ctx.fill_preserve() ctx.set_line_width(2) ctx.set_source_rgba(0, 0, 0, 0.3) ctx.stroke_preserve() ctx.set_source_surface(surface, 0, 0) ctx.clip() if alpha: ctx.paint_with_alpha(0.5) else: ctx.paint()
def __set_artwork(self): """ Set artist artwork """ artwork_height = 0 if Lp().settings.get_value('artist-artwork'): if len(self._artist_ids) == 1 and\ Lp().settings.get_value('artist-artwork'): artist = Lp().artists.get_name(self._artist_ids[0]) for suffix in ["lastfm", "spotify", "wikipedia"]: uri = InfoCache.get_artwork( artist, suffix, ArtSize.ARTIST_SMALL * 2 * self.__artwork.get_scale_factor()) if uri is not None: self.__artwork.set_from_file(uri) artwork_height = ArtSize.ARTIST_SMALL * 2 self.__artwork.get_style_context().remove_class( 'artwork-icon') self.__artwork.show() self.__artwork_box.show() break # Add a default icon if len(self._artist_ids) == 1 and artwork_height == 0: self.__artwork.set_from_icon_name('avatar-default-symbolic', Gtk.IconSize.DND) artwork_height = 32 self.__artwork.get_style_context().add_class('artwork-icon') self.__artwork.show() self.__artwork_box.show() # Create an self.__empty widget with header height ctx = self.__label.get_pango_context() layout = Pango.Layout.new(ctx) layout.set_text("a", 1) # Font scale 2 font_height = int(layout.get_pixel_size()[1]) * 2 if artwork_height > font_height: self.__empty.set_property('height-request', artwork_height) else: self.__empty.set_property('height-request', font_height)
def __init__(self, artist_ids, genre_ids): """ Init ArtistView @param artist id as int (Current if None) @param genre id as int """ ArtistAlbumsView.__init__(self, artist_ids, genre_ids) self._signal_id = None self._artist_ids = artist_ids empty = Gtk.Grid() empty.set_property('height-request', ArtSize.ARTIST_SMALL * 2) empty.show() self._albumbox.add(empty) builder = Gtk.Builder() builder.add_from_resource('/org/gnome/Lollypop/ArtistView.ui') builder.connect_signals(self) self._artwork = builder.get_object('artwork') self._jump_button = builder.get_object('jump-button') self._jump_button.set_tooltip_text(_("Go to current track")) self._spinner = builder.get_object('spinner') header = builder.get_object('header') header.set_property('valign', Gtk.Align.START) self._overlay.add_overlay(header) self._overlay.set_overlay_pass_through(header, True) if len(artist_ids) == 1 and Lp().settings.get_value('artist-artwork'): artist = Lp().artists.get_name(artist_ids[0]) for suffix in ["lastfm", "spotify", "wikipedia"]: uri = InfoCache.get_artwork(artist, suffix, ArtSize.ARTIST_SMALL * 2 * self._artwork.get_scale_factor()) if uri is not None: self._artwork.set_from_file(uri) self._artwork.show() break artists = [] for artist_id in artist_ids: artists.append(Lp().artists.get_name(artist_id)) builder.get_object('artist').set_label(", ".join(artists))
def _cache_artists_art(self): """ Cache artwork for all artists """ # We create cache if needed InfoCache.init() # Then cache artwork for lastfm/wikipedia/spotify # We cache content as the same time # TODO Make this code more generic for (artist_id, artist) in Lp().artists.get([]): debug("ArtDownloader::_cache_artists_art(): %s" % artist) artwork_set = False if not Gio.NetworkMonitor.get_default().get_network_available() or\ InfoCache.exists_in_cache(artist): continue if Lp().lastfm is not None: try: (url, content) = Lp().lastfm.get_artist_infos(artist) if url is not None: s = Gio.File.new_for_uri(url) (status, data, tag) = s.load_contents() if status: artwork_set = True InfoCache.cache(artist, content, data, "lastfm") else: InfoCache.cache(artist, None, None, "lastfm") except: InfoCache.cache(artist, None, None, "lastfm") if ArtDownloader.Wikipedia is not None: try: wp = ArtDownloader.Wikipedia() (url, content) = wp.get_page_infos(artist) if url is not None: s = Gio.File.new_for_uri(url) (status, data, tag) = s.load_contents() if status: artwork_set = True InfoCache.cache(artist, content, data, "wikipedia") else: InfoCache.cache(artist, None, None, "wikipedia") except: InfoCache.cache(artist, None, None, "wikipedia") url = self._get_spotify_artist_artwork(artist) if url is not None: s = Gio.File.new_for_uri(url) (status, data, tag) = s.load_contents() if status: artwork_set = True InfoCache.cache(artist, None, data, "spotify") else: InfoCache.cache(artist, None, None, "spotify") if artwork_set: Lp().art.emit('artist-artwork-changed', artist) self._cache_artists_running = False