Fix 'load' so one can append a playlist to the current playlist
This commit is contained in:
parent
465a57b3af
commit
fb6b196646
@ -50,6 +50,7 @@ greatly improved MPD client support.
|
|||||||
- Implement ``seek`` and ``seekid``.
|
- Implement ``seek`` and ``seekid``.
|
||||||
- Fix ``playlistfind`` output so the correct song is played when playing
|
- Fix ``playlistfind`` output so the correct song is played when playing
|
||||||
songs directly from search results in GMPC.
|
songs directly from search results in GMPC.
|
||||||
|
- Fix ``load`` so that one can append a playlist to the current playlist.
|
||||||
|
|
||||||
- Backends:
|
- Backends:
|
||||||
|
|
||||||
@ -73,7 +74,10 @@ greatly improved MPD client support.
|
|||||||
- :meth:`mopidy.backends.base.BaseBackend()` now accepts an
|
- :meth:`mopidy.backends.base.BaseBackend()` now accepts an
|
||||||
``output_queue`` which it can use to send messages (i.e. audio data)
|
``output_queue`` which it can use to send messages (i.e. audio data)
|
||||||
to the output process.
|
to the output process.
|
||||||
|
- :meth:`mopidy.backends.base.BaseCurrentPlaylistController.load()` now
|
||||||
|
appends to the existing playlist. Use
|
||||||
|
:meth:`mopidy.backends.base.BaseCurrentPlaylistController.clear()` if you
|
||||||
|
want to clear it first.
|
||||||
|
|
||||||
|
|
||||||
0.1.0a3 (2010-08-03)
|
0.1.0a3 (2010-08-03)
|
||||||
|
|||||||
@ -107,16 +107,15 @@ class BaseCurrentPlaylistController(object):
|
|||||||
|
|
||||||
def load(self, tracks):
|
def load(self, tracks):
|
||||||
"""
|
"""
|
||||||
Replace the tracks in the current playlist with the given tracks.
|
Append the given tracks to the current playlist.
|
||||||
|
|
||||||
:param tracks: tracks to load
|
:param tracks: tracks to load
|
||||||
:type tracks: list of :class:`mopidy.models.Track`
|
:type tracks: list of :class:`mopidy.models.Track`
|
||||||
"""
|
"""
|
||||||
self._cp_tracks = []
|
|
||||||
self.version += 1
|
self.version += 1
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
self.add(track)
|
self.add(track)
|
||||||
self.backend.playback.new_playlist_loaded_callback()
|
self.backend.playback.on_current_playlist_change()
|
||||||
|
|
||||||
def move(self, start, end, to_position):
|
def move(self, start, end, to_position):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -253,23 +253,21 @@ class BasePlaybackController(object):
|
|||||||
self.stop()
|
self.stop()
|
||||||
self.current_cp_track = None
|
self.current_cp_track = None
|
||||||
|
|
||||||
def new_playlist_loaded_callback(self):
|
def on_current_playlist_change(self):
|
||||||
"""
|
"""
|
||||||
Tell the playback controller that a new playlist has been loaded.
|
Tell the playback controller that the current playlist has changed.
|
||||||
|
|
||||||
Typically called by :class:`mopidy.process.CoreProcess` after a message
|
Used by :class:`mopidy.backends.base.BaseCurrentPlaylistController`.
|
||||||
from a library thread is received.
|
|
||||||
"""
|
"""
|
||||||
self.current_cp_track = None
|
|
||||||
self._first_shuffle = True
|
self._first_shuffle = True
|
||||||
self._shuffled = []
|
self._shuffled = []
|
||||||
|
|
||||||
if self.state == self.PLAYING:
|
if not self.backend.current_playlist.cp_tracks:
|
||||||
if len(self.backend.current_playlist.tracks) > 0:
|
self.stop()
|
||||||
self.play()
|
self.current_cp_track = None
|
||||||
else:
|
elif (self.current_cp_track not in
|
||||||
self.stop()
|
self.backend.current_playlist.cp_tracks):
|
||||||
elif self.state == self.PAUSED:
|
self.current_cp_track = None
|
||||||
self.stop()
|
self.stop()
|
||||||
|
|
||||||
def next(self):
|
def next(self):
|
||||||
|
|||||||
@ -341,6 +341,7 @@ def swap(frontend, songpos1, songpos2):
|
|||||||
tracks.insert(songpos1, song2)
|
tracks.insert(songpos1, song2)
|
||||||
del tracks[songpos2]
|
del tracks[songpos2]
|
||||||
tracks.insert(songpos2, song1)
|
tracks.insert(songpos2, song1)
|
||||||
|
frontend.backend.current_playlist.clear()
|
||||||
frontend.backend.current_playlist.load(tracks)
|
frontend.backend.current_playlist.load(tracks)
|
||||||
|
|
||||||
@handle_pattern(r'^swapid "(?P<cpid1>\d+)" "(?P<cpid2>\d+)"$')
|
@handle_pattern(r'^swapid "(?P<cpid1>\d+)" "(?P<cpid2>\d+)"$')
|
||||||
|
|||||||
@ -86,6 +86,10 @@ def load(frontend, name):
|
|||||||
``load {NAME}``
|
``load {NAME}``
|
||||||
|
|
||||||
Loads the playlist ``NAME.m3u`` from the playlist directory.
|
Loads the playlist ``NAME.m3u`` from the playlist directory.
|
||||||
|
|
||||||
|
*Clarifications:*
|
||||||
|
|
||||||
|
- ``load`` appends the given playlist to the current playlist.
|
||||||
"""
|
"""
|
||||||
matches = frontend.backend.stored_playlists.search(name)
|
matches = frontend.backend.stored_playlists.search(name)
|
||||||
if matches:
|
if matches:
|
||||||
@ -139,9 +143,9 @@ def playlistmove(frontend, name, from_pos, to_pos):
|
|||||||
|
|
||||||
*Clarifications:*
|
*Clarifications:*
|
||||||
|
|
||||||
- The second argument is not a ``SONGID`` as used elsewhere in the
|
- The second argument is not a ``SONGID`` as used elsewhere in the protocol
|
||||||
protocol documentation, but just the ``SONGPOS`` to move *from*,
|
documentation, but just the ``SONGPOS`` to move *from*, i.e.
|
||||||
i.e. ``playlistmove {NAME} {FROM_SONGPOS} {TO_SONGPOS}``.
|
``playlistmove {NAME} {FROM_SONGPOS} {TO_SONGPOS}``.
|
||||||
"""
|
"""
|
||||||
raise MpdNotImplemented # TODO
|
raise MpdNotImplemented # TODO
|
||||||
|
|
||||||
|
|||||||
@ -91,12 +91,6 @@ class BaseCurrentPlaylistControllerTest(object):
|
|||||||
self.controller.clear()
|
self.controller.clear()
|
||||||
self.assertEqual(self.playback.state, self.playback.STOPPED)
|
self.assertEqual(self.playback.state, self.playback.STOPPED)
|
||||||
|
|
||||||
def test_load(self):
|
|
||||||
tracks = []
|
|
||||||
self.assertNotEqual(id(tracks), id(self.controller.tracks))
|
|
||||||
self.controller.load(tracks)
|
|
||||||
self.assertEqual(tracks, self.controller.tracks)
|
|
||||||
|
|
||||||
def test_get_by_uri_returns_unique_match(self):
|
def test_get_by_uri_returns_unique_match(self):
|
||||||
track = Track(uri='a')
|
track = Track(uri='a')
|
||||||
self.controller.load([Track(uri='z'), track, Track(uri='y')])
|
self.controller.load([Track(uri='z'), track, Track(uri='y')])
|
||||||
@ -136,10 +130,15 @@ class BaseCurrentPlaylistControllerTest(object):
|
|||||||
self.controller.load([track1, track2, track3])
|
self.controller.load([track1, track2, track3])
|
||||||
self.assertEqual(track2, self.controller.get(uri='b')[1])
|
self.assertEqual(track2, self.controller.get(uri='b')[1])
|
||||||
|
|
||||||
@populate_playlist
|
def test_load_appends_to_the_current_playlist(self):
|
||||||
def test_load_replaces_playlist(self):
|
self.controller.load([Track(uri='a'), Track(uri='b')])
|
||||||
self.backend.current_playlist.load([])
|
self.assertEqual(len(self.controller.tracks), 2)
|
||||||
self.assertEqual(len(self.backend.current_playlist.tracks), 0)
|
self.controller.load([Track(uri='c'), Track(uri='d')])
|
||||||
|
self.assertEqual(len(self.controller.tracks), 4)
|
||||||
|
self.assertEqual(self.controller.tracks[0].uri, 'a')
|
||||||
|
self.assertEqual(self.controller.tracks[1].uri, 'b')
|
||||||
|
self.assertEqual(self.controller.tracks[2].uri, 'c')
|
||||||
|
self.assertEqual(self.controller.tracks[3].uri, 'd')
|
||||||
|
|
||||||
def test_load_does_not_reset_version(self):
|
def test_load_does_not_reset_version(self):
|
||||||
version = self.controller.version
|
version = self.controller.version
|
||||||
@ -148,22 +147,17 @@ class BaseCurrentPlaylistControllerTest(object):
|
|||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_load_preserves_playing_state(self):
|
def test_load_preserves_playing_state(self):
|
||||||
tracks = self.controller.tracks
|
|
||||||
playback = self.playback
|
|
||||||
|
|
||||||
self.playback.play()
|
self.playback.play()
|
||||||
self.controller.load([tracks[1]])
|
track = self.playback.current_track
|
||||||
self.assertEqual(playback.state, playback.PLAYING)
|
self.controller.load(self.controller.tracks[1:2])
|
||||||
self.assertEqual(tracks[1], self.playback.current_track)
|
self.assertEqual(self.playback.state, self.playback.PLAYING)
|
||||||
|
self.assertEqual(self.playback.current_track, track)
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_load_preserves_stopped_state(self):
|
def test_load_preserves_stopped_state(self):
|
||||||
tracks = self.controller.tracks
|
self.controller.load(self.controller.tracks[1:2])
|
||||||
playback = self.playback
|
self.assertEqual(self.playback.state, self.playback.STOPPED)
|
||||||
|
self.assertEqual(self.playback.current_track, None)
|
||||||
self.controller.load([tracks[2]])
|
|
||||||
self.assertEqual(playback.state, playback.STOPPED)
|
|
||||||
self.assertEqual(None, self.playback.current_track)
|
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_move_single(self):
|
def test_move_single(self):
|
||||||
@ -575,15 +569,15 @@ class BasePlaybackControllerTest(object):
|
|||||||
self.playback.end_of_track_callback()
|
self.playback.end_of_track_callback()
|
||||||
self.assertEqual(self.playback.current_playlist_position, None)
|
self.assertEqual(self.playback.current_playlist_position, None)
|
||||||
|
|
||||||
def test_new_playlist_loaded_callback_gets_called(self):
|
def test_on_current_playlist_change_gets_called(self):
|
||||||
callback = self.playback.new_playlist_loaded_callback
|
callback = self.playback.on_current_playlist_change
|
||||||
|
|
||||||
def wrapper():
|
def wrapper():
|
||||||
wrapper.called = True
|
wrapper.called = True
|
||||||
return callback()
|
return callback()
|
||||||
wrapper.called = False
|
wrapper.called = False
|
||||||
|
|
||||||
self.playback.new_playlist_loaded_callback = wrapper
|
self.playback.on_current_playlist_change = wrapper
|
||||||
self.backend.current_playlist.load([])
|
self.backend.current_playlist.load([])
|
||||||
|
|
||||||
self.assert_(wrapper.called)
|
self.assert_(wrapper.called)
|
||||||
@ -608,27 +602,28 @@ class BasePlaybackControllerTest(object):
|
|||||||
self.assert_(event.is_set())
|
self.assert_(event.is_set())
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_new_playlist_loaded_callback_when_playing(self):
|
def test_on_current_playlist_change_when_playing(self):
|
||||||
self.playback.play()
|
self.playback.play()
|
||||||
|
current_track = self.playback.current_track
|
||||||
self.backend.current_playlist.load([self.tracks[2]])
|
self.backend.current_playlist.load([self.tracks[2]])
|
||||||
self.assertEqual(self.playback.state, self.playback.PLAYING)
|
self.assertEqual(self.playback.state, self.playback.PLAYING)
|
||||||
self.assertEqual(self.playback.current_track, self.tracks[2])
|
self.assertEqual(self.playback.current_track, current_track)
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_new_playlist_loaded_callback_when_stopped(self):
|
def test_on_current_playlist_change_when_stopped(self):
|
||||||
|
current_track = self.playback.current_track
|
||||||
self.backend.current_playlist.load([self.tracks[2]])
|
self.backend.current_playlist.load([self.tracks[2]])
|
||||||
self.assertEqual(self.playback.state, self.playback.STOPPED)
|
self.assertEqual(self.playback.state, self.playback.STOPPED)
|
||||||
self.assertEqual(self.playback.current_track, None)
|
self.assertEqual(self.playback.current_track, None)
|
||||||
self.assertEqual(self.playback.next_track, self.tracks[2])
|
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_new_playlist_loaded_callback_when_paused(self):
|
def test_on_current_playlist_change_when_paused(self):
|
||||||
self.playback.play()
|
self.playback.play()
|
||||||
self.playback.pause()
|
self.playback.pause()
|
||||||
|
current_track = self.playback.current_track
|
||||||
self.backend.current_playlist.load([self.tracks[2]])
|
self.backend.current_playlist.load([self.tracks[2]])
|
||||||
self.assertEqual(self.playback.state, self.playback.STOPPED)
|
self.assertEqual(self.playback.state, self.backend.playback.PAUSED)
|
||||||
self.assertEqual(self.playback.current_track, None)
|
self.assertEqual(self.playback.current_track, current_track)
|
||||||
self.assertEqual(self.playback.next_track, self.tracks[2])
|
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_pause_when_stopped(self):
|
def test_pause_when_stopped(self):
|
||||||
@ -899,7 +894,7 @@ class BasePlaybackControllerTest(object):
|
|||||||
self.playback.random = True
|
self.playback.random = True
|
||||||
self.assertEqual(self.playback.next_track, self.tracks[2])
|
self.assertEqual(self.playback.next_track, self.tracks[2])
|
||||||
self.backend.current_playlist.load(self.tracks[:1])
|
self.backend.current_playlist.load(self.tracks[:1])
|
||||||
self.assertEqual(self.playback.next_track, self.tracks[0])
|
self.assertEqual(self.playback.next_track, self.tracks[1])
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_played_track_during_random_not_played_again(self):
|
def test_played_track_during_random_not_played_again(self):
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user