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:
parent
e0e3a1c518
commit
6f6e2c7fd7
@ -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):
|
||||
|
||||
@ -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>.+)$')
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user