Skip to content

Commit

Permalink
Merge a7d0cae into 327e83e
Browse files Browse the repository at this point in the history
  • Loading branch information
richardambridge committed Jan 22, 2015
2 parents 327e83e + a7d0cae commit 85badc5
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 3 deletions.
12 changes: 11 additions & 1 deletion README.rst
Expand Up @@ -112,7 +112,17 @@ The following configuration values are available:

- ``spotify/allow_playlists``: Whether or not playlists should be exposed.
Defaults to ``true``.


- ``spotify/offline_playlists``: Specify which playlists from spotify you wish
to mark as 'Available offline'. The tracks for these playlists will be downloaded and available for play back when mopidy is unable to connect to spotify. The option takes a comma separated list of playlists to mark as offline. Items can be regular expression. Examples::

- offline_playlists = My play list, My list2
My play list and My list2 playlists will be marked offline
- offline_playlists = Foo.*
Match any playlist beginning with Foo (.* is a wild card)
- offline_playlists =
Empty list, no items will be marked offline
- ``spotify/search_album_count``: Maximum number of albums returned in search
results. Number between 0 and 200. Defaults to 20.

Expand Down
1 change: 1 addition & 0 deletions mopidy_spotify/__init__.py
Expand Up @@ -29,6 +29,7 @@ def get_config_schema(self):
schema['private_session'] = config.Boolean()

schema['timeout'] = config.Integer(minimum=0)
schema['offline_playlists'] = config.List(optional=True)

schema['cache_dir'] = config.Path(optional=True)
schema['settings_dir'] = config.Path()
Expand Down
1 change: 1 addition & 0 deletions mopidy_spotify/ext.conf
Expand Up @@ -6,6 +6,7 @@ bitrate = 160
volume_normalization = true
private_session = false
timeout = 10
offline_playlists =
cache_dir = $XDG_CACHE_DIR/mopidy/spotify
settings_dir = $XDG_CONFIG_DIR/mopidy/spotify
allow_network = true
Expand Down
48 changes: 48 additions & 0 deletions mopidy_spotify/playlists.py
@@ -1,6 +1,7 @@
from __future__ import unicode_literals

import logging
import re
import time

from mopidy import backend
Expand Down Expand Up @@ -61,10 +62,32 @@ def playlists(self):
if self._backend._session is None:
return []

offlinecount = self._backend._session.offline.num_playlists
logger.info("offline playlist count:%d", offlinecount)
if offlinecount > 0:
offlineS = self._backend._session.offline
syncstatus = offlineS.sync_status
if syncstatus:
queued = offlineS.sync_status.queued_tracks
done = offlineS.sync_status.done_tracks
errored = offlineS.sync_status.error_tracks
logger.info(
"Offline sync status: Queued= %d, Done=%d, Error=%d",
queued, done, errored)
else:
logger.info("Offline sync status: Not syncing")

seconds = offlineS.time_left
logger.info(
"Time until user must go online %d hours",
seconds / 3600)

if self._backend._session.playlist_container is None:
return []

start = time.time()
config = self._backend._config
offlineplaylists = config['spotify']['offline_playlists']

username = self._backend._session.user_name
result = []
Expand All @@ -84,6 +107,31 @@ def playlists(self):
if playlist is not None:
result.append(playlist)

logger.info("loaded playlist:%s offline status=%s tracks:%d",
playlist.name,
sp_playlist.offline_status,
len(sp_playlist.tracks))

offline = False
for pl in offlineplaylists:
p = re.compile(pl)
if p.match(sp_playlist.name):
offline = True
offlineStatus = sp_playlist.offline_status
if offline and offlineStatus == spotify.PlaylistOfflineStatus.NO:
logger.info("Offline playlist:%s,%s",
sp_playlist.name,
sp_playlist.offline_status)
sp_playlist.set_offline_mode(offline=True)
if not offline and \
offlineStatus != spotify.PlaylistOfflineStatus.NO:
logger.info("Online playlist:%s,%s",
sp_playlist.name,
sp_playlist.offline_status)
sp_playlist.set_offline_mode(offline=False)

info = self._backend._session.offline.tracks_to_sync
logger.info("Offline tracks to sync: %s", info)
# TODO Add starred playlist

logger.debug('Playlists fetched in %.3fs', time.time() - start)
Expand Down
1 change: 1 addition & 0 deletions tests/conftest.py
Expand Up @@ -26,6 +26,7 @@ def config():
'search_album_count': 20,
'search_artist_count': 10,
'search_track_count': 50,
'offline_playlists': ["Playlist1", "Foo", "Regex.*"],
'toplist_countries': ['GB', 'US'],
}
}
Expand Down
1 change: 1 addition & 0 deletions tests/test_extension.py
Expand Up @@ -31,6 +31,7 @@ def test_get_config_schema():
assert 'search_artist_count' in schema
assert 'search_track_count' in schema
assert 'toplist_countries' in schema
assert 'offline_playlists' in schema


def test_setup():
Expand Down
11 changes: 9 additions & 2 deletions tests/test_playlists.py
Expand Up @@ -22,6 +22,7 @@ def session_mock(sp_playlist_mock, sp_user_mock):
sp_playlist2_mock.is_loaded = True
sp_playlist2_mock.owner = mock.Mock(spec=spotify.User)
sp_playlist2_mock.owner.canonical_name = 'bob'
sp_playlist2_mock.offline_status = spotify.PlaylistOfflineStatus.NO
sp_playlist2_mock.link.uri = 'spotify:playlist:bob:baz'
sp_playlist2_mock.name = 'Baz'
sp_playlist2_mock.tracks = []
Expand Down Expand Up @@ -145,13 +146,19 @@ def test_lookup_of_playlist_with_other_owner(
assert playlist.name == 'Foo (by bob)'


def test_playlists_when_playlist_container_isnt_loaded(session_mock, provider):
def test_playlists_when_playlist_container_isnt_loaded(
session_mock, provider, config):
session_mock.playlist_container = None
session_mock.offline.time_left = 3600
provider._backend._config = config

assert provider.playlists == []


def test_playlists_with_folders_and_ignored_unloaded_playlist(provider):
def test_playlists_with_folders_and_ignored_unloaded_playlist(
session_mock, provider, config):
session_mock.offline.time_left = 3600
provider._backend._config = config
assert len(provider.playlists) == 2

assert provider.playlists[0].name == 'Foo'
Expand Down

0 comments on commit 85badc5

Please sign in to comment.