diff --git a/pyproject.toml b/pyproject.toml index 9f9ab43..762bdc9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,7 @@ classifiers = [ ] dynamic = ["version"] dependencies = [ - "mopidy >= 4.0.0a7", + "mopidy >= 4.0.0a8", "pygobject >= 3.50", "pykka >= 4.1", ] diff --git a/src/mopidy_mpd/protocol/playback.py b/src/mopidy_mpd/protocol/playback.py index da54a4e..edaa913 100644 --- a/src/mopidy_mpd/protocol/playback.py +++ b/src/mopidy_mpd/protocol/playback.py @@ -2,8 +2,7 @@ from typing import TYPE_CHECKING, Never -from mopidy.core import PlaybackState -from mopidy.types import DurationMs, Percentage +from mopidy.types import DurationMs, Percentage, PlaybackState from mopidy_mpd import exceptions, protocol diff --git a/src/mopidy_mpd/protocol/status.py b/src/mopidy_mpd/protocol/status.py index ed95c63..d10c658 100644 --- a/src/mopidy_mpd/protocol/status.py +++ b/src/mopidy_mpd/protocol/status.py @@ -2,7 +2,7 @@ from typing import TYPE_CHECKING -from mopidy.core import PlaybackState +from mopidy.types import PlaybackState from mopidy_mpd import exceptions, protocol, translator diff --git a/tests/dummy_audio.py b/tests/dummy_audio.py index 70f4c81..fc45dc8 100644 --- a/tests/dummy_audio.py +++ b/tests/dummy_audio.py @@ -4,8 +4,11 @@ tests of the core and backends. """ +from typing import override + import pykka from mopidy import audio +from mopidy.types import DurationMs, PlaybackState def create_proxy(config=None, mixer=None): @@ -13,12 +16,11 @@ def create_proxy(config=None, mixer=None): # TODO: reset position on track change? -class DummyAudio(pykka.ThreadingActor): +class DummyAudio(audio.Audio, pykka.ThreadingActor): def __init__(self, config=None, mixer=None): super().__init__() - self.state = audio.PlaybackState.STOPPED - self._volume = 0 - self._position = 0 + self.state = PlaybackState.STOPPED + self._position = DurationMs(0) self._source_setup_callback = None self._about_to_finish_callback = None self._uri = None @@ -27,72 +29,60 @@ def __init__(self, config=None, mixer=None): self._tags = {} self._bad_uris = set() + @override def set_uri(self, uri, live_stream=False, download=False): assert self._uri is None, "prepare change not called before set" - self._position = 0 + self._position = DurationMs(0) self._uri = uri self._stream_changed = True self._live_stream = live_stream self._tags = {} - def set_appsrc(self, *args, **kwargs): - pass + @override + def set_source_setup_callback(self, callback): + self._source_setup_callback = callback - def emit_data(self, buffer_): - pass + @override + def set_about_to_finish_callback(self, callback): + self._about_to_finish_callback = callback + @override def get_position(self): return self._position + @override def set_position(self, position): self._position = position audio.AudioListener.send("position_changed", position=position) return True + @override def start_playback(self): - return self._change_state(audio.PlaybackState.PLAYING) + return self._change_state(PlaybackState.PLAYING) + @override def pause_playback(self): - return self._change_state(audio.PlaybackState.PAUSED) + return self._change_state(PlaybackState.PAUSED) + @override def prepare_change(self): self._uri = None self._source_setup_callback = None return True + @override def stop_playback(self): - return self._change_state(audio.PlaybackState.STOPPED) - - def get_volume(self): - return self._volume - - def set_volume(self, volume): - self._volume = volume - return True - - def set_metadata(self, track): - pass + return self._change_state(PlaybackState.STOPPED) + @override def get_current_tags(self): return self._tags - def set_source_setup_callback(self, callback): - self._source_setup_callback = callback - - def set_about_to_finish_callback(self, callback): - self._about_to_finish_callback = callback - - def enable_sync_handler(self): - pass - - def wait_for_state_change(self): - pass - def _change_state(self, new_state): if not self._uri: return False - if new_state == audio.PlaybackState.STOPPED and self._uri: + if new_state == PlaybackState.STOPPED and self._uri: self._stream_changed = True self._uri = None @@ -111,7 +101,7 @@ def _change_state(self, new_state): target_state=None, ) - if new_state == audio.PlaybackState.PLAYING: + if new_state == PlaybackState.PLAYING: self._tags["audio-codec"] = ["fake info..."] audio.AudioListener.send("tags_changed", tags=["audio-codec"]) @@ -123,27 +113,3 @@ def trigger_fake_playback_failure(self, uri): def trigger_fake_tags_changed(self, tags): self._tags.update(tags) audio.AudioListener.send("tags_changed", tags=self._tags.keys()) - - def get_source_setup_callback(self): - # This needs to be called from outside the actor or we lock up. - def wrapper(): - if self._source_setup_callback: - self._source_setup_callback() - - return wrapper - - def get_about_to_finish_callback(self): - # This needs to be called from outside the actor or we lock up. - def wrapper(): - if self._about_to_finish_callback: - self.prepare_change() - self._about_to_finish_callback() - - if not self._uri or not self._about_to_finish_callback: - self._tags = {} - audio.AudioListener.send("reached_end_of_stream") - else: - audio.AudioListener.send("position_changed", position=0) - audio.AudioListener.send("stream_changed", uri=self._uri) - - return wrapper diff --git a/tests/protocol/test_playback.py b/tests/protocol/test_playback.py index 610cb2c..d816dc5 100644 --- a/tests/protocol/test_playback.py +++ b/tests/protocol/test_playback.py @@ -1,7 +1,7 @@ import unittest -from mopidy.core import PlaybackState from mopidy.models import Track +from mopidy.types import PlaybackState from tests import protocol diff --git a/tests/protocol/test_regression.py b/tests/protocol/test_regression.py index 172a434..81208aa 100644 --- a/tests/protocol/test_regression.py +++ b/tests/protocol/test_regression.py @@ -22,8 +22,8 @@ class IssueGH17RegressionTest(protocol.BaseTestCase): - Press next until you get to the unplayable track """ - @mock.patch.object(protocol.core.tracklist.random, "shuffle", mock_shuffle) def test(self): + random.seed(1) tracks = [ Track(uri="dummy:a"), Track(uri="dummy:b"), @@ -42,14 +42,18 @@ def test(self): assert self.core.playback.get_current_track().get().uri == "dummy:a" self.send_request('random "1"') self.send_request("next") - assert self.core.playback.get_current_track().get().uri == "dummy:b" + assert self.core.playback.get_current_track().get().uri == "dummy:d" self.send_request("next") - # Should now be at track 'c', but playback fails and it skips ahead assert self.core.playback.get_current_track().get().uri == "dummy:f" self.send_request("next") - assert self.core.playback.get_current_track().get().uri == "dummy:d" + assert self.core.playback.get_current_track().get().uri == "dummy:a" self.send_request("next") assert self.core.playback.get_current_track().get().uri == "dummy:e" + self.send_request("next") + assert self.core.playback.get_current_track().get().uri == "dummy:b" + self.send_request("next") + # All tracks have been played, including the error one, which we skipped. + assert self.core.playback.get_current_track().get() is None class IssueGH18RegressionTest(protocol.BaseTestCase): diff --git a/tests/test_status.py b/tests/test_status.py index 23833ec..5ee2129 100644 --- a/tests/test_status.py +++ b/tests/test_status.py @@ -3,8 +3,8 @@ import pykka from mopidy import core -from mopidy.core import PlaybackState from mopidy.models import Track +from mopidy.types import PlaybackState from mopidy_mpd import dispatcher, uri_mapper from mopidy_mpd.protocol import status