Esempio n. 1
0
    def _moveid(self, cmd_args):
        """
            Move id in playlist
            @syntax move track_id destination
            @param args as str
            @return msg as str
        """
        try:
            tracks_ids = Lp().playlists.get_tracks_ids(Type.MPD)
            arg = self._get_args(cmd_args)
            track_id = int(arg[0])
            orig = tracks_ids.index(track_id)
            dst = int(arg[1])
            del tracks_ids[orig]
            tracks_ids.insert(dst, track_id)

            Lp().playlists.clear(Type.MPD)
            tracks = []
            for track_id in tracks_ids:
                tracks.append(Track(track_id))
            Lp().player.set_user_playlist_by_id(Type.NONE)
            Lp().playlists.add_tracks(Type.MPD, tracks, False)
        except:
            pass
        return ""
Esempio n. 2
0
 def do_render(self, ctx, widget, background_area, cell_area, flags):
     if self.album == Type.NONE:
         return
     surface = Lp().art.get_album_artwork(Album(self.album),
                                          ArtSize.MEDIUM,
                                          widget.get_scale_factor())
     width = surface.get_width()
     height = surface.get_height()
     # If cover smaller than wanted size, translate
     translate_x = cell_area.x
     translate_y = cell_area.y
     wanted = ArtSize.MEDIUM * widget.get_scale_factor()
     if width < wanted:
         translate_x += (wanted - width) / 2
     if height < wanted:
         translate_y += (wanted - height) / 2
     ctx.translate(translate_x, translate_y)
     ctx.new_sub_path()
     radius = 2
     degrees = pi / 180
     ctx.arc(width + 2 - radius, radius,
             radius - 0.5, -90 * degrees, 0 * degrees)
     ctx.arc(width + 2 - radius, height + 2 - radius,
             radius - 0.5, 0 * degrees, 90 * degrees)
     ctx.arc(radius, height + 2 - radius,
             radius - 0.5, 90 * degrees, 180 * degrees)
     ctx.arc(radius, radius, radius - 0.5, 180 * degrees, 270 * degrees)
     ctx.close_path()
     ctx.set_line_width(1)
     ctx.fill()
     ctx.set_source_surface(surface, 1, 1)
     ctx.paint()
Esempio n. 3
0
 def _download_albums_art(self):
     """
         Download albums artwork (from queue)
         @thread safe
     """
     self._in_albums_download = True
     sql = Lp().db.get_cursor()
     while self._albums_queue:
         album_id = self._albums_queue.pop()
         album = Lp().albums.get_name(album_id)
         artist = Lp().albums.get_artist_name(album_id)
         pixbuf = self._get_album_art_spotify(artist, album)
         if pixbuf is None:
             pixbuf = self._get_album_art_itunes(artist, album)
         if pixbuf is None:
             pixbuf = self._get_album_art_lastfm(artist, album)
         if pixbuf is None:
             continue
         try:
                 Lp().art.save_album_artwork(pixbuf, album_id)
                 Lp().art.clean_album_cache(Album(album_id))
                 GLib.idle_add(Lp().art.album_artwork_update, album_id)
         except Exception as e:
             print("ArtDownloader::_download_albums_art: %s" % e)
     self._in_albums_download = False
     sql.close()
Esempio n. 4
0
 def _get_album_art_lastfm(self, artist, album):
     """
         Get album artwork from lastfm
         @param artist as string
         @param album as string
         @return pixbuf as GdkPixbuf.Pixbuf
         @tread safe
     """
     pixbuf = None
     if Lp().lastfm is not None:
         try:
             last_album = Lp().lastfm.get_album(artist, album)
             url = last_album.get_cover_image(4)
             if url is not None:
                 s = Gio.File.new_for_uri(url)
                 (status, data, tag) = s.load_contents()
                 if status:
                     stream = Gio.MemoryInputStream.new_from_data(data,
                                                                  None)
                     pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(
                                 stream, ArtSize.MONSTER,
                                 ArtSize.MONSTER,
                                 False,
                                 None)
         except Exception as e:
             print("ArtDownloader::_get_album_art_lastfm: %s" % e)
     return pixbuf
Esempio n. 5
0
    def _sort_items(self, model, itera, iterb, data):
        """
            Sort model
        """
        if not self._updating:
            return False

        a_index = model.get_value(itera, 0)
        b_index = model.get_value(iterb, 0)

        # Static vs static
        if a_index < 0 and b_index < 0:
            return a_index < b_index
        # Static entries always on top
        elif b_index < 0:
            return True
        # Static entries always on top
        if a_index < 0:
            return False
        # String comparaison for non static
        else:
            if self._is_artists:
                a = Lp().artists.get_sortname(a_index)
                b = Lp().artists.get_sortname(b_index)
            else:
                a = model.get_value(itera, 1)
                b = model.get_value(iterb, 1)
            return a.lower() > b.lower()
Esempio n. 6
0
 def __update_metadata(self):
     if self.__get_status() == 'Stopped':
         self.__metadata = {}
     else:
         if Lp().player.current_track.id >= 0:
             track_id = Lp().player.current_track.id
         else:
             track_id = randint(10000000, 90000000)
         self.__metadata['mpris:trackid'] = self.__get_media_id(track_id)
         track_number = Lp().player.current_track.number
         if track_number is None:
             track_number = 1
         self.__metadata['xesam:trackNumber'] = GLib.Variant('i',
                                                             track_number)
         self.__metadata['xesam:title'] = GLib.Variant(
                                             's',
                                             Lp().player.current_track.name)
         self.__metadata['xesam:album'] = GLib.Variant(
                                       's',
                                       Lp().player.current_track.album.name)
         self.__metadata['xesam:artist'] = GLib.Variant(
                                          'as',
                                          Lp().player.current_track.artists)
         self.__metadata['xesam:albumArtist'] = GLib.Variant(
                                    'as',
                                    Lp().player.current_track.album_artists)
         self.__metadata['mpris:length'] = GLib.Variant(
                               'x',
                               Lp().player.current_track.duration * 1000000)
         self.__metadata['xesam:genre'] = GLib.Variant(
                                           'as',
                                           Lp().player.current_track.genres)
         self.__metadata['xesam:url'] = GLib.Variant(
                                              's',
                                              Lp().player.current_track.uri)
         self.__metadata["xesam:userRating"] = GLib.Variant(
                             'd',
                             Lp().player.current_track.get_popularity() / 5)
         if Lp().player.current_track.id == Type.RADIOS:
             cover_path = Lp().art.get_radio_cache_path(
                  ", ".join(Lp().player.current_track.artists),
                  ArtSize.MONSTER)
         elif Lp().player.current_track.id == Type.EXTERNALS:
             cover_path = "/tmp/lollypop_mpris.jpg"
             pixbuf = Lp().art.pixbuf_from_tags(
                 GLib.filename_from_uri(Lp().player.current_track.uri)[0],
                 ArtSize.MONSTER)
             if pixbuf is not None:
                 pixbuf.savev(cover_path, "jpeg",
                              ["quality"], ["90"])
         else:
             cover_path = Lp().art.get_album_cache_path(
                 Lp().player.current_track.album, ArtSize.MONSTER)
         if cover_path is not None:
             self.__metadata['mpris:artUrl'] = GLib.Variant(
                                                     's',
                                                     "file://" + cover_path)
         elif 'mpris:artUrl' in self.__metadata:
             self.__metadata['mpris:artUrl'] = GLib.Variant('s', '')
Esempio n. 7
0
    def set_party(self, party):
        """
            Set party mode on if party is True
            Play a new random track if not already playing
            @param party as bool
        """
        if party == self._is_party:
            return
        self._is_party = party

        self.reset_history()
        self.context.genre_ids = {}

        if self.plugins1.rgvolume is not None and\
           self.plugins2.rgvolume is not None:
            if party:
                self.context.next = NextContext.NONE
                self.plugins1.rgvolume.props.album_mode = 0
                self.plugins2.rgvolume.props.album_mode = 0
            else:
                self.plugins1.rgvolume.props.album_mode = 1
                self.plugins2.rgvolume.props.album_mode = 1

        if party:
            self._external_tracks = []
            self.context.genre_ids = {}
            self.context.track_id = None
            party_ids = self.get_party_ids()
            if party_ids:
                self._albums = Lp().albums.get_party_ids(party_ids)
            else:
                self._albums = Lp().albums.get_ids()
            # We do not store genre_ids for ALL/POPULARS/...
            genre_ids = []
            for genre_id in party_ids:
                if genre_id > 0:
                    genre_ids.append(genre_id)
            # Set context for each album
            for album_id in self._albums:
                self.context.genre_ids[album_id] = genre_ids
                self.context.artist_ids[album_id] = []
            # Start a new song if not playing
            if (self.current_track.id in [None, Type.RADIOS])\
                    and self._albums:
                track_id = self._get_random()
                self.load(Track(track_id))
            elif not self.is_playing():
                self.play()
        else:
            # We need to put some context, take first available genre
            if self.current_track.id:
                self.set_albums(self.current_track.id,
                                [self.current_track.album_artist_id], [])
        self.emit('party-changed', party)
Esempio n. 8
0
 def get_party_ids(self):
     """
         Return party ids
         @return [ids as int]
     """
     party_settings = Lp().settings.get_value("party-ids")
     ids = []
     genre_ids = Lp().genres.get_ids()
     genre_ids.append(Type.POPULARS)
     genre_ids.append(Type.RECENTS)
     for setting in party_settings:
         if isinstance(setting, int) and setting in genre_ids:
             ids.append(setting)
     return ids
Esempio n. 9
0
    def __init__(self):
        """
            Init popover
        """
        Gtk.Popover.__init__(self)

        party_grid = Gtk.Grid()
        party_grid.set_property('margin-start', 10)
        party_grid.set_property('margin-end', 10)
        party_grid.set_property('margin-bottom', 5)
        party_grid.set_property('margin-top', 5)
        party_grid.set_column_spacing(10)
        party_grid.set_row_spacing(7)
        party_grid.show()
        scrolled = Gtk.ScrolledWindow()
        scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
        scrolled.add(party_grid)
        scrolled.show()
        self.add(scrolled)
        size = Lp().window.get_size()
        self.set_size_request(-1,
                              size[1]*0.6)

        genres = Lp().genres.get()
        genres.insert(0, (Type.POPULARS, _("Populars")))
        genres.insert(1, (Type.RECENTS, _("Recently added")))
        ids = Lp().player.get_party_ids()
        i = 0
        x = 0
        for genre_id, genre in genres:
            label = Gtk.Label()
            label.set_property('halign', Gtk.Align.START)
            label.set_ellipsize(Pango.EllipsizeMode.END)
            label.set_text(genre)
            label.set_tooltip_text(genre)
            label.show()
            switch = Gtk.Switch()
            if genre_id in ids:
                switch.set_state(True)
            switch.connect("state-set", self._on_switch_state_set, genre_id)
            switch.show()
            party_grid.attach(label, x, i, 1, 1)
            party_grid.attach(switch, x+1, i, 1, 1)
            if x == 0:
                x += 2
            else:
                label.set_property('margin-start', 15)
                i += 1
                x = 0
Esempio n. 10
0
 def _add_artist(self, scanner, artist_id, album_id):
     """
         Add artist to artist list
         @param scanner as CollectionScanner
         @param artist id as int
         @param album id as int
     """
     artist_name = Lp().artists.get_name(artist_id)
     if self._show_genres:
         genre_ids = Lp().albums.get_genre_ids(album_id)
         genre_ids.append(Type.ALL)
         if self._list_one.get_selected_id() in genre_ids:
             self._list_two.add_value((artist_id, artist_name))
     else:
         self._list_one.add_value((artist_id, artist_name))
Esempio n. 11
0
 def update_cover(self):
     """
         Update cover for album id id needed
     """
     if self._cover is None:
         return
     surface = Lp().art.get_album_artwork(
                         self._album,
                         ArtSize.BIG * self._cover.get_scale_factor())
     self._cover.set_from_surface(surface)
     if surface.get_height() > surface.get_width():
         self._overlay_orientation = Gtk.Orientation.VERTICAL
     else:
         self._overlay_orientation = Gtk.Orientation.HORIZONTAL
     del surface
Esempio n. 12
0
 def _test_lastfm_connection(self):
     """
         Test lastfm connection
         @thread safe
     """
     try:
         u = Lp().lastfm.get_authenticated_user()
         u.get_id()
         GLib.idle_add(self._test_img.set_from_icon_name,
                       'object-select-symbolic',
                       Gtk.IconSize.MENU)
     except:
         GLib.idle_add(self._test_img.set_from_icon_name,
                       'computer-fail-symbolic',
                       Gtk.IconSize.MENU)
Esempio n. 13
0
 def _update_metadata(self):
     if self._get_status() == 'Stopped':
         self._metadata = {}
     else:
         if Lp().player.current_track.id >= 0:
             self._metadata['mpris:trackid'] = dbus.ObjectPath(
                 '/org/lollypop/%s' % Lp().player.current_track.id)
         else:
             # MPRIS SUX
             track_id = randint(10000000, 90000000)
             self._metadata['mpris:trackid'] = dbus.ObjectPath(
                 '/org/lollypop/%s' % track_id)
         track_number = Lp().player.current_track.number
         if track_number is None:
             track_number = 1
         self._metadata['xesam:trackNumber'] = track_number
         self._metadata['xesam:title'] = Lp().player.current_track.name
         self._metadata['xesam:album'] = Lp(
                                           ).player.current_track.album.name
         self._metadata['xesam:artist'] = Lp().player.current_track.artists
         self._metadata['xesam:albumArtist'] = \
             ", ".join(Lp().player.current_track.album_artists)
         self._metadata['mpris:length'] = dbus.Int64(
             Lp().player.current_track.duration * 1000000)
         self._metadata['xesam:genre'] = Lp().player.current_track.genres\
             or "Web"
         self._metadata['xesam:url'] = Lp().player.current_track.uri
         self._metadata["xesam:userRating"] = \
             Lp().player.current_track.get_popularity() / 5
         if Lp().player.current_track.id == Type.RADIOS:
             cover_path = Lp().art.get_radio_cache_path(
                  ", ".join(Lp().player.current_track.artists),
                  ArtSize.MONSTER)
         elif Lp().player.current_track.id == Type.EXTERNALS:
             cover_path = "/tmp/lollypop_mpris.jpg"
             pixbuf = Lp().art.pixbuf_from_tags(
                 GLib.filename_from_uri(Lp().player.current_track.uri)[0],
                 ArtSize.MONSTER)
             if pixbuf is not None:
                 pixbuf.savev(cover_path, "jpeg",
                              ["quality"], ["90"])
         else:
             cover_path = Lp().art.get_album_cache_path(
                 Lp().player.current_track.album, ArtSize.MONSTER)
         if cover_path is not None:
             self._metadata['mpris:artUrl'] = "file://" + cover_path
         elif 'mpris:artUrl' in self._metadata:
             self._metadata['mpris:artUrl'] = ''
Esempio n. 14
0
 def set_cover(self):
     """
         Set cover for album if state changed
     """
     if self._cover is None:
         return
     surface = Lp().art.get_album_artwork(
                         self._album,
                         ArtSize.BIG * self._cover.get_scale_factor())
     self._cover.set_from_surface(surface)
     self._cover.set_size_request(100, 100)
     if surface.get_height() > surface.get_width():
         self._overlay_orientation = Gtk.Orientation.VERTICAL
     else:
         self._overlay_orientation = Gtk.Orientation.HORIZONTAL
     del surface
Esempio n. 15
0
class Disc:
    """
        Represent an album disc
    """

    def __init__(self, album, disc_number):
        self.db = Lp().albums
        self.album = album
        self.number = disc_number
        self._track_ids = []

    @property
    def track_ids(self):
        """
            Get all tracks ids of the disc

            @return list of int
        """
        if not self._track_ids:
            self._track_ids = self.db.get_disc_tracks(self.album.id,
                                                      self.album.genre_ids,
                                                      self.album.artist_ids,
                                                      self.number)
        return self._track_ids

    @property
    def tracks(self):
        """
            Get all tracks of the disc

            @return list of Track
        """
        return [Track(id) for id in self.track_ids]
Esempio n. 16
0
class Disc:
    """
        Represent an album disc
    """

    def __init__(self, album, disc_number):
        self.db = Lp().albums
        self.album = album
        self.number = disc_number
        self._track_ids = []

    @property
    def name(self):
        """
            Disc name
            @return disc name as str
        """

    @property
    def track_ids(self):
        """
            Get all tracks ids of the disc
            @return list of int
        """
        if not self._track_ids:
            self._track_ids = self.db.get_disc_tracks(self.album.id,
                                                      self.album.genre_ids,
                                                      self.album.artist_ids,
                                                      self.number)
            # If user tagged track with an artist not present in album
            if not self._track_ids:
                print("%s missing an album artist in artists" %
                      self.album.name)
                self._track_ids = self.db.get_disc_tracks(self.album.id,
                                                          self.album.genre_ids,
                                                          [],
                                                          self.number)
        return self._track_ids

    @property
    def tracks(self):
        """
            Get all tracks of the disc

            @return list of Track
        """
        return [Track(id) for id in self.track_ids]
Esempio n. 17
0
 def _on_map_wikia(self, widget, force=False):
     """
         Load on map
         @param widget as Gtk.Viewport
         @param force as bool
     """
     self._menu.hide()
     if self._current is None:
         self._current = self._get_current()
     artist = Lp().artists.get_name(self._current[0])
     title = Lp().tracks.get_name(self._current[2])
     Lp().settings.set_value('infoswitch',
                             GLib.Variant('s', 'wikia'))
     url = "http://lyrics.wikia.com/wiki/%s:%s" % (artist.replace(' ', '_'),
                                                   title.replace(' ', '_'))
     # Delayed load due to WebKit memory loading
     GLib.timeout_add(250, self._load_web, widget, url, True, True)
Esempio n. 18
0
 def _party_switch_state(self, widget, state, genre_id):
     """
         Update party ids when use change a switch in dialog
         @param widget as unused, state as widget state, genre id as int
     """
     ids = Lp().player.get_party_ids()
     if state:
         try:
             ids.append(genre_id)
         except:
             pass
     else:
         try:
             ids.remove(genre_id)
         except:
             pass
     Lp().settings.set_value('party-ids',  GLib.Variant('ai', ids))
Esempio n. 19
0
    def _on_current_changed(self, player):
        """
            Update notification with track_id infos
            @param player Player
        """
        if player.current_track.title == '':
            return
        state = Lp().window.get_window().get_state()
        app = Lp().window.get_application()
        if player.current_track.id is None or\
                state & Gdk.WindowState.FOCUSED or\
                app.is_fullscreen():
            return
        if player.current_track.id == Type.RADIOS:
            cover_path = Lp().art.get_radio_cache_path(
                player.current_track.artist, ArtSize.BIG)
        else:
            cover_path = Lp().art.get_album_cache_path(
                player.current_track.album, ArtSize.BIG)
        if cover_path is not None:
            self._notification.set_hint('image-path',
                                        GLib.Variant('s', cover_path))
        else:
            self._notification.set_hint('image-path',
                                        GLib.Variant('s', ''))

        if player.current_track.album.name == '':
            self._notification.update(
                player.current_track.title,
                # TRANSLATORS: by refers to the artist,
                _("by %s") %
                '<b>' + player.current_track.artist + '</b>',
                'lollypop')
        else:
            self._notification.update(
                player.current_track.title,
                # TRANSLATORS: by refers to the artist,
                # from to the album
                _("by %s, from %s") %
                ('<b>' + player.current_track.artist + '</b>',
                 '<i>' + player.current_track.album.name + '</i>'),
                'lollypop')
        try:
            self._notification.show()
        except:
            pass
Esempio n. 20
0
 def set_party_ids(self):
     """
         Set party mode ids
     """
     party_ids = self.get_party_ids()
     if party_ids:
         self._albums = Lp().albums.get_party_ids(party_ids)
     else:
         self._albums = Lp().albums.get_ids()
     # We do not store genre_ids for ALL/POPULARS/...
     genre_ids = []
     for genre_id in party_ids:
         if genre_id > 0:
             genre_ids.append(genre_id)
     # Set context for each album
     for album_id in self._albums:
         self._context.genre_ids[album_id] = genre_ids
         self._context.artist_ids[album_id] = []
Esempio n. 21
0
    def set_albums(self, track_id, artist_ids, genre_ids):
        """
            Set album list (for next/prev)
            @param track id as int
            @param artist id as int
            @param genre id as int
        """
        # Invalid track
        if track_id is None:
            return
        album = Track(track_id).album
        self._albums = []
        ShufflePlayer.reset_history(self)

        # We are not playing a user playlist anymore
        self._user_playlist = []
        self._user_playlist_id = None
        # We are in all artists
        if (genre_ids and genre_ids[0] == Type.ALL) or\
           (artist_ids and artist_ids[0] == Type.ALL):
            self._albums = Lp().albums.get_compilations()
            self._albums += Lp().albums.get_ids()
        # We are in populars view, add popular albums
        elif genre_ids and genre_ids[0] == Type.POPULARS:
            if self._shuffle in [Shuffle.TRACKS_ARTIST, Shuffle.ALBUMS_ARTIST]:
                self._albums = []
                self.next_track = Track()
                for album_id in Lp().albums.get_populars():
                    if Lp().albums.get_artist_id(album_id) == \
                            album.artist_id:
                        self._albums.append(album_id)
            else:
                self._albums = Lp().albums.get_populars()
        # We are in recents view, add recent albums
        elif genre_ids and genre_ids[0] == Type.RECENTS:
            self._albums = Lp().albums.get_recents()
        # We are in randoms view, add random albums
        elif genre_ids and genre_ids[0] == Type.RANDOMS:
            self._albums = Lp().albums.get_cached_randoms()
        # We are in compilation view without genre
        elif genre_ids and genre_ids[0] == Type.COMPILATIONS:
            self._albums = Lp().albums.get_compilations()
        # Random tracks/albums for artist
        elif self._shuffle in [Shuffle.TRACKS_ARTIST, Shuffle.ALBUMS_ARTIST]:
            self._albums = Lp().albums.get_ids([album.artist_id], genre_ids)
        # Add all albums for genre
        else:
            if not artist_ids:
                self._albums = Lp().albums.get_compilations(genre_ids)
            self._albums += Lp().albums.get_ids(artist_ids, genre_ids)

        album.set_genre(genre_ids)
        if track_id in album.tracks_ids:
            self.context.artist_ids = artist_ids
            self.context.genre_ids = genre_ids
            # Shuffle album list if needed
            self._shuffle_albums()
        else:  # Error
            self.stop()
Esempio n. 22
0
 def _populate(self):
     """
         Same as _populate_threaded()
         @thread safe
     """
     self._urls = Lp().art.get_duck_arts(self._name+"+logo+radio")
     if self._urls:
         self._add_pixbufs()
     else:
         GLib.idle_add(self._show_not_found)
Esempio n. 23
0
 def _get_album_art_lastfm(self, artist, album):
     """
         Get album artwork from lastfm
         @param artist as string
         @param album as string
         @return data as bytes
         @tread safe
     """
     image = None
     if Lp().lastfm is not None:
         try:
             last_album = Lp().lastfm.get_album(artist, album)
             url = last_album.get_cover_image(4)
             if url is not None:
                 s = Gio.File.new_for_uri(url)
                 (status, image, tag) = s.load_contents()
         except Exception as e:
             print("ArtDownloader::_get_album_art_lastfm: %s" % e)
     return image
Esempio n. 24
0
 def _populate(self):
     """
         Same as _populate_threaded()
         @thread safe
     """
     self._urls = Lp().art.get_google_arts(self._name + "+logo+radio", self._start)
     if self._urls:
         self._start += GOOGLE_INC
         self._add_pixbufs()
     else:
         GLib.idle_add(self._show_not_found)
Esempio n. 25
0
    def set_party(self, party):
        """
            Set party mode on if party is True
            Play a new random track if not already playing
            @param party as bool
        """
        self.reset_history()

        if self._rgvolume is not None:
            if party:
                self.context.next = NextContext.NONE
                self._rgvolume.props.album_mode = 0
            else:
                self._rgvolume.props.album_mode = 1

        self._is_party = party

        if party:
            self._external_tracks = []
            self.context.genre_ids = []
            self.context.track_id = None
            party_ids = self.get_party_ids()
            if party_ids:
                self._albums = Lp().albums.get_party_ids(party_ids)
            else:
                self._albums = Lp().albums.get_ids()

            # Start a new song if not playing
            if (self.current_track.id in [None, Type.RADIOS])\
                    and self._albums:
                track_id = self._get_random()
                self.load(Track(track_id))
            elif not self.is_playing():
                self.play()
        else:
            # We need to put some context, take first available genre
            if self.current_track.id:
                self.set_albums(self.current_track.id,
                                [self.current_track.album_artist_id], [])
        self.emit('party-changed', party)
        Lp().window.update_view()
Esempio n. 26
0
 def do_render(self, ctx, widget, background_area, cell_area, flags):
     size = ArtSize.MEDIUM * widget.get_scale_factor()
     surface = Lp().art.get_album_artwork(Album(self.album), size)
     width = surface.get_width()
     height = surface.get_height()
     ctx.translate(cell_area.x, cell_area.y)
     ctx.new_sub_path()
     radius = 2
     degrees = pi / 180
     ctx.arc(width + 2 - radius, radius,
             radius - 0.5, -90 * degrees, 0 * degrees)
     ctx.arc(width + 2 - radius, height + 2 - radius,
             radius - 0.5, 0 * degrees, 90 * degrees)
     ctx.arc(radius, height + 2 - radius,
             radius - 0.5, 90 * degrees, 180 * degrees)
     ctx.arc(radius, radius, radius - 0.5, 180 * degrees, 270 * degrees)
     ctx.close_path()
     ctx.set_line_width(1)
     ctx.fill()
     ctx.set_source_surface(surface, 1, 1)
     ctx.paint()
Esempio n. 27
0
    def _string_for_track_id(self, track_id, index=Type.NONE):
        """
            Get mpd protocol string for track id
            @param track id as int
            @param track index as int
            @return str
        """
        if track_id is None:
            msg = ""
        else:
            track = Track(track_id)
            if index == Type.NONE:
                index = 1
                if Lp().player.is_party():
                    tracks_ids = [Lp().player.prev_track.id,
                                  Lp().player.current_track.id,
                                  Lp().player.next_track.id]
                    index = tracks_ids.index(track_id)
                else:
                    tracks_ids = Lp().playlists.get_tracks_ids(Type.MPD)
                    try:
                        index = tracks_ids.index(track_id) + 1
                    except:
                        pass
            msg = "file: %s\nArtist: %s\nAlbum: %s\nAlbumArtist: %s\
\nTitle: %s\nDate: %s\nGenre: %s\nTime: %s\nId: %s\nPos: %s\nTrack: %s\n" % (
                     track.path,
                     track.artist,
                     track.album.name,
                     track.album_artist,
                     track.name,
                     track.album.year,
                     track.genre,
                     track.duration,
                     track.id,
                     index,
                     index)
        return msg
Esempio n. 28
0
 def __on_current_changed(self, player):
     """
         Send notification with track_id infos
         @param player Player
     """
     if player.current_track.title == '' or self.__inhibitor:
         self.__inhibitor = False
         return
     state = Lp().window.get_window().get_state()
     app = Lp().window.get_application()
     if player.current_track.id is None or\
             state & Gdk.WindowState.FOCUSED or\
             app.is_fullscreen():
         return
     if player.current_track.id == Type.RADIOS:
         cover_path = Lp().art.get_radio_cache_path(
             player.current_track.album_artists[0], ArtSize.BIG)
     else:
         cover_path = Lp().art.get_album_cache_path(
             player.current_track.album, ArtSize.BIG)
     if cover_path is None:
         cover_path = 'org.gnome.Lollypop'
     if player.current_track.album.name == '':
         self.__notification.show_new(
             player.current_track.title,
             # TRANSLATORS: by refers to the artist,
             _("by %s") %
             '<b>' + ", ".join(player.current_track.artists) + '</b>',
             cover_path)
     else:
         self.__notification.show_new(
             player.current_track.title,
             # TRANSLATORS: by refers to the artist,
             # from to the album
             _("by %s, from %s") %
             ('<b>' + ", ".join(player.current_track.artists) + '</b>',
              '<i>' + player.current_track.album.name + '</i>'),
             cover_path)
Esempio n. 29
0
 def _move(self, cmd_args):
     """
         Move range in playlist
         @syntax move position destination
         @param args as str
         @return msg as str
     """
     # TODO implement range
     tracks_ids = Lp().playlists.get_tracks_ids(Type.MPD)
     arg = self._get_args(cmd_args)
     orig = int(arg[0])
     dst = int(arg[1])
     if orig != dst:
         track_id = tracks_ids[orig]
         del tracks_ids[orig]
         tracks_ids.insert(dst, track_id)
         Lp().playlists.clear(Type.MPD, False)
         tracks = []
         for track_id in tracks_ids:
             tracks.append(Track(track_id))
         Lp().player.set_user_playlist_by_id(Type.NONE)
         Lp().playlists.add_tracks(Type.MPD, tracks, False)
     return ""
Esempio n. 30
0
 def exists_in_db(self):
     """
         Search if item exists in db
         @return bool
     """
     artist_ids = []
     for artist in self.artists:
         artist_id = Lp().artists.get_id(artist)
         artist_ids.append(artist_id)
     if self.is_track:
         for track_id in Lp().tracks.get_ids_for_name(self.name):
             db_artist_ids = Lp().tracks.get_artist_ids(track_id)
             union = list(set(artist_ids) & set(db_artist_ids))
             if union == db_artist_ids:
                 return True
     else:
         album_ids = Lp().albums.get_ids(artist_ids, [])
         album_ids += Lp().albums.get_ids(artist_ids, [Type.CHARTS])
         for album_id in album_ids:
             album_name = Lp().albums.get_name(album_id)
             if album_name.lower() == self.album_name.lower():
                 return True
     return False
Esempio n. 31
0
    def __add2db(self, uri, mtime):
        """
            Add new file to db with information
            @param uri as string
            @param mtime as int
            @return track id as int
        """
        f = Lio.File.new_for_uri(uri)
        debug("CollectionScanner::add2db(): Read tags")
        info = self.get_info(uri)
        tags = info.get_tags()
        name = f.get_basename()
        title = self.get_title(tags, name)
        artists = self.get_artists(tags)
        composers = self.get_composers(tags)
        performers = self.get_performers(tags)
        a_sortnames = self.get_artist_sortnames(tags)
        aa_sortnames = self.get_album_artist_sortnames(tags)
        album_artists = self.get_album_artist(tags)
        album_name = self.get_album_name(tags)
        genres = self.get_genres(tags)
        discnumber = self.get_discnumber(tags)
        discname = self.get_discname(tags)
        tracknumber = self.get_tracknumber(tags, name)
        year = self.get_original_year(tags)
        if year is None:
            year = self.get_year(tags)
        duration = int(info.get_duration()/1000000000)

        # If no artists tag, use album artist
        if artists == "":
            artists = album_artists
        # if artists is always null, no album artists too,
        # use composer/performer
        if artists == "":
            artists = performers
            album_artists = composers
            if artists == "":
                artists = album_artists
            if artists == "":
                artists = _("Unknown")

        debug("CollectionScanner::add2db(): Restore stats")
        # Restore stats
        (track_pop, track_rate, track_ltime, album_mtime,
         loved, album_pop, album_rate) = self.__history.get(name, duration)
        # If nothing in stats, use track mtime
        if album_mtime == 0:
            album_mtime = mtime

        debug("CollectionScanner::add2db(): Add artists %s" % artists)
        artist_ids = self.add_artists(artists, album_artists, a_sortnames)

        debug("CollectionScanner::add2db(): "
              "Add album artists %s" % album_artists)
        album_artist_ids = self.add_album_artists(album_artists, aa_sortnames)

        new_artist_ids = list(set(album_artist_ids) | set(artist_ids))

        debug("CollectionScanner::add2db(): Add album: "
              "%s, %s" % (album_name, album_artist_ids))
        (album_id, new_album) = self.add_album(album_name, album_artist_ids,
                                               uri, loved, album_pop,
                                               album_rate, False)

        genre_ids = self.add_genres(genres)

        # Add track to db
        debug("CollectionScanner::add2db(): Add track")
        track_id = Lp().tracks.add(title, uri, duration,
                                   tracknumber, discnumber, discname,
                                   album_id, year, track_pop, track_rate,
                                   track_ltime)

        debug("CollectionScanner::add2db(): Update tracks")
        self.update_track(track_id, artist_ids, genre_ids, mtime)
        self.update_album(album_id, album_artist_ids,
                          genre_ids, album_mtime, year)
        if new_album:
            with SqlCursor(Lp().db) as sql:
                sql.commit()
        for genre_id in genre_ids:
            GLib.idle_add(self.emit, "genre-updated", genre_id, True)
        for artist_id in new_artist_ids:
            GLib.idle_add(self.emit, "artist-updated", artist_id, True)
        return track_id
Esempio n. 32
0
    def __copy_to_device(self, playlists):
        """
            Copy file from playlist to device
            @param playlists as [str]
        """
        for playlist in playlists:
            m3u = None
            stream = None
            if playlist != Type.NONE:
                try:
                    playlist_name = Lp().playlists.get_name(playlist)
                    # Create playlist
                    m3u = Gio.File.new_for_path("/tmp/lollypop_%s.m3u" %
                                                (playlist_name, ))
                    self.__retry(
                        m3u.replace_contents,
                        (b'#EXTM3U\n', None, False,
                         Gio.FileCreateFlags.REPLACE_DESTINATION, None))
                    stream = m3u.open_readwrite(None)
                except Exception as e:
                    print("DeviceWidget::_copy_to_device(): %s" % e)
            # Get tracks
            if playlist == Type.NONE:
                track_ids = []
                album_ids = Lp().albums.get_synced_ids()
                for album_id in album_ids:
                    track_ids += Lp().albums.get_track_ids(album_id)
            else:
                track_ids = Lp().playlists.get_track_ids(playlist)
            # Start copying
            for track_id in track_ids:
                if track_id is None:
                    continue
                if not self._syncing:
                    self._fraction = 1.0
                    self.__in_thread = False
                    return
                track = Track(track_id)
                if not track.uri.startswith('file:'):
                    continue
                album_name = escape(track.album_name.lower())
                is_compilation = track.album.artist_ids[0] == Type.COMPILATIONS
                if is_compilation:
                    on_device_album_uri = "%s/%s" %\
                                          (self._uri,
                                           album_name)
                else:
                    artists = escape(", ".join(track.album.artists).lower())
                    on_device_album_uri = "%s/%s_%s" %\
                                          (self._uri,
                                           artists,
                                           album_name)

                d = Gio.File.new_for_uri(on_device_album_uri)
                if not d.query_exists(None):
                    self.__retry(d.make_directory_with_parents, (None, ))
                # Copy album art
                art = Lp().art.get_album_artwork_path(track.album)
                if art is not None:
                    src_art = Gio.File.new_for_path(art)
                    art_uri = "%s/cover.jpg" % on_device_album_uri
                    self.__copied_art_uris.append(art_uri)
                    dst_art = Gio.File.new_for_uri(art_uri)
                    if not dst_art.query_exists(None):
                        self.__retry(
                            src_art.copy,
                            (dst_art, Gio.FileCopyFlags.OVERWRITE, None, None))

                filepath = GLib.filename_from_uri(track.uri)[0]
                track_name = escape(GLib.path_get_basename(filepath))
                # Check extension, if not mp3, convert
                ext = os.path.splitext(filepath)[1]
                if (ext != ".mp3" or self.__normalize) and self.__convert:
                    convertion_needed = True
                    track_name = track_name.replace(ext, ".mp3")
                else:
                    convertion_needed = False
                src_track = Gio.File.new_for_uri(track.uri)
                info = src_track.query_info('time::modified',
                                            Gio.FileQueryInfoFlags.NONE, None)
                # Prefix track with mtime to make sure updating it later
                mtime = info.get_attribute_as_string('time::modified')
                dst_uri = "%s/%s_%s" % (on_device_album_uri, mtime, track_name)
                if stream is not None:
                    if is_compilation:
                        line = "%s/%s_%s\n" %\
                                (album_name,
                                 mtime,
                                 track_name)
                    else:
                        line = "%s_%s/%s_%s\n" %\
                                (artists,
                                 album_name,
                                 mtime,
                                 track_name)
                    self.__retry(stream.get_output_stream().write,
                                 (line.encode(encoding='UTF-8'), None))
                dst_track = Gio.File.new_for_uri(dst_uri)
                if not dst_track.query_exists(None):
                    if convertion_needed:
                        mp3_uri = "file:///tmp/%s" % track_name
                        mp3_file = Gio.File.new_for_uri(mp3_uri)
                        pipeline = self.__convert_to_mp3(src_track, mp3_file)
                        # Check if encoding is finished
                        if pipeline is not None:
                            bus = pipeline.get_bus()
                            bus.add_signal_watch()
                            bus.connect('message::eos', self.__on_bus_eos)
                            self.__encoding = True
                            while self.__encoding and self._syncing:
                                sleep(1)
                            bus.disconnect_by_func(self.__on_bus_eos)
                            pipeline.set_state(Gst.State.PAUSED)
                            pipeline.set_state(Gst.State.READY)
                            pipeline.set_state(Gst.State.NULL)
                            self.__retry(
                                mp3_file.move,
                                (dst_track, Gio.FileCopyFlags.OVERWRITE, None,
                                 None))
                            # To be sure
                            try:
                                mp3_file.delete(None)
                            except:
                                pass
                    else:
                        self.__retry(src_track.copy,
                                     (dst_track, Gio.FileCopyFlags.OVERWRITE,
                                      None, None))
                else:
                    self.__done += 1
                self.__done += 1
                self._fraction = self.__done / self.__total
            if stream is not None:
                stream.close()
            if m3u is not None:
                playlist_name = escape(playlist_name)
                dst = Gio.File.new_for_uri(self._uri + '/' + playlist_name +
                                           '.m3u')
                self.__retry(m3u.move,
                             (dst, Gio.FileCopyFlags.OVERWRITE, None, None))
Esempio n. 33
0
 def _on_action_press_event(self, widget, event):
     """
         Append album to current list if not present
         Remove it if present
         @param: widget as Gtk.EventBox
         @param: event as Gdk.Event
     """
     if Lp().player.locked:
         return True
     if Lp().player.has_album(self._album):
         if Lp().player.current_track.album.id == self._album.id:
             # If not last album, skip it
             if len(Lp().player.get_albums()) > 1:
                 Lp().player.skip_album()
                 Lp().player.remove_album(self._album)
             # remove it and stop playback by going to next track
             else:
                 Lp().player.remove_album(self._album)
                 Lp().player.set_next()
                 Lp().player.next()
         else:
             Lp().player.remove_album(self._album)
         self._show_append(True)
     else:
         if Lp().player.is_playing() and not Lp().player.get_albums():
             Lp().player.play_album(self._album)
         else:
             Lp().player.add_album(self._album)
         self._show_append(False)
     return True
Esempio n. 34
0
 def _on_next_btn_clicked(self, button):
     """
         Next track on next button clicked
         @param button as Gtk.Button
     """
     Lp().player.next()
Esempio n. 35
0
 def __on_volume_changed(self, player, data=None):
     self.PropertiesChanged(self.__MPRIS_PLAYER_IFACE,
                            {'Volume': GLib.Variant('d',
                             Lp().player.volume), },
                            [])
Esempio n. 36
0
 def __disable_react_to_playback(self):
     if self.__status_handler_id is not None:
         Lp().player.disconnect(self.__status_handler_id)
Esempio n. 37
0
 def Next(self):
     if Lp().notify is not None:
         Lp().notify.inhibit()
     Lp().player.next()
Esempio n. 38
0
    def __scan(self, uris):
        """
            Scan music collection for music files
            @param uris as [string], uris to scan
            @thread safe
        """
        if self.__history is None:
            self.__history = History()
        mtimes = Lp().tracks.get_mtimes()
        (new_tracks, new_dirs, ignore_dirs) = self.__get_objects_for_uris(
                                                                         uris)
        orig_tracks = Lp().tracks.get_uris(ignore_dirs)
        was_empty = len(orig_tracks) == 0

        if ignore_dirs:
            if Lp().notify is not None:
                Lp().notify.send(_("Lollypop is detecting an empty folder."),
                                 _("Check your music settings."))
        count = len(new_tracks) + len(orig_tracks)
        # Add monitors on dirs
        if self.__inotify is not None:
            for d in new_dirs:
                if d.startswith("file://"):
                    self.__inotify.add_monitor(d)

        with SqlCursor(Lp().db) as sql:
            i = 0
            # Look for new files/modified files
            try:
                to_add = []
                for uri in new_tracks:
                    if self.__thread is None:
                        return
                    try:
                        GLib.idle_add(self.__update_progress, i, count)
                        f = Lio.File.new_for_uri(uri)
                        info = f.query_info("time::modified",
                                            Gio.FileQueryInfoFlags.NONE,
                                            None)
                        mtime = int(info.get_attribute_as_string(
                                                             "time::modified"))
                        # If songs exists and mtime unchanged, continue,
                        # else rescan
                        if uri in orig_tracks:
                            orig_tracks.remove(uri)
                            i += 1
                            if mtime <= mtimes.get(uri, mtime + 1):
                                i += 1
                                continue
                            else:
                                self.__del_from_db(uri)
                        # On first scan, use modification time
                        # Else, use current time
                        if not was_empty:
                            mtime = int(time())
                        to_add.append((uri, mtime))
                    except Exception as e:
                        print("CollectionScanner::__scan(mtime):", e)
                # Clean deleted files
                # Now because we need to populate history
                for uri in orig_tracks:
                    i += 1
                    GLib.idle_add(self.__update_progress, i, count)
                    self.__del_from_db(uri)
                # Add files to db
                for (uri, mtime) in to_add:
                    try:
                        debug("Adding file: %s" % uri)
                        i += 1
                        GLib.idle_add(self.__update_progress, i, count)
                        self.__add2db(uri, mtime)
                    except Exception as e:
                        print("CollectionScanner::__scan(add):", e, uri)
                sql.commit()
            except Exception as e:
                print("CollectionScanner::__scan():", e)
        GLib.idle_add(self.__finish)
        del self.__history
        self.__history = None
Esempio n. 39
0
 def Pause(self):
     Lp().player.pause()
Esempio n. 40
0
 def __update_progress(self, current, total):
     """
         Update progress bar status
         @param scanned items as int, total items as int
     """
     Lp().window.progress.set_fraction(current / total, self)
Esempio n. 41
0
 def load():
     artists = Lp().artists.get(genre_ids)
     compilations = Lp().albums.get_compilation_ids(genre_ids)
     return (artists, compilations)
Esempio n. 42
0
    def do(self, search_items):
        """
            Return tracks containing name
            @param search items as [str]
            @return tracks as [SearchItem]
        """
        self.__stop = False
        # Local search
        added_album_ids = []
        added_track_ids = []
        for item in search_items:
            if self.__stop:
                return
            albums = []
            tracks_non_album_artist = []
            # Get all albums for all artists and non album_artist tracks
            for artist_id in Lp().artists.search(item):
                if self.__stop:
                    return
                for album_id in Lp().albums.get_ids([artist_id], []):
                    if (album_id, artist_id) not in albums:
                        albums.append((album_id, artist_id))
                for track_id, track_name in Lp(
                ).tracks.get_as_non_album_artist(artist_id):
                    tracks_non_album_artist.append((track_id, track_name))

            for album_id, artist_id in albums:
                if self.__stop:
                    return
                if album_id in added_album_ids:
                    continue
                search_item = SearchItem()
                search_item.id = album_id
                added_album_ids.append(album_id)
                search_item.is_track = False
                search_item.artist_ids = [artist_id]
                search_item.year = Lp().albums.get_year(album_id)
                self._items.append(search_item)
                GLib.idle_add(self.emit, 'item-found')

            try:
                year = int(item)
                albums = Lp().albums.get_by_year(year)
            except:
                albums = []
            albums += Lp().albums.search(item)
            for album_id in albums:
                if self.__stop:
                    return
                if album_id in added_album_ids:
                    continue
                search_item = SearchItem()
                search_item.id = album_id
                added_album_ids.append(album_id)
                search_item.is_track = False
                search_item.artist_ids = Lp().albums.get_artist_ids(album_id)
                search_item.year = Lp().albums.get_year(album_id)
                self._items.append(search_item)
                GLib.idle_add(self.emit, 'item-found')

            for track_id, track_name in Lp().tracks.search(
                    item) + tracks_non_album_artist:
                if self.__stop:
                    return
                if track_id in added_track_ids:
                    continue
                search_item = SearchItem()
                search_item.id = track_id
                added_track_ids.append(track_id)
                search_item.is_track = True
                search_item.artist_ids = Lp().tracks.get_artist_ids(track_id)
                self._items.append(search_item)
                GLib.idle_add(self.emit, 'item-found')
        self._finished = True
        GLib.idle_add(self.emit, 'item-found')
Esempio n. 43
0
    def __init__(self, parent):
        """
            Init widget
            @param device as Device
            @param parent as Gtk.Widget
        """
        Gtk.Bin.__init__(self)
        MtpSync.__init__(self)
        self.__parent = parent
        self.__stop = False
        self._uri = None

        builder = Gtk.Builder()
        builder.add_from_resource('/org/gnome/Lollypop/DeviceManagerWidget.ui')
        widget = builder.get_object('widget')
        self.__error_label = builder.get_object('error-label')
        self.__switch_albums = builder.get_object('switch_albums')
        self.__switch_albums.set_state(Lp().settings.get_value('sync-albums'))
        self.__switch_mp3 = builder.get_object('switch_mp3')
        self.__switch_normalize = builder.get_object('switch_normalize')
        if not self._check_encoder_status():
            self.__switch_mp3.set_sensitive(False)
            self.__switch_normalize.set_sensitive(False)
            self.__switch_mp3.set_tooltip_text(
                _("You need to install " + "gstreamer-plugins-ugly"))
        else:
            self.__switch_mp3.set_state(Lp().settings.get_value('convert-mp3'))
        self.__menu_items = builder.get_object('menu-items')
        self.__menu = builder.get_object('menu')

        self.__model = Gtk.ListStore(bool, str, int)

        self.__selection_list = SelectionList(False)
        self.__selection_list.connect('item-selected', self.__on_item_selected)
        widget.attach(self.__selection_list, 1, 1, 1, 1)
        self.__selection_list.set_hexpand(True)

        self.__view = builder.get_object('view')
        self.__view.set_model(self.__model)

        builder.connect_signals(self)

        self.add(widget)

        self.__infobar = builder.get_object('infobar')
        self.__infobar_label = builder.get_object('infobarlabel')

        renderer0 = Gtk.CellRendererToggle()
        renderer0.set_property('activatable', True)
        renderer0.connect('toggled', self.__on_item_toggled)
        column0 = Gtk.TreeViewColumn(" ✓", renderer0, active=0)
        column0.set_clickable(True)
        column0.connect('clicked', self.__on_column0_clicked)

        renderer1 = CellRendererAlbum()
        self.__column1 = Gtk.TreeViewColumn("", renderer1, album=2)

        renderer2 = Gtk.CellRendererText()
        renderer2.set_property('ellipsize-set', True)
        renderer2.set_property('ellipsize', Pango.EllipsizeMode.END)
        self.__column2 = Gtk.TreeViewColumn("", renderer2, markup=1)
        self.__column2.set_expand(True)

        self.__view.append_column(column0)
        self.__view.append_column(self.__column1)
        self.__view.append_column(self.__column2)
Esempio n. 44
0
    def __remove_from_device(self, playlists):
        """
            Delete files not available in playlist
        """
        track_uris = []
        track_ids = []

        # Get tracks
        if playlists and playlists[0] == Type.NONE:
            track_ids = []
            album_ids = Lp().albums.get_synced_ids()
            for album_id in album_ids:
                track_ids += Lp().albums.get_track_ids(album_id)
        else:
            for playlist in playlists:
                track_ids += Lp().playlists.get_track_ids(playlist)

        # Get tracks uris
        for track_id in track_ids:
            if not self._syncing:
                self._fraction = 1.0
                self.__in_thread = False
                return
            track = Track(track_id)
            if not track.uri.startswith('file:'):
                continue
            album_name = escape(track.album_name.lower())
            if track.album.artist_ids[0] == Type.COMPILATIONS:
                on_device_album_uri = "%s/%s" % (self._uri, album_name)
            else:
                artists = escape(", ".join(track.album.artists).lower())
                on_device_album_uri = "%s/%s_%s" % (self._uri, artists,
                                                    album_name)
            filepath = GLib.filename_from_uri(track.uri)[0]
            track_name = escape(GLib.path_get_basename(filepath))
            # Check extension, if not mp3, convert
            ext = os.path.splitext(filepath)[1]
            if ext != ".mp3" and self.__convert:
                track_name = track_name.replace(ext, ".mp3")
            on_disk = Gio.File.new_for_path(filepath)
            info = on_disk.query_info('time::modified',
                                      Gio.FileQueryInfoFlags.NONE, None)
            # Prefix track with mtime to make sure updating it later
            mtime = info.get_attribute_as_string('time::modified')
            dst_uri = "%s/%s_%s" % (on_device_album_uri, mtime, track_name)
            track_uris.append(dst_uri)

        on_mtp_files = self.__get_track_files()

        # Delete file on device and not in playlists
        for uri in on_mtp_files:
            if not self._syncing:
                self._fraction = 1.0
                self.__in_thread = False
                return

            if uri not in track_uris and uri not in self.__copied_art_uris:
                to_delete = Gio.File.new_for_uri(uri)
                self.__retry(to_delete.delete, (None, ))
            self.__done += 1
            self._fraction = self.__done / self.__total
Esempio n. 45
0
 def Previous(self):
     if Lp().notify is not None:
         Lp().notify.inhibit()
     Lp().player.prev()
Esempio n. 46
0
 def __del_from_db(self, uri):
     """
         Delete track from db
         @param uri as str
     """
     try:
         f = Lio.File.new_for_uri(uri)
         name = f.get_basename()
         track_id = Lp().tracks.get_id_by_uri(uri)
         album_id = Lp().tracks.get_album_id(track_id)
         genre_ids = Lp().tracks.get_genre_ids(track_id)
         album_artist_ids = Lp().albums.get_artist_ids(album_id)
         artist_ids = Lp().tracks.get_artist_ids(track_id)
         popularity = Lp().tracks.get_popularity(track_id)
         rate = Lp().tracks.get_rate(track_id)
         ltime = Lp().tracks.get_ltime(track_id)
         mtime = Lp().albums.get_mtime(album_id)
         duration = Lp().tracks.get_duration(track_id)
         album_popularity = Lp().albums.get_popularity(album_id)
         album_rate = Lp().albums.get_rate(album_id)
         loved = Lp().albums.get_loved(album_id)
         uri = Lp().tracks.get_uri(track_id)
         self.__history.add(name, duration, popularity, rate,
                            ltime, mtime, loved, album_popularity,
                            album_rate)
         Lp().tracks.remove(track_id)
         Lp().tracks.clean(track_id)
         deleted = Lp().albums.clean(album_id)
         if deleted:
             with SqlCursor(Lp().db) as sql:
                 sql.commit()
             GLib.idle_add(self.emit, "album-updated", album_id, True)
         for artist_id in album_artist_ids + artist_ids:
             Lp().artists.clean(artist_id)
             GLib.idle_add(self.emit, "artist-updated", artist_id, False)
         for genre_id in genre_ids:
             Lp().genres.clean(genre_id)
             GLib.idle_add(self.emit, "genre-updated", genre_id, False)
     except Exception as e:
         print("CollectionScanner::__del_from_db:", e)
Esempio n. 47
0
 def _on_volume_changed(self, player, data=None):
     self.PropertiesChanged(self.MPRIS_PLAYER_IFACE,
                            {'Volume': dbus.Double(
                             Lp().player.volume), },
                            [])
Esempio n. 48
0
 def populate(self):
     """
         Populate widget content
     """
     self.get_style_context().remove_class('loading')
     self.set_sensitive(True)
     self.set_property('has-tooltip', True)
     self.connect('query-tooltip', self.__on_query_tooltip)
     row_widget = Gtk.EventBox()
     row_widget.set_property('valign', Gtk.Align.CENTER)
     row_widget.set_margin_top(self.__MARGIN)
     row_widget.set_margin_end(self.__MARGIN)
     grid = Gtk.Grid()
     grid.set_column_spacing(8)
     if self.__album.artists:
         artists = escape(", ".join(self.__album.artists))
     else:
         artists = _("Compilation")
     self.__artist_label = Gtk.Label.new("<b>%s</b>" % artists)
     self.__artist_label.set_use_markup(True)
     self.__artist_label.set_hexpand(True)
     self.__artist_label.set_property('halign', Gtk.Align.START)
     self.__artist_label.set_ellipsize(Pango.EllipsizeMode.END)
     self.__title_label = Gtk.Label.new(self.__album.name)
     self.__title_label.set_ellipsize(Pango.EllipsizeMode.END)
     cover = Gtk.Image()
     cover.get_style_context().add_class('small-cover-frame')
     surface = Lp().art.get_album_artwork(self.__album, ArtSize.MEDIUM,
                                          self.get_scale_factor())
     cover.set_from_surface(surface)
     cover.set_size_request(ArtSize.MEDIUM, ArtSize.MEDIUM)
     del surface
     self.__play_indicator = Gtk.Image.new_from_icon_name(
         'media-playback-start-symbolic', Gtk.IconSize.MENU)
     delete_button = Gtk.Button.new_from_icon_name('user-trash-symbolic',
                                                   Gtk.IconSize.MENU)
     # Here a hack to make old Gtk version support min-height css attribute
     # min-height = 24px, borders = 2px
     delete_button.set_property('height-request', 26)
     delete_button.get_image().set_opacity(0.2)
     delete_button.set_relief(Gtk.ReliefStyle.NONE)
     delete_button.get_style_context().add_class('menu-button')
     delete_button.get_style_context().add_class('track-menu-button')
     delete_button.set_property('valign', Gtk.Align.CENTER)
     delete_button.connect('clicked', self.__on_delete_clicked)
     vgrid = Gtk.Grid()
     vgrid.set_column_spacing(5)
     vgrid.add(self.__play_indicator)
     vgrid.add(self.__title_label)
     grid.attach(self.__artist_label, 1, 0, 1, 1)
     grid.attach(delete_button, 2, 0, 1, 2)
     grid.attach(cover, 0, 0, 1, 2)
     grid.attach(vgrid, 1, 1, 1, 1)
     row_widget.add(grid)
     self.add(row_widget)
     self.get_style_context().add_class('trackrow')
     self.show_play_indicator(
         self.__album.id == Lp().player.current_track.album.id)
     self.show_all()
     self.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, [],
                          Gdk.DragAction.MOVE)
     self.drag_source_add_text_targets()
     self.drag_dest_set(Gtk.DestDefaults.DROP | Gtk.DestDefaults.MOTION, [],
                        Gdk.DragAction.MOVE)
     self.drag_dest_add_text_targets()
     self.connect('drag-begin', self.__on_drag_begin)
     self.connect('drag-data-get', self.__on_drag_data_get)
     self.connect('drag-data-received', self.__on_drag_data_received)
     self.connect('drag-motion', self.__on_drag_motion)
     self.connect('drag-leave', self.__on_drag_leave)
Esempio n. 49
0
 def _update_metadata(self):
     if self._get_status() == 'Stopped':
         self._metadata = {}
     else:
         if Lp().player.current_track.id >= 0:
             self._metadata['mpris:trackid'] = dbus.ObjectPath(
                 '/org/lollypop/%s' % Lp().player.current_track.id)
         else:
             # MPRIS SUX
             track_id = randint(10000000, 90000000)
             self._metadata['mpris:trackid'] = dbus.ObjectPath(
                 '/org/lollypop/%s' % track_id)
         track_number = Lp().player.current_track.number
         if track_number is None:
             track_number = 1
         self._metadata['xesam:trackNumber'] = track_number
         self._metadata['xesam:title'] = Lp().player.current_track.name
         self._metadata['xesam:album'] = Lp(
                                           ).player.current_track.album.name
         self._metadata['xesam:artist'] = Lp().player.current_track.artists
         self._metadata['xesam:albumArtist'] = \
             ", ".join(Lp().player.current_track.album_artists)
         self._metadata['mpris:length'] = dbus.Int64(
             Lp().player.current_track.duration * 1000000)
         self._metadata['xesam:genre'] = Lp().player.current_track.genres\
             or "Web"
         self._metadata['xesam:url'] = Lp().player.current_track.uri
         rate = Lp().player.current_track.get_rate()
         if rate == Type.NONE:
             rate = Lp().player.current_track.get_popularity()
         self._metadata["xesam:userRating"] = dbus.Double(rate / 5)
         if Lp().player.current_track.id == Type.RADIOS:
             cover_path = Lp().art.get_radio_cache_path(
                  ", ".join(Lp().player.current_track.artists),
                  ArtSize.MONSTER)
         elif Lp().player.current_track.id == Type.EXTERNALS:
             cover_path = "/tmp/lollypop_mpris.jpg"
             pixbuf = Lp().art.pixbuf_from_tags(
                 GLib.filename_from_uri(Lp().player.current_track.uri)[0],
                 ArtSize.MONSTER)
             if pixbuf is not None:
                 pixbuf.savev(cover_path, "jpeg",
                              ["quality"], ["90"])
         else:
             cover_path = Lp().art.get_album_cache_path(
                 Lp().player.current_track.album, ArtSize.MONSTER)
         if cover_path is not None:
             self._metadata['mpris:artUrl'] = "file://" + cover_path
         elif 'mpris:artUrl' in self._metadata:
             self._metadata['mpris:artUrl'] = ''
Esempio n. 50
0
 def load():
     genres = Lp().genres.get()
     return genres
Esempio n. 51
0
 def Set(self, interface, property_name, new_value):
     if property_name == 'Volume':
         Lp().player.set_volume(new_value)
Esempio n. 52
0
 def load():
     artists = Lp().artists.get_local()
     compilations = Lp().albums.get_compilation_ids()
     return (artists, compilations)
Esempio n. 53
0
 def _on_prev_btn_clicked(self, button):
     """
         Previous track on prev button clicked
         @param button as Gtk.Button
     """
     Lp().player.prev()
Esempio n. 54
0
 def SetPosition(self, track_id, position):
     Lp().player.seek(position/1000000)
Esempio n. 55
0
 def __update_metadata(self):
     if self.__get_status() == 'Stopped':
         self.__metadata = {}
     else:
         if Lp().player.current_track.id >= 0:
             track_id = Lp().player.current_track.id
         else:
             track_id = randint(10000000, 90000000)
         self.__metadata['mpris:trackid'] = self.__get_media_id(track_id)
         track_number = Lp().player.current_track.number
         if track_number is None:
             track_number = 1
         self.__metadata['xesam:trackNumber'] = GLib.Variant('i',
                                                             track_number)
         self.__metadata['xesam:title'] = GLib.Variant(
                                             's',
                                             Lp().player.current_track.name)
         self.__metadata['xesam:album'] = GLib.Variant(
                                       's',
                                       Lp().player.current_track.album.name)
         self.__metadata['xesam:artist'] = GLib.Variant(
                                          'as',
                                          Lp().player.current_track.artists)
         self.__metadata['xesam:albumArtist'] = GLib.Variant(
                                    'as',
                                    Lp().player.current_track.album_artists)
         self.__metadata['mpris:length'] = GLib.Variant(
                               'x',
                               Lp().player.current_track.duration * 1000000)
         self.__metadata['xesam:genre'] = GLib.Variant(
                                           'as',
                                           Lp().player.current_track.genres)
         self.__metadata['xesam:url'] = GLib.Variant(
                                              's',
                                              Lp().player.current_track.uri)
         rate = Lp().player.current_track.get_rate()
         if rate == Type.NONE:
             rate = Lp().player.current_track.get_popularity()
         self.__metadata["xesam:userRating"] = GLib.Variant('d', rate / 5)
         if Lp().player.current_track.id == Type.RADIOS:
             cover_path = Lp().art.get_radio_cache_path(
                  ", ".join(Lp().player.current_track.artists),
                  ArtSize.MONSTER)
         elif Lp().player.current_track.id == Type.EXTERNALS:
             cover_path = "/tmp/lollypop_mpris.jpg"
             pixbuf = Lp().art.pixbuf_from_tags(
                 GLib.filename_from_uri(Lp().player.current_track.uri)[0],
                 ArtSize.MONSTER)
             if pixbuf is not None:
                 pixbuf.savev(cover_path, "jpeg",
                              ["quality"], ["90"])
         else:
             cover_path = Lp().art.get_album_cache_path(
                 Lp().player.current_track.album, ArtSize.MONSTER)
         if cover_path is not None:
             self.__metadata['mpris:artUrl'] = GLib.Variant(
                                                     's',
                                                     "file://" + cover_path)
         elif 'mpris:artUrl' in self.__metadata:
             self.__metadata['mpris:artUrl'] = GLib.Variant('s', '')
Esempio n. 56
0
 def Stop(self):
     Lp().player.stop()
Esempio n. 57
0
 def PlayPause(self):
     Lp().player.play_pause()
Esempio n. 58
0
def is_loved(track_id):
    """
        Check if object is in loved playlist
        @return bool
    """
    return Lp().playlists.exists_track(Type.LOVED, track_id)
Esempio n. 59
0
    def _sync(self, playlists, convert, normalize):
        """
            Sync playlists with device. If playlists contains Type.NONE,
            sync albums marked as to be synced
            @param playlists as [str]
            @param convert as bool
            @param normalize as bool
        """
        try:
            self.__in_thread = True
            self.__convert = convert
            self.__normalize = normalize
            self.__errors = False
            self.__errors_count = 0
            self.__copied_art_uris = []
            # For progress bar
            self.__total = 1
            self.__done = 0
            self._fraction = 0.0
            plnames = []

            GLib.idle_add(Lp().window.progress.set_fraction, 0, self)

            if playlists and playlists[0] == Type.NONE:
                # New tracks for synced albums
                album_ids = Lp().albums.get_synced_ids()
                for album_id in album_ids:
                    self.__total += len(Lp().albums.get_track_ids(album_id))
            else:
                # New tracks for playlists
                for playlist in playlists:
                    plnames.append(Lp().playlists.get_name(playlist))
                    self.__total += len(Lp().playlists.get_tracks(playlist))

            # Old tracks
            try:
                children = self.__get_track_files()
                self.__total += len(children)
            except:
                pass
            GLib.idle_add(self._update_progress)

            # Copy new tracks to device
            if self._syncing:
                self.__copy_to_device(playlists)

            # Remove old tracks from device
            if self._syncing:
                self.__remove_from_device(playlists)

            # Remove empty dirs
            self.__remove_empty_dirs()

            # Remove old playlists
            d = Gio.File.new_for_uri(self._uri)
            infos = d.enumerate_children(
                'standard::name', Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
                None)
            for info in infos:
                f = info.get_name()
                if f.endswith(".m3u") and f[:-4] not in plnames:
                    uri = self._uri + '/' + f
                    d = Gio.File.new_for_uri(uri)
                    self.__retry(d.delete, (None, ))

            d = Gio.File.new_for_uri(self._uri + "/unsync")
            if not d.query_exists(None):
                self.__retry(d.make_directory_with_parents, (None, ))
        except Exception as e:
            print("DeviceManagerWidget::_sync(): %s" % e)
        self._fraction = 1.0
        self._syncing = False
        self.__in_thread = False
        if self.__errors:
            GLib.idle_add(self.__on_errors)
Esempio n. 60
0
 def Play(self):
     if Lp().player.current_track.id is None:
         Lp().player.set_party(True)
     else:
         Lp().player.play()