def _on_map_lyrics(self, widget): """ Load on map @param widget as Gtk.Viewport """ self._on_child_unmap(widget) Lp().settings.set_value('infoswitch', GLib.Variant('s', 'lyrics')) self.__jump_button.hide() if self.__current_track.id is None: self.__current_track = Lp().player.current_track # First try to get lyrics from tags from lollypop.tagreader import TagReader reader = TagReader() try: info = reader.get_info(self.__current_track.uri) except: info = None lyrics = "" if info is not None: tags = info.get_tags() lyrics = reader.get_lyrics(tags) if lyrics or InfoPopover.WebView is None\ or not get_network_available(): label = Gtk.Label() label.set_vexpand(True) label.set_hexpand(True) label.set_margin_top(10) label.set_margin_end(10) label.show() widget.add(label) if lyrics: label.set_label(lyrics) elif not get_network_available(): string = GLib.markup_escape_text(_("Network access disabled")) label.get_style_context().add_class('dim-label') label.set_markup( "<span font_weight='bold' size='xx-large'>" + string + "</span>") else: string = GLib.markup_escape_text( _("No lyrics found, please install gir1.2-webkit2-4.0")) label.get_style_context().add_class('dim-label') label.set_markup( "<span font_weight='bold' size='xx-large'>" + string + "</span>") elif get_network_available(): artists = ", ".join(Lp().player.current_track.artists) title = self.__current_track.name search = GLib.uri_escape_string(artists + " " + title, None, True) url = "http://genius.com/search?q=%s" % search # Delayed load due to WebKit memory loading and Gtk animation web = self.WebView(True, True) web.add_word('search') web.add_word('lyrics') web.show() widget.add(web) GLib.timeout_add(250, web.load, url, OpenLink.OPEN)
def populate(self, track): """ Set lyrics @param track as Track """ self.__current_track = track self.update_artwork(self.__current_width, self.__current_height) self.__lyrics_text = "" self.__update_lyrics_style() self.__lyrics_label.set_text(_("Loading…")) self.__cancellable.cancel() self.__cancellable.reset() # First try to get lyrics from tags from lollypop.tagreader import TagReader reader = TagReader() try: info = reader.get_info(self.__current_track.uri) except: info = None if info is not None: tags = info.get_tags() self.__lyrics_text = reader.get_lyrics(tags) if self.__lyrics_text: self.__lyrics_label.set_label(self.__lyrics_text) else: self.__download_wikia_lyrics() self.__download_genius_lyrics()
def __update_for_url(self, url): """ Update charts for url @param url as str """ if not get_network_available(): return debug("ItunesCharts::__update_for_url(): %s => %s" % (url, self.__LIMIT)) web = Web() ids = self.__get_ids(url) position = len(ids) while ids: sleep(10) (itunes_id, itunes_genre) = ids.pop(0) album = self.__get_album(itunes_id) if self.__stop: return if album is None or not album.subitems: position -= 1 continue album.mtime = self.__time + position for item in album.subitems: item.mtime = self.__time debug("ItunesCharts::__update_for_url(): %s - %s" % (album.name, album.artists)) t = TagReader() with SqlCursor(Lp().db) as sql: genre_ids = t.add_genres(itunes_genre) sql.commit() genre_ids.append(Type.ITUNES) web.save_album_thread(album, DbPersistent.CHARTS, genre_ids) position -= 1
def __update_for_url(self, url): """ Update charts for url @param url as str """ if not get_network_available(): return debug("ItunesCharts::__update_for_url(): %s => %s" % (url, self.__LIMIT)) web = Web() ids = self.__get_ids(url) position = len(ids) while ids: sleep(10) (itunes_id, itunes_genre) = ids.pop(0) album = self.__get_album(itunes_id) if self.__stop: return if album is None or not album.subitems: position -= 1 continue album.mtime = self.__time + position for item in album.subitems: item.mtime = self.__time debug("ItunesCharts::__update_for_url(): %s - %s" % ( album.name, album.artists)) t = TagReader() with SqlCursor(Lp().db) as sql: genre_ids = t.add_genres(itunes_genre) sql.commit() genre_ids.append(Type.ITUNES) web.save_album_thread(album, DbPersistent.CHARTS, genre_ids) position -= 1
def _on_bus_message_tag(self, bus, message): """ Read tags from stream @param bus as Gst.Bus @param message as Gst.Message """ # Some radio streams send message tag every seconds! changed = False if self._current_track.id >= 0 or self._current_track.duration > 0.0: return Logger.debug("Player::__on_bus_message_tag(): %s" % self._current_track.uri) reader = TagReader() tags = message.parse_tag() title = reader.get_title(tags, "") if title != "" and self._current_track.name != title: self._current_track.name = title changed = True if self._current_track.name == "": self._current_track.name = self._current_track.uri changed = True artists = reader.get_artists(tags) if artists != "" and self._current_track.artists != artists: self._current_track.artists = artists.split(",") changed = True if not self._current_track.artists: self._current_track.artists = self._current_track.album_artists changed = True if changed: self.emit("current-changed")
def __init__(self): BinPlayer.__init__(self) QueuePlayer.__init__(self) LinearPlayer.__init__(self) ShufflePlayer.__init__(self) UserPlaylistPlayer.__init__(self) TagReader.__init__(self)
def _on_map_lyrics(self, widget): """ Load on map @param widget as Gtk.Viewport """ self._on_child_unmap(widget) Lp().settings.set_value('infoswitch', GLib.Variant('s', 'lyrics')) self.__jump_button.hide() if self.__current_track.id is None: self.__current_track = Lp().player.current_track # First try to get lyrics from tags from lollypop.tagreader import TagReader reader = TagReader() try: info = reader.get_info(self.__current_track.uri) except: info = None lyrics = "" if info is not None: tags = info.get_tags() lyrics = reader.get_lyrics(tags) if lyrics or InfoPopover.WebView is None\ or not get_network_available(): label = Gtk.Label() label.set_vexpand(True) label.set_hexpand(True) label.set_margin_top(10) label.set_margin_end(10) label.show() widget.add(label) if lyrics: label.set_label(lyrics) elif not get_network_available(): string = GLib.markup_escape_text(_("Network access disabled")) label.get_style_context().add_class('dim-label') label.set_markup("<span font_weight='bold' size='xx-large'>" + string + "</span>") else: string = GLib.markup_escape_text( _("No lyrics found, please install gir1.2-webkit2-4.0")) label.get_style_context().add_class('dim-label') label.set_markup("<span font_weight='bold' size='xx-large'>" + string + "</span>") elif get_network_available(): title = self.__current_track.name if self.__current_track.id == Type.RADIOS: search = GLib.uri_escape_string(title, None, True) else: artists = ", ".join(Lp().player.current_track.artists) search = GLib.uri_escape_string(artists + " " + title, None, True) url = "http://genius.com/search?q=%s" % search # Delayed load due to WebKit memory loading and Gtk animation web = self.WebView(True, True) web.add_word('search') web.add_word('lyrics') web.show() widget.add(web) GLib.timeout_add(250, web.load, url, OpenLink.OPEN)
def __init__(self): """ Init radio art """ BaseArt.__init__(self) TagReader.__init__(self) self.__favorite = Lp().settings.get_value( 'favorite-cover').get_string()
def __init__(self): """ Init album art """ BaseArt.__init__(self) TagReader.__init__(self) self.__favorite = Lp().settings.get_value( "favorite-cover").get_string()
def __init__(self): """ Init radio art """ BaseArt.__init__(self) ArtDownloader.__init__(self) TagReader.__init__(self) self._favorite = Lp().settings.get_value('favorite-cover').get_string()
def __save_track(self, item, persistent, album_artist): """ Save item into collection as track @param item as SearchItem @param persistent as DbPersistent @param album artist as str @return (album id as int, track id as int) """ # Get uri from helpers for helper in self.__helpers: uri = helper.get_uri(item) if uri: break # Don't found anything if not uri: return (None, None) track_id = Lp().tracks.get_id_by_uri(uri) # Check if track needs to be updated if track_id is not None: if Lp().tracks.get_persistent(track_id) == DbPersistent.NONE\ and persistent == DbPersistent.EXTERNAL: Lp().tracks.set_persistent(track_id, DbPersistent.EXTERNAL) return (None, None) t = TagReader() with SqlCursor(Lp().db) as sql: # Happen often with Itunes/Spotify if album_artist not in item.artists: item.artists.append(album_artist) artists = "; ".join(item.artists) artist_ids = t.add_artists(artists, album_artist, "") album_artist_ids = t.add_album_artists(album_artist, "") (album_id, new_album) = t.add_album(item.album, album_artist_ids, "", False, 0, 0, int(time()), True) # FIXME: Check this, could move this in add_album() if new_album: Lp().albums.set_synced(album_id, Type.NONE) if persistent == DbPersistent.CHARTS: genre_ids = [Type.CHARTS] new_artist_ids = [] else: new_artist_ids = list(set(artist_ids) | set(album_artist_ids)) genre_ids = t.add_genres("Web", album_id) # Add track to db track_id = Lp().tracks.add(item.name, uri, item.duration, 0, item.discnumber, "", album_id, item.year, 0, 0, 0, persistent) t.update_track(track_id, artist_ids, genre_ids) t.update_album(album_id, album_artist_ids, genre_ids, None) sql.commit() for genre_id in genre_ids: GLib.idle_add(Lp().scanner.emit, 'genre-updated', genre_id, True) for artist_id in new_artist_ids: GLib.idle_add(Lp().scanner.emit, 'artist-updated', artist_id, True) return (album_id, track_id)
def __init__(self): BaseArt.__init__(self) TagReader.__init__(self) self._favorite = Lp.settings.get_value('favorite-cover').get_string() if not os.path.exists(self._CACHE_PATH): try: os.mkdir(self._CACHE_PATH) except: print("Can't create %s" % self._CACHE_PATH)
def __on_bus_message_tag(self, bus, message): """ Read tags from stream @param bus as Gst.Bus @param message as Gst.Message """ # Some radio streams send message tag every seconds! changed = False if (self.current_track.persistent == DbPersistent.INTERNAL or self.current_track.mtime != 0) and\ (self.current_track.id >= 0 or self.current_track.duration > 0.0): return debug("Player::__on_bus_message_tag(): %s" % self.current_track.uri) reader = TagReader() # Update duration of non internals if self.current_track.persistent != DbPersistent.INTERNAL: t = Thread(target=self.__update_current_duration, args=(reader, self.current_track)) t.daemon = True t.start() return tags = message.parse_tag() title = reader.get_title(tags, '') if title != '' and self.current_track.name != title: self.current_track.name = title changed = True if self.current_track.name == '': self.current_track.name = self.current_track.uri changed = True artists = reader.get_artists(tags) if artists != '' and self.current_track.artists != artists: self.current_track.artists = artists.split(',') changed = True if not self.current_track.artists: self.current_track.artists = self.current_track.album_artists changed = True if self.current_track.id == Type.EXTERNALS: (b, duration) = self._playbin.query_duration(Gst.Format.TIME) if b: self.current_track.duration = duration/1000000000 # We do not use tagreader as we need to check if value is None self.current_track.album_name = tags.get_string_index('album', 0)[1] if self.current_track.album_name is None: self.current_track.album_name = '' self.current_track.genres = reader.get_genres(tags).split(',') changed = True if changed: self.emit('current-changed')
def __save_track(self, item, persistent, album_artist): """ Save item into collection as track @param item as SearchItem @param persistent as DbPersistent @param album artist as str @return (album id as int, track id as int) """ # Get uri from helpers for helper in self.__helpers: uri = helper.get_uri(item) if uri: break # Don't found anything if not uri: return (None, None) track_id = Lp().tracks.get_id_by_uri(uri) # Check if track needs to be updated if track_id is not None: if Lp().tracks.get_persistent(track_id) == DbPersistent.NONE\ and persistent == DbPersistent.EXTERNAL: Lp().tracks.set_persistent(track_id, DbPersistent.EXTERNAL) return (None, None) t = TagReader() with SqlCursor(Lp().db) as sql: # Happen often with Itunes/Spotify if album_artist not in item.artists: item.artists.append(album_artist) artists = "; ".join(item.artists) artist_ids = t.add_artists(artists, album_artist, "") album_artist_ids = t.add_album_artists(album_artist, "") (album_id, new_album) = t.add_album(item.album, album_artist_ids, "", 0, int(time()), True) # FIXME: Check this, could move this in add_album() if new_album: Lp().albums.set_synced(album_id, Type.NONE) if persistent == DbPersistent.CHARTS: genre_ids = [Type.CHARTS] new_artist_ids = [] else: new_artist_ids = list(set(artist_ids) | set(album_artist_ids)) genre_ids = t.add_genres("Web", album_id) # Add track to db track_id = Lp().tracks.add(item.name, uri, item.duration, 0, item.discnumber, "", album_id, item.year, 0, 0, 0, persistent) t.update_track(track_id, artist_ids, genre_ids) t.update_album(album_id, album_artist_ids, genre_ids, None) sql.commit() for genre_id in genre_ids: GLib.idle_add(Lp().scanner.emit, 'genre-updated', genre_id, True) for artist_id in new_artist_ids: GLib.idle_add(Lp().scanner.emit, 'artist-updated', artist_id, True) return (album_id, track_id)
def __on_bus_message_tag(self, bus, message): """ Read tags from stream @param bus as Gst.Bus @param message as Gst.Message """ # Some radio streams send message tag every seconds! changed = False if (self.current_track.persistent == DbPersistent.INTERNAL or self.current_track.mtime != 0) and\ (self.current_track.id >= 0 or self.current_track.duration > 0.0): return debug("Player::__on_bus_message_tag(): %s" % self.current_track.uri) reader = TagReader() # Update duration of non internals if self.current_track.persistent != DbPersistent.INTERNAL: t = Thread(target=self.__update_current_duration, args=(reader, self.current_track)) t.daemon = True t.start() return tags = message.parse_tag() title = reader.get_title(tags, '') if title != '' and self.current_track.name != title: self.current_track.name = title changed = True if self.current_track.name == '': self.current_track.name = self.current_track.uri changed = True artists = reader.get_artists(tags) if artists != '' and self.current_track.artists != artists: self.current_track.artists = artists.split(',') changed = True if not self.current_track.artists: self.current_track.artists = self.current_track.album_artists changed = True if self.current_track.id == Type.EXTERNALS: (b, duration) = self._playbin.query_duration(Gst.Format.TIME) if b: self.current_track.duration = duration / 1000000000 # We do not use tagreader as we need to check if value is None self.current_track.album_name = tags.get_string_index('album', 0)[1] if self.current_track.album_name is None: self.current_track.album_name = '' self.current_track.genres = reader.get_genres(tags).split(',') changed = True if changed: self.emit('current-changed')
def populate(self, track): """ Set lyrics @param track as Track """ self.__banner.translate_button.set_sensitive(False) if track.id is None: self.__lyrics_label.set_text("") return self.__lyrics_label.set_text(_("Loading…")) lyrics = "" if isinstance(track, Track): self.__lyrics_helper.load(track) # First check synced lyrics if self.__lyrics_helper.available: if self.__lyrics_timeout_id is None: self.__lyrics_timeout_id = GLib.timeout_add( 200, self.__show_sync_lyrics) return else: if self.__lyrics_timeout_id is not None: GLib.source_remove(self.__lyrics_timeout_id) self.__lyrics_timeout_id = None if track.storage_type & (StorageType.COLLECTION | StorageType.EXTERNAL): from lollypop.tagreader import TagReader, Discoverer tagreader = TagReader() discoverer = Discoverer() try: info = discoverer.get_info(track.uri) except: info = None if info is not None: tags = info.get_tags() lyrics = tagreader.get_lyrics(tags) if lyrics: self.__lyrics_label.set_text(lyrics) self.__lyrics_text = lyrics else: name = track.name + track.album.name + ",".join(track.artists) content = self.__information_store.get_information(name, LYRICS_PATH) if content: self.__lyrics_label.set_text(content.decode("utf-8")) elif not get_network_available(): self.__lyrics_label.set_text( _("Network unavailable or disabled in settings")) else: self.__lyrics_helper.get_lyrics_from_web(track, self.__on_lyrics, False, track)
def __init__(self): """ Init radio art """ BaseArt.__init__(self) ArtDownloader.__init__(self) TagReader.__init__(self) self._favorite = Lp.settings.get_value('favorite-cover').get_string() if not os.path.exists(self._CACHE_PATH): try: os.mkdir(self._CACHE_PATH) except: print("Can't create %s" % self._CACHE_PATH)
def __init__(self): """ Init collection scanner """ GObject.GObject.__init__(self) TagReader.__init__(self) self.__thread = None self.__history = None if Lp().settings.get_value('auto-update'): self.__inotify = Inotify() else: self.__inotify = None
def __init__(self): """ Init collection scanner """ GObject.GObject.__init__(self) TagReader.__init__(self) self.__thread = None self.__history = None if Lp().settings.get_value('auto-update'): self.__inotify = Inotify() else: self.__inotify = None Lp().albums.update_max_count()
def __update_current_duration(self, track, uri): """ Update current track duration @param track as Track @param uri as str """ try: reader = TagReader() duration = reader.get_info(uri).get_duration() / 1000000000 if duration != track.duration and duration > 0: App().tracks.set_duration(track.id, int(duration)) track.reset("duration") GLib.idle_add(self.emit, "duration-changed", track.id) except Exception as e: Logger.error("BinPlayer::__update_current_duration(): %s" % e)
def __init__(self): """ Init collection scanner """ GObject.GObject.__init__(self) TagReader.__init__(self) self.__thread = None self.__history = None self.__disable_compilations = True if App().settings.get_value("auto-update"): self.__inotify = Inotify() else: self.__inotify = None App().albums.update_max_count()
def __save_track(self, item, persistent, album_artist): """ Save item into collection as track @param item as SearchItem @param persistent as DbPersistent @param album artist as str @return (album id as int, track id as int) """ yid = self.__get_youtube_id(item) if yid is None: return (None, None) uri = "https://www.youtube.com/watch?v=%s" % yid track_id = Lp().tracks.get_id_by_uri(uri) # Check if track needs to be updated if track_id is not None: if Lp().tracks.get_persistent(track_id) == DbPersistent.NONE\ and persistent == DbPersistent.EXTERNAL: Lp().tracks.set_persistent(track_id, DbPersistent.EXTERNAL) return (None, None) t = TagReader() with SqlCursor(Lp().db) as sql: artists = "; ".join(item.artists) (artist_ids, new_artist_ids) = t.add_artists(artists, album_artist, "") (album_artist_ids, new_album_artist_ids) = t.add_album_artists(album_artist, "") (album_id, new_album) = t.add_album(item.album, album_artist_ids, "", 0, 0) (genre_ids, new_genre_ids) = t.add_genres(_("Youtube"), album_id) # Add track to db uri = "https://www.youtube.com/watch?v=%s" % yid track_id = Lp().tracks.add(item.name, uri, item.duration, 0, item.discnumber, "", album_id, None, 0, 0, 0, persistent) t.update_track(track_id, artist_ids, genre_ids) t.update_album(album_id, album_artist_ids, genre_ids, None) sql.commit() # Notify about new artists/genres if new_genre_ids or new_artist_ids: for genre_id in new_genre_ids: GLib.idle_add(Lp().scanner.emit, 'genre-updated', genre_id, True) for artist_id in new_artist_ids: GLib.idle_add(Lp().scanner.emit, 'artist-updated', artist_id, album_id, True) return (album_id, track_id)
def _on_bus_message_tag(self, bus, message): """ Read tags from stream @param bus as Gst.Bus @param message as Gst.Message """ if self._current_track.storage_type != StorageType.EXTERNAL: return Logger.debug("Player::__on_bus_message_tag(): %s" % self._current_track.uri) reader = TagReader() tags = message.parse_tag() title = reader.get_title(tags, "") if len(title) > 1 and self._current_track.title != title: self._current_track.set_name(title) emit_signal(self, "current-changed")
def _on_map_lyrics(self, widget): """ Load on map @param widget as Gtk.Viewport """ self._on_child_unmap(widget) Lp().settings.set_value('infoswitch', GLib.Variant('s', 'lyrics')) self.__jump_button.hide() if self.__current_track.id is None: self.__current_track = Lp().player.current_track # First try to get lyrics from tags from lollypop.tagreader import TagReader reader = TagReader() try: info = reader.get_info(self.__current_track.uri) except: info = None lyrics = "" if info is not None: tags = info.get_tags() lyrics = reader.get_lyrics(tags) if lyrics or InfoPopover.WebView is None: label = Gtk.Label() label.set_vexpand(True) label.set_hexpand(True) label.set_margin_top(10) label.set_margin_end(10) label.show() widget.add(label) if lyrics: label.set_label(lyrics) else: label.set_label( _("No lyrics found, please install gir1.2-webkit2-4.0")) else: artists = ", ".join(Lp().player.current_track.artists) title = self.__current_track.name url = "http://genius.com/search?q=%s" % artists + " " + title # Delayed load due to WebKit memory loading and Gtk animation web = self.WebView(True, True) web.add_word('search') web.add_word('lyrics') web.show() widget.add(web) GLib.timeout_add(250, web.load, url, OpenLink.OPEN)
def populate(self, track): """ Set lyrics @param track as Track """ self.__current_track = track self.update_artwork(self.__size, self.__size) self.__lyrics_text = "" self.__lyrics_label.set_text(_("Loading…")) self.__cancellable.cancel() self.__cancellable = Gio.Cancellable() self.__sync_lyrics_helper.load(track) self.__update_lyrics_style() if self.__sync_lyrics_helper.available: self.__translate_button.hide() if self.__lyrics_timeout_id is None: self.__lyrics_timeout_id = GLib.timeout_add( 500, self.__show_sync_lyrics) return else: self.__translate_button.show() if self.__lyrics_timeout_id is not None: GLib.source_remove(self.__lyrics_timeout_id) self.__lyrics_timeout_id = None # First try to get lyrics from tags from lollypop.tagreader import TagReader reader = TagReader() try: info = reader.get_info(self.__current_track.uri) except: info = None if info is not None: tags = info.get_tags() self.__lyrics_text = reader.get_lyrics(tags) if self.__lyrics_text: self.__lyrics_label.set_text(self.__lyrics_text) else: if get_network_available("WIKIA"): self.__download_wikia_lyrics() if get_network_available("GENIUS"): self.__download_genius_lyrics() if self.__downloads_running == 0: self.__lyrics_label.set_text( _("You have disabled lyrics search in network settings !"))
def __init__(self): """ Init popover """ Gtk.Popover.__init__(self) self.set_position(Gtk.PositionType.BOTTOM) self.connect('unmap', self.__on_self_unmap) builder = Gtk.Builder() builder.add_from_resource('/org/gnome/Lollypop/ExternalsPopover.ui') builder.connect_signals(self) self.__signal_id = None self.__view = builder.get_object('view') self.__model = builder.get_object('model') self.__tagreader = TagReader() renderer0 = Gtk.CellRendererPixbuf() renderer1 = Gtk.CellRendererText() renderer1.set_property('weight', 800) renderer1.set_property('weight-set', True) renderer1.set_property('ellipsize-set', True) renderer1.set_property('ellipsize', Pango.EllipsizeMode.END) renderer2 = Gtk.CellRendererText() renderer2.set_property('ellipsize-set', True) renderer2.set_property('ellipsize', Pango.EllipsizeMode.END) renderer3 = Gtk.CellRendererText() column = Gtk.TreeViewColumn('') column.pack_start(renderer0, True) column.pack_start(renderer1, True) column.pack_start(renderer2, True) column.pack_end(renderer3, False) column.add_attribute(renderer0, 'icon-name', 1) column.add_attribute(renderer1, 'text', 2) column.add_attribute(renderer2, 'text', 3) column.add_attribute(renderer3, 'text', 4) column.set_expand(True) column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) self.__view.append_column(column) self.add(self.__view) self.__signal_id = Lp().player.connect('current-changed', self.__on_current_changed) height = Lp().window.get_size()[1] self.set_size_request(400, height*0.7)
def _on_bus_message_tag(self, bus, message): """ Read tags from stream @param bus as Gst.Bus @param message as Gst.Message """ # Some radio streams send message tag every seconds! changed = False if self._current_track.id >= 0 or self._current_track.duration > 0.0: return debug("Player::__on_bus_message_tag(): %s" % self._current_track.uri) reader = TagReader() tags = message.parse_tag() title = reader.get_title(tags, "") if title != "" and self._current_track.name != title: self._current_track.name = title changed = True if self._current_track.name == "": self._current_track.name = self._current_track.uri changed = True artists = reader.get_artists(tags) if artists != "" and self._current_track.artists != artists: self._current_track.artists = artists.split(",") changed = True if not self._current_track.artists: self._current_track.artists = self._current_track.album_artists changed = True if self._current_track.id == Type.EXTERNALS: (b, duration) = self._playbin.query_duration(Gst.Format.TIME) if b: self._current_track.duration = duration/1000000000 # We do not use tagreader as we need to check if value is None self._current_track.album_name = tags.get_string_index("album", 0)[1] if self._current_track.album_name is None: self._current_track.album_name = "" self._current_track.genres = reader.get_genres(tags).split(",") changed = True if changed: self.emit("current-changed")
def load(self, track): """ Load lyrics for track @param track as Track """ self.__track = track self.__timestamps = {} uri_no_ext = ".".join(track.uri.split(".")[:-1]) self.__lrc_file = Gio.File.new_for_uri(uri_no_ext + ".lrc") if self.__lrc_file.query_exists(): self.__get_timestamps() else: from lollypop.tagreader import TagReader reader = TagReader() try: info = reader.get_info(track.uri) except: info = None if info is not None: tags = info.get_tags() for (lyrics, timestamp) in reader.get_synced_lyrics(tags): self.__timestamps[timestamp] = lyrics
def _on_map_lyrics(self, widget): """ Load on map @param widget as Gtk.Viewport """ Lp().settings.set_value("infoswitch", GLib.Variant("s", "lyrics")) self.__jump_button.hide() if self.__current_track.id is None: self.__current_track = Lp().player.current_track # First try to get lyrics from tags from lollypop.tagreader import TagReader reader = TagReader() try: info = reader.get_info(self.__current_track.uri) except: info = None lyrics = "" if info is not None: tags = info.get_tags() lyrics = reader.get_lyrics(tags) if lyrics or InfoPopover.WebView is None\ or not get_network_available(): # Destroy previous widgets self._on_child_unmap(widget) label = Gtk.Label() label.set_vexpand(True) label.set_hexpand(True) label.set_margin_top(10) label.set_margin_end(10) label.show() widget.add(label) if lyrics: label.set_label(lyrics) elif not get_network_available(): string = GLib.markup_escape_text(_("Network access disabled")) label.get_style_context().add_class("dim-label") label.set_markup('<span font_weight="bold" size="xx-large">' + string + "</span>") else: string = GLib.markup_escape_text( _("No lyrics found, please install gir1.2-webkit2-4.0")) label.get_style_context().add_class("dim-label") label.set_markup('<span font_weight="bold" size="xx-large">' + string + "</span>") elif get_network_available(): title = self.__current_track.name if self.__current_track.id == Type.RADIOS: search = GLib.uri_escape_string(title, None, True) else: artists = ", ".join(Lp().player.current_track.artists) search = GLib.uri_escape_string(artists + " " + title, None, True) url = "http://genius.com/search?q=%s" % search # If we do not have a webview in children, create a new one # Else load url children = widget.get_children() if not children or not isinstance(children[0], self.WebView): # Destroy previous widgets self._on_child_unmap(widget) web = self.WebView(True, True) web.add_word("search") web.add_word("lyrics") web.show() widget.add(web) # Delayed load due to WebKit memory loading and Gtk animation GLib.timeout_add(250, web.load, url, OpenLink.NEW) elif url != children[0].url: children[0].load(url, OpenLink.NEW)
class ExternalsPopover(Gtk.Popover): """ Popover for external tracks """ def __init__(self): """ Init popover """ Gtk.Popover.__init__(self) self.set_position(Gtk.PositionType.BOTTOM) self.connect('unmap', self.__on_self_unmap) builder = Gtk.Builder() builder.add_from_resource('/org/gnome/Lollypop/ExternalsPopover.ui') builder.connect_signals(self) self.__signal_id = None self.__view = builder.get_object('view') self.__model = builder.get_object('model') self.__tagreader = TagReader() renderer0 = Gtk.CellRendererPixbuf() renderer1 = Gtk.CellRendererText() renderer1.set_property('weight', 800) renderer1.set_property('weight-set', True) renderer1.set_property('ellipsize-set', True) renderer1.set_property('ellipsize', Pango.EllipsizeMode.END) renderer2 = Gtk.CellRendererText() renderer2.set_property('ellipsize-set', True) renderer2.set_property('ellipsize', Pango.EllipsizeMode.END) renderer3 = Gtk.CellRendererText() column = Gtk.TreeViewColumn('') column.pack_start(renderer0, True) column.pack_start(renderer1, True) column.pack_start(renderer2, True) column.pack_end(renderer3, False) column.add_attribute(renderer0, 'icon-name', 1) column.add_attribute(renderer1, 'text', 2) column.add_attribute(renderer2, 'text', 3) column.add_attribute(renderer3, 'text', 4) column.set_expand(True) column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) self.__view.append_column(column) self.add(self.__view) self.__signal_id = Lp().player.connect('current-changed', self.__on_current_changed) height = Lp().window.get_size()[1] self.set_size_request(400, height*0.7) def populate(self): """ Populate popover """ self.__model.clear() self.__populate(Lp().player.get_externals()) ####################### # PROTECTED # ####################### def _on_row_activated(self, view, path, column): """ Play selected track @param view as Gtk.TreeView @param path as Gtk.TreePath @param column as Gtk.TreeViewColumn """ if path is not None: iterator = self.__model.get_iter(path) if iterator is not None: uri = self.__model.get_value(iterator, 0) Lp().player.play_this_external(uri) ####################### # PRIVATE # ####################### def __populate(self, tracks): """ Populate popover @param tracks as [Track] @thread safe """ for track in tracks: if track.duration == 0.0: try: info = self.__tagreader.get_info(track.uri) track_name = GLib.path_get_basename( GLib.filename_from_uri(track.uri)[0]) if info is not None: tags = info.get_tags() track.duration = info.get_duration()/1000000000 track.name = self.__tagreader.get_title(tags, track_name) track.artist_names = self.__tagreader.get_artists(tags) else: track.name = track_name except Exception as e: print("ExternalsPopover::__populate(): %s" % e) track.name = track_name GLib.idle_add(self.__add_track, track) def __add_track(self, track): """ Add track to model @param track as Track @param filepath as string """ if track.uri == Lp().player.current_track.uri: self.__model.append((track.uri, 'media-playback-start-symbolic', track.artist, track.title, seconds_to_string(track.duration))) else: self.__model.append((track.uri, '', track.artist, track.title, seconds_to_string(track.duration))) def __on_self_unmap(self, widget): """ Disconnect signals and destroy @param widget as Gtk.Widget """ if self.__signal_id is not None: Lp().player.disconnect(self.__signal_id) GLib.idle_add(self.destroy) def __on_current_changed(self, player): """ Update play symbol @param player as Player """ for item in self.__model: if item[0] == player.current_track.uri: item[1] = 'media-playback-start-symbolic' else: item[1] = ''
class CollectionImporter: """ Import files to main collection (as files) """ def __init__(self): """ Init collection scanner """ self.__tag_reader = TagReader() def add(self, uris): """ Add uris to collection """ GLib.idle_add(App().window.container.progress.pulse, True) walk_uris = list(uris) while walk_uris: uri = walk_uris.pop(0) if not uri: continue try: f = Gio.File.new_for_uri(uri) file_type = f.query_file_type(Gio.FileQueryInfoFlags.NONE, None) if file_type == Gio.FileType.DIRECTORY: infos = f.enumerate_children( "standard::name,standard::type,standard::is-hidden", Gio.FileQueryInfoFlags.NONE, None) for info in infos: f = infos.get_child(info) child_uri = f.get_uri() if info.get_is_hidden(): continue elif info.get_file_type() == Gio.FileType.DIRECTORY: walk_uris.append(child_uri) else: if is_audio(f): self.__add_file(f) elif is_audio(f): self.__add_file(f) else: Logger.info("Not an audio file %s" % uri) except Exception as e: Logger.error("CollectionImporter::add(): %s" % e) GLib.idle_add(App().window.container.progress.pulse, False) ####################### # PRIVATE # ####################### def __add_file(self, f): """ Add file to collection @param f as Gio.File """ try: # We only import to primary collection music_uris = App().settings.get_music_uris() if music_uris: music_uri = music_uris[0] else: Logger.error("CollectionImporter::__add_file(): No collection") return info = self.__tag_reader.get_info(f.get_uri()) tags = info.get_tags() name = f.get_basename() title = self.__tag_reader.get_title(tags, name) artists = self.__tag_reader.get_artists(tags) album_artists = self.__tag_reader.get_album_artist(tags) album_name = self.__tag_reader.get_album_name(tags) tracknumber = self.__tag_reader.get_tracknumber(tags, name) # If no artists tag, use album artist if album_artists == "": album_artists = artists if album_artists == "": album_artists = _("Unknown") extension = f.get_uri().split(".")[-1] dest_dir_uri = "%s/%s/%s" % (music_uri, album_artists, album_name) dest_dir = Gio.File.new_for_uri(dest_dir_uri) if not dest_dir.query_exists(): dest_dir.make_directory_with_parents(None) if tracknumber == 0: dest_uri = "%s/%s.%s" % (dest_dir_uri, title, extension) else: dest_uri = "%s/%02d_%s.%s" % (dest_dir_uri, tracknumber, title, extension) dest = Gio.File.new_for_uri(dest_uri) f.copy(dest, Gio.FileCopyFlags.NONE, None, None, None) except Exception as e: Logger.error("CollectionImporter::__add_file(): %s" % e)
def __save_track(self, item, persistent, album_artist, genre_ids): """ Save item into collection as track @param item as SearchItem @param persistent as DbPersistent @param album artist as str @param genre ids as [int] @return (album id as int, track id as int) """ t = TagReader() # Get uri from helpers for helper in self.__helpers: uri = helper.get_uri(item) if uri: break # Don"t found anything if not uri: return (None, None) # If album exists, is not in charts and we want to save # a charts track to this album, abort! # User already saved this album to collection, # may have removed some tracks, do not add them again! (exists, album_id) = item.album.exists_in_db() if exists: album_genre_ids = Lp().albums.get_genre_ids(album_id) if Type.CHARTS not in album_genre_ids and\ persistent == DbPersistent.CHARTS: return (None, None) # Check if track needs to be updated (exists, track_id) = item.exists_in_db() if exists: if Lp().tracks.get_persistent(track_id) == DbPersistent.NONE\ and persistent == DbPersistent.EXTERNAL: Lp().tracks.set_persistent(track_id, DbPersistent.EXTERNAL) return (None, None) # Do not mark as charts any local/web track track_genre_ids = Lp().tracks.get_genre_ids(track_id) if Type.CHARTS in track_genre_ids: album_id = Lp().tracks.get_album_id(track_id) with SqlCursor(Lp().db) as sql: t.update_track(track_id, [], genre_ids, item.mtime) t.update_album(album_id, [], genre_ids, item.album.mtime, None) sql.commit() return (None, None) with SqlCursor(Lp().db) as sql: # Happen often with Itunes/Spotify if album_artist not in item.artists: item.artists.append(album_artist) artists = "; ".join(item.artists) artist_ids = t.add_artists(artists, album_artist, "") album_artist_ids = t.add_album_artists(album_artist, "") (album_id, new_album) = t.add_album(item.album.name, album_artist_ids, "", False, 0, 0, True) # FIXME: Check this, could move this in add_album() if new_album: Lp().albums.set_synced(album_id, Type.NONE) if persistent == DbPersistent.CHARTS: genre_ids.append(Type.CHARTS) new_artist_ids = [] else: new_artist_ids = list(set(artist_ids) | set(album_artist_ids)) # Default genre id if missing if not genre_ids: genre_ids = t.add_genres("Web") # Add track to db track_id = Lp().tracks.add(item.name, uri, item.duration, item.tracknumber, item.discnumber, "", album_id, item.year, 0, 0, 0, persistent) t.update_track(track_id, artist_ids, genre_ids, item.mtime) t.update_album(album_id, album_artist_ids, genre_ids, item.mtime, None) sql.commit() if persistent != DbPersistent.CHARTS: for genre_id in genre_ids: GLib.idle_add(Lp().scanner.emit, "genre-updated", genre_id, True) for artist_id in new_artist_ids: GLib.idle_add(Lp().scanner.emit, "artist-updated", artist_id, True) return (album_id, track_id)
def __init__(self): """ Init collection scanner """ self.__tag_reader = TagReader()
def __save_track(self, item, persistent, album_artist, genre_ids): """ Save item into collection as track @param item as SearchItem @param persistent as DbPersistent @param album artist as str @param genre ids as [int] @return (album id as int, track id as int) """ t = TagReader() # Get uri from helpers for helper in self.__helpers: uri = helper.get_uri(item) if uri: break # Don't found anything if not uri: return (None, None) # If album exists, is not in charts and we want to save # a charts track to this album, abort! # User already saved this album to collection, # may have removed some tracks, do not add them again! (exists, album_id) = item.album.exists_in_db() if exists: album_genre_ids = Lp().albums.get_genre_ids(album_id) if Type.CHARTS not in album_genre_ids and\ persistent == DbPersistent.CHARTS: return (None, None) # Check if track needs to be updated (exists, track_id) = item.exists_in_db() if exists: if Lp().tracks.get_persistent(track_id) == DbPersistent.NONE\ and persistent == DbPersistent.EXTERNAL: Lp().tracks.set_persistent(track_id, DbPersistent.EXTERNAL) return (None, None) # Do not mark as charts any local/web track track_genre_ids = Lp().tracks.get_genre_ids(track_id) if Type.CHARTS in track_genre_ids: album_id = Lp().tracks.get_album_id(track_id) with SqlCursor(Lp().db) as sql: t.update_track(track_id, [], genre_ids, item.mtime) t.update_album(album_id, [], genre_ids, item.album.mtime, None) sql.commit() return (None, None) with SqlCursor(Lp().db) as sql: # Happen often with Itunes/Spotify if album_artist not in item.artists: item.artists.append(album_artist) artists = "; ".join(item.artists) artist_ids = t.add_artists(artists, album_artist, "") album_artist_ids = t.add_album_artists(album_artist, "") (album_id, new_album) = t.add_album(item.album.name, album_artist_ids, "", False, 0, 0, True) # FIXME: Check this, could move this in add_album() if new_album: Lp().albums.set_synced(album_id, Type.NONE) if persistent == DbPersistent.CHARTS: genre_ids.append(Type.CHARTS) new_artist_ids = [] else: new_artist_ids = list(set(artist_ids) | set(album_artist_ids)) # Default genre id if missing if not genre_ids: genre_ids = t.add_genres("Web") # Add track to db track_id = Lp().tracks.add(item.name, uri, item.duration, item.tracknumber, item.discnumber, "", album_id, item.year, 0, 0, 0, persistent) t.update_track(track_id, artist_ids, genre_ids, item.mtime) t.update_album(album_id, album_artist_ids, genre_ids, item.mtime, None) sql.commit() if persistent != DbPersistent.CHARTS: for genre_id in genre_ids: GLib.idle_add(Lp().scanner.emit, 'genre-updated', genre_id, True) for artist_id in new_artist_ids: GLib.idle_add(Lp().scanner.emit, 'artist-updated', artist_id, True) return (album_id, track_id)