merge implementation of multi-word search
This commit is contained in:
commit
be949d45df
@ -28,6 +28,26 @@ We got an updated :doc:`release roadmap <development/roadmap>`!
|
|||||||
with GMPC and ncmpc.
|
with GMPC and ncmpc.
|
||||||
- ``noidle`` command now returns ``OK`` instead of an error. Should make some
|
- ``noidle`` command now returns ``OK`` instead of an error. Should make some
|
||||||
clients work a bit better.
|
clients work a bit better.
|
||||||
|
- Having multiple identical tracks in a playlist is now working properly.
|
||||||
|
(CPID refactoring)
|
||||||
|
|
||||||
|
- Libspotify backend:
|
||||||
|
|
||||||
|
- Fix choppy playback using the Libspotify backend by using blocking ALSA
|
||||||
|
mode. (Fixes: GH-7)
|
||||||
|
|
||||||
|
- Backend API:
|
||||||
|
|
||||||
|
- :meth:`mopidy.backends.BaseCurrentPlaylistController.load()` now accepts
|
||||||
|
lists of :class:`mopidy.models.Track` instead of
|
||||||
|
:class:`mopidy.models.Playlist`, as none of the other fields on the
|
||||||
|
``Playlist`` model was in use.
|
||||||
|
- :meth:`mopidy.backends.BaseCurrentPlaylistController.remove()` now takes
|
||||||
|
criterias, just like
|
||||||
|
:meth:`mopidy.backends.BaseCurrentPlaylistController.get()`, and not the
|
||||||
|
track to remove.
|
||||||
|
- :attr:`mopidy.backends.BaseCurrentPlaylistController.tracks` is now
|
||||||
|
read-only. Use the methods to change its contents.
|
||||||
|
|
||||||
|
|
||||||
0.1.0a2 (2010-06-02)
|
0.1.0a2 (2010-06-02)
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import time
|
|||||||
|
|
||||||
from mopidy import settings
|
from mopidy import settings
|
||||||
from mopidy.models import Playlist
|
from mopidy.models import Playlist
|
||||||
|
from mopidy.mpd import serializer
|
||||||
from mopidy.utils import get_class
|
from mopidy.utils import get_class
|
||||||
|
|
||||||
logger = logging.getLogger('mopidy.backends.base')
|
logger = logging.getLogger('mopidy.backends.base')
|
||||||
@ -88,21 +89,37 @@ class BaseCurrentPlaylistController(object):
|
|||||||
|
|
||||||
def __init__(self, backend):
|
def __init__(self, backend):
|
||||||
self.backend = backend
|
self.backend = backend
|
||||||
self._playlist = Playlist()
|
self._cp_tracks = []
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
"""Cleanup after component."""
|
"""Cleanup after component."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def playlist(self):
|
def tracks(self):
|
||||||
"""The currently loaded :class:`mopidy.models.Playlist`."""
|
"""
|
||||||
return copy(self._playlist)
|
List of :class:`mopidy.model.Track` in the current playlist.
|
||||||
|
|
||||||
@playlist.setter
|
Read-only.
|
||||||
def playlist(self, new_playlist):
|
"""
|
||||||
self._playlist = new_playlist
|
return [t[1] for t in self._cp_tracks]
|
||||||
self.version += 1
|
|
||||||
|
def _get_cp_track(self, **criteria):
|
||||||
|
matches = self._cp_tracks
|
||||||
|
for (key, value) in criteria.iteritems():
|
||||||
|
if key == 'cpid':
|
||||||
|
matches = filter(lambda ct: ct[0] == value, matches)
|
||||||
|
else:
|
||||||
|
matches = filter(lambda ct: getattr(ct[1], key) == value,
|
||||||
|
matches)
|
||||||
|
if len(matches) == 1:
|
||||||
|
return matches[0]
|
||||||
|
criteria_string = ', '.join(
|
||||||
|
['%s=%s' % (k, v) for (k, v) in criteria.iteritems()])
|
||||||
|
if len(matches) == 0:
|
||||||
|
raise LookupError(u'"%s" match no tracks' % criteria_string)
|
||||||
|
else:
|
||||||
|
raise LookupError(u'"%s" match multiple tracks' % criteria_string)
|
||||||
|
|
||||||
def add(self, track, at_position=None):
|
def add(self, track, at_position=None):
|
||||||
"""
|
"""
|
||||||
@ -114,22 +131,20 @@ class BaseCurrentPlaylistController(object):
|
|||||||
:param at_position: position in current playlist to add track
|
:param at_position: position in current playlist to add track
|
||||||
:type at_position: int or :class:`None`
|
:type at_position: int or :class:`None`
|
||||||
"""
|
"""
|
||||||
tracks = self.playlist.tracks
|
assert at_position <= len(self._cp_tracks), \
|
||||||
|
u'at_position can not be greater than playlist length'
|
||||||
assert at_position <= len(tracks), 'at_position can not be greater' \
|
|
||||||
+ ' than playlist length'
|
|
||||||
|
|
||||||
if at_position is not None:
|
if at_position is not None:
|
||||||
tracks.insert(at_position, track)
|
self._cp_tracks.insert(at_position, (self.version, track))
|
||||||
else:
|
else:
|
||||||
tracks.append(track)
|
self._cp_tracks.append((self.version, track))
|
||||||
self.playlist = self.playlist.with_(tracks=tracks)
|
self.version += 1
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
"""Clear the current playlist."""
|
"""Clear the current playlist."""
|
||||||
self.backend.playback.stop()
|
self.backend.playback.stop()
|
||||||
self.backend.playback.current_track = None
|
self.backend.playback.current_track = None
|
||||||
self.playlist = Playlist()
|
self._cp_tracks = []
|
||||||
|
self.version += 1
|
||||||
|
|
||||||
def get(self, **criteria):
|
def get(self, **criteria):
|
||||||
"""
|
"""
|
||||||
@ -139,6 +154,8 @@ class BaseCurrentPlaylistController(object):
|
|||||||
|
|
||||||
Examples::
|
Examples::
|
||||||
|
|
||||||
|
get(cpid=7) # Returns track with CPID 7
|
||||||
|
# (current playlist ID)
|
||||||
get(id=1) # Returns track with ID 1
|
get(id=1) # Returns track with ID 1
|
||||||
get(uri='xyz') # Returns track with URI 'xyz'
|
get(uri='xyz') # Returns track with URI 'xyz'
|
||||||
get(id=1, uri='xyz') # Returns track with ID 1 and URI 'xyz'
|
get(id=1, uri='xyz') # Returns track with ID 1 and URI 'xyz'
|
||||||
@ -147,26 +164,19 @@ class BaseCurrentPlaylistController(object):
|
|||||||
:type criteria: dict
|
:type criteria: dict
|
||||||
:rtype: :class:`mopidy.models.Track`
|
:rtype: :class:`mopidy.models.Track`
|
||||||
"""
|
"""
|
||||||
matches = self._playlist.tracks
|
return self._get_cp_track(**criteria)[1]
|
||||||
for (key, value) in criteria.iteritems():
|
|
||||||
matches = filter(lambda t: getattr(t, key) == value, matches)
|
|
||||||
if len(matches) == 1:
|
|
||||||
return matches[0]
|
|
||||||
criteria_string = ', '.join(
|
|
||||||
['%s=%s' % (k, v) for (k, v) in criteria.iteritems()])
|
|
||||||
if len(matches) == 0:
|
|
||||||
raise LookupError(u'"%s" match no tracks' % criteria_string)
|
|
||||||
else:
|
|
||||||
raise LookupError(u'"%s" match multiple tracks' % criteria_string)
|
|
||||||
|
|
||||||
def load(self, playlist):
|
def load(self, tracks):
|
||||||
"""
|
"""
|
||||||
Replace the current playlist with the given playlist.
|
Replace the tracks in the current playlist with the given tracks.
|
||||||
|
|
||||||
:param playlist: playlist to load
|
:param tracks: tracks to load
|
||||||
:type playlist: :class:`mopidy.models.Playlist`
|
:type tracks: list of :class:`mopidy.models.Track`
|
||||||
"""
|
"""
|
||||||
self.playlist = playlist
|
self._cp_tracks = []
|
||||||
|
self.version += 1
|
||||||
|
for track in tracks:
|
||||||
|
self.add(track)
|
||||||
self.backend.playback.new_playlist_loaded_callback()
|
self.backend.playback.new_playlist_loaded_callback()
|
||||||
|
|
||||||
def move(self, start, end, to_position):
|
def move(self, start, end, to_position):
|
||||||
@ -183,35 +193,37 @@ class BaseCurrentPlaylistController(object):
|
|||||||
if start == end:
|
if start == end:
|
||||||
end += 1
|
end += 1
|
||||||
|
|
||||||
tracks = self.playlist.tracks
|
cp_tracks = self._cp_tracks
|
||||||
|
|
||||||
assert start < end, 'start must be smaller than end'
|
assert start < end, 'start must be smaller than end'
|
||||||
assert start >= 0, 'start must be at least zero'
|
assert start >= 0, 'start must be at least zero'
|
||||||
assert end <= len(tracks), 'end can not be larger than playlist length'
|
assert end <= len(cp_tracks), \
|
||||||
|
'end can not be larger than playlist length'
|
||||||
assert to_position >= 0, 'to_position must be at least zero'
|
assert to_position >= 0, 'to_position must be at least zero'
|
||||||
assert to_position <= len(tracks), 'to_position can not be larger ' + \
|
assert to_position <= len(cp_tracks), \
|
||||||
'than playlist length'
|
'to_position can not be larger than playlist length'
|
||||||
|
|
||||||
new_tracks = tracks[:start] + tracks[end:]
|
new_cp_tracks = cp_tracks[:start] + cp_tracks[end:]
|
||||||
for track in tracks[start:end]:
|
for cp_track in cp_tracks[start:end]:
|
||||||
new_tracks.insert(to_position, track)
|
new_cp_tracks.insert(to_position, cp_track)
|
||||||
to_position += 1
|
to_position += 1
|
||||||
self.playlist = self.playlist.with_(tracks=new_tracks)
|
self._cp_tracks = new_cp_tracks
|
||||||
|
self.version += 1
|
||||||
|
|
||||||
def remove(self, track):
|
def remove(self, **criteria):
|
||||||
"""
|
"""
|
||||||
Remove the track from the current playlist.
|
Remove the track from the current playlist.
|
||||||
|
|
||||||
:param track: track to remove
|
Uses :meth:`get` to lookup the track to remove.
|
||||||
|
|
||||||
|
:param criteria: on or more criteria to match by
|
||||||
|
:type criteria: dict
|
||||||
:type track: :class:`mopidy.models.Track`
|
:type track: :class:`mopidy.models.Track`
|
||||||
"""
|
"""
|
||||||
tracks = self.playlist.tracks
|
cp_track = self._get_cp_track(**criteria)
|
||||||
|
position = self._cp_tracks.index(cp_track)
|
||||||
assert track in tracks, 'track must be in playlist'
|
del self._cp_tracks[position]
|
||||||
|
self.version += 1
|
||||||
position = tracks.index(track)
|
|
||||||
del tracks[position]
|
|
||||||
self.playlist = self.playlist.with_(tracks=tracks)
|
|
||||||
|
|
||||||
def shuffle(self, start=None, end=None):
|
def shuffle(self, start=None, end=None):
|
||||||
"""
|
"""
|
||||||
@ -223,7 +235,7 @@ class BaseCurrentPlaylistController(object):
|
|||||||
:param end: position after last track to shuffle
|
:param end: position after last track to shuffle
|
||||||
:type end: int or :class:`None`
|
:type end: int or :class:`None`
|
||||||
"""
|
"""
|
||||||
tracks = self.playlist.tracks
|
cp_tracks = self._cp_tracks
|
||||||
|
|
||||||
if start is not None and end is not None:
|
if start is not None and end is not None:
|
||||||
assert start < end, 'start must be smaller than end'
|
assert start < end, 'start must be smaller than end'
|
||||||
@ -232,18 +244,20 @@ class BaseCurrentPlaylistController(object):
|
|||||||
assert start >= 0, 'start must be at least zero'
|
assert start >= 0, 'start must be at least zero'
|
||||||
|
|
||||||
if end is not None:
|
if end is not None:
|
||||||
assert end <= len(tracks), 'end can not be larger than ' + \
|
assert end <= len(cp_tracks), 'end can not be larger than ' + \
|
||||||
'playlist length'
|
'playlist length'
|
||||||
|
|
||||||
before = tracks[:start or 0]
|
before = cp_tracks[:start or 0]
|
||||||
shuffled = tracks[start:end]
|
shuffled = cp_tracks[start:end]
|
||||||
after = tracks[end or len(tracks):]
|
after = cp_tracks[end or len(cp_tracks):]
|
||||||
random.shuffle(shuffled)
|
random.shuffle(shuffled)
|
||||||
self.playlist = self.playlist.with_(tracks=before+shuffled+after)
|
self._cp_tracks = before + shuffled + after
|
||||||
|
self.version += 1
|
||||||
|
|
||||||
def destroy(self):
|
def mpd_format(self, *args, **kwargs):
|
||||||
"""Cleanup after component."""
|
"""Not a part of the generic backend API."""
|
||||||
pass
|
kwargs['cpids'] = [ct[0] for ct in self._cp_tracks]
|
||||||
|
return serializer.tracks_to_mpd_format(self.tracks, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class BaseLibraryController(object):
|
class BaseLibraryController(object):
|
||||||
@ -322,6 +336,9 @@ class BasePlaybackController(object):
|
|||||||
#: Tracks are not removed from the playlist.
|
#: Tracks are not removed from the playlist.
|
||||||
consume = False
|
consume = False
|
||||||
|
|
||||||
|
#: The CPID (current playlist ID) of :attr:`current_track`.
|
||||||
|
current_cpid = 0 # TODO Get the correct CPID
|
||||||
|
|
||||||
#: The currently playing or selected :class:`mopidy.models.Track`.
|
#: The currently playing or selected :class:`mopidy.models.Track`.
|
||||||
current_track = None
|
current_track = None
|
||||||
|
|
||||||
@ -362,7 +379,7 @@ class BasePlaybackController(object):
|
|||||||
if self.current_track is None:
|
if self.current_track is None:
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
return self.backend.current_playlist.playlist.tracks.index(
|
return self.backend.current_playlist.tracks.index(
|
||||||
self.current_track)
|
self.current_track)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return None
|
return None
|
||||||
@ -377,7 +394,7 @@ class BasePlaybackController(object):
|
|||||||
enabled this should be a random track, all tracks should be played once
|
enabled this should be a random track, all tracks should be played once
|
||||||
before the list repeats.
|
before the list repeats.
|
||||||
"""
|
"""
|
||||||
tracks = self.backend.current_playlist.playlist.tracks
|
tracks = self.backend.current_playlist.tracks
|
||||||
|
|
||||||
if not tracks:
|
if not tracks:
|
||||||
return None
|
return None
|
||||||
@ -418,7 +435,7 @@ class BasePlaybackController(object):
|
|||||||
if self.current_track is None or self.current_playlist_position == 0:
|
if self.current_track is None or self.current_playlist_position == 0:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return self.backend.current_playlist.playlist.tracks[
|
return self.backend.current_playlist.tracks[
|
||||||
self.current_playlist_position - 1]
|
self.current_playlist_position - 1]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -506,7 +523,7 @@ class BasePlaybackController(object):
|
|||||||
self._shuffled = []
|
self._shuffled = []
|
||||||
|
|
||||||
if self.state == self.PLAYING:
|
if self.state == self.PLAYING:
|
||||||
if self.backend.current_playlist.playlist.length > 0:
|
if len(self.backend.current_playlist.tracks) > 0:
|
||||||
self.play()
|
self.play()
|
||||||
else:
|
else:
|
||||||
self.stop()
|
self.stop()
|
||||||
@ -528,7 +545,7 @@ class BasePlaybackController(object):
|
|||||||
|
|
||||||
# FIXME handle in play aswell?
|
# FIXME handle in play aswell?
|
||||||
if self.consume:
|
if self.consume:
|
||||||
self.backend.current_playlist.remove(original_track)
|
self.backend.current_playlist.remove(id=original_track.id)
|
||||||
|
|
||||||
if self.random and self.current_track in self._shuffled:
|
if self.random and self.current_track in self._shuffled:
|
||||||
self._shuffled.remove(self.current_track)
|
self._shuffled.remove(self.current_track)
|
||||||
@ -553,7 +570,7 @@ class BasePlaybackController(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if track:
|
if track:
|
||||||
assert track in self.backend.current_playlist.playlist.tracks
|
assert track in self.backend.current_playlist.tracks
|
||||||
elif not self.current_track:
|
elif not self.current_track:
|
||||||
track = self.next_track
|
track = self.next_track
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
from copy import copy
|
from copy import copy
|
||||||
|
|
||||||
|
from mopidy.mpd import serializer
|
||||||
|
|
||||||
class ImmutableObject(object):
|
class ImmutableObject(object):
|
||||||
"""
|
"""
|
||||||
Superclass for immutable objects whose fields can only be modified via the
|
Superclass for immutable objects whose fields can only be modified via the
|
||||||
@ -138,43 +140,8 @@ class Track(ImmutableObject):
|
|||||||
"""List of :class:`Artist`. Read-only."""
|
"""List of :class:`Artist`. Read-only."""
|
||||||
return list(self._artists)
|
return list(self._artists)
|
||||||
|
|
||||||
def mpd_format(self, position=0, search_result=False):
|
def mpd_format(self, *args, **kwargs):
|
||||||
"""
|
return serializer.track_to_mpd_format(self, *args, **kwargs)
|
||||||
Format track for output to MPD client.
|
|
||||||
|
|
||||||
:param position: track's position in playlist
|
|
||||||
:type position: integer
|
|
||||||
:param search_result: format for output in search result
|
|
||||||
:type search_result: boolean
|
|
||||||
:rtype: list of two-tuples
|
|
||||||
"""
|
|
||||||
result = [
|
|
||||||
('file', self.uri or ''),
|
|
||||||
('Time', self.length and (self.length // 1000) or 0),
|
|
||||||
('Artist', self.mpd_format_artists()),
|
|
||||||
('Title', self.name or ''),
|
|
||||||
('Album', self.album and self.album.name or ''),
|
|
||||||
('Date', self.date or ''),
|
|
||||||
]
|
|
||||||
if self.album is not None and self.album.num_tracks != 0:
|
|
||||||
result.append(('Track', '%d/%d' % (
|
|
||||||
self.track_no, self.album.num_tracks)))
|
|
||||||
else:
|
|
||||||
result.append(('Track', self.track_no))
|
|
||||||
if not search_result:
|
|
||||||
result.append(('Pos', position))
|
|
||||||
result.append(('Id', self.id or position))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def mpd_format_artists(self):
|
|
||||||
"""
|
|
||||||
Format track artists for output to MPD client.
|
|
||||||
|
|
||||||
:rtype: string
|
|
||||||
"""
|
|
||||||
artists = list(self._artists)
|
|
||||||
artists.sort(key=lambda a: a.name)
|
|
||||||
return u', '.join([a.name for a in artists])
|
|
||||||
|
|
||||||
|
|
||||||
class Playlist(ImmutableObject):
|
class Playlist(ImmutableObject):
|
||||||
@ -214,33 +181,8 @@ class Playlist(ImmutableObject):
|
|||||||
"""The number of tracks in the playlist. Read-only."""
|
"""The number of tracks in the playlist. Read-only."""
|
||||||
return len(self._tracks)
|
return len(self._tracks)
|
||||||
|
|
||||||
def mpd_format(self, start=0, end=None, search_result=False):
|
def mpd_format(self, *args, **kwargs):
|
||||||
"""
|
return serializer.playlist_to_mpd_format(self, *args, **kwargs)
|
||||||
Format playlist for output to MPD client.
|
|
||||||
|
|
||||||
Optionally limit output to the slice ``[start:end]`` of the playlist.
|
|
||||||
|
|
||||||
:param start: position of first track to include in output
|
|
||||||
:type start: int (positive or negative)
|
|
||||||
:param end: position after last track to include in output
|
|
||||||
:type end: int (positive or negative) or :class:`None` for end of list
|
|
||||||
:rtype: list of lists of two-tuples
|
|
||||||
"""
|
|
||||||
if start < 0:
|
|
||||||
range_start = self.length + start
|
|
||||||
else:
|
|
||||||
range_start = start
|
|
||||||
if end is not None and end < 0:
|
|
||||||
range_end = self.length - end
|
|
||||||
elif end is not None and end >= 0:
|
|
||||||
range_end = end
|
|
||||||
else:
|
|
||||||
range_end = self.length
|
|
||||||
tracks = []
|
|
||||||
for track, position in zip(self.tracks[start:end],
|
|
||||||
range(range_start, range_end)):
|
|
||||||
tracks.append(track.mpd_format(position, search_result))
|
|
||||||
return tracks
|
|
||||||
|
|
||||||
def with_(self, uri=None, name=None, tracks=None, last_modified=None):
|
def with_(self, uri=None, name=None, tracks=None, last_modified=None):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -291,7 +291,7 @@ class MpdFrontend(object):
|
|||||||
track = self.backend.library.lookup(uri)
|
track = self.backend.library.lookup(uri)
|
||||||
if track is None:
|
if track is None:
|
||||||
raise MpdNoExistError(u'No such song', command=u'addid')
|
raise MpdNoExistError(u'No such song', command=u'addid')
|
||||||
if songpos and songpos > self.backend.current_playlist.playlist.length:
|
if songpos and songpos > len(self.backend.current_playlist.tracks):
|
||||||
raise MpdArgError(u'Bad song index', command=u'addid')
|
raise MpdArgError(u'Bad song index', command=u'addid')
|
||||||
self.backend.current_playlist.add(track, at_position=songpos)
|
self.backend.current_playlist.add(track, at_position=songpos)
|
||||||
return ('Id', track.id)
|
return ('Id', track.id)
|
||||||
@ -309,25 +309,25 @@ class MpdFrontend(object):
|
|||||||
if end is not None:
|
if end is not None:
|
||||||
end = int(end)
|
end = int(end)
|
||||||
else:
|
else:
|
||||||
end = self.backend.current_playlist.playlist.length
|
end = len(self.backend.current_playlist.tracks)
|
||||||
tracks = self.backend.current_playlist.playlist.tracks[start:end]
|
tracks = self.backend.current_playlist.tracks[start:end]
|
||||||
if not tracks:
|
if not tracks:
|
||||||
raise MpdArgError(u'Bad song index', command=u'delete')
|
raise MpdArgError(u'Bad song index', command=u'delete')
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
self.backend.current_playlist.remove(track)
|
self.backend.current_playlist.remove(id=track.id)
|
||||||
|
|
||||||
@handle_pattern(r'^delete "(?P<songpos>\d+)"$')
|
@handle_pattern(r'^delete "(?P<songpos>\d+)"$')
|
||||||
def _current_playlist_delete_songpos(self, songpos):
|
def _current_playlist_delete_songpos(self, songpos):
|
||||||
"""See :meth:`_current_playlist_delete_range`"""
|
"""See :meth:`_current_playlist_delete_range`"""
|
||||||
try:
|
try:
|
||||||
songpos = int(songpos)
|
songpos = int(songpos)
|
||||||
track = self.backend.current_playlist.playlist.tracks[songpos]
|
track = self.backend.current_playlist.tracks[songpos]
|
||||||
self.backend.current_playlist.remove(track)
|
self.backend.current_playlist.remove(id=track.id)
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise MpdArgError(u'Bad song index', command=u'delete')
|
raise MpdArgError(u'Bad song index', command=u'delete')
|
||||||
|
|
||||||
@handle_pattern(r'^deleteid "(?P<songid>\d+)"$')
|
@handle_pattern(r'^deleteid "(?P<cpid>\d+)"$')
|
||||||
def _current_playlist_deleteid(self, songid):
|
def _current_playlist_deleteid(self, cpid):
|
||||||
"""
|
"""
|
||||||
*musicpd.org, current playlist section:*
|
*musicpd.org, current playlist section:*
|
||||||
|
|
||||||
@ -335,10 +335,9 @@ class MpdFrontend(object):
|
|||||||
|
|
||||||
Deletes the song ``SONGID`` from the playlist
|
Deletes the song ``SONGID`` from the playlist
|
||||||
"""
|
"""
|
||||||
songid = int(songid)
|
|
||||||
try:
|
try:
|
||||||
track = self.backend.current_playlist.get(id=songid)
|
cpid = int(cpid)
|
||||||
return self.backend.current_playlist.remove(track)
|
return self.backend.current_playlist.remove(cpid=cpid)
|
||||||
except LookupError:
|
except LookupError:
|
||||||
raise MpdNoExistError(u'No such song', command=u'deleteid')
|
raise MpdNoExistError(u'No such song', command=u'deleteid')
|
||||||
|
|
||||||
@ -364,7 +363,7 @@ class MpdFrontend(object):
|
|||||||
``TO`` in the playlist.
|
``TO`` in the playlist.
|
||||||
"""
|
"""
|
||||||
if end is None:
|
if end is None:
|
||||||
end = self.backend.current_playlist.playlist.length
|
end = len(self.backend.current_playlist.tracks)
|
||||||
start = int(start)
|
start = int(start)
|
||||||
end = int(end)
|
end = int(end)
|
||||||
to = int(to)
|
to = int(to)
|
||||||
@ -377,8 +376,8 @@ class MpdFrontend(object):
|
|||||||
to = int(to)
|
to = int(to)
|
||||||
self.backend.current_playlist.move(songpos, songpos + 1, to)
|
self.backend.current_playlist.move(songpos, songpos + 1, to)
|
||||||
|
|
||||||
@handle_pattern(r'^moveid "(?P<songid>\d+)" "(?P<to>\d+)"$')
|
@handle_pattern(r'^moveid "(?P<cpid>\d+)" "(?P<to>\d+)"$')
|
||||||
def _current_playlist_moveid(self, songid, to):
|
def _current_playlist_moveid(self, cpid, to):
|
||||||
"""
|
"""
|
||||||
*musicpd.org, current playlist section:*
|
*musicpd.org, current playlist section:*
|
||||||
|
|
||||||
@ -388,10 +387,10 @@ class MpdFrontend(object):
|
|||||||
the playlist. If ``TO`` is negative, it is relative to the current
|
the playlist. If ``TO`` is negative, it is relative to the current
|
||||||
song in the playlist (if there is one).
|
song in the playlist (if there is one).
|
||||||
"""
|
"""
|
||||||
songid = int(songid)
|
cpid = int(cpid)
|
||||||
to = int(to)
|
to = int(to)
|
||||||
track = self.backend.current_playlist.get(id=songid)
|
track = self.backend.current_playlist.get(cpid=cpid)
|
||||||
position = self.backend.current_playlist.playlist.tracks.index(track)
|
position = self.backend.current_playlist.tracks.index(track)
|
||||||
self.backend.current_playlist.move(position, position + 1, to)
|
self.backend.current_playlist.move(position, position + 1, to)
|
||||||
|
|
||||||
@handle_pattern(r'^playlist$')
|
@handle_pattern(r'^playlist$')
|
||||||
@ -431,8 +430,8 @@ class MpdFrontend(object):
|
|||||||
return None
|
return None
|
||||||
raise MpdNotImplemented # TODO
|
raise MpdNotImplemented # TODO
|
||||||
|
|
||||||
@handle_pattern(r'^playlistid( "(?P<songid>\d+)")*$')
|
@handle_pattern(r'^playlistid( "(?P<cpid>\d+)")*$')
|
||||||
def _current_playlist_playlistid(self, songid=None):
|
def _current_playlist_playlistid(self, cpid=None):
|
||||||
"""
|
"""
|
||||||
*musicpd.org, current playlist section:*
|
*musicpd.org, current playlist section:*
|
||||||
|
|
||||||
@ -441,15 +440,16 @@ class MpdFrontend(object):
|
|||||||
Displays a list of songs in the playlist. ``SONGID`` is optional
|
Displays a list of songs in the playlist. ``SONGID`` is optional
|
||||||
and specifies a single song to display info for.
|
and specifies a single song to display info for.
|
||||||
"""
|
"""
|
||||||
if songid is not None:
|
if cpid is not None:
|
||||||
try:
|
try:
|
||||||
songid = int(songid)
|
cpid = int(cpid)
|
||||||
track = self.backend.current_playlist.get(id=songid)
|
track = self.backend.current_playlist.get(cpid=cpid)
|
||||||
return track.mpd_format()
|
position = self.backend.current_playlist.tracks.index(track)
|
||||||
|
return track.mpd_format(position=position, cpid=cpid)
|
||||||
except LookupError:
|
except LookupError:
|
||||||
raise MpdNoExistError(u'No such song', command=u'playlistid')
|
raise MpdNoExistError(u'No such song', command=u'playlistid')
|
||||||
else:
|
else:
|
||||||
return self.backend.current_playlist.playlist.mpd_format()
|
return self.backend.current_playlist.mpd_format()
|
||||||
|
|
||||||
@handle_pattern(r'^playlistinfo$')
|
@handle_pattern(r'^playlistinfo$')
|
||||||
@handle_pattern(r'^playlistinfo "(?P<songpos>-?\d+)"$')
|
@handle_pattern(r'^playlistinfo "(?P<songpos>-?\d+)"$')
|
||||||
@ -479,15 +479,18 @@ class MpdFrontend(object):
|
|||||||
end = songpos + 1
|
end = songpos + 1
|
||||||
if start == -1:
|
if start == -1:
|
||||||
end = None
|
end = None
|
||||||
return self.backend.current_playlist.playlist.mpd_format(
|
return self.backend.current_playlist.mpd_format(start, end)
|
||||||
start, end)
|
|
||||||
else:
|
else:
|
||||||
if start is None:
|
if start is None:
|
||||||
start = 0
|
start = 0
|
||||||
start = int(start)
|
start = int(start)
|
||||||
|
if not (0 <= start <= len(self.backend.current_playlist.tracks)):
|
||||||
|
raise MpdArgError(u'Bad song index', command=u'playlistinfo')
|
||||||
if end is not None:
|
if end is not None:
|
||||||
end = int(end)
|
end = int(end)
|
||||||
return self.backend.current_playlist.playlist.mpd_format(start, end)
|
if end > len(self.backend.current_playlist.tracks):
|
||||||
|
end = None
|
||||||
|
return self.backend.current_playlist.mpd_format(start, end)
|
||||||
|
|
||||||
@handle_pattern(r'^playlistsearch "(?P<tag>[^"]+)" "(?P<needle>[^"]+)"$')
|
@handle_pattern(r'^playlistsearch "(?P<tag>[^"]+)" "(?P<needle>[^"]+)"$')
|
||||||
def _current_playlist_playlistsearch(self, tag, needle):
|
def _current_playlist_playlistsearch(self, tag, needle):
|
||||||
@ -515,7 +518,7 @@ class MpdFrontend(object):
|
|||||||
"""
|
"""
|
||||||
# XXX Naive implementation that returns all tracks as changed
|
# XXX Naive implementation that returns all tracks as changed
|
||||||
if int(version) < self.backend.current_playlist.version:
|
if int(version) < self.backend.current_playlist.version:
|
||||||
return self.backend.current_playlist.playlist.mpd_format()
|
return self.backend.current_playlist.mpd_format()
|
||||||
|
|
||||||
@handle_pattern(r'^plchangesposid "(?P<version>\d+)"$')
|
@handle_pattern(r'^plchangesposid "(?P<version>\d+)"$')
|
||||||
def _current_playlist_plchangesposid(self, version):
|
def _current_playlist_plchangesposid(self, version):
|
||||||
@ -535,7 +538,7 @@ class MpdFrontend(object):
|
|||||||
if int(version) != self.backend.current_playlist.version:
|
if int(version) != self.backend.current_playlist.version:
|
||||||
result = []
|
result = []
|
||||||
for position, track in enumerate(
|
for position, track in enumerate(
|
||||||
self.backend.current_playlist.playlist.tracks):
|
self.backend.current_playlist.tracks):
|
||||||
result.append((u'cpos', position))
|
result.append((u'cpos', position))
|
||||||
result.append((u'Id', track.id))
|
result.append((u'Id', track.id))
|
||||||
return result
|
return result
|
||||||
@ -568,18 +571,17 @@ class MpdFrontend(object):
|
|||||||
"""
|
"""
|
||||||
songpos1 = int(songpos1)
|
songpos1 = int(songpos1)
|
||||||
songpos2 = int(songpos2)
|
songpos2 = int(songpos2)
|
||||||
playlist = self.backend.current_playlist.playlist
|
tracks = self.backend.current_playlist.tracks
|
||||||
tracks = playlist.tracks
|
|
||||||
song1 = tracks[songpos1]
|
song1 = tracks[songpos1]
|
||||||
song2 = tracks[songpos2]
|
song2 = tracks[songpos2]
|
||||||
del tracks[songpos1]
|
del tracks[songpos1]
|
||||||
tracks.insert(songpos1, song2)
|
tracks.insert(songpos1, song2)
|
||||||
del tracks[songpos2]
|
del tracks[songpos2]
|
||||||
tracks.insert(songpos2, song1)
|
tracks.insert(songpos2, song1)
|
||||||
self.backend.current_playlist.load(playlist.with_(tracks=tracks))
|
self.backend.current_playlist.load(tracks)
|
||||||
|
|
||||||
@handle_pattern(r'^swapid "(?P<songid1>\d+)" "(?P<songid2>\d+)"$')
|
@handle_pattern(r'^swapid "(?P<cpid1>\d+)" "(?P<cpid2>\d+)"$')
|
||||||
def _current_playlist_swapid(self, songid1, songid2):
|
def _current_playlist_swapid(self, cpid1, cpid2):
|
||||||
"""
|
"""
|
||||||
*musicpd.org, current playlist section:*
|
*musicpd.org, current playlist section:*
|
||||||
|
|
||||||
@ -587,13 +589,13 @@ class MpdFrontend(object):
|
|||||||
|
|
||||||
Swaps the positions of ``SONG1`` and ``SONG2`` (both song ids).
|
Swaps the positions of ``SONG1`` and ``SONG2`` (both song ids).
|
||||||
"""
|
"""
|
||||||
songid1 = int(songid1)
|
cpid1 = int(cpid1)
|
||||||
songid2 = int(songid2)
|
cpid2 = int(cpid2)
|
||||||
song1 = self.backend.current_playlist.get(id=songid1)
|
track1 = self.backend.current_playlist.get(cpid=cpid1)
|
||||||
song2 = self.backend.current_playlist.get(id=songid2)
|
track2 = self.backend.current_playlist.get(cpid=cpid2)
|
||||||
songpos1 = self.backend.current_playlist.playlist.tracks.index(song1)
|
position1 = self.backend.current_playlist.tracks.index(track1)
|
||||||
songpos2 = self.backend.current_playlist.playlist.tracks.index(song2)
|
position2 = self.backend.current_playlist.tracks.index(track2)
|
||||||
self._current_playlist_swap(songpos1, songpos2)
|
self._current_playlist_swap(position1, position2)
|
||||||
|
|
||||||
@handle_pattern(r'^$')
|
@handle_pattern(r'^$')
|
||||||
def _empty(self):
|
def _empty(self):
|
||||||
@ -635,8 +637,7 @@ class MpdFrontend(object):
|
|||||||
- capitalizes the type argument.
|
- capitalizes the type argument.
|
||||||
"""
|
"""
|
||||||
query = self._build_query(mpd_query)
|
query = self._build_query(mpd_query)
|
||||||
return self.backend.library.find_exact(query).mpd_format(
|
return self.backend.library.find_exact(query).mpd_format()
|
||||||
search_result=True)
|
|
||||||
|
|
||||||
@handle_pattern(r'^findadd '
|
@handle_pattern(r'^findadd '
|
||||||
r'(?P<query>("?([Aa]lbum|[Aa]rtist|[Ff]ilename|[Tt]itle|[Aa]ny)"? "[^"]+"\s?)+)$')
|
r'(?P<query>("?([Aa]lbum|[Aa]rtist|[Ff]ilename|[Tt]itle|[Aa]ny)"? "[^"]+"\s?)+)$')
|
||||||
@ -799,8 +800,7 @@ class MpdFrontend(object):
|
|||||||
- capitalizes the field argument.
|
- capitalizes the field argument.
|
||||||
"""
|
"""
|
||||||
query = self._build_query(mpd_query)
|
query = self._build_query(mpd_query)
|
||||||
return self.backend.library.search(query).mpd_format(
|
return self.backend.library.search(query).mpd_format()
|
||||||
search_result=True)
|
|
||||||
|
|
||||||
@handle_pattern(r'^update( "(?P<uri>[^"]+)")*$')
|
@handle_pattern(r'^update( "(?P<uri>[^"]+)")*$')
|
||||||
def _music_db_update(self, uri=None, rescan_unmodified_files=False):
|
def _music_db_update(self, uri=None, rescan_unmodified_files=False):
|
||||||
@ -928,9 +928,9 @@ class MpdFrontend(object):
|
|||||||
"""
|
"""
|
||||||
return self.backend.playback.play()
|
return self.backend.playback.play()
|
||||||
|
|
||||||
@handle_pattern(r'^playid "(?P<songid>\d+)"$')
|
@handle_pattern(r'^playid "(?P<cpid>\d+)"$')
|
||||||
@handle_pattern(r'^playid "(?P<songid>-1)"$')
|
@handle_pattern(r'^playid "(?P<cpid>-1)"$')
|
||||||
def _playback_playid(self, songid):
|
def _playback_playid(self, cpid):
|
||||||
"""
|
"""
|
||||||
*musicpd.org, playback section:*
|
*musicpd.org, playback section:*
|
||||||
|
|
||||||
@ -943,12 +943,12 @@ class MpdFrontend(object):
|
|||||||
- issues ``playid "-1"`` after playlist replacement to start playback
|
- issues ``playid "-1"`` after playlist replacement to start playback
|
||||||
at the first track.
|
at the first track.
|
||||||
"""
|
"""
|
||||||
songid = int(songid)
|
cpid = int(cpid)
|
||||||
try:
|
try:
|
||||||
if songid == -1:
|
if cpid == -1:
|
||||||
track = self.backend.current_playlist.playlist.tracks[0]
|
track = self.backend.current_playlist.tracks[0]
|
||||||
else:
|
else:
|
||||||
track = self.backend.current_playlist.get(id=songid)
|
track = self.backend.current_playlist.get(cpid=cpid)
|
||||||
return self.backend.playback.play(track)
|
return self.backend.playback.play(track)
|
||||||
except LookupError:
|
except LookupError:
|
||||||
raise MpdNoExistError(u'No such song', command=u'playid')
|
raise MpdNoExistError(u'No such song', command=u'playid')
|
||||||
@ -970,9 +970,9 @@ class MpdFrontend(object):
|
|||||||
songpos = int(songpos)
|
songpos = int(songpos)
|
||||||
try:
|
try:
|
||||||
if songpos == -1:
|
if songpos == -1:
|
||||||
track = self.backend.current_playlist.playlist.tracks[0]
|
track = self.backend.current_playlist.tracks[0]
|
||||||
else:
|
else:
|
||||||
track = self.backend.current_playlist.playlist.tracks[songpos]
|
track = self.backend.current_playlist.tracks[songpos]
|
||||||
return self.backend.playback.play(track)
|
return self.backend.playback.play(track)
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise MpdArgError(u'Bad song index', command=u'play')
|
raise MpdArgError(u'Bad song index', command=u'play')
|
||||||
@ -1091,8 +1091,8 @@ class MpdFrontend(object):
|
|||||||
"""
|
"""
|
||||||
raise MpdNotImplemented # TODO
|
raise MpdNotImplemented # TODO
|
||||||
|
|
||||||
@handle_pattern(r'^seekid "(?P<songid>\d+)" "(?P<seconds>\d+)"$')
|
@handle_pattern(r'^seekid "(?P<cpid>\d+)" "(?P<seconds>\d+)"$')
|
||||||
def _playback_seekid(self, songid, seconds):
|
def _playback_seekid(self, cpid, seconds):
|
||||||
"""
|
"""
|
||||||
*musicpd.org, playback section:*
|
*musicpd.org, playback section:*
|
||||||
|
|
||||||
@ -1246,7 +1246,8 @@ class MpdFrontend(object):
|
|||||||
"""
|
"""
|
||||||
if self.backend.playback.current_track is not None:
|
if self.backend.playback.current_track is not None:
|
||||||
return self.backend.playback.current_track.mpd_format(
|
return self.backend.playback.current_track.mpd_format(
|
||||||
position=self.backend.playback.current_playlist_position)
|
position=self.backend.playback.current_playlist_position,
|
||||||
|
cpid=self.backend.playback.current_cpid)
|
||||||
|
|
||||||
@handle_pattern(r'^idle$')
|
@handle_pattern(r'^idle$')
|
||||||
@handle_pattern(r'^idle (?P<subsystems>.+)$')
|
@handle_pattern(r'^idle (?P<subsystems>.+)$')
|
||||||
@ -1381,7 +1382,7 @@ class MpdFrontend(object):
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
def __status_status_playlist_length(self):
|
def __status_status_playlist_length(self):
|
||||||
return self.backend.current_playlist.playlist.length
|
return len(self.backend.current_playlist.tracks)
|
||||||
|
|
||||||
def __status_status_playlist_version(self):
|
def __status_status_playlist_version(self):
|
||||||
return self.backend.current_playlist.version
|
return self.backend.current_playlist.version
|
||||||
@ -1396,6 +1397,7 @@ class MpdFrontend(object):
|
|||||||
return int(self.backend.playback.single)
|
return int(self.backend.playback.single)
|
||||||
|
|
||||||
def __status_status_songid(self):
|
def __status_status_songid(self):
|
||||||
|
# TODO Replace track.id with CPID
|
||||||
if self.backend.playback.current_track.id is not None:
|
if self.backend.playback.current_track.id is not None:
|
||||||
return self.backend.playback.current_track.id
|
return self.backend.playback.current_track.id
|
||||||
else:
|
else:
|
||||||
@ -1535,8 +1537,7 @@ class MpdFrontend(object):
|
|||||||
Album, Artist, Track
|
Album, Artist, Track
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return self.backend.stored_playlists.get(name=name).mpd_format(
|
return self.backend.stored_playlists.get(name=name).mpd_format()
|
||||||
search_result=True)
|
|
||||||
except LookupError:
|
except LookupError:
|
||||||
raise MpdNoExistError(
|
raise MpdNoExistError(
|
||||||
u'No such playlist', command=u'listplaylistinfo')
|
u'No such playlist', command=u'listplaylistinfo')
|
||||||
@ -1586,8 +1587,7 @@ class MpdFrontend(object):
|
|||||||
"""
|
"""
|
||||||
matches = self.backend.stored_playlists.search(name)
|
matches = self.backend.stored_playlists.search(name)
|
||||||
if matches:
|
if matches:
|
||||||
self.backend.current_playlist.load(matches[0])
|
self.backend.current_playlist.load(matches[0].tracks)
|
||||||
self.backend.playback.new_playlist_loaded_callback() # FIXME not needed?
|
|
||||||
|
|
||||||
@handle_pattern(r'^playlistadd "(?P<name>[^"]+)" "(?P<uri>[^"]+)"$')
|
@handle_pattern(r'^playlistadd "(?P<name>[^"]+)" "(?P<uri>[^"]+)"$')
|
||||||
def _stored_playlist_playlistadd(self, name, uri):
|
def _stored_playlist_playlistadd(self, name, uri):
|
||||||
|
|||||||
74
mopidy/mpd/serializer.py
Normal file
74
mopidy/mpd/serializer.py
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
def track_to_mpd_format(track, position=None, cpid=None):
|
||||||
|
"""
|
||||||
|
Format track for output to MPD client.
|
||||||
|
|
||||||
|
:param track: the track
|
||||||
|
:type track: :class:`mopidy.models.Track`
|
||||||
|
:param position: track's position in playlist
|
||||||
|
:type position: integer
|
||||||
|
:param cpid: track's CPID (current playlist ID)
|
||||||
|
:type cpid: integer
|
||||||
|
:rtype: list of two-tuples
|
||||||
|
"""
|
||||||
|
result = [
|
||||||
|
('file', track.uri or ''),
|
||||||
|
('Time', track.length and (track.length // 1000) or 0),
|
||||||
|
('Artist', track_artists_to_mpd_format(track)),
|
||||||
|
('Title', track.name or ''),
|
||||||
|
('Album', track.album and track.album.name or ''),
|
||||||
|
('Date', track.date or ''),
|
||||||
|
]
|
||||||
|
if track.album is not None and track.album.num_tracks != 0:
|
||||||
|
result.append(('Track', '%d/%d' % (
|
||||||
|
track.track_no, track.album.num_tracks)))
|
||||||
|
else:
|
||||||
|
result.append(('Track', track.track_no))
|
||||||
|
if position is not None and cpid is not None:
|
||||||
|
result.append(('Pos', position))
|
||||||
|
result.append(('Id', cpid))
|
||||||
|
return result
|
||||||
|
|
||||||
|
def track_artists_to_mpd_format(track):
|
||||||
|
"""
|
||||||
|
Format track artists for output to MPD client.
|
||||||
|
|
||||||
|
:param track: the track
|
||||||
|
:type track: :class:`mopidy.models.Track`
|
||||||
|
:rtype: string
|
||||||
|
"""
|
||||||
|
artists = track.artists
|
||||||
|
artists.sort(key=lambda a: a.name)
|
||||||
|
return u', '.join([a.name for a in artists])
|
||||||
|
|
||||||
|
def tracks_to_mpd_format(tracks, start=0, end=None, cpids=None):
|
||||||
|
"""
|
||||||
|
Format list of tracks for output to MPD client.
|
||||||
|
|
||||||
|
Optionally limit output to the slice ``[start:end]`` of the list.
|
||||||
|
|
||||||
|
:param tracks: the tracks
|
||||||
|
:type tracks: list of :class:`mopidy.models.Track`
|
||||||
|
:param start: position of first track to include in output
|
||||||
|
:type start: int (positive or negative)
|
||||||
|
:param end: position after last track to include in output
|
||||||
|
:type end: int (positive or negative) or :class:`None` for end of list
|
||||||
|
:rtype: list of lists of two-tuples
|
||||||
|
"""
|
||||||
|
if end is None:
|
||||||
|
end = len(tracks)
|
||||||
|
tracks = tracks[start:end]
|
||||||
|
positions = range(start, end)
|
||||||
|
cpids = cpids and cpids[start:end] or [None for t in tracks]
|
||||||
|
assert len(tracks) == len(positions) == len(cpids)
|
||||||
|
result = []
|
||||||
|
for track, position, cpid in zip(tracks, positions, cpids):
|
||||||
|
result.append(track_to_mpd_format(track, position, cpid))
|
||||||
|
return result
|
||||||
|
|
||||||
|
def playlist_to_mpd_format(playlist, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Format playlist for output to MPD client.
|
||||||
|
|
||||||
|
Arguments as for :func:`tracks_to_mpd_format`, except the first one.
|
||||||
|
"""
|
||||||
|
return tracks_to_mpd_format(playlist.tracks, *args, **kwargs)
|
||||||
@ -44,12 +44,12 @@ class BaseCurrentPlaylistControllerTest(object):
|
|||||||
def test_add(self):
|
def test_add(self):
|
||||||
for track in self.tracks:
|
for track in self.tracks:
|
||||||
self.controller.add(track)
|
self.controller.add(track)
|
||||||
self.assertEqual(track, self.controller.playlist.tracks[-1])
|
self.assertEqual(track, self.controller.tracks[-1])
|
||||||
|
|
||||||
def test_add_at_position(self):
|
def test_add_at_position(self):
|
||||||
for track in self.tracks[:-1]:
|
for track in self.tracks[:-1]:
|
||||||
self.controller.add(track, 0)
|
self.controller.add(track, 0)
|
||||||
self.assertEqual(track, self.controller.playlist.tracks[0])
|
self.assertEqual(track, self.controller.tracks[0])
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_add_at_position_outside_of_playlist(self):
|
def test_add_at_position_outside_of_playlist(self):
|
||||||
@ -58,12 +58,18 @@ class BaseCurrentPlaylistControllerTest(object):
|
|||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_add_sets_id_property(self):
|
def test_add_sets_id_property(self):
|
||||||
for track in self.controller.playlist.tracks:
|
for track in self.controller.tracks:
|
||||||
self.assertNotEqual(None, track.id)
|
self.assertNotEqual(None, track.id)
|
||||||
|
|
||||||
|
@populate_playlist
|
||||||
|
def test_get_by_cpid(self):
|
||||||
|
track = self.controller.tracks[1]
|
||||||
|
cpid = self.controller._cp_tracks[1][0] # XXX Messing in internals
|
||||||
|
self.assertEqual(track, self.controller.get(cpid=cpid))
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_get_by_id(self):
|
def test_get_by_id(self):
|
||||||
track = self.controller.playlist.tracks[1]
|
track = self.controller.tracks[1]
|
||||||
self.assertEqual(track, self.controller.get(id=track.id))
|
self.assertEqual(track, self.controller.get(id=track.id))
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
@ -72,7 +78,7 @@ class BaseCurrentPlaylistControllerTest(object):
|
|||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_get_by_uri(self):
|
def test_get_by_uri(self):
|
||||||
track = self.controller.playlist.tracks[1]
|
track = self.controller.tracks[1]
|
||||||
self.assertEqual(track, self.controller.get(uri=track.uri))
|
self.assertEqual(track, self.controller.get(uri=track.uri))
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
@ -83,11 +89,11 @@ class BaseCurrentPlaylistControllerTest(object):
|
|||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_clear(self):
|
def test_clear(self):
|
||||||
self.controller.clear()
|
self.controller.clear()
|
||||||
self.assertEqual(len(self.controller.playlist.tracks), 0)
|
self.assertEqual(len(self.controller.tracks), 0)
|
||||||
|
|
||||||
def test_clear_empty_playlist(self):
|
def test_clear_empty_playlist(self):
|
||||||
self.controller.clear()
|
self.controller.clear()
|
||||||
self.assertEqual(len(self.controller.playlist.tracks), 0)
|
self.assertEqual(len(self.controller.tracks), 0)
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_clear_when_playing(self):
|
def test_clear_when_playing(self):
|
||||||
@ -97,21 +103,19 @@ class BaseCurrentPlaylistControllerTest(object):
|
|||||||
self.assertEqual(self.playback.state, self.playback.STOPPED)
|
self.assertEqual(self.playback.state, self.playback.STOPPED)
|
||||||
|
|
||||||
def test_load(self):
|
def test_load(self):
|
||||||
new_playlist = Playlist()
|
tracks = []
|
||||||
self.assertNotEqual(id(new_playlist), id(self.controller.playlist))
|
self.assertNotEqual(id(tracks), id(self.controller.tracks))
|
||||||
self.controller.load(new_playlist)
|
self.controller.load(tracks)
|
||||||
# FIXME how do we test this without going into internals?
|
self.assertEqual(tracks, self.controller.tracks)
|
||||||
self.assertEqual(new_playlist, self.controller._playlist)
|
|
||||||
|
|
||||||
def test_get_by_id_returns_unique_match(self):
|
def test_get_by_id_returns_unique_match(self):
|
||||||
track = Track(id=1)
|
track = Track(id=1)
|
||||||
self.controller.playlist = Playlist(
|
self.controller.load([Track(id=13), track, Track(id=17)])
|
||||||
tracks=[Track(id=13), track, Track(id=17)])
|
|
||||||
self.assertEqual(track, self.controller.get(id=1))
|
self.assertEqual(track, self.controller.get(id=1))
|
||||||
|
|
||||||
def test_get_by_id_raises_error_if_multiple_matches(self):
|
def test_get_by_id_raises_error_if_multiple_matches(self):
|
||||||
track = Track(id=1)
|
track = Track(id=1)
|
||||||
self.controller.playlist = Playlist(tracks=[Track(id=13), track, track])
|
self.controller.load([Track(id=13), track, track])
|
||||||
try:
|
try:
|
||||||
self.controller.get(id=1)
|
self.controller.get(id=1)
|
||||||
self.fail(u'Should raise LookupError if multiple matches')
|
self.fail(u'Should raise LookupError if multiple matches')
|
||||||
@ -128,14 +132,12 @@ class BaseCurrentPlaylistControllerTest(object):
|
|||||||
|
|
||||||
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.playlist = Playlist(
|
self.controller.load([Track(uri='z'), track, Track(uri='y')])
|
||||||
tracks=[Track(uri='z'), track, Track(uri='y')])
|
|
||||||
self.assertEqual(track, self.controller.get(uri='a'))
|
self.assertEqual(track, self.controller.get(uri='a'))
|
||||||
|
|
||||||
def test_get_by_uri_raises_error_if_multiple_matches(self):
|
def test_get_by_uri_raises_error_if_multiple_matches(self):
|
||||||
track = Track(uri='a')
|
track = Track(uri='a')
|
||||||
self.controller.playlist = Playlist(
|
self.controller.load([Track(uri='z'), track, track])
|
||||||
tracks=[Track(uri='z'), track, track])
|
|
||||||
try:
|
try:
|
||||||
self.controller.get(uri='a')
|
self.controller.get(uri='a')
|
||||||
self.fail(u'Should raise LookupError if multiple matches')
|
self.fail(u'Should raise LookupError if multiple matches')
|
||||||
@ -155,7 +157,7 @@ class BaseCurrentPlaylistControllerTest(object):
|
|||||||
track1 = Track(id=1, uri='a')
|
track1 = Track(id=1, uri='a')
|
||||||
track2 = Track(id=1, uri='b')
|
track2 = Track(id=1, uri='b')
|
||||||
track3 = Track(id=2, uri='b')
|
track3 = Track(id=2, uri='b')
|
||||||
self.controller.playlist = Playlist(tracks=[track1, track2, track3])
|
self.controller.load([track1, track2, track3])
|
||||||
self.assertEqual(track1, self.controller.get(id=1, uri='a'))
|
self.assertEqual(track1, self.controller.get(id=1, uri='a'))
|
||||||
self.assertEqual(track2, self.controller.get(id=1, uri='b'))
|
self.assertEqual(track2, self.controller.get(id=1, uri='b'))
|
||||||
self.assertEqual(track3, self.controller.get(id=2, uri='b'))
|
self.assertEqual(track3, self.controller.get(id=2, uri='b'))
|
||||||
@ -164,37 +166,35 @@ class BaseCurrentPlaylistControllerTest(object):
|
|||||||
track1 = Track(id=1)
|
track1 = Track(id=1)
|
||||||
track2 = Track(uri='b')
|
track2 = Track(uri='b')
|
||||||
track3 = Track(id=2)
|
track3 = Track(id=2)
|
||||||
self.controller.playlist = Playlist(tracks=[track1, track2, track3])
|
self.controller.load([track1, track2, track3])
|
||||||
self.assertEqual(track1, self.controller.get(id=1))
|
self.assertEqual(track1, self.controller.get(id=1))
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_load_replaces_playlist(self):
|
def test_load_replaces_playlist(self):
|
||||||
self.backend.current_playlist.load(Playlist())
|
self.backend.current_playlist.load([])
|
||||||
tracks = self.backend.current_playlist.playlist.tracks
|
self.assertEqual(len(self.backend.current_playlist.tracks), 0)
|
||||||
self.assertEqual(len(tracks), 0)
|
|
||||||
|
|
||||||
def test_load_does_not_reset_version(self):
|
def test_load_does_not_reset_version(self):
|
||||||
version = self.controller.version
|
version = self.controller.version
|
||||||
|
self.controller.load([])
|
||||||
self.controller.load(Playlist())
|
self.assertEqual(self.controller.version, version + 1)
|
||||||
self.assertEqual(self.controller.version, version+1)
|
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_load_preserves_playing_state(self):
|
def test_load_preserves_playing_state(self):
|
||||||
tracks = self.controller.playlist.tracks
|
tracks = self.controller.tracks
|
||||||
playback = self.playback
|
playback = self.playback
|
||||||
|
|
||||||
self.playback.play()
|
self.playback.play()
|
||||||
self.controller.load(Playlist(tracks=[tracks[1]]))
|
self.controller.load([tracks[1]])
|
||||||
self.assertEqual(playback.state, playback.PLAYING)
|
self.assertEqual(playback.state, playback.PLAYING)
|
||||||
self.assertEqual(tracks[1], self.playback.current_track)
|
self.assertEqual(tracks[1], self.playback.current_track)
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_load_preserves_stopped_state(self):
|
def test_load_preserves_stopped_state(self):
|
||||||
tracks = self.controller.playlist.tracks
|
tracks = self.controller.tracks
|
||||||
playback = self.playback
|
playback = self.playback
|
||||||
|
|
||||||
self.controller.load(Playlist(tracks=[tracks[2]]))
|
self.controller.load([tracks[2]])
|
||||||
self.assertEqual(playback.state, playback.STOPPED)
|
self.assertEqual(playback.state, playback.STOPPED)
|
||||||
self.assertEqual(None, self.playback.current_track)
|
self.assertEqual(None, self.playback.current_track)
|
||||||
|
|
||||||
@ -202,32 +202,32 @@ class BaseCurrentPlaylistControllerTest(object):
|
|||||||
def test_move_single(self):
|
def test_move_single(self):
|
||||||
self.controller.move(0, 0, 2)
|
self.controller.move(0, 0, 2)
|
||||||
|
|
||||||
tracks = self.controller.playlist.tracks
|
tracks = self.controller.tracks
|
||||||
self.assertEqual(tracks[2], self.tracks[0])
|
self.assertEqual(tracks[2], self.tracks[0])
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_move_group(self):
|
def test_move_group(self):
|
||||||
self.controller.move(0, 2, 1)
|
self.controller.move(0, 2, 1)
|
||||||
|
|
||||||
tracks = self.controller.playlist.tracks
|
tracks = self.controller.tracks
|
||||||
self.assertEqual(tracks[1], self.tracks[0])
|
self.assertEqual(tracks[1], self.tracks[0])
|
||||||
self.assertEqual(tracks[2], self.tracks[1])
|
self.assertEqual(tracks[2], self.tracks[1])
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_moving_track_outside_of_playlist(self):
|
def test_moving_track_outside_of_playlist(self):
|
||||||
tracks = len(self.controller.playlist.tracks)
|
tracks = len(self.controller.tracks)
|
||||||
test = lambda: self.controller.move(0, 0, tracks+5)
|
test = lambda: self.controller.move(0, 0, tracks+5)
|
||||||
self.assertRaises(AssertionError, test)
|
self.assertRaises(AssertionError, test)
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_move_group_outside_of_playlist(self):
|
def test_move_group_outside_of_playlist(self):
|
||||||
tracks = len(self.controller.playlist.tracks)
|
tracks = len(self.controller.tracks)
|
||||||
test = lambda: self.controller.move(0, 2, tracks+5)
|
test = lambda: self.controller.move(0, 2, tracks+5)
|
||||||
self.assertRaises(AssertionError, test)
|
self.assertRaises(AssertionError, test)
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_move_group_out_of_range(self):
|
def test_move_group_out_of_range(self):
|
||||||
tracks = len(self.controller.playlist.tracks)
|
tracks = len(self.controller.tracks)
|
||||||
test = lambda: self.controller.move(tracks+2, tracks+3, 0)
|
test = lambda: self.controller.move(tracks+2, tracks+3, 0)
|
||||||
self.assertRaises(AssertionError, test)
|
self.assertRaises(AssertionError, test)
|
||||||
|
|
||||||
@ -236,35 +236,36 @@ class BaseCurrentPlaylistControllerTest(object):
|
|||||||
test = lambda: self.controller.move(2, 1, 0)
|
test = lambda: self.controller.move(2, 1, 0)
|
||||||
self.assertRaises(AssertionError, test)
|
self.assertRaises(AssertionError, test)
|
||||||
|
|
||||||
def test_playlist_attribute_is_immutable(self):
|
def test_tracks_attribute_is_immutable(self):
|
||||||
playlist1 = self.controller.playlist
|
tracks1 = self.controller.tracks
|
||||||
playlist2 = self.controller.playlist
|
tracks2 = self.controller.tracks
|
||||||
|
self.assertNotEqual(id(tracks1), id(tracks2))
|
||||||
self.assertNotEqual(id(playlist1), id(playlist2))
|
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_remove(self):
|
def test_remove(self):
|
||||||
track1 = self.controller.playlist.tracks[1]
|
track1 = self.controller.tracks[1]
|
||||||
track2 = self.controller.playlist.tracks[2]
|
track2 = self.controller.tracks[2]
|
||||||
self.controller.remove(track1)
|
version = self.controller.version
|
||||||
self.assert_(track1 not in self.controller.playlist.tracks)
|
self.controller.remove(id=track1.id)
|
||||||
self.assertEqual(track2, self.controller.playlist.tracks[1])
|
self.assert_(version < self.controller.version)
|
||||||
|
self.assert_(track1 not in self.controller.tracks)
|
||||||
|
self.assertEqual(track2, self.controller.tracks[1])
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_removing_track_that_does_not_exist(self):
|
def test_removing_track_that_does_not_exist(self):
|
||||||
test = lambda: self.controller.remove(Track())
|
test = lambda: self.controller.remove(id=12345)
|
||||||
self.assertRaises(AssertionError, test)
|
self.assertRaises(LookupError, test)
|
||||||
|
|
||||||
def test_removing_from_empty_playlist(self):
|
def test_removing_from_empty_playlist(self):
|
||||||
test = lambda: self.controller.remove(Track())
|
test = lambda: self.controller.remove(id=12345)
|
||||||
self.assertRaises(AssertionError, test)
|
self.assertRaises(LookupError, test)
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_shuffle(self):
|
def test_shuffle(self):
|
||||||
random.seed(1)
|
random.seed(1)
|
||||||
self.controller.shuffle()
|
self.controller.shuffle()
|
||||||
|
|
||||||
shuffled_tracks = self.controller.playlist.tracks
|
shuffled_tracks = self.controller.tracks
|
||||||
|
|
||||||
self.assertNotEqual(self.tracks, shuffled_tracks)
|
self.assertNotEqual(self.tracks, shuffled_tracks)
|
||||||
self.assertEqual(set(self.tracks), set(shuffled_tracks))
|
self.assertEqual(set(self.tracks), set(shuffled_tracks))
|
||||||
@ -274,7 +275,7 @@ class BaseCurrentPlaylistControllerTest(object):
|
|||||||
random.seed(1)
|
random.seed(1)
|
||||||
self.controller.shuffle(1, 3)
|
self.controller.shuffle(1, 3)
|
||||||
|
|
||||||
shuffled_tracks = self.controller.playlist.tracks
|
shuffled_tracks = self.controller.tracks
|
||||||
|
|
||||||
self.assertNotEqual(self.tracks, shuffled_tracks)
|
self.assertNotEqual(self.tracks, shuffled_tracks)
|
||||||
self.assertEqual(self.tracks[0], shuffled_tracks[0])
|
self.assertEqual(self.tracks[0], shuffled_tracks[0])
|
||||||
@ -287,7 +288,7 @@ class BaseCurrentPlaylistControllerTest(object):
|
|||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_shuffle_superset(self):
|
def test_shuffle_superset(self):
|
||||||
tracks = len(self.controller.playlist.tracks)
|
tracks = len(self.controller.tracks)
|
||||||
test = lambda: self.controller.shuffle(1, tracks+5)
|
test = lambda: self.controller.shuffle(1, tracks+5)
|
||||||
self.assertRaises(AssertionError, test)
|
self.assertRaises(AssertionError, test)
|
||||||
|
|
||||||
@ -296,7 +297,7 @@ class BaseCurrentPlaylistControllerTest(object):
|
|||||||
random.seed(1)
|
random.seed(1)
|
||||||
self.controller.shuffle(1)
|
self.controller.shuffle(1)
|
||||||
|
|
||||||
shuffled_tracks = self.controller.playlist.tracks
|
shuffled_tracks = self.controller.tracks
|
||||||
|
|
||||||
self.assertNotEqual(self.tracks, shuffled_tracks)
|
self.assertNotEqual(self.tracks, shuffled_tracks)
|
||||||
self.assertEqual(self.tracks[0], shuffled_tracks[0])
|
self.assertEqual(self.tracks[0], shuffled_tracks[0])
|
||||||
@ -304,8 +305,8 @@ class BaseCurrentPlaylistControllerTest(object):
|
|||||||
|
|
||||||
def test_version(self):
|
def test_version(self):
|
||||||
version = self.controller.version
|
version = self.controller.version
|
||||||
self.controller.playlist = Playlist()
|
self.controller.load([])
|
||||||
self.assertEqual(version+1, self.controller.version)
|
self.assert_(version < self.controller.version)
|
||||||
|
|
||||||
|
|
||||||
class BasePlaybackControllerTest(object):
|
class BasePlaybackControllerTest(object):
|
||||||
@ -614,7 +615,7 @@ class BasePlaybackControllerTest(object):
|
|||||||
wrapper.called = False
|
wrapper.called = False
|
||||||
|
|
||||||
self.playback.new_playlist_loaded_callback = wrapper
|
self.playback.new_playlist_loaded_callback = wrapper
|
||||||
self.backend.current_playlist.load(Playlist())
|
self.backend.current_playlist.load([])
|
||||||
|
|
||||||
self.assert_(wrapper.called)
|
self.assert_(wrapper.called)
|
||||||
|
|
||||||
@ -639,26 +640,23 @@ class BasePlaybackControllerTest(object):
|
|||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_new_playlist_loaded_callback_when_playing(self):
|
def test_new_playlist_loaded_callback_when_playing(self):
|
||||||
playlist = Playlist(tracks=[self.tracks[2]])
|
|
||||||
self.playback.play()
|
self.playback.play()
|
||||||
self.backend.current_playlist.load(playlist)
|
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, self.tracks[2])
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_new_playlist_loaded_callback_when_stopped(self):
|
def test_new_playlist_loaded_callback_when_stopped(self):
|
||||||
playlist = Playlist(tracks=[self.tracks[2]])
|
self.backend.current_playlist.load([self.tracks[2]])
|
||||||
self.backend.current_playlist.load(playlist)
|
|
||||||
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])
|
self.assertEqual(self.playback.next_track, self.tracks[2])
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_new_playlist_loaded_callback_when_paused(self):
|
def test_new_playlist_loaded_callback_when_paused(self):
|
||||||
playlist = Playlist(tracks=[self.tracks[2]])
|
|
||||||
self.playback.play()
|
self.playback.play()
|
||||||
self.playback.pause()
|
self.playback.pause()
|
||||||
self.backend.current_playlist.load(playlist)
|
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])
|
self.assertEqual(self.playback.next_track, self.tracks[2])
|
||||||
@ -735,7 +733,7 @@ class BasePlaybackControllerTest(object):
|
|||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_seek_when_playing(self):
|
def test_seek_when_playing(self):
|
||||||
length = self.backend.current_playlist.playlist.tracks[0].length
|
length = self.backend.current_playlist.tracks[0].length
|
||||||
self.playback.play()
|
self.playback.play()
|
||||||
self.playback.seek(length - 1000)
|
self.playback.seek(length - 1000)
|
||||||
position = self.playback.time_position
|
position = self.playback.time_position
|
||||||
@ -743,7 +741,7 @@ class BasePlaybackControllerTest(object):
|
|||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_seek_when_paused(self):
|
def test_seek_when_paused(self):
|
||||||
length = self.backend.current_playlist.playlist.tracks[0].length
|
length = self.backend.current_playlist.tracks[0].length
|
||||||
self.playback.play()
|
self.playback.play()
|
||||||
self.playback.pause()
|
self.playback.pause()
|
||||||
self.playback.seek(length - 1000)
|
self.playback.seek(length - 1000)
|
||||||
@ -842,16 +840,15 @@ class BasePlaybackControllerTest(object):
|
|||||||
self.playback.consume = True
|
self.playback.consume = True
|
||||||
self.playback.play()
|
self.playback.play()
|
||||||
self.playback.next()
|
self.playback.next()
|
||||||
tracks = self.backend.current_playlist.playlist.tracks
|
self.assert_(self.tracks[0] not in self.backend.current_playlist.tracks)
|
||||||
self.assert_(self.tracks[0] not in tracks)
|
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_playlist_is_empty_after_all_tracks_are_played_with_consume(self):
|
def test_playlist_is_empty_after_all_tracks_are_played_with_consume(self):
|
||||||
self.playback.consume = True
|
self.playback.consume = True
|
||||||
self.playback.play()
|
self.playback.play()
|
||||||
for i in range(len(self.backend.current_playlist.playlist.tracks)):
|
for i in range(len(self.backend.current_playlist.tracks)):
|
||||||
self.playback.next()
|
self.playback.next()
|
||||||
self.assertEqual(len(self.backend.current_playlist.playlist.tracks), 0)
|
self.assertEqual(len(self.backend.current_playlist.tracks), 0)
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
def test_play_with_random(self):
|
def test_play_with_random(self):
|
||||||
@ -932,7 +929,7 @@ class BasePlaybackControllerTest(object):
|
|||||||
random.seed(1)
|
random.seed(1)
|
||||||
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(Playlist(tracks=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[0])
|
||||||
|
|
||||||
@populate_playlist
|
@populate_playlist
|
||||||
@ -946,8 +943,7 @@ class BasePlaybackControllerTest(object):
|
|||||||
self.playback.next()
|
self.playback.next()
|
||||||
|
|
||||||
def test_playing_track_with_invalid_uri(self):
|
def test_playing_track_with_invalid_uri(self):
|
||||||
playlist = Playlist(tracks=[Track(uri='foobar')])
|
self.backend.current_playlist.load([Track(uri='foobar')])
|
||||||
self.backend.current_playlist.load(playlist)
|
|
||||||
self.playback.play()
|
self.playback.play()
|
||||||
self.assertEqual(self.playback.state, self.playback.STOPPED)
|
self.assertEqual(self.playback.state, self.playback.STOPPED)
|
||||||
|
|
||||||
|
|||||||
@ -228,45 +228,6 @@ class TrackTest(unittest.TestCase):
|
|||||||
self.assertEqual(track.id, track_id)
|
self.assertEqual(track.id, track_id)
|
||||||
self.assertRaises(AttributeError, setattr, track, 'id', None)
|
self.assertRaises(AttributeError, setattr, track, 'id', None)
|
||||||
|
|
||||||
def test_mpd_format_for_empty_track(self):
|
|
||||||
track = Track()
|
|
||||||
result = track.mpd_format()
|
|
||||||
self.assert_(('file', '') in result)
|
|
||||||
self.assert_(('Time', 0) in result)
|
|
||||||
self.assert_(('Artist', '') in result)
|
|
||||||
self.assert_(('Title', '') in result)
|
|
||||||
self.assert_(('Album', '') in result)
|
|
||||||
self.assert_(('Track', 0) in result)
|
|
||||||
self.assert_(('Date', '') in result)
|
|
||||||
self.assert_(('Pos', 0) in result)
|
|
||||||
self.assert_(('Id', 0) in result)
|
|
||||||
|
|
||||||
def test_mpd_format_for_nonempty_track(self):
|
|
||||||
track = Track(
|
|
||||||
uri=u'a uri',
|
|
||||||
artists=[Artist(name=u'an artist')],
|
|
||||||
name=u'a name',
|
|
||||||
album=Album(name=u'an album', num_tracks=13),
|
|
||||||
track_no=7,
|
|
||||||
date=dt.date(1977, 1, 1),
|
|
||||||
length=137000,
|
|
||||||
id=122,
|
|
||||||
)
|
|
||||||
result = track.mpd_format(position=9)
|
|
||||||
self.assert_(('file', 'a uri') in result)
|
|
||||||
self.assert_(('Time', 137) in result)
|
|
||||||
self.assert_(('Artist', 'an artist') in result)
|
|
||||||
self.assert_(('Title', 'a name') in result)
|
|
||||||
self.assert_(('Album', 'an album') in result)
|
|
||||||
self.assert_(('Track', '7/13') in result)
|
|
||||||
self.assert_(('Date', dt.date(1977, 1, 1)) in result)
|
|
||||||
self.assert_(('Pos', 9) in result)
|
|
||||||
self.assert_(('Id', 122) in result)
|
|
||||||
|
|
||||||
def test_mpd_format_artists(self):
|
|
||||||
track = Track(artists=[Artist(name=u'ABBA'), Artist(name=u'Beatles')])
|
|
||||||
self.assertEqual(track.mpd_format_artists(), u'ABBA, Beatles')
|
|
||||||
|
|
||||||
def test_invalid_kwarg(self):
|
def test_invalid_kwarg(self):
|
||||||
test = lambda: Track(foo='baz')
|
test = lambda: Track(foo='baz')
|
||||||
self.assertRaises(TypeError, test)
|
self.assertRaises(TypeError, test)
|
||||||
@ -450,33 +411,6 @@ class PlaylistTest(unittest.TestCase):
|
|||||||
self.assertRaises(AttributeError, setattr, playlist, 'last_modified',
|
self.assertRaises(AttributeError, setattr, playlist, 'last_modified',
|
||||||
None)
|
None)
|
||||||
|
|
||||||
def test_mpd_format(self):
|
|
||||||
playlist = Playlist(tracks=[
|
|
||||||
Track(track_no=1), Track(track_no=2), Track(track_no=3)])
|
|
||||||
result = playlist.mpd_format()
|
|
||||||
self.assertEqual(len(result), 3)
|
|
||||||
|
|
||||||
def test_mpd_format_with_range(self):
|
|
||||||
playlist = Playlist(tracks=[
|
|
||||||
Track(track_no=1), Track(track_no=2), Track(track_no=3)])
|
|
||||||
result = playlist.mpd_format(1, 2)
|
|
||||||
self.assertEqual(len(result), 1)
|
|
||||||
self.assertEqual(dict(result[0])['Track'], 2)
|
|
||||||
|
|
||||||
def test_mpd_format_with_negative_start_and_no_end(self):
|
|
||||||
playlist = Playlist(tracks=[
|
|
||||||
Track(track_no=1), Track(track_no=2), Track(track_no=3)])
|
|
||||||
result = playlist.mpd_format(-1, None)
|
|
||||||
self.assertEqual(len(result), 1)
|
|
||||||
self.assertEqual(dict(result[0])['Track'], 3)
|
|
||||||
|
|
||||||
def test_mpd_format_with_negative_start_and_end(self):
|
|
||||||
playlist = Playlist(tracks=[
|
|
||||||
Track(track_no=1), Track(track_no=2), Track(track_no=3)])
|
|
||||||
result = playlist.mpd_format(-2, -1)
|
|
||||||
self.assertEqual(len(result), 1)
|
|
||||||
self.assertEqual(dict(result[0])['Track'], 2)
|
|
||||||
|
|
||||||
def test_with_new_uri(self):
|
def test_with_new_uri(self):
|
||||||
tracks = [Track()]
|
tracks = [Track()]
|
||||||
last_modified = dt.datetime.now()
|
last_modified = dt.datetime.now()
|
||||||
|
|||||||
@ -118,7 +118,7 @@ class StatusHandlerTest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_currentsong(self):
|
def test_currentsong(self):
|
||||||
track = Track()
|
track = Track()
|
||||||
self.b.current_playlist.playlist = Playlist(tracks=[track])
|
self.b.current_playlist.load([track])
|
||||||
self.b.playback.current_track = track
|
self.b.playback.current_track = track
|
||||||
result = self.h.handle_request(u'currentsong')
|
result = self.h.handle_request(u'currentsong')
|
||||||
self.assert_(u'file: ' in result)
|
self.assert_(u'file: ' in result)
|
||||||
@ -258,7 +258,7 @@ class StatusHandlerTest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_status_method_when_playlist_loaded_contains_song(self):
|
def test_status_method_when_playlist_loaded_contains_song(self):
|
||||||
track = Track()
|
track = Track()
|
||||||
self.b.current_playlist.load(Playlist(tracks=[track]))
|
self.b.current_playlist.load([track])
|
||||||
self.b.playback.current_track = track
|
self.b.playback.current_track = track
|
||||||
result = dict(self.h._status_status())
|
result = dict(self.h._status_status())
|
||||||
self.assert_('song' in result)
|
self.assert_('song' in result)
|
||||||
@ -266,7 +266,7 @@ class StatusHandlerTest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_status_method_when_playlist_loaded_contains_pos_as_songid(self):
|
def test_status_method_when_playlist_loaded_contains_pos_as_songid(self):
|
||||||
track = Track()
|
track = Track()
|
||||||
self.b.current_playlist.load(Playlist(tracks=[track]))
|
self.b.current_playlist.load([track])
|
||||||
self.b.playback.current_track = track
|
self.b.playback.current_track = track
|
||||||
result = dict(self.h._status_status())
|
result = dict(self.h._status_status())
|
||||||
self.assert_('songid' in result)
|
self.assert_('songid' in result)
|
||||||
@ -274,7 +274,7 @@ class StatusHandlerTest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_status_method_when_playlist_loaded_contains_id_as_songid(self):
|
def test_status_method_when_playlist_loaded_contains_id_as_songid(self):
|
||||||
track = Track(id=1)
|
track = Track(id=1)
|
||||||
self.b.current_playlist.load(Playlist(tracks=[track]))
|
self.b.current_playlist.load([track])
|
||||||
self.b.playback.current_track = track
|
self.b.playback.current_track = track
|
||||||
result = dict(self.h._status_status())
|
result = dict(self.h._status_status())
|
||||||
self.assert_('songid' in result)
|
self.assert_('songid' in result)
|
||||||
@ -447,7 +447,7 @@ class PlaybackControlHandlerTest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_pause_off(self):
|
def test_pause_off(self):
|
||||||
track = Track()
|
track = Track()
|
||||||
self.b.current_playlist.playlist = Playlist(tracks=[track])
|
self.b.current_playlist.load([track])
|
||||||
self.b.playback.current_track = track
|
self.b.playback.current_track = track
|
||||||
self.h.handle_request(u'play "0"')
|
self.h.handle_request(u'play "0"')
|
||||||
self.h.handle_request(u'pause "1"')
|
self.h.handle_request(u'pause "1"')
|
||||||
@ -457,7 +457,7 @@ class PlaybackControlHandlerTest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_pause_on(self):
|
def test_pause_on(self):
|
||||||
track = Track()
|
track = Track()
|
||||||
self.b.current_playlist.playlist = Playlist(tracks=[track])
|
self.b.current_playlist.load([track])
|
||||||
self.b.playback.current_track = track
|
self.b.playback.current_track = track
|
||||||
self.h.handle_request(u'play "0"')
|
self.h.handle_request(u'play "0"')
|
||||||
result = self.h.handle_request(u'pause "1"')
|
result = self.h.handle_request(u'pause "1"')
|
||||||
@ -466,7 +466,7 @@ class PlaybackControlHandlerTest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_play_without_pos(self):
|
def test_play_without_pos(self):
|
||||||
track = Track()
|
track = Track()
|
||||||
self.b.current_playlist.playlist = Playlist(tracks=[track])
|
self.b.current_playlist.load([track])
|
||||||
self.b.playback.current_track = track
|
self.b.playback.current_track = track
|
||||||
self.b.playback.state = self.b.playback.PAUSED
|
self.b.playback.state = self.b.playback.PAUSED
|
||||||
result = self.h.handle_request(u'play')
|
result = self.h.handle_request(u'play')
|
||||||
@ -474,42 +474,42 @@ class PlaybackControlHandlerTest(unittest.TestCase):
|
|||||||
self.assertEqual(self.b.playback.PLAYING, self.b.playback.state)
|
self.assertEqual(self.b.playback.PLAYING, self.b.playback.state)
|
||||||
|
|
||||||
def test_play_with_pos(self):
|
def test_play_with_pos(self):
|
||||||
self.b.current_playlist.load(Playlist(tracks=[Track()]))
|
self.b.current_playlist.load([Track()])
|
||||||
result = self.h.handle_request(u'play "0"')
|
result = self.h.handle_request(u'play "0"')
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
self.assertEqual(self.b.playback.PLAYING, self.b.playback.state)
|
self.assertEqual(self.b.playback.PLAYING, self.b.playback.state)
|
||||||
|
|
||||||
def test_play_with_pos_out_of_bounds(self):
|
def test_play_with_pos_out_of_bounds(self):
|
||||||
self.b.current_playlist.load(Playlist())
|
self.b.current_playlist.load([])
|
||||||
result = self.h.handle_request(u'play "0"')
|
result = self.h.handle_request(u'play "0"')
|
||||||
self.assertEqual(result[0], u'ACK [2@0] {play} Bad song index')
|
self.assertEqual(result[0], u'ACK [2@0] {play} Bad song index')
|
||||||
self.assertEqual(self.b.playback.STOPPED, self.b.playback.state)
|
self.assertEqual(self.b.playback.STOPPED, self.b.playback.state)
|
||||||
|
|
||||||
def test_play_minus_one_plays_first_in_playlist(self):
|
def test_play_minus_one_plays_first_in_playlist(self):
|
||||||
track = Track(id=0)
|
track = Track()
|
||||||
self.b.current_playlist.load(Playlist(tracks=[track]))
|
self.b.current_playlist.load([track])
|
||||||
result = self.h.handle_request(u'play "-1"')
|
result = self.h.handle_request(u'play "-1"')
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
self.assertEqual(self.b.playback.PLAYING, self.b.playback.state)
|
self.assertEqual(self.b.playback.PLAYING, self.b.playback.state)
|
||||||
self.assertEqual(self.b.playback.current_track, track)
|
self.assertEqual(self.b.playback.current_track, track)
|
||||||
|
|
||||||
def test_playid(self):
|
def test_playid(self):
|
||||||
self.b.current_playlist.load(Playlist(tracks=[Track(id=0)]))
|
self.b.current_playlist.load([Track()])
|
||||||
result = self.h.handle_request(u'playid "0"')
|
result = self.h.handle_request(u'playid "1"')
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
self.assertEqual(self.b.playback.PLAYING, self.b.playback.state)
|
self.assertEqual(self.b.playback.PLAYING, self.b.playback.state)
|
||||||
|
|
||||||
def test_playid_minus_one_plays_first_in_playlist(self):
|
def test_playid_minus_one_plays_first_in_playlist(self):
|
||||||
track = Track(id=0)
|
track = Track()
|
||||||
self.b.current_playlist.load(Playlist(tracks=[track]))
|
self.b.current_playlist.load([track])
|
||||||
result = self.h.handle_request(u'playid "-1"')
|
result = self.h.handle_request(u'playid "-1"')
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
self.assertEqual(self.b.playback.PLAYING, self.b.playback.state)
|
self.assertEqual(self.b.playback.PLAYING, self.b.playback.state)
|
||||||
self.assertEqual(self.b.playback.current_track, track)
|
self.assertEqual(self.b.playback.current_track, track)
|
||||||
|
|
||||||
def test_playid_which_does_not_exist(self):
|
def test_playid_which_does_not_exist(self):
|
||||||
self.b.current_playlist.load(Playlist(tracks=[Track(id=0)]))
|
self.b.current_playlist.load([Track()])
|
||||||
result = self.h.handle_request(u'playid "1"')
|
result = self.h.handle_request(u'playid "12345"')
|
||||||
self.assertEqual(result[0], u'ACK [50@0] {playid} No such song')
|
self.assertEqual(result[0], u'ACK [50@0] {playid} No such song')
|
||||||
|
|
||||||
def test_previous(self):
|
def test_previous(self):
|
||||||
@ -539,12 +539,12 @@ class CurrentPlaylistHandlerTest(unittest.TestCase):
|
|||||||
def test_add(self):
|
def test_add(self):
|
||||||
needle = Track(uri='dummy://foo')
|
needle = Track(uri='dummy://foo')
|
||||||
self.b.library._library = [Track(), Track(), needle, Track()]
|
self.b.library._library = [Track(), Track(), needle, Track()]
|
||||||
self.b.current_playlist.playlist = Playlist(
|
self.b.current_playlist.load(
|
||||||
tracks=[Track(), Track(), Track(), Track(), Track()])
|
[Track(), Track(), Track(), Track(), Track()])
|
||||||
self.assertEqual(self.b.current_playlist.playlist.length, 5)
|
self.assertEqual(len(self.b.current_playlist.tracks), 5)
|
||||||
result = self.h.handle_request(u'add "dummy://foo"')
|
result = self.h.handle_request(u'add "dummy://foo"')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.length, 6)
|
self.assertEqual(len(self.b.current_playlist.tracks), 6)
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[5], needle)
|
self.assertEqual(self.b.current_playlist.tracks[5], needle)
|
||||||
self.assertEqual(len(result), 1)
|
self.assertEqual(len(result), 1)
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
@ -556,33 +556,33 @@ class CurrentPlaylistHandlerTest(unittest.TestCase):
|
|||||||
def test_addid_without_songpos(self):
|
def test_addid_without_songpos(self):
|
||||||
needle = Track(uri='dummy://foo', id=137)
|
needle = Track(uri='dummy://foo', id=137)
|
||||||
self.b.library._library = [Track(), Track(), needle, Track()]
|
self.b.library._library = [Track(), Track(), needle, Track()]
|
||||||
self.b.current_playlist.playlist = Playlist(
|
self.b.current_playlist.load(
|
||||||
tracks=[Track(), Track(), Track(), Track(), Track()])
|
[Track(), Track(), Track(), Track(), Track()])
|
||||||
self.assertEqual(self.b.current_playlist.playlist.length, 5)
|
self.assertEqual(len(self.b.current_playlist.tracks), 5)
|
||||||
result = self.h.handle_request(u'addid "dummy://foo"')
|
result = self.h.handle_request(u'addid "dummy://foo"')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.length, 6)
|
self.assertEqual(len(self.b.current_playlist.tracks), 6)
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[5], needle)
|
self.assertEqual(self.b.current_playlist.tracks[5], needle)
|
||||||
self.assert_(u'Id: 137' in result)
|
self.assert_(u'Id: 137' in result)
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_addid_with_songpos(self):
|
def test_addid_with_songpos(self):
|
||||||
needle = Track(uri='dummy://foo', id=137)
|
needle = Track(uri='dummy://foo', id=137)
|
||||||
self.b.library._library = [Track(), Track(), needle, Track()]
|
self.b.library._library = [Track(), Track(), needle, Track()]
|
||||||
self.b.current_playlist.playlist = Playlist(
|
self.b.current_playlist.load(
|
||||||
tracks=[Track(), Track(), Track(), Track(), Track()])
|
[Track(), Track(), Track(), Track(), Track()])
|
||||||
self.assertEqual(self.b.current_playlist.playlist.length, 5)
|
self.assertEqual(len(self.b.current_playlist.tracks), 5)
|
||||||
result = self.h.handle_request(u'addid "dummy://foo" "3"')
|
result = self.h.handle_request(u'addid "dummy://foo" "3"')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.length, 6)
|
self.assertEqual(len(self.b.current_playlist.tracks), 6)
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[3], needle)
|
self.assertEqual(self.b.current_playlist.tracks[3], needle)
|
||||||
self.assert_(u'Id: 137' in result)
|
self.assert_(u'Id: 137' in result)
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_addid_with_songpos_out_of_bounds_should_ack(self):
|
def test_addid_with_songpos_out_of_bounds_should_ack(self):
|
||||||
needle = Track(uri='dummy://foo', id=137)
|
needle = Track(uri='dummy://foo', id=137)
|
||||||
self.b.library._library = [Track(), Track(), needle, Track()]
|
self.b.library._library = [Track(), Track(), needle, Track()]
|
||||||
self.b.current_playlist.playlist = Playlist(
|
self.b.current_playlist.load(
|
||||||
tracks=[Track(), Track(), Track(), Track(), Track()])
|
[Track(), Track(), Track(), Track(), Track()])
|
||||||
self.assertEqual(self.b.current_playlist.playlist.length, 5)
|
self.assertEqual(len(self.b.current_playlist.tracks), 5)
|
||||||
result = self.h.handle_request(u'addid "dummy://foo" "6"')
|
result = self.h.handle_request(u'addid "dummy://foo" "6"')
|
||||||
self.assertEqual(result[0], u'ACK [2@0] {addid} Bad song index')
|
self.assertEqual(result[0], u'ACK [2@0] {addid} Bad song index')
|
||||||
|
|
||||||
@ -591,118 +591,122 @@ class CurrentPlaylistHandlerTest(unittest.TestCase):
|
|||||||
self.assertEqual(result[0], u'ACK [50@0] {addid} No such song')
|
self.assertEqual(result[0], u'ACK [50@0] {addid} No such song')
|
||||||
|
|
||||||
def test_clear(self):
|
def test_clear(self):
|
||||||
self.b.current_playlist.playlist = Playlist(
|
self.b.current_playlist.load(
|
||||||
tracks=[Track(), Track(), Track(), Track(), Track()])
|
[Track(), Track(), Track(), Track(), Track()])
|
||||||
self.assertEqual(self.b.current_playlist.playlist.length, 5)
|
self.assertEqual(len(self.b.current_playlist.tracks), 5)
|
||||||
result = self.h.handle_request(u'clear')
|
result = self.h.handle_request(u'clear')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.length, 0)
|
self.assertEqual(len(self.b.current_playlist.tracks), 0)
|
||||||
self.assertEqual(self.b.playback.current_track, None)
|
self.assertEqual(self.b.playback.current_track, None)
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_delete_songpos(self):
|
def test_delete_songpos(self):
|
||||||
self.b.current_playlist.playlist = Playlist(
|
self.b.current_playlist.load(
|
||||||
tracks=[Track(), Track(), Track(), Track(), Track()])
|
[Track(id=1), Track(id=2), Track(id=3), Track(id=4), Track(id=5)])
|
||||||
self.assertEqual(self.b.current_playlist.playlist.length, 5)
|
self.assertEqual(len(self.b.current_playlist.tracks), 5)
|
||||||
result = self.h.handle_request(u'delete "2"')
|
result = self.h.handle_request(u'delete "2"')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.length, 4)
|
self.assertEqual(len(self.b.current_playlist.tracks), 4)
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_delete_songpos_out_of_bounds(self):
|
def test_delete_songpos_out_of_bounds(self):
|
||||||
self.b.current_playlist.playlist = Playlist(
|
self.b.current_playlist.load(
|
||||||
tracks=[Track(), Track(), Track(), Track(), Track()])
|
[Track(), Track(), Track(), Track(), Track()])
|
||||||
self.assertEqual(self.b.current_playlist.playlist.length, 5)
|
self.assertEqual(len(self.b.current_playlist.tracks), 5)
|
||||||
result = self.h.handle_request(u'delete "5"')
|
result = self.h.handle_request(u'delete "5"')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.length, 5)
|
self.assertEqual(len(self.b.current_playlist.tracks), 5)
|
||||||
self.assertEqual(result[0], u'ACK [2@0] {delete} Bad song index')
|
self.assertEqual(result[0], u'ACK [2@0] {delete} Bad song index')
|
||||||
|
|
||||||
def test_delete_open_range(self):
|
def test_delete_open_range(self):
|
||||||
self.b.current_playlist.playlist = Playlist(
|
self.b.current_playlist.load(
|
||||||
tracks=[Track(), Track(), Track(), Track(), Track()])
|
[Track(id=1), Track(id=2), Track(id=3), Track(id=4), Track(id=5)])
|
||||||
self.assertEqual(self.b.current_playlist.playlist.length, 5)
|
self.assertEqual(len(self.b.current_playlist.tracks), 5)
|
||||||
result = self.h.handle_request(u'delete "1:"')
|
result = self.h.handle_request(u'delete "1:"')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.length, 1)
|
self.assertEqual(len(self.b.current_playlist.tracks), 1)
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_delete_closed_range(self):
|
def test_delete_closed_range(self):
|
||||||
self.b.current_playlist.playlist = Playlist(
|
self.b.current_playlist.load(
|
||||||
tracks=[Track(), Track(), Track(), Track(), Track()])
|
[Track(id=1), Track(id=2), Track(id=3), Track(id=4), Track(id=5)])
|
||||||
self.assertEqual(self.b.current_playlist.playlist.length, 5)
|
self.assertEqual(len(self.b.current_playlist.tracks), 5)
|
||||||
result = self.h.handle_request(u'delete "1:3"')
|
result = self.h.handle_request(u'delete "1:3"')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.length, 3)
|
self.assertEqual(len(self.b.current_playlist.tracks), 3)
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_delete_range_out_of_bounds(self):
|
def test_delete_range_out_of_bounds(self):
|
||||||
self.b.current_playlist.playlist = Playlist(
|
self.b.current_playlist.load(
|
||||||
tracks=[Track(), Track(), Track(), Track(), Track()])
|
[Track(), Track(), Track(), Track(), Track()])
|
||||||
self.assertEqual(self.b.current_playlist.playlist.length, 5)
|
self.assertEqual(len(self.b.current_playlist.tracks), 5)
|
||||||
result = self.h.handle_request(u'delete "5:7"')
|
result = self.h.handle_request(u'delete "5:7"')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.length, 5)
|
self.assertEqual(len(self.b.current_playlist.tracks), 5)
|
||||||
self.assertEqual(result[0], u'ACK [2@0] {delete} Bad song index')
|
self.assertEqual(result[0], u'ACK [2@0] {delete} Bad song index')
|
||||||
|
|
||||||
def test_deleteid(self):
|
def test_deleteid(self):
|
||||||
self.b.current_playlist.load(Playlist(tracks=[Track(id=0), Track()]))
|
self.b.current_playlist.load([Track(), Track()])
|
||||||
self.assertEqual(self.b.current_playlist.playlist.length, 2)
|
self.assertEqual(len(self.b.current_playlist.tracks), 2)
|
||||||
result = self.h.handle_request(u'deleteid "0"')
|
result = self.h.handle_request(u'deleteid "2"')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.length, 1)
|
self.assertEqual(len(self.b.current_playlist.tracks), 1)
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_deleteid_does_not_exist(self):
|
def test_deleteid_does_not_exist(self):
|
||||||
self.b.current_playlist.load(Playlist(tracks=[Track(id=1), Track()]))
|
self.b.current_playlist.load([Track(), Track()])
|
||||||
self.assertEqual(self.b.current_playlist.playlist.length, 2)
|
self.assertEqual(len(self.b.current_playlist.tracks), 2)
|
||||||
result = self.h.handle_request(u'deleteid "0"')
|
result = self.h.handle_request(u'deleteid "12345"')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.length, 2)
|
self.assertEqual(len(self.b.current_playlist.tracks), 2)
|
||||||
self.assertEqual(result[0], u'ACK [50@0] {deleteid} No such song')
|
self.assertEqual(result[0], u'ACK [50@0] {deleteid} No such song')
|
||||||
|
|
||||||
def test_move_songpos(self):
|
def test_move_songpos(self):
|
||||||
self.b.current_playlist.load(Playlist(tracks=[
|
self.b.current_playlist.load([
|
||||||
Track(name='a'), Track(name='b'), Track(name='c'),
|
Track(name='a'), Track(name='b'), Track(name='c'),
|
||||||
Track(name='d'), Track(name='e'), Track(name='f')]))
|
Track(name='d'), Track(name='e'), Track(name='f'),
|
||||||
|
])
|
||||||
result = self.h.handle_request(u'move "1" "0"')
|
result = self.h.handle_request(u'move "1" "0"')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[0].name, 'b')
|
self.assertEqual(self.b.current_playlist.tracks[0].name, 'b')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[1].name, 'a')
|
self.assertEqual(self.b.current_playlist.tracks[1].name, 'a')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[2].name, 'c')
|
self.assertEqual(self.b.current_playlist.tracks[2].name, 'c')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[3].name, 'd')
|
self.assertEqual(self.b.current_playlist.tracks[3].name, 'd')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[4].name, 'e')
|
self.assertEqual(self.b.current_playlist.tracks[4].name, 'e')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[5].name, 'f')
|
self.assertEqual(self.b.current_playlist.tracks[5].name, 'f')
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_move_open_range(self):
|
def test_move_open_range(self):
|
||||||
self.b.current_playlist.load(Playlist(tracks=[
|
self.b.current_playlist.load([
|
||||||
Track(name='a'), Track(name='b'), Track(name='c'),
|
Track(name='a'), Track(name='b'), Track(name='c'),
|
||||||
Track(name='d'), Track(name='e'), Track(name='f')]))
|
Track(name='d'), Track(name='e'), Track(name='f'),
|
||||||
|
])
|
||||||
result = self.h.handle_request(u'move "2:" "0"')
|
result = self.h.handle_request(u'move "2:" "0"')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[0].name, 'c')
|
self.assertEqual(self.b.current_playlist.tracks[0].name, 'c')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[1].name, 'd')
|
self.assertEqual(self.b.current_playlist.tracks[1].name, 'd')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[2].name, 'e')
|
self.assertEqual(self.b.current_playlist.tracks[2].name, 'e')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[3].name, 'f')
|
self.assertEqual(self.b.current_playlist.tracks[3].name, 'f')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[4].name, 'a')
|
self.assertEqual(self.b.current_playlist.tracks[4].name, 'a')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[5].name, 'b')
|
self.assertEqual(self.b.current_playlist.tracks[5].name, 'b')
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_move_closed_range(self):
|
def test_move_closed_range(self):
|
||||||
self.b.current_playlist.load(Playlist(tracks=[
|
self.b.current_playlist.load([
|
||||||
Track(name='a'), Track(name='b'), Track(name='c'),
|
Track(name='a'), Track(name='b'), Track(name='c'),
|
||||||
Track(name='d'), Track(name='e'), Track(name='f')]))
|
Track(name='d'), Track(name='e'), Track(name='f'),
|
||||||
|
])
|
||||||
result = self.h.handle_request(u'move "1:3" "0"')
|
result = self.h.handle_request(u'move "1:3" "0"')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[0].name, 'b')
|
self.assertEqual(self.b.current_playlist.tracks[0].name, 'b')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[1].name, 'c')
|
self.assertEqual(self.b.current_playlist.tracks[1].name, 'c')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[2].name, 'a')
|
self.assertEqual(self.b.current_playlist.tracks[2].name, 'a')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[3].name, 'd')
|
self.assertEqual(self.b.current_playlist.tracks[3].name, 'd')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[4].name, 'e')
|
self.assertEqual(self.b.current_playlist.tracks[4].name, 'e')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[5].name, 'f')
|
self.assertEqual(self.b.current_playlist.tracks[5].name, 'f')
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_moveid(self):
|
def test_moveid(self):
|
||||||
self.b.current_playlist.load(Playlist(tracks=[
|
self.b.current_playlist.load([
|
||||||
Track(name='a'), Track(name='b'), Track(name='c'),
|
Track(name='a'), Track(name='b'), Track(name='c'),
|
||||||
Track(name='d'), Track(name='e', id=137), Track(name='f')]))
|
Track(name='d'), Track(name='e'), Track(name='f'),
|
||||||
result = self.h.handle_request(u'moveid "137" "2"')
|
])
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[0].name, 'a')
|
result = self.h.handle_request(u'moveid "5" "2"')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[1].name, 'b')
|
self.assertEqual(self.b.current_playlist.tracks[0].name, 'a')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[2].name, 'e')
|
self.assertEqual(self.b.current_playlist.tracks[1].name, 'b')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[3].name, 'c')
|
self.assertEqual(self.b.current_playlist.tracks[2].name, 'e')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[4].name, 'd')
|
self.assertEqual(self.b.current_playlist.tracks[3].name, 'c')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[5].name, 'f')
|
self.assertEqual(self.b.current_playlist.tracks[4].name, 'd')
|
||||||
|
self.assertEqual(self.b.current_playlist.tracks[5].name, 'f')
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_playlist_returns_same_as_playlistinfo(self):
|
def test_playlist_returns_same_as_playlistinfo(self):
|
||||||
@ -715,54 +719,70 @@ class CurrentPlaylistHandlerTest(unittest.TestCase):
|
|||||||
self.assert_(u'ACK [0@0] {} Not implemented' in result)
|
self.assert_(u'ACK [0@0] {} Not implemented' in result)
|
||||||
|
|
||||||
def test_playlistfind_by_filename(self):
|
def test_playlistfind_by_filename(self):
|
||||||
result = self.h.handle_request(u'playlistfind "filename" "file:///dev/null"')
|
result = self.h.handle_request(
|
||||||
|
u'playlistfind "filename" "file:///dev/null"')
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_playlistfind_by_filename_without_quotes(self):
|
def test_playlistfind_by_filename_without_quotes(self):
|
||||||
result = self.h.handle_request(u'playlistfind filename "file:///dev/null"')
|
result = self.h.handle_request(
|
||||||
|
u'playlistfind filename "file:///dev/null"')
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_playlistfind_by_filename_in_current_playlist(self):
|
def test_playlistfind_by_filename_in_current_playlist(self):
|
||||||
self.b.current_playlist.playlist = Playlist(tracks=[
|
self.b.current_playlist.load([
|
||||||
Track(uri='file:///exists')])
|
Track(uri='file:///exists')])
|
||||||
result = self.h.handle_request(u'playlistfind filename "file:///exists"')
|
result = self.h.handle_request(
|
||||||
|
u'playlistfind filename "file:///exists"')
|
||||||
self.assert_(u'file: file:///exists' in result)
|
self.assert_(u'file: file:///exists' in result)
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_playlistid_without_songid(self):
|
def test_playlistid_without_songid(self):
|
||||||
self.b.current_playlist.load(Playlist(
|
self.b.current_playlist.load([Track(name='a'), Track(name='b')])
|
||||||
tracks=[Track(name='a', id=33), Track(name='b', id=38)]))
|
|
||||||
result = self.h.handle_request(u'playlistid')
|
result = self.h.handle_request(u'playlistid')
|
||||||
self.assert_(u'Title: a' in result)
|
self.assert_(u'Title: a' in result)
|
||||||
self.assert_(u'Id: 33' in result)
|
|
||||||
self.assert_(u'Title: b' in result)
|
self.assert_(u'Title: b' in result)
|
||||||
self.assert_(u'Id: 38' in result)
|
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_playlistid_with_songid(self):
|
def test_playlistid_with_songid(self):
|
||||||
self.b.current_playlist.load(Playlist(
|
self.b.current_playlist.load([Track(name='a'), Track(name='b')])
|
||||||
tracks=[Track(name='a', id=33), Track(name='b', id=38)]))
|
result = self.h.handle_request(u'playlistid "2"')
|
||||||
result = self.h.handle_request(u'playlistid "38"')
|
|
||||||
self.assert_(u'Title: a' not in result)
|
self.assert_(u'Title: a' not in result)
|
||||||
self.assert_(u'Id: 33' not in result)
|
self.assert_(u'Id: 1' not in result)
|
||||||
self.assert_(u'Title: b' in result)
|
self.assert_(u'Title: b' in result)
|
||||||
self.assert_(u'Id: 38' in result)
|
self.assert_(u'Id: 2' in result)
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_playlistid_with_not_existing_songid_fails(self):
|
def test_playlistid_with_not_existing_songid_fails(self):
|
||||||
self.b.current_playlist.load(Playlist(
|
self.b.current_playlist.load([Track(name='a'), Track(name='b')])
|
||||||
tracks=[Track(name='a', id=33), Track(name='b', id=38)]))
|
|
||||||
result = self.h.handle_request(u'playlistid "25"')
|
result = self.h.handle_request(u'playlistid "25"')
|
||||||
self.assertEqual(result[0], u'ACK [50@0] {playlistid} No such song')
|
self.assertEqual(result[0], u'ACK [50@0] {playlistid} No such song')
|
||||||
|
|
||||||
def test_playlistinfo_without_songpos_or_range(self):
|
def test_playlistinfo_without_songpos_or_range(self):
|
||||||
# FIXME testing just ok is not enough
|
self.b.current_playlist.load([
|
||||||
|
Track(name='a'), Track(name='b'), Track(name='c'),
|
||||||
|
Track(name='d'), Track(name='e'), Track(name='f'),
|
||||||
|
])
|
||||||
result = self.h.handle_request(u'playlistinfo')
|
result = self.h.handle_request(u'playlistinfo')
|
||||||
|
self.assert_(u'Title: a' in result)
|
||||||
|
self.assert_(u'Title: b' in result)
|
||||||
|
self.assert_(u'Title: c' in result)
|
||||||
|
self.assert_(u'Title: d' in result)
|
||||||
|
self.assert_(u'Title: e' in result)
|
||||||
|
self.assert_(u'Title: f' in result)
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_playlistinfo_with_songpos(self):
|
def test_playlistinfo_with_songpos(self):
|
||||||
# FIXME testing just ok is not enough
|
self.b.current_playlist.load([
|
||||||
result = self.h.handle_request(u'playlistinfo "5"')
|
Track(name='a'), Track(name='b'), Track(name='c'),
|
||||||
|
Track(name='d'), Track(name='e'), Track(name='f'),
|
||||||
|
])
|
||||||
|
result = self.h.handle_request(u'playlistinfo "4"')
|
||||||
|
self.assert_(u'Title: a' not in result)
|
||||||
|
self.assert_(u'Title: b' not in result)
|
||||||
|
self.assert_(u'Title: c' not in result)
|
||||||
|
self.assert_(u'Title: d' not in result)
|
||||||
|
self.assert_(u'Title: e' in result)
|
||||||
|
self.assert_(u'Title: f' not in result)
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_playlistinfo_with_negative_songpos_same_as_playlistinfo(self):
|
def test_playlistinfo_with_negative_songpos_same_as_playlistinfo(self):
|
||||||
@ -771,13 +791,39 @@ class CurrentPlaylistHandlerTest(unittest.TestCase):
|
|||||||
self.assertEqual(result1, result2)
|
self.assertEqual(result1, result2)
|
||||||
|
|
||||||
def test_playlistinfo_with_open_range(self):
|
def test_playlistinfo_with_open_range(self):
|
||||||
# FIXME testing just ok is not enough
|
self.b.current_playlist.load([
|
||||||
result = self.h.handle_request(u'playlistinfo "10:"')
|
Track(name='a'), Track(name='b'), Track(name='c'),
|
||||||
|
Track(name='d'), Track(name='e'), Track(name='f'),
|
||||||
|
])
|
||||||
|
result = self.h.handle_request(u'playlistinfo "2:"')
|
||||||
|
self.assert_(u'Title: a' not in result)
|
||||||
|
self.assert_(u'Title: b' not in result)
|
||||||
|
self.assert_(u'Title: c' in result)
|
||||||
|
self.assert_(u'Title: d' in result)
|
||||||
|
self.assert_(u'Title: e' in result)
|
||||||
|
self.assert_(u'Title: f' in result)
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_playlistinfo_with_closed_range(self):
|
def test_playlistinfo_with_closed_range(self):
|
||||||
# FIXME testing just ok is not enough
|
self.b.current_playlist.load([
|
||||||
|
Track(name='a'), Track(name='b'), Track(name='c'),
|
||||||
|
Track(name='d'), Track(name='e'), Track(name='f'),
|
||||||
|
])
|
||||||
|
result = self.h.handle_request(u'playlistinfo "2:4"')
|
||||||
|
self.assert_(u'Title: a' not in result)
|
||||||
|
self.assert_(u'Title: b' not in result)
|
||||||
|
self.assert_(u'Title: c' in result)
|
||||||
|
self.assert_(u'Title: d' in result)
|
||||||
|
self.assert_(u'Title: e' not in result)
|
||||||
|
self.assert_(u'Title: f' not in result)
|
||||||
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
|
def test_playlistinfo_with_too_high_start_of_range_returns_arg_error(self):
|
||||||
result = self.h.handle_request(u'playlistinfo "10:20"')
|
result = self.h.handle_request(u'playlistinfo "10:20"')
|
||||||
|
self.assert_(u'ACK [2@0] {playlistinfo} Bad song index' in result)
|
||||||
|
|
||||||
|
def test_playlistinfo_with_too_high_end_of_range_returns_ok(self):
|
||||||
|
result = self.h.handle_request(u'playlistinfo "0:20"')
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_playlistsearch(self):
|
def test_playlistsearch(self):
|
||||||
@ -785,8 +831,8 @@ class CurrentPlaylistHandlerTest(unittest.TestCase):
|
|||||||
self.assert_(u'ACK [0@0] {} Not implemented' in result)
|
self.assert_(u'ACK [0@0] {} Not implemented' in result)
|
||||||
|
|
||||||
def test_plchanges(self):
|
def test_plchanges(self):
|
||||||
self.b.current_playlist.load(Playlist(
|
self.b.current_playlist.load(
|
||||||
tracks=[Track(name='a'), Track(name='b'), Track(name='c')]))
|
[Track(name='a'), Track(name='b'), Track(name='c')])
|
||||||
result = self.h.handle_request(u'plchanges "0"')
|
result = self.h.handle_request(u'plchanges "0"')
|
||||||
self.assert_(u'Title: a' in result)
|
self.assert_(u'Title: a' in result)
|
||||||
self.assert_(u'Title: b' in result)
|
self.assert_(u'Title: b' in result)
|
||||||
@ -794,8 +840,8 @@ class CurrentPlaylistHandlerTest(unittest.TestCase):
|
|||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_plchangesposid(self):
|
def test_plchangesposid(self):
|
||||||
self.b.current_playlist.load(Playlist(
|
self.b.current_playlist.load(
|
||||||
tracks=[Track(id=11), Track(id=12), Track(id=13)]))
|
[Track(id=11), Track(id=12), Track(id=13)])
|
||||||
result = self.h.handle_request(u'plchangesposid "0"')
|
result = self.h.handle_request(u'plchangesposid "0"')
|
||||||
self.assert_(u'cpos: 0' in result)
|
self.assert_(u'cpos: 0' in result)
|
||||||
self.assert_(u'Id: 11' in result)
|
self.assert_(u'Id: 11' in result)
|
||||||
@ -806,64 +852,69 @@ class CurrentPlaylistHandlerTest(unittest.TestCase):
|
|||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_shuffle_without_range(self):
|
def test_shuffle_without_range(self):
|
||||||
self.b.current_playlist.load(Playlist(tracks=[
|
self.b.current_playlist.load([
|
||||||
Track(name='a'), Track(name='b'), Track(name='c'),
|
Track(name='a'), Track(name='b'), Track(name='c'),
|
||||||
Track(name='d'), Track(name='e'), Track(name='f')]))
|
Track(name='d'), Track(name='e'), Track(name='f'),
|
||||||
self.assertEqual(self.b.current_playlist.version, 1)
|
])
|
||||||
|
version = self.b.current_playlist.version
|
||||||
result = self.h.handle_request(u'shuffle')
|
result = self.h.handle_request(u'shuffle')
|
||||||
self.assertEqual(self.b.current_playlist.version, 2)
|
self.assert_(version < self.b.current_playlist.version)
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_shuffle_with_open_range(self):
|
def test_shuffle_with_open_range(self):
|
||||||
self.b.current_playlist.load(Playlist(tracks=[
|
self.b.current_playlist.load([
|
||||||
Track(name='a'), Track(name='b'), Track(name='c'),
|
Track(name='a'), Track(name='b'), Track(name='c'),
|
||||||
Track(name='d'), Track(name='e'), Track(name='f')]))
|
Track(name='d'), Track(name='e'), Track(name='f'),
|
||||||
self.assertEqual(self.b.current_playlist.version, 1)
|
])
|
||||||
|
version = self.b.current_playlist.version
|
||||||
result = self.h.handle_request(u'shuffle "4:"')
|
result = self.h.handle_request(u'shuffle "4:"')
|
||||||
self.assertEqual(self.b.current_playlist.version, 2)
|
self.assert_(version < self.b.current_playlist.version)
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[0].name, 'a')
|
self.assertEqual(self.b.current_playlist.tracks[0].name, 'a')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[1].name, 'b')
|
self.assertEqual(self.b.current_playlist.tracks[1].name, 'b')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[2].name, 'c')
|
self.assertEqual(self.b.current_playlist.tracks[2].name, 'c')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[3].name, 'd')
|
self.assertEqual(self.b.current_playlist.tracks[3].name, 'd')
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_shuffle_with_closed_range(self):
|
def test_shuffle_with_closed_range(self):
|
||||||
self.b.current_playlist.load(Playlist(tracks=[
|
self.b.current_playlist.load([
|
||||||
Track(name='a'), Track(name='b'), Track(name='c'),
|
Track(name='a'), Track(name='b'), Track(name='c'),
|
||||||
Track(name='d'), Track(name='e'), Track(name='f')]))
|
Track(name='d'), Track(name='e'), Track(name='f'),
|
||||||
self.assertEqual(self.b.current_playlist.version, 1)
|
])
|
||||||
|
version = self.b.current_playlist.version
|
||||||
result = self.h.handle_request(u'shuffle "1:3"')
|
result = self.h.handle_request(u'shuffle "1:3"')
|
||||||
self.assertEqual(self.b.current_playlist.version, 2)
|
self.assert_(version < self.b.current_playlist.version)
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[0].name, 'a')
|
self.assertEqual(self.b.current_playlist.tracks[0].name, 'a')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[3].name, 'd')
|
self.assertEqual(self.b.current_playlist.tracks[3].name, 'd')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[4].name, 'e')
|
self.assertEqual(self.b.current_playlist.tracks[4].name, 'e')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[5].name, 'f')
|
self.assertEqual(self.b.current_playlist.tracks[5].name, 'f')
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_swap(self):
|
def test_swap(self):
|
||||||
self.b.current_playlist.load(Playlist(tracks=[
|
self.b.current_playlist.load([
|
||||||
Track(name='a'), Track(name='b'), Track(name='c'),
|
Track(name='a'), Track(name='b'), Track(name='c'),
|
||||||
Track(name='d'), Track(name='e'), Track(name='f')]))
|
Track(name='d'), Track(name='e'), Track(name='f'),
|
||||||
|
])
|
||||||
result = self.h.handle_request(u'swap "1" "4"')
|
result = self.h.handle_request(u'swap "1" "4"')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[0].name, 'a')
|
self.assertEqual(self.b.current_playlist.tracks[0].name, 'a')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[1].name, 'e')
|
self.assertEqual(self.b.current_playlist.tracks[1].name, 'e')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[2].name, 'c')
|
self.assertEqual(self.b.current_playlist.tracks[2].name, 'c')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[3].name, 'd')
|
self.assertEqual(self.b.current_playlist.tracks[3].name, 'd')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[4].name, 'b')
|
self.assertEqual(self.b.current_playlist.tracks[4].name, 'b')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[5].name, 'f')
|
self.assertEqual(self.b.current_playlist.tracks[5].name, 'f')
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
def test_swapid(self):
|
def test_swapid(self):
|
||||||
self.b.current_playlist.load(Playlist(tracks=[
|
self.b.current_playlist.load([
|
||||||
Track(name='a'), Track(name='b', id=13), Track(name='c'),
|
Track(name='a'), Track(name='b'), Track(name='c'),
|
||||||
Track(name='d'), Track(name='e', id=29), Track(name='f')]))
|
Track(name='d'), Track(name='e'), Track(name='f'),
|
||||||
result = self.h.handle_request(u'swapid "13" "29"')
|
])
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[0].name, 'a')
|
result = self.h.handle_request(u'swapid "2" "5"')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[1].name, 'e')
|
self.assertEqual(self.b.current_playlist.tracks[0].name, 'a')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[2].name, 'c')
|
self.assertEqual(self.b.current_playlist.tracks[1].name, 'e')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[3].name, 'd')
|
self.assertEqual(self.b.current_playlist.tracks[2].name, 'c')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[4].name, 'b')
|
self.assertEqual(self.b.current_playlist.tracks[3].name, 'd')
|
||||||
self.assertEqual(self.b.current_playlist.playlist.tracks[5].name, 'f')
|
self.assertEqual(self.b.current_playlist.tracks[4].name, 'b')
|
||||||
|
self.assertEqual(self.b.current_playlist.tracks[5].name, 'f')
|
||||||
self.assert_(u'OK' in result)
|
self.assert_(u'OK' in result)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
57
tests/mpd/serializer_test.py
Normal file
57
tests/mpd/serializer_test.py
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import datetime as dt
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from mopidy.models import Album, Artist, Playlist, Track
|
||||||
|
from mopidy.mpd import serializer
|
||||||
|
|
||||||
|
class TrackMpdFormatTest(unittest.TestCase):
|
||||||
|
def test_mpd_format_for_empty_track(self):
|
||||||
|
result = serializer.track_to_mpd_format(Track())
|
||||||
|
self.assert_(('file', '') in result)
|
||||||
|
self.assert_(('Time', 0) in result)
|
||||||
|
self.assert_(('Artist', '') in result)
|
||||||
|
self.assert_(('Title', '') in result)
|
||||||
|
self.assert_(('Album', '') in result)
|
||||||
|
self.assert_(('Track', 0) in result)
|
||||||
|
self.assert_(('Date', '') in result)
|
||||||
|
|
||||||
|
def test_mpd_format_for_nonempty_track(self):
|
||||||
|
track = Track(
|
||||||
|
uri=u'a uri',
|
||||||
|
artists=[Artist(name=u'an artist')],
|
||||||
|
name=u'a name',
|
||||||
|
album=Album(name=u'an album', num_tracks=13),
|
||||||
|
track_no=7,
|
||||||
|
date=dt.date(1977, 1, 1),
|
||||||
|
length=137000,
|
||||||
|
)
|
||||||
|
result = serializer.track_to_mpd_format(track, position=9, cpid=122)
|
||||||
|
self.assert_(('file', 'a uri') in result)
|
||||||
|
self.assert_(('Time', 137) in result)
|
||||||
|
self.assert_(('Artist', 'an artist') in result)
|
||||||
|
self.assert_(('Title', 'a name') in result)
|
||||||
|
self.assert_(('Album', 'an album') in result)
|
||||||
|
self.assert_(('Track', '7/13') in result)
|
||||||
|
self.assert_(('Date', dt.date(1977, 1, 1)) in result)
|
||||||
|
self.assert_(('Pos', 9) in result)
|
||||||
|
self.assert_(('Id', 122) in result)
|
||||||
|
|
||||||
|
def test_mpd_format_artists(self):
|
||||||
|
track = Track(artists=[Artist(name=u'ABBA'), Artist(name=u'Beatles')])
|
||||||
|
self.assertEqual(serializer.track_artists_to_mpd_format(track),
|
||||||
|
u'ABBA, Beatles')
|
||||||
|
|
||||||
|
|
||||||
|
class PlaylistMpdFormatTest(unittest.TestCase):
|
||||||
|
def test_mpd_format(self):
|
||||||
|
playlist = Playlist(tracks=[
|
||||||
|
Track(track_no=1), Track(track_no=2), Track(track_no=3)])
|
||||||
|
result = serializer.playlist_to_mpd_format(playlist)
|
||||||
|
self.assertEqual(len(result), 3)
|
||||||
|
|
||||||
|
def test_mpd_format_with_range(self):
|
||||||
|
playlist = Playlist(tracks=[
|
||||||
|
Track(track_no=1), Track(track_no=2), Track(track_no=3)])
|
||||||
|
result = serializer.playlist_to_mpd_format(playlist, 1, 2)
|
||||||
|
self.assertEqual(len(result), 1)
|
||||||
|
self.assertEqual(dict(result[0])['Track'], 2)
|
||||||
Loading…
Reference in New Issue
Block a user