Example #1
0
    def _add_item(self, source, param, item, remaining=0, data=None):
        if not item:
            if remaining == 0:
                self.view.set_model(self.model)
                self.window.pop_loading_notification()
                self.view.show()
            return

        self._offset += 1
        artist = utils.get_artist_name(item)
        title = utils.get_media_title(item)

        _iter = self.model.append(None)

        loading_icon = Gdk.pixbuf_get_from_surface(
            self._loadin_icon_surface, 0, 0,
            self._loading_icon_surface.get_width(),
            self._loading_icon_surface.get_height())

        self.model[_iter][0, 1, 2, 3, 4, 5, 7, 9] = [
            str(item.get_id()),
            '',
            title,
            artist,
            loading_icon,
            item,
            0,
            False
        ]
        self.cache.lookup(item, self._iconWidth, self._iconHeight,
                          self._on_lookup_ready, _iter)
Example #2
0
 def _get_active_playlist(self):
     playlist = self._get_playlist_from_id(self.player.playlistId) \
         if self.player.playlistType == 'Playlist' else None
     playlistName = utils.get_media_title(playlist) \
         if playlist else ''
     return (playlist is not None,
             (self._get_playlist_path(playlist), playlistName, ''))
Example #3
0
    def _add_playlist_to_sidebar(self, playlist, index=None):
        """Add a playlist to sidebar

        :param GrlMedia playlist: playlist to add
        :param int index: position
        """
        if index is None:
            index = -1
        if playlists.is_static_playlist(playlist):
            index = 0

        title = utils.get_media_title(playlist)
        row = Gtk.ListBoxRow()
        row.playlist = playlist
        label = Gtk.Label(label=title,
                          xalign=0,
                          xpad=16,
                          ypad=16,
                          ellipsize=Pango.EllipsizeMode.END)
        row.add(label)
        row.show_all()
        self._sidebar.insert(row, index)
        self._offset += 1

        if len(self._sidebar) == 1:
            self._sidebar.select_row(row)
            self._sidebar.emit('row-activated', row)
Example #4
0
    def _create_song_widget(self, song):
        """Helper function to create a song widget for a
        single song

        :param song: A Grilo media item
        :returns: A complete song widget
        :rtype: Gtk.EventBox
        """
        song_widget = SongWidget(song)
        self._songs.append(song_widget)

        title = utils.get_media_title(song)

        itr = self._model.append(None)

        self._model[itr][0, 1, 2, 5, 6] = [title, '', '', song, False]

        song_widget.itr = itr
        song_widget.model = self._model
        song_widget.connect('button-release-event', self._song_activated)
        song_widget.connect('selection-changed', self._on_selection_changed)

        self.bind_property('selection-mode', song_widget, 'selection-mode',
                           GObject.BindingFlags.SYNC_CREATE)
        self.bind_property('show-durations', song_widget, 'show-duration',
                           GObject.BindingFlags.SYNC_CREATE)
        self.bind_property('show-favorites', song_widget, 'show-favorite',
                           GObject.BindingFlags.SYNC_CREATE)
        self.bind_property('show-song-numbers', song_widget,
                           'show-song-number',
                           GObject.BindingFlags.SYNC_CREATE)

        return song_widget
Example #5
0
    def _on_playlist_activated(self, sidebar, row, data=None):
        """Update view with content from selected playlist"""
        playlist = row.playlist
        playlist_name = utils.get_media_title(playlist)

        if self.rename_active:
            self.disable_rename_playlist()

        self._current_playlist = playlist
        self._name_label.set_text(playlist_name)
        self._current_playlist_index = row.get_index()

        # if the active queue has been set by this playlist,
        # use it as model, otherwise build the liststore
        self._view.set_model(None)
        self.model.clear()
        self._iter_to_clean = None
        self._iter_to_clean_model = None
        self._songs_count = 0
        grilo.populate_playlist_songs(playlist, self._add_song)

        if self._current_playlist_is_protected():
            self._playlist_delete_action.set_enabled(False)
            self._playlist_rename_action.set_enabled(False)
            self._remove_song_action.set_enabled(False)
            self._view.set_reorderable(False)
        else:
            self._playlist_delete_action.set_enabled(True)
            self._playlist_rename_action.set_enabled(True)
            self._remove_song_action.set_enabled(True)
            self._view.set_reorderable(True)
Example #6
0
    def load(self, media):
        self._progress_scale_zero()
        self._set_duration(media.get_duration())
        self.songTotalTimeLabel.set_label(
            utils.seconds_to_string(media.get_duration()))
        self.progressScale.set_sensitive(True)

        self.playBtn.set_sensitive(True)
        self._sync_prev_next()

        artist = utils.get_artist_name(media)
        self.artistLabel.set_label(artist)
        self._currentArtist = artist

        self.coverImg.set_from_surface(self._loading_icon_surface)
        self.cache.lookup(media, ArtSize.xsmall, self._on_cache_lookup, None)

        self._currentTitle = utils.get_media_title(media)
        self.titleLabel.set_label(self._currentTitle)

        self._currentTimestamp = int(time.time())

        url = media.get_url()
        if url != self.player.get_value('current-uri', 0):
            self.player.set_property('uri', url)

        if self.currentTrack and self.currentTrack.valid():
            currentTrack = self.playlist.get_iter(self.currentTrack.get_path())
            self.emit('playlist-item-changed', self.playlist, currentTrack)
            self.emit('current-changed')

        self._validate_next_track()
Example #7
0
    def _add_item(self, source, param, item, remaining=0, data=None):
        self.window.notification.set_timeout(0)
        if not item:
            if remaining == 0:
                self.view.set_model(self.model)
                self.window.notification.dismiss()
                self.view.show()
            return

        self._offset += 1
        artist = utils.get_artist_name(item)
        title = utils.get_media_title(item)

        _iter = self.model.append(None)

        loading_icon = Gdk.pixbuf_get_from_surface(
            self._loadin_icon_surface, 0, 0,
            self._loading_icon_surface.get_width(),
            self._loading_icon_surface.get_height())

        self.model[_iter][0, 1, 2, 3, 4, 5, 7, 9] = [
            str(item.get_id()), '', title, artist, loading_icon, item, 0, False
        ]
        self.cache.lookup(item, self._iconWidth, self._iconHeight,
                          self._on_lookup_ready, _iter)
Example #8
0
    def _now_playing(self, media):
        """Internal method called by self.now_playing"""
        api_key = self._authentication.props.client_id
        sk = self._authentication.call_get_access_token_sync(None)[0]
        secret = self._authentication.props.client_secret

        artist = utils.get_artist_name(media)
        title = utils.get_media_title(media)

        sig = ("api_key{}artist{}methodtrack.updateNowPlayingsk{}track"
               "{}{}").format(api_key, artist, sk, title, secret)

        api_sig = md5(sig.encode()).hexdigest()
        request_dict = {
            "api_key": api_key,
            "method": "track.updateNowPlaying",
            "artist": artist,
            "track": title,
            "sk": sk,
            "api_sig": api_sig
        }

        try:
            r = requests.post("https://ws.audioscrobbler.com/2.0/",
                              request_dict)
            if r.status_code != 200:
                logger.warn("Failed to update currently played track: %s %s" %
                            (r.status_code, r.reason))
                logger.warn(r.text)
        except Exception as e:
            logger.warn(e)
Example #9
0
    def _add_playlist_to_sidebar(self,
                                 playlist,
                                 index=None,
                                 select_playlist=False):
        """Add a playlist to sidebar

        :param GrlMedia playlist: playlist to add
        :param int index: position
        """
        if index is None:
            index = -1
        if playlists.is_smart_playlist(playlist):
            index = 0

        title = utils.get_media_title(playlist)
        row = SidebarRow()
        row.props.text = title
        # FIXME: Passing the Grl.Media with the row object is ugly.
        row.playlist = playlist

        self._sidebar.insert(row, index)
        self._offset += 1

        if select_playlist:
            self._sidebar.select_row(row)
            row.emit('activate')
    def __init__(self,
                 media=None,
                 query=None,
                 tag_text=None,
                 source=None,
                 coremodel=None,
                 coreselection=None,
                 grilo=None,
                 tracker=None):
        super().__init__()

        if media:
            self.props.pl_id = media.get_id()
            self.props.title = utils.get_media_title(media)
            self.props.count = media.get_childcount()
            self.props.creation_date = media.get_creation_date()

        self.props.query = query
        self.props.tag_text = tag_text
        self._model = None
        self._source = source
        self._coremodel = coremodel
        self._coreselection = coreselection
        self._grilo = grilo
        self._tracker = tracker

        self._fast_options = Grl.OperationOptions()
        self._fast_options.set_resolution_flags(
            Grl.ResolutionFlags.FAST_ONLY | Grl.ResolutionFlags.IDLE_RELAY)

        self._songs_todelete = []
Example #11
0
 def _get_active_playlist(self):
     playlist = self._get_playlist_from_id(self.player.playlistId) \
         if self.player.playlistType == 'Playlist' else None
     playlistName = utils.get_media_title(playlist) \
         if playlist else ''
     return (playlist is not None, (self._get_playlist_path(playlist),
                                    playlistName, ''))
Example #12
0
    def _on_playlist_activated(self, sidebar, row, data=None):
        """Update view with content from selected playlist"""
        playlist = row.playlist
        playlist_name = utils.get_media_title(playlist)

        if self.rename_active:
            self._pl_ctrls.disable_rename_playlist()

        self._current_playlist = playlist
        self._pl_ctrls.props.playlist_name = playlist_name
        self._current_playlist_index = row.get_index()

        # if the active queue has been set by this playlist,
        # use it as model, otherwise build the liststore
        self._view.set_model(None)
        self.model.clear()
        self._iter_to_clean = None
        self._iter_to_clean_model = None
        self._update_songs_count(0)
        self._pl_ctrls.props.display_songs_count = False
        grilo.populate_playlist_songs(playlist, self._add_song)

        protected_pl = playlists.is_smart_playlist(self._current_playlist)
        self._playlist_delete_action.set_enabled(not protected_pl)
        self._playlist_rename_action.set_enabled(not protected_pl)
        self._remove_song_action.set_enabled(not protected_pl)
        self._view.set_reorderable(not protected_pl)
Example #13
0
    def load(self, media):
        self._progress_scale_zero()
        self._set_duration(media.get_duration())
        self.songTotalTimeLabel.set_label(
            utils.seconds_to_string(media.get_duration()))
        self.progressScale.set_sensitive(True)

        self.playBtn.set_sensitive(True)
        self._sync_prev_next()

        artist = utils.get_artist_name(media)
        self.artistLabel.set_label(artist)

        self.coverImg.set_from_surface(self._loading_icon_surface)
        self.cache.lookup(media, ArtSize.XSMALL, self._on_cache_lookup, None)

        title = utils.get_media_title(media)
        self.titleLabel.set_label(title)

        self._time_stamp = int(time.time())

        url = media.get_url()
        if url != self.player.get_value('current-uri', 0):
            self.player.set_property('uri', url)

        if self.currentTrack and self.currentTrack.valid():
            currentTrack = self.playlist.get_iter(self.currentTrack.get_path())
            self.emit('playlist-item-changed', self.playlist, currentTrack)
            self.emit('current-changed')

        self._validate_next_track()
Example #14
0
    def _on_playlist_activated(self, sidebar, row, data=None):
        """Update view with content from selected playlist"""
        playlist = row.playlist
        playlist_name = utils.get_media_title(playlist)

        if self.rename_active:
            self._pl_ctrls.disable_rename_playlist()

        self._current_playlist = playlist
        self._pl_ctrls.props.playlist_name = playlist_name
        self._current_playlist_index = row.get_index()

        # if the active queue has been set by this playlist,
        # use it as model, otherwise build the liststore
        self._view.set_model(None)
        self.model.clear()
        self._iter_to_clean = None
        self._iter_to_clean_model = None
        self._update_songs_count(0)
        self._pl_ctrls.props.display_songs_count = False
        grilo.populate_playlist_songs(playlist, self._add_song)

        protected_pl = playlists.is_smart_playlist(self._current_playlist)
        self._playlist_delete_action.set_enabled(not protected_pl)
        self._playlist_rename_action.set_enabled(not protected_pl)
        self._remove_song_action.set_enabled(not protected_pl)
        self._view.set_reorderable(not protected_pl)
    def _update_model(self, player, playlist, current_iter):
        """Player changed callback.

        :param player: The player object
        :param playlist: The current playlist
        :param current_iter: The current iter of the playlist model
        """
        # self is not our playlist, return
        if (playlist != self.model):
            return False

        current_song = playlist[current_iter][5]
        song_passed = False
        _iter = playlist.get_iter_first()
        self._duration = 0

        while _iter:
            song = playlist[_iter][5]
            self._duration += song.get_duration()
            escaped_title = GLib.markup_escape_text(
                utils.get_media_title(song))
            if (song == current_song):
                title = '<b>%s</b>' % escaped_title
                song_passed = True
            elif (song_passed):
                title = '<span>%s</span>' % escaped_title
            else:
                title = '<span color=\'grey\'>%s</span>' % escaped_title
            playlist[_iter][0] = title
            _iter = playlist.iter_next(_iter)
            self._ui.get_object('running_length_label_info').set_text(
                _("%d min") % (int(self._duration / 60) + 1))

        return False
Example #16
0
    def _create_song_widget(self, track):
        """Helper function to create a song widget for a
        single song

        :param track: A Grilo media item
        :returns: A complete song widget
        :rtype: Gtk.EventBox
        """
        builder = Gtk.Builder()
        builder.add_from_resource('/org/gnome/Music/TrackWidget.ui')
        song_widget = builder.get_object('eventbox1')
        self._songs.append(song_widget)

        title = utils.get_media_title(track)

        itr = self._model.append(None)

        self._model[itr][0, 1, 2, 5, 6] = [title, '', '', track, False]

        song_widget.itr = itr
        song_widget.model = self._model

        track_number = track.get_track_number()
        if track_number == 0:
            track_number = ""
        song_widget.number = builder.get_object('num')
        song_widget.number.set_markup(
            '<span color=\'grey\'>{}</span>'.format(track_number))
        song_widget.number.set_no_show_all(True)

        song_widget.title = builder.get_object('title')
        song_widget.title.set_text(title)
        song_widget.title.set_max_width_chars(50)

        song_widget.duration = builder.get_object('duration')
        time = utils.seconds_to_string(track.get_duration())
        song_widget.duration.set_text(time)

        song_widget.check_button = builder.get_object('select')
        song_widget.check_button.set_visible(False)
        song_widget.check_button.connect('toggled', self._check_button_toggled,
                                         song_widget)

        song_widget.now_playing_sign = builder.get_object('image1')
        song_widget.now_playing_sign.set_from_icon_name(
            NOW_PLAYING_ICON_NAME, Gtk.IconSize.SMALL_TOOLBAR)
        song_widget.now_playing_sign.set_no_show_all(True)
        song_widget.can_be_played = True
        song_widget.connect('button-release-event', self._track_activated)

        song_widget.star_stack = builder.get_object('starstack')
        song_widget.star_stack.set_favorite(track.get_lyrics())
        song_widget.star_stack.set_visible(True)

        song_widget.starevent = builder.get_object('starevent')
        song_widget.starevent.connect('button-release-event',
                                      self._toggle_favorite, song_widget)

        return song_widget
Example #17
0
    def __init__(self, media):
        """Initialize the AlbumCover

        :param Grl.Media media: The media object to use
        """
        super().__init__()

        AlbumCover._nr_albums += 1

        self._media = media

        self._tooltip = TwoLineTip()

        artist = utils.get_artist_name(media)
        title = utils.get_media_title(media)

        self._tooltip.props.title = utils.get_artist_name(media)
        self._tooltip.props.subtitle = utils.get_media_title(media)

        self._artist_label.props.label = artist
        self._title_label.props.label = title

        self.bind_property(
            'selected', self._check, 'active',
            GObject.BindingFlags.BIDIRECTIONAL
            | GObject.BindingFlags.SYNC_CREATE)
        self.bind_property('selection-mode', self._check, 'visible',
                           GObject.BindingFlags.BIDIRECTIONAL)

        self.connect('query-tooltip', self._on_tooltip_query)

        self._events.add_events(Gdk.EventMask.TOUCH_MASK)

        self._cover_stack.props.size = Art.Size.MEDIUM

        self.show()

        # FIXME: To work around slow updating of the albumsview,
        # load album covers with a fixed delay. This results in a
        # quick first show with a placeholder cover and then a
        # reasonably responsive view while loading the actual
        # covers.
        GLib.timeout_add(50 * self._nr_albums,
                         self._cover_stack.update,
                         media,
                         priority=GLib.PRIORITY_LOW)
Example #18
0
 def GetPlaylists(self, index, max_count, order, reverse):
     if order != 'Alphabetical':
         return []
     playlists = [(self._get_playlist_path(playlist),
                   utils.get_media_title(playlist) or '', '')
                  for playlist in self.playlists]
     return playlists[index:index + max_count] if not reverse \
         else playlists[index + max_count - 1:index - 1 if index - 1 >= 0 else None:-1]
Example #19
0
    def enable_rename_playlist(self, pl_torename):
        """Enables rename button and entry

        :param Grl.Media pl_torename : The playlist to rename
        """
        self._name_stack.props.visible_child_name = "renaming_dialog"
        self._set_rename_entry_text_and_focus(
            utils.get_media_title(pl_torename))
Example #20
0
    def __init__(self, media):
        """Initialize the AlbumCover

        :param Grl.Media media: The media object to use
        """
        super().__init__()

        AlbumCover._nr_albums += 1

        self._media = media

        self._tooltip = TwoLineTip()

        artist = utils.get_artist_name(media)
        title = utils.get_media_title(media)

        self._tooltip.props.title = utils.get_artist_name(media)
        self._tooltip.props.subtitle = utils.get_media_title(media)

        self._artist_label.props.label = artist
        self._title_label.props.label = title

        self.bind_property(
            'selected', self._check, 'active',
            GObject.BindingFlags.BIDIRECTIONAL
            | GObject.BindingFlags.SYNC_CREATE)
        self.bind_property(
            'selection-mode', self._check, 'visible',
            GObject.BindingFlags.BIDIRECTIONAL)

        self.connect('query-tooltip', self._on_tooltip_query)

        self._events.add_events(Gdk.EventMask.TOUCH_MASK)

        self._cover_stack.props.size = Art.Size.MEDIUM

        self.show()

        # FIXME: To work around slow updating of the albumsview,
        # load album covers with a fixed delay. This results in a
        # quick first show with a placeholder cover and then a
        # reasonably responsive view while loading the actual
        # covers.
        GLib.timeout_add(
            50 * self._nr_albums, self._cover_stack.update, media,
            priority=GLib.PRIORITY_LOW)
Example #21
0
 def GetPlaylists(self, index, max_count, order, reverse):
     if order != 'Alphabetical':
         return []
     playlists = [(self._get_playlist_dbus_path(playlist),
                   utils.get_media_title(playlist) or '', '')
                  for playlist in self.playlists]
     return playlists[index:index + max_count] if not reverse \
         else playlists[index + max_count - 1:index - 1 if index - 1 >= 0 else None:-1]
Example #22
0
 def _add_item(self, source, param, item, remaining=0, data=None):
     self.window.notification.set_timeout(0)
     if not item:
         if remaining == 0:
             self.view.set_model(self.model)
             self.window.notification.dismiss()
             self.view.show()
         return
     self._offset += 1
     item.set_title(utils.get_media_title(item))
     artist = utils.get_artist_name(item)
     if item.get_url() is None:
         return
     self.model.insert_with_valuesv(-1, [2, 3, 5, 9], [
         utils.get_media_title(item), artist, item,
         bool(item.get_lyrics())
     ])
Example #23
0
    def _add_item(self, source, param, item, remaining=0, data=None):
        """Adds track item to the model"""
        if not item and not remaining:
            self._view.set_model(self.model)
            self._window.notifications_popup.pop_loading()
            self._view.show()
            return

        self._offset += 1
        item.set_title(utils.get_media_title(item))
        artist = utils.get_artist_name(item)

        if not item.get_url():
            return

        self.model.insert_with_valuesv(
            -1, [2, 3, 5, 9],
            [utils.get_media_title(item), artist, item, item.get_favourite()])
Example #24
0
    def _get_active_playlist(self):
        playlist = None
        playlist_name = ''
        if self.player.get_playlist_type() == PlayerPlaylist.Type.PLAYLIST:
            playlist = self._get_playlist_from_id(
                self.player.get_playlist_id())
            playlist_name = utils.get_media_title(playlist)

        path = self._get_playlist_path(playlist)
        return (playlist is not None, (path, playlist_name, ''))
Example #25
0
    def update(self, media):
        """Update the CoreAlbum object with new info

        :param Grl.Media media: A media object
        """
        self.props.media = media
        self.props.artist = utils.get_artist_name(media)
        self.props.composer = media.get_composer()
        self.props.title = utils.get_media_title(media)
        self.props.year = utils.get_media_year(media)
Example #26
0
 def update(self, media):
     self.props.media = media
     self.props.album = utils.get_album_title(media)
     self.props.album_disc_number = media.get_album_disc_number()
     self.props.artist = utils.get_artist_name(media)
     self.props.duration = media.get_duration()
     self.props.favorite = media.get_favourite()
     self.props.play_count = media.get_play_count()
     self.props.title = utils.get_media_title(media)
     self.props.track_number = media.get_track_number()
     self.props.url = media.get_url()
Example #27
0
 def clean_model(self):
     itr = self._model.get_iter_first()
     while itr:
         song = self._model.get_value(itr, 5)
         song_widget = song.song_widget
         escaped_title = GLib.markup_escape_text(utils.get_media_title(song))
         if song_widget.can_be_played:
             song_widget.now_playing_sign.hide()
         song_widget.title.set_markup('<span>%s</span>' % escaped_title)
         itr = self._model.iter_next(itr)
     return False
    def _update_view(self, player, playlist, current_iter):
        media = playlist[current_iter][player.Field.SONG]
        self._duration_label.set_label(
            utils.seconds_to_string(media.get_duration()))

        self._play_button.set_sensitive(True)
        self._sync_prev_next()

        self._artist_label.set_label(utils.get_artist_name(media))
        self._title_label.set_label(utils.get_media_title(media))
        self._cover_stack.update(media)
Example #29
0
 def clean_model(self):
     itr = self._model.get_iter_first()
     while itr:
         song = self._model.get_value(itr, 5)
         song_widget = song.song_widget
         escaped_title = GLib.markup_escape_text(
             utils.get_media_title(song))
         if song_widget.can_be_played:
             song_widget.now_playing_sign.hide()
         song_widget.title.set_markup('<span>%s</span>' % escaped_title)
         itr = self._model.iter_next(itr)
     return False
Example #30
0
    def _add_item_to_model(self, item):
        """Adds (non-static only) playlists to the model"""

        # Hide playlists that are going to be deleted
        if item.get_id() in self._playlists_todelete_ids:
            return None

        self._user_playlists_available = True
        new_iter = self._model.insert_with_valuesv(
            -1, [0, 1], [utils.get_media_title(item), item])

        return new_iter
Example #31
0
    def _add_item(self, source, param, item, remaining=0, data=None):
        """Adds track item to the model"""
        if not item and not remaining:
            self.view.set_model(self.model)
            self.window.pop_loading_notification()
            self.view.show()
            return

        self._offset += 1
        item.set_title(utils.get_media_title(item))
        artist = utils.get_artist_name(item)

        if not item.get_url():
            return

        self.model.insert_with_valuesv(-1, [2, 3, 5, 9], [
            utils.get_media_title(item),
            artist,
            item,
            item.get_favourite()
        ])
Example #32
0
    def _get_removal_notification_message(self, type_, media_id):
        """ Returns a label for the playlist notification popup

        Handles two cases:
        - playlist removal
        - songs from playlist removal
        """
        msg = ""

        if type_ == PlaylistNotification.Type.PLAYLIST:
            pl_todelete = self.pls_todelete[media_id]
            playlist_title = utils.get_media_title(pl_todelete['playlist'])
            msg = _("Playlist {} removed".format(playlist_title))

        else:
            song_todelete = self._songs_todelete[media_id]
            playlist_title = utils.get_media_title(song_todelete['playlist'])
            song_title = utils.get_media_title(song_todelete['song'])
            msg = _("{} removed from {}".format(song_title, playlist_title))

        return msg
Example #33
0
    def _lastfm_api_call(self, media, time_stamp, request_type_key):
        """Internal method called by self.scrobble"""
        api_key = self._goa_lastfm.client_id
        sk = self._goa_lastfm.session_key
        secret = self._goa_lastfm.secret

        artist = utils.get_artist_name(media)
        title = utils.get_media_title(media)

        request_type = {
            "update now playing": "track.updateNowPlaying",
            "scrobble": "track.scrobble"
        }

        # The album is optional. So only provide it when it is
        # available.
        album = media.get_album()

        request_dict = {}
        if album:
            request_dict.update({
                "album": album
            })

        if time_stamp is not None:
            request_dict.update({
                "timestamp": str(time_stamp)
            })

        request_dict.update({
            "api_key": api_key,
            "method": request_type[request_type_key],
            "artist": artist,
            "track": title,
            "sk": sk,
        })

        sig = ""
        for key in sorted(request_dict):
            sig += key + request_dict[key]

        sig += secret

        api_sig = md5(sig.encode()).hexdigest()
        request_dict.update({
            "api_sig": api_sig
        })

        msg = Soup.form_request_new_from_hash(
            "POST", "https://ws.audioscrobbler.com/2.0/", request_dict)
        self._soup_session.queue_message(
            msg, self._lastfm_api_callback, request_type_key)
Example #34
0
    def _get_metadata(self, media=None, index=None):
        song_dbus_path = self._get_song_dbus_path(media, index)
        if not self.player.props.current_song:
            return {'mpris:trackid': GLib.Variant('o', song_dbus_path)}

        if not media:
            media = self.player.props.current_song

        length = media.get_duration() * 1e6
        user_rating = 1.0 if media.get_favourite() else 0.0
        artist = utils.get_artist_name(media)

        metadata = {
            'mpris:trackid': GLib.Variant('o', song_dbus_path),
            'xesam:url': GLib.Variant('s', media.get_url()),
            'mpris:length': GLib.Variant('x', length),
            'xesam:trackNumber': GLib.Variant('i', media.get_track_number()),
            'xesam:useCount': GLib.Variant('i', media.get_play_count()),
            'xesam:userRating': GLib.Variant('d', user_rating),
            'xesam:title': GLib.Variant('s', utils.get_media_title(media)),
            'xesam:album': GLib.Variant('s', utils.get_album_title(media)),
            'xesam:artist': GLib.Variant('as', [artist]),
            'xesam:albumArtist': GLib.Variant('as', [artist])
        }

        genre = media.get_genre()
        if genre is not None:
            metadata['xesam:genre'] = GLib.Variant('as', [genre])

        last_played = media.get_last_played()
        if last_played is not None:
            last_played_str = last_played.format("%FT%T%:z")
            metadata['xesam:lastUsed'] = GLib.Variant('s', last_played_str)

        # If the media has already been part of an MPRIS playlist, its
        # thumbnail is already set. Otherwise, try to look for it in the
        # cache directory and set the media thumbnail for a future use.
        # The search is only through the cache to prevent any delayed
        # loading.
        # FIXME: The thumbnail retrieval should take place in the
        # player.
        art_url = media.get_thumbnail()
        if not art_url:
            thumb_file = lookup_art_file_from_cache(media)
            if thumb_file:
                art_url = GLib.filename_to_uri(thumb_file.get_path())
                media.set_thumbnail(art_url)

        if art_url:
            metadata['mpris:artUrl'] = GLib.Variant('s', art_url)

        return metadata
Example #35
0
    def _get_removal_notification_message(self, type_, media_id):
        """ Returns a label for the playlist notification popup

        Handles two cases:
        - playlist removal
        - songs from playlist removal
        """
        msg = ""

        if type_ == PlaylistNotification.Type.PLAYLIST:
            pl_todelete = self.pls_todelete[media_id]
            playlist_title = utils.get_media_title(pl_todelete['playlist'])
            msg = _("Playlist {} removed".format(playlist_title))

        else:
            song_todelete = self._songs_todelete[media_id]
            playlist_title = utils.get_media_title(song_todelete['playlist'])
            song_title = utils.get_media_title(song_todelete['song'])
            msg = _("{} removed from {}".format(
                song_title, playlist_title))

        return msg
Example #36
0
    def __init__(self, playlist):
        """Create a row of the PlaylistDialog

        :param Grl.Media playlist: the associated playlist
        """
        super().__init__()

        self.props.playlist = playlist
        self._label.props.label = utils.get_media_title(playlist)

        self.bind_property(
            "selected", self._selection_icon, "visible",
            GObject.BindingFlags.SYNC_CREATE)
Example #37
0
    def _lastfm_api_call(self, media, time_stamp, request_type_key):
        """Internal method called by self.scrobble"""
        api_key = self._goa_lastfm.client_id
        sk = self._goa_lastfm.session_key
        secret = self._goa_lastfm.secret

        artist = utils.get_artist_name(media)
        title = utils.get_media_title(media)

        request_type = {
            "update now playing": "track.updateNowPlaying",
            "scrobble": "track.scrobble"
        }

        # The album is optional. So only provide it when it is
        # available.
        album = media.get_album()

        request_dict = {}
        if album:
            request_dict.update({"album": album})

        if time_stamp is not None:
            request_dict.update({"timestamp": time_stamp})

        request_dict.update({
            "api_key": api_key,
            "method": request_type[request_type_key],
            "artist": artist,
            "track": title,
            "sk": sk,
        })

        sig = ""
        for key in sorted(request_dict):
            sig += key + str(request_dict[key])

        sig += secret

        api_sig = md5(sig.encode()).hexdigest()
        request_dict.update({"api_sig": api_sig})

        try:
            r = requests.post("https://ws.audioscrobbler.com/2.0/",
                              request_dict)
            if r.status_code != 200:
                logger.warning("Failed to {} track: {} {}".format(
                    request_type_key, r.status_code, r.reason))
                logger.warning(r.text)
        except Exception as e:
            logger.warning(e)
    def _add_item_to_model(self, item):
        """Adds (non-static only) playlists to the model"""

        # Don't show static playlists
        if self.playlist.is_static_playlist(item):
            return None

        new_iter = self.model.append()
        self.model.set(
            new_iter,
            [0, 1, 2],
            [utils.get_media_title(item), False, item]
        )
        return new_iter
Example #39
0
    def _add_item_to_model(self, item):
        """Adds (non-static only) playlists to the model"""

        # Don't show static playlists
        if self.playlist.is_static_playlist(item):
            return None

        new_iter = self.model.append()
        self.model.set(
            new_iter,
            [0, 1, 2],
            [utils.get_media_title(item), False, item]
        )
        return new_iter
 def _add_item_to_model(self, item, model):
     if not item:
         self._update_songs_count()
         if self.player.playlist:
             self.player._validate_next_track()
         self.emit('playlist-songs-loaded')
         return
     self._offset += 1
     title = utils.get_media_title(item)
     item.set_title(title)
     artist = item.get_artist() or _("Unknown Artist")
     model.insert_with_valuesv(
         -1, [2, 3, 5, 9],
         [title, artist, item, bool(item.get_lyrics())])
     self.songs_count += 1
Example #41
0
    def _add_item_to_model(self, item):
        """Adds (non-static only) playlists to the model"""

        # Don't show static playlists
        if self._playlist.is_static_playlist(item):
            return None

        # Hide playlists that are going to be deleted
        if item.get_id() in self._playlists_todelete_ids:
            return None

        new_iter = self._model.insert_with_valuesv(
            -1, [0, 1], [utils.get_media_title(item), item])

        return new_iter
Example #42
0
 def _add_item_to_model(self, item, model):
     if not item:
         self._update_songs_count()
         if self.player.playlist:
             self.player._validate_next_track()
         self.emit('playlist-songs-loaded')
         return
     self._offset += 1
     title = utils.get_media_title(item)
     item.set_title(title)
     artist = utils.get_album_title(item)
     model.insert_with_valuesv(
         -1,
         [2, 3, 5, 9],
         [title, artist, item, item.get_favourite()])
     self.songs_count += 1
Example #43
0
    def _on_item_activated(self, widget, id, path):
        if self.star_handler.star_renderer_click:
            self.star_handler.star_renderer_click = False
            return

        try:
            child_path = self.filter_model.convert_path_to_child_path(path)
        except TypeError:
            return
        _iter = self.model.get_iter(child_path)
        if self.model[_iter][11] == 'album':
            title = self.model.get_value(_iter, 2)
            artist = self.model.get_value(_iter, 3)
            item = self.model.get_value(_iter, 5)
            self._albumWidget.update(artist, title, item,
                                     self.header_bar, self.selection_toolbar)
            self.header_bar.set_state(ToolbarState.SEARCH_VIEW)
            title = utils.get_media_title(item)
            self.header_bar.header_bar.set_title(title)
            self.header_bar.header_bar.sub_title = artist
            self.set_visible_child(self._albumWidget)
            self.header_bar.searchbar.show_bar(False)
        elif self.model[_iter][11] == 'artist':
            artist = self.model.get_value(_iter, 2)
            albums = self._artists[artist.casefold()]['albums']

            self._artistAlbumsWidget = ArtistAlbumsWidget(
                artist, albums, self.player,
                self.header_bar, self.selection_toolbar, self.window, True
            )
            self.add(self._artistAlbumsWidget)
            self._artistAlbumsWidget.show()

            self.header_bar.set_state(ToolbarState.SEARCH_VIEW)
            self.header_bar.header_bar.set_title(artist)
            self.set_visible_child(self._artistAlbumsWidget)
            self.header_bar.searchbar.show_bar(False)
        elif self.model[_iter][11] == 'song':
            if self.model.get_value(_iter, 12) != DiscoveryStatus.FAILED:
                child_iter = self.songs_model.convert_child_iter_to_iter(_iter)[1]
                self.player.set_playlist('Search Results', None, self.songs_model, child_iter, 5, 12)
                self.player.set_playing(True)
        else:  # Headers
            if self.view.get_generic_view().row_expanded(path):
                self.view.get_generic_view().collapse_row(path)
            else:
                self.view.get_generic_view().expand_row(path, False)
Example #44
0
 def _add_playlist_item_to_model(self, item, index=None):
     if index is None:
         index = -1
     if not item:
         self.window.pop_loading_notification()
         self.emit('playlists-loaded')
         return
     _iter = self.playlists_model.insert_with_valuesv(
         index,
         [2, 5],
         [utils.get_media_title(item), item])
     if self.playlists_model.iter_n_children(None) == 1:
         _iter = self.playlists_model.get_iter_first()
         selection = self.playlists_sidebar.get_generic_view().get_selection()
         selection.select_iter(_iter)
         self.playlists_sidebar.emit('item-activated', '0',
                                     self.playlists_model.get_path(_iter))
Example #45
0
    def _add_song_to_model(self, song, model, index=-1):
        """Add song to a playlist
        :param Grl.Media song: song to add
        :param Gtk.ListStore model: model
        """
        if not song:
            return None

        title = utils.get_media_title(song)
        song.set_title(title)
        artist = utils.get_artist_name(song)
        iter_ = model.insert_with_valuesv(
            index, [2, 3, 5, 9],
            [title, artist, song, song.get_favourite()])

        self._update_songs_count(self._songs_count + 1)
        return iter_
Example #46
0
    def _get_active_playlist(self):
        """Get Active Maybe_Playlist

        Maybe_Playlist is a structure describing a playlist, or nothing
        according to MPRIS specifications.
        If a playlist is active, return True and its description
        (path, name and icon).
        If no playlist is active, return False and an undefined structure.
        :returns: playlist existence and its structure
        :rtype: tuple
        """
        if self.player.get_playlist_type() != PlayerPlaylist.Type.PLAYLIST:
            return (False, ("/", "", ""))

        playlist = self._get_playlist_from_id(self.player.get_playlist_id())
        playlist_name = utils.get_media_title(playlist)
        path = self._get_playlist_dbus_path(playlist)
        return (True, (path, playlist_name, ""))
Example #47
0
    def _get_metadata(self, media=None, index=None):
        song_dbus_path = self._get_song_dbus_path(media, index)
        if not self.player.props.current_song:
            return {
                'mpris:trackid': GLib.Variant('o', song_dbus_path)
            }

        if not media:
            media = self.player.props.current_song

        length = media.get_duration() * 1e6
        user_rating = 1.0 if media.get_favourite() else 0.0
        artist = utils.get_artist_name(media)

        metadata = {
            'mpris:trackid': GLib.Variant('o', song_dbus_path),
            'xesam:url': GLib.Variant('s', media.get_url()),
            'mpris:length': GLib.Variant('x', length),
            'xesam:trackNumber': GLib.Variant('i', media.get_track_number()),
            'xesam:useCount': GLib.Variant('i', media.get_play_count()),
            'xesam:userRating': GLib.Variant('d', user_rating),
            'xesam:title': GLib.Variant('s', utils.get_media_title(media)),
            'xesam:album': GLib.Variant('s', utils.get_album_title(media)),
            'xesam:artist': GLib.Variant('as', [artist]),
            'xesam:albumArtist': GLib.Variant('as', [artist])
        }

        genre = media.get_genre()
        if genre is not None:
            metadata['xesam:genre'] = GLib.Variant('as', [genre])

        last_played = media.get_last_played()
        if last_played is not None:
            last_played_str = last_played.format("%FT%T%:z")
            metadata['xesam:lastUsed'] = GLib.Variant('s', last_played_str)

        art_url = media.get_thumbnail()
        if art_url is not None:
            metadata['mpris:artUrl'] = GLib.Variant('s', art_url)

        return metadata
Example #48
0
    def _update_view(self, player):
        """Updates model when the song changes

        :param Player player: The main player object
        """
        current_song = player.props.current_song
        self._duration_label.set_label(
            utils.seconds_to_string(current_song.get_duration()))

        self._play_button.set_sensitive(True)
        self._sync_prev_next()

        artist = utils.get_artist_name(current_song)
        title = utils.get_media_title(current_song)

        self._title_label.props.label = title
        self._artist_label.props.label = artist

        self._tooltip.props.title = title
        self._tooltip.props.subtitle = artist

        self._cover_stack.update(current_song)
Example #49
0
    def _on_child_activated(self, widget, child, user_data=None):
        item = child.media_item

        if self.star_handler.star_renderer_click:
            self.star_handler.star_renderer_click = False
            return

        # Toggle the selection when in selection mode
        if self.selection_mode:
            child.check.set_active(not child.check.get_active())
            return

        title = utils.get_media_title(item)
        self._escaped_title = title
        self._artist = utils.get_artist_name(item)

        self._albumWidget.update(self._artist, title, item, self.header_bar, self.selection_toolbar)

        self.header_bar.set_state(ToolbarState.CHILD_VIEW)
        self.header_bar.header_bar.set_title(self._escaped_title)
        self.header_bar.header_bar.sub_title = self._artist
        self.set_visible_child(self._albumWidget)
Example #50
0
    def _update_model(self, player, playlist, current_iter):
        """Player changed callback.

        :param player: The player object
        :param playlist: The current playlist
        :param current_iter: The current iter of the playlist model
        """
        if playlist != self._model:
            return True

        current_song = playlist[current_iter][5]

        self._duration = 0

        song_passed = False
        _iter = playlist.get_iter_first()

        while _iter:
            song = playlist[_iter][5]
            song_widget = song.song_widget
            self._duration += song.get_duration()
            escaped_title = GLib.markup_escape_text(utils.get_media_title(song))

            if song == current_song:
                song_widget.now_playing_sign.show()
                song_widget.title.set_markup("<b>{}</b>".format(escaped_title))
                song_passed = True
            elif song_passed:
                song_widget.now_playing_sign.hide()
                song_widget.title.set_markup("<span>{}</span>".format(escaped_title))
            else:
                song_widget.now_playing_sign.hide()
                song_widget.title.set_markup("<span color='grey'>{}</span>".format(escaped_title))

            _iter = playlist.iter_next(_iter)

        self._builder.get_object("running_length_label_info").set_text(_("%d min") % (int(self._duration / 60) + 1))

        return True
Example #51
0
    def _add_playlist_to_sidebar(
            self, playlist, index=None, select_playlist=False):
        """Add a playlist to sidebar

        :param GrlMedia playlist: playlist to add
        :param int index: position
        """
        if index is None:
            index = -1
        if playlists.is_smart_playlist(playlist):
            index = 0

        title = utils.get_media_title(playlist)
        row = SidebarRow()
        row.props.text = title
        # FIXME: Passing the Grl.Media with the row object is ugly.
        row.playlist = playlist

        self._sidebar.insert(row, index)
        self._offset += 1

        if select_playlist:
            self._sidebar.select_row(row)
            row.emit('activate')
Example #52
0
    def update_model(self, player, playlist, currentIter):
        # this is not our playlist, return
        if playlist != self._model:
            # TODO, only clean once, but that can wait util we have clean
            # the code a bit, and until the playlist refactoring.
            # the overhead is acceptable for now
            self.clean_model()
            return False

        currentSong = playlist.get_value(currentIter, 5)
        song_passed = False
        itr = playlist.get_iter_first()

        while itr:
            song = playlist.get_value(itr, 5)
            song_widget = song.song_widget

            if not song_widget.can_be_played:
                itr = playlist.iter_next(itr)
                continue

            escaped_title = GLib.markup_escape_text(utils.get_media_title(song))
            if (song == currentSong):
                song_widget.now_playing_sign.show()
                song_widget.title.set_markup('<b>%s</b>' % escaped_title)
                song_passed = True
            elif (song_passed):
                song_widget.now_playing_sign.hide()
                song_widget.title.set_markup('<span>%s</span>' % escaped_title)
            else:
                song_widget.now_playing_sign.hide()
                song_widget.title.set_markup(
                    '<span color=\'grey\'>%s</span>' % escaped_title
                )
            itr = playlist.iter_next(itr)
        return False
Example #53
0
    def _create_song_widget(self, song):
        """Helper function to create a song widget for a
        single song

        :param song: A Grilo media item
        :returns: A complete song widget
        :rtype: Gtk.EventBox
        """
        song_widget = SongWidget(song)
        self._songs.append(song_widget)

        title = utils.get_media_title(song)

        itr = self._model.append(None)

        self._model[itr][0, 1, 2, 5, 6] = [title, '', '', song, False]

        song_widget.itr = itr
        song_widget.model = self._model
        song_widget.connect('button-release-event', self._song_activated)
        song_widget.connect('selection-changed', self._on_selection_changed)

        self.bind_property(
            'selection-mode', song_widget, 'selection-mode',
            GObject.BindingFlags.SYNC_CREATE)
        self.bind_property(
            'show-durations', song_widget, 'show-duration',
            GObject.BindingFlags.SYNC_CREATE)
        self.bind_property(
            'show-favorites', song_widget, 'show-favorite',
            GObject.BindingFlags.SYNC_CREATE)
        self.bind_property(
            'show-song-numbers', song_widget, 'show-song-number',
            GObject.BindingFlags.SYNC_CREATE)

        return song_widget
Example #54
0
    def _create_album_item(self, item):
        artist = utils.get_artist_name(item)
        title = utils.get_media_title(item)

        builder = Gtk.Builder.new_from_resource("/org/gnome/Music/AlbumCover.ui")

        child = Gtk.FlowBoxChild()
        child.image = builder.get_object("image")
        child.check = builder.get_object("check")
        child.title = builder.get_object("title")
        child.subtitle = builder.get_object("subtitle")
        child.events = builder.get_object("events")
        child.media_item = item

        child.title.set_label(title)
        child.subtitle.set_label(artist)

        child.image.set_from_surface(self._loading_icon_surface)
        # In the case of off-sized icons (eg. provided in the soundfile)
        # keep the size request equal to all other icons to get proper
        # alignment with GtkFlowBox.
        child.image.set_property("width-request", ArtSize.medium.width)
        child.image.set_property("height-request", ArtSize.medium.height)

        child.events.connect("button-release-event", self._on_album_event_triggered, child)

        child.check_handler_id = child.check.connect("notify::active", self._on_child_toggled, child)

        child.check.bind_property("visible", self, "selection_mode", GObject.BindingFlags.BIDIRECTIONAL)

        child.add(builder.get_object("main_box"))
        child.show()

        self.cache.lookup(item, ArtSize.medium, self._on_lookup_ready, child)

        return child
Example #55
0
    def _get_metadata(self, media=None):
        if not media:
            media = self.player.get_current_media()
        if not media:
            return {}

        metadata = {
            'mpris:trackid': GLib.Variant('o', self._get_media_id(media)),
            'xesam:url': GLib.Variant('s', media.get_url())
        }

        try:
            length = media.get_duration() * 1000000
            assert length is not None
            metadata['mpris:length'] = GLib.Variant('x', length)
        except:
            pass

        try:
            trackNumber = media.get_track_number()
            assert trackNumber is not None
            metadata['xesam:trackNumber'] = GLib.Variant('i', trackNumber)
        except:
            pass

        try:
            useCount = media.get_play_count()
            assert useCount is not None
            metadata['xesam:useCount'] = GLib.Variant('i', useCount)
        except:
            pass

        try:
            userRating = media.get_rating()
            assert userRating is not None
            metadata['xesam:userRating'] = GLib.Variant('d', userRating)
        except:
            pass

        try:
            title = utils.get_media_title(media)
            assert title is not None
            metadata['xesam:title'] = GLib.Variant('s', title)
        except:
            pass


        album = utils.get_album_title(media)
        metadata['xesam:album'] = GLib.Variant('s', album)

        artist = utils.get_artist_name(media)
        metadata['xesam:artist'] = GLib.Variant('as', [artist])
        metadata['xesam:albumArtist'] = GLib.Variant('as', [artist])

        try:
            genre = media.get_genre()
            assert genre is not None
            metadata['xesam:genre'] = GLib.Variant('as', genre)
        except:
            pass

        try:
            lastUsed = media.get_last_played()
            assert lastUsed is not None
            metadata['xesam:lastUsed'] = GLib.Variant('s', lastUsed)
        except:
            pass

        try:
            artUrl = media.get_thumbnail()
            assert artUrl is not None
            metadata['mpris:artUrl'] = GLib.Variant('s', artUrl)
        except:
            pass

        return metadata
Example #56
0
    def _add_item(self, source, param, item, remaining=0, data=None):
        if data is None:
            return

        model, category = data

        self.found_items_number = (
            self.model.iter_n_children(self.head_iters[0]) +
            self.model.iter_n_children(self.head_iters[1]) +
            self.model.iter_n_children(self.head_iters[2]) +
            self.model.iter_n_children(self.head_iters[3]))

        if category == 'song' and self.found_items_number == 0 and remaining == 0:
            if grilo.search_source:
                self.emit('no-music-found')

        # We need to remember the view before the search view
        if self.window.curr_view != self.window.views[5] and \
           self.window.prev_view != self.window.views[5]:
            self.previous_view = self.window.prev_view

        if remaining == 0:
            self.window.pop_loading_notification()
            self.view.show()

        if not item or model != self.model:
            return

        self._offset += 1
        title = utils.get_media_title(item)
        item.set_title(title)
        artist = utils.get_artist_name(item)
        # FIXME: Can't be None in treemodel
        composer = item.get_composer() or ""

        group = 3
        try:
            group = {'album': 0, 'artist': 1, 'song': 2}[category]
        except:
            pass

        # FIXME: HiDPI icon lookups return a surface that can't be
        # scaled by GdkPixbuf, so it results in a * scale factor sized
        # icon for the search view.
        _iter = None
        if category == 'album':
            _iter = self.model.insert_with_values(
                self.head_iters[group], -1,
                [0, 2, 3, 4, 5, 9, 11, 13],
                [str(item.get_id()), title, artist,
                 self._loading_icon, item, 2, category, composer])
            self.cache.lookup(item, ArtSize.small, self._on_lookup_ready, _iter)
        elif category == 'song':
            _iter = self.model.insert_with_values(
                self.head_iters[group], -1,
                [0, 2, 3, 4, 5, 9, 11, 13],
                [str(item.get_id()), title, artist,
                 self._loading_icon, item,
                 2 if source.get_id() != 'grl-tracker-source' \
                    else item.get_favourite(), category, composer])
            self.cache.lookup(item, ArtSize.small, self._on_lookup_ready, _iter)
        else:
            if not artist.casefold() in self._artists:
                _iter = self.model.insert_with_values(
                    self.head_iters[group], -1,
                    [0, 2, 4, 5, 9, 11, 13],
                    [str(item.get_id()), artist,
                     self._loading_icon, item, 2, category, composer])
                self.cache.lookup(item, ArtSize.small, self._on_lookup_ready,
                                  _iter)
                self._artists[artist.casefold()] = {'iter': _iter, 'albums': []}

            self._artists[artist.casefold()]['albums'].append(item)

        if self.model.iter_n_children(self.head_iters[group]) == 1:
            path = self.model.get_path(self.head_iters[group])
            path = self.filter_model.convert_child_path_to_path(path)
            self.view.get_generic_view().expand_row(path, False)