Beispiel #1
0
    def _remove_from_device(self, playlists):
        """
            Delete files not available in playlist
        """
        track_uris = []
        tracks_ids = []

        # Get tracks ids
        for playlist in playlists:
            tracks_ids += Lp().playlists.get_tracks_ids(playlist)

        # Get tracks uris
        for track_id in tracks_ids:
            if not self._syncing:
                self._fraction = 1.0
                self._in_thread = False
                return
            track = Track(track_id)
            album_name = GLib.uri_escape_string(track.album_name.lower(),
                                                "",
                                                False)
            artist_name = GLib.uri_escape_string(track.artist.lower(),
                                                 "",
                                                 False)
            album_uri = "%s/tracks/%s_%s" % (self._uri,
                                             artist_name,
                                             album_name)
            track_name = GLib.uri_escape_string(GLib.basename(track.path),
                                                "",
                                                False)
            # Check extension, if not mp3, convert
            ext = os.path.splitext(track.path)[1]
            if ext != ".mp3" and self._convert:
                track_name = track_name.replace(ext, ".mp3")
            on_disk = Gio.File.new_for_path(track.path)
            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" % (album_uri, mtime, track_name)
            track_uris.append(dst_uri)

        on_mtp_files = self._get_tracks_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
Beispiel #2
0
    def _remove_from_device(self, playlists):
        """
            Delete files not available in playlist
        """
        track_uris = []
        tracks_ids = []

        # Get tracks ids
        for playlist in playlists:
            tracks_ids += Lp().playlists.get_tracks_ids(playlist)

        # Get tracks uris
        for track_id in tracks_ids:
            if not self._syncing:
                self._fraction = 1.0
                self._in_thread = False
                return
            track = Track(track_id)
            album_name = GLib.uri_escape_string(track.album_name.lower(), "",
                                                False)
            artist_name = GLib.uri_escape_string(track.artist.lower(), "",
                                                 False)
            album_uri = "%s/tracks/%s_%s" % (self._uri, artist_name,
                                             album_name)
            track_name = GLib.uri_escape_string(GLib.basename(track.path), "",
                                                False)
            # Check extension, if not mp3, convert
            ext = os.path.splitext(track.path)[1]
            if ext != ".mp3" and self._convert:
                track_name = track_name.replace(ext, ".mp3")
            on_disk = Gio.File.new_for_path(track.path)
            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" % (album_uri, mtime, track_name)
            track_uris.append(dst_uri)

        on_mtp_files = self._get_tracks_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
Beispiel #3
0
    def do_locate(self, path):
        if path.startswith('license.'):
            filename = GLib.basename(path)
            manager = GtkSource.LanguageManager.get_default()
            language = manager.guess_language(filename, None)

            if self.license == None or language == None:
                return self.empty()

            header = Ide.language_format_header(language, self.license)
            gbytes = GLib.Bytes(header.encode())

            return Gio.MemoryInputStream.new_from_bytes(gbytes)

        return super().do_locate(self, path)
Beispiel #4
0
    def do_locate(self, path):
        if path.startswith('license.'):
            filename = GLib.basename(path)
            manager = GtkSource.LanguageManager.get_default()
            language = manager.guess_language(filename, None)

            if self.license is None or language is None:
                return self.empty()

            header = Ide.language_format_header(language, self.license)
            gbytes = GLib.Bytes(header.encode())

            return Gio.MemoryInputStream.new_from_bytes(gbytes)

        return super().do_locate(self, path)
Beispiel #5
0
    def _copy_to_device(self, playlists):
        """
            Copy file from playlist to device
            @param playlists as [str]
        """
        for playlist in playlists:
            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)
                m3u = None
                stream = None

            # Start copying
            tracks_ids = Lp().playlists.get_tracks_ids(playlist)
            for track_id in tracks_ids:
                if track_id is None:
                    continue
                if not self._syncing:
                    self._fraction = 1.0
                    self._in_thread = False
                    return
                track = Track(track_id)
                album_name = GLib.uri_escape_string(track.album_name.lower(),
                                                    "",
                                                    False)
                artist_name = GLib.uri_escape_string(track.artist.lower(),
                                                     "",
                                                     False)
                on_device_album_uri = "%s/tracks/%s_%s" %\
                                      (self._uri,
                                       artist_name,
                                       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))

                track_name = GLib.uri_escape_string(GLib.basename(track.path),
                                                    "",
                                                    False)
                # Check extension, if not mp3, convert
                ext = os.path.splitext(track.path)[1]
                if ext != ".mp3" and self._convert:
                    convertion_needed = True
                    track_name = track_name.replace(ext, ".mp3")
                else:
                    convertion_needed = False
                src_track = Gio.File.new_for_path(track.path)
                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:
                    line = "tracks/%s_%s/%s_%s\n" %\
                            (artist_name.lower(),
                             album_name.lower(),
                             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._sync:
                                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 = GLib.uri_escape_string(playlist_name,
                                                       "",
                                                       False)
                dst = Gio.File.new_for_uri(self._uri+'/'+playlist_name+'.m3u')
                self._retry(m3u.move,
                            (dst, Gio.FileCopyFlags.OVERWRITE, None, None))
Beispiel #6
0
    def _remove_from_device(self, playlists, sql):
        """
            Delete files not available in playlist
            if sql None, delete all files
            @param playlists as [str]
            @param sql cursor
        """
        track_uris = []
        tracks_id = []

        # Get tracks ids
        for playlist in playlists:
            tracks_id += Lp.playlists.get_tracks_id(playlist, sql)

        # Get tracks uris
        for track_id in tracks_id:
            if not self._syncing:
                self._fraction = 1.0
                self._in_thread = False
                return
            album_id = Lp.tracks.get_album_id(track_id, sql)
            album_name = Lp.albums.get_name(album_id, sql)
            # Sanitize file names as some MTP devices do not like this
            # Or this is a Gio/GObject Introspection bug
            album_name = "".join([
                c for c in album_name if c.isalpha() or c.isdigit() or c == ' '
            ]).rstrip()
            artist_name = Lp.albums.get_artist_name(album_id, sql)
            # Sanitize file names as some MTP devices do not like this
            # Or this is a Gio/GObject Introspection bug
            artist_name = "".join([
                c for c in artist_name
                if c.isalpha() or c.isdigit() or c == ' '
            ]).rstrip()
            track_path = Lp.tracks.get_path(track_id, sql)
            album_uri = "%s/tracks/%s_%s" % (self._uri, artist_name.lower(),
                                             album_name.lower())

            track_name = GLib.basename(track_path)
            # Sanitize file names as some MTP devices do not like this
            # Or this is a Gio/GObject Introspection bug
            track_name = "".join([
                c for c in track_name
                if c.isalpha() or c.isdigit() or c == ' ' or c == '.'
            ]).rstrip()
            on_disk = Gio.File.new_for_path(track_path)
            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" % (album_uri, mtime, track_name)
            track_uris.append(dst_uri)

        on_mtp_files = self._get_children_uris(self._uri + '/tracks')

        # 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
            GLib.idle_add(self._update_progress)
Beispiel #7
0
    def _copy_to_device(self, playlists, sql):
        """
            Copy file from playlist to device
            @param playlists as [str]
            @param sql cursor
        """
        for playlist in playlists:
            try:
                # Create playlist
                m3u = Gio.File.new_for_path("/tmp/lollypop_%s.m3u" %
                                            (playlist, ))
                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)
                m3u = None
                stream = None

            # Start copying
            tracks_id = Lp.playlists.get_tracks_id(playlist, sql)
            for track_id in tracks_id:
                if track_id is None:
                    continue
                if not self._syncing:
                    self._fraction = 1.0
                    self._in_thread = False
                    return
                album_id = Lp.tracks.get_album_id(track_id, sql)
                album_name = Lp.albums.get_name(album_id, sql)
                # Sanitize file names as some MTP devices do not like this
                # Or this is a Gio/GObject Introspection bug
                album_name = "".join([
                    c for c in album_name
                    if c.isalpha() or c.isdigit() or c == ' '
                ]).rstrip()
                artist_name = Lp.albums.get_artist_name(album_id, sql)
                # Sanitize file names as some MTP devices do not like this
                # Or this is a Gio/GObject Introspection bug
                artist_name = "".join([
                    c for c in artist_name
                    if c.isalpha() or c.isdigit() or c == ' '
                ]).rstrip()
                track_path = Lp.tracks.get_path(track_id, sql)
                on_device_album_uri = "%s/tracks/%s_%s" %\
                                      (self._uri,
                                       artist_name.lower(),
                                       album_name.lower())

                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_art_path(album_id, sql)
                if art:
                    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))

                track_name = GLib.basename(track_path)
                # Sanitize file names as some MTP devices do not like this
                # Or this is a Gio/GObject Introspection bug
                track_name = "".join([
                    c for c in track_name
                    if c.isalpha() or c.isdigit() or c == ' ' or c == '.'
                ]).rstrip()
                src_track = Gio.File.new_for_path(track_path)
                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:
                    line = "tracks/%s_%s/%s_%s\n" %\
                            (artist_name.lower(),
                             album_name.lower(),
                             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):
                    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
                GLib.idle_add(self._update_progress)
            if stream is not None:
                stream.close()
            if m3u is not None:
                dst = Gio.File.new_for_uri(self._uri + '/' + playlist + '.m3u')
                self._retry(m3u.move,
                            (dst, Gio.FileCopyFlags.OVERWRITE, None, None))
Beispiel #8
0
    def _copy_to_device(self, playlists):
        """
            Copy file from playlist to device
            @param playlists as [str]
        """
        for playlist in playlists:
            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)
                m3u = None
                stream = None

            # Start copying
            tracks_ids = Lp().playlists.get_tracks_ids(playlist)
            for track_id in tracks_ids:
                if track_id is None:
                    continue
                if not self._syncing:
                    self._fraction = 1.0
                    self._in_thread = False
                    return
                track = Track(track_id)
                album_name = GLib.uri_escape_string(track.album_name,
                                                    "",
                                                    False)
                artist_name = GLib.uri_escape_string(track.artist,
                                                     "",
                                                     False)
                on_device_album_uri = "%s/tracks/%s_%s" %\
                                      (self._uri,
                                       artist_name.lower(),
                                       album_name.lower())

                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))

                track_name = GLib.uri_escape_string(GLib.basename(track.path),
                                                    "",
                                                    False)
                src_track = Gio.File.new_for_path(track.path)
                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:
                    line = "tracks/%s_%s/%s_%s\n" %\
                            (artist_name.lower(),
                             album_name.lower(),
                             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):
                    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
                GLib.idle_add(self._update_progress)
            if stream is not None:
                stream.close()
            if m3u is not None:
                playlist_name = GLib.uri_escape_string(playlist_name,
                                                       "",
                                                       False)
                dst = Gio.File.new_for_uri(self._uri+'/'+playlist_name+'.m3u')
                self._retry(m3u.move,
                            (dst, Gio.FileCopyFlags.OVERWRITE, None, None))
Beispiel #9
0
    def __add2db(self, uri, info, mtime):
        """
            Add new file to db with informations
            @param uri as string
            @param info as GstPbutils.DiscovererInfo
            @param mtime as int
            @return track id as int
        """
        debug("CollectionScanner::add2db(): Read tags")
        path = GLib.filename_from_uri(uri)[0]
        tags = info.get_tags()
        title = self.get_title(tags, path)
        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, GLib.basename(path))
        year = self.get_year(tags)
        duration = int(info.get_duration() / 1000000000)
        name = GLib.path_get_basename(path)

        # 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_ltime, amtime,
         album_pop) = self.__history.get(name, duration)
        # If nothing in stats, set mtime
        if amtime == 0:
            amtime = mtime
        debug("CollectionScanner::add2db(): Add artists %s" % artists)
        (artist_ids,
         new_artist_ids) = self.add_artists(artists, album_artists,
                                            a_sortnames)
        debug("CollectionScanner::add2db(): "
              "Add album artists %s" % album_artists)
        (album_artist_ids, new_album_artist_ids) = self.add_album_artists(
            album_artists, aa_sortnames)
        new_artist_ids += new_album_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,
                                               path, album_pop, amtime)

        (genre_ids, new_genre_ids) = self.add_genres(genres, album_id)

        # 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_ltime, mtime)

        debug("CollectionScanner::add2db(): Update tracks")
        self.update_track(track_id, artist_ids, genre_ids)
        self.update_album(album_id, album_artist_ids, genre_ids, year)
        # Notify about new artists/genres
        if new_genre_ids or new_artist_ids:
            with SqlCursor(Lp().db) as sql:
                sql.commit()
            for genre_id in new_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, album_id,
                              True)
        return track_id
Beispiel #10
0
    def _copy_to_device(self, playlists):
        """
            Copy file from playlist to device
            @param playlists as [str]
        """
        for playlist in playlists:
            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)
                m3u = None
                stream = None

            # Start copying
            tracks_ids = Lp().playlists.get_tracks_ids(playlist)
            for track_id in tracks_ids:
                if track_id is None:
                    continue
                if not self._syncing:
                    self._fraction = 1.0
                    self._in_thread = False
                    return
                track = Track(track_id)
                album_name = GLib.uri_escape_string(track.album_name.lower(),
                                                    "", False)
                artist_name = GLib.uri_escape_string(track.artist.lower(), "",
                                                     False)
                on_device_album_uri = "%s/tracks/%s_%s" %\
                                      (self._uri,
                                       artist_name,
                                       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))

                track_name = GLib.uri_escape_string(GLib.basename(track.path),
                                                    "", False)
                src_track = Gio.File.new_for_path(track.path)
                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:
                    line = "tracks/%s_%s/%s_%s\n" %\
                            (artist_name.lower(),
                             album_name.lower(),
                             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):
                    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
                GLib.idle_add(self._update_progress)
            if stream is not None:
                stream.close()
            if m3u is not None:
                playlist_name = GLib.uri_escape_string(playlist_name, "",
                                                       False)
                dst = Gio.File.new_for_uri(self._uri + '/' + playlist_name +
                                           '.m3u')
                self._retry(m3u.move,
                            (dst, Gio.FileCopyFlags.OVERWRITE, None, None))
Beispiel #11
0
    def _remove_from_device(self, playlists, sql):
        """
            Delete files not available in playlist
            if sql None, delete all files
            @param playlists as [str]
            @param sql cursor
        """
        track_uris = []
        tracks_id = []

        # Get tracks ids
        for playlist in playlists:
            tracks_id += Lp.playlists.get_tracks_id(playlist, sql)

        # Get tracks uris
        for track_id in tracks_id:
            if not self._syncing:
                self._fraction = 1.0
                self._in_thread = False
                return
            track = Track(track_id)
            # Sanitize file names as some MTP devices do not like this
            # Or this is a Gio/GObject Introspection bug
            album_name = "".join([c for c in track.album_name if
                                  c.isalpha() or
                                  c.isdigit() or c == ' ']).rstrip()
            # Sanitize file names as some MTP devices do not like this
            # Or this is a Gio/GObject Introspection bug
            artist_name = "".join([c for c in track.artist if
                                   c.isalpha() or
                                   c.isdigit() or c == ' ']).rstrip()
            track_path = Lp.tracks.get_path(track_id, sql)
            album_uri = "%s/tracks/%s_%s" % (self._uri,
                                             artist_name.lower(),
                                             album_name.lower())

            track_name = GLib.basename(track_path)
            # Sanitize file names as some MTP devices do not like this
            # Or this is a Gio/GObject Introspection bug
            track_name = "".join([c for c in track_name if c.isalpha() or
                                  c.isdigit() or
                                  c == ' ' or
                                  c == '.']).rstrip()
            on_disk = Gio.File.new_for_path(track_path)
            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" % (album_uri, mtime, track_name)
            track_uris.append(dst_uri)

        on_mtp_files = self._get_children_uris(self._uri+'/tracks')

        # 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
            GLib.idle_add(self._update_progress)
Beispiel #12
0
    def _copy_to_device(self, playlists, sql):
        """
            Copy file from playlist to device
            @param playlists as [str]
            @param sql cursor
        """
        for playlist in playlists:
            try:
                # Create playlist
                m3u = Gio.File.new_for_path(
                    "/tmp/lollypop_%s.m3u" % (playlist,))
                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)
                m3u = None
                stream = None

            # Start copying
            tracks_id = Lp.playlists.get_tracks_id(playlist, sql)
            for track_id in tracks_id:
                if track_id is None:
                    continue
                if not self._syncing:
                    self._fraction = 1.0
                    self._in_thread = False
                    return
                track = Track(track_id)
                # Sanitize file names as some MTP devices do not like this
                # Or this is a Gio/GObject Introspection bug
                album_name = "".join([c for c in track.album_name if
                                      c.isalpha() or
                                      c.isdigit() or c == ' ']).rstrip()
                # Sanitize file names as some MTP devices do not like this
                # Or this is a Gio/GObject Introspection bug
                artist_name = "".join([c for c in track.artist if
                                       c.isalpha() or
                                       c.isdigit() or c == ' ']).rstrip()
                track_path = Lp.tracks.get_path(track_id, sql)
                on_device_album_uri = "%s/tracks/%s_%s" %\
                                      (self._uri,
                                       artist_name.lower(),
                                       album_name.lower())

                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_art_path(track.album, sql)
                if art:
                    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))

                track_name = GLib.basename(track_path)
                # Sanitize file names as some MTP devices do not like this
                # Or this is a Gio/GObject Introspection bug
                track_name = "".join([c for c in track_name if c.isalpha() or
                                      c.isdigit() or
                                      c == ' ' or
                                      c == '.']).rstrip()
                src_track = Gio.File.new_for_path(track_path)
                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:
                    line = "tracks/%s_%s/%s_%s\n" %\
                            (artist_name.lower(),
                             album_name.lower(),
                             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):
                    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
                GLib.idle_add(self._update_progress)
            if stream is not None:
                stream.close()
            if m3u is not None:
                dst = Gio.File.new_for_uri(self._uri+'/'+playlist+'.m3u')
                self._retry(m3u.move,
                            (dst, Gio.FileCopyFlags.OVERWRITE, None, None))
Beispiel #13
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:
                artists = escape(", ".join(track.artists).lower())
            else:
                artists = escape(", ".join(track.album.artists).lower())
            album_uri = "%s/%s_%s" % (self._uri,
                                      artists,
                                      album_name)
            filepath = GLib.filename_from_uri(track.uri)[0]
            track_name = escape(GLib.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" % (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
Beispiel #14
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())
                if track.album.artist_ids[0] == Type.COMPILATIONS:
                    artists = escape(", ".join(track.artists).lower())
                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.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:
                    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))