diff --git a/docs/changelog.rst b/docs/changelog.rst index 941dcd7c..e31d1b9c 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -69,6 +69,19 @@ Internal changes :issue:`1115`) +v1.0.6 (2015-06-25) +=================== + +Bug fix release. + +- Core/MPD/Local: Add support for ``title`` in + :meth:`mopidy.core.LibraryController.get_distinct`. (Fixes: :issue:`1181`, + PR: :issue:`1183`) + +- Core: Make sure track changes make it to audio while paused. + (Fixes: :issue:`1177`, PR: :issue:`1185`) + + v1.0.5 (2015-05-19) =================== diff --git a/mopidy/__init__.py b/mopidy/__init__.py index 9ea6664e..ce01a0f1 100644 --- a/mopidy/__init__.py +++ b/mopidy/__init__.py @@ -14,4 +14,4 @@ if not (2, 7) <= sys.version_info < (3,): warnings.filterwarnings('ignore', 'could not open display') -__version__ = '1.0.5' +__version__ = '1.0.6' diff --git a/mopidy/backend.py b/mopidy/backend.py index 0cea0f85..fd91044f 100644 --- a/mopidy/backend.py +++ b/mopidy/backend.py @@ -103,6 +103,9 @@ class LibraryProvider(object): *MAY be implemented by subclass.* Default implementation will simply return an empty set. + + Note that backends should always return an empty set for unexpected + field types. """ return set() diff --git a/mopidy/core/library.py b/mopidy/core/library.py index f801836a..c300fbb9 100644 --- a/mopidy/core/library.py +++ b/mopidy/core/library.py @@ -123,8 +123,8 @@ class LibraryController(object): protocol supports in a more sane fashion. Other frontends are not recommended to use this method. - :param string field: One of ``artist``, ``albumartist``, ``album``, - ``composer``, ``performer``, ``date`` or ``genre``. + :param string field: One of ``track``, ``artist``, ``albumartist``, + ``album``, ``composer``, ``performer``, ``date`` or ``genre``. :param dict query: Query to use for limiting results, see :meth:`search` for details about the query format. :rtype: set of values corresponding to the requested field type. diff --git a/mopidy/core/playback.py b/mopidy/core/playback.py index 6d17620a..0350c763 100644 --- a/mopidy/core/playback.py +++ b/mopidy/core/playback.py @@ -207,6 +207,12 @@ class PlaybackController(object): if old_state == PlaybackState.PLAYING: self._play(on_error_step=on_error_step) elif old_state == PlaybackState.PAUSED: + # NOTE: this is just a quick hack to fix #1177 as this code has + # already been killed in the gapless branch. + backend = self._get_backend() + if backend: + backend.playback.prepare_change() + backend.playback.change_track(tl_track.track).get() self.pause() # TODO: this is not really end of track, this is on_need_next_track diff --git a/mopidy/local/json.py b/mopidy/local/json.py index 715b5c5d..bc2ca775 100644 --- a/mopidy/local/json.py +++ b/mopidy/local/json.py @@ -141,7 +141,10 @@ class JsonLibrary(local.Library): return [] def get_distinct(self, field, query=None): - if field == 'artist': + if field == 'track': + def distinct(track): + return {track.name} + elif field == 'artist': def distinct(track): return {a.name for a in track.artists} elif field == 'albumartist': diff --git a/mopidy/mpd/protocol/music_db.py b/mopidy/mpd/protocol/music_db.py index 1b3a3ee7..16375eb7 100644 --- a/mopidy/mpd/protocol/music_db.py +++ b/mopidy/mpd/protocol/music_db.py @@ -23,6 +23,7 @@ _SEARCH_MAPPING = { 'track': 'track_no'} _LIST_MAPPING = { + 'title': 'track', 'album': 'album', 'albumartist': 'albumartist', 'artist': 'artist', @@ -32,6 +33,7 @@ _LIST_MAPPING = { 'performer': 'performer'} _LIST_NAME_MAPPING = { + 'title': 'Title', 'album': 'Album', 'albumartist': 'AlbumArtist', 'artist': 'Artist', diff --git a/tests/core/test_playback.py b/tests/core/test_playback.py index 67f5841e..76054684 100644 --- a/tests/core/test_playback.py +++ b/tests/core/test_playback.py @@ -708,6 +708,7 @@ class CorePlaybackWithOldBackendTest(unittest.TestCase): c = core.Core(mixer=None, backends=[b]) c.tracklist.add(uris=['dummy1:a']) c.playback.play() # No TypeError == test passed. + b.playback.play.assert_called_once_with() class TestPlay(unittest.TestCase): @@ -727,3 +728,26 @@ class TestPlay(unittest.TestCase): self.core.playback.play(tlid=self.tl_tracks[1].tlid) self.backend.playback.change_track.assert_called_once_with( self.tl_tracks[1].track) + + +class Bug1177RegressionTest(unittest.TestCase): + def test(self): + b = mock.Mock() + b.uri_schemes.get.return_value = ['dummy'] + b.playback = mock.Mock(spec=backend.PlaybackProvider) + b.playback.change_track.return_value.get.return_value = True + b.playback.play.return_value.get.return_value = True + + track1 = Track(uri='dummy:a', length=40000) + track2 = Track(uri='dummy:b', length=40000) + + c = core.Core(mixer=None, backends=[b]) + c.tracklist.add([track1, track2]) + + c.playback.play() + b.playback.change_track.assert_called_once_with(track1) + b.playback.change_track.reset_mock() + + c.playback.pause() + c.playback.next() + b.playback.change_track.assert_called_once_with(track2) diff --git a/tests/mpd/protocol/test_music_db.py b/tests/mpd/protocol/test_music_db.py index acdfbe13..b1f5f7c8 100644 --- a/tests/mpd/protocol/test_music_db.py +++ b/tests/mpd/protocol/test_music_db.py @@ -646,6 +646,12 @@ class MusicDatabaseListTest(protocol.BaseTestCase): self.send_request('list "foo"') self.assertEqualResponse('ACK [2@0] {list} incorrect arguments') + # Track title + + def test_list_title(self): + self.send_request('list "title"') + self.assertInResponse('OK') + # Artist def test_list_artist_with_quotes(self): diff --git a/tests/test_version.py b/tests/test_version.py index 0e5c7c7d..511d8eb9 100644 --- a/tests/test_version.py +++ b/tests/test_version.py @@ -61,5 +61,6 @@ class VersionTest(unittest.TestCase): self.assertVersionLess('1.0.1', '1.0.2') self.assertVersionLess('1.0.2', '1.0.3') self.assertVersionLess('1.0.3', '1.0.4') - self.assertVersionLess('1.0.4', __version__) - self.assertVersionLess(__version__, '1.0.6') + self.assertVersionLess('1.0.4', '1.0.5') + self.assertVersionLess('1.0.5', __version__) + self.assertVersionLess(__version__, '1.0.7')