def __download_wikia_lyrics(self):
     """
         Downloas lyrics from wikia
     """
     self.__downloads_running += 1
     # Update lyrics
     if self.__current_track.id == Type.RADIOS:
         split = self.__current_track.name.split(" - ")
         if len(split) < 2:
             return
         artist = GLib.uri_escape_string(split[0], None, False)
         title = GLib.uri_escape_string(split[1], None, False)
     else:
         if self.__current_track.artists:
             artist = GLib.uri_escape_string(
                 self.__current_track.artists[0], None, False)
         elif self.__current_track.album_artists:
             artist = self.__current_track.album_artists[0]
         else:
             artist = ""
         title = GLib.uri_escape_string(self.__current_track.name, None,
                                        False)
     uri = "https://lyrics.wikia.com/wiki/%s:%s" % (artist, title)
     helper = TaskHelper()
     helper.load_uri_content(uri, self.__cancellable,
                             self.__on_lyrics_downloaded, "lyricbox", "\n")
 def _get_audiodb_album_artwork_uri(self, artist, album, cancellable=None):
     """
         Get album artwork from audiodb
         @param artist as str
         @param album as str
         @param cancellable as Gio.Cancellable
         @return uri as str
         @thread safe
     """
     if not get_network_available("AUDIODB"):
         return None
     try:
         album = GLib.uri_escape_string(album, None, True)
         artist = GLib.uri_escape_string(artist, None, True)
         uri = "https://theaudiodb.com/api/v1/json/"
         uri += "%s/searchalbum.php?s=%s&a=%s" % (AUDIODB_CLIENT_ID, artist,
                                                  album)
         (status,
          data) = App().task_helper.load_uri_content_sync(uri, cancellable)
         if status:
             decode = json.loads(data.decode("utf-8"))
             if decode["album"]:
                 for item in decode["album"]:
                     uri = item["strAlbumThumb"]
                     return uri
     except Exception as e:
         Logger.error("ArtDownloader::_get_audiodb_album_artwork_uri: %s" %
                      e)
     return None
Beispiel #3
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 = GLib.uri_escape_string(album_name,
                                        "",
                                        False)
         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 = GLib.uri_escape_string(info.get_name(),
                                                "",
                                                False)
                 children.append("%s/tracks/%s/%s" % (self._uri,
                                                      album,
                                                      track))
     return children
Beispiel #4
0
 def _on_map_lyrics(self, widget):
     """
         Load on map
         @param widget as Gtk.Viewport
     """
     self._on_child_unmap(widget)
     Lp().settings.set_value('infoswitch', GLib.Variant('s', 'lyrics'))
     self.__jump_button.hide()
     if self.__current_track.id is None:
         self.__current_track = Lp().player.current_track
     # First try to get lyrics from tags
     from lollypop.tagreader import TagReader
     reader = TagReader()
     try:
         info = reader.get_info(self.__current_track.uri)
     except:
         info = None
     lyrics = ""
     if info is not None:
         tags = info.get_tags()
         lyrics = reader.get_lyrics(tags)
     if lyrics or InfoPopover.WebView is None\
             or not get_network_available():
         label = Gtk.Label()
         label.set_vexpand(True)
         label.set_hexpand(True)
         label.set_margin_top(10)
         label.set_margin_end(10)
         label.show()
         widget.add(label)
         if lyrics:
             label.set_label(lyrics)
         elif not get_network_available():
             string = GLib.markup_escape_text(_("Network access disabled"))
             label.get_style_context().add_class('dim-label')
             label.set_markup("<span font_weight='bold' size='xx-large'>" +
                              string + "</span>")
         else:
             string = GLib.markup_escape_text(
                 _("No lyrics found, please install gir1.2-webkit2-4.0"))
             label.get_style_context().add_class('dim-label')
             label.set_markup("<span font_weight='bold' size='xx-large'>" +
                              string + "</span>")
     elif get_network_available():
         title = self.__current_track.name
         if self.__current_track.id == Type.RADIOS:
             search = GLib.uri_escape_string(title, None, True)
         else:
             artists = ", ".join(Lp().player.current_track.artists)
             search = GLib.uri_escape_string(artists + " " + title, None,
                                             True)
         url = "http://genius.com/search?q=%s" % search
         # Delayed load due to WebKit memory loading and Gtk animation
         web = self.WebView(True, True)
         web.add_word('search')
         web.add_word('lyrics')
         web.show()
         widget.add(web)
         GLib.timeout_add(250, web.load, url, OpenLink.OPEN)
Beispiel #5
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 #6
0
    def __on_decide_destination(self, download, filename, wanted_filename):
        """
            Modify destination if needed
            @param download as WebKit2.Download
            @param filename as str
            @param wanted_filename as str
        """
        filename = filename.replace("/", "_")
        extension = filename.split(".")[-1]
        if wanted_filename:
            # FIXME We should find a way to pass good extension,
            # fallback to avi
            if extension == filename:
                extension = "avi"
            filename = wanted_filename + "." + extension
        directory_uri = App().settings.get_value('download-uri').get_string()
        if not directory_uri:
            directory = GLib.get_user_special_dir(
                GLib.UserDirectory.DIRECTORY_DOWNLOAD)
            directory_uri = GLib.filename_to_uri(directory, None)
        destination_uri = "%s/%s" % (directory_uri,
                                     GLib.uri_escape_string(filename,
                                                            None,
                                                            False))
        not_ok = True
        i = 1
        try:
            while not_ok:
                f = Gio.File.new_for_uri(destination_uri)
                if f.query_exists():
                    extension_less = filename.replace(".%s" % extension, "")
                    new_filename = "%s_%s.%s" % (extension_less, i, extension)
                    destination_uri = "%s/%s" % (directory_uri,
                                                 GLib.uri_escape_string(
                                                     new_filename,
                                                     None,
                                                     False))
                else:
                    not_ok = False
                i += 1
        except:
            # Fallback to be sure
            destination_uri = "%s/@@%s" % (directory_uri,
                                           GLib.uri_escape_string(
                                               filename,
                                               None,
                                               False))

        webkit_uri = GLib.uri_unescape_string(destination_uri, None)
        download.set_destination(webkit_uri)
        self.emit('download-start', str(download))
        # Notify user about download
        window = App().active_window
        if window is not None:
            window.toolbar.end.show_download(download)
Beispiel #7
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 #8
0
 def get_artist_id(self, artist_name, cancellable):
     """
         Get artist id
         @param artist_name as str
         @param cancellable as Gio.Cancellable
         @return str/None
     """
     try:
         artist_name = GLib.uri_escape_string(artist_name, None,
                                              True).replace(" ", "+")
         token = App().ws_director.token_ws.get_token(
             "SPOTIFY", cancellable)
         bearer = "Bearer %s" % token
         headers = [("Authorization", bearer)]
         uri = "https://api.spotify.com/v1/search?q=%s&type=artist" %\
             artist_name
         (status,
          data) = App().task_helper.load_uri_content_sync_with_headers(
              uri, headers, cancellable)
         if status:
             decode = json.loads(data.decode("utf-8"))
             for item in decode["artists"]["items"]:
                 return item["id"]
     except Exception as e:
         Logger.error("SpotifyWebHelper::get_artist_id(): %s", e)
     return None
 def tracks(self, name):
     """
         Return tracks containing name
         @param name as str
     """
     try:
         formated = GLib.uri_escape_string(name, None, True).replace(
                                                                   ' ', '+')
         s = Lio.File.new_for_uri("https://api.spotify.com/v1/search?q=%s"
                                  "&type=track" % formated)
         (status, data, tag) = s.load_contents(self._cancel)
         if status:
             decode = json.loads(data.decode('utf-8'))
             tracks = []
             for item in decode['tracks']['items']:
                 if item['name'].lower() in tracks:
                     continue
                 album_item = SearchItem()
                 search_item = SearchItem()
                 search_item.is_track = True
                 search_item.name = item['name']
                 album_item.name = item['name']
                 search_item.album = album_item
                 tracks.append(search_item.name.lower())
                 search_item.tracknumber = int(item['track_number'])
                 search_item.discnumber = int(item['disc_number'])
                 search_item.duration = int(item['duration_ms']) / 1000
                 search_item.cover = item['album']['images'][0]['url']
                 search_item.smallcover = item['album']['images'][2]['url']
                 for artist in item['artists']:
                     search_item.artists.append(artist['name'])
                 self._items.append(search_item)
                 GLib.idle_add(self.emit, 'item-found')
     except Exception as e:
         print("SpotifySearch::tracks(): %s" % e)
Beispiel #10
0
 def _get_deezer_album_artwork(self, artist, album):
     """
         Get album artwork from deezer
         @param artist as string
         @param album as string
         @return image as bytes
         @tread safe
     """
     image = None
     try:
         album_formated = GLib.uri_escape_string(album, None, True)
         s = Lio.File.new_for_uri("https://api.deezer.com/search/album/?"
                                  "q=%s&output=json" %
                                  album_formated)
         (status, data, tag) = s.load_contents()
         if status:
             decode = json.loads(data.decode('utf-8'))
             url = None
             for item in decode['data']:
                 if item['artist']['name'].lower() == artist.lower():
                     url = item['cover_xl']
                     break
             if url is not None:
                 s = Lio.File.new_for_uri(url)
                 (status, image, tag) = s.load_contents()
     except Exception as e:
         print("Downloader::__get_deezer_album_artwork: %s" % e)
     return image
Beispiel #11
0
 def _get_spotify_artist_artwork_uri(self, artist, cancellable=None):
     """
         Get artist artwork using Spotify
         @param artist as str
         @param cancellable as Gio.Cancellable
         @return uri as str
         @tread safe
     """
     if not get_network_available("SPOTIFY"):
         return []
     try:
         artist_formated = GLib.uri_escape_string(
             artist, None, True).replace(" ", "+")
         uri = "https://api.spotify.com/v1/search?q=%s" % artist_formated +\
               "&type=artist"
         token = App().ws_director.token_ws.get_token("SPOTIFY",
                                                      cancellable)
         bearer = "Bearer %s" % token
         headers = [("Authorization", bearer)]
         (status,
          data) = App().task_helper.load_uri_content_sync_with_headers(
                 uri, headers, cancellable)
         if status:
             uri = None
             decode = json.loads(data.decode("utf-8"))
             for item in decode["artists"]["items"]:
                 if noaccents(item["name"].lower()) ==\
                         noaccents(artist.lower()):
                     uri = item["images"][0]["url"]
                     return [uri]
     except Exception as e:
         Logger.warning("%s %s", e, artist)
         Logger.warning(
             "DownloaderArt::_get_spotify_artist_artwork_uri(): %s", data)
     return []
 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
 def _get_deezer_artist_artwork_uri(self, artist, cancellable=None):
     """
         Return deezer artist information
         @param artist as str
         @param cancellable as Gio.Cancellable
         @return uri as str
         @tread safe
     """
     if not get_network_available("DEEZER"):
         return None
     try:
         artist_formated = GLib.uri_escape_string(artist, None,
                                                  True).replace(" ", "+")
         uri = "https://api.deezer.com/search/artist/?" +\
               "q=%s&output=json&index=0&limit=1&" % artist_formated
         (status,
          data) = App().task_helper.load_uri_content_sync(uri, cancellable)
         if status:
             uri = None
             decode = json.loads(data.decode("utf-8"))
             uri = decode["data"][0]["picture_xl"]
             return uri
     except Exception as e:
         Logger.debug(
             "ArtDownloader::_get_deezer_artist_artwork_uri(): %s" % e)
     return None
Beispiel #14
0
 def _get_itunes_album_artwork(self, artist, album):
     """
         Get album artwork from itunes
         @param artist as string
         @param album as string
         @return image as bytes
         @tread safe
     """
     image = None
     try:
         album_formated = GLib.uri_escape_string(album, None,
                                                 True).replace(" ", "+")
         uri = "https://itunes.apple.com/search" +\
               "?entity=album&term=%s" % album_formated
         helper = TaskHelper()
         (status, data) = helper.load_uri_content_sync(uri, None)
         if status:
             decode = json.loads(data.decode("utf-8"))
             for item in decode["results"]:
                 if item["artistName"].lower() == artist.lower():
                     uri = item["artworkUrl60"].replace("60x60", "512x512")
                     (status,
                      image) = helper.load_uri_content_sync(uri, None)
                     break
     except Exception as e:
         Logger.error("Downloader::_get_album_art_itunes: %s [%s/%s]" %
                      (e, artist, album))
     return image
Beispiel #15
0
 def tracks(self, name):
     """
         Return tracks containing name
         @param name as str
     """
     try:
         formated = GLib.uri_escape_string(name, None,
                                           True).replace(' ', '+')
         s = Gio.File.new_for_uri("https://api.spotify.com/v1/search?q=%s"
                                  "&type=track" % formated)
         (status, data, tag) = s.load_contents(self._cancel)
         if status:
             decode = json.loads(data.decode('utf-8'))
             tracks = []
             for item in decode['tracks']['items']:
                 if item['name'].lower() in tracks:
                     continue
                 search_item = SearchItem()
                 search_item.is_track = True
                 search_item.name = item['name']
                 tracks.append(search_item.name.lower())
                 search_item.album = item['album']['name']
                 search_item.tracknumber = int(item['track_number'])
                 search_item.discnumber = int(item['disc_number'])
                 search_item.duration = int(item['duration_ms']) / 1000
                 search_item.cover = item['album']['images'][0]['url']
                 search_item.smallcover = item['album']['images'][2]['url']
                 for artist in item['artists']:
                     search_item.artists.append(artist['name'])
                 self._items.append(search_item)
                 GLib.idle_add(self.emit, 'item-found')
     except Exception as e:
         print("SpotifySearch::tracks(): %s" % e)
Beispiel #16
0
 def _get_deezer_album_artwork(self, artist, album):
     """
         Get album artwork from deezer
         @param artist as string
         @param album as string
         @return image as bytes
         @tread safe
     """
     image = None
     try:
         album_formated = GLib.uri_escape_string(album, None, True)
         uri = "https://api.deezer.com/search/album/?" +\
               "q=%s&output=json" % album_formated
         helper = TaskHelper()
         (status, data) = helper.load_uri_content_sync(uri, None)
         if status:
             decode = json.loads(data.decode("utf-8"))
             uri = None
             for item in decode["data"]:
                 if item["artist"]["name"].lower() == artist.lower():
                     uri = item["cover_xl"]
                     break
             if uri is not None:
                 (status, image) = helper.load_uri_content_sync(uri, None)
     except Exception as e:
         Logger.error("Downloader::__get_deezer_album_artwork: %s" % e)
     return image
Beispiel #17
0
    def __get_youtube_id_fallback(self, item):
        """
            Get youtube id (fallback)
            @param item as SearchItem
            @return youtube id as str
        """
        try:
            from bs4 import BeautifulSoup
        except:
            print("$ sudo pip3 install beautifulsoup4")
            return None
        try:
            # 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.replace(' ', '+'), None,
                                            True)
            f = Gio.File.new_for_uri("https://www.youtube.com/"
                                     "results?search_query=%s" % search)
            (status, data, tag) = f.load_contents(None)
            if not status:
                return None

            html = data.decode('utf-8')
            soup = BeautifulSoup(html, 'html.parser')
            ytems = []
            for link in soup.findAll('a'):
                href = link.get('href')
                title = link.get('title')
                if href is None or title is None:
                    continue
                if href.startswith("/watch?v="):
                    href = href.replace("/watch?v=", "")
                    ytems.append((href, title))
            dic = {}
            best = self.__BAD_SCORE
            for (yid, title) in ytems:
                score = self.__get_youtube_score(title, item.name, artist,
                                                 item.album)
                if score < best:
                    best = score
                elif score == best:
                    continue  # Keep first result
                dic[score] = yid
            # Return url from first dic item
            if best == self.__BAD_SCORE:
                return None
            else:
                return dic[best]
        except Exception as e:
            print("Youtube::__get_youtube_id_fallback():", e)
            self.__fallback = True
        return None
Beispiel #18
0
 def _on_map_lyrics(self, widget):
     """
         Load on map
         @param widget as Gtk.Viewport
     """
     self._on_child_unmap(widget)
     Lp().settings.set_value('infoswitch',
                             GLib.Variant('s', 'lyrics'))
     self.__jump_button.hide()
     if self.__current_track.id is None:
         self.__current_track = Lp().player.current_track
     # First try to get lyrics from tags
     from lollypop.tagreader import TagReader
     reader = TagReader()
     try:
         info = reader.get_info(self.__current_track.uri)
     except:
         info = None
     lyrics = ""
     if info is not None:
         tags = info.get_tags()
         lyrics = reader.get_lyrics(tags)
     if lyrics or InfoPopover.WebView is None\
             or not get_network_available():
         label = Gtk.Label()
         label.set_vexpand(True)
         label.set_hexpand(True)
         label.set_margin_top(10)
         label.set_margin_end(10)
         label.show()
         widget.add(label)
         if lyrics:
             label.set_label(lyrics)
         elif not get_network_available():
             string = GLib.markup_escape_text(_("Network access disabled"))
             label.get_style_context().add_class('dim-label')
             label.set_markup(
                    "<span font_weight='bold' size='xx-large'>" +
                    string +
                    "</span>")
         else:
             string = GLib.markup_escape_text(
                    _("No lyrics found, please install gir1.2-webkit2-4.0"))
             label.get_style_context().add_class('dim-label')
             label.set_markup(
                    "<span font_weight='bold' size='xx-large'>" +
                    string +
                    "</span>")
     elif get_network_available():
         artists = ", ".join(Lp().player.current_track.artists)
         title = self.__current_track.name
         search = GLib.uri_escape_string(artists + " " + title, None, True)
         url = "http://genius.com/search?q=%s" % search
         # Delayed load due to WebKit memory loading and Gtk animation
         web = self.WebView(True, True)
         web.add_word('search')
         web.add_word('lyrics')
         web.show()
         widget.add(web)
         GLib.timeout_add(250, web.load, url, OpenLink.OPEN)
Beispiel #19
0
    def get_duck_arts(self, search):
        """
            Get arts on duck image corresponding to search
            @param search words as string
            @return [urls as string]
        """
        data = None
        urls = []

        if not Gio.NetworkMonitor.get_default().get_network_available():
            return []

        try:
            f = Gio.File.new_for_uri("https://duckduckgo.com/i.js"
                                     "?q=%s&ia=images" %
                                     (GLib.uri_escape_string(search,
                                                             "",
                                                             False),))
            (status, data, tag) = f.load_contents()
            if not status:
                return []
        except Exception as e:
            print(e)
            return []
        try:
            decode = json.loads(data.decode('utf-8'))
            if decode is None:
                return urls
            for item in decode['results']:
                urls.append(item['image'])
        except:
            pass

        return urls
Beispiel #20
0
 def tracks(self, name):
     """
         Return tracks containing name
         @param name as str
     """
     try:
         formated = GLib.uri_escape_string(name, None,
                                           True).replace(' ', '+')
         s = Lio.File.new_for_uri("https://itunes.apple.com/search"
                                  "?entity=musicTrack&term=%s" % formated)
         (status, data, tag) = s.load_contents(self._cancel)
         if status:
             decode = json.loads(data.decode('utf-8'))
             tracks = []
             for item in decode['results']:
                 if item['trackName'].lower() in tracks:
                     continue
                 album_item = SearchItem()
                 album_item.name = item['collectionName']
                 search_item = SearchItem()
                 search_item.is_track = True
                 search_item.name = item['trackName']
                 tracks.append(search_item.name.lower())
                 search_item.album = album_item
                 search_item.tracknumber = int(item['trackNumber'])
                 search_item.discnumber = int(item['discNumber'])
                 search_item.duration = int(item['trackTimeMillis']) / 1000
                 search_item.cover = item['artworkUrl60'].replace(
                     '60x60', '512x512')
                 search_item.smallcover = item['artworkUrl100']
                 search_item.artists.append(item['artistName'])
                 self._items.append(search_item)
                 GLib.idle_add(self.emit, 'item-found')
     except Exception as e:
         print("SpotifySearch::tracks(): %s" % e)
Beispiel #21
0
 def _get_album_art_itunes(self, artist, album):
     """
         Get album artwork from itunes
         @param artist as string
         @param album as string
         @return image as bytes
         @tread safe
     """
     image = None
     try:
         album_formated = GLib.uri_escape_string(
                             album, None, True).replace(' ', '+')
         s = Gio.File.new_for_uri("https://itunes.apple.com/search"
                                  "?entity=album&term=%s" % album_formated)
         (status, data, tag) = s.load_contents()
         if status:
             decode = json.loads(data.decode('utf-8'))
             for item in decode['results']:
                 if item['artistName'].lower() == artist.lower():
                     url = item['artworkUrl60'].replace('60x60',
                                                        '512x512')
                     s = Gio.File.new_for_uri(url)
                     (status, image, tag) = s.load_contents()
                     break
     except Exception as e:
         print("ArtDownloader::_get_album_art_itunes: %s [%s/%s]" %
               (e, artist, album))
     return image
Beispiel #22
0
 def _get_album_art_itunes(self, artist, album):
     """
         Get album artwork from itunes
         @param artist as string
         @param album as string
         @return pixbuf as GdkPixbuf.Pixbuf
         @tread safe
     """
     pixbuf = None
     try:
         album_formated = GLib.uri_escape_string(
                             album, None, True).replace(' ', '+')
         s = Gio.File.new_for_uri("https://itunes.apple.com/search"
                                  "?entity=album&term=%s" % album_formated)
         (status, data, tag) = s.load_contents()
         if status:
             decode = json.loads(data.decode('utf-8'))
             for item in decode['results']:
                 if item['artistName'].lower() == artist.lower():
                     url = item['artworkUrl60'].replace('60x60',
                                                        '512x512')
                     s = Gio.File.new_for_uri(url)
                     (status, data, tag) = s.load_contents()
                     if status:
                         stream = Gio.MemoryInputStream.new_from_data(data,
                                                                      None)
                         pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(
                                     stream, ArtSize.MONSTER,
                                     ArtSize.MONSTER,
                                     False,
                                     None)
                     break
     except Exception as e:
         print("ArtDownloader::_get_album_art_itunes: %s" % e)
     return pixbuf
Beispiel #23
0
 def _get_audiodb_artist_info(self, artist):
     """
         Get artist info from audiodb
         @param artist as str
         @return info as bytes
     """
     if not get_network_available("AUDIODB"):
         return None
     try:
         artist = GLib.uri_escape_string(artist, None, True)
         uri = "https://theaudiodb.com/api/v1/json/"
         uri += "%s/search.php?s=%s" % (AUDIODB_CLIENT_ID, artist)
         (status, data) = App().task_helper.load_uri_content_sync(uri, None)
         if status:
             decode = json.loads(data.decode("utf-8"))
             language = getdefaultlocale()[0][-2:]
             for item in decode["artists"]:
                 for key in ["strBiography%s" % language, "strBiographyEN"]:
                     info = item[key]
                     if info is not None:
                         return info.encode("utf-8")
     except Exception as e:
         Logger.error("InfoDownloader::_get_audiodb_artist_info: %s, %s" %
                      (e, artist))
     return None
Beispiel #24
0
 def _get_itunes_album_artwork(self, artist, album):
     """
         Get album artwork from itunes
         @param artist as string
         @param album as string
         @return image as bytes
         @tread safe
     """
     image = None
     try:
         album_formated = GLib.uri_escape_string(
                             album, None, True).replace(' ', '+')
         s = Gio.File.new_for_uri("https://itunes.apple.com/search"
                                  "?entity=album&term=%s" % album_formated)
         (status, data, tag) = s.load_contents()
         if status:
             decode = json.loads(data.decode('utf-8'))
             for item in decode['results']:
                 if item['artistName'].lower() == artist.lower():
                     url = item['artworkUrl60'].replace('60x60',
                                                        '512x512')
                     s = Gio.File.new_for_uri(url)
                     (status, image, tag) = s.load_contents()
                     break
     except Exception as e:
         print("Downloader::_get_album_art_itunes: %s [%s/%s]" %
               (e, artist, album))
     return image
Beispiel #25
0
    def get_google_arts(self, search):
        """
            Get arts on duck image corresponding to search
            @param search words as string
            @return [urls as string]
        """
        data = None
        urls = []

        if not get_network_available():
            return []

        cs_api_key = Lp().settings.get_value('cs-api-key').get_string()

        try:
            f = Lio.File.new_for_uri("https://www.googleapis.com/"
                                     "customsearch/v1?key=%s&cx=%s"
                                     "&q=%s&searchType=image" %
                                     (cs_api_key,
                                      GOOGLE_API_ID,
                                      GLib.uri_escape_string(search,
                                                             "",
                                                             False)))

            (status, data, tag) = f.load_contents()
            if status:
                decode = json.loads(data.decode('utf-8'))
                if decode is None:
                    return urls
                for item in decode['items']:
                    urls.append(item['link'])
        except Exception as e:
            print(e)
        return urls
Beispiel #26
0
 def __fallback(self, current_search):
     """
         Fallback google image search, low quality
         @param current search as str
     """
     try:
         from bs4 import BeautifulSoup
     except:
         print("$ sudo pip3 install beautifulsoup4")
         return
     urls = []
     GLib.idle_add(self._label.set_text, _("Low quality, missing API key…"))
     try:
         for search in self.__get_current_searches():
             url = "https://www.google.fr/search?q=%s&tbm=isch" %\
                 GLib.uri_escape_string(search, None, True)
             f = Lio.File.new_for_uri(url)
             (status, data, tag) = f.load_contents()
             if status:
                 html = data.decode("utf-8")
                 soup = BeautifulSoup(html, "html.parser")
                 for link in soup.findAll("img"):
                     try:
                         urls.append(link.attrs["data-src"])
                     except:
                         pass
     except Exception as e:
         print("ArtworkSearch::__fallback: %s" % e)
     self.__add_pixbufs(urls, current_search)
Beispiel #27
0
    def get_duck_arts(self, search):
        """
            Get arts on duck image corresponding to search
            @param search words as string
            @return [urls as string]
        """
        data = None
        urls = []

        if not Gio.NetworkMonitor.get_default().get_network_available():
            return []

        try:
            f = Gio.File.new_for_uri(
                "https://duckduckgo.com/i.js"
                "?q=%s&ia=images" %
                (GLib.uri_escape_string(search, "", False), ))
            (status, data, tag) = f.load_contents()
            if not status:
                return []
        except Exception as e:
            print(e)
            return []
        try:
            decode = json.loads(data.decode('utf-8'))
            if decode is None:
                return urls
            for item in decode['results']:
                urls.append(item['image'])
        except:
            pass

        return urls
 def _get_deezer_album_artwork_uri(self, artist, album, cancellable=None):
     """
         Get album artwork uri from deezer
         @param artist as str
         @param album as str
         @param cancellable as Gio.Cancellable
         @return uri as str
         @tread safe
     """
     if not get_network_available("DEEZER"):
         return None
     try:
         album_formated = GLib.uri_escape_string(album, None, True)
         uri = "https://api.deezer.com/search/album/?" +\
               "q=%s&output=json" % album_formated
         (status,
          data) = App().task_helper.load_uri_content_sync(uri, cancellable)
         if status:
             decode = json.loads(data.decode("utf-8"))
             uri = None
             for item in decode["data"]:
                 if noaccents(item["artist"]["name"].lower()) ==\
                         noaccents(artist.lower()):
                     uri = item["cover_xl"]
                     return uri
     except Exception as e:
         Logger.error("ArtDownloader::__get_deezer_album_artwork_uri: %s" %
                      e)
     return None
Beispiel #29
0
 def __init__(self, item):
     """
         Init row
         @param item as Item
     """
     Gtk.ListBoxRow.__init__(self)
     self.__item = item
     value = GLib.uri_escape_string(item.get_property("value"), None, True)
     markup = "%s <b>%s</b>" % (item.get_property("name"), value)
     self.__label = Gtk.Label()
     self.__label.set_markup(markup)
     self.__label.set_max_width_chars(20)
     self.__label.set_property("halign", Gtk.Align.START)
     self.__label.show()
     eventbox = Gtk.EventBox()
     eventbox.show()
     eventbox.add(self.__label)
     self.add(eventbox)
     self.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, [],
                          Gdk.DragAction.MOVE)
     self.drag_source_add_text_targets()
     self.connect("drag-data-get", self.__on_drag_data_get)
     self.drag_dest_set(Gtk.DestDefaults.DROP | Gtk.DestDefaults.MOTION, [],
                        Gdk.DragAction.MOVE)
     self.drag_dest_add_text_targets()
     self.connect("drag-data-received", self.__on_drag_data_received)
     self.connect("drag-motion", self.__on_drag_motion)
     self.connect("drag-leave", self.__on_drag_leave)
Beispiel #30
0
 def __fallback(self, current_search):
     """
         Fallback google image search, low quality
         @param current search as str
     """
     try:
         from bs4 import BeautifulSoup
     except:
         print("$ sudo pip3 install beautifulsoup4")
         return
     urls = []
     GLib.idle_add(self._label.set_text,
                   _("Low quality, missing API key…"))
     try:
         for search in self.__get_current_searches():
             url = "https://www.google.fr/search?q=%s&tbm=isch" %\
                 GLib.uri_escape_string(search, None, True)
             f = Lio.File.new_for_uri(url)
             (status, data, tag) = f.load_contents()
             if status:
                 html = data.decode('utf-8')
                 soup = BeautifulSoup(html, 'html.parser')
                 for link in soup.findAll('img'):
                     try:
                         urls.append(link.attrs['data-src'])
                     except:
                         pass
     except Exception as e:
         print("ArtworkSearch::__fallback: %s" % e)
     self.__add_pixbufs(urls, current_search)
 def _get_itunes_album_artwork_uri(self, artist, album, cancellable=None):
     """
         Get album artwork uri from itunes
         @param artist as str
         @param album as str
         @param cancellable as Gio.Cancellable
         @return uri as str
         @tread safe
     """
     if not get_network_available("ITUNES"):
         return None
     try:
         album_formated = GLib.uri_escape_string(album, None,
                                                 True).replace(" ", "+")
         uri = "https://itunes.apple.com/search" +\
               "?entity=album&term=%s" % album_formated
         (status,
          data) = App().task_helper.load_uri_content_sync(uri, cancellable)
         if status:
             decode = json.loads(data.decode("utf-8"))
             for item in decode["results"]:
                 if noaccents(item["artistName"].lower()) ==\
                         noaccents(artist.lower()):
                     uri = item["artworkUrl60"].replace(
                         "60x60", "1024x1024")
                     return uri
     except Exception as e:
         Logger.error("ArtDownloader::_get_album_art_itunes_uri: %s" % e)
     return None
Beispiel #32
0
 def _get_audiodb_artist_artwork_uri(self, artist, cancellable=None):
     """
         Get artist artwork using AutdioDB
         @param artist as str
         @param cancellable as Gio.Cancellable
         @return uri as str
         @thread safe
     """
     if not get_network_available("AUDIODB"):
         return []
     try:
         artist = GLib.uri_escape_string(artist, None, True)
         uri = "https://theaudiodb.com/api/v1/json/"
         uri += "%s/search.php?s=%s" % (AUDIODB_CLIENT_ID, artist)
         (status, data) = App().task_helper.load_uri_content_sync(
             uri, cancellable)
         if status:
             decode = json.loads(data.decode("utf-8"))
             uri = None
             for item in decode["artists"]:
                 for key in ["strArtistFanart", "strArtistThumb"]:
                     uri = item[key]
                     if uri is not None:
                         return [uri]
     except Exception as e:
         Logger.warning("%s %s", e, artist)
         Logger.warning(
             "DownloaderArt::_get_audiodb_artist_artwork_uri: %s", data)
     return []
Beispiel #33
0
 def get_artist_id(self, artist_name, callback):
     """
         Get artist id
         @param artist_name as str
         @param callback as function
     """
     if self.wait_for_token():
         GLib.timeout_add(
             500, self.get_artist_id, artist_name, callback)
         return
     try:
         def on_content(uri, status, data):
             found = False
             if status:
                 decode = json.loads(data.decode("utf-8"))
                 for item in decode["artists"]["items"]:
                     found = True
                     artist_id = item["uri"].split(":")[-1]
                     callback(artist_id)
                     return
             if not found:
                 callback(None)
         artist_name = GLib.uri_escape_string(
             artist_name, None, True).replace(" ", "+")
         token = "Bearer %s" % self.__token
         helper = TaskHelper()
         helper.add_header("Authorization", token)
         uri = "https://api.spotify.com/v1/search?q=%s&type=artist" %\
             artist_name
         helper.load_uri_content(uri, None, on_content)
     except Exception as e:
         Logger.error("SpotifyHelper::get_artist_id(): %s", e)
         callback(None)
Beispiel #34
0
 def tracks(self, name):
     """
         Return tracks containing name
         @param name as str
     """
     try:
         formated = GLib.uri_escape_string(name, None, True).replace(
                                                                   " ", "+")
         s = Lio.File.new_for_uri("https://api.spotify.com/v1/search?q=%s"
                                  "&type=track" % formated)
         (status, data, tag) = s.load_contents(self._cancel)
         if status:
             decode = json.loads(data.decode("utf-8"))
             tracks = []
             for item in decode["tracks"]["items"]:
                 if item["name"].lower() in tracks:
                     continue
                 album_item = SearchItem()
                 search_item = SearchItem()
                 search_item.is_track = True
                 search_item.name = item["name"]
                 album_item.name = item["name"]
                 search_item.album = album_item
                 tracks.append(search_item.name.lower())
                 search_item.tracknumber = int(item["track_number"])
                 search_item.discnumber = int(item["disc_number"])
                 search_item.duration = int(item["duration_ms"]) / 1000
                 search_item.cover = item["album"]["images"][0]["url"]
                 search_item.smallcover = item["album"]["images"][2]["url"]
                 for artist in item["artists"]:
                     search_item.artists.append(artist["name"])
                 self._items.append(search_item)
                 GLib.idle_add(self.emit, "item-found")
     except Exception as e:
         print("SpotifySearch::tracks(): %s" % e)
Beispiel #35
0
def archive_open(path):
    """ Opens the archive @path as a GFile representing it as a directory.
    @path must be a local path (for the moment). """

    # This is crazy, but it's the only way to get it working:
    # 1. get a URI with special characters escaped.  This makes sense.
    # 2. escape that result, so it can be part of the archive:// URI.  More tricky,
    #    but still makes some sense.
    # 3. escape the URI a *3rd* time, getting e.g. "/" to %253A.  Things that got
    #    escaped in step 1 are then escaped 3 times (e.g. "é" becomes %2525A9).
    #    GOD WHY!??
    # 4. make all this an archive:// URI
    uri = GLib.filename_to_uri(path)
    for i in range(2):  # WTF, seriously!??
        uri = GLib.uri_escape_string(uri, None, False)
    uri = 'archive://' + uri
    print(uri)

    zf = Gio.File.new_for_uri(uri)

    zf._was_already_mounted = False
    try:
        func = synchronize_async(
            type(zf).mount_enclosing_volume,
            type(zf).mount_enclosing_volume_finish)
        func(zf, Gio.MountMountFlags.NONE, None, None)
    except GLib.Error as ex:
        if ex.matches(GLib.quark_from_string('g-io-error-quark'),
                      Gio.IOErrorEnum.ALREADY_MOUNTED):
            zf._was_already_mounted = True
        else:
            raise

    return zf
Beispiel #36
0
    def get_google_arts(self, search):
        """
            Get arts on duck image corresponding to search
            @param search words as string
            @return [urls as string]
        """
        data = None
        urls = []

        if not get_network_available():
            return []

        cs_api_key = Lp().settings.get_value("cs-api-key").get_string()

        try:
            f = Lio.File.new_for_uri("https://www.googleapis.com/"
                                     "customsearch/v1?key=%s&cx=%s"
                                     "&q=%s&searchType=image" %
                                     (cs_api_key,
                                      GOOGLE_API_ID,
                                      GLib.uri_escape_string(search,
                                                             "",
                                                             False)))

            (status, data, tag) = f.load_contents()
            if status:
                decode = json.loads(data.decode("utf-8"))
                if decode is None:
                    return urls
                for item in decode["items"]:
                    urls.append(item["link"])
        except Exception as e:
            print(e)
        return urls
Beispiel #37
0
 def _get_album_art_itunes(self, artist, album):
     """
         Get album artwork from itunes
         @param artist as string
         @param album as string
         @return pixbuf as GdkPixbuf.Pixbuf
         @tread safe
     """
     pixbuf = None
     try:
         album_formated = GLib.uri_escape_string(album, None,
                                                 True).replace(' ', '+')
         s = Gio.File.new_for_uri("https://itunes.apple.com/search"
                                  "?entity=album&term=%s" % album_formated)
         (status, data, tag) = s.load_contents()
         if status:
             decode = json.loads(data.decode('utf-8'))
             for item in decode['results']:
                 if item['artistName'].lower() == artist.lower():
                     url = item['artworkUrl60'].replace('60x60', '512x512')
                     s = Gio.File.new_for_uri(url)
                     (status, data, tag) = s.load_contents()
                     if status:
                         stream = Gio.MemoryInputStream.new_from_data(
                             data, None)
                         pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(
                             stream, ArtSize.MONSTER, ArtSize.MONSTER,
                             False, None)
                     break
     except Exception as e:
         print("ArtDownloader::_get_album_art_itunes: %s" % e)
     return pixbuf
Beispiel #38
0
 def tracks(self, name):
     """
         Return tracks containing name
         @param name as str
     """
     try:
         formated = GLib.uri_escape_string(name, None, True).replace(
                                                                   ' ', '+')
         s = Lio.File.new_for_uri("https://itunes.apple.com/search"
                                  "?entity=musicTrack&term=%s" % formated)
         (status, data, tag) = s.load_contents(self._cancel)
         if status:
             decode = json.loads(data.decode('utf-8'))
             tracks = []
             for item in decode['results']:
                 if item['trackName'].lower() in tracks:
                     continue
                 album_item = SearchItem()
                 album_item.name = item['collectionName']
                 search_item = SearchItem()
                 search_item.is_track = True
                 search_item.name = item['trackName']
                 tracks.append(search_item.name.lower())
                 search_item.album = album_item
                 search_item.tracknumber = int(item['trackNumber'])
                 search_item.discnumber = int(item['discNumber'])
                 search_item.duration = int(item['trackTimeMillis']) / 1000
                 search_item.cover = item['artworkUrl60'].replace('60x60',
                                                                  '512x512')
                 search_item.smallcover = item['artworkUrl100']
                 search_item.artists.append(item['artistName'])
                 self._items.append(search_item)
                 GLib.idle_add(self.emit, 'item-found')
     except Exception as e:
         print("SpotifySearch::tracks(): %s" % e)
Beispiel #39
0
    def __on_report_activate(self, action, param):
        """
            Launch bug report page
            @param action as Gio.SimpleAction
            @param param as GLib.Variant
        """
        argv = ["uname", "-a", None]
        (s, o, e, s) = GLib.spawn_sync(None, argv, None,
                                       GLib.SpawnFlags.SEARCH_PATH, None)
        if o:
            os = o.decode("utf-8")
        else:
            os = "Unknown"

        github = "https://github.com/gnumdk/eolie/issues/new?body="
        body = """
TRANSLATORS:
https://translate.zanata.org/project/view/eolie

### Environment
- Eolie version: %s
- GTK+ version: %s.%s
- Operating system: %s

### Bug/Feature
If your bug is a rendering bug or a WebKit crash, you should report it here:
https://bugs.webkit.org -> Section WebKit Gtk -> title starting with [GTK]

<Describe your bug here>""" % (self.__version, Gtk.get_major_version(),
                               Gtk.get_minor_version(), os)
        url = github + GLib.uri_escape_string(body, "", False)
        self.active_window.container.add_webview(url, LoadingType.FOREGROUND,
                                                 False)
Beispiel #40
0
 def _get_deezer_album_artwork(self, artist, album):
     """
         Get album artwork from deezer
         @param artist as string
         @param album as string
         @return image as bytes
         @tread safe
     """
     image = None
     try:
         album_formated = GLib.uri_escape_string(album, None, True)
         s = Gio.File.new_for_uri("https://api.deezer.com/search/album/?"
                                  "q=%s&output=json" %
                                  album_formated)
         (status, data, tag) = s.load_contents()
         if status:
             decode = json.loads(data.decode('utf-8'))
             url = None
             for item in decode['data']:
                 if item['artist']['name'].lower() == artist.lower():
                     url = item['cover_xl']
                     break
             if url is not None:
                 s = Gio.File.new_for_uri(url)
                 (status, image, tag) = s.load_contents()
     except Exception as e:
         print("Downloader::__get_deezer_album_artwork: %s" % e)
     return image
 def _get_spotify_artist_artwork_uri(self, artist, cancellable=None):
     """
         Return spotify artist information
         @param artist as str
         @param cancellable as Gio.Cancellable
         @return uri as str
         @tread safe
     """
     if not get_network_available("SPOTIFY"):
         return None
     try:
         artist_formated = GLib.uri_escape_string(artist, None,
                                                  True).replace(" ", "+")
         uri = "https://api.spotify.com/v1/search?q=%s" % artist_formated +\
               "&type=artist"
         token = "Bearer %s" % self.__get_spotify_token(cancellable)
         helper = TaskHelper()
         helper.add_header("Authorization", token)
         (status, data) = helper.load_uri_content_sync(uri, cancellable)
         if status:
             uri = None
             decode = json.loads(data.decode("utf-8"))
             for item in decode["artists"]["items"]:
                 if noaccents(item["name"].lower()) ==\
                         noaccents(artist.lower()):
                     uri = item["images"][0]["url"]
                     return uri
     except Exception as e:
         Logger.debug(
             "ArtDownloader::_get_spotify_artist_artwork_uri(): %s" % e)
     return None
 def __get_youtube_id(self, item):
     """
         Get youtube id
         @param item as SearchItem
         @return youtube id as str
     """
     if self.__fallback:
         return self.__get_youtube_id_fallback(item)
     # 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.replace(' ', '+'),
                         None,
                         True)
     key = Lp().settings.get_value('cs-api-key').get_string()
     try:
         f = Gio.File.new_for_uri("https://www.googleapis.com/youtube/v3/"
                                  "search?part=snippet&q=%s&"
                                  "type=video&key=%s&cx=%s" % (
                                                           search,
                                                           key,
                                                           GOOGLE_API_ID))
         (status, data, tag) = f.load_contents(None)
         if status:
             decode = json.loads(data.decode('utf-8'))
             dic = {}
             best = self.__BAD_SCORE
             for i in decode['items']:
                 score = self.__get_youtube_score(i['snippet']['title'],
                                                  item.name,
                                                  artist,
                                                  item.album)
                 if score < best:
                     best = score
                 elif score == best:
                     continue  # Keep first result
                 dic[score] = i['id']['videoId']
             # Return url from first dic item
             if best == self.__BAD_SCORE:
                 return None
             else:
                 return dic[best]
     except IndexError:
         pass
     except Exception as e:
         print("WebYouTube::__get_youtube_id():", e)
         self.__fallback = True
         return self.__get_youtube_id_fallback(item)
     return None
Beispiel #43
0
 def __on_search_timeout(self, string):
     """
         Populate widget
         @param string as str
     """
     self.__timeout_id = None
     url = "http://opml.radiotime.com/Search.ashx?query=%s" %\
         GLib.uri_escape_string(string, "/", False)
     self.populate(url)
Beispiel #44
0
 def _append_playlists(self, playlists):
     """
         Append a playlist
         @param playlists as [(int, str)]
         @param playlist selected as bool
     """
     for playlist in playlists:
         playlist_name = GLib.uri_escape_string(playlist[1], "", False)
         playlist_obj = Gio.File.new_for_uri(self._uri + "/" +
                                             playlist_name + '.m3u')
         selected = playlist_obj.query_exists(None)
         self._model.append([selected, playlist[1], playlist[0]])
Beispiel #45
0
 def __get_albums(self, name):
     """
         Get albums for name
         @param name as str
     """
     try:
         # Read album list
         formated = GLib.uri_escape_string(name, None, True).replace(
                                                                   ' ', '+')
         s = Lio.File.new_for_uri("https://itunes.apple.com/search"
                                  "?entity=album&term=%s" % formated)
         (status, data, tag) = s.load_contents(self._cancel)
         if not status:
             raise
         decode = json.loads(data.decode('utf-8'))
         # For each album, get cover and tracks
         for item in decode['results']:
             album_item = SearchItem()
             album_item.name = item['collectionName']
             album_item.is_track = False
             album_item.artists = [item['artistName']]
             album_item.cover = item['artworkUrl60'].replace('60x60',
                                                             '512x512')
             album_item.smallcover = item['artworkUrl100']
             s = Lio.File.new_for_uri("https://itunes.apple.com/lookup"
                                      "?id=%s&entity=song" %
                                      item['collectionId'])
             (status, data, tag) = s.load_contents(self._cancel)
             if not status:
                 raise
             decode = json.loads(data.decode('utf-8'))
             for item in decode['results']:
                 if item['wrapperType'] == "collection":
                     continue
                 track_item = SearchItem()
                 track_item.is_track = True
                 try:
                     track_item.year = decode['releaseDate'][:4]
                 except:
                     pass  # May be missing
                 track_item.name = item['trackName']
                 track_item.album = album_item
                 track_item.tracknumber = int(item['trackNumber'])
                 track_item.discnumber = int(item['discNumber'])
                 track_item.duration = int(item['trackTimeMillis'])\
                     / 1000
                 track_item.artists.append(item['artistName'])
                 album_item.subitems.append(track_item)
             self._items.append(album_item)
             GLib.idle_add(self.emit, 'item-found')
     except Exception as e:
         print("ItunesSearch::__get_albums(): %s" % e)
 def __append_playlists(self, playlists):
     """
         Append a playlist
         @param playlists as [(int, str)]
     """
     if playlists and not self.__stop:
         playlist = playlists.pop(0)
         playlist_name = GLib.uri_escape_string(playlist[1], "", False)
         playlist_obj = Gio.File.new_for_uri(self._uri + "/" +
                                             playlist_name + '.m3u')
         selected = playlist_obj.query_exists()
         self.__model.append([selected, playlist[1], playlist[0]])
         GLib.idle_add(self.__append_playlists, playlists)
Beispiel #47
0
 def _append_playlists(self, playlists):
     """
         Append a playlist
         @param playlists as [(int, str)]
         @param playlist selected as bool
     """
     if playlists:
         playlist = playlists.pop(0)
         playlist_name = GLib.uri_escape_string(playlist[1], "", False)
         selected = playlist_name + ".m3u" in self._on_disk_playlists
         self._model.append([selected, playlist[1], playlist[0]])
         GLib.idle_add(self._append_playlists, playlists)
     else:
         self._view.get_selection().unselect_all()
Beispiel #48
0
 def __get_albums(self, name):
     """
         Get albums for name
         @param name as str
     """
     try:
         # Read album list
         formated = GLib.uri_escape_string(name, None, True).replace(
                                                                   ' ', '+')
         s = Lio.File.new_for_uri("https://api.spotify.com/v1/search?q=%s"
                                  "&type=album" % formated)
         (status, data, tag) = s.load_contents(self._cancel)
         if status:
             decode = json.loads(data.decode('utf-8'))
             # For each album, get cover and tracks
             for item in decode['albums']['items']:
                 album_item = SearchItem()
                 album_item.name = item['name']
                 album_item.is_track = False
                 album_item.cover = item['images'][0]['url']
                 album_item.smallcover = item['images'][2]['url']
                 s = Lio.File.new_for_uri("https://api.spotify.com/v1/"
                                          "albums/%s" % item['id'])
                 (status, data, tag) = s.load_contents(self._cancel)
                 if status:
                     decode = json.loads(data.decode('utf-8'))
                     for item in decode['tracks']['items']:
                         track_item = SearchItem()
                         track_item.is_track = True
                         try:
                             track_item.year = decode[
                                                     'release_date'][:4]
                         except:
                             pass  # May be missing
                         track_item.name = item['name']
                         track_item.album = album_item
                         track_item.tracknumber = int(item['track_number'])
                         track_item.discnumber = int(item['disc_number'])
                         track_item.duration = int(item['duration_ms'])\
                             / 1000
                         for artist in item['artists']:
                             track_item.artists.append(artist['name'])
                         if not album_item.artists:
                             album_item.artists = track_item.artists
                         album_item.subitems.append(track_item)
                 self._items.append(album_item)
                 GLib.idle_add(self.emit, 'item-found')
     except Exception as e:
         print("SpotifySearch::albums(): %s" % e)
Beispiel #49
0
    def _get_album_art_spotify(self, artist, album):
        """
            Get album artwork from itunes
            @param artist as string
            @param album as string
            @return pixbuf as GdkPixbuf.Pixbuf
            @tread safe
        """
        pixbuf = None
        artists_spotify_ids = []
        try:
            artist_formated = GLib.uri_escape_string(
                                artist, None, True).replace(' ', '+')
            s = Gio.File.new_for_uri("https://api.spotify.com/v1/search?q=%s"
                                     "&type=artist" % artist_formated)
            (status, data, tag) = s.load_contents()
            if status:
                decode = json.loads(data.decode('utf-8'))
                for item in decode['artists']['items']:
                    artists_spotify_ids.append(item['id'])

            for artist_spotify_id in artists_spotify_ids:
                s = Gio.File.new_for_uri("https://api.spotify.com/v1/artists/"
                                         "%s/albums" % artist_spotify_id)
                (status, data, tag) = s.load_contents()
                if status:
                    decode = json.loads(data.decode('utf-8'))
                    url = None
                    for item in decode['items']:
                        if item['name'] == album:
                            url = item['images'][0]['url']
                            break

                    if url is not None:
                        s = Gio.File.new_for_uri(url)
                        (status, data, tag) = s.load_contents()
                        if status:
                            stream = Gio.MemoryInputStream.new_from_data(data,
                                                                         None)
                            pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(
                                        stream, ArtSize.MONSTER,
                                        ArtSize.MONSTER,
                                        False,
                                        None)
                    break
        except Exception as e:
            print("ArtDownloader::_get_album_art_spotify: %s" % e)
        return pixbuf
Beispiel #50
0
 def _append_playlists(self, playlists):
     """
         Append a playlist
         @param playlists as [(int, str)]
         @param playlist selected as bool
     """
     if playlists:
         playlist = playlists.pop(0)
         playlist_name = GLib.uri_escape_string(playlist[1], "", False)
         playlist_obj = Gio.File.new_for_uri(self._uri + "/" +
                                             playlist_name + '.m3u')
         selected = playlist_obj.query_exists(None)
         self._model.append([selected, playlist[1], playlist[0]])
         GLib.idle_add(self._append_playlists, playlists)
     else:
         self._view.get_selection().unselect_all()
Beispiel #51
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
Beispiel #52
0
 def get_spotify_artist_artwork(self, artist):
     """
         Return spotify artwork url
         @param artist as str
         @return url as str/None
     """
     try:
         artist_formated = GLib.uri_escape_string(
                             artist, None, True).replace(' ', '+')
         s = Gio.File.new_for_uri("https://api.spotify.com/v1/search?q=%s"
                                  "&type=artist" % artist_formated)
         (status, data, tag) = s.load_contents()
         if status:
             decode = json.loads(data.decode('utf-8'))
             return decode['artists']['items'][0]['images'][0]['url']
     except Exception as e:
         debug("ArtDownloader::get_spotify_artist_artwork(): %s" % e)
     return None
Beispiel #53
0
 def _get_album_art_spotify(self, artist, album):
     """
         Get album artwork from itunes
         @param artist as string
         @param album as string
         @return pixbuf as GdkPixbuf.Pixbuf
         @tread safe
     """
     pixbuf = None
     album_spotify_id = None
     try:
         album_formated = GLib.uri_escape_string(
                             album, None, True).replace(' ', '+')
         s = Gio.File.new_for_uri("https://ws.spotify.com/search/"
                                  "1/album.json?q=%s" % album_formated)
         (status, data, tag) = s.load_contents()
         if status:
             decode = json.loads(data.decode('utf-8'))
             for item in decode['albums']:
                 if item['artists'][0]['name'].lower() == artist.lower():
                     album_spotify_id = item['href'].replace(
                                 'spotify:album:', '')
                     break
         if album_spotify_id is not None:
             s = Gio.File.new_for_uri("https://api.spotify.com/"
                                      "v1/albums/%s" % album_spotify_id)
             (status, data, tag) = s.load_contents()
             if status:
                 decode = json.loads(data.decode('utf-8'))
                 url = decode['images'][0]['url']
                 s = Gio.File.new_for_uri(url)
                 (status, data, tag) = s.load_contents()
                 if status:
                     stream = Gio.MemoryInputStream.new_from_data(data,
                                                                  None)
                     pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(
                                 stream, ArtSize.MONSTER,
                                 ArtSize.MONSTER,
                                 False,
                                 None)
     except Exception as e:
         print("ArtDownloader::_get_album_art_spotify: %s" % e)
     return pixbuf
    def _dequeue(self):
        self._lock.acquire()
        if not self._queued:
            self._lock.release()
            return
        uri, target = self._queued.pop()
        # Really crappy way to figure out an extension
        extension = "." + AUDIO_ENCODER.split('enc')[0][-3:]

        target = os.path.join(MUSIC_DIRECTORY, GLib.uri_escape_string(target, None, False) + extension)
        self._lock.release()
        pipeline = Gst.parse_launch("uridecodebin uri=" + uri + " ! " + AUDIO_ENCODER + " ! filesink location=" + target)

        if self.pipeline:
            self.pipeline.disconnect_by_func(self._eosCb)
            self.pipeline.setState(Gst.State.NULL)

        self.pipeline = SimplePipeline(pipeline, None)
        self.pipeline.connect("eos", self._eosCb)
        self.pipeline.setState(Gst.State.PLAYING)
Beispiel #55
0
 def _get_deezer_artist_info(self, artist):
     """
         Return deezer artist information
         @param artist as str
         @return (url as str/None, content as None)
     """
     try:
         artist_formated = GLib.uri_escape_string(
                             artist, None, True).replace(' ', '+')
         s = Lio.File.new_for_uri("https://api.deezer.com/search/artist/?"
                                  "q=%s&output=json&index=0&limit=1&" %
                                  artist_formated)
         (status, data, tag) = s.load_contents()
         if status:
             decode = json.loads(data.decode('utf-8'))
             return (decode['data'][0]['picture_xl'], None)
     except Exception as e:
         debug("Downloader::_get_deezer_artist_artwork(): %s [%s]" %
               (e, artist))
     return (None, None)
Beispiel #56
0
    def _get_album_art_spotify(self, artist, album):
        """
            Get album artwork from itunes
            @param artist as string
            @param album as string
            @return image as bytes
            @tread safe
        """
        image = None
        artists_spotify_ids = []
        try:
            artist_formated = GLib.uri_escape_string(
                                artist, None, True).replace(' ', '+')
            s = Gio.File.new_for_uri("https://api.spotify.com/v1/search?q=%s"
                                     "&type=artist" % artist_formated)
            (status, data, tag) = s.load_contents()
            if status:
                decode = json.loads(data.decode('utf-8'))
                for item in decode['artists']['items']:
                    artists_spotify_ids.append(item['id'])

            for artist_spotify_id in artists_spotify_ids:
                s = Gio.File.new_for_uri("https://api.spotify.com/v1/artists/"
                                         "%s/albums" % artist_spotify_id)
                (status, data, tag) = s.load_contents()
                if status:
                    decode = json.loads(data.decode('utf-8'))
                    url = None
                    for item in decode['items']:
                        if item['name'] == album:
                            url = item['images'][0]['url']
                            break

                    if url is not None:
                        s = Gio.File.new_for_uri(url)
                        (status, image, tag) = s.load_contents()
                    break
        except Exception as e:
            print("ArtDownloader::_get_album_art_spotify: %s [%s/%s]" %
                  (e, artist, album))
        return image
Beispiel #57
0
 def _get_spotify_artist_info(self, artist):
     """
         Return spotify artist information
         @param artist as str
         @return (url as str/None, content as None)
     """
     try:
         artist_formated = GLib.uri_escape_string(
                             artist, None, True).replace(' ', '+')
         s = Lio.File.new_for_uri("https://api.spotify.com/v1/search?q=%s"
                                  "&type=artist" % artist_formated)
         (status, data, tag) = s.load_contents()
         if status:
             decode = json.loads(data.decode('utf-8'))
             for item in decode['artists']['items']:
                 if item['name'].lower() == artist.lower():
                     return (item['images'][0]['url'], None)
     except Exception as e:
         debug("Downloader::_get_spotify_artist_artwork(): %s [%s]" %
               (e, artist))
     return (None, None)
Beispiel #58
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
Beispiel #59
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 #60
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))