diff --git a/mopidy/backends/__init__.py b/mopidy/backends/__init__.py index fc4eb6f4..f7705f64 100644 --- a/mopidy/backends/__init__.py +++ b/mopidy/backends/__init__.py @@ -46,10 +46,10 @@ class BaseBackend(object): uri_handlers = [] def destroy(self): - ''' + """ Call destroy on all sub-components in backend so that they can cleanup after themselves. - ''' + """ if self.current_playlist: self.current_playlist.destroy() @@ -227,7 +227,7 @@ class BaseCurrentPlaylistController(object): self.playlist = self.playlist.with_(tracks=before+shuffled+after) def destroy(self): - '''Cleanup after component''' + """Cleanup after component""" pass @@ -284,7 +284,7 @@ class BaseLibraryController(object): raise NotImplementedError def destroy(self): - '''Cleanup after component''' + """Cleanup after component""" pass @@ -604,7 +604,7 @@ class BasePlaybackController(object): raise NotImplementedError def destroy(self): - '''Cleanup after component''' + """Cleanup after component""" pass @@ -720,5 +720,5 @@ class BaseStoredPlaylistsController(object): return filter(lambda p: query in p.name, self._playlists) def destroy(self): - '''Cleanup after component''' + """Cleanup after component""" pass diff --git a/mopidy/backends/gstreamer.py b/mopidy/backends/gstreamer.py index 567e7acf..8a79ff11 100644 --- a/mopidy/backends/gstreamer.py +++ b/mopidy/backends/gstreamer.py @@ -9,12 +9,14 @@ pygst.require('0.10') import gst import logging import os +import glob import shutil import threading from mopidy.backends import * -from mopidy.models import Playlist +from mopidy.models import Playlist, Track from mopidy import settings +from mopidy.utils import m3u_to_uris logger = logging.getLogger(u'backends.gstreamer') @@ -117,8 +119,23 @@ class GStreamerPlaybackController(BasePlaybackController): class GStreamerStoredPlaylistsController(BaseStoredPlaylistsController): def __init__(self, *args): super(GStreamerStoredPlaylistsController, self).__init__(*args) - # FIXME need test that ensures that folder is created self._folder = os.path.expanduser(settings.PLAYLIST_FOLDER) + self.refresh() + + def refresh(self): + playlists = [] + + for m3u in glob.glob(os.path.join(self._folder, '*.m3u')): + name = os.path.basename(m3u)[:len('.m3u')] + track_uris = m3u_to_uris(m3u) + tracks = map(lambda u: Track(uri=u), track_uris) + playlist = Playlist(tracks=tracks, name=name) + + # FIXME playlist name needs better handling + + playlists.append(playlist) + + self.playlists = playlists def create(self, name): playlist = Playlist(name=name) @@ -149,6 +166,13 @@ class GStreamerStoredPlaylistsController(BaseStoredPlaylistsController): shutil.move(src, dst) def save(self, playlist): - file = os.path.join(self._folder, playlist.name + '.m3u') - open(file, 'w').close() + file_path = os.path.join(self._folder, playlist.name + '.m3u') + + with open(file_path, 'w') as file: + for track in playlist.tracks: + if track.uri.startswith('file:'): + file.write(track.uri[len('file:'):] + '\n') + else: + file.write(track.uri + '\n') + self._playlists.append(playlist) diff --git a/mopidy/utils.py b/mopidy/utils.py index 0275e055..f0d972ee 100644 --- a/mopidy/utils.py +++ b/mopidy/utils.py @@ -97,7 +97,7 @@ def m3u_to_uris(file_path): """ Convert M3U file list of uris - Example M3U data: + Example M3U data:: # This is a comment Alternative\Band - Song.mp3 diff --git a/tests/backends/gstreamer_test.py b/tests/backends/gstreamer_test.py index 78b1f7cb..71e92a53 100644 --- a/tests/backends/gstreamer_test.py +++ b/tests/backends/gstreamer_test.py @@ -2,11 +2,13 @@ import unittest import os import urllib -from mopidy.models import Playlist, Track -from mopidy.backends.gstreamer import GStreamerBackend from mopidy import settings +from mopidy.backends.gstreamer import GStreamerBackend +from mopidy.mixers.dummy import DummyMixer +from mopidy.models import Playlist, Track from tests.backends.base import * +from tests import SkipTest folder = os.path.dirname(__file__) folder = os.path.join(folder, '..', 'data') @@ -78,6 +80,46 @@ class GStreamerBackendStoredPlaylistsControllerTest(BaseStoredPlaylistsControlle self.assert_(not os.path.exists(file1)) self.assert_(os.path.exists(file2)) + def test_playlist_contents_get_written_to_disk(self): + track = Track(uri=generate_song(1)) + uri = track.uri[len('file:'):] + playlist = Playlist(tracks=[track], name='test') + file_path = os.path.join(settings.PLAYLIST_FOLDER, 'test.m3u') + + self.stored.save(playlist) + + with open(file_path) as file: + contents = file.read() + + self.assertEqual(uri, contents.strip()) + + def test_playlists_are_loaded_at_startup(self): + track = Track(uri=generate_song(1)) + uri = track.uri[len('file:'):] + playlist = Playlist(tracks=[track], name='test') + file_path = os.path.join(settings.PLAYLIST_FOLDER, 'test.m3u') + + self.stored.save(playlist) + + self.backend.destroy() + self.backend = self.backend_class(mixer=DummyMixer()) + self.stored = self.backend.stored_playlists + + self.assert_(self.stored.playlists) + self.assertEqual('test', self.stored.playlists[0].name) + self.assertEqual(track.uri, self.stored.playlists[0].tracks[0].uri) + + def test_santitising_of_playlist_filenames(self): + raise SkipTest + + def test_playlist_folder_is_createad(self): + raise SkipTest + + def test_create_sets_playlist_uri(self): + raise SkipTest + + def test_save_sets_playlist_uri(self): + raise SkipTest if __name__ == '__main__': unittest.main()