diff --git a/docs/changelog.rst b/docs/changelog.rst index 818619e4..c966cc45 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -4,6 +4,18 @@ Changelog This changelog is used to track all major changes to Mopidy. +v1.0.8 (2015-07-22) +=================== + +Bug fix release. + +- Fix reversal of ``Title`` and ``Name`` in MPD protocol (Fixes: :issue:`1212` + PR: :issue:`1214`) + +- Fix crash if an M3U file in the :confval:`m3u/playlist_dir` directory has a + file name not decodable with the current file system encoding. (Fixes: + :issue:`1209`) + v1.0.7 (2015-06-26) =================== diff --git a/docs/ext/material_webclient.png b/docs/ext/material_webclient.png new file mode 100644 index 00000000..1f8b13f8 Binary files /dev/null and b/docs/ext/material_webclient.png differ diff --git a/docs/ext/mixers.rst b/docs/ext/mixers.rst index f934efce..88fd27dd 100644 --- a/docs/ext/mixers.rst +++ b/docs/ext/mixers.rst @@ -29,6 +29,14 @@ Extension for controlling volume using an external Arcam amplifier. Developed and tested with an Arcam AVR-300. +Mopidy-dam1021 +============== + +https://github.com/fortaa/mopidy-dam1021 + +Extension for controlling volume using a dam1021 DAC device. + + Mopidy-NAD ========== diff --git a/docs/ext/web.rst b/docs/ext/web.rst index 7355dbf9..f6a2110a 100644 --- a/docs/ext/web.rst +++ b/docs/ext/web.rst @@ -48,6 +48,22 @@ To install, run:: pip install Mopidy-Local-Images +Mopidy-Material-Webclient +========================= + +https://github.com/matgallacher/mopidy-material-webclient + +A Mopidy web client with an Android Material design feel. + +.. image:: /ext/material_webclient.png + :width: 960 + :height: 520 + +To install, run:: + + pip install Mopidy-Material-Webclient + + Mopidy-Mobile ============= diff --git a/mopidy/__init__.py b/mopidy/__init__.py index 7ab3b9e6..e9f2e6c3 100644 --- a/mopidy/__init__.py +++ b/mopidy/__init__.py @@ -30,4 +30,4 @@ except ImportError: warnings.filterwarnings('ignore', 'could not open display') -__version__ = '1.0.7' +__version__ = '1.0.8' diff --git a/mopidy/m3u/playlists.py b/mopidy/m3u/playlists.py index 8800e468..33281129 100644 --- a/mopidy/m3u/playlists.py +++ b/mopidy/m3u/playlists.py @@ -66,7 +66,7 @@ class M3UPlaylistsProvider(backend.PlaylistsProvider): for path in glob.glob(os.path.join(self._playlists_dir, b'*.m3u')): relpath = os.path.basename(path) uri = translator.path_to_playlist_uri(relpath) - name = os.path.splitext(relpath)[0].decode(encoding) + name = os.path.splitext(relpath)[0].decode(encoding, 'replace') tracks = translator.parse_m3u(path) playlists[uri] = Playlist(uri=uri, name=name, tracks=tracks) diff --git a/mopidy/mpd/translator.py b/mopidy/mpd/translator.py index 8359f86b..b1c139b7 100644 --- a/mopidy/mpd/translator.py +++ b/mopidy/mpd/translator.py @@ -38,12 +38,15 @@ def track_to_mpd_format(track, position=None, stream_title=None): # https://github.com/mopidy/mopidy/issues/923#issuecomment-79584110 ('Time', track.length and (track.length // 1000) or 0), ('Artist', artists_to_mpd_format(track.artists)), - ('Title', track.name or ''), ('Album', track.album and track.album.name or ''), ] - if stream_title: - result.append(('Name', stream_title)) + if stream_title is not None: + result.append(('Title', stream_title)) + if track.name: + result.append(('Name', track.name)) + else: + result.append(('Title', track.name or '')) if track.date: result.append(('Date', track.date)) diff --git a/tests/core/test_library.py b/tests/core/test_library.py index 51313daa..c49809cf 100644 --- a/tests/core/test_library.py +++ b/tests/core/test_library.py @@ -204,7 +204,8 @@ class CoreLibraryTest(unittest.TestCase): self.core.library.refresh() self.library1.refresh.assert_called_once_with(None) - self.library2.refresh.assert_called_twice_with(None) + self.library2.refresh.assert_called_with(None) + self.assertEqual(self.library2.refresh.call_count, 2) def test_find_exact_combines_results_from_all_backends(self): track1 = Track(uri='dummy1:a') diff --git a/tests/m3u/test_playlists.py b/tests/m3u/test_playlists.py index b7ac827f..31d8f100 100644 --- a/tests/m3u/test_playlists.py +++ b/tests/m3u/test_playlists.py @@ -1,9 +1,12 @@ +# encoding: utf-8 + from __future__ import absolute_import, unicode_literals import os import shutil import tempfile import unittest +import urllib import pykka @@ -108,6 +111,7 @@ class M3UPlaylistsProviderTest(unittest.TestCase): with open(path) as f: m3u = f.read().splitlines() + self.assertEqual(['#EXTM3U', '#EXTINF:60,Test', track.uri], m3u) def test_latin1_playlist_contents_is_written_to_disk(self): @@ -142,9 +146,17 @@ class M3UPlaylistsProviderTest(unittest.TestCase): self.assertEqual(playlist.name, result.name) self.assertEqual(track.uri, result.tracks[0].uri) - @unittest.SkipTest - def test_santitising_of_playlist_filenames(self): - pass + def test_load_playlist_with_nonfilesystem_encoding_of_filename(self): + uri = 'm3u:%s.m3u' % urllib.quote('øæå'.encode('latin-1')) + path = playlist_uri_to_path(uri, self.playlists_dir) + with open(path, 'wb+') as f: + f.write(b'#EXTM3U\n') + + self.core.playlists.refresh() + + self.assertEqual(len(self.core.playlists.as_list()), 1) + result = self.core.playlists.lookup(uri) + self.assertEqual('\ufffd\ufffd\ufffd', result.name) @unittest.SkipTest def test_playlists_dir_is_created(self): diff --git a/tests/mpd/protocol/test_connection.py b/tests/mpd/protocol/test_connection.py index da25153d..e25402bd 100644 --- a/tests/mpd/protocol/test_connection.py +++ b/tests/mpd/protocol/test_connection.py @@ -9,7 +9,7 @@ class ConnectionHandlerTest(protocol.BaseTestCase): def test_close_closes_the_client_connection(self): with patch.object(self.session, 'close') as close_mock: self.send_request('close') - close_mock.assertEqualResponsecalled_once_with() + close_mock.assert_called_once_with() self.assertEqualResponse('OK') def test_empty_request(self): diff --git a/tests/test_version.py b/tests/test_version.py index f8afd3db..c0c2d9e6 100644 --- a/tests/test_version.py +++ b/tests/test_version.py @@ -62,5 +62,6 @@ class VersionTest(unittest.TestCase): self.assertVersionLess('1.0.3', '1.0.4') self.assertVersionLess('1.0.4', '1.0.5') self.assertVersionLess('1.0.5', '1.0.6') - self.assertVersionLess('1.0.6', __version__) - self.assertVersionLess(__version__, '1.0.8') + self.assertVersionLess('1.0.6', '1.0.7') + self.assertVersionLess('1.0.7', __version__) + self.assertVersionLess(__version__, '1.0.9')