def do_render(self, ctx, widget, background_area, cell_area, flags): size = ArtSize.MEDIUM * widget.get_scale_factor() surface = Lp().art.get_album_artwork(Album(self.album), size) ctx.translate(cell_area.x, cell_area.y) ctx.new_sub_path() radius = 2 degrees = pi / 180 ctx.arc(size + 2 - radius, radius, radius - 0.5, -90 * degrees, 0 * degrees) ctx.arc(size + 2 - radius, size + 2 - radius, radius - 0.5, 0 * degrees, 90 * degrees) ctx.arc(radius, size + 2 - radius, radius - 0.5, 90 * degrees, 180 * degrees) ctx.arc(radius, radius, radius - 0.5, 180 * degrees, 270 * degrees) ctx.close_path() ctx.set_line_width(1) ctx.fill() ctx.set_source_surface(surface, 1, 1) ctx.paint()
def __append_albums(self, albums): """ Append albums @param albums as [int] """ if albums and not self.__stop: album = Album(albums.pop(0)) synced = Lp().albums.get_synced(album.id) # Do not sync youtube albums if synced != Type.NONE: if album.artist_ids[0] == Type.COMPILATIONS: name = GLib.markup_escape_text(album.name) else: artists = ", ".join(album.artists) name = "<b>%s</b> - %s" % ( GLib.markup_escape_text(artists), GLib.markup_escape_text(album.name)) self.__model.append([synced, name, album.id]) GLib.idle_add(self.__append_albums, albums)
def update_artwork(self, width, height): """ Update artwork @param width as int @param height as int """ same_artwork = self._previous_artwork_id ==\ App().player.current_track.album.id and not self.__per_track_cover if width < 1 or height < 1 or same_artwork: return self._previous_artwork_id = App().player.current_track.album.id scale_factor = self._artwork.get_scale_factor() if App().player.current_track.id == Type.RADIOS: App().art_helper.set_radio_artwork( App().player.current_track.radio_name, width, height, scale_factor, self.__effect, self._on_artwork, ) elif App().player.current_track.id is not None: if self.__per_track_cover: effect = self.__effect | 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: effect = self.__effect album = App().player.current_track.album App().art_helper.set_album_artwork( album, width, height, scale_factor, effect, self._on_artwork, ) if self.__show_tooltip: self._artwork.set_tooltip_text( App().player.current_track.album.name)
def _get_random(self): """ Return a random track and make sure it has never been played """ for album_id in sorted(self._albums, key=lambda *args: random.random()): tracks = Album(album_id, self.context.genre_id).tracks_ids for track in sorted(tracks, key=lambda *args: random.random()): if album_id not in self._already_played_tracks.keys() or\ track not in self._already_played_tracks[album_id]: return track # No new tracks for this album, remove it # If albums not in shuffle history, it's not present # in db anymore (update since shuffle set) if album_id in self._already_played_tracks.keys(): self._already_played_tracks.pop(album_id) self._already_played_albums.append(album_id) self._albums.remove(album_id) return None
def __on_save_artwork_tags(self, source, result, album_id): """ Save image to tags @param source as GObject.Object @param result as Gio.AsyncResult @param album_id as int """ if not source.call_finish(result): return dbus_helper = DBusHelper() for uri in Lp().albums.get_track_uris(album_id, [], []): path = GLib.filename_from_uri(uri)[0] dbus_helper.call( "SetCover", GLib.Variant( "(ss)", (path, "%s/lollypop_cover_tags.jpg" % self._CACHE_PATH)), None, None) self.clean_album_cache(Album(album_id)) GLib.idle_add(self.album_artwork_update, album_id)
def save_album_artwork(self, pixbuf, album_id): """ Save pixbuf for album id @param pixbuf as Gdk.Pixbuf @param album id as int """ try: album = Album(album_id) path_count = Lp().albums.get_path_count(album.path) # Many albums with same path, suffix with artist_album name if path_count > 1: artpath = os.path.join(album.path, "{}_{}.jpg".format( album.artist_name, album.name)) if os.path.exists(os.path.join(album.path, self._favorite)): os.remove(os.path.join(album.path, self._favorite)) else: artpath = os.path.join(album.path, self._favorite) pixbuf.savev(artpath, "jpeg", ["quality"], ["90"]) except Exception as e: print("Art::save_album_artwork(): %s" % e)
def __draw_surface(self, surface, ctx, positions, album_ids): """ Draw surface for first available album @param surface as cairo.Surface @param ctx as Cairo.context @param positions as {} @param album_ids as [int] @thread safe """ # Workaround Gdk not being thread safe def draw_pixbuf(surface, ctx, pixbuf, positions, album_ids): if self.__cancellable.is_cancelled(): return (x, y) = positions.pop(0) x *= self.__cover_size y *= self.__cover_size subsurface = Gdk.cairo_surface_create_from_pixbuf( pixbuf, self._scale_factor, None) ctx.translate(x, y) ctx.set_source_surface(subsurface, 0, 0) ctx.paint() ctx.translate(-x, -y) self.__draw_surface(surface, ctx, positions, album_ids) if self.__cancellable.is_cancelled(): return elif album_ids and len(positions) > 0: album_id = album_ids.pop(0) pixbuf = App().art.get_album_artwork(Album(album_id), self.__cover_size, self.__cover_size, self._scale_factor) if pixbuf is None: GLib.idle_add(self.__draw_surface, surface, ctx, positions, album_ids) else: GLib.idle_add(draw_pixbuf, surface, ctx, pixbuf, positions, album_ids) else: GLib.idle_add(self.__set_surface, surface)
def _on_album_updated(self, scanner, album_id, added): """ Handles changes in collection @param scanner as CollectionScanner @param album_id as int @param added as bool """ if self._view_type & (ViewType.SEARCH | ViewType.DND): return if added: album_ids = App().window.container.get_view_album_ids( self.__genre_ids, self.__artist_ids) if album_id not in album_ids: return index = album_ids.index(album_id) self.insert_album(Album(album_id), False, index) else: for child in self._box.get_children(): if child.album.id == album_id: child.destroy()
def del_tracks(self, track_ids): """ Delete tracks from db @param track_ids as [int] """ with SqlCursor(self) as sql: for track_id in track_ids: album_id = Lp().tracks.get_album_id(track_id) art_file = Lp().art.get_album_cache_name(Album(album_id)) genre_ids = Lp().tracks.get_genre_ids(track_id) album_artist_ids = Lp().albums.get_artist_ids(album_id) artist_ids = Lp().tracks.get_artist_ids(track_id) Lp().tracks.remove(track_id) Lp().tracks.clean(track_id) if Lp().albums.clean(album_id): Lp().art.clean_store(art_file) for artist_id in album_artist_ids + artist_ids: Lp().artists.clean(artist_id) for genre_id in genre_ids: Lp().genres.clean(genre_id) sql.commit()
def __init__(self, object): """ Init edit menu @param object as Album/Track """ # Ignore genre_ids/artist_ids if isinstance(object, Album): obj = Album(object.id) else: obj = Track(object.id) BaseMenu.__init__(self, obj) if self._object.is_web: self.__set_remove_action() else: favorite = Lp().settings.get_value('tag-editor').get_string() for editor in [favorite] + TAG_EDITORS: if GLib.find_program_in_path(editor) is not None: self.__tag_editor = editor self.__set_edit_actions() break
def __init__(self, artist_id, album_id): """ Init Popover @param artist id as int @param album id as int """ Gtk.Popover.__init__(self) self._album = Album(album_id) self._start = 0 self._orig_pixbufs = {} self._stack = Gtk.Stack() self._stack.show() builder = Gtk.Builder() builder.add_from_resource('/org/gnome/Lollypop/CoversPopover.ui') widget = builder.get_object('widget') widget.add(self._stack) self._view = Gtk.FlowBox() self._view.set_selection_mode(Gtk.SelectionMode.NONE) self._view.connect('child-activated', self._on_activate) self._view.set_max_children_per_line(100) self._view.set_property('row-spacing', 10) self._view.show() self._label = builder.get_object('label') self._label.set_text(_("Please wait...")) builder.get_object('viewport').add(self._view) self._scrolled = builder.get_object('scrolled') spinner = builder.get_object('spinner') self._not_found = builder.get_object('notfound') self._stack.add(spinner) self._stack.add(self._not_found) self._stack.add(self._scrolled) self._stack.set_visible_child(spinner) self.add(widget)
def _set_artwork(self): """ Set artist artwork """ def set_icon_name(): icon_name = get_icon_name(self._data) or "avatar-default-symbolic" self._artwork.set_from_icon_name(icon_name, Gtk.IconSize.DIALOG) self.emit("populated") self._artwork.get_style_context().add_class("artwork-icon-large") if self._artwork is None: return RoundedFlowBoxWidget.set_artwork(self) if self._data < 0: set_icon_name() elif 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], []) 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: set_icon_name()
def _restore_state(self): """ Restore list state """ def select_list_two(selection_list, ids): # For some reasons, we need to delay this # If list two is short, we may receive list two selected-item # signal before list one GLib.idle_add(self._list_two.select_ids, ids) self._list_two.disconnect_by_func(select_list_two) try: state_one_ids = App().settings.get_value("state-one-ids") state_two_ids = App().settings.get_value("state-two-ids") state_three_ids = App().settings.get_value("state-three-ids") # Empty because we do not have any genre set if not state_one_ids: state_one_ids = state_two_ids state_two_ids = state_three_ids if state_one_ids: self._list_one.select_ids(state_one_ids) # If list two not available, directly show view sidebar_content = App().settings.get_enum("sidebar-content") if state_two_ids and (App().window.is_adaptive or sidebar_content == SidebarContent.DEFAULT): self.show_view(state_one_ids, state_two_ids) # Wait for list to be populated and select item elif state_two_ids and not state_three_ids: self._list_two.connect("populated", select_list_two, state_two_ids) if state_three_ids: album = Album(state_three_ids[0], state_one_ids, state_two_ids) self.show_view([Type.ALBUM], album) elif not App().window.is_adaptive: self._list_one.select_first() except Exception as e: Logger.error("ListsContainer::_restore_state(): %s", e)
def save_album_artwork(self, data, album_id): """ Save data for album id @param data as bytes @param album id as int """ try: artpath = None save_to_tags = Lp().settings.get_value('save-to-tags') and\ which("kid3-cli") is not None album = Album(album_id) path_count = Lp().albums.get_path_count(album.path) filename = self.get_album_cache_name(album) + ".jpg" if save_to_tags: t = Thread(target=self.__save_artwork_tags, args=(data, album)) t.daemon = True t.start() if album.path == "" or is_readonly(album.path): artpath = os.path.join(self._STORE_PATH, filename) # Many albums with same path, suffix with artist_album name elif path_count > 1: artpath = os.path.join(album.path, filename) if os.path.exists(os.path.join(album.path, self.__favorite)): os.remove(os.path.join(album.path, self.__favorite)) else: artpath = os.path.join(album.path, self.__favorite) # Update cover file if exists event if we have written to tags if not save_to_tags or os.path.exists(artpath): stream = Gio.MemoryInputStream.new_from_data(data, None) pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale( stream, ArtSize.MONSTER, ArtSize.MONSTER, True, None) pixbuf.savev(artpath, "jpeg", ["quality"], ["90"]) del pixbuf self.clean_album_cache(album) GLib.idle_add(self.album_artwork_update, album.id) except Exception as e: print("Art::save_album_artwork(): %s" % e)
def __create_albums_from_album_payload(self, payload, album_ids, cancellable): """ Get albums from an album payload @param payload as {} @param album_ids as [int] @param cancellable as Gio.Cancellable """ # Populate tracks for album_item in payload: if cancellable.is_cancelled(): return album_id = App().db.exists_in_db( album_item["name"], [artist["name"] for artist in album_item["artists"]], None) if album_id is not None: if album_id not in album_ids: album = Album(album_id) if album.tracks: track = album.tracks[0] if track.is_web: self.__create_album(album_id, None, cancellable) album_ids.append(album_id) continue uri = "https://api.spotify.com/v1/albums/%s" % album_item["id"] token = "Bearer %s" % self.__token helper = TaskHelper() helper.add_header("Authorization", token) (status, data) = helper.load_uri_content_sync(uri, cancellable) if status: decode = json.loads(data.decode("utf-8")) track_payload = decode["tracks"]["items"] for item in track_payload: item["album"] = album_item self.__create_albums_from_tracks_payload(track_payload, album_ids, cancellable)
def __remove_object(self, action, variant): """ Remove album @param SimpleAction @param GVariant """ artist_ids = [] if self._is_album: album = Album(self._object_id) for track_id in album.track_ids: artist_ids += Lp().tracks.get_artist_ids(track_id) uri = Lp().tracks.get_uri(track_id) Lp().playlists.remove(uri) Lp().tracks.remove(track_id) Lp().tracks.clean(track_id) art_file = Lp().art.get_album_cache_name(album) Lp().art.clean_store(art_file) else: track = Track(self._object_id) album = track.album artist_ids = Lp().tracks.get_artist_ids(track.id) uri = Lp().tracks.get_uri(track.id) Lp().playlists.remove(uri) Lp().tracks.remove(track.id) Lp().tracks.clean(track.id) artist_ids += album.artist_ids genre_ids = Lp().albums.get_genre_ids(album.id) deleted = Lp().albums.clean(album.id) for artist_id in list(set(artist_ids)): Lp().artists.clean(artist_id) # Do not check clean return GLib.idle_add(Lp().scanner.emit, 'artist-updated', artist_id, False) for genre_id in genre_ids: Lp().genres.clean(genre_id) GLib.idle_add(Lp().scanner.emit, 'genre-updated', genre_id, False) with SqlCursor(Lp().db) as sql: sql.commit() GLib.idle_add(Lp().scanner.emit, 'album-updated', album.id, deleted)
def __on_insert_track(self, row, new_track_id, down): """ Insert a new row at position @param row as PlaylistRow @param new_track_id as int @param down as bool """ new_track = Track(new_track_id) children = self._box.get_children() position = children.index(row) lenght = len(children) if down: position += 1 # Append track to current/next album if position < lenght and\ children[position].album.id == new_track.album.id: new_track.set_album(children[position].album) children[position].prepend_rows([new_track]) children[position].album.insert_track(new_track, 0) # Append track to previous/current album elif position - 1 < lenght and\ children[position - 1].album.id == new_track.album.id: new_track.set_album(children[position - 1].album) children[position - 1].append_rows([new_track]) children[position - 1].album.insert_track(new_track) # Add a new album else: album = Album(new_track.album.id) album.set_tracks([new_track]) new_row = self.__row_for_album(album) new_row.populate() new_row.show() self._box.insert(new_row, position) App().player.add_album(album, position) if row.previous_row is not None and\ row.previous_row.album.id ==\ App().player.current_track.album.id: App().player.set_next() App().player.set_prev()
def __init__(self, object): """ Init edit menu @param object as Album/Track """ # Ignore genre_ids/artist_ids if isinstance(object, Album): obj = Album(object.id) else: obj = Track(object.id) BaseMenu.__init__(self, obj) if self._object.is_web: self.__set_remove_action() else: # Check portal for tag editor try: Gio.bus_get(Gio.BusType.SESSION, None, self.__on_get_bus, "CanLaunchTagEditor", None, self.__on_can_launch_tag_editor) except Exception as e: print("EditMenu::__init__():", e)
def __init__(self, album_id, genre_ids=[]): """ Init widget """ self._album = Album(album_id, genre_ids) self._filter_ids = [] self._selected = None self._loading = Loading.NONE self._cover = None self._widget = None self._play_all_button = None self._artwork_button = None self._action_button = None self._show_overlay = False self._lock_overlay = False self._timeout_id = None self._overlay_orientation = Gtk.Orientation.HORIZONTAL self._squared_class = "squared-icon" self._rounded_class = "rounded-icon" self._scan_signal = Lp().scanner.connect('album-updated', self.__on_album_updated) self.connect('destroy', self.__on_destroy)
def get_album_art_path(self, album_id, sql=None): """ Look for covers in dir: - favorite from settings first - Artist_Album.jpg then - Any any supported image otherwise @param album id as int @return cover file path as string """ if album_id is None: return None album = Album(album_id) paths = [ os.path.join(album.path, self._favorite), # Used when having muliple albums in same folder os.path.join(album.path, "{}_{}.jpg".format(album.artist_name, album.name)) ] for path in paths: if os.path.exists(path): return path return self.get_locally_available_cover(album)
def _restore_state(self): """ Restore state """ self._stack.destroy_children() state_one_ids = App().settings.get_value("state-one-ids") state_two_ids = App().settings.get_value("state-two-ids") state_three_ids = App().settings.get_value("state-three-ids") sidebar_content = App().settings.get_enum("sidebar-content") if state_one_ids and state_two_ids and state_three_ids: self.show_view(state_one_ids, None, False) album = Album(state_three_ids[0], state_one_ids, state_two_ids) self.show_view([Type.ALBUM], album) elif state_one_ids and state_two_ids: if sidebar_content == SidebarContent.GENRES: self.show_view([Type.GENRES], None, False) self.show_view([Type.GENRES], state_one_ids[0], False) self.show_view(state_two_ids) else: self.show_view(state_one_ids, None, False) self.show_view(state_one_ids, state_two_ids) elif state_one_ids: self.show_view(state_one_ids)
def _on_album_activated(self, flowbox, child): """ Show Context view for activated album @param flowbox as Gtk.Flowbox @param child as Gtk.FlowboxChild """ album_widget = child.get_child() if self._press_rect is None: if self._context_album_id == album_widget.get_id(): self._context_album_id = None self._context.hide() self._context_widget.destroy() self._context_widget = None else: if Lp().settings.get_value('auto-play'): album = Album(album_widget.get_id()) track = Track(album.tracks_ids[0]) Lp().player.load(track) Lp().player.set_albums(track.id, None, self._genre_id) else: self._context_album_id = album_widget.get_id() self._populate_context(self._context_album_id) self._context.show() else: if self._context_album_id is not None: self._context_album_id = None self._context.hide() self._context_widget.destroy() self._context_widget = None popover = AlbumPopoverWidget(album_widget.get_id(), self._genre_id) popover.set_relative_to(album_widget) popover.set_pointing_to(self._press_rect) self._context_widget = popover.get_widget() popover.connect('destroy', self._on_popover_destroyed) popover.show()
def __on_save_artwork_tags(self, source, result, album_id): """ Save image to tags @param source as GObject.Object @param result as Gio.AsyncResult @param album_id as int """ try: can_set_cover = source.call_finish(result) except: can_set_cover = False if can_set_cover: dbus_helper = DBusHelper() for uri in Lp().albums.get_track_uris(album_id, [], []): path = GLib.filename_from_uri(uri)[0] dbus_helper.call( "SetCover", GLib.Variant("(ss)", (path, "%s/lollypop_cover_tags.jpg" % self._CACHE_PATH)), None, None) self.clean_album_cache(Album(album_id)) GLib.idle_add(self.album_artwork_update, album_id) else: # Lollypop-portal or kid3-cli removed? Lp().settings.set_value("save-to-tags", GLib.Variant("b", False))
def play_albums(self, album_id, filter1_ids, filter2_ids): """ Play albums related to track/genre_ids/artist_ids @param album_id as int/None @param filter1_ids as [int] @param filter2_ids as [int] """ self._albums = [] album_ids = [] if album_id is None else [album_id] self.reset_history() # We are not playing a user playlist anymore self._playlist_tracks = [] self._playlist_ids = [] # We are in all artists if (filter1_ids and filter1_ids[0] == Type.ALL) or\ (filter2_ids and filter2_ids[0] == Type.ALL): # Genres: all, Artists: compilations if filter2_ids and filter2_ids[0] == Type.COMPILATIONS: album_ids += App().albums.get_compilation_ids([], True) # Genres: all, Artists: ids elif filter2_ids and filter2_ids[0] != Type.ALL: album_ids += App().albums.get_ids(filter2_ids, [], True) # Genres: all, Artists: all else: if App().settings.get_value("show-compilations-in-album-view"): album_ids += App().albums.get_compilation_ids([], True) album_ids += App().albums.get_ids([], [], True) # We are in populars view, add popular albums elif filter1_ids and filter1_ids[0] == Type.POPULARS: album_ids += App().albums.get_populars() # We are in loved view, add loved albums elif filter1_ids and filter1_ids[0] == Type.LOVED: album_ids += App().albums.get_loved_albums() # We are in recents view, add recent albums elif filter1_ids and filter1_ids[0] == Type.RECENTS: album_ids += App().albums.get_recents() # We are in randoms view, add random albums elif filter1_ids and filter1_ids[0] == Type.RANDOMS: album_ids += App().albums.get_cached_randoms() # We are in compilation view without genre elif filter1_ids and filter1_ids[0] == Type.COMPILATIONS: album_ids += App().albums.get_compilation_ids([]) # We are in years view elif filter1_ids and filter1_ids[0] == Type.YEARS: album_ids += [] for year in filter2_ids: album_ids += App().albums.get_albums_for_year(year) album_ids += App().albums.get_compilations_for_year(year) # Add albums for artists/genres else: # If we are not in compilation view and show compilation is on, # add compilations if filter2_ids and filter2_ids[0] == Type.COMPILATIONS: album_ids += App().albums.get_compilation_ids( filter1_ids, True) elif filter2_ids: # In artist view, play all albums if ignoring return [] album_ids += App().albums.get_ids( filter2_ids, filter1_ids, True) if not album_ids: album_ids += App().albums.get_ids( filter2_ids, filter1_ids, False) elif App().settings.get_value( "show-compilations-in-album-view"): album_ids += App().albums.get_compilation_ids( filter1_ids, True) album_ids += App().albums.get_ids([], filter1_ids, True) else: album_ids += App().albums.get_ids([], filter1_ids, True) shuffle_setting = App().settings.get_enum("shuffle") if not album_ids: return elif shuffle_setting == Shuffle.ALBUMS: if album_id is None: shuffle(album_ids) album = Album(album_ids.pop(0), filter1_ids, filter2_ids, True) else: album = Album(album_ids.pop(0), filter1_ids, filter2_ids, True) shuffle(album_ids) else: album = Album(album_ids.pop(0), filter1_ids, filter2_ids, True) # Select a track and start playback track = None self._albums = [album] if shuffle_setting == Shuffle.TRACKS: track = choice(album.tracks) elif shuffle_setting == Shuffle.ALBUMS: if self._albums and self._albums[0].tracks: track = self._albums[0].tracks[0] elif album.tracks: track = album.tracks[0] # Create album objects for _album_id in album_ids: if _album_id == album_id: continue album = Album(_album_id, filter1_ids, filter2_ids, True) self._albums.append(album) if track is not None: self.load(track) self.emit("playlist-changed")
def play_albums(self, album_id, filter1_ids, filter2_ids): """ Play albums related to track/genre_ids/artist_ids @param album_id as int/None @param filter1_ids as [int] @param filter2_ids as [int] """ self._albums = [] album_ids = [] self.reset_history() # We are not playing a user playlist anymore self._playlist_tracks = [] self._playlist_ids = [] # We are in all artists if (filter1_ids and filter1_ids[0] == Type.ALL) or\ (filter2_ids and filter2_ids[0] == Type.ALL): # Genres: all, Artists: compilations if filter2_ids and filter2_ids[0] == Type.COMPILATIONS: album_ids += App().albums.get_compilation_ids([], True) # Genres: all, Artists: ids elif filter2_ids and filter2_ids[0] != Type.ALL: album_ids += App().albums.get_ids(filter2_ids, [], True) # Genres: all, Artists: all else: if App().settings.get_value("show-compilations-in-album-view"): album_ids += App().albums.get_compilation_ids([], True) album_ids += App().albums.get_ids([], [], True) # We are in populars view, add popular albums elif filter1_ids and filter1_ids[0] == Type.POPULARS: album_ids += App().albums.get_populars() # We are in loved view, add loved albums elif filter1_ids and filter1_ids[0] == Type.LOVED: album_ids += App().albums.get_loved_albums() # We are in recents view, add recent albums elif filter1_ids and filter1_ids[0] == Type.RECENTS: album_ids += App().albums.get_recents() # We are in randoms view, add random albums elif filter1_ids and filter1_ids[0] == Type.RANDOMS: album_ids += App().albums.get_randoms() # We are in compilation view without genre elif filter1_ids and filter1_ids[0] == Type.COMPILATIONS: album_ids += App().albums.get_compilation_ids([]) # We are in years view elif filter1_ids and filter1_ids[0] == Type.YEARS: album_ids += [] for year in filter2_ids: album_ids += App().albums.get_albums_for_year(year) album_ids += App().albums.get_compilations_for_year(year) # Reset filter2_ids as contains unwanted filter for later # Album constructor filter2_ids = [] # Add albums for artists/genres else: # If we are not in compilation view and show compilation is on, # add compilations if filter2_ids and filter2_ids[0] == Type.COMPILATIONS: album_ids += App().albums.get_compilation_ids( filter1_ids, True) elif filter2_ids: # In artist view, play all albums if ignoring return [] if App().settings.get_value("show-performers"): album_ids += App().tracks.get_album_ids(filter2_ids, filter1_ids, True) else: album_ids += App().albums.get_ids(filter2_ids, filter1_ids, True) if not album_ids: if App().settings.get_value("show-performers"): album_ids += App().tracks.get_album_ids(filter2_ids, filter1_ids, False) else: album_ids += App().albums.get_ids(filter2_ids, filter1_ids, False) elif App().settings.get_value( "show-compilations-in-album-view"): album_ids += App().albums.get_compilation_ids( filter1_ids, True) album_ids += App().albums.get_ids([], filter1_ids, True) else: album_ids += App().albums.get_ids([], filter1_ids, True) if not album_ids: return # Create album objects albums = [] album = None for _album_id in album_ids: _album = Album(_album_id, filter1_ids, filter2_ids, True) if album_id == _album_id: album = _album albums.append(_album) shuffle_setting = App().settings.get_enum("shuffle") if shuffle_setting == Shuffle.ALBUMS: self.__play_shuffle_albums(album, albums) elif shuffle_setting == Shuffle.TRACKS: self.__play_shuffle_tracks(album, albums) else: self.__play_albums(album, albums) self.emit("playlist-changed")
def load(): album_ids = App().albums.get_synced_ids(0) album_ids += App().albums.get_synced_ids(index) return [Album(album_id) for album_id in album_ids]
def load(): album_ids = self.get_view_album_ids(genre_ids, artist_ids) return [ Album(album_id, genre_ids, artist_ids) for album_id in album_ids ]
def load(): items = [] for year in years: items += App().albums.get_compilations_for_year(year) items += App().albums.get_albums_for_year(year) return [Album(album_id, [Type.YEARS], []) for album_id in items]
def __on_command_line(self, app, app_cmd_line): """ Handle command line @param app as Gio.Application @param options as Gio.ApplicationCommandLine """ self.__externals_count = 0 args = app_cmd_line.get_arguments() options = app_cmd_line.get_options_dict() if options.contains("debug"): self.debug = True if options.contains("set-rating"): value = options.lookup_value("set-rating").get_string() try: value = min(max(0, int(value)), 5) if self.player.current_track.id is not None: self.player.current_track.set_rate(value) except Exception as e: print(e) pass elif options.contains("play-pause"): self.player.play_pause() elif options.contains("play-ids"): try: value = options.lookup_value("play-ids").get_string() ids = value.split(";") track_ids = [] for id in ids: if id[0:2] == "a:": album = Album(int(id[2:])) track_ids += album.track_ids else: track_ids.append(int(id[2:])) track = Track(track_ids[0]) self.player.load(track) self.player.populate_user_playlist_by_tracks( track_ids, [Type.SEARCH]) except Exception as e: print(e) pass elif options.contains("next"): self.player.next() elif options.contains("prev"): self.player.prev() elif options.contains("emulate-phone"): self.window.add_fake_phone() elif len(args) > 1: self.player.clear_externals() for uri in args[1:]: try: uri = GLib.filename_to_uri(uri) except: pass parser = TotemPlParser.Parser.new() parser.connect("entry-parsed", self.__on_entry_parsed) parser.parse_async(uri, True, None, None) elif self.window is not None and self.window.is_visible(): self.window.present_with_time(Gtk.get_current_event_time()) elif self.window is not None: # self.window.setup_window() # self.window.present() # Horrible HACK: https://bugzilla.gnome.org/show_bug.cgi?id=774130 self.window.save_view_state() self.window.destroy() self.window = Window() # If not GNOME/Unity add menu to toolbar if not is_gnome() and not is_unity(): menu = self.__setup_app_menu() self.window.setup_menu(menu) self.window.connect("delete-event", self.__hide_on_delete) self.window.init_list_one() self.window.show() self.player.emit("status-changed") self.player.emit("current-changed") return 0
def __on_command_line(self, app, app_cmd_line): """ Handle command line @param app as Gio.Application @param options as Gio.ApplicationCommandLine """ try: args = app_cmd_line.get_arguments() options = app_cmd_line.get_options_dict() if options.contains("debug"): self.debug = True # We are forced to enable scrobblers here if we want full debug if not self.scrobblers: if LastFM is not None: self.scrobblers = [LastFM("lastfm"), LastFM("librefm")] self.load_listenbrainz() if options.contains("set-rating"): value = options.lookup_value("set-rating").get_string() try: value = min(max(0, int(value)), 5) if self.player.current_track.id is not None: self.player.current_track.set_rate(value) except Exception as e: Logger.error("Application::__on_command_line(): %s", e) pass elif options.contains("play-pause"): self.player.play_pause() elif options.contains("stop"): self.player.stop() ## anhsirk0 edits elif options.contains("set-next"): try: track_id = int(args[1]) try: self.player.append_to_queue(track_id, notify=True) except: pass except: pass ## anhsirk0 edits ends elif options.contains("play-ids"): try: value = options.lookup_value("play-ids").get_string() ids = value.split(";") tracks = [] for id in ids: if id[0:2] == "a:": album = Album(int(id[2:])) tracks += album.tracks else: tracks.append(Track(int(id[2:]))) self.player.load(tracks[0]) self.player.populate_playlist_by_tracks( tracks, [Type.SEARCH]) except Exception as e: Logger.error("Application::__on_command_line(): %s", e) pass elif options.contains("next"): self.player.next() elif options.contains("prev"): self.player.prev() elif options.contains("emulate-phone"): self.__window.toolbar.end.devices_popover.add_fake_phone() elif len(args) > 1: uris = [] pls = [] for uri in args[1:]: try: uri = GLib.filename_to_uri(uri) except: pass f = Gio.File.new_for_uri(uri) if not f.query_exists(): uri = GLib.filename_to_uri( "%s/%s" % (GLib.get_current_dir(), uri)) f = Gio.File.new_for_uri(uri) if is_audio(f): uris.append(uri) elif is_pls(f): pls.append(uri) else: info = f.query_info(Gio.FILE_ATTRIBUTE_STANDARD_TYPE, Gio.FileQueryInfoFlags.NONE, None) if info.get_file_type() == Gio.FileType.DIRECTORY: uris.append(uri) if pls: from gi.repository import TotemPlParser parser = TotemPlParser.Parser.new() parser.connect("entry-parsed", self.__on_entry_parsed, uris) parser.parse_async(uri, True, None, self.__on_parse_finished, uris) else: self.__on_parse_finished(None, None, uris) elif self.__window is not None: if not self.__window.is_visible(): self.__window.present() self.player.emit("status-changed") self.player.emit("current-changed") Gdk.notify_startup_complete() except Exception as e: Logger.error("Application::__on_command_line(): %s", e) return 0