Let track{,s}_to_mpd_format() understand CpTrack objects

Thus the cpid and cpids kwargs can be removed, and lots of code doing
formatting of MPD responses can be simplified. This also reduces the
need for making full copies of the current playlist, which improves
performance.
This commit is contained in:
Stein Magnus Jodal 2011-12-28 00:30:38 +01:00
parent e0e3a1c518
commit 6f6e2c7fd7
4 changed files with 30 additions and 36 deletions

View File

@ -1,7 +1,8 @@
from mopidy.frontends.mpd.exceptions import (MpdArgError, MpdNoExistError,
MpdNotImplemented)
from mopidy.frontends.mpd.protocol import handle_request
from mopidy.frontends.mpd.translator import tracks_to_mpd_format
from mopidy.frontends.mpd.translator import (track_to_mpd_format,
tracks_to_mpd_format)
@handle_request(r'^add "(?P<uri>[^"]*)"$')
def add(context, uri):
@ -193,10 +194,9 @@ def playlistfind(context, tag, needle):
if tag == 'filename':
try:
cp_track = context.backend.current_playlist.get(uri=needle).get()
(cpid, track) = cp_track
position = context.backend.current_playlist.cp_tracks.get().index(
cp_track)
return track.mpd_format(cpid=cpid, position=position)
return track_to_mpd_format(cp_track, position=position)
except LookupError:
return None
raise MpdNotImplemented # TODO
@ -217,14 +217,12 @@ def playlistid(context, cpid=None):
cp_track = context.backend.current_playlist.get(cpid=cpid).get()
position = context.backend.current_playlist.cp_tracks.get().index(
cp_track)
return cp_track.track.mpd_format(position=position, cpid=cpid)
return track_to_mpd_format(cp_track, position=position)
except LookupError:
raise MpdNoExistError(u'No such song', command=u'playlistid')
else:
cpids = [ct[0] for ct in
context.backend.current_playlist.cp_tracks.get()]
return tracks_to_mpd_format(
context.backend.current_playlist.tracks.get(), cpids=cpids)
context.backend.current_playlist.cp_tracks.get())
@handle_request(r'^playlistinfo$')
@handle_request(r'^playlistinfo "(?P<songpos>-?\d+)"$')
@ -258,9 +256,7 @@ def playlistinfo(context, songpos=None,
# Hot code path: Fetch a single track, while avoiding deep-copying
# the entire playlist
cp_track = context.backend.current_playlist.get(cpid=songpos).get()
cpids = [cp_track.cpid]
tracks = [cp_track.track]
return tracks_to_mpd_format(tracks, 0, 1, cpids=cpids)
return tracks_to_mpd_format([cp_track], 0, 1)
else:
if start is None:
start = 0
@ -272,9 +268,7 @@ def playlistinfo(context, songpos=None,
if end > context.backend.current_playlist.length.get():
end = None
cp_tracks = context.backend.current_playlist.cp_tracks.get()
cpids = [cp_track.cpid for cp_track in cp_tracks]
tracks = [cp_track.track for cp_track in cp_tracks]
return tracks_to_mpd_format(tracks, start, end, cpids=cpids)
return tracks_to_mpd_format(cp_tracks, start, end)
@handle_request(r'^playlistsearch "(?P<tag>[^"]+)" "(?P<needle>[^"]+)"$')
@handle_request(r'^playlistsearch (?P<tag>\S+) "(?P<needle>[^"]+)"$')
@ -313,10 +307,8 @@ def plchanges(context, version):
"""
# XXX Naive implementation that returns all tracks as changed
if int(version) < context.backend.current_playlist.version:
cpids = [ct[0] for ct in
context.backend.current_playlist.cp_tracks.get()]
return tracks_to_mpd_format(
context.backend.current_playlist.tracks.get(), cpids=cpids)
context.backend.current_playlist.cp_tracks.get())
@handle_request(r'^plchangesposid "(?P<version>\d+)"$')
def plchangesposid(context, version):

View File

@ -1,8 +1,9 @@
import pykka.future
from mopidy.backends.base import PlaybackController
from mopidy.frontends.mpd.protocol import handle_request
from mopidy.frontends.mpd.exceptions import MpdNotImplemented
from mopidy.frontends.mpd.protocol import handle_request
from mopidy.frontends.mpd.translator import track_to_mpd_format
#: Subsystems that can be registered with idle command.
SUBSYSTEMS = ['database', 'mixer', 'options', 'output',
@ -32,9 +33,8 @@ def currentsong(context):
"""
current_cp_track = context.backend.playback.current_cp_track.get()
if current_cp_track is not None:
return current_cp_track.track.mpd_format(
position=context.backend.playback.current_playlist_position.get(),
cpid=current_cp_track.cpid)
position = context.backend.playback.current_playlist_position.get()
return track_to_mpd_format(current_cp_track, position=position)
@handle_request(r'^idle$')
@handle_request(r'^idle (?P<subsystems>.+)$')

View File

@ -2,26 +2,28 @@ import os
import re
from mopidy import settings
from mopidy.utils.path import mtime as get_mtime
from mopidy.frontends.mpd import protocol
from mopidy.utils.path import uri_to_path, split_path
from mopidy.models import CpTrack
from mopidy.utils.path import mtime as get_mtime, uri_to_path, split_path
def track_to_mpd_format(track, position=None, cpid=None):
def track_to_mpd_format(track, position=None):
"""
Format track for output to MPD client.
:param track: the track
:type track: :class:`mopidy.models.Track`
:type track: :class:`mopidy.models.Track` or :class:`mopidy.models.CpTrack`
:param position: track's position in playlist
:type position: integer
:param cpid: track's CPID (current playlist ID)
:type cpid: integer
:param key: if we should set key
:type key: boolean
:param mtime: if we should set mtime
:type mtime: boolean
:rtype: list of two-tuples
"""
if isinstance(track, CpTrack):
(cpid, track) = track
else:
(cpid, track) = (None, track)
result = [
('file', track.uri or ''),
('Time', track.length and (track.length // 1000) or 0),
@ -88,14 +90,15 @@ def artists_to_mpd_format(artists):
artists.sort(key=lambda a: a.name)
return u', '.join([a.name for a in artists if a.name])
def tracks_to_mpd_format(tracks, start=0, end=None, cpids=None):
def tracks_to_mpd_format(tracks, start=0, end=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`
:type tracks: list of :class:`mopidy.models.Track` or
:class:`mopidy.models.CpTrack`
: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
@ -106,11 +109,10 @@ def tracks_to_mpd_format(tracks, start=0, end=None, cpids=None):
end = len(tracks)
tracks = tracks[start:end]
positions = range(start, end)
cpids = cpids and cpids[start:end] or [None for _ in tracks]
assert len(tracks) == len(positions) == len(cpids)
assert len(tracks) == len(positions)
result = []
for track, position, cpid in zip(tracks, positions, cpids):
result.append(track_to_mpd_format(track, position, cpid))
for track, position in zip(tracks, positions):
result.append(track_to_mpd_format(track, position))
return result
def playlist_to_mpd_format(playlist, *args, **kwargs):

View File

@ -4,7 +4,7 @@ import os
from mopidy import settings
from mopidy.utils.path import mtime, uri_to_path
from mopidy.frontends.mpd import translator, protocol
from mopidy.models import Album, Artist, Playlist, Track
from mopidy.models import Album, Artist, CpTrack, Playlist, Track
from tests import unittest
@ -45,17 +45,17 @@ class TrackMpdFormatTest(unittest.TestCase):
self.assert_(('Pos', 1) not in result)
def test_track_to_mpd_format_with_cpid(self):
result = translator.track_to_mpd_format(Track(), cpid=1)
result = translator.track_to_mpd_format(CpTrack(1, Track()))
self.assert_(('Id', 1) not in result)
def test_track_to_mpd_format_with_position_and_cpid(self):
result = translator.track_to_mpd_format(Track(), position=1, cpid=2)
result = translator.track_to_mpd_format(CpTrack(2, Track()), position=1)
self.assert_(('Pos', 1) in result)
self.assert_(('Id', 2) in result)
def test_track_to_mpd_format_for_nonempty_track(self):
result = translator.track_to_mpd_format(
self.track, position=9, cpid=122)
CpTrack(122, self.track), position=9)
self.assert_(('file', 'a uri') in result)
self.assert_(('Time', 137) in result)
self.assert_(('Artist', 'an artist') in result)