Example #1
0
 def __update_for_url(self, url):
     """
         Update charts for url
         @param url as str
     """
     if not get_network_available():
             return
     debug("SpotifyCharts::__update_for_url(): %s" % (url))
     ids = self.__get_ids(url)
     web = Web()
     search = SpotifySearch()
     position = len(ids)
     while ids:
         sleep(10)
         track_id = ids.pop(0)
         album = search.get_track(track_id)
         if self.__stop:
             return
         if album is None or not album.subitems:
             position -= 1
             continue
         for item in album.subitems:
             item.mtime = self.__time + position
         debug("SpotifyCharts::__update_for_url(): %s - %s - %s" % (
                                                             album.name,
                                                             album.artists,
                                                             track_id))
         web.save_album_thread(album, DbPersistent.CHARTS, [Type.SPOTIFY])
         position -= 1
Example #2
0
 def __scrobble(self, artist, album, title, timestamp, first=True):
     """
         Scrobble track
         @param artist as str
         @param title as str
         @param album_title as str
         @param timestamp as int
         @param duration as int
         @param first is internal
         @thread safe
     """
     debug("LastFM::__scrobble(): %s, %s, %s, %s" % (artist,
                                                     album,
                                                     title,
                                                     timestamp))
     try:
         self.scrobble(artist=artist,
                       album=album,
                       title=title,
                       timestamp=timestamp)
     except BadAuthenticationError as e:
         pass
     except Exception as e:
         print("Lastfm::scrobble():", e)
         # Scrobble sometimes fails
         if first:
             self.__connect(self.__username, self.__password)
             self.__scrobble(artist, album, title, timestamp, False)
Example #3
0
 def __connect(self, username, password, populate_loved=False):
     """
         Connect lastfm
         @param username as str
         @param password as str
         @thread safe
     """
     self.__username = username
     if self.__goa is not None or (password != '' and username != ''):
         self.__is_auth = True
     else:
         self.__is_auth = False
     try:
         self.session_key = ""
         self.__check_for_proxy()
         if self.__goa is not None:
             self.session_key = self.__goa.call_get_access_token_sync(
                                                                   None)[0]
         else:
             skg = SessionKeyGenerator(self)
             self.session_key = skg.get_session_key(
                                               username=self.__username,
                                               password_hash=md5(password))
         if populate_loved:
             self.__populate_loved_tracks()
     except Exception as e:
         debug("Lastfm::__connect(): %s" % e)
         self.__is_auth = False
Example #4
0
 def __now_playing(self, artist, album, title, duration, first=True):
     """
         Now playing track
         @param artist as str
         @param title as str
         @param album as str
         @param duration as int
         @param first is internal
         @thread safe
     """
     try:
         self.update_now_playing(artist=artist,
                                 album=album,
                                 title=title,
                                 duration=duration)
         debug("LastFM::__now_playing(): %s, %s, %s, %s" % (artist,
                                                            album,
                                                            title,
                                                            duration))
     except BadAuthenticationError:
         if Lp().notify is not None:
             GLib.idle_add(Lp().notify.send, _("Wrong Last.fm credentials"))
     except Exception as e:
         print("Lastfm::scrobble():", e)
         # now playing sometimes fails
         if first:
             self.__connect(self.__username, self.__password)
             self.__now_playing(artist, album, title, duration, False)
Example #5
0
 def __on_stream_about_to_finish(self, playbin):
     """
         When stream is about to finish, switch to next track without gap
         @param playbin as Gst bin
     """
     debug("Player::__on_stream_about_to_finish(): %s" % playbin)
     # Don't do anything if crossfade on, track already changed
     if self._crossfading:
         return
     if self.current_track.id == Type.RADIOS:
         return
     self._scrobble(self.current_track, self._start_time)
     # Increment popularity
     if not Lp().scanner.is_locked():
         Lp().tracks.set_more_popular(self.current_track.id)
         # In party mode, linear popularity
         if self.is_party:
             pop_to_add = 1
         # In normal mode, based on tracks count
         else:
             pop_to_add = int(
                 Lp().albums.max_count /
                 Lp().albums.get_tracks_count(self.current_track.album_id))
         Lp().albums.set_more_popular(self.current_track.album_id,
                                      pop_to_add)
     if self._next_track.id is not None:
         self._load_track(self._next_track)
Example #6
0
 def _load_track(self, track, init_volume=True):
     """
         Load track
         @param track as Track
         @param init volume as bool
         @return False if track not loaded
     """
     if self._need_to_stop():
         return False
     if init_volume:
         self._plugins.volume.props.volume = 1.0
     debug("BinPlayer::_load_track(): %s" % track.uri)
     try:
         if track.id in self._queue:
             self._queue_track = track
             self._queue.remove(track.id)
             self.emit('queue-changed')
             self._playbin.set_property('uri', self._queue_track.uri)
         else:
             self._current_track = track
             self._queue_track = None
             self._playbin.set_property('uri', self.current_track.uri)
     except Exception as e:  # Gstreamer error
         print("BinPlayer::_load_track(): ", e)
         self._queue_track = None
         return False
     return True
Example #7
0
 def _connect(self, username, password, populate_loved=False):
     """
         Connect lastfm
         @param username as str
         @param password as str
         @thread safe
     """
     self._username = username
     if self._goa is not None or (password != '' and username != ''):
         self._is_auth = True
     else:
         self._is_auth = False
     try:
         self._check_for_proxy()
         if self._goa is None:
             LastFMNetwork.__init__(
                 self,
                 api_key=self._API_KEY,
                 api_secret=self._API_SECRET,
                 username=self._username,
                 password_hash=md5(password))
         else:
             LastFMNetwork.__init__(
                 self,
                 api_key=self._API_KEY,
                 api_secret=self._API_SECRET,
                 session_key=self._goa.call_get_access_token_sync(None)[0])
         if populate_loved:
             self._populate_loved_tracks()
     except Exception as e:
         debug("Lastfm::_connect(): %s" % e)
         self._is_auth = False
Example #8
0
 def _add(self, files):
     GLib.idle_add(self._progress.show)
     sql = Objects.db.get_cursor()
     tracks = Objects.tracks.get_paths(sql)
     count = len(files)
     i = 0
     GLib.idle_add(self._update_progress, i, count)
     for f in files:
         track_id = None
         if not self._in_thread:
             sql.close()
             self._is_locked = False
             return
         if f not in tracks:
             infos = Objects.player.get_infos(f)
             if infos is not None:
                 debug("Adding file: %s" % f)
                 track_id = self._add2db(f, 0, infos, True, sql)
             else:
                 print("Can't get infos for ", f)
         else:
             track_id = Objects.tracks.get_id_by_path(f, sql)
         if track_id is not None:
             if i == 0:
                 sql.commit()
             GLib.idle_add(self.emit, "added", track_id, i==0)
         i += 1
         GLib.idle_add(self._update_progress, i, count)
     Objects.albums.search_compilations(True, sql)
     sql.commit()
     sql.close()
     GLib.idle_add(self._progress.hide)
     self._in_thread = False
     self._is_locked = False
Example #9
0
 def __now_playing(self, artist, album, title, duration, first=True):
     """
         Now playing track
         @param artist as str
         @param title as str
         @param album as str
         @param duration as int
         @param first is internal
         @thread safe
     """
     try:
         self.update_now_playing(artist=artist,
                                 album=album,
                                 title=title,
                                 duration=duration)
         debug("LastFM::__now_playing(): %s, %s, %s, %s" %
               (artist, album, title, duration))
     except WSError:
         pass
     except Exception as e:
         print("LastFM::__now_playing():", e)
         # now playing sometimes fails
         if first:
             self.__connect()
             self.__now_playing(artist, album, title, duration, False)
Example #10
0
 def _on_stream_start(self, bus, message):
     """
         On stream start
         Emit "current-changed" to notify others components
         @param bus as Gst.Bus
         @param message as Gst.Message
     """
     self._start_time = time()
     self._gst_duration = self._playbin.query_duration(
                                                 Gst.Format.TIME)[1] / 1000
     debug("Player::_on_stream_start(): %s" % self.current_track.uri)
     self.emit('current-changed')
     # Update now playing on lastfm
     if Lp().lastfm is not None and self.current_track.id >= 0:
         if self.current_track.album_artist_id == Type.COMPILATIONS:
             artist = self.current_track.artist
         else:
             artist = self.current_track.album_artist
             Lp().lastfm.now_playing(artist,
                                     self.current_track.album_name,
                                     self.current_track.title,
                                     int(self.current_track.duration))
     if not Lp().scanner.is_locked():
         Lp().tracks.set_listened_at(self.current_track.id, int(time()))
     self._handled_error = None
Example #11
0
 def _load_track(self, track, init_volume=True):
     """
         Load track
         @param track as Track
         @param init volume as bool
         @return False if track not loaded
     """
     if self.__need_to_stop():
         return False
     if init_volume:
         self._plugins.volume.props.volume = 1.0
     debug("BinPlayer::_load_track(): %s" % track.uri)
     try:
         self._current_track = track
         if track.is_web:
             loaded = self._load_web(track)
             # If track not loaded, go next
             if not loaded:
                 self.set_next()
                 GLib.timeout_add(500, self.__load, self.next_track,
                                  init_volume)
             return False  # Return not loaded as handled by load_web()
         else:
             self._playbin.set_property("uri", track.uri)
     except Exception as e:  # Gstreamer error
         print("BinPlayer::_load_track(): ", e)
         return False
     return True
Example #12
0
 def _load_track(self, track, init_volume=True):
     """
         Load track
         @param track as Track
         @param init volume as bool
         @return False if track not loaded
     """
     if self.__need_to_stop():
         return False
     if init_volume:
         self._plugins.volume.props.volume = 1.0
     debug("BinPlayer::_load_track(): %s" % track.uri)
     try:
         if track.id in self._queue:
             self._queue_track = track
             self._queue.remove(track.id)
             self.emit('queue-changed')
         else:
             self._current_track = track
             self._queue_track = None
         if track.is_youtube:
             loaded = self._load_youtube(track)
             # If track not loaded, go next
             if not loaded:
                 self.set_next()
                 GLib.timeout_add(500, self.__load, self.next_track,
                                  init_volume)
             return False  # Return not loaded as handled by load_youtube()
         else:
             self._playbin.set_property('uri', track.uri)
     except Exception as e:  # Gstreamer error
         print("BinPlayer::_load_track(): ", e)
         self._queue_track = None
         return False
     return True
Example #13
0
 def __connect(self, full_sync=False):
     """
         Connect service
         @param full_sync as bool
         @thread safe
     """
     if self.__goa is not None or (self.__password != ""
                                   and self.__login != ""):
         self.__is_auth = True
     else:
         self.__is_auth = False
     try:
         self.session_key = ""
         self.__check_for_proxy()
         if self.__goa is not None:
             self.session_key = self.__goa.call_get_access_token_sync(
                 None)[0]
         else:
             skg = SessionKeyGenerator(self)
             self.session_key = skg.get_session_key(username=self.__login,
                                                    password_hash=md5(
                                                        self.__password))
         if full_sync:
             self.__populate_loved_tracks()
     except Exception as e:
         debug("LastFM::__connect(): %s" % e)
         self.__is_auth = False
Example #14
0
 def __delayedclean_view(self, view):
     """
         Clean view
         @param valid view as View
     """
     debug("ViewContainer::__delayedclean_view(): %s" % view)
     view.destroy()
Example #15
0
 def __update_for_url(self, url):
     """
         Update charts for url
         @param url as str
     """
     if not get_network_available():
             return
     debug("SpotifyCharts::__update_for_url(): %s" % (url))
     ids = self.__get_ids(url)
     web = Web()
     search = SpotifySearch()
     position = len(ids)
     while ids:
         sleep(10)
         track_id = ids.pop(0)
         album = search.get_track(track_id)
         if self.__stop:
             return
         if album is None or not album.subitems:
             position -= 1
             continue
         for item in album.subitems:
             item.mtime = self.__time + position
         debug("SpotifyCharts::__update_for_url(): %s - %s - %s" % (
                                                             album.name,
                                                             album.artists,
                                                             track_id))
         web.save_album_thread(album, DbPersistent.CHARTS, [Type.SPOTIFY])
         position -= 1
Example #16
0
 def __on_stream_about_to_finish(self, playbin):
     """
         When stream is about to finish, switch to next track without gap
         @param playbin as Gst bin
     """
     debug("Player::__on_stream_about_to_finish(): %s" % playbin)
     # Don"t do anything if crossfade on, track already changed
     if self._crossfading:
         return
     if self._current_track.id == Type.RADIOS:
         return
     self._scrobble(self._current_track, self._start_time)
     # Increment popularity
     if not Lp().scanner.is_locked() and self._current_track.id >= 0:
         Lp().tracks.set_more_popular(self._current_track.id)
         # In party mode, linear popularity
         if self.is_party:
             pop_to_add = 1
         # In normal mode, based on tracks count
         else:
             # Some users report an issue where get_tracks_count() return 0
             # See issue #886
             # Don"t understand how this can happen!
             count = Lp().albums.get_tracks_count(
                 self._current_track.album_id)
             if count:
                 pop_to_add = int(Lp().albums.max_count / count)
             else:
                 pop_to_add = 1
         Lp().albums.set_more_popular(self._current_track.album_id,
                                      pop_to_add)
     if self._next_track.id is not None:
         self._load_track(self._next_track)
Example #17
0
 def _now_playing(self, artist, album, title, duration, first=True):
     """
         Now playing track
         @param artist as str
         @param title as str
         @param album as str
         @param duration as int
         @param first is internal
         @thread safe
     """
     debug("LastFM::_now_playing(): %s, %s, %s, %s" % (artist,
                                                       album,
                                                       title,
                                                       duration))
     try:
         LastFMNetwork.update_now_playing(self,
                                          artist=artist,
                                          album=album,
                                          title=title,
                                          duration=duration)
     except BadAuthenticationError:
         if Lp.notify is not None:
             GLib.idle_add(Lp.notify.send, _("Wrong Last.fm credentials"))
     except:
         # now playing sometimes fails
         if first:
             self._connect(self._username, self._password)
             self._now_playing(artist, album, title, duration, False)
Example #18
0
 def get_token(cancellable):
     """
         Get a new auth token
         @param cancellable as Gio.Cancellable
         @return str
     """
     # Remove 60 seconds to be sure
     if int(time()) + 60 < SpotifySearch.__EXPIRES and\
             SpotifySearch.__TOKEN is not None:
         debug("Use spotify token: %s" % SpotifySearch.__TOKEN)
         return SpotifySearch.__TOKEN
     try:
         token_uri = "https://accounts.spotify.com/api/token"
         credentials = "%s:%s" % (SPOTIFY_CLIENT_ID, SPOTIFY_SECRET)
         encoded = b64encode(credentials.encode("utf-8"))
         credentials = encoded.decode("utf-8")
         session = Soup.Session.new()
         data = {"grant_type": "client_credentials"}
         msg = Soup.form_request_new_from_hash("POST", token_uri, data)
         msg.request_headers.append("Authorization",
                                    "Basic %s" % credentials)
         status = session.send_message(msg)
         if status == 200:
             body = msg.get_property("response-body")
             data = body.flatten().get_data()
             decode = json.loads(data.decode("utf-8"))
             SpotifySearch.__EXPIRES = int(time()) +\
                 int(decode["expires_in"])
             SpotifySearch.__TOKEN = decode["access_token"]
             return SpotifySearch.__TOKEN
     except:
         return ""
Example #19
0
 def __delayedclean_view(self, view):
     """
         Clean view
         @param valid view as View
     """
     debug("ViewContainer::__delayedclean_view(): %s" % view)
     view.destroy()
Example #20
0
 def _scrobble(self, artist, album, title, timestamp, duration, first=True):
     """
         Scrobble track
         @param artist as str
         @param title as str
         @param album_title as str
         @param timestamp as int
         @param duration as int
         @param first is internal
         @thread safe
     """
     debug("LastFM::_scrobble(): %s, %s, %s, %s, %s" % (artist,
                                                        album,
                                                        title,
                                                        timestamp,
                                                        duration))
     try:
         LastFMNetwork.scrobble(self,
                                artist=artist,
                                album=album,
                                title=title,
                                timestamp=timestamp)
     except BadAuthenticationError as e:
         pass
     except Exception as e:
         print("Lastfm::scrobble():", e)
         # Scrobble sometimes fails
         if first:
             self._connect(self._username, self._password)
Example #21
0
 def _get_objects_for_paths(self, paths):
     """
         Return all tracks/dirs for paths
         @param paths as string
         @return ([tracks path], [dirs path], track count)
     """
     tracks = []
     track_dirs = list(paths)
     count = 0
     for path in paths:
         for root, dirs, files in os.walk(path):
             # Add dirs
             for d in dirs:
                 track_dirs.append(os.path.join(root, d))
             # Add files
             for name in files:
                 filepath = os.path.join(root, name)
                 try:
                     f = Gio.File.new_for_path(filepath)
                     if is_pls(f):
                         pass
                     elif is_audio(f):
                         tracks.append(filepath)
                         count += 1
                     else:
                         debug("%s not detected as a music file" % filepath)
                 except Exception as e:
                     print("CollectionScanner::_get_objects_for_paths: %s" %
                           e)
     return (tracks, track_dirs, count)
Example #22
0
 def __update_for_url(self, url):
     """
         Update charts for url
         @param url as str
     """
     if not Gio.NetworkMonitor.get_default().get_network_available():
         return
     debug("SpotifyCharts::__update_for_url(): %s => %s" %
           (url, self.__count))
     ids = self.__get_ids(url)
     yt = Youtube()
     search = SpotifySearch()
     while ids:
         sleep(10)
         track_id = ids.pop(0)
         album_id = search.get_album_id(track_id)
         album = search.get_album(album_id)
         if album is None or album.exists_in_db():
             continue
         if self._stop:
             return
         Lp().db.del_tracks(Lp().tracks.get_old_from_charts(self.__count))
         debug("SpotifyCharts::__update_for_url(): %s - %s - %s" %
               (album.name, album.artists, album_id))
         yt.save_album(album, DbPersistent.CHARTS)
Example #23
0
 def __get_objects_for_paths(self, paths):
     """
         Return all tracks/dirs for paths
         @param paths as string
         @return ([tracks path], [dirs path], track count)
     """
     tracks = []
     track_dirs = list(paths)
     for path in paths:
         for root, dirs, files in os.walk(path, followlinks=True):
             # Add dirs
             for d in dirs:
                 track_dirs.append(os.path.join(root, d))
             # Add files
             for name in files:
                 path = os.path.join(root, name)
                 uri = GLib.filename_to_uri(path)
                 try:
                     f = Gio.File.new_for_uri(uri)
                     if is_pls(f):
                         pass
                     elif is_audio(f):
                         tracks.append(uri)
                     else:
                         debug("%s not detected as a music file" % uri)
                 except Exception as e:
                     print(
                         "CollectionScanner::__get_objects_for_paths: %s" %
                         e)
     return (tracks, track_dirs)
Example #24
0
 def __update_for_url(self, url):
     """
         Update charts for url
         @param url as str
     """
     if not get_network_available():
         return
     debug("ItunesCharts::__update_for_url(): %s => %s" %
           (url, self.__LIMIT))
     web = Web()
     ids = self.__get_ids(url)
     position = len(ids)
     while ids:
         sleep(10)
         (itunes_id, itunes_genre) = ids.pop(0)
         album = self.__get_album(itunes_id)
         if self.__stop:
             return
         if album is None or not album.subitems:
             position -= 1
             continue
         album.mtime = self.__time + position
         for item in album.subitems:
             item.mtime = self.__time
         debug("ItunesCharts::__update_for_url(): %s - %s" %
               (album.name, album.artists))
         t = TagReader()
         with SqlCursor(Lp().db) as sql:
             genre_ids = t.add_genres(itunes_genre)
             sql.commit()
         genre_ids.append(Type.ITUNES)
         web.save_album_thread(album, DbPersistent.CHARTS, genre_ids)
         position -= 1
Example #25
0
 def _on_stream_start(self, bus, message):
     """
         On stream start
         Emit "current-changed" to notify others components
         @param bus as Gst.Bus
         @param message as Gst.Message
     """
     self._start_time = time()
     debug("Player::_on_stream_start(): %s" % self._current_track.uri)
     self.emit("current-changed")
     # Update now playing on lastfm
     # Not supported by librefm
     if Lp().lastfm is not None and\
             Lp().lastfm.session_key and\
             self._current_track.id >= 0:
         artists = ", ".join(self._current_track.artists)
         Lp().lastfm.now_playing(artists, self._current_track.album_name,
                                 self._current_track.title,
                                 int(self._current_track.duration))
     try:
         if not Lp().scanner.is_locked():
             Lp().tracks.set_listened_at(self._current_track.id,
                                         int(time()))
     except:  # Locked database
         pass
 def __update_for_url(self, url):
     """
         Update charts for url
         @param url as str
     """
     if not get_network_available():
             return
     debug("SpotifyCharts::__update_for_url(): %s => %s" % (url,
                                                            self.__count))
     ids = self.__get_ids(url)
     web = Web()
     search = SpotifySearch()
     while ids:
         sleep(10)
         track_id = ids.pop(0)
         album_id = search.get_album_id(track_id)
         album = search.get_album(album_id)
         if album is None or album.exists_in_db():
             continue
         if self._stop:
             return
         Lp().db.del_tracks(Lp().tracks.get_old_from_charts(self.__count))
         debug("SpotifyCharts::__update_for_url(): %s - %s - %s" % (
                                                             album.name,
                                                             album.artists,
                                                             album_id))
         web.save_album(album, DbPersistent.CHARTS)
Example #27
0
 def _scrobble(self, artist, album, title, timestamp, duration):
     """
         Scrobble track
         @param artist as str
         @param title as str
         @param album_title as str
         @param timestamp as int
         @param duration as int
         @thread safe
     """
     debug("LastFM::_scrobble(): %s, %s, %s, %s, %s" % (artist,
                                                        album,
                                                        title,
                                                        timestamp,
                                                        duration))
     try:
         LastFMNetwork.scrobble(self,
                                artist=artist,
                                album=album,
                                title=title,
                                timestamp=timestamp)
     except BadAuthenticationError:
         pass
     except:
         self._connect(self._username, self._password)
Example #28
0
 def __connect(self, username, password, populate_loved=False):
     """
         Connect lastfm
         @param username as str
         @param password as str
         @thread safe
     """
     self.__username = username
     if self.__goa is not None or (password != '' and username != ''):
         self.__is_auth = True
     else:
         self.__is_auth = False
     try:
         self.__check_for_proxy()
         if self.__goa is None:
             LastFMNetwork.__init__(self,
                                    api_key=self.__API_KEY,
                                    api_secret=self.__API_SECRET,
                                    username=self.__username,
                                    password_hash=md5(password))
         else:
             LastFMNetwork.__init__(
                 self,
                 api_key=self.__API_KEY,
                 api_secret=self.__API_SECRET,
                 session_key=self.__goa.call_get_access_token_sync(None)[0])
         if populate_loved:
             self.__populate_loved_tracks()
     except Exception as e:
         debug("Lastfm::__connect(): %s" % e)
         self.__is_auth = False
Example #29
0
 def _scrobble(self, artist, album, title, timestamp, duration):
     """
         Scrobble track
         @param artist as str
         @param title as str
         @param album_title as str
         @param timestamp as int
         @param duration as int
         @thread safe
     """
     debug("LastFM::_scrobble(): %s, %s, %s, %s, %s" % (artist,
                                                        album,
                                                        title,
                                                        timestamp,
                                                        duration))
     try:
         LastFMNetwork.scrobble(self,
                                artist=artist,
                                album=album,
                                title=title,
                                timestamp=timestamp)
     except BadAuthenticationError:
         pass
     except:
         self._connect(self._username, self._password)
Example #30
0
 def __update_for_url(self, url):
     """
         Update charts for url
         @param url as str
     """
     if not get_network_available():
             return
     debug("ItunesCharts::__update_for_url(): %s => %s" % (url,
                                                           self.__LIMIT))
     web = Web()
     ids = self.__get_ids(url)
     position = len(ids)
     while ids:
         sleep(10)
         (itunes_id, itunes_genre) = ids.pop(0)
         album = self.__get_album(itunes_id)
         if self.__stop:
             return
         if album is None or not album.subitems:
             position -= 1
             continue
         album.mtime = self.__time + position
         for item in album.subitems:
             item.mtime = self.__time
         debug("ItunesCharts::__update_for_url(): %s - %s" % (
                                                             album.name,
                                                             album.artists))
         t = TagReader()
         with SqlCursor(Lp().db) as sql:
             genre_ids = t.add_genres(itunes_genre)
             sql.commit()
         genre_ids.append(Type.ITUNES)
         web.save_album_thread(album, DbPersistent.CHARTS, genre_ids)
         position -= 1
Example #31
0
 def __on_stream_about_to_finish(self, playbin):
     """
         When stream is about to finish, switch to next track without gap
         @param playbin as Gst bin
     """
     debug("Player::__on_stream_about_to_finish(): %s" % playbin)
     # Don't do anything if crossfade on, track already changed
     if self._crossfading:
         return
     if self.current_track.id == Type.RADIOS:
         return
     self._scrobble(self.current_track, self._start_time)
     # Increment popularity
     if not Lp().scanner.is_locked():
         Lp().tracks.set_more_popular(self.current_track.id)
         # In party mode, linear popularity
         if self.is_party:
             pop_to_add = 1
         # In normal mode, based on tracks count
         else:
             pop_to_add = int(Lp().albums.max_count /
                              Lp().albums.get_tracks_count(
                                               self.current_track.album_id))
         Lp().albums.set_more_popular(self.current_track.album_id,
                                      pop_to_add)
     if self._next_track.id is not None:
         self._load_track(self._next_track)
Example #32
0
 def __connect(self, username, password, populate_loved=False):
     """
         Connect lastfm
         @param username as str
         @param password as str
         @thread safe
     """
     self.__username = username
     if self.__goa is not None or (password != '' and username != ''):
         self.__is_auth = True
     else:
         self.__is_auth = False
     try:
         self.session_key = ""
         self.__check_for_proxy()
         if self.__goa is not None:
             self.session_key = self.__goa.call_get_access_token_sync(
                                                                   None)[0]
         else:
             skg = SessionKeyGenerator(self)
             self.session_key = skg.get_session_key(
                                               username=self.__username,
                                               password_hash=md5(password))
         if populate_loved:
             self.__populate_loved_tracks()
     except Exception as e:
         debug("Lastfm::__connect(): %s" % e)
         self.__is_auth = False
Example #33
0
 def _get_objects_for_paths(self, paths):
     """
         Return all tracks/dirs for paths
         @param paths as string
         @return ([tracks path], [dirs path], track count)
     """
     tracks = []
     track_dirs = list(paths)
     count = 0
     for path in paths:
         for root, dirs, files in os.walk(path):
             # Add dirs
             for d in dirs:
                 track_dirs.append(os.path.join(root, d))
             # Add files
             for name in files:
                 filepath = os.path.join(root, name)
                 try:
                     f = Gio.File.new_for_path(filepath)
                     if is_pls(f):
                         pass
                     elif is_audio(f):
                         tracks.append(filepath)
                         count += 1
                     else:
                         debug("%s not detected as a music file" % filepath)
                 except Exception as e:
                     print("CollectionScanner::_get_objects_for_paths: %s"
                           % e)
     return (tracks, track_dirs, count)
Example #34
0
 def _load_track(self, track, init_volume=True):
     """
         Load track
         @param track as Track
         @param init volume as bool
         @return False if track not loaded
     """
     if self.__need_to_stop():
         return False
     if init_volume:
         self._plugins.volume.props.volume = 1.0
     debug("BinPlayer::_load_track(): %s" % track.uri)
     try:
         if track.id in self._queue:
             self._queue_track = track
             self._queue.remove(track.id)
             self.emit('queue-changed')
         else:
             self._current_track = track
             self._queue_track = None
         if track.is_web:
             loaded = self._load_web(track)
             # If track not loaded, go next
             if not loaded:
                 self.set_next()
                 GLib.timeout_add(500, self.__load,
                                  self.next_track, init_volume)
             return False  # Return not loaded as handled by load_web()
         else:
             self._playbin.set_property('uri', track.uri)
     except Exception as e:  # Gstreamer error
         print("BinPlayer::_load_track(): ", e)
         self._queue_track = None
         return False
     return True
Example #35
0
    def __on_bus_message_tag(self, bus, message):
        """
            Read tags from stream
            @param bus as Gst.Bus
            @param message as Gst.Message
        """
        # Some radio streams send message tag every seconds!
        changed = False
        if (self.current_track.persistent == DbPersistent.INTERNAL or
            self.current_track.mtime != 0) and\
            (self.current_track.id >= 0 or
             self.current_track.duration > 0.0):
            return
        debug("Player::__on_bus_message_tag(): %s" % self.current_track.uri)
        reader = TagReader()

        # Update duration of non internals
        if self.current_track.persistent != DbPersistent.INTERNAL:
            t = Thread(target=self.__update_current_duration,
                       args=(reader, self.current_track))
            t.daemon = True
            t.start()
            return

        tags = message.parse_tag()
        title = reader.get_title(tags, '')
        if title != '' and self.current_track.name != title:
            self.current_track.name = title
            changed = True
        if self.current_track.name == '':
            self.current_track.name = self.current_track.uri
            changed = True
        artists = reader.get_artists(tags)
        if artists != '' and self.current_track.artists != artists:
            self.current_track.artists = artists.split(',')
            changed = True
        if not self.current_track.artists:
            self.current_track.artists = self.current_track.album_artists
            changed = True

        if self.current_track.id == Type.EXTERNALS:
            (b, duration) = self._playbin.query_duration(Gst.Format.TIME)
            if b:
                self.current_track.duration = duration / 1000000000
            # We do not use tagreader as we need to check if value is None
            self.current_track.album_name = tags.get_string_index('album',
                                                                  0)[1]
            if self.current_track.album_name is None:
                self.current_track.album_name = ''
            self.current_track.artists = reader.get_artists(tags).split(',')
            self.current_track.set_album_artists(
                reader.get_album_artist(tags).split(','))
            if self.current_track.album_artist == '':
                self.current_track.set_album_artists(
                    self.current_track.artists)
            self.current_track.genres = reader.get_genres(tags).split(',')
            changed = True
        if changed:
            self.emit('current-changed')
Example #36
0
 def _on_bus_eos(self, bus, message):
     debug("Player::_on_bus_eos(): %s" % self.current_track.uri)
     if self.context.next != NextContext.NONE:
         self.context.next = NextContext.NONE
         self._set_next()
         self.next()
     else:
         self.load(self.current_track)
Example #37
0
 def __on_current_changed(self, player):
     """
         Update toolbar
         @param player as Player
     """
     debug("Toolbar::_on_current_changed")
     self.__toolbar_playback.on_current_changed(player)
     self.__toolbar_info.on_current_changed(player)
     self.__toolbar_title.on_current_changed(player)
Example #38
0
 def _on_bus_error(self, bus, message):
     debug("Error playing: %s" % self.current_track.uri)
     if self._handled_error != self.current_track.uri:
         self._handled_error = self.current_track.uri
         Lp.notify.send(_("File doesn't exist: %s") %
                        self.current_track.uri)
         self._set_next()
         self.next()
     return False
Example #39
0
 def _on_current_changed(self, player):
     """
         Update toolbar
         @param player as Player
     """
     debug("Toolbar::_on_current_changed")
     self._toolbar_playback.on_current_changed(player)
     self._toolbar_info.on_current_changed(player)
     self._toolbar_title.on_current_changed(player)
Example #40
0
 def __on_get_secret(self, source, result):
     """
         Store secret proxy
         @param source as GObject.Object
         @param result as Gio.AsyncResult
     """
     try:
         self.__secret = Secret.Service.get_finish(result)
     except Exception as e:
         self.__secret = -1
         debug("PasswordsHelper::__on_get_secret(): %s" % e)
Example #41
0
 def _cache_artists_art(self):
     """
         Cache artwork for all artists
     """
     # We create cache if needed
     InfoCache.init()
     # Then cache artwork for lastfm/wikipedia/spotify
     # We cache content as the same time
     # TODO Make this code more generic
     for (artist_id, artist) in Lp().artists.get([]):
         debug("ArtDownloader::_cache_artists_art(): %s" % artist)
         artwork_set = False
         if not Gio.NetworkMonitor.get_default().get_network_available() or\
                 InfoCache.exists_in_cache(artist):
             continue
         if Lp().lastfm is not None:
             try:
                 (url, content) = Lp().lastfm.get_artist_infos(artist)
                 if url is not None:
                     s = Gio.File.new_for_uri(url)
                     (status, data, tag) = s.load_contents()
                     if status:
                         artwork_set = True
                         InfoCache.cache(artist, content, data, "lastfm")
                     else:
                         InfoCache.cache(artist, None, None, "lastfm")
             except:
                 InfoCache.cache(artist, None, None, "lastfm")
         if ArtDownloader.Wikipedia is not None:
             try:
                 wp = ArtDownloader.Wikipedia()
                 (url, content) = wp.get_page_infos(artist)
                 if url is not None:
                     s = Gio.File.new_for_uri(url)
                     (status, data, tag) = s.load_contents()
                     if status:
                         artwork_set = True
                         InfoCache.cache(artist, content, data, "wikipedia")
                     else:
                         InfoCache.cache(artist, None, None, "wikipedia")
             except:
                 InfoCache.cache(artist, None, None, "wikipedia")
         url = self._get_spotify_artist_artwork(artist)
         if url is not None:
             s = Gio.File.new_for_uri(url)
             (status, data, tag) = s.load_contents()
             if status:
                 artwork_set = True
                 InfoCache.cache(artist, None, data, "spotify")
             else:
                 InfoCache.cache(artist, None, None, "spotify")
         if artwork_set:
             Lp().art.emit('artist-artwork-changed', artist)
     self._cache_artists_running = False
Example #42
0
    def _scan(self, paths):
        sql = Lp.db.get_cursor()
        orig_tracks = Lp.tracks.get_paths(sql)
        self._is_empty = len(orig_tracks) == 0

        # Add monitors on dirs
        (new_tracks, new_dirs, count) = self._get_objects_for_paths(paths)
        if self._inotify is not None:
            for d in new_dirs:
                self._inotify.add_monitor(d)

        i = 0
        for filepath in new_tracks:
            if not self._in_thread:
                sql.close()
                self._is_locked = False
                return
            GLib.idle_add(self._update_progress, i, count)
            try:
                mtime = int(os.path.getmtime(filepath))
                if filepath not in orig_tracks:
                    infos = self.get_infos(filepath)
                    if infos is not None:
                        debug("Adding file: %s" % filepath)
                        self._add2db(filepath, mtime, infos, sql)
                    else:
                        print("Can't get infos for ", filepath)
                else:
                    # Update tags by removing song and readd it
                    if mtime != self._mtimes[filepath]:
                        self._del_from_db(filepath, sql)
                        infos = self.get_infos(filepath)
                        if infos is not None:
                            debug("Adding file: %s" % filepath)
                            self._add2db(filepath, mtime, infos, sql)
                        else:
                            print("Can't get infos for ", filepath)
                    orig_tracks.remove(filepath)

            except Exception as e:
                print(ascii(filepath))
                print("CollectionScanner::_scan(): %s" % e)
            i += 1

        # Clean deleted files
        if i > 0:
            for filepath in orig_tracks:
                self._del_from_db(filepath, sql)

        self._restore_popularities(sql)
        self._restore_mtimes(sql)
        sql.commit()
        sql.close()
        GLib.idle_add(self._finish)
Example #43
0
 def _on_bus_eos(self, bus, message):
     debug("Player::_on_bus_eos(): %s" % self.current_track.uri)
     if self.context.next not in [NextContext.NONE,
                                  NextContext.START_NEW_ALBUM]:
         self.stop()
         self.context.next = NextContext.NONE
         if self.next_track.id is not None:
             self._load_track(self.next_track)
         self.emit('current-changed')
     else:
         self._playbin.set_state(Gst.State.NULL)
         self._playbin.set_state(Gst.State.PLAYING)
Example #44
0
    def __on_bus_message_tag(self, bus, message):
        """
            Read tags from stream
            @param bus as Gst.Bus
            @param message as Gst.Message
        """
        # Some radio streams send message tag every seconds!
        changed = False
        if (self.current_track.persistent == DbPersistent.INTERNAL or
            self.current_track.mtime != 0) and\
            (self.current_track.id >= 0 or
             self.current_track.duration > 0.0):
            return
        debug("Player::__on_bus_message_tag(): %s" % self.current_track.uri)
        reader = TagReader()

        # Update duration of non internals
        if self.current_track.persistent != DbPersistent.INTERNAL:
            t = Thread(target=self.__update_current_duration,
                       args=(reader, self.current_track))
            t.daemon = True
            t.start()
            return

        tags = message.parse_tag()
        title = reader.get_title(tags, '')
        if title != '' and self.current_track.name != title:
            self.current_track.name = title
            changed = True
        if self.current_track.name == '':
            self.current_track.name = self.current_track.uri
            changed = True
        artists = reader.get_artists(tags)
        if artists != '' and self.current_track.artists != artists:
            self.current_track.artists = artists.split(',')
            changed = True
        if not self.current_track.artists:
            self.current_track.artists = self.current_track.album_artists
            changed = True

        if self.current_track.id == Type.EXTERNALS:
            (b, duration) = self._playbin.query_duration(Gst.Format.TIME)
            if b:
                self.current_track.duration = duration/1000000000
            # We do not use tagreader as we need to check if value is None
            self.current_track.album_name = tags.get_string_index('album',
                                                                  0)[1]
            if self.current_track.album_name is None:
                self.current_track.album_name = ''
            self.current_track.genres = reader.get_genres(tags).split(',')
            changed = True
        if changed:
            self.emit('current-changed')
Example #45
0
 def __on_bus_eos(self, bus, message):
     """
         On end of stream, stop playback
         go next otherwise
     """
     debug("Player::__on_bus_eos(): %s" % self.current_track.uri)
     if self._playbin.get_bus() == bus:
         self.stop()
         self._next_context = NextContext.NONE
         if self._next_track.id is not None:
             self._load_track(self._next_track)
         self.emit('current-changed')
Example #46
0
 def __on_bus_eos(self, bus, message):
     """
         On end of stream, stop playback
         go next otherwise
     """
     debug("Player::__on_bus_eos(): %s" % self._current_track.uri)
     if self._playbin.get_bus() == bus:
         self.stop()
         self._next_context = NextContext.NONE
         if self._next_track.id is not None:
             self._load_track(self._next_track)
         self.emit("current-changed")
Example #47
0
 def __get_objects_for_uris(self, uris):
     """
         Return all tracks/dirs for uris
         @param uris as string
         @return (track uri as [str], track dirs as [str],
                  ignore dirs as [str])
     """
     tracks = []
     ignore_dirs = []
     track_dirs = list(uris)
     walk_uris = list(uris)
     while walk_uris:
         uri = walk_uris.pop(0)
         empty = True
         try:
             d = Gio.File.new_for_uri(uri)
             infos = d.enumerate_children(
                 "standard::name,standard::type,standard::is-hidden",
                 Gio.FileQueryInfoFlags.NONE, None)
         except Exception as e:
             print("CollectionScanner::__get_objects_for_uris():", e)
             ignore_dirs.append(uri)
             continue
         for info in infos:
             f = infos.get_child(info)
             child_uri = f.get_uri()
             empty = False
             if info.get_is_hidden():
                 continue
             elif info.get_file_type() == Gio.FileType.DIRECTORY:
                 track_dirs.append(child_uri)
                 walk_uris.append(child_uri)
             else:
                 try:
                     f = Gio.File.new_for_uri(child_uri)
                     if is_pls(f):
                         pass
                     elif is_audio(f):
                         tracks.append(child_uri)
                     else:
                         debug("%s not detected as a music file" %
                               child_uri)
                 except Exception as e:
                     print(
                         "CollectionScanner::"
                         "__get_objects_for_uris():", e)
         # If a root uri is empty
         # Ensure user is not doing something bad
         if empty and uri in uris:
             ignore_dirs.append(uri)
     return (tracks, track_dirs, ignore_dirs)
Example #48
0
 def _on_bus_eos(self, bus, message):
     """
         On end of stream, stop playing if user ask for,
         go next otherwise
     """
     debug("Player::_on_bus_eos(): %s" % self.current_track.uri)
     if self.context.next not in [NextContext.NONE, NextContext.START_NEW_ALBUM]:
         self.stop()
         self.context.next = NextContext.NONE
         if self.next_track.id is not None:
             self._load_track(self.next_track)
         self.emit("current-changed")
     else:
         self.next()
Example #49
0
 def _on_bus_error(self, bus, message):
     """
         Try a codec install and update current track
         @param bus as Gst.Bus
         @param message as Gst.Message
     """
     debug("Error playing: %s" % self._current_track.uri)
     Lp().window.pulse(False)
     if self.__codecs.is_missing_codec(message):
         self.__codecs.install()
         Lp().scanner.stop()
     elif Lp().notify is not None:
         Lp().notify.send(message.parse_error()[0].message)
     self.stop()
 def __get_objects_for_uris(self, uris):
     """
         Return all tracks/dirs for uris
         @param uris as string
         @return (track uri as [str], track dirs as [str],
                  ignore dirs as [str])
     """
     tracks = []
     ignore_dirs = []
     track_dirs = list(uris)
     walk_uris = list(uris)
     while walk_uris:
         uri = walk_uris.pop(0)
         empty = True
         try:
             d = Lio.File.new_for_uri(uri)
             infos = d.enumerate_children(
                 'standard::name,standard::type,standard::is-hidden',
                 Gio.FileQueryInfoFlags.NONE,
                 None)
         except Exception as e:
             print("CollectionScanner::__get_objects_for_uris():", e)
             continue
         for info in infos:
             f = infos.get_child(info)
             child_uri = f.get_uri()
             empty = False
             if info.get_is_hidden():
                 continue
             elif info.get_file_type() == Gio.FileType.DIRECTORY:
                 track_dirs.append(child_uri)
                 walk_uris.append(child_uri)
             else:
                 try:
                     f = Lio.File.new_for_uri(child_uri)
                     if is_pls(f):
                         pass
                     elif is_audio(f):
                         tracks.append(child_uri)
                     else:
                         debug("%s not detected as a music file" % uri)
                 except Exception as e:
                     print("CollectionScanner::"
                           "__get_objects_for_uris():", e)
         # If a root uri is empty
         # Ensure user is not doing something bad
         if empty and uri in uris:
             ignore_dirs.append(uri)
     return (tracks, track_dirs, ignore_dirs)
Example #51
0
 def _on_bus_error(self, bus, message):
     debug("Error playing: %s" % self.current_track.uri)
     if self._codecs.is_missing_codec(message):
         self._codecs.install()
         self.stop()
         Lp.scanner.stop()
         return True
     if self._handled_error != self.current_track.uri:
         self._handled_error = self.current_track.uri
         if Lp.notify is not None:
             Lp.notify.send(_("File doesn't exist: %s") %
                            self.current_track.uri)
         self.set_next()
         self.next()
     return False
Example #52
0
 def __on_clear_search(self, source, result, callback=None, *args):
     """
         Clear passwords
         @param source as GObject.Object
         @param result as Gio.AsyncResult
     """
     try:
         if result is not None:
             items = source.search_finish(result)
             for item in items:
                 item.delete(None, None)
         if callback is not None:
             callback(*args)
     except Exception as e:
         debug("PasswordsHelper::__on_clear_search(): %s" % e)
Example #53
0
 def __on_bus_error(self, bus, message):
     """
         Handle first bus error, ignore others
         @param bus as Gst.Bus
         @param message as Gst.Message
     """
     debug("Error playing: %s" % self.current_track.uri)
     Lp().window.pulse(False)
     if self.__codecs.is_missing_codec(message):
         self.__codecs.install()
         Lp().scanner.stop()
     elif Lp().notify is not None:
         Lp().notify.send(message.parse_error()[0].message)
     self.emit('current-changed')
     return True
Example #54
0
 def __on_bus_error(self, bus, message):
     """
         Handle first bus error, ignore others
         @param bus as Gst.Bus
         @param message as Gst.Message
     """
     debug("Error playing: %s" % self._current_track.uri)
     Lp().window.pulse(False)
     if self.__codecs.is_missing_codec(message):
         self.__codecs.install()
         Lp().scanner.stop()
     elif Lp().notify is not None:
         Lp().notify.send(message.parse_error()[0].message)
     self.emit("current-changed")
     return True
Example #55
0
 def _on_bus_eos(self, bus, message):
     """
         On end of stream, stop playing if user ask for,
         go next otherwise
     """
     debug("Player::_on_bus_eos(): %s" % self.current_track.uri)
     if self.context.next not in [
             NextContext.NONE, NextContext.START_NEW_ALBUM
     ]:
         self.stop()
         self.context.next = NextContext.NONE
         if self.next_track.id is not None:
             self._load_track(self.next_track)
         self.emit('current-changed')
     else:
         self.next()
Example #56
0
 def __on_bus_eos(self, bus, message):
     """
         On end of stream, stop playback
         go next otherwise
     """
     debug("Player::__on_bus_eos(): %s" % self.current_track.uri)
     if self._playbin.get_bus() == bus:
         self.stop()
         self._finished = NextContext.NONE
         if Lp().settings.get_value('repeat'):
             self._context.next = NextContext.NONE
         else:
             self._context.next = NextContext.STOP_ALL
         if self._next_track.id is not None:
             self._load_track(self._next_track)
         self.emit('current-changed')
Example #57
0
 def _on_bus_eos(self, bus, message):
     """
         On end of stream, stop playback
         go next otherwise
     """
     debug("Player::_on_bus_eos(): %s" % self.current_track.uri)
     if self._playbin.get_bus() == bus:
         self.stop()
         self._finished = NextContext.NONE
         if Lp().settings.get_value('repeat'):
             self._context.next = NextContext.NONE
         else:
             self._context.next = NextContext.STOP_ALL
         if self._next_track.id is not None:
             self._load_track(self._next_track)
         self.emit('current-changed')
Example #58
0
 def _on_stream_about_to_finish(self, playbin):
     """
         When stream is about to finish, switch to next track without gap
         @param playbin as Gst bin
     """
     debug("Player::_on_stream_about_to_finish(): %s" % playbin)
     # Don't do anything if crossfade on
     if self._crossfading:
         return
     if self.current_track.id == Type.RADIOS:
         return
     finished = self.current_track
     finished_start_time = self._start_time
     if self._next_track.id is not None:
         self._load_track(self._next_track)
     self._track_finished(finished, finished_start_time)
Example #59
0
 def _on_bus_error(self, bus, message):
     """
         Handle first bus error, ignore others
         @param bus as Gst.Bus
         @param message as Gst.Message
     """
     debug("Error playing: %s" % self.current_track.uri)
     if self._codecs.is_missing_codec(message):
         self._codecs.install()
         Lp.scanner.stop()
     elif Lp.notify is not None:
         Lp.notify.send(_("File doesn't exist: %s") %
                        self.current_track.uri)
     self.stop()
     self.emit('current-changed')
     return True