diff --git a/mopidy/backends/local/actor.py b/mopidy/backends/local/actor.py index 8f53af4d..b73c53e2 100644 --- a/mopidy/backends/local/actor.py +++ b/mopidy/backends/local/actor.py @@ -8,7 +8,7 @@ import pykka from mopidy.backends import base from mopidy.utils import encoding, path -from .library import LocalLibraryProvider +from .library import LocalLibraryProvider, LocalLibraryUpdateProvider from .playlists import LocalPlaylistsProvider logger = logging.getLogger('mopidy.backends.local') @@ -23,6 +23,7 @@ class LocalBackend(pykka.ThreadingActor, base.Backend): self.check_dirs_and_files() self.library = LocalLibraryProvider(backend=self) + self.updater = LocalLibraryUpdateProvider(backend=self) self.playback = base.BasePlaybackProvider(audio=audio, backend=self) self.playlists = LocalPlaylistsProvider(backend=self) diff --git a/mopidy/backends/local/library.py b/mopidy/backends/local/library.py index 669e72d7..43768cd4 100644 --- a/mopidy/backends/local/library.py +++ b/mopidy/backends/local/library.py @@ -1,7 +1,11 @@ from __future__ import unicode_literals import logging +import os +import tempfile + from mopidy.backends import base +from mopidy.frontends.mpd import translator as mpd_translator from mopidy.models import Album, SearchResult from .translator import parse_mpd_tag_cache @@ -127,3 +131,43 @@ class LocalLibraryProvider(base.BaseLibraryProvider): for value in values: if not value: raise LookupError('Missing query') + + +# TODO: rename and move to tagcache extension. +class LocalLibraryUpdateProvider(base.BaseLibraryProvider): + def __init__(self, *args, **kwargs): + super(LocalLibraryUpdateProvider, self).__init__(*args, **kwargs) + self._tracks = {} + self._media_dir = self.backend.config['local']['media_dir'] + self._tag_cache_file = self.backend.config['local']['tag_cache_file'] + + def load(self): + tracks = parse_mpd_tag_cache(self._tag_cache_file, self._media_dir) + for track in tracks: + self._tracks[track.uri] = track + return tracks + + def add(self, track): + self._tracks[track.uri] = track + + def remove(self, uri): + if uri in self._tracks: + del self._tracks[uri] + + def commit(self): + directory, basename = os.path.split(self._tag_cache_file) + tmp = tempfile.NamedTemporaryFile( + prefix=basename + '.', dir=directory, delete=False) + + try: + for row in mpd_translator.tracks_to_tag_cache_format( + self._tracks.values(), self._media_dir): + if len(row) == 1: + tmp.write(('%s\n' % row).encode('utf-8')) + else: + tmp.write(('%s: %s\n' % row).encode('utf-8')) + + os.rename(tmp.name, self._tag_cache_file) + finally: + if os.path.exists(tmp.name): + os.remove(tmp.name) diff --git a/mopidy/frontends/mpd/translator.py b/mopidy/frontends/mpd/translator.py index b646732f..8e9d12e0 100644 --- a/mopidy/frontends/mpd/translator.py +++ b/mopidy/frontends/mpd/translator.py @@ -10,6 +10,8 @@ from mopidy.frontends.mpd.exceptions import MpdArgError from mopidy.models import TlTrack from mopidy.utils.path import mtime as get_mtime, uri_to_path, split_path +# TODO: special handling of local:// uri scheme + def track_to_mpd_format(track, position=None): """ @@ -213,6 +215,7 @@ def query_from_mpd_search_format(mpd_query): return query +# TODO: move to tagcache backend. def tracks_to_tag_cache_format(tracks, media_dir): """ Format list of tracks for output to MPD tag cache @@ -234,6 +237,7 @@ def tracks_to_tag_cache_format(tracks, media_dir): _add_to_tag_cache(result, dirs, files, media_dir) return result + # TODO: bytes only def _add_to_tag_cache(result, dirs, files, media_dir): base_path = media_dir.encode('utf-8')