Пример #1
0
 def uncache_artwork(prefix, suffix, scale):
     """
         Remove info from cache
         @param prefix as str
         @param suffix as str
         @param scale factor as int
     """
     filepath = "%s/%s_%s_%s.jpg" % (InfoCache.CACHE_PATH,
                                     escape(prefix),
                                     suffix,
                                     ArtSize.ARTIST)
     f = Gio.File.new_for_path(filepath)
     try:
         f.delete(None)
     except:
         pass
     for i in [1, 2]:
         filepath = "%s/%s_%s_%s.jpg" % (InfoCache.CACHE_PATH,
                                         escape(prefix),
                                         suffix,
                                         ArtSize.ARTIST_SMALL*scale*i)
         f = Gio.File.new_for_path(filepath)
         try:
             f.delete(None)
         except:
             pass
Пример #2
0
 def _get_tracks_files(self):
     """
         Return children uris for uri
         @return [str]
     """
     children = []
     dir_uris = [self._uri+'/tracks/']
     while dir_uris:
         uri = dir_uris.pop(0)
         album_name = uri.replace(self._uri+"/tracks/", "")
         album = escape(album_name)
         d = Gio.File.new_for_uri(self._uri+"/tracks/"+album)
         infos = d.enumerate_children(
             'standard::name,standard::type',
             Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
             None)
         for info in infos:
             if info.get_file_type() == Gio.FileType.DIRECTORY:
                 dir_uris.append(uri+info.get_name())
             else:
                 track = escape(info.get_name())
                 children.append("%s/tracks/%s/%s" % (self._uri,
                                                      album,
                                                      track))
     return children
Пример #3
0
 def exists(prefix):
     """
         Return True if an info is cached
         @param prefix as string
     """
     exists = False
     for (suffix, helper1, helper2) in InfoCache.WEBSERVICES:
         filepath = "%s/%s_%s.jpg" % (InfoCache._INFO_PATH,
                                      escape(prefix),
                                      suffix)
         if path.exists(filepath):
             exists = True
         else:
             # FIXME Remove this code, support for old lollypop versions
             #
             old_path = "%s/%s_%s_%s.jpg" % (InfoCache._CACHE_PATH,
                                             escape(prefix),
                                             suffix,
                                             ArtSize.ARTIST)
             if path.exists(old_path):
                 rename(old_path, filepath)
                 exists = True
             #
             ##########################################################
     return exists
Пример #4
0
 def __search_term(self, term):
     """
         Search term on Wikipdia
         @param term as str
         @return pageid as str
     """
     try:
         for locale in [self.__locale, "en"]:
             uri = self.__API_SEARCH % (locale, term)
             (status, data) = App().task_helper.load_uri_content_sync(uri)
             if status:
                 decode = json.loads(data.decode("utf-8"))
                 for item in decode["query"]["search"]:
                     if escape(item["title"].lower()) ==\
                             escape(term.lower()):
                         return (locale, item["pageid"])
                     else:
                         for word in [
                                 _("band"),
                                 _("singer"), "band", "singer"
                         ]:
                             if item["snippet"].lower().find(word) != -1:
                                 return (locale, item["pageid"])
     except Exception as e:
         print("Wikipedia::__search_term(): %s", e)
     return ("", None)
Пример #5
0
 def exists(prefix):
     """
         Return True if an info is cached
         @param prefix as string
     """
     exists = False
     for (suffix, helper1, helper2) in InfoCache.WEBSERVICES:
         filepath = "%s/%s_%s.jpg" % (InfoCache._INFO_PATH,
                                      escape(prefix),
                                      suffix)
         if path.exists(filepath):
             exists = True
         else:
             # FIXME Remove this code, support for old lollypop versions
             #
             old_path = "%s/%s_%s_%s.jpg" % (InfoCache._CACHE_PATH,
                                             escape(prefix),
                                             suffix,
                                             ArtSize.ARTIST)
             if path.exists(old_path):
                 rename(old_path, filepath)
                 exists = True
             #
             ##########################################################
     return exists
Пример #6
0
 def add_artist_artwork(self, artist, data, is_web=False):
     """
         Add artist artwork to store
         @param artist as str
         @param data as bytes
         @param is_web as bool
         @thread safe
     """
     self.uncache_artist_artwork(artist)
     if is_web:
         filepath = "%s/web_%s.jpg" % (self._INFO_PATH, escape(artist))
     else:
         filepath = "%s/%s.jpg" % (self._INFO_PATH, escape(artist))
     if data is None:
         f = Gio.File.new_for_path(filepath)
         fstream = f.replace(None, False,
                             Gio.FileCreateFlags.REPLACE_DESTINATION, None)
         fstream.close()
     else:
         bytes = GLib.Bytes(data)
         stream = Gio.MemoryInputStream.new_from_bytes(bytes)
         pixbuf = GdkPixbuf.Pixbuf.new_from_stream(stream, None)
         stream.close()
         pixbuf.savev(filepath, "jpeg", ["quality"], ["100"])
     GLib.idle_add(self.emit, "artist-artwork-changed", artist)
Пример #7
0
 def __get_uris_to_copy(self, tracks):
     """
         Get on device URI for all tracks
         @param tracks as [Track]
     """
     uris = []
     art_uris = []
     for track in tracks:
         f = Gio.File.new_for_uri(track.uri)
         album_device_uri = "%s/%s" % (
             self.__uri, self.__get_album_on_device_uri(track))
         album_local_uri = f.get_parent().get_uri()
         src_uri = "%s/%s" % (album_local_uri,
                              GLib.uri_escape_string(
                                  f.get_basename(), None, True))
         dst_uri = "%s/%s" % (album_device_uri, escape(f.get_basename()))
         (convertion_needed,
          dst_uri) = self.__is_convertion_needed(src_uri, dst_uri)
         uris.append((src_uri, dst_uri))
         art_uri = App().art.get_album_artwork_uri(track.album)
         if art_uri is not None:
             art_filename = Gio.File.new_for_uri(art_uri).get_basename()
             art_uris.append(
                 (art_uri,
                  "%s/%s" % (album_device_uri, escape(art_filename))))
     return uris + art_uris
Пример #8
0
 def uncache_artwork(prefix, suffix, scale):
     """
         Remove info from cache
         @param prefix as str
         @param suffix as str
         @param scale factor as int
     """
     filepath = "%s/%s_%s.jpg" % (InfoCache.CACHE_PATH,
                                  escape(prefix),
                                  suffix)
     f = Gio.File.new_for_path(filepath)
     try:
         f.delete(None)
     except:
         pass
     filepath = "%s/%s_%s_%s.jpg" % (InfoCache.CACHE_PATH,
                                     escape(prefix),
                                     suffix,
                                     ArtSize.ARTIST_SMALL*scale)
     f = Gio.File.new_for_path(filepath)
     try:
         f.delete(None)
     except:
         pass
     Lp().art.emit('artist-artwork-changed', prefix)
Пример #9
0
 def get_artwork(prefix, suffix, size=ArtSize.ARTIST):
     """
         Return path for artwork, empty if none
         @param prefix as string
         @param suffix as string
         @param size as int
         @return path as string/None
     """
     filepath = "%s/%s_%s_%s.jpg" % (InfoCache.CACHE_PATH,
                                     escape(prefix),
                                     suffix,
                                     ArtSize.ARTIST)
     filepath_at_size = "%s/%s_%s_%s.jpg" % (InfoCache.CACHE_PATH,
                                             escape(prefix),
                                             suffix,
                                             size)
     if not path.exists(filepath) or path.getsize(filepath) == 0:
         return None
     # Make cache for this size
     if not path.exists(filepath_at_size):
         pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(filepath,
                                                         size,
                                                         size)
         if pixbuf.get_height() > pixbuf.get_width():
             vertical = True
         else:
             vertical = False
         del pixbuf
         extract = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB,
                                        True, 8,
                                        size, size)
         if vertical:
             pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(filepath,
                                                              size,
                                                              -1,
                                                              True)
             diff = pixbuf.get_height() - size
             pixbuf.copy_area(0, diff/2,
                              pixbuf.get_width(),
                              size,
                              extract,
                              0, 0)
         else:
             pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(filepath,
                                                              -1,
                                                              size,
                                                              True)
             diff = pixbuf.get_width() - size
             pixbuf.copy_area(diff/2, 0,
                              size,
                              pixbuf.get_height(),
                              extract,
                              0, 0)
         extract.savev(filepath_at_size, "jpeg", ["quality"], ["90"])
         del pixbuf
         del extract
     return filepath_at_size
Пример #10
0
 def get_artwork(prefix, suffix, size):
     """
         Return path for artwork
         @param prefix as string
         @param suffix as string
         @param size as int
         @return path as string/None
     """
     try:
         for (suffix, helper1, helper2) in InfoCache.WEBSERVICES:
             extract = None
             filepath = "%s/%s_%s.jpg" % (InfoCache._INFO_PATH,
                                          escape(prefix), suffix)
             filepath_at_size = "%s/%s_%s_%s.jpg" % (
                 InfoCache._CACHE_PATH, escape(prefix), suffix, size)
             if not path.exists(filepath) or path.getsize(filepath) == 0:
                 filepath_at_size = None
                 continue
             # Make cache for this size
             if not path.exists(filepath_at_size):
                 pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(
                     filepath, size, size)
                 if pixbuf.get_height() > pixbuf.get_width():
                     vertical = True
                 elif pixbuf.get_height() < pixbuf.get_width():
                     vertical = False
                 else:
                     extract = pixbuf
                 if extract is None:
                     del pixbuf
                     extract = GdkPixbuf.Pixbuf.new(
                         GdkPixbuf.Colorspace.RGB, True, 8, size, size)
                     if vertical:
                         pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
                             filepath, size, -1, True)
                         diff = pixbuf.get_height() - size
                         pixbuf.copy_area(0, diff / 2, pixbuf.get_width(),
                                          size, extract, 0, 0)
                     else:
                         pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
                             filepath, -1, size, True)
                         diff = pixbuf.get_width() - size
                         pixbuf.copy_area(diff / 2, 0, size,
                                          pixbuf.get_height(), extract, 0,
                                          0)
                     del pixbuf
                 extract.savev(filepath_at_size, "jpeg", ["quality"], [
                     str(Lp().settings.get_value(
                         'cover-quality').get_int32())
                 ])
                 del extract
             return filepath_at_size
     except Exception as e:
         print("InfoCache::get_artwork():", e)
         return None
Пример #11
0
 def get_artwork_path(artist, size, scale_factor):
     """
         Return path for artwork
         @param artist as string
         @param size as int
         @param scale_factor as int
         @return path as string/None
     """
     try:
         size *= scale_factor
         extract = None
         filepath = "%s/%s.jpg" % (InformationStore._INFO_PATH,
                                   escape(artist))
         filepath_at_size = "%s/%s_%s.jpg" % (InformationStore._CACHE_PATH,
                                              escape(artist), size)
         f = Gio.File.new_for_path(filepath)
         if not f.query_exists():
             return None
         info = f.query_info("standard::size", Gio.FileQueryInfoFlags.NONE)
         if info.get_size() == 0:
             return None
         # Make cache for this size
         f = Gio.File.new_for_path(filepath_at_size)
         if not f.query_exists():
             pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(
                 filepath, size, size)
             if pixbuf.get_height() > pixbuf.get_width():
                 vertical = True
             elif pixbuf.get_height() < pixbuf.get_width():
                 vertical = False
             else:
                 extract = pixbuf
             if extract is None:
                 extract = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB,
                                                True, 8, size, size)
                 if vertical:
                     pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
                         filepath, size, -1, True)
                     diff = pixbuf.get_height() - size
                     pixbuf.copy_area(0, diff / 2, pixbuf.get_width(), size,
                                      extract, 0, 0)
                 else:
                     pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
                         filepath, -1, size, True)
                     diff = pixbuf.get_width() - size
                     pixbuf.copy_area(diff / 2, 0, size,
                                      pixbuf.get_height(), extract, 0, 0)
             extract.savev(filepath_at_size, "jpeg", ["quality"], [
                 str(App().settings.get_value("cover-quality").get_int32())
             ])
         return filepath_at_size
     except Exception as e:
         Logger.error("InformationStore::get_artwork_path(): %s" % e)
         return None
Пример #12
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 = escape(track.album_name.lower())
            if track.album_artist_id == Type.COMPILATIONS:
                artist_name = escape(track.artist.lower())
            else:
                artist_name = escape(track.album_artist.lower())
            album_uri = "%s/tracks/%s_%s" % (self._uri,
                                             artist_name,
                                             album_name)
            track_name = escape(GLib.basename(track.path))
            # 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
Пример #13
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 = escape(track.album_name.lower())
            if track.album_artist_id == Type.COMPILATIONS:
                artist_name = escape(track.artist.lower())
            else:
                artist_name = escape(track.album_artist.lower())
            album_uri = "%s/tracks/%s_%s" % (self._uri, artist_name,
                                             album_name)
            track_name = escape(GLib.basename(track.path))
            # 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
Пример #14
0
 def __get_album_on_device_uri(self, track):
     """
         Get on device URI for album
         @param track as Track
         @return URI as str
     """
     album_name = track.album_name.lower()
     is_compilation = track.album.artist_ids[0] == Type.COMPILATIONS
     if is_compilation:
         string = escape(album_name)
     else:
         artists = ", ".join(track.album.artists).lower()
         string = escape("%s_%s" % (artists, album_name))
     return GLib.uri_escape_string(string[:100], None, True)
Пример #15
0
 def add(prefix, content, data, suffix):
     """
         Add info to store
         @param prefix as str
         @param content as str
         @param data as bytes
         @param suffix as str
     """
     filepath = "%s/%s_%s" % (InfoCache._INFO_PATH, escape(prefix), suffix)
     if content is not None:
         f = Gio.File.new_for_path(filepath + ".txt")
         fstream = f.replace(None, False,
                             Gio.FileCreateFlags.REPLACE_DESTINATION, None)
         if fstream is not None:
             fstream.write(content, None)
             fstream.close()
     if data is None:
         f = Gio.File.new_for_path(filepath + ".jpg")
         fstream = f.replace(None, False,
                             Gio.FileCreateFlags.REPLACE_DESTINATION, None)
         fstream.close()
     else:
         bytes = GLib.Bytes(data)
         stream = Gio.MemoryInputStream.new_from_bytes(bytes)
         bytes.unref()
         pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(
             stream, ArtSize.ARTIST, -1, True, None)
         stream.close()
         pixbuf.savev(
             filepath + ".jpg", "jpeg", ["quality"],
             [str(Lp().settings.get_value("cover-quality").get_int32())])
Пример #16
0
 def get_artist_cache_name(self, artist):
     """
         Get a uniq string for artist
         @param artist as str
     """
     name = "@ARTIST@_%s" % (escape(artist)[:100])
     return name
Пример #17
0
 def __download_genius_lyrics(self):
     """
         Download lyrics from genius
     """
     self.__downloads_running += 1
     # Update lyrics
     if self.__current_track.id == Type.RADIOS:
         split = App().player.current_track.name.split(" - ")
         if len(split) < 2:
             return
         artist = split[0]
         title = split[1]
     else:
         if self.__current_track.artists:
             artist = self.__current_track.artists[0]
         elif self.__current_track.album_artists:
             artist = self.__current_track.album_artists[0]
         else:
             artist = ""
         title = self.__current_track.name
     string = escape("%s %s" % (artist, title))
     uri = "https://genius.com/%s-lyrics" % string.replace(" ", "-")
     helper = TaskHelper()
     helper.load_uri_content(uri, self.__cancellable,
                             self.__on_lyrics_downloaded,
                             "song_body-lyrics", "")
Пример #18
0
 def cache(prefix, content, data, suffix):
     """
         Cache datas
         @param prefix as str
         @param content as str
         @param data as bytes
         @param suffix as str
     """
     filepath = "%s/%s_%s" % (InfoCache.CACHE_PATH,
                              escape(prefix),
                              suffix)
     if content is not None:
         f = Gio.File.new_for_path(filepath+".txt")
         fstream = f.replace(None, False,
                             Gio.FileCreateFlags.REPLACE_DESTINATION, None)
         if fstream is not None:
             fstream.write(content, None)
             fstream.close()
     if data is None:
         f = Gio.File.new_for_path(filepath+".jpg")
         fstream = f.replace(None, False,
                             Gio.FileCreateFlags.REPLACE_DESTINATION, None)
         fstream.close()
     else:
         stream = Gio.MemoryInputStream.new_from_data(data, None)
         pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(stream,
                                                            ArtSize.ARTIST,
                                                            -1,
                                                            True,
                                                            None)
         pixbuf.savev(filepath+"_"+str(ArtSize.ARTIST)+".jpg",
                      "jpeg", ["quality"], ["90"])
         Lp().art.emit('artist-artwork-changed', prefix)
         del pixbuf
Пример #19
0
 def __get_radio_art_path(self, name):
     """
         Get radio artwork path
         @param name as str
         @return filepath as str
     """
     return "%s/%s.png" % (self._RADIOS_PATH, escape(name))
Пример #20
0
 def __migrate_old_dir(self):
     """
         Migrate old data dir
     """
     try:
         old_path = GLib.get_user_data_dir() + "/lollypop/info"
         old_src = Gio.File.new_for_path(old_path)
         if not old_src.query_exists():
             return
         storage_type = get_default_storage_type()
         for (artist_id, artist,
              *ignore) in App().artists.get([], storage_type):
             for ext in ["jpg", "txt"]:
                 src_path = "%s/%s.%s" % (old_path, escape(artist), ext)
                 src = Gio.File.new_for_path(src_path)
                 if not src.query_exists():
                     continue
                 encoded = self.encode_artist_name(artist)
                 dst_path = "%s/%s.%s" % (ARTISTS_PATH, encoded, ext)
                 dst = Gio.File.new_for_path(dst_path)
                 src.copy(dst, Gio.FileCopyFlags.OVERWRITE, None, None)
         old_dst = Gio.File.new_for_path(GLib.get_user_data_dir() +
                                         "/lollypop/info-backup")
         old_src.move(old_dst, Gio.FileCopyFlags.OVERWRITE, None, None)
     except Exception as e:
         Logger.error("ArtistArt::__migrate_old_dir(): %s -> %s", e,
                      old_path)
Пример #21
0
 def add(prefix, content, data, suffix):
     """
         Add info to store
         @param prefix as str
         @param content as str
         @param data as bytes
         @param suffix as str
     """
     filepath = "%s/%s_%s" % (InfoCache._INFO_PATH,
                              escape(prefix),
                              suffix)
     if content is not None:
         f = Gio.File.new_for_path(filepath+".txt")
         fstream = f.replace(None, False,
                             Gio.FileCreateFlags.REPLACE_DESTINATION, None)
         if fstream is not None:
             fstream.write(content, None)
             fstream.close()
     if data is None:
         f = Gio.File.new_for_path(filepath+".jpg")
         fstream = f.replace(None, False,
                             Gio.FileCreateFlags.REPLACE_DESTINATION, None)
         fstream.close()
     else:
         stream = Gio.MemoryInputStream.new_from_data(data, None)
         pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(stream,
                                                            ArtSize.ARTIST,
                                                            -1,
                                                            True,
                                                            None)
         pixbuf.savev(filepath+".jpg",
                      "jpeg", ["quality"], ["90"])
         del pixbuf
Пример #22
0
 def __get_radio_cache_name(self, name):
     """
         Get a uniq string for radio
         @param album_id as int
         @param sql as sqlite cursor
     """
     return "@@" + escape(name) + "@@radio@@"
Пример #23
0
 def add(prefix, content, data, suffix):
     """
         Add info to store
         @param prefix as str
         @param content as str
         @param data as bytes
         @param suffix as str
     """
     filepath = "%s/%s_%s" % (InfoCache._INFO_PATH, escape(prefix), suffix)
     if content is not None:
         f = Gio.File.new_for_path(filepath + ".txt")
         fstream = f.replace(None, False,
                             Gio.FileCreateFlags.REPLACE_DESTINATION, None)
         if fstream is not None:
             fstream.write(content, None)
             fstream.close()
     if data is None:
         f = Gio.File.new_for_path(filepath + ".jpg")
         fstream = f.replace(None, False,
                             Gio.FileCreateFlags.REPLACE_DESTINATION, None)
         fstream.close()
     else:
         stream = Gio.MemoryInputStream.new_from_data(data, None)
         pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(
             stream, ArtSize.ARTIST, -1, True, None)
         pixbuf.savev(filepath + ".jpg", "jpeg", ["quality"], ["90"])
         del pixbuf
Пример #24
0
 def get_album_cache_name(self, album):
     """
         Get a uniq string for album
         @param album as Album
     """
     name = "_".join(album.artists)[:100] +\
         "_" + album.name[:100] + "_" + album.year
     return escape(name)
Пример #25
0
 def __get_album_cache_name(self, album):
     """
         Get a uniq string for album
         @param album as Album
     """
     # FIXME special chars
     name = "_".join(album.artists) + "_" + album.name + "_" + album.year
     return escape(name)
Пример #26
0
 def get_album_cache_name(self, album):
     """
         Get a uniq string for album
         @param album as Album
     """
     name = "_".join(album.artists)[:100] +\
         "_" + album.name[:100] + "_" + album.year
     return escape(name)
Пример #27
0
    def __get_jgm_id(self, item):
        """
            Get jmg id
            @param item as SearchItem
            @return jpg id as str
        """
        # Try to handle compilations (itunes one)
        unwanted = ["variout artists", "multi-interprètes"]
        if item.artists[0].lower() in unwanted:
            if len(item.artists) > 1:
                artist = item.artists[1]
            else:
                artist = ""
        else:
            artist = item.artists[0]
        unescaped = "%s %s" % (artist,
                               item.name)
        for c in ['/', '?', '!']:
            if c in unescaped:
                unescaped = unescaped.replace(c, ' ')

        search = GLib.uri_escape_string(unescaped,
                                        '',
                                        True)
        try:
            # Strip /? as API doesn't like it
            f = Lio.File.new_for_uri("http://app.jgm90.com/cmapi/search/"
                                     "%s/1/10" % search.strip('/?'))
            (status, data, tag) = f.load_contents(None)
            if status:
                decode = json.loads(data.decode('utf-8'))
                for song in decode['result']['songs']:
                    try:
                        song_artist = escape(
                                            song['artists'][0]['name'].lower())
                        if song_artist == escape(artist.lower()):
                            return song['id']
                    except Exception as e:
                        print("WebJmg90::__get_jmg_id():", e)
        except IndexError:
            pass
        except KeyError:
            pass
        except Exception as e:
            print("WebJmg90::__get_jmg_id():", e)
        return None
Пример #28
0
 def _get_album_cache_name(self, album):
     """
         Get a uniq string for album
         @param album as Album
     """
     # FIXME special chars
     name = "_".join(album.artists) + "_" + album.name + "_" + album.year
     return escape(name)
Пример #29
0
 def artwork_exists(artist):
     """
         True if artwork exists
         @param artist as str
         @return bool
     """
     filepath = "%s/%s.jpg" % (InformationStore._INFO_PATH, escape(artist))
     return GLib.file_test(filepath, GLib.FileTest.EXISTS)
Пример #30
0
    def __write_playlists(self, playlist_ids):
        """
            Write playlists on disk
            @param playlist_ids as [int]
        """
        for playlist_id in playlist_ids:
            if self.__cancellable.is_cancelled():
                break
            try:
                # Get tracks
                if App().playlists.get_smart(playlist_id):
                    request = App().playlists.get_smart_sql(playlist_id)
                    track_ids = App().db.execute(request)
                else:
                    track_ids = App().playlists.get_track_ids(playlist_id)

                # Build tracklist
                tracklist = "#EXTM3U\n"
                for track_id in track_ids:
                    if self.__cancellable.is_cancelled():
                        break
                    track = Track(track_id)
                    f = Gio.File.new_for_uri(track.uri)
                    filename = f.get_basename()
                    album_uri = self.__get_album_name(track)
                    uri = "%s/%s" % (album_uri, escape(filename))
                    (convertion_needed,
                     uri) = self.__is_convertion_needed(track.uri, uri)
                    tracklist += "%s\n" % uri

                # Write playlist file
                playlist_name = escape(App().playlists.get_name(playlist_id))
                playlist_uri = "%s/%s.m3u" % (self.__uri, playlist_name)
                Logger.debug("MtpSync::__write_playlists(): %s" % playlist_uri)
                temp_uri = os.path.join(tempfile.gettempdir(),
                                        "lollypop_%s.m3u" % playlist_name)
                m3u_temp = Gio.File.new_for_path(temp_uri)
                m3u_temp.replace_contents(
                    tracklist.encode("utf-8"), None, False,
                    Gio.FileCreateFlags.REPLACE_DESTINATION,
                    self.__cancellable)
                m3u = Gio.File.new_for_uri(playlist_uri)
                m3u_temp.move(m3u, Gio.FileCopyFlags.OVERWRITE, None, None)
            except Exception as e:
                Logger.error("MtpSync::__write_playlists(): %s", e)
Пример #31
0
 def get_album_cache_name(self, album):
     """
         Get a uniq string for album
         @param album as Album
     """
     name = "%s_%s_%s" % (" ".join(album.artists)[:100],
                          album.name[:100],
                          album.year)
     return escape(name)
Пример #32
0
 def uncache(prefix, suffix):
     """
         Remove info from cache
         @param prefix as str
         @param suffix as str
     """
     filepath = "%s/%s_%s.txt" % (InfoCache.CACHE_PATH, escape(prefix), suffix)
     f = Gio.File.new_for_path(filepath)
     try:
         f.delete(None)
     except:
         pass
     filepath = "%s/%s_%s_%s.jpg" % (InfoCache.CACHE_PATH, escape(prefix), suffix, ArtSize.ARTIST)
     f = Gio.File.new_for_path(filepath)
     try:
         f.delete(None)
     except:
         pass
Пример #33
0
 def __sync_playlists(self, playlist_ids):
     """
         Sync file from playlist to device
         @param playlist_ids as [int]
     """
     for playlist_id in playlist_ids:
         if self.__cancellable.is_cancelled():
             break
         m3u = None
         stream = None
         playlist = App().playlists.get_name(playlist_id)
         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:
             Logger.error("DeviceWidget::__sync_playlists(): %s" % e)
         if App().playlists.get_smart(playlist_id):
             request = App().playlists.get_smart_sql(playlist_id)
             track_ids = App().db.execute(request)
         else:
             track_ids = App().playlists.get_track_ids(playlist_id)
         # Start copying
         for track_id in track_ids:
             if self.__cancellable.is_cancelled():
                 break
             if track_id is None:
                 self.__done += 1
                 continue
             track = Track(track_id)
             (track_name, artists, album_name, is_compilation) =\
                 self.__sync_track_id(track)
             if stream is not None:
                 if is_compilation:
                     line = "%s/%s\n" %\
                         (album_name,
                          track_name)
                 else:
                     line = "%s_%s/%s\n" %\
                         (artists,
                          album_name,
                          track_name)
                 self.__retry(stream.get_output_stream().write,
                              (line.encode(encoding="UTF-8"), None))
         if stream is not None:
             stream.close()
         if m3u is not None:
             playlist = escape(playlist)
             dst = Gio.File.new_for_uri(self.__uri + "/" + playlist +
                                        ".m3u")
             self.__retry(m3u.move,
                          (dst, Gio.FileCopyFlags.OVERWRITE, None, None))
Пример #34
0
    def __get_jgm_id(self, item):
        """
            Get jmg id
            @param item as SearchItem
            @return jpg id as str
        """
        # Try to handle compilations (itunes one)
        unwanted = ["variout artists", "multi-interprètes"]
        if item.artists[0].lower() in unwanted:
            if len(item.artists) > 1:
                artist = item.artists[1]
            else:
                artist = ""
        else:
            artist = item.artists[0]
        unescaped = "%s %s" % (artist, item.name)
        for c in ['/', '?', '!']:
            if c in unescaped:
                unescaped = unescaped.replace(c, ' ')

        search = GLib.uri_escape_string(unescaped, '', True)
        try:
            # Strip /? as API doesn't like it
            f = Lio.File.new_for_uri("http://app.jgm90.com/cmapi/search/"
                                     "%s/1/10" % search.strip('/?'))
            (status, data, tag) = f.load_contents(None)
            if status:
                decode = json.loads(data.decode('utf-8'))
                for song in decode['result']['songs']:
                    try:
                        song_artist = escape(
                            song['artists'][0]['name'].lower())
                        if song_artist == escape(artist.lower()):
                            return song['id']
                    except Exception as e:
                        print("WebJmg90::__get_jmg_id():", e)
        except IndexError:
            pass
        except KeyError:
            pass
        except Exception as e:
            print("WebJmg90::__get_jmg_id():", e)
        return None
Пример #35
0
    def __get_jgm_id(self, item):
        """
            Get jmg id
            @param item as SearchItem
            @return jpg id as str
        """
        # Try to handle compilations (itunes one)
        unwanted = ["variout artists", "multi-interprètes"]
        if item.artists[0].lower() in unwanted:
            if len(item.artists) > 1:
                artist = item.artists[1]
            else:
                artist = ""
        else:
            artist = item.artists[0]
        unescaped = "%s %s" % (artist, item.name)
        for c in ["/", "?", "!"]:
            if c in unescaped:
                unescaped = unescaped.replace(c, " ")

        search = GLib.uri_escape_string(unescaped, "", True)
        try:
            f = Lio.File.new_for_uri("http://app.jgm90.com/cmapi/search/"
                                     "%s/1/10" % search)
            (status, data, tag) = f.load_contents(None)
            if status:
                decode = json.loads(data.decode("utf-8"))
                for song in decode["result"]["songs"]:
                    try:
                        song_artist = escape(
                            song["artists"][0]["name"].lower())
                        if song_artist == escape(artist.lower()):
                            return song["id"]
                    except Exception as e:
                        print("WebJmg90::__get_jmg_id():", e)
        except IndexError:
            pass
        except KeyError:
            pass
        except Exception as e:
            print("WebJmg90::__get_jmg_id():", e)
        return None
Пример #36
0
 def remove(prefix, suffix):
     """
         Remove info from store
         @param prefix as str
         @param suffix as str
     """
     filepath = "%s/%s_%s.txt" % (InfoCache._INFO_PATH, escape(prefix),
                                  suffix)
     f = Gio.File.new_for_path(filepath)
     try:
         f.delete(None)
     except:
         pass
     filepath = "%s/%s_%s.jpg" % (InfoCache._INFO_PATH, escape(prefix),
                                  suffix)
     f = Gio.File.new_for_path(filepath)
     try:
         f.delete(None)
     except:
         pass
Пример #37
0
 def exists_in_cache(prefix):
     """
         Return True if an info is cached
         @param prefix as string
     """
     exists = False
     for suffix in ["lastfm", "wikipedia", "spotify"]:
         filepath = "%s/%s_%s_%s.jpg" % (InfoCache.CACHE_PATH, escape(prefix), suffix, ArtSize.ARTIST)
         if path.exists(filepath):
             exists = True
     return exists
Пример #38
0
 def exists(prefix):
     """
         Return True if an info is cached
         @param prefix as string
     """
     exists = False
     for (suffix, helper1, helper2) in InfoCache.WEBSERVICES:
         filepath = "%s/%s_%s.jpg" % (InfoCache._INFO_PATH, escape(prefix),
                                      suffix)
         if path.exists(filepath):
             exists = True
     return exists
Пример #39
0
 def uncache_artwork(artist):
     """
         Remove artwork from cache
         @param artist as str
     """
     try:
         from pathlib import Path
         search = "%s*.jpg" % escape(artist)
         for p in Path(InformationStore._CACHE_PATH).glob(search):
             p.unlink()
     except Exception as e:
         Logger.error("InformationStore::uncache_artwork(): %s" % e)
Пример #40
0
 def get_bio(artist):
     """
         Get content from cache
         @param artist as str
         @return content as bytes
     """
     filepath = "%s/%s.txt" % (InformationStore._INFO_PATH, escape(artist))
     content = None
     f = Gio.File.new_for_path(filepath)
     if f.query_exists():
         (status, content, tag) = f.load_contents()
     return content
 def get_information(self, artist):
     """
         Get artist information
         @param artist as str
         @return content as bytes
     """
     filepath = "%s/%s.txt" % (App().art._INFO_PATH, escape(artist))
     content = None
     f = Gio.File.new_for_path(filepath)
     if f.query_exists():
         (status, content, tag) = f.load_contents()
     return content
Пример #42
0
 def __get_jgm_id(self, item):
     """
         Get jmg id
         @param item as SearchItem
         @return jpg id as str
     """
     # Try to handle compilations (itunes one)
     if item.artists[0].lower() == "various artists":
         if len(item.artists) > 1:
             artist = item.artists[1]
         else:
             artist = ""
     else:
         artist = item.artists[0]
     unescaped = "%s %s" % (artist,
                            item.name)
     search = GLib.uri_escape_string(unescaped,
                                     None,
                                     True)
     try:
         f = Gio.File.new_for_uri("http://app.jgm90.com/cmapi/search/"
                                  "%s/1/10" % search)
         (status, data, tag) = f.load_contents(None)
         if status:
             decode = json.loads(data.decode('utf-8'))
             for song in decode['result']['songs']:
                 try:
                     song_artist = escape(
                                         song['artists'][0]['name'].lower())
                     if song_artist == escape(artist.lower()):
                         return song['id']
                 except:
                     pass
     except IndexError:
         pass
     except KeyError:
         pass
     except Exception as e:
         print("WebJmg90::__get_jmg_id():", e)
     return None
Пример #43
0
 def remove(prefix, suffix):
     """
         Remove info from store
         @param prefix as str
         @param suffix as str
     """
     filepath = "%s/%s_%s.txt" % (InfoCache._INFO_PATH,
                                  escape(prefix),
                                  suffix)
     f = Gio.File.new_for_path(filepath)
     try:
         f.delete(None)
     except:
         pass
     filepath = "%s/%s_%s.jpg" % (InfoCache._INFO_PATH,
                                  escape(prefix),
                                  suffix)
     f = Gio.File.new_for_path(filepath)
     try:
         f.delete(None)
     except:
         pass
Пример #44
0
 def __on_label_button_release_event(self, button, event):
     """
         Show information cache (for edition)
         @param button as Gtk.Button
         @param event as Gdk.Event
     """
     uri = "file://%s/%s.txt" % (App().art._INFO_PATH,
                                 escape(self.__artist_name))
     f = Gio.File.new_for_uri(uri)
     if not f.query_exists():
         f.replace_contents(b"", None, False, Gio.FileCreateFlags.NONE,
                            None)
     Gtk.show_uri_on_window(App().window, uri, Gdk.CURRENT_TIME)
Пример #45
0
 def uncache(prefix, suffix):
     """
         Remove info from cache
         @param prefix as str
         @param suffix as str
     """
     filepath = "%s/%s_%s.txt" % (InfoCache.CACHE_PATH,
                                  escape(prefix),
                                  suffix)
     f = Gio.File.new_for_path(filepath)
     try:
         f.delete(None)
     except:
         pass
     filepath = "%s/%s_%s.jpg" % (InfoCache.CACHE_PATH,
                                  escape(prefix),
                                  suffix)
     f = Gio.File.new_for_path(filepath)
     try:
         f.delete(None)
     except:
         pass
     Lp().art.emit('artist-artwork-changed', prefix)
Пример #46
0
 def __get_youtube_score(self, page_title, title, artist, album):
     """
         Calculate youtube score
         if page_title looks like (title, artist, album), score is lower
         @return int
     """
     page_title = escape(page_title.lower(), [])
     artist = escape(artist.lower(), [])
     album = escape(album.lower(), [])
     title = escape(title.lower(), [])
     # YouTube page title should be at least as long as wanted title
     if len(page_title) < len(title):
         return self.__BAD_SCORE
     # Remove common word for a valid track
     page_title = page_title.replace('official', '')
     page_title = page_title.replace('video', '')
     page_title = page_title.replace('audio', '')
     # Remove artist name
     page_title = page_title.replace(artist, '')
     # Remove album name
     page_title = page_title.replace(album, '')
     # Remove title
     page_title = page_title.replace(title, '')
     return len(page_title)
Пример #47
0
 def get(prefix, suffix):
     """
         Get content from cache
         @param prefix as str
         @param suffix as str
         @return (content as string, data as bytes)
     """
     filepath = "%s/%s_%s" % (InfoCache.CACHE_PATH, escape(prefix), suffix)
     content = None
     data = None
     if path.exists(filepath + ".txt"):
         f = Gio.File.new_for_path(filepath + ".txt")
         (status, content, tag) = f.load_contents()
         if not status:
             content = None
         image_path = filepath + "_" + str(ArtSize.ARTIST) + ".jpg"
         if path.exists(image_path):
             f = Gio.File.new_for_path(image_path)
             (status, data, tag) = f.load_contents()
             if not status:
                 data = None
     return (content, data)
Пример #48
0
 def get_artwork(prefix, suffix, size):
     """
         Return path for artwork
         @param prefix as string
         @param suffix as string
         @param size as int
         @return path as string/None
     """
     try:
         for (suffix, helper1, helper2) in InfoCache.WEBSERVICES:
             extract = None
             filepath = "%s/%s_%s.jpg" % (InfoCache._INFO_PATH,
                                          escape(prefix),
                                          suffix)
             filepath_at_size = "%s/%s_%s_%s.jpg" % (InfoCache._CACHE_PATH,
                                                     escape(prefix),
                                                     suffix,
                                                     size)
             if not path.exists(filepath) or path.getsize(filepath) == 0:
                 filepath_at_size = None
                 continue
             # Make cache for this size
             if not path.exists(filepath_at_size):
                 pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(filepath,
                                                                 size,
                                                                 size)
                 if pixbuf.get_height() > pixbuf.get_width():
                     vertical = True
                 elif pixbuf.get_height() < pixbuf.get_width():
                     vertical = False
                 else:
                     extract = pixbuf
                 if extract is None:
                     del pixbuf
                     extract = GdkPixbuf.Pixbuf.new(
                                                 GdkPixbuf.Colorspace.RGB,
                                                 True, 8,
                                                 size, size)
                     if vertical:
                         pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
                                                                   filepath,
                                                                   size,
                                                                   -1,
                                                                   True)
                         diff = pixbuf.get_height() - size
                         pixbuf.copy_area(0, diff/2,
                                          pixbuf.get_width(),
                                          size,
                                          extract,
                                          0, 0)
                     else:
                         pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
                                                                   filepath,
                                                                   -1,
                                                                   size,
                                                                   True)
                         diff = pixbuf.get_width() - size
                         pixbuf.copy_area(diff/2, 0,
                                          size,
                                          pixbuf.get_height(),
                                          extract,
                                          0, 0)
                     del pixbuf
                 extract.savev(filepath_at_size, "jpeg",
                               ["quality"], ["90"])
                 del extract
             return filepath_at_size
     except Exception as e:
         print("InfoCache::get_artwork():", e)
         return None
Пример #49
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 track.uri.startswith('https:'):
                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)
            f = Lio.File.new_for_uri(track.uri)
            track_name = f.get_basename()
            # Check extension, if not mp3, convert
            m = match('.*(\.[^.]*)', track.uri)
            ext = m.group(1)
            if ext != ".mp3" and self.__convert:
                track_name = track_name.replace(ext, ".mp3")
            on_disk = Lio.File.new_for_uri(track.uri)
            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)
            # To be sure to get uri correctly escaped for Gio
            f = Lio.File.new_for_uri(dst_uri)
            track_uris.append(f.get_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
            debug("MtpSync::__remove_from_device(): %s" % uri)
            if uri not in track_uris and uri not in self.__copied_art_uris:
                debug("MtpSync::__remove_from_device(): deleting %s" % uri)
                to_delete = Lio.File.new_for_uri(uri)
                self.__retry(to_delete.delete, (None,))
            self.__done += 1
            self._fraction = self.__done/self.__total
Пример #50
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 = Lio.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 track.uri.startswith('https:'):
                    continue
                debug("MtpSync::__copy_to_device(): %s" % track.uri)
                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 = Lio.File.new_for_uri(on_device_album_uri)
                if not d.query_exists():
                    self.__retry(d.make_directory_with_parents, (None,))
                # Copy album art
                art = Lp().art.get_album_artwork_uri(track.album)
                debug("MtpSync::__copy_to_device(): %s" % art)
                if art is not None:
                    src_art = Lio.File.new_for_uri(art)
                    art_uri = "%s/cover.jpg" % on_device_album_uri
                    # To be sure to get uri correctly escaped for Gio
                    f = Lio.File.new_for_uri(art_uri)
                    self.__copied_art_uris.append(f.get_uri())
                    dst_art = Lio.File.new_for_uri(art_uri)
                    if not dst_art.query_exists():
                        self.__retry(src_art.copy,
                                     (dst_art, Gio.FileCopyFlags.OVERWRITE,
                                      None, None))
                f = Lio.File.new_for_uri(track.uri)
                track_name = f.get_basename()
                # Check extension, if not mp3, convert
                m = match('.*(\.[^.]*)', track.uri)
                ext = m.group(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 = Lio.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 = Lio.File.new_for_uri(dst_uri)
                if not dst_track.query_exists():
                    if convertion_needed:
                        mp3_uri = "file:///tmp/%s" % track_name
                        mp3_file = Lio.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 = Lio.File.new_for_uri(self._uri+'/'+playlist_name+'.m3u')
                self.__retry(m3u.move,
                             (dst, Gio.FileCopyFlags.OVERWRITE, None, None))
Пример #51
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_track_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 = escape(track.album_name.lower())
                artists = escape(", ".join(track.artists).lower())
                on_device_album_uri = "%s/tracks/%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))

                track_name = escape(GLib.basename(track.path))
                # 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" %\
                            (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._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 = escape(playlist_name)
                dst = Gio.File.new_for_uri(self._uri+'/'+playlist_name+'.m3u')
                self._retry(m3u.move,
                            (dst, Gio.FileCopyFlags.OVERWRITE, None, None))