Пример #1
0
 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()
Пример #2
0
    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)
        count = 0
        cursor = None

        Query()
        if Query.music_folder:
            try:
                cursor = tracker.query(Query.all_songs_count(), None)
                if cursor is not None and cursor.next(None):
                    count = cursor.get_integer(0)
            except Exception as e:
                logger.error("Tracker query crashed: %s", e)
                count = 0

            if count > 0:
                self._switch_to_player_view()
            # To revert to the No Music View when no songs are found
            else:
                if self.toolbar._selectionMode is False:
                    self._switch_to_empty_view()
        else:
            # Revert to No Music view if XDG dirs are not set
            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()
Пример #3
0
 def toggle_favorite(self, song_item):
     # TODO: change "bool(song_item.get_lyrics())" --> song_item.get_favourite() once query works properly
     # TODO: when .set/get_favourite work, set_favourite outside loop: item.set_favourite(!item.get_favourite())
     if bool(song_item.get_lyrics()):  # is favorite
         self.sparqltracker.update(Query.remove_favorite(song_item.get_url()), GLib.PRIORITY_DEFAULT, None)
         song_item.set_lyrics("")
     else:  # not favorite
         self.sparqltracker.update(Query.add_favorite(song_item.get_url()), GLib.PRIORITY_DEFAULT, None)
         song_item.set_lyrics("i'm truthy")
Пример #4
0
 def toggle_favorite(self, song_item):
     # TODO: change "bool(song_item.get_lyrics())" --> song_item.get_favourite() once query works properly
     # TODO: when .set/get_favourite work, set_favourite outside loop: item.set_favourite(!item.get_favourite())
     if bool(song_item.get_lyrics()): # is favorite
         self.sparqltracker.update(Query.remove_favorite(song_item.get_url()), GLib.PRIORITY_DEFAULT, None)
         song_item.set_lyrics("")
     else: # not favorite
         self.sparqltracker.update(Query.add_favorite(song_item.get_url()), GLib.PRIORITY_DEFAULT, None)
         song_item.set_lyrics("i'm truthy")
Пример #5
0
    def get_album_art_for_item(self, item, callback, data=None):
        item_id = item.get_id()

        query = None
        if isinstance(item, Grl.MediaAudio):
            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, data)
Пример #6
0
    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)
Пример #7
0
    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)
Пример #8
0
    def create_playlist_and_return_id(self, title, tag_text):
        self.tracker.update_blank(Query.create_tag(tag_text),
                                  GLib.PRIORITY_LOW, None)

        data = self.tracker.update_blank(
            Query.create_playlist_with_tag(title, tag_text), GLib.PRIORITY_LOW,
            None)
        playlist_urn = data.get_child_value(0).get_child_value(0).\
            get_child_value(0).get_child_value(1).get_string()

        cursor = self.tracker.query(Query.get_playlist_with_urn(playlist_urn),
                                    None)
        if not cursor or not cursor.next():
            return
        return cursor.get_integer(0)
Пример #9
0
    def create_playlist_and_return_id(self, title, tag_text):
        self.tracker.update_blank(Query.create_tag(tag_text), GLib.PRIORITY_DEFAULT, None)

        data = self.tracker.update_blank(
            Query.create_playlist_with_tag(title, tag_text), GLib.PRIORITY_DEFAULT,
            None)
        playlist_urn = data.get_child_value(0).get_child_value(0).\
            get_child_value(0).get_child_value(1).get_string()

        cursor = self.tracker.query(
            Query.get_playlist_with_urn(playlist_urn),
            None)
        if not cursor or not cursor.next():
            return
        return cursor.get_integer(0)
Пример #10
0
        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)
Пример #11
0
    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)
Пример #12
0
    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)
        count = 0
        cursor = None

        Query()
        if Query.music_folder:
            try:
                cursor = tracker.query(Query.all_songs_count(), None)
                if cursor is not None and cursor.next(None):
                    count = cursor.get_integer(0)
            except Exception as e:
                logger.error("Tracker query crashed: %s", e)
                count = 0

            if count > 0:
                self._switch_to_player_view()
            # To revert to the No Music View when no songs are found
            else:
                if self.toolbar._selectionMode is False:
                    self._switch_to_empty_view()
        else:
            # Revert to No Music view if XDG dirs are not set
            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()
Пример #13
0
    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)
Пример #14
0
    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_DEFAULT,
                None, update_callback, None
            )
Пример #15
0
    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)
Пример #16
0
        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)
Пример #17
0
    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)
Пример #18
0
    def populate_playlists(self, offset, callback, count=-1):
        """Asynchronously get playlists (user and smart ones)

        :param int offset: start index
        :param function callback: callback function
        :param int count: limit number of results
        """
        self.populate_items(Query.all_playlists(), offset, callback, count)
Пример #19
0
    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)
Пример #20
0
 def populate_album_songs(self, album, callback, count=-1):
     if album.get_source() == 'grl-tracker-source':
         self.populate_items(Query.album_songs(album.get_id()), 0, callback, count)
     else:
         source = self.sources[album.get_source()]
         length = len(album.tracks)
         for i, track in enumerate(album.tracks):
             callback(source, None, track, length - (i + 1), None)
         callback(source, None, None, 0, None)
Пример #21
0
    def populate_user_playlists(self, offset, callback, count=-1):
        """Asynchronously get user playlists

        :param int offset: start index
        :param function callback: callback function
        :param int count: limit number of results
        """
        self.populate_items(
            Query.all_user_playlists(), offset, callback, count)
Пример #22
0
    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_DEFAULT,
            None, update_callback, None
        )
Пример #23
0
 def populate_album_songs(self, album, callback, count=-1):
     if album.get_source() == 'grl-tracker-source':
         self.populate_items(Query.album_songs(album.get_id()), 0, callback, count)
     else:
         source = self.sources[album.get_source()]
         length = len(album.tracks)
         for i, track in enumerate(album.tracks):
             callback(source, None, track, length - (i + 1), None)
         callback(source, None, None, 0, None)
Пример #24
0
    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)
Пример #25
0
    def populate_user_playlists(self, offset, callback, count=-1):
        """Asynchronously get user playlists

        :param int offset: start index
        :param function callback: callback function
        :param int count: limit number of results
        """
        if self.tracker:
            GLib.idle_add(self.populate_items, Query.all_user_playlists(),
                          offset, callback, count)
Пример #26
0
    def populate_playlists(self, offset, callback, count=-1, data=None):
        """Asynchronously get playlists (user and smart ones)

        :param int offset: start index
        :param function callback: callback function
        :param int count: limit number of results
        :param object data: user data
        """
        self.populate_items(
            Query.all_playlists(), offset, callback, count, data)
Пример #27
0
        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)
Пример #28
0
    def get_media_from_uri(self, uri, callback):
        options = self.options.copy()
        query = Query.get_song_with_url(uri)

        def _callback(source, param, item, count, data, error):
            if not error:
                callback(source, param, item)
                return

        self.tracker.query(query, self.METADATA_KEYS, options, _callback, None)
Пример #29
0
    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)
Пример #30
0
        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)
Пример #31
0
 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()
Пример #32
0
    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_DEFAULT,
                None, update_callback, item
            )
Пример #33
0
    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()
Пример #34
0
    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
Пример #35
0
    def reorder_playlist(self, playlist, items, new_positions):
        """Change the order of songs on a playlist.

        :param GlrMedia playlist: playlist to reorder
        :param list items: songs to reorder
        :param list new_positions: new songs positions
        """
        def update_callback(conn, res, data):
            conn.update_finish(res)

        for item, new_position in zip(items, new_positions):
            self.tracker.update_async(
                Query.change_song_position(playlist.get_id(), item.get_id(),
                                           new_position), GLib.PRIORITY_LOW,
                None, update_callback, item)
Пример #36
0
    def fetch_or_create_static_playlists(self):
        """For all static playlists: get ID, if exists; if not, create the playlist and get ID."""
        playlists = [cls for name, cls in inspect.getmembers(StaticPlaylists)
                     if inspect.isclass(cls) and not (name == "__class__")]  # hacky

        for playlist in playlists:
            cursor = self.tracker.query(Query.get_playlist_with_tag(playlist.TAG_TEXT), None)
            while cursor.next():
                playlist_id = cursor.get_string(1)[0]
                playlist.ID = int(playlist_id)  # hacky; shouldn't be reassigned every time

            if not playlist.ID:
                # create the playlist
                playlist.ID = self.create_playlist_and_return_id(playlist.TITLE, playlist.TAG_TEXT)

            self.update_static_playlist(playlist)
Пример #37
0
    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
Пример #38
0
    def rename(self, item, new_name):
        """Rename a playlist

        :param item: playlist to rename
        :param new_name: new playlist name
        :type item: Grl.Media
        :type new_name: str
        :return: None
        :rtype: None
        """
        def update_callback(conn, res, data):
            conn.update_finish(res)
            self.emit('playlist-renamed', item)

        self.tracker.update_async(
            Query.rename_playlist(item.get_id(), new_name), GLib.PRIORITY_LOW,
            None, update_callback, None)
Пример #39
0
        def callback(cursor, res, final_query):
            has_next = False
            try:
                has_next = cursor.next_finish(res)
            except GLib.Error as err:
                logger.warning("Error: {}, {}".format(err.__class__, err))

            # Only perform the update when the cursor reached the end
            if has_next:
                uri = cursor.get_string(0)[0]
                final_query += Query.add_song_to_playlist(playlist.ID, uri)

                cursor.next_async(None, callback, final_query)
            else:
                self._tracker.update_blank_async(
                    final_query, GLib.PRIORITY_LOW, None,
                    self._smart_playlist_update_finished, playlist)
Пример #40
0
    def fetch_or_create_static_playlists(self):
        """For all static playlists: get ID, if exists; if not, create the playlist and get ID."""
        def callback(obj, result, playlist):
            cursor = obj.query_finish(result)
            while (cursor.next(None)):
                playlist.ID = cursor.get_integer(1)

            if not playlist.ID:
                # create the playlist
                playlist.ID = self.create_playlist_and_return_id(
                    playlist.TITLE, playlist.TAG_TEXT)

            self.update_static_playlist(playlist)

        for playlist in self._static_playlists.get_all():
            self.tracker.query_async(
                Query.get_playlist_with_tag(playlist.TAG_TEXT), None, callback,
                playlist)
Пример #41
0
    def songs_available(self, callback):
        """Checks if there are any songs available

        Calls a callback function with True or False depending on the
        availability of songs.
        :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.warning("Error: {}, {}".format(err.__class__, err))
                callback(False)
                return

            if has_next:
                count = conn.get_integer(0)

                if count > 0:
                    callback(True)
                    return

            callback(False)

        def songs_query_cb(conn, res, data):
            try:
                cursor = conn.query_finish(res)
            except GLib.Error as err:
                logger.warning("Error: {}, {}".format(err.__class__, err))
                self.props.tracker_available = False
                callback(False)
                return

            cursor.next_async(None, cursor_next_cb, None)

        # TODO: currently just checks tracker, should work with any
        # queryable supported Grilo source.
        if not self.props.tracker_available:
            callback(False)
            return

        self.tracker_sparql.query_async(
            Query.all_songs_count(), None, songs_query_cb, None)
Пример #42
0
    def _setup_view(self):
        self._box = Gtk.VBox()
        self.player = Player()
        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)
        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)
        count = 1
        cursor = tracker.query(Query.all_songs_count(), None)
        if cursor is not None and cursor.next(None):
            count = cursor.get_integer(0)
        if count > 0:
            self._switch_to_player_view()
        # To revert to the No Music View when no songs are found
        else:
            if self.toolbar._selectionMode is False:
                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()
Пример #43
0
    def songs_available(self, callback):
        """Checks if there are any songs available

        Calls a callback function with True or False depending on the
        availability of songs.
        :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.warning("Error: {}, {}".format(err.__class__, err))
                callback(False)
                return

            if has_next:
                count = conn.get_integer(0)

                if count > 0:
                    callback(True)
                    return

            callback(False)

        def songs_query_cb(conn, res, data):
            try:
                cursor = conn.query_finish(res)
            except GLib.Error as err:
                logger.warning("Error: {}, {}".format(err.__class__, err))
                self.props.tracker_available = False
                callback(False)
                return

            cursor.next_async(None, cursor_next_cb, None)

        # TODO: currently just checks tracker, should work with any
        # queryable supported Grilo source.
        if not self.props.tracker_available:
            callback(False)
            return

        self.tracker_sparql.query_async(
            Query.all_songs_count(), None, songs_query_cb, None)
Пример #44
0
        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)
Пример #45
0
    def fetch_or_create_static_playlists(self):
        """For all static playlists: get ID, if exists; if not, create the playlist and get ID."""
        playlists = [cls for name, cls in inspect.getmembers(StaticPlaylists)
                     if inspect.isclass(cls) and not (name == "__class__")]  # hacky

        def callback(obj, result, playlist):
            cursor = obj.query_finish(result)
            while (cursor.next(None)):
                playlist.ID = cursor.get_integer(1)

            if not playlist.ID:
                # create the playlist
                playlist.ID = self.create_playlist_and_return_id(playlist.TITLE, playlist.TAG_TEXT)

            self.update_static_playlist(playlist)

        for playlist in playlists:
            self.tracker.query_async(
                Query.get_playlist_with_tag(playlist.TAG_TEXT), None,
                callback, playlist)
Пример #46
0
    def create_playlist(self, title):
        def get_callback(source, param, item, count, data, error):
            if item:
                self.emit('playlist-created', item)

        def query_callback(conn, res, data):
            cursor = conn.query_finish(res)
            if not cursor or not cursor.next():
                return
            playlist_id = cursor.get_integer(0)
            grilo.get_playlist_with_id(playlist_id, get_callback)

        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)
Пример #47
0
    def fetch_or_create_static_playlists(self):
        """For all static playlists: get ID, if exists; if not, create the playlist and get ID."""
        playlists = [cls for name, cls in inspect.getmembers(StaticPlaylists)
                     if inspect.isclass(cls) and not (name == "__class__")]  # hacky

        def callback(obj, result, playlist):
            cursor = obj.query_finish(result)
            while (cursor.next(None)):
                playlist.ID = cursor.get_integer(1)

            if not playlist.ID:
                # create the playlist
                playlist.ID = self.create_playlist_and_return_id(playlist.TITLE, playlist.TAG_TEXT)

            self.update_static_playlist(playlist)

        for playlist in playlists:
            self.tracker.query_async(
                Query.get_playlist_with_tag(playlist.TAG_TEXT), None,
                callback, playlist)
Пример #48
0
        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)
Пример #49
0
    def update_static_playlist(self, playlist):
        """Given a static playlist (subclass of StaticPlaylists), updates according to its query."""
        # Clear the playlist
        self.clear_playlist_with_id(playlist.ID)

        # Get a list of matching songs
        cursor = self.tracker.query(playlist.QUERY, None)
        if not cursor:
            return

        # For each song run 'add song to playlist'
        while cursor.next():
            uri = cursor.get_string(0)[0]
            self.tracker.update_blank_async(
                Query.add_song_to_playlist(playlist.ID, uri),
                GLib.PRIORITY_DEFAULT,
                None, None, None
            )

        # tell system we updated the playlist so playlist is reloaded
        self.emit('playlist-updated', playlist.ID)
Пример #50
0
    def update_static_playlist(self, playlist):
        """Given a static playlist (subclass of StaticPlaylists), updates according to its query."""
        # Clear the playlist
        self.clear_playlist_with_id(playlist.ID)

        final_query = ''

        # Get a list of matching songs
        cursor = self.tracker.query(playlist.QUERY, None)
        if not cursor:
            return

        # For each song run 'add song to playlist'
        while cursor.next():
            uri = cursor.get_string(0)[0]
            final_query += Query.add_song_to_playlist(playlist.ID, uri)

        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)
Пример #51
0
    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
        )
Пример #52
0
    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)
Пример #53
0
    def create_playlist(self, title):
        def get_callback(source, param, item, count, data, error):
            if item:
                self.emit('playlist-created', item)

        def query_callback(conn, res, data):
            cursor = conn.query_finish(res)
            if not cursor or not cursor.next():
                return
            playlist_id = cursor.get_integer(0)
            grilo.get_playlist_with_id(playlist_id, get_callback)

        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_DEFAULT,
            None, update_callback, None
        )
Пример #54
0
 def _on_changes_pending(self, data=None):
     count = 1
     cursor = tracker.query(Query.all_songs_count(), None)
     if cursor is not None and cursor.next(None):
         count = cursor.get_integer(0)
     if not count > 0:
         if self.toolbar._selectionMode is False and len(self.views) != 1:
             self._stack.disconnect(self._on_notify_model_id)
             self.disconnect(self._key_press_event_id)
             view_count = len(self.views)
             for i in range(0, view_count):
                 view = self.views.pop()
                 view.destroy()
             self.toolbar.hide_stack()
             self._switch_to_empty_view()
     else:
         if (self.views[0] == self.views[-1]):
             view = self.views.pop()
             view.destroy()
             self._switch_to_player_view()
             self.toolbar._search_button.set_sensitive(True)
             self.toolbar._select_button.set_sensitive(True)
             self.toolbar.show_stack()
Пример #55
0
 def _on_changes_pending(self, data=None):
     count = 1
     cursor = tracker.query(Query.all_songs_count(), None)
     if cursor is not None and cursor.next(None):
         count = cursor.get_integer(0)
     if not count > 0:
         if self.toolbar._selectionMode is False and len(self.views) != 1:
             self._stack.disconnect(self._on_notify_model_id)
             self.disconnect(self._key_press_event_id)
             view_count = len(self.views)
             for i in range(0, view_count):
                 view = self.views.pop()
                 view.destroy()
             self.toolbar.hide_stack()
             self._switch_to_empty_view()
     else:
         if (self.views[0] == self.views[-1]):
             view = self.views.pop()
             view.destroy()
             self._switch_to_player_view()
             self.toolbar._search_button.set_sensitive(True)
             self.toolbar._select_button.set_sensitive(True)
             self.toolbar.show_stack()
Пример #56
0
    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)
Пример #57
0
    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)
Пример #58
0
 def populate_playlists(self, offset, callback, count=-1):
     self.populate_items(Query.all_playlists(), offset, callback, count)
Пример #59
0
 def populate_playlist_songs(self, playlist, callback, count=-1):
     self.populate_items(Query.playlist_songs(playlist.get_id()), 0, callback, count)