def get_album_art_for_item(self, item, callback): item_id = item.get_id() if item.is_audio(): query = Query.get_album_for_song_id(item_id) else: query = Query.get_album_for_album_id(item_id) options = self.full_options.copy() options.set_count(1) self.search_source.query(query, self.METADATA_THUMBNAIL_KEYS, options, callback)
def create_playlist(self, title): def get_callback(source, param, item, count, data, error): if item: self.emit('playlist-created', item) def cursor_callback(cursor, res, data): try: has_next = cursor.next_finish(res) except GLib.Error as err: logger.warn("Error: %s, %s", err.__class__, err) return playlist_id = cursor.get_integer(0) grilo.get_playlist_with_id(playlist_id, get_callback) def query_callback(conn, res, data): try: cursor = conn.query_finish(res) except GLib.Error as err: logger.warn("Error: %s, %s", err.__class__, err) return if not cursor: return cursor.next_async(None, cursor_callback, data) def update_callback(conn, res, data): playlist_urn = conn.update_blank_finish(res)[0][0]['playlist'] self.tracker.query_async(Query.get_playlist_with_urn(playlist_urn), None, query_callback, None) self.tracker.update_blank_async(Query.create_playlist(title), GLib.PRIORITY_LOW, None, update_callback, None)
def add_to_playlist(self, playlist, items): def get_callback(source, param, item, count, data, error): if item: self.emit('song-added-to-playlist', playlist, item) def query_callback(conn, res, data): cursor = conn.query_finish(res) if not cursor or not cursor.next(): return entry_id = cursor.get_integer(0) grilo.get_playlist_song_with_id(playlist.get_id(), entry_id, get_callback) def update_callback(conn, res, data): entry_urn = conn.update_blank_finish(res)[0][0]['entry'] self.tracker.query_async( Query.get_playlist_song_with_urn(entry_urn), None, query_callback, None) for item in items: uri = item.get_url() if not uri: continue self.tracker.update_blank_async( Query.add_song_to_playlist(playlist.get_id(), uri), GLib.PRIORITY_LOW, None, update_callback, None)
def _on_grilo_ready(self, data=None): """For all static playlists: get ID, if exists; if not, create the playlist and get ID.""" def playlist_id_fetched_cb(cursor, res, playlist): """ Called after the playlist id is fetched """ try: cursor.next_finish(res) except GLib.Error as err: logger.warn("Error: %s, %s", err.__class__, err) return playlist.ID = cursor.get_integer(1) if not playlist.ID: # Create the static playlist self._create_static_playlist(playlist) else: # Update playlist self.update_static_playlist(playlist) def callback(obj, result, playlist): """ Starts retrieving the playlist id """ try: cursor = obj.query_finish(result) except GLib.Error as err: logger.warn("Error: %s, %s", err.__class__, err) return # Search for the playlist ID cursor.next_async(None, playlist_id_fetched_cb, playlist) # Start fetching all the static playlists for playlist in self._static_playlists.get_all(): self.tracker.query_async( Query.get_playlist_with_tag(playlist.TAG_TEXT), None, callback, playlist)
def tag_created_cb(obj, res, playlist): """ Called when the tag is created """ creation_query = Query.create_playlist_with_tag(title, tag_text) # Start creating the playlist itself self.tracker.update_blank_async(creation_query, GLib.PRIORITY_LOW, None, playlist_created_cb, playlist)
def delete_playlist(self, item): def update_callback(conn, res, data): conn.update_finish(res) self.emit('playlist-deleted', item) self.tracker.update_async(Query.delete_playlist(item.get_id()), GLib.PRIORITY_LOW, None, update_callback, None)
def _create_static_playlist(self, playlist): """ Create the tag and the static playlist, and fetch the newly created playlist's songs. """ title = playlist.TITLE tag_text = playlist.TAG_TEXT def playlist_next_async_cb(cursor, res, playlist): """ Called after we finished moving the Tracker cursor, and ready to retrieve the playlist id""" # Update the playlist ID try: cursor.next_finish(res) except GLib.Error as err: logger.warn("Error: %s, %s", err.__class__, err) return playlist.ID = cursor.get_integer(0) # Fetch the playlist contents self.update_static_playlist(playlist) def playlist_queried_cb(obj, res, playlist): """ Called after the playlist is created and the ID is fetched """ try: cursor = obj.query_finish(res) except GLib.Error as err: logger.warn("Error: %s, %s", err.__class__, err) return cursor.next_async(None, playlist_next_async_cb, playlist) def playlist_created_cb(obj, res, playlist): """ Called when the static playlist is created """ data = obj.update_blank_finish(res) playlist_urn = data.get_child_value(0).get_child_value(0).\ get_child_value(0).get_child_value(1).get_string() query = Query.get_playlist_with_urn(playlist_urn) # Start fetching the playlist self.tracker.query_async(query, None, playlist_queried_cb, playlist) def tag_created_cb(obj, res, playlist): """ Called when the tag is created """ creation_query = Query.create_playlist_with_tag(title, tag_text) # Start creating the playlist itself self.tracker.update_blank_async(creation_query, GLib.PRIORITY_LOW, None, playlist_created_cb, playlist) # Start the playlist creation by creating the tag self.tracker.update_blank_async(Query.create_tag(tag_text), GLib.PRIORITY_LOW, None, tag_created_cb, playlist)
def remove_from_playlist(self, playlist, items): def update_callback(conn, res, data): conn.update_finish(res) self.emit('song-removed-from-playlist', playlist, data) for item in items: self.tracker.update_async( Query.remove_song_from_playlist(playlist.get_id(), item.get_id()), GLib.PRIORITY_LOW, None, update_callback, item)
def populate_album_songs(self, album, callback, count=-1): if album.get_source() == 'grl-tracker-source': GLib.idle_add(self.populate_items, Query.album_songs(album.get_id()), 0, callback, count) else: source = self.sources[album.get_source()] length = len(album.songs) for i, track in enumerate(album.songs): callback(source, None, track, length - (i + 1), None) callback(source, None, None, 0, None)
def playlist_created_cb(obj, res, playlist): """ Called when the static playlist is created """ data = obj.update_blank_finish(res) playlist_urn = data.get_child_value(0).get_child_value(0).\ get_child_value(0).get_child_value(1).get_string() query = Query.get_playlist_with_urn(playlist_urn) # Start fetching the playlist self.tracker.query_async(query, None, playlist_queried_cb, playlist)
def __init__(self): Query() self.MostPlayed.QUERY = Query.get_most_played_songs() self.NeverPlayed.QUERY = Query.get_never_played_songs() self.RecentlyPlayed.QUERY = Query.get_recently_played_songs() self.RecentlyAdded.QUERY = Query.get_recently_added_songs() self.Favorites.QUERY = Query.get_favorite_songs()
def _setup_view(self): self._box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) self.player = Player(self) self.selection_toolbar = SelectionToolbar() self.toolbar = Toolbar() self.views = [] self._stack = Gtk.Stack( transition_type=Gtk.StackTransitionType.CROSSFADE, transition_duration=100, visible=True, can_focus=False) # Add the 'background' styleclass so it properly hides the # bottom line of the searchbar self._stack.get_style_context().add_class('background') self._overlay = Gtk.Overlay(child=self._stack) self._overlay.add_overlay(self.toolbar.dropdown) self.set_titlebar(self.toolbar.header_bar) self._box.pack_start(self.toolbar.searchbar, False, False, 0) self._box.pack_start(self._overlay, True, True, 0) self._box.pack_start(self.player.actionbar, False, False, 0) self._box.pack_start(self.selection_toolbar.actionbar, False, False, 0) self.add(self._box) def songs_available_cb(available): if available: self._switch_to_player_view() else: self._switch_to_empty_view() Query() if Query.music_folder: grilo.songs_available(songs_available_cb) else: self._switch_to_empty_view() self.toolbar._search_button.connect('toggled', self._on_search_toggled) self.toolbar.connect('selection-mode-changed', self._on_selection_mode_changed) self.selection_toolbar._add_to_playlist_button.connect( 'clicked', self._on_add_to_playlist_button_clicked) self.selection_toolbar._remove_from_playlist_button.connect( 'clicked', self._on_remove_from_playlist_button_clicked) self.toolbar.set_state(ToolbarState.MAIN) self.toolbar.header_bar.show() self._overlay.show() self.player.actionbar.show_all() self._box.show() self.show()
def _on_content_changed(self, mediaSource, changedMedias, changeType, locationUnknown): try: with self.tracker.handler_block(self.notification_handler): for media in changedMedias: media_id = media.get_id() if changeType == Grl.SourceChangeType.ADDED: # Check that this media is an audio file mime_type = self.tracker.query_sync( Query.is_audio(media_id), [Grl.METADATA_KEY_MIME], self.options)[0].get_mime() if mime_type and mime_type.startswith("audio"): self.changed_media_ids.append(media_id) if changeType == Grl.SourceChangeType.REMOVED: # There is no way to check that removed item is a media # so always do the refresh # todo: remove one single url try: self.changed_media_ids.append(media.get_id()) except Exception as e: logger.warn("Skipping %s", media) if self.changed_media_ids == []: self.pending_changed_medias = [] if self.content_changed_timeout is not None: GLib.source_remove(self.content_changed_timeout) self.content_changed_timeout = None return False self.changed_media_ids = list(set(self.changed_media_ids)) logger.debug("Changed medias: %s", self.changed_media_ids) if len(self.changed_media_ids) >= self.CHANGED_MEDIA_MAX_ITEMS: self.emit_change_signal() elif self.changed_media_ids != []: if self.pending_event_id > 0: GLib.Source.remove(self.pending_event_id) self.pending_event_id = 0 self.pending_event_id = GLib.timeout_add(self.CHANGED_MEDIA_SIGNAL_TIMEOUT, self.emit_change_signal) except Exception as e: logger.warn("Exception in _on_content_changed: %s", e) finally: self.pending_changed_medias = [] if self.content_changed_timeout is not None: GLib.source_remove(self.content_changed_timeout) self.content_changed_timeout = None return False
def callback(cursor, res, final_query): uri = cursor.get_string(0)[0] final_query += Query.add_song_to_playlist(playlist.ID, uri) try: has_next = cursor.next_finish(res) except GLib.Error as err: logger.warn("Error: %s, %s", err.__class__, err) has_next = False # Only perform the update when the cursor reached the end if has_next: cursor.next_async(None, callback, final_query) return self.tracker.update_blank_async(final_query, GLib.PRIORITY_LOW, None, None, None) # tell system we updated the playlist so playlist is reloaded self.emit('playlist-updated', playlist.ID)
def playlists_available(self, callback): """Checks if there are any non-static playlists available Calls a callback function with True or False depending on the availability of playlists. :param callback: Function to call on result """ def cursor_next_cb(conn, res, data): try: has_next = conn.next_finish(res) except GLib.Error as err: logger.warn("Error: %s, %s", err.__class__, err) callback(False) return if has_next: count = conn.get_integer(0) if count > 0: callback(True) return callback(False) def playlists_query_cb(conn, res, data): try: cursor = conn.query_finish(res) except GLib.Error as err: logger.warn("Error: %s, %s", err.__class__, err) callback(False) return cursor.next_async(None, cursor_next_cb, None) # TODO: currently just checks tracker, should work with any # queryable supported Grilo source. self.sparqltracker.query_async( Query.all_non_static_playlists_count(), None, playlists_query_cb, None)
def get_playlist_song_with_id(self, playlist_id, entry_id, callback): options = self.options.copy() query = Query.get_playlist_song_with_id(playlist_id, entry_id) self.tracker.query(query, self.METADATA_KEYS, options, callback, None)
def populate_playlist_songs(self, playlist, callback, count=-1): if self.tracker: GLib.idle_add(self.populate_items, Query.playlist_songs(playlist.get_id()), 0, callback, count)
def populate_playlists(self, offset, callback, count=-1): if self.tracker: GLib.idle_add(self.populate_items, Query.all_playlists(), offset, callback, count)
def clear_playlist(self, playlist): """Starts cleaning the playlist""" query = Query.clear_playlist_with_id(playlist.ID) self.tracker.update_async(query, GLib.PRIORITY_LOW, None, self._static_playlist_cleared_cb, playlist)
def update_callback(conn, res, data): entry_urn = conn.update_blank_finish(res)[0][0]['entry'] self.tracker.query_async( Query.get_playlist_song_with_urn(entry_urn), None, query_callback, None)