コード例 #1
0
ファイル: test_player.py プロジェクト: zzcandor/FeelUOwn
async def test_playlist_exit_fm_mode(app_mock, song, mocker):
    mocker.patch.object(Playlist, 'a_set_current_song')
    pl = Playlist(app_mock)
    pl.mode = PlaylistMode.fm
    pl.current_song = song
    assert pl.mode is PlaylistMode.normal
    assert app_mock.task_mgr.get_or_create.called
コード例 #2
0
async def test_reactivate_fm_mode_after_playing_other_songs(
        event_loop, app_mock, song, song1, mocker):
    def f(*args, **kwargs):
        return [song1]

    def is_active(fm):
        return fm.is_active

    playlist = Playlist(app_mock)
    app_mock.playlist = playlist
    app_mock.task_mgr = TaskManager(app_mock, event_loop)
    fm = FM(app_mock)
    fm.activate(f)
    assert playlist.mode is PlaylistMode.fm
    await asyncio.sleep(0.1)  # wait for fm-fetch-song task finished

    # user trigger play next
    app_mock.playlist.current_song = song
    assert playlist.mode is PlaylistMode.normal
    assert is_active(fm) is False

    await asyncio.sleep(0.1)  # wait for validate-song task finished
    assert playlist.list() == [song]

    fm.activate(f)
    assert is_active(fm) is True
    assert playlist.mode is PlaylistMode.fm
コード例 #3
0
ファイル: test_player.py プロジェクト: xiaospica/FeelUOwn
async def test_playlist_exit_fm_mode(app_mock, song, mocker,
                                     mock_a_set_cursong):
    pl = Playlist(app_mock)
    pl.mode = PlaylistMode.fm
    pl.current_song = song
    assert pl.mode is PlaylistMode.normal
    assert app_mock.task_mgr.get_or_create.called
コード例 #4
0
def test_play_all(app_mock):
    player = Player()
    playlist = Playlist(app_mock)
    player.set_playlist(playlist)
    playlist.mode = PlaylistMode.fm
    playlist.set_models([], next_=True)
    assert playlist.mode == PlaylistMode.normal
コード例 #5
0
async def test_playlist_change_mode(app_mock, mocker):
    # from normal to fm
    pl = Playlist(app_mock)
    pl.mode = PlaylistMode.fm
    assert pl.playback_mode is PlaybackMode.sequential

    # from fm to normal
    pl.mode = PlaylistMode.normal
    assert pl.mode is PlaylistMode.normal
コード例 #6
0
def test_playlist_next_should_call_set_current_song(app_mock, mocker, song):
    mock_set_current_song = mocker.patch.object(Playlist, 'set_current_song')
    pl = Playlist(app_mock)
    pl.add(song)
    task = pl.next()
    # Next method should call set_current_song and return an asyncio task.
    # Since it is complex to mock and return a asyncio.Task, we do not
    # check the type of task object.
    assert task is not None
    assert mock_set_current_song.called
コード例 #7
0
class TestPlaylist(TestCase):
    def setUp(self):
        self.s1 = FakeSongModel()
        self.s2 = FakeSongModel()
        self.playlist = Playlist(app_mock)
        self.playlist.add(self.s1)
        self.playlist.add(self.s2)

    def tearDown(self):
        self.playlist.clear()

    def test_add(self):
        self.playlist.add(self.s1)
        self.assertEqual(len(self.playlist), 2)

    def test_getitem(self):
        self.assertEqual(self.playlist[1], self.s2)

    def test_mark_as_bad(self):
        self.assertEqual(self.playlist.next_song, self.s1)
        self.playlist.mark_as_bad(self.s1)
        self.assertEqual(self.playlist.next_song, self.s2)

    def test_list(self):
        self.assertIn(self.s1, self.playlist.list())
コード例 #8
0
ファイル: test_player.py プロジェクト: zzcandor/FeelUOwn
async def test_playlist_change_mode(app_mock, mocker):
    mock_clear = mocker.patch.object(Playlist, 'clear')
    # from normal to fm
    pl = Playlist(app_mock)
    pl.mode = PlaylistMode.fm
    mock_clear.assert_called_once_with()
    assert pl.playback_mode is PlaybackMode.sequential

    # from fm to normal
    pl.mode = PlaylistMode.normal
    assert pl.mode is PlaylistMode.normal
コード例 #9
0
ファイル: test_player.py プロジェクト: roceys/FeelUOwn
async def test_playlist_fm_mode_play_previous(app_mock, song, song1, mocker):
    pl = Playlist(app_mock)
    pl.mode = PlaylistMode.fm
    pl.fm_add(song1)
    pl.fm_add(song)
    pl._current_song = song
    pl.current_song = song1  # should not exit fm mode
    assert pl.mode is PlaylistMode.fm
コード例 #10
0
ファイル: test_player.py プロジェクト: zzcandor/FeelUOwn
async def test_playlist_fm_mode_play_next(app_mock, song, song1, mocker):
    mocker.patch.object(Playlist, 'a_set_current_song')
    pl = Playlist(app_mock)
    pl.mode = PlaylistMode.fm
    pl.fm_add(song1)
    pl.fm_add(song)
    pl._current_song = song1
    pl.current_song = song   # should not exit fm mode
    assert pl.mode is PlaylistMode.fm
コード例 #11
0
ファイル: test_player.py プロジェクト: xiaospica/FeelUOwn
async def test_playlist_fm_mode_play_next(app_mock, song, song1,
                                          mock_a_set_cursong):
    pl = Playlist(app_mock)
    pl.mode = PlaylistMode.fm
    pl.fm_add(song1)
    pl.fm_add(song)
    pl._current_song = song1
    pl.current_song = song   # should not exit fm mode
    assert pl.mode is PlaylistMode.fm
コード例 #12
0
async def test_playlist_resumed_from_eof_reached(app_mock, song, mocker,
                                                 mock_a_set_cursong):
    mock_set_current_song = mocker.patch.object(Playlist, 'set_current_song')
    pl = Playlist(app_mock)

    def feed_playlist():
        pl.fm_add(song)
        pl.next()

    pl.eof_reached.connect(feed_playlist)
    pl.mode = PlaylistMode.fm
    pl.next()
    mock_set_current_song.assert_has_calls([mock.call(song)])
コード例 #13
0
ファイル: test_player.py プロジェクト: roceys/FeelUOwn
async def test_playlist_eof_reached(app_mock, song, mocker):
    mock_emit = mocker.patch.object(Signal, 'emit')
    pl = Playlist(app_mock)
    pl.mode = PlaylistMode.fm
    pl.next()  # first emit
    pl.fm_add(song)
    # assume current_song is song
    pl._current_song = song
    pl.next()  # second emit
    mock_emit.assert_has_calls([
        mock.call(),
        mock.call(),
    ])
コード例 #14
0
ファイル: test_player.py プロジェクト: roceys/FeelUOwn
async def test_playlist_resumed_from_eof_reached(app_mock, song, mocker):
    mock_current_song = mocker.patch.object(Playlist, 'current_song')
    mock_set = mocker.MagicMock()
    mock_current_song.__get__ = mocker.MagicMock(return_value=None)
    mock_current_song.__set__ = mock_set
    pl = Playlist(app_mock)

    def feed_playlist():
        pl.fm_add(song)
        pl.next()

    pl.eof_reached.connect(feed_playlist)
    pl.mode = PlaylistMode.fm
    pl.next()
    mock_set.assert_has_calls([mock.call(pl, song)])
コード例 #15
0
def test_when_playlist_fm_mode_exited(app_mock, song, mocker):
    mock_fetch = mocker.MagicMock()
    app_mock.playlist = Playlist(app_mock)
    fm = FM(app_mock)
    fm.activate(mock_fetch)
    app_mock.playlist.mode = PlaylistMode.normal
    assert fm._activated is False  # noqa
コード例 #16
0
ファイル: app.py プロジェクト: BruceZhang1993/FeelUOwn
    def __init__(self, args, config):

        self.mode = config.MODE  # DEPRECATED: use app.config.MODE instead
        self.config = config
        self.args = args
        self.initialized = Signal()
        self.about_to_shutdown = Signal()

        self.plugin_mgr = PluginsManager(self)
        self.request = Request()  # TODO: rename request to http
        self.version_mgr = VersionManager(self)
        self.task_mgr = TaskManager(self)

        # Library.
        self.library = Library(config.PROVIDERS_STANDBY)
        # TODO: initialization should be moved into initialize
        Resolver.library = self.library

        # Player.
        self.player = Player(
            audio_device=bytes(config.MPV_AUDIO_DEVICE, 'utf-8'))
        self.playlist = Playlist(
            self, audio_select_policy=config.AUDIO_SELECT_POLICY)
        self.live_lyric = LiveLyric(self)
        self.fm = FM(self)

        # TODO: initialization should be moved into initialize
        self.player.set_playlist(self.playlist)

        self.about_to_shutdown.connect(lambda _: self.dump_state(), weak=False)
コード例 #17
0
ファイル: test_player.py プロジェクト: zzcandor/FeelUOwn
async def test_prepare_media_in_non_mainthread(app_mock, song):
    pl = Playlist(app_mock)
    loop = asyncio.get_event_loop()
    try:
        await loop.run_in_executor(None, pl.prepare_media, song)
    except RuntimeError:
        pytest.fail('Prepare media in non mainthread should work')
コード例 #18
0
async def test_playlist_eof_reached(app_mock, song, mocker,
                                    mock_a_set_cursong):
    mock_emit = mocker.patch.object(Signal, 'emit')
    pl = Playlist(app_mock)
    pl.mode = PlaylistMode.fm
    pl.next()  # first emit
    pl.fm_add(song)
    # assume current_song is song
    pl._current_song = song
    pl.next()  # second emit
    mock_emit.assert_has_calls([
        mock.call(PlaybackMode.sequential),
        mock.call(PlaylistMode.fm),
        mock.call(),
        mock.call(0, 1),  # songs_added
        mock.call()
    ])
コード例 #19
0
def test_change_song(app_mock, mocker, song, song1):
    mocker.patch.object(Player, 'play')
    pl = Playlist(app_mock)
    pl.add(song)
    pl._current_song = song
    player = Player()
    player.set_playlist(pl)
    with mock.patch.object(Playlist,
                           'current_song',
                           new_callable=mock.PropertyMock) as mock_s:
        mock_s.return_value = song  # return current song
        pl.set_current_song(song1)
        pl.next()
        assert pl.current_song == song
コード例 #20
0
def mpvplayer():
    player = MpvPlayer(Playlist(app_mock))
    player.volume = 0
    yield player
    player.stop()
    # HELP: player.shutdown() causes error on Windows
    #  Windows fatal exception: code 0xe24c4a02
    # Ref: https://github.com/feeluown/FeelUOwn/runs/4996179558
    player.shutdown()
コード例 #21
0
def attach_attrs(app):
    """初始化 app 属性"""
    loop = asyncio.get_event_loop()
    app.library = Library(app.config.PROVIDERS_STANDBY)
    app.live_lyric = LiveLyric(app)
    player_kwargs = dict(
        audio_device=bytes(app.config.MPV_AUDIO_DEVICE, 'utf-8'))
    app.playlist = Playlist(app,
                            audio_select_policy=app.config.AUDIO_SELECT_POLICY)
    app.player = Player(app.playlist, **(player_kwargs or {}))
    app.plugin_mgr = PluginsManager(app)
    app.request = Request()
    app.task_mgr = TaskManager(app, loop)
    app.fm = FM(app)

    if app.mode & (app.DaemonMode | app.GuiMode):
        app.version_mgr = VersionManager(app)

    if app.mode & app.DaemonMode:
        app.server = FuoServer(app)
        app.pubsub_gateway = PubsubGateway()
        app._ll_publisher = LiveLyricPublisher(app.pubsub_gateway)

    if app.mode & app.GuiMode:
        from feeluown.uimodels.provider import ProviderUiManager
        from feeluown.uimodels.playlist import PlaylistUiManager
        from feeluown.uimodels.my_music import MyMusicUiManager
        from feeluown.uimodels.collection import CollectionUiManager
        from feeluown.collection import CollectionManager

        from .gui.browser import Browser
        from .gui.hotkey import HotkeyManager
        from .gui.image import ImgManager
        from .gui.theme import ThemeManager
        from .gui.tips import TipsManager
        from .gui.ui import Ui
        from .gui.tray import Tray

        # GUI 的一些辅助管理模块
        app.coll_mgr = CollectionManager(app)
        app.theme_mgr = ThemeManager(app)
        app.tips_mgr = TipsManager(app)
        app.hotkey_mgr = HotkeyManager(app)
        app.img_mgr = ImgManager(app)

        # GUI 组件的数据管理模块
        app.pvd_uimgr = ProviderUiManager(app)
        app.pl_uimgr = PlaylistUiManager(app)
        app.mymusic_uimgr = MyMusicUiManager(app)
        app.coll_uimgr = CollectionUiManager(app)

        app.browser = Browser(app)
        app.ui = Ui(app)
        if app.config.ENABLE_TRAY:
            app.tray = Tray(app)
        app.show_msg = app.ui.toolbar.status_line.get_item(
            'notify').widget.show_msg
コード例 #22
0
async def test_fetch_song_cancelled(event_loop, app_mock, song, mocker):
    mock_fetch = mocker.MagicMock()
    app_mock.playlist = Playlist(app_mock)
    app_mock.task_mgr = TaskManager(app_mock, event_loop)
    fm = FM(app_mock)
    fm.activate(mock_fetch)
    task_spec = app_mock.task_mgr.get_or_create(fm._fetch_songs_task_name)
    task_spec._task.cancel()
    await asyncio.sleep(0.1)  # schedule cancel callback
    assert fm._is_fetching_songs is False
コード例 #23
0
def test_fm_activate_and_deactivate(app_mock, song, mocker):
    mock_fetch = mocker.MagicMock(return_value=[song])
    app_mock.playlist = Playlist(app_mock)
    fm = FM(app_mock)
    fm.activate(mock_fetch)
    assert app_mock.playlist.mode is PlaylistMode.fm
    assert app_mock.task_mgr.get_or_create.called

    fm.deactivate()
    assert app_mock.playlist.mode is PlaylistMode.normal
コード例 #24
0
ファイル: test_playlist.py プロジェクト: zhiiker/FeelUOwn
def pl(app_mock, song, song1):
    """
    pl: [song, song1], current_song: song
    """
    playlist = Playlist(app_mock)
    playlist.add(song)
    playlist.add(song1)
    playlist._current_song = song
    return playlist
コード例 #25
0
ファイル: test_serializers.py プロジェクト: zhiiker/FeelUOwn
def test_serialize_app(mocker):
    app = mocker.Mock(spec=App)
    app.live_lyric = mocker.Mock()
    app.live_lyric.current_sentence = ''
    player = Player(Playlist(app))
    app.player = player
    app.playlist = player.playlist
    for format in ('plain', 'json'):
        serialize(format, app, brief=False)
        serialize(format, app, fetch=True)
    player.shutdown()
コード例 #26
0
async def test_fetch_song_failed(event_loop, app_mock, song, mocker):
    mock_fetch = mocker.MagicMock(side_effect=ProviderIOError)
    mock_fm_add = mocker.patch.object(Playlist, 'fm_add')
    app_mock.playlist = Playlist(app_mock)
    app_mock.task_mgr = TaskManager(app_mock, event_loop)
    fm = FM(app_mock)
    fm.activate(mock_fetch)
    assert fm._is_fetching_songs is True
    await asyncio.sleep(0.1)  # schedule mock_fetch callback
    assert fm._is_fetching_songs is False
    assert not mock_fm_add.called
コード例 #27
0
class TestPlayerAndPlaylist(TestCase):
    def setUp(self):
        self.playlist = Playlist(app_mock)
        self.player = MpvPlayer()
        self.player.set_playlist(self.player)

    def tearDown(self):
        self.player.stop()
        self.player.shutdown()

    @skipIf(cannot_play_audio, '')
    @mock.patch.object(MpvPlayer, 'play')
    def test_remove_current_song_2(self, mock_play):
        """当播放列表只有一首歌时,移除它"""
        s1 = FakeValidSongModel()
        self.playlist.current_song = s1
        time.sleep(MPV_SLEEP_SECOND)  # 让 Mpv 真正的开始播放
        self.playlist.remove(s1)
        self.assertEqual(len(self.playlist), 0)
        self.assertEqual(self.player.state, State.stopped)
コード例 #28
0
async def test_multiple_eof_reached_signal(event_loop, app_mock, song, mocker):
    mock_fetch = mocker.MagicMock(return_value=[song] * 3)
    mock_fm_add = mocker.patch.object(Playlist, 'fm_add')
    app_mock.playlist = Playlist(app_mock)
    app_mock.task_mgr = TaskManager(app_mock, event_loop)
    fm = FM(app_mock)
    fm.activate(mock_fetch)
    app_mock.playlist.next()
    app_mock.playlist.next()
    task_spec = app_mock.task_mgr.get_or_create(fm._fetch_songs_task_name)
    await task_spec._task  # this is a little bit tricky
    # called exactly once
    mock_fetch.assert_called_once_with(3)
    assert mock_fm_add.called
コード例 #29
0
ファイル: test_player.py プロジェクト: roceys/FeelUOwn
async def test_set_cursong_in_non_mainthread(app_mock, song):
    pl = Playlist(app_mock)

    def set_in_non_mainthread():
        pl.current_song = song

    loop = asyncio.get_event_loop()
    try:
        # make song url invalid
        song.url = ''
        # playlist should create a asyncio task to fetch a standby
        # set current song in non mainthread
        await loop.run_in_executor(None, set_in_non_mainthread)
    except RuntimeError:
        pytest.fail('Set current song in non mainthread should work')
コード例 #30
0
ファイル: test_player.py プロジェクト: zhiiker/FeelUOwn
async def test_play_next_bad_song(app_mock, song, song1, mocker):
    """
    Prepare media for song raises unknown error, the song should
    be marked as bad.
    """
    pl = Playlist(app_mock)
    mocker.patch.object(pl, '_prepare_media', side_effect=Exception())
    mock_mark_as_bad = mocker.patch.object(pl, 'mark_as_bad')
    mock_next = mocker.patch.object(pl, 'next')
    pl.add(song)
    pl.add(song1)
    pl._current_song = song
    await pl.a_set_current_song(pl.next_song)
    assert mock_mark_as_bad.called
    assert mock_next.called