def _on_activated(self, widget, track): """ Handle playback if album or pass signal @param widget as TracksWidget @param track as Track """ if self.view_type & (ViewType.ALBUM | ViewType.ARTIST): tracks = [] for child in self.children: if child.track.loved != -1 or track.id == child.track.id: tracks.append(child.track) child.set_state_flags(Gtk.StateFlags.NORMAL, True) # Do not update album list if in party or album already available playback_track = App().player.track_in_playback(track) if playback_track is not None: App().player.load(playback_track) elif not App().player.is_party: album = Album(track.album.id, [], []) album.set_tracks(tracks) if not App().settings.get_value("append-albums"): App().player.clear_albums() App().player.add_album(album) App().player.load(album.get_track(track.id)) else: App().player.load(track) else: emit_signal(self, "activated", track)
def __split_album_row(self, album_row, track_row, direction): """ Split album row at track row with direction @param album_row as AlbumRow @param track_row as TrackRow @param direction as Gtk.DirectionType @return AlbumRow """ height = AlbumRow.get_best_height(album_row) children = album_row.children index = children.index(track_row) if direction == Gtk.DirectionType.DOWN: index += 1 if index + 1 > len(children): return None elif index - 1 < 0: return None rows = album_row.children[:index] split_album = Album(album_row.album.id) split_album.set_tracks([row.track for row in rows]) split_album_row = AlbumRow(split_album, height, self.__view_type) split_album_row.reveal() split_album_row.show() for row in rows: empty = album_row.album.remove_track(row.track) if empty: album_row.destroy() row.destroy() return split_album_row
def save_album_payload_to_db(self, payload, storage_type, notify, cancellable): """ Save album to DB @param payload as {} @param storage_type as StorageType @param notify as bool @param cancellable as Gio.Cancellable @return CollectionItem/None """ lp_album_id = get_lollypop_album_id(payload["name"], payload["artists"]) album_id = App().albums.get_id_for_lp_album_id(lp_album_id) if album_id >= 0: album = Album(album_id) if notify: emit_signal(self, "match-album", album_id, storage_type) return album.collection_item item = self.__save_album(payload, storage_type) album = Album(item.album_id) if notify: self.save_artwork(album, payload["artwork-uri"], cancellable) emit_signal(self, "match-album", album.id, storage_type) return item
def __on_disc_button_press_event(self, button, event, disc): """ Add disc to playback @param button as Gtk.Button @param event as Gdk.ButtonEvent @param disc as Disc """ album = Album(disc.album.id) album.set_tracks(disc.tracks) App().player.play_album(album)
def _append_to_playback(self, action, variant): """ Append track to playback @param Gio.SimpleAction @param GLib.Variant """ album = Album(self.__track.album.id) album.set_tracks([self.__track]) App().player.add_album(album) if App().player.is_playing: App().player.add_album(album) else: App().player.play_album(album)
def _on_playlist_track_added(self, playlists, playlist_id, uri): """ Append track to album list @param playlists as Playlists @param playlist_id as int @param uri as str """ if playlist_id == self.__playlist_id: track = Track(App().tracks.get_id_by_uri(uri)) album = Album(track.album.id) album.set_tracks([track]) self.add_reveal_albums([album]) self.add_value(album)
def _on_collection_updated(self, scanner, item, scan_update): """ Handles changes in collection @param scanner as CollectionScanner @param item as CollectionItem @param scan_update as ScanUpdate """ if scan_update == ScanUpdate.ADDED: wanted = True for genre_id in item.genre_ids: genre_ids = remove_static(self._genre_ids) if genre_ids and genre_id not in genre_ids: wanted = False for artist_id in item.artist_ids: artist_ids = remove_static(self._artist_ids) if artist_ids and artist_id not in artist_ids: wanted = False if wanted: self.add_value(Album(item.album_id)) elif scan_update == ScanUpdate.MODIFIED: for child in self.children: if child.data.id == item.album_id: child.data.reset_tracks() break elif scan_update == ScanUpdate.REMOVED: for child in self.children: if child.data.id == item.album_id: child.destroy() break
def get_today_album(): """ Get today album @return Album/None """ current_date = GLib.DateTime.new_now_local().get_day_of_year() (date, album_id) = (0, None) try: (date, album_id) = load(open(LOLLYPOP_DATA_PATH + "/today.bin", "rb")) if App().albums.get_storage_type(album_id) == StorageType.NONE: date = 0 except Exception as e: Logger.warning("TodayBannerWidget::__get_today_album(): %s", e) try: if date != current_date: storage_type = get_default_storage_type() album_id = App().albums.get_randoms(storage_type, None, False, 1)[0] dump((current_date, album_id), open(LOLLYPOP_DATA_PATH + "/today.bin", "wb")) return Album(album_id) except Exception as e: Logger.error("TodayBannerWidget::__get_today_album(): %s", e) return None
def add_artist_to_playback(artist_ids, genre_ids, add): """ Add artist to current playback @param artist_ids as [int] @param genre_ids as [int] @param add as bool """ try: storage_type = get_default_storage_type() album_ids = App().albums.get_ids(genre_ids, artist_ids, storage_type, False) if App().settings.get_value("play-featured"): album_ids += App().artists.get_featured(genre_ids, artist_ids, storage_type, False) if add: albums = [] for album_id in album_ids: if album_id not in App().player.album_ids: album = Album(album_id, genre_ids, artist_ids, False) albums.append(album) App().player.add_albums(albums) else: App().player.remove_album_by_ids(album_ids) if len(App().player.albums) == 0: App().player.stop() elif App().player.current_track.album.id\ not in App().player.album_ids: App().player.skip_album() except Exception as e: Logger.error("add_artist_to_playback(): %s" % e)
def __add_album_header(self, text, album_id, menu_name): """ Add an header for album to close menu @param text as str @param album_id as int @param menu_name as str """ button = Gtk.ModelButton.new() button.set_hexpand(True) button.connect("clicked", lambda x: emit_signal(self, "hidden", True)) button.show() label = Gtk.Label.new() label.set_markup(text) label.set_ellipsize(Pango.EllipsizeMode.END) label.show() artwork = Gtk.Image.new() close_image = Gtk.Image.new_from_icon_name("pan-up-symbolic", Gtk.IconSize.BUTTON) close_image.show() grid = Gtk.Grid() grid.set_halign(Gtk.Align.START) grid.set_column_spacing(MARGIN) grid.add(artwork) grid.add(label) grid.add(close_image) button.set_image(grid) button.get_style_context().add_class("padding") App().art_helper.set_album_artwork( Album(album_id), ArtSize.SMALL, ArtSize.SMALL, artwork.get_scale_factor(), ArtBehaviour.CACHE | ArtBehaviour.CROP_SQUARE, self.__on_artwork, artwork) self.__boxes[menu_name].add(button)
def __init__(self, genre_id, view_type, header=False): """ Init decade menu @param genre_id as int @param view_type as ViewType @param header as bool """ Gio.Menu.__init__(self) if header: from lollypop.menu_header import RoundedMenuHeader name = App().genres.get_name(genre_id) artwork_name = "genre_%s" % name self.append_item(RoundedMenuHeader(name, artwork_name)) if not view_type & ViewType.BANNER: from lollypop.menu_playback import GenrePlaybackMenu self.append_section(_("Playback"), GenrePlaybackMenu(genre_id)) from lollypop.menu_sync import SyncAlbumsMenu section = Gio.Menu() self.append_section(_("Add to"), section) storage_type = get_default_storage_type() album_ids = App().albums.get_ids([genre_id], [], storage_type, False) album_ids += App().albums.get_compilation_ids([genre_id], storage_type, False) albums = [Album(album_id) for album_id in album_ids] section.append_submenu(_("Devices"), SyncAlbumsMenu(albums))
def _set_artwork(self): """ Set artist artwork """ if self._artwork is None: return RoundedFlowBoxWidget.set_artwork(self) if App().settings.get_value("artist-artwork"): App().art_helper.set_artist_artwork( self.name, self._art_size, self._art_size, self._artwork.get_scale_factor(), ArtBehaviour.ROUNDED | ArtBehaviour.CROP_SQUARE | ArtBehaviour.CACHE, self.__on_artist_artwork) else: album_ids = App().albums.get_ids([], [self._data], StorageType.ALL, True) if album_ids: shuffle(album_ids) App().art_helper.set_album_artwork( Album(album_ids[0]), self._art_size, self._art_size, self._artwork.get_scale_factor(), ArtBehaviour.ROUNDED | ArtBehaviour.CROP_SQUARE | ArtBehaviour.CACHE, self.__on_artist_artwork) else: self.__on_artist_artwork(None)
def __init__(self, track_id=None, album=None): """ Init track @param track_id as int @param album as Album """ Base.__init__(self, App().tracks) self.id = track_id self._uri = None if album is None: from lollypop.objects_album import Album self.__album = Album(self.album_id) self.__album.set_tracks([self], False) else: self.__album = album
def load(): items = [] for year in self._artist_ids: items += App().albums.get_compilation_ids_for_year( year, self.storage_type, True) items += App().albums.get_ids_for_year(year, self.storage_type, True) return [Album(album_id, [Type.YEARS], []) for album_id in items]
def load(): # No skipped albums for this views if self._genre_ids and self._genre_ids[0] in [ Type.POPULARS, Type.LITTLE, Type.RANDOMS, Type.RECENTS ]: skipped = False else: skipped = True album_ids = get_album_ids_for(self._genre_ids, self._artist_ids, self.storage_type, skipped) albums = [] for album_id in album_ids: album = Album(album_id, self._genre_ids, self._artist_ids, True) album.set_storage_type(self.storage_type) albums.append(album) return albums
def __play(self, action, variant): """ Play albums @param Gio.SimpleAction @param GLib.Variant """ album_ids = self.__get_album_ids() albums = [Album(album_id) for album_id in album_ids] App().player.play_albums(albums)
def load(): (genre_id, genre) = App().genres.get_random() GLib.idle_add(self._label.set_text, genre) storage_type = get_default_storage_type() album_ids = App().albums.get_randoms(storage_type, genre_id, False, self.ITEMS) return [Album(album_id) for album_id in album_ids]
def next_album(self): """ Get next album to add @return Album """ storage_type = get_default_storage_type() for album_id in App().albums.get_randoms(storage_type, None, False, 2): if album_id != self.current_track.album.id: return Album(album_id) return None
def load(): if self.__artist_id == Type.COMPILATIONS: album_ids = App().albums.get_compilation_ids( self.__genre_ids, self.storage_type, True) else: album_ids = App().albums.get_ids( self.__genre_ids, [self.__artist_id], self.storage_type, True) if excluded_album_id in album_ids: album_ids.remove(excluded_album_id) return [Album(album_id) for album_id in album_ids]
def set_artwork(self, width, height, callback, behaviour): """ Set artwork @param width as int @param height as int @param callback as function """ scale_factor = self.get_scale_factor() if App().player.current_track.id is not None: if self.__per_track_cover: behaviour |= ArtBehaviour.NO_CACHE album = Album(App().player.current_track.album.id) App().art.clean_album_cache(album, width * scale_factor, height * scale_factor) album.set_tracks([App().player.current_track]) else: album = App().player.current_track.album App().art_helper.set_album_artwork(album, width, height, scale_factor, behaviour, callback) else: self.set_from_surface(None)
def _on_album_match(self, spotify_helper, album_id, storage_type): """ Handles changes in collection @param scanner as CollectionScanner @param album_id as int @param storage_type as StorageType """ count = len(self.children) if count == self.ITEMS: return if self.__storage_type & storage_type: self.add_value(Album(album_id)) self.show()
def __init__(self, object): """ Init edit menu @param object as Album/Track """ Gio.Menu.__init__(self) # Ignore genre_ids/artist_ids if isinstance(object, Album): self.__object = Album(object.id) else: self.__object = Track(object.id) self.__set_save_action() if self.__object.storage_type & StorageType.COLLECTION: self.__set_open_action()
def __cache_albums_artwork(self): """ Cache albums artwork (from queue) @thread safe """ self.__in_albums_download = True try: while self.__albums_queue: album_id = self.__albums_queue.pop() album = App().albums.get_name(album_id) artist_ids = App().albums.get_artist_ids(album_id) is_compilation = artist_ids and\ artist_ids[0] == Type.COMPILATIONS if is_compilation: artist = "" else: artist = ", ".join(App().albums.get_artists(album_id)) found = False for api in self.__album_methods.keys(): result = self.__album_methods[api](artist, album) for uri in result: (status, data) = App().task_helper.load_uri_content_sync(uri, None) if status: found = True App().art.save_album_artwork(Album(album_id), data) break # Found, do not search in another helper if found: break # Not found, save empty artwork if not found: App().art.save_album_artwork(Album(album_id), None) except Exception as e: Logger.error("DownloaderArt::__cache_albums_artwork: %s" % e) self.__in_albums_download = False
def _on_tertiary_press_gesture(self, x, y, event): """ Play artist @param x as int @param y as int @param event as Gdk.Event """ child = self._box.get_child_at_pos(x, y) if child is None or child.artwork is None: return album_ids = App().albums.get_ids([child.data], [], self.storage_type, False) albums = [Album(album_id) for album_id in album_ids] if albums: App().player.play_album_for_albums(albums[0], albums)
def __on_banner_play_all(self, banner, random): """ Play all albums @param banner as AlbumsBannerWidget @param random as bool """ album_ids = App().genres.get_album_ids(True) if not album_ids: return albums = [Album(album_id) for album_id in album_ids] if random: shuffle(albums) App().player.play_album_for_albums(albums[0], albums) else: App().player.play_album_for_albums(albums[0], albums)
def __get_album_from_artists(self, similar_artist_ids): """ Add a new album to playback @param similar_artist_ids as [int] @return Album """ # Get an album storage_type = get_default_storage_type() album_ids = App().albums.get_ids( [], similar_artist_ids, storage_type, False) shuffle(album_ids) while album_ids: album_id = album_ids.pop(0) if album_id not in self.album_ids: return Album(album_id, [], [], False) return None
def _get_child(self, album_id): """ Get an album view widget @param album_id as int @return AlbumView """ if self.destroyed: return None album = Album(album_id, self.__genre_ids, self.__artist_ids) widget = AlbumView(album, self.storage_type, ViewType.ARTIST) widget.show() widget.set_property("valign", Gtk.Align.START) self.__list.add(widget) return widget
def __on_banner_play_all(self, banner, random): """ Play all albums @param banner as AlbumsBannerWidget @param random as bool """ album_ids = App().albums.get_ids([], [], self.storage_type, False, OrderBy.YEAR_ASC) if not album_ids: return albums = [Album(album_id, [], [], False) for album_id in album_ids] if random: shuffle(albums) App().player.play_album_for_albums(albums[0], albums) else: App().player.play_album_for_albums(albums[0], albums)
def set_party_ids(self): """ Set party mode ids """ if not self._is_party: return party_ids = App().settings.get_value("party-ids") storage_type = get_default_storage_type() album_ids = App().albums.get_ids(party_ids, [], storage_type, False) emit_signal(self, "playback-setted", []) self._albums = [] if album_ids: emit_signal(self, "loading-changed", True, Track()) for album_id in album_ids: album = Album(album_id, [], [], False) self._albums.append(album) emit_signal(self, "playback-setted", list(self._albums))
def __init__(self, artist_id, storage_type, view_type, header=False): """ Init artist menu @param artist_id as int @param storage_type as StorageType @param view_type as ViewType @param header as bool """ Gio.Menu.__init__(self) if header: from lollypop.menu_header import ArtistMenuHeader self.append_item(ArtistMenuHeader(artist_id)) if view_type & ViewType.BANNER: show_artist_tracks = App().settings.get_value("show-artist-tracks") action = Gio.SimpleAction.new_stateful( "show-artist-tracks", None, GLib.Variant.new_boolean(show_artist_tracks)) App().add_action(action) action.connect("change-state", self.__on_change_state) self.append(_("Show tracks"), "app.show-artist-tracks") if not show_artist_tracks: action = Gio.SimpleAction.new_stateful( "show-year-below-name", None, GLib.Variant.new_boolean( App().settings.get_value("show-year-below-name"))) App().add_action(action) action.connect("change-state", self.__on_change_state) self.append(_("Show year"), "app.show-year-below-name") action = Gio.SimpleAction.new_stateful( "play-featured", None, GLib.Variant.new_boolean( App().settings.get_value("play-featured"))) App().add_action(action) action.connect("change-state", self.__on_change_state) self.append(_("Play featured"), "app.play-featured") else: from lollypop.menu_playback import ArtistPlaybackMenu self.append_section(_("Playback"), ArtistPlaybackMenu(artist_id, storage_type)) menu = Gio.Menu() self.append_section(_("Artist"), menu) storage_type = get_default_storage_type() album_ids = App().albums.get_ids([], [artist_id], storage_type, False) albums = [Album(album_id) for album_id in album_ids] menu.append_submenu(_("Devices"), SyncAlbumsMenu(albums)) menu.append_submenu(_("Playlists"), PlaylistsMenu(albums))