Exemple #1
0
 def __init__(self):
     """
         Init playbin
     """
     # In the case of gapless playback, both 'about-to-finish'
     # and 'eos' can occur during the same stream.
     self.__track_in_pipe = False
     self.__cancellable = Gio.Cancellable()
     self.__codecs = Codecs()
     self._current_track = Track()
     self._next_track = Track()
     self._prev_track = Track()
     self._playbin = self._playbin1 = Gst.ElementFactory.make(
         "playbin", "player")
     self._playbin2 = Gst.ElementFactory.make("playbin", "player")
     self._plugins = self._plugins1 = PluginsPlayer(self._playbin1)
     self._plugins2 = PluginsPlayer(self._playbin2)
     for playbin in [self._playbin1, self._playbin2]:
         flags = playbin.get_property("flags")
         flags &= ~GstPlayFlags.GST_PLAY_FLAG_VIDEO
         playbin.set_property("flags", flags)
         playbin.set_property("buffer-size", 5 << 20)
         playbin.set_property("buffer-duration", 10 * Gst.SECOND)
         playbin.connect("notify::volume", self.__on_volume_changed)
         playbin.connect("about-to-finish", self._on_stream_about_to_finish)
         bus = playbin.get_bus()
         bus.add_signal_watch()
         bus.connect("message::error", self._on_bus_error)
         bus.connect("message::eos", self._on_bus_eos)
         bus.connect("message::element", self._on_bus_element)
         bus.connect("message::stream-start", self._on_stream_start)
         bus.connect("message::tag", self._on_bus_message_tag)
     self._start_time = 0
Exemple #2
0
 def remove(playlist_id):
     tracks = []
     for obj in self.__objects:
         if isinstance(obj, Album):
             for track_id in obj.track_ids:
                 tracks.append(Track(track_id))
         else:
             tracks = [Track(obj.id)]
         App().playlists.remove_tracks(playlist_id, tracks, True)
Exemple #3
0
 def __init__(self, object):
     """
         Init edit menu
         @param object as Album/Track
     """
     Gio.Menu.__init__(self)
     # Ignore genre_ids/artist_ids
     if isinstance(object, Album):
         self.__object = Album(object.id)
     else:
         self.__object = Track(object.id)
     self.__set_save_action()
     if self.__object.storage_type & StorageType.COLLECTION:
         self.__set_open_action()
Exemple #4
0
 def stop(self):
     """
         Change player state to STOPPED
         @param force as bool
     """
     self._current_track = Track()
     self._current_track = Track()
     self._prev_track = Track()
     self._next_track = Track()
     emit_signal(self, "current-changed")
     emit_signal(self, "prev-changed")
     emit_signal(self, "next-changed")
     self._playbin.set_state(Gst.State.NULL)
     emit_signal(self, "status-changed")
Exemple #5
0
 def set_next(self):
     """
         Play next track
     """
     if self._current_track.id is None:
         return
     if self._current_track.id == self.__stop_after_track_id:
         self._next_track = Track()
         return
     try:
         next_track = QueuePlayer.next(self)
         if next_track.id is None:
             # Diverge current track to restore playback from queue
             diverge_current_track = None
             if self._queue_current_track is not None:
                 diverge_current_track = self._current_track
                 self._current_track = self._queue_current_track
             if App().settings.get_value("shuffle") or self.is_party:
                 next_track = ShufflePlayer.next(self)
             else:
                 next_track = LinearPlayer.next(self)
             # Restore current track
             if diverge_current_track is not None:
                 self._current_track = diverge_current_track
                 self._queue_current_track = None
         self._next_track = next_track
         emit_signal(self, "next-changed")
     except Exception as e:
         Logger.error("Player::set_next(): %s" % e)
 def __play_radio_common(self):
     """
         Emit signal and reset cancellable
     """
     emit_signal(self, "loading-changed", True, Track())
     self.__radio_cancellable.cancel()
     self.__radio_cancellable = Gio.Cancellable()
Exemple #7
0
 def __get_next(self):
     """
         Next track in shuffle mode
         @return track as Track
     """
     try:
         if App().settings.get_value("shuffle") or self._is_party:
             if self._albums:
                 track = self.__get_tracks_random()
                 # All tracks done
                 # Try to get another one track after reseting history
                 if track.id is None:
                     self.__to_play_albums = list(self._albums)
                     shuffle(self.__to_play_albums)
                     repeat = App().settings.get_enum("repeat")
                     # Do not reset history if a new album is going to
                     # be added
                     if repeat not in [
                             Repeat.AUTO_SIMILAR, Repeat.AUTO_RANDOM
                     ]:
                         self.__history = []
                         self.__already_played_tracks = {}
                     if repeat == Repeat.ALL:
                         return self.__get_next()
                 return track
     except Exception as e:
         Logger.error("ShufflePLayer::__get_next(): %s", e)
     return Track()
Exemple #8
0
 def get_tracks(self, playlist_id):
     """
         Return availables tracks for playlist
         @param playlist_id as int
         @return [Track]
     """
     return [Track(track_id)
             for track_id in self.get_track_ids(playlist_id)]
Exemple #9
0
 def prev(self):
     """
         Prev track base on.current_track context
         @return track as Track
     """
     repeat = App().settings.get_enum("repeat")
     # No album in playback
     if not self._albums:
         return Track()
     # User want us to repeat current track
     elif repeat == Repeat.TRACK:
         return self._current_track
     album = self._current_track.album
     track = self.__fallback_track_if_album_missing(album)
     # Current album missing, go to fallback track
     if track is not None:
         return track
     new_track_position = self._current_track.position - 1
     # Previous album
     if new_track_position < 0:
         try:
             pos = self.albums.index(album)
             albums_count = len(self._albums)
             new_pos = 0
             # Search for a prev album
             for idx in chain(reversed(range(0, pos)),
                              reversed(range(pos, albums_count))):
                 if self._albums[idx].tracks:
                     new_pos = idx
                     break
             if new_pos == albums_count - 1:
                 if repeat == Repeat.ALL:
                     pos = new_pos
                 else:
                     return Track()
             else:
                 pos = new_pos
         except Exception as e:
             Logger.error("LinearPlayer::prev(): %s", e)
             pos = 0  # Happens if current album has been removed
         track = self._albums[pos].tracks[-1]
     # Previous track
     else:
         track = album.tracks[new_track_position]
     return track
Exemple #10
0
 def start_party(*ignore):
     if self._albums:
         # Start a new song if not playing
         if self._current_track.id is None:
             track = self.__get_tracks_random()
             self.load(track)
         elif not self.is_playing:
             self.play()
     emit_signal(self, "loading-changed", False, Track())
Exemple #11
0
 def next(self):
     """
         Next track for current album or next album
         @return track as Track
     """
     repeat = App().settings.get_enum("repeat")
     # No album in playback
     if not self.albums:
         return Track()
     # User want us to repeat current track
     elif repeat == Repeat.TRACK:
         return self._current_track
     album = self._current_track.album
     track = self.__fallback_track_if_album_missing(album)
     # Current album missing, go to fallback track
     if track is not None:
         return track
     new_track_position = self._current_track.position + 1
     # next album
     if new_track_position >= len(album.track_ids):
         try:
             pos = self.albums.index(album)
             albums_count = len(self._albums)
             new_pos = 0
             # Search for a next album
             for idx in chain(range(pos + 1, albums_count), range(0, pos)):
                 if self._albums[idx].tracks:
                     new_pos = idx
                     break
             if new_pos == 0:
                 if repeat == Repeat.ALL:
                     pos = 0
                 else:
                     return Track()
             else:
                 pos = new_pos
         except Exception as e:
             Logger.error("LinearPlayer::next(): %s", e)
             pos = 0  # Happens if current album has been removed
         track = self._albums[pos].tracks[0]
     # next track
     else:
         track = album.tracks[new_track_position]
     return track
 def play_radio_from_populars(self, artist_ids):
     """
         Play a radio from artists popular tracks
         @param artist_ids as [int]
     """
     track_ids = App().tracks.get_populars(artist_ids, StorageType.ALL,
                                           False, 100)
     shuffle(track_ids)
     albums = tracks_to_albums([Track(track_id) for track_id in track_ids])
     App().player.play_albums(albums)
 def play_radio_from_loved(self, artist_ids):
     """
         Play a radio from artists loved tracks
         @param artist_ids as [int]
     """
     track_ids = App().tracks.get_loved_track_ids(artist_ids,
                                                  StorageType.ALL)
     shuffle(track_ids)
     albums = tracks_to_albums([Track(track_id) for track_id in track_ids])
     App().player.play_albums(albums)
Exemple #14
0
 def load():
     request = App().playlists.get_smart_sql(self.__playlist_id)
     # We need to inject skipped/storage_type
     storage_type = get_default_storage_type()
     split = request.split("ORDER BY")
     split[0] += " AND tracks.loved != %s" % Type.NONE
     split[0] += " AND tracks.storage_type&%s " % storage_type
     track_ids = App().db.execute("ORDER BY".join(split))
     return tracks_to_albums(
         [Track(track_id) for track_id in track_ids])
 def get_track(self, track_id):
     """
         Get track
         @param track_id as int
         @return Track
     """
     for track in self.tracks:
         if track.id == track_id:
             return track
     return Track()
Exemple #16
0
 def next(self):
     """
         Get next track id
         @return Track
     """
     track_id = None
     if self.__queue:
         track_id = self.__queue[0]
         if self._queue_current_track is None:
             self._queue_current_track = self._current_track
     return Track(track_id)
 def append_track(self, track, clone=True):
     """
         Append track to album, do not disable clone if you know self is
         already used
         @param track as Track
         @param clone as bool
     """
     if clone:
         self._tracks.append(Track(track.id, self))
     else:
         self._tracks.append(track)
         track.set_album(self)
Exemple #18
0
 def _on_match_track(self, search, track_id, storage_type):
     """
         Add a new track to view
         @param search as *Search
         @param track_id as int
         @param storage_type as StorageType
     """
     if storage_type & StorageType.SEARCH:
         track = Track(track_id)
         self.__stack.current_child.search_tracks_view.show()
         self.__stack.current_child.search_tracks_view.append_row(track)
         self.show_placeholder(False)
 def next_album(self):
     """
         Get next album to add
         @return Album
     """
     genre_ids = App().artists.get_genre_ids(self.current_track.artist_ids,
                                             StorageType.COLLECTION)
     track_ids = App().tracks.get_randoms(genre_ids, StorageType.COLLECTION,
                                          1)
     if track_ids:
         return Track(track_ids[0]).album
     return None
 def play_radio_from_collection(self, artist_ids):
     """
         Play a radio from collection for artist ids
         @param artist_ids as [int]
     """
     genre_ids = App().artists.get_genre_ids(artist_ids,
                                             StorageType.COLLECTION)
     track_ids = App().tracks.get_randoms(genre_ids, StorageType.COLLECTION,
                                          False, 100)
     albums = tracks_to_albums([Track(track_id) for track_id in track_ids],
                               False)
     self.play_albums(albums)
Exemple #21
0
 def __fallback_track_if_album_missing(self, album):
     """
         Get a fallback track if album not in player
         @param album as Album
         @return Track/None
     """
     if album not in self._albums:
         album = self._albums[0]
         if album.tracks:
             return album.tracks[0]
         else:
             return Track()
     return None
 def tracks(self):
     """
         Get disc tracks
         @return [Track]
     """
     if not self.__tracks and self.album.id is not None:
         self.__tracks = [
             Track(track_id, self.album)
             for track_id in self.db.get_disc_track_ids(
                 self.album.id, self.album.genre_ids, self.album.artist_ids,
                 self.number, self.__storage_type, self.__skipped)
         ]
     return self.__tracks
Exemple #23
0
 def _on_playlist_track_added(self, playlists, playlist_id, uri):
     """
         Append track to album list
         @param playlists as Playlists
         @param playlist_id as int
         @param uri as str
     """
     if playlist_id == self.__playlist_id:
         track = Track(App().tracks.get_id_by_uri(uri))
         album = Album(track.album.id)
         album.set_tracks([track])
         self.add_reveal_albums([album])
         self.add_value(album)
 def __on_match_track(self, similars, track_id, storage_type):
     """
         Load/Play track album
         @param similars as Similars
         @param track_id as int
         @param storage_type as StorageType
     """
     track = Track(track_id)
     album = track.album
     if self.albums:
         self.add_album(album)
     else:
         self.play_album(album)
Exemple #25
0
 def next(self):
     """
         Next shuffle track
         @return Track
     """
     repeat = App().settings.get_enum("repeat")
     if repeat == Repeat.TRACK:
         return self._current_track
     if self.shuffle_has_next:
         track = self.__history.next.value
     elif self._albums:
         track = self.__get_next()
     else:
         track = Track()
     return track
Exemple #26
0
 def load():
     track_ids = []
     if self.__playlist_id == Type.LOVED:
         for track_id in App().tracks.get_loved_track_ids(
                 [],
                 self.storage_type):
             if track_id not in track_ids:
                 track_ids.append(track_id)
     else:
         for track_id in App().playlists.get_track_ids(
                 self.__playlist_id):
             if track_id not in track_ids:
                 track_ids.append(track_id)
     return tracks_to_albums(
         [Track(track_id) for track_id in track_ids])
Exemple #27
0
 def populate(self):
     """
         Populate view
     """
     if App().player.queue:
         tracks = [Track(track_id) for track_id in App().player.queue]
         albums = tracks_to_albums(tracks)
     else:
         albums = App().player.albums
     if albums:
         if len(albums) == 1:
             self.add_reveal_albums(albums)
         AlbumsListView.populate(self, albums)
         self.show_placeholder(False)
     else:
         self.show_placeholder(True)
Exemple #28
0
 def _on_playlist_track_removed(self, playlists, playlist_id, uri):
     """
         Remove track from album list
         @param playlists as Playlists
         @param playlist_id as int
         @param uri as str
     """
     if playlist_id == self.__playlist_id:
         track = Track(App().tracks.get_id_by_uri(uri))
         for album_row in self.children:
             if album_row.album.id == track.album.id:
                 for track_row in album_row.children:
                     if track_row.track.id == track.id:
                         track_row.destroy()
                         if len(self.children) == 1:
                             album_row.destroy()
                             break
Exemple #29
0
 def set_party_ids(self):
     """
         Set party mode ids
     """
     if not self._is_party:
         return
     party_ids = App().settings.get_value("party-ids")
     storage_type = get_default_storage_type()
     album_ids = App().albums.get_ids(party_ids, [], storage_type, False)
     emit_signal(self, "playback-setted", [])
     self._albums = []
     if album_ids:
         emit_signal(self, "loading-changed", True, Track())
     for album_id in album_ids:
         album = Album(album_id, [], [], False)
         self._albums.append(album)
     emit_signal(self, "playback-setted", list(self._albums))
Exemple #30
0
    def __write_playlists(self, playlist_ids):
        """
            Write playlists on disk
            @param playlist_ids as [int]
        """
        for playlist_id in playlist_ids:
            if self.__cancellable.is_cancelled():
                break
            try:
                # Get tracks
                if App().playlists.get_smart(playlist_id):
                    request = App().playlists.get_smart_sql(playlist_id)
                    track_ids = App().db.execute(request)
                else:
                    track_ids = App().playlists.get_track_ids(playlist_id)

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

                # Write playlist file
                playlist_name = escape(App().playlists.get_name(playlist_id))
                playlist_uri = "%s/%s.m3u" % (self.__uri, playlist_name)
                Logger.debug("MtpSync::__write_playlists(): %s" % playlist_uri)
                temp_uri = os.path.join(tempfile.gettempdir(),
                                        "lollypop_%s.m3u" % playlist_name)
                m3u_temp = Gio.File.new_for_path(temp_uri)
                m3u_temp.replace_contents(
                    tracklist.encode("utf-8"), None, False,
                    Gio.FileCreateFlags.REPLACE_DESTINATION,
                    self.__cancellable)
                m3u = Gio.File.new_for_uri(playlist_uri)
                m3u_temp.move(m3u, Gio.FileCopyFlags.OVERWRITE, None, None)
            except Exception as e:
                Logger.error("MtpSync::__write_playlists(): %s", e)