def __init__(self, songs=None, playback_mode=PlaybackMode.loop, audio_select_policy='hq<>'): """ :param songs: list of :class:`feeluown.models.SongModel` :param playback_mode: :class:`feeluown.player.PlaybackMode` """ #: store value for ``current_song`` property self._current_song = None #: songs whose url is invalid self._bad_songs = DedupList() #: store value for ``songs`` property self._songs = DedupList(songs or []) self.audio_select_policy = audio_select_policy #: store value for ``playback_mode`` property self._playback_mode = playback_mode #: playback mode changed signal self.playback_mode_changed = Signal() self.song_changed = Signal() """current song changed signal The player will play the song after it receive the signal, when song is None, the player will stop playback. """ self.song_changed_v2 = Signal() """current song chagned signal, v2
def __init__(self, app, songs=None, playback_mode=PlaybackMode.loop, audio_select_policy='hq<>'): """ :param songs: list of :class:`feeluown.models.SongModel` :param playback_mode: :class:`feeluown.player.PlaybackMode` """ self._app = app #: init playlist mode normal self._mode = PlaylistMode.normal #: playlist eof signal # playlist have no enough songs self.eof_reached = Signal() #: playlist mode changed signal self.mode_changed = Signal() #: store value for ``current_song`` property self._current_song = None #: songs whose url is invalid self._bad_songs = DedupList() #: store value for ``songs`` property self._songs = DedupList(songs or []) self.audio_select_policy = audio_select_policy #: store value for ``playback_mode`` property self._playback_mode = playback_mode #: playback mode changed signal self.playback_mode_changed = Signal() self.song_changed = Signal() """current song changed signal The player will play the song after it receive the signal, when song is None, the player will stop playback. """ self.song_changed_v2 = Signal() """current song chagned signal, v2 emit(song, media) """ #: When watch mode is on, playlist try to play the mv/video of the song self.watch_mode = False self._t_scm = self._app.task_mgr.get_or_create('set-current-model') # .. versionadded:: 3.7.11 # The *songs_removed* and *songs_added* signal. self.songs_removed = Signal() # (index, count) self.songs_added = Signal() # (index, count) self._app.player.media_finished.connect(self._on_media_finished)
def __init__(self, app, songs=None, playback_mode=PlaybackMode.loop, audio_select_policy='hq<>'): """ :param songs: list of :class:`feeluown.models.SongModel` :param playback_mode: :class:`feeluown.player.PlaybackMode` """ self._app = app #: mainthread asyncio loop ref # We know that feeluown is a asyncio-app, and we can assume # that the playlist is inited in main thread. self._loop = asyncio.get_event_loop() #: init playlist mode normal self._mode = PlaylistMode.normal #: playlist eof signal # playlist have no enough songs self.eof_reached = Signal() #: playlist mode changed signal self.mode_changed = Signal() #: store value for ``current_song`` property self._current_song = None #: songs whose url is invalid self._bad_songs = DedupList() #: store value for ``songs`` property self._songs = DedupList(songs or []) self.audio_select_policy = audio_select_policy #: store value for ``playback_mode`` property self._playback_mode = playback_mode #: playback mode changed signal self.playback_mode_changed = Signal() self.song_changed = Signal() """current song changed signal The player will play the song after it receive the signal, when song is None, the player will stop playback. """ self.song_changed_v2 = Signal() """current song chagned signal, v2 emit(song, media) """ #: When watch mode is on, playlist try to play the mv/video of the song self.watch_mode = False
def addremove(): song_list = DedupList() num = 1000 for i in range(0, num): song = BriefSongModel(source='xxxx', identifier=str(i)) if song not in song_list: song_list.append(song) for i in range(num // 10): song_list.pop(0)
def init_from(self, songs): """ THINKING: maybe we should rename this method or maybe we should change mode on application level We change playlistmode here because the `player.play_all` call this method. We should check if we need to exit fm mode in `play_xxx`. Currently, we have two play_xxx API: play_all and play_song. 1. play_all -> init_from 2. play_song -> current_song.setter (alpha) temporarily, should only called by player.play_songs """ if self.mode is PlaylistMode.fm: self.mode = PlaylistMode.normal self.clear() # since we will call songs.clear method during playlist clearing, # we need to deepcopy songs object here. self._songs = DedupList(copy.deepcopy(songs))
def init_from(self, songs): """(alpha) temporarily, should only called by player.play_songs""" self.clear() # since we will call songs.clear method during playlist clearing, # we need to deepcopy songs object here. self._songs = DedupList(copy.deepcopy(songs))
def test_dedup_list(): # init assert DedupList([1, 2, 3]) == [1, 2, 3] dlist = DedupList([3, 2, 3, 4, 2, 3, 1]) assert dlist == [3, 2, 4, 1] # add dlist = dlist + [5, 1, 6] assert isinstance(dlist, DedupList) assert dlist == [3, 2, 4, 1, 5, 6] # radd dlist = [1, 2, 3, 7] + dlist assert isinstance(dlist, DedupList) assert dlist == [1, 2, 3, 7, 4, 5, 6] # setitem dlist[0] = 8 assert dlist == [8, 2, 3, 7, 4, 5, 6] with pytest.raises(ValueError): dlist[2] = 5 # append dlist.append(8) assert dlist == [8, 2, 3, 7, 4, 5, 6] dlist.append(9) assert dlist == [8, 2, 3, 7, 4, 5, 6, 9] # extend dlist.extend([8, 1, 10, 11, 3]) assert dlist == [8, 2, 3, 7, 4, 5, 6, 9, 1, 10, 11] # insert dlist.insert(0, 5) assert dlist == [8, 2, 3, 7, 4, 5, 6, 9, 1, 10, 11] dlist.insert(0, 12) assert dlist == [12, 8, 2, 3, 7, 4, 5, 6, 9, 1, 10, 11] dlist.insert(-1, 13) assert dlist == [12, 8, 2, 3, 7, 4, 5, 6, 9, 1, 10, 13, 11] dlist.insert(-12, 14) assert dlist == [12, 14, 8, 2, 3, 7, 4, 5, 6, 9, 1, 10, 13, 11] dlist.insert(-14, 15) assert dlist == [15, 12, 14, 8, 2, 3, 7, 4, 5, 6, 9, 1, 10, 13, 11] dlist.insert(-99, 16) assert dlist == [16, 15, 12, 14, 8, 2, 3, 7, 4, 5, 6, 9, 1, 10, 13, 11] dlist.insert(99, 17) assert dlist == [16, 15, 12, 14, 8, 2, 3, 7, 4, 5, 6, 9, 1, 10, 13, 11, 17] # pop assert dlist.pop() == 17 assert dlist == [16, 15, 12, 14, 8, 2, 3, 7, 4, 5, 6, 9, 1, 10, 13, 11] assert dlist.pop(0) == 16 assert dlist == [15, 12, 14, 8, 2, 3, 7, 4, 5, 6, 9, 1, 10, 13, 11] assert dlist.pop(-2) == 13 assert dlist == [15, 12, 14, 8, 2, 3, 7, 4, 5, 6, 9, 1, 10, 11] with pytest.raises(IndexError): dlist.pop(20) # copy dlist_orig = [Obj(i) for i in range(5)] dlist_copy = copy(dlist_orig) assert dlist_copy == dlist_orig assert id(dlist_copy) != id(dlist_orig) assert id(dlist_copy[0]) == id(dlist_orig[0]) # deepcopy dlist_orig = [Obj(i) for i in range(5)] dlist_copy = deepcopy(dlist_orig) assert dlist_copy == dlist_orig assert id(dlist_copy) != id(dlist_orig) assert id(dlist_copy[0]) != id(dlist_orig[0]) # getitem assert [dlist[i] for i in range(14)] == \ [15, 12, 14, 8, 2, 3, 7, 4, 5, 6, 9, 1, 10, 11] # swap dlist.swap(7, 9) assert dlist == [15, 12, 14, 8, 2, 3, 7, 6, 5, 4, 9, 1, 10, 11] # index for idx, item in zip(range(len(dlist)), dlist): assert dlist.index(item) == idx with pytest.raises(ValueError): dlist.index(8, 4) with pytest.raises(ValueError): dlist.index(8, 1, 3) # sort dlist.sort() assert dlist == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15] for idx, item in zip(range(len(dlist)), dlist): assert dlist.index(item) == idx # remove dlist.remove(3) assert dlist == [1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15] with pytest.raises(ValueError): dlist.remove(16) # index should be correct after item is removed assert dlist.index(1) == 0 assert dlist.index(4) == 2 # clear dlist.clear() assert dlist == []