Fix 'load' so one can append a playlist to the current playlist

This commit is contained in:
Stein Magnus Jodal 2010-08-14 21:24:39 +02:00
parent 465a57b3af
commit fb6b196646
6 changed files with 53 additions and 52 deletions

View File

@ -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)

View File

@ -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):
""" """

View File

@ -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):

View File

@ -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+)"$')

View File

@ -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

View File

@ -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):