mopidy/mopidy/frontends/mpd/translator.py
2010-10-29 23:06:58 +02:00

138 lines
4.3 KiB
Python

import os
import re
from mopidy import settings
from mopidy.frontends.mpd import protocol
from mopidy.utils.path import path_to_uri, uri_to_path, split_path
def track_to_mpd_format(track, position=None, cpid=None, key=False, mtime=False):
"""
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
: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
"""
result = [
('file', uri_to_mpd_relative_path(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))
if key and track.uri:
result.insert(0, ('key', os.path.basename(track.uri)))
if mtime and track.uri:
mtime = os.stat(uri_to_path(track.uri)).st_mtime
result.append(('mtime', int(mtime)))
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 _ 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)
def uri_to_mpd_relative_path(uri):
"""
Strip uri and LOCAL_MUSIC_FOLDER part of uri.
:param uri: the uri
:type uri: string
:rtype: string
"""
if uri is None:
return ''
path = path_to_uri(settings.LOCAL_MUSIC_FOLDER)
return re.sub('^' + re.escape(path), '', uri)
def tracks_to_tag_cache_format(tracks):
"""
Format list of tracks for output to MPD tag cache
:param tracks: the tracks
:type tracks: list of :class:`mopidy.models.Track`
:rtype: list of lists of two-tuples
"""
result = [
('info_begin',),
('mpd_version', protocol.VERSION),
('fs_charset', protocol.ENCODING),
('info_end',)
]
result.append(('songList begin',))
for track in tracks:
result.extend(track_to_mpd_format(track, key=True))
result.append(('songList end',))
return result
def tracks_to_directory_tree(tracks):
directories = ({}, [])
for track in tracks:
folder = os.path.dirname(uri_to_path(track.uri))
current = directories
for part in split_path(folder):
if part not in current[0]:
current[0][part] = ({}, [])
current = current[0][part]
current[1].append(track)
return directories