diff --git a/MANIFEST.in b/MANIFEST.in index 1c126f85..033c51f2 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,4 @@ -include LICENSE pylintrc *.rst data/mopidy.desktop +include LICENSE pylintrc *.rst *.ini data/mopidy.desktop include mopidy/backends/spotify/spotify_appkey.key recursive-include docs * prune docs/_build diff --git a/docs/changes.rst b/docs/changes.rst index dbdc9d3b..12da4e6d 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -5,11 +5,35 @@ Changes This change log is used to track all major changes to Mopidy. -0.4.0 (in development) +0.5.0 (in development) ====================== No description yet. +**Changes** + +No changes yet. + + +0.4.0 (2011-04-27) +================== + +Mopidy 0.4.0 is another release without major feature additions. In 0.4.0 we've +fixed a bunch of issues and bugs, with the help of several new contributors +who are credited in the changelog below. The major change of 0.4.0 is an +internal refactoring which clears way for future features, and which also make +Mopidy work on Python 2.7. In other words, Mopidy 0.4.0 works on Ubuntu 11.04 +and Arch Linux. + +Please note that 0.4.0 requires some updated dependencies, as listed under +*Important changes* below. Also, the known bug in the Spotify playlist +loading from Mopidy 0.3.0 is still present. + +.. warning:: Known bug in Spotify playlist loading + + There is a known bug in the loading of Spotify playlists. To avoid the bug, + follow the simple workaround described at :issue:`59`. + **Important changes** @@ -30,7 +54,7 @@ No description yet. - Mopidy now use Pykka actors for thread management and inter-thread communication. The immediate advantage of this is that Mopidy now works on - Python 2.7. (Fixes: :issue:`66`) + Python 2.7, which is the default on e.g. Ubuntu 11.04. (Fixes: :issue:`66`) - Spotify backend: @@ -40,6 +64,11 @@ No description yet. - Better error messages on wrong login or network problems. Thanks to Antoine Pierlot-Garcin for patches to Mopidy and Pyspotify. (Fixes: :issue:`77`) + - Reduce log level for trivial log messages from warning to info. (Fixes: + :issue:`71`) + + - Pause playback on network connection errors. (Fixes: :issue:`65`) + - Local backend: - Fix crash in :command:`mopidy-scan` if a track has no artist name. Thanks @@ -61,11 +90,29 @@ No description yet. - Fix bug where ``status`` returned ``song: None``, which caused MPDroid to crash. (Fixes: :issue:`69`) + - Gracefully fallback to IPv4 sockets on systems that supports IPv6, but has + turned it off. (Fixes: :issue:`75`) + +- GStreamer output: + + - Use ``uridecodebin`` for playing audio from both Spotify and the local + backend. This contributes to support for multiple backends simultaneously. + - Settings: - Fix crash on ``--list-settings`` on clean installation. Thanks to Martins Grunskis for the bug report and patch. (Fixes: :issue:`63`) +- Packaging: + + - Replace test data symlinks with real files to avoid symlink issues when + installing with pip. (Fixes: :issue:`68`) + +- Debugging: + + - Include platform, architecture, Linux distribution, and Python version in + the debug log, to ease debugging of issues with attached debug logs. + 0.3.1 (2010-01-22) ================== diff --git a/docs/conf.py b/docs/conf.py index 4587c16d..7ae3c126 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -202,4 +202,4 @@ latex_documents = [ needs_sphinx = '1.0' -extlinks = {'issue': ('http://github.com/mopidy/mopidy/issues#issue/%s', 'GH-')} +extlinks = {'issue': ('http://github.com/mopidy/mopidy/issues/%s', 'GH-')} diff --git a/mopidy/__init__.py b/mopidy/__init__.py index 1fbf99c8..79a0aa29 100644 --- a/mopidy/__init__.py +++ b/mopidy/__init__.py @@ -5,7 +5,7 @@ if not (2, 6) <= sys.version_info < (3,): from subprocess import PIPE, Popen -VERSION = (0, 4, 0) +VERSION = (0, 5, 0) def get_version(): try: diff --git a/mopidy/backends/spotify/playback.py b/mopidy/backends/spotify/playback.py index 496bd83c..3f2a157b 100644 --- a/mopidy/backends/spotify/playback.py +++ b/mopidy/backends/spotify/playback.py @@ -24,7 +24,7 @@ class SpotifyPlaybackProvider(BasePlaybackProvider): self.backend.gstreamer.set_metadata(track) return True except SpotifyError as e: - logger.warning('Play %s failed: %s', track.uri, e) + logger.info('Playback of %s failed: %s', track.uri, e) return False def resume(self): diff --git a/mopidy/backends/spotify/session_manager.py b/mopidy/backends/spotify/session_manager.py index 1d997156..09064db2 100644 --- a/mopidy/backends/spotify/session_manager.py +++ b/mopidy/backends/spotify/session_manager.py @@ -74,7 +74,11 @@ class SpotifySessionManager(BaseThread, PyspotifySessionManager): def connection_error(self, session, error): """Callback used by pyspotify""" - logger.error(u'Spotify connection error: %s', error) + if error is None: + logger.info(u'Spotify connection error resolved') + else: + logger.error(u'Spotify connection error: %s', error) + self.backend.playback.pause() def message_to_user(self, session, message): """Callback used by pyspotify""" diff --git a/mopidy/backends/spotify/translator.py b/mopidy/backends/spotify/translator.py index 64422485..dca2b285 100644 --- a/mopidy/backends/spotify/translator.py +++ b/mopidy/backends/spotify/translator.py @@ -62,5 +62,5 @@ class SpotifyTranslator(object): if str(Link.from_track(t, 0))], ) except SpotifyError, e: - logger.warning(u'Failed translating Spotify playlist ' + logger.info(u'Failed translating Spotify playlist ' '(probably a playlist folder boundary): %s', e) diff --git a/mopidy/core.py b/mopidy/core.py index 60e25ef1..4ca6ec29 100644 --- a/mopidy/core.py +++ b/mopidy/core.py @@ -24,9 +24,11 @@ def main(): setup_backend() setup_frontends() try: - time.sleep(10000*24*60*60) + while ActorRegistry.get_all(): + time.sleep(1) + logger.info(u'No actors left. Exiting...') except KeyboardInterrupt: - logger.info(u'Exiting...') + logger.info(u'User interrupt. Exiting...') ActorRegistry.stop_all() def parse_options(): diff --git a/mopidy/frontends/mpd/server.py b/mopidy/frontends/mpd/server.py index 8507e266..1be46ef4 100644 --- a/mopidy/frontends/mpd/server.py +++ b/mopidy/frontends/mpd/server.py @@ -52,7 +52,7 @@ class MpdServer(asyncore.dispatcher): self._format_hostname(settings.MPD_SERVER_HOSTNAME), settings.MPD_SERVER_PORT) except IOError, e: - logger.error('MPD server startup failed: %s' % e) + logger.error(u'MPD server startup failed: %s' % str(e).decode('utf-8')) sys.exit(1) def handle_accept(self): diff --git a/mopidy/gstreamer.py b/mopidy/gstreamer.py index 5c242a66..6a00ca37 100644 --- a/mopidy/gstreamer.py +++ b/mopidy/gstreamer.py @@ -13,6 +13,15 @@ from mopidy.backends.base import Backend logger = logging.getLogger('mopidy.gstreamer') +default_caps = gst.Caps(""" + audio/x-raw-int, + endianness=(int)1234, + channels=(int)2, + width=(int)16, + depth=(int)16, + signed=(boolean)true, + rate=(int)44100""") + class BaseOutput(object): def connect_bin(self, pipeline, element_to_link_to): """ @@ -92,10 +101,11 @@ class GStreamer(ThreadingActor): self.gst_volume = self.gst_pipeline.get_by_name('volume') self.gst_taginject = self.gst_pipeline.get_by_name('tag') - self.gst_uridecodebin = gst.element_factory_make('uridecodebin', 'uri') - self.gst_uridecodebin.connect('pad-added', self._process_new_pad, + uridecodebin = gst.element_factory_make('uridecodebin', 'uri') + uridecodebin.connect('notify::source', self._process_new_source) + uridecodebin.connect('pad-added', self._process_new_pad, self.gst_convert.get_pad('sink')) - self.gst_pipeline.add(self.gst_uridecodebin) + self.gst_pipeline.add(uridecodebin) for output in settings.OUTPUTS: output_cls = get_class(output)() @@ -106,6 +116,13 @@ class GStreamer(ThreadingActor): gst_bus.add_signal_watch() gst_bus.connect('message', self._process_gstreamer_message) + def _process_new_source(self, element, pad): + source = element.get_by_name('source') + try: + source.set_property('caps', default_caps) + except TypeError: + pass + def _process_new_pad(self, source, pad, target_pad): pad.link(target_pad) diff --git a/mopidy/mixers/nad.py b/mopidy/mixers/nad.py index bd53376e..62f38bb7 100644 --- a/mopidy/mixers/nad.py +++ b/mopidy/mixers/nad.py @@ -190,7 +190,7 @@ class NadTalker(ThreadingActor): # trailing whitespace. if not self._device.isOpen(): self._device.open() - result = self._device.readline(eol='\n').strip() + result = self._device.readline().strip() if result: logger.debug('Read: %s', result) return result diff --git a/tests/data/scanner/advanced/song1.mp3 b/tests/data/scanner/advanced/song1.mp3 deleted file mode 120000 index 6896a7a2..00000000 --- a/tests/data/scanner/advanced/song1.mp3 +++ /dev/null @@ -1 +0,0 @@ -../sample.mp3 \ No newline at end of file diff --git a/tests/data/scanner/advanced/song1.mp3 b/tests/data/scanner/advanced/song1.mp3 new file mode 100644 index 00000000..ad5aa37a Binary files /dev/null and b/tests/data/scanner/advanced/song1.mp3 differ diff --git a/tests/data/scanner/advanced/song2.mp3 b/tests/data/scanner/advanced/song2.mp3 deleted file mode 120000 index 6896a7a2..00000000 --- a/tests/data/scanner/advanced/song2.mp3 +++ /dev/null @@ -1 +0,0 @@ -../sample.mp3 \ No newline at end of file diff --git a/tests/data/scanner/advanced/song2.mp3 b/tests/data/scanner/advanced/song2.mp3 new file mode 100644 index 00000000..ad5aa37a Binary files /dev/null and b/tests/data/scanner/advanced/song2.mp3 differ diff --git a/tests/data/scanner/advanced/song3.mp3 b/tests/data/scanner/advanced/song3.mp3 deleted file mode 120000 index 6896a7a2..00000000 --- a/tests/data/scanner/advanced/song3.mp3 +++ /dev/null @@ -1 +0,0 @@ -../sample.mp3 \ No newline at end of file diff --git a/tests/data/scanner/advanced/song3.mp3 b/tests/data/scanner/advanced/song3.mp3 new file mode 100644 index 00000000..ad5aa37a Binary files /dev/null and b/tests/data/scanner/advanced/song3.mp3 differ diff --git a/tests/data/scanner/advanced/subdir1/song4.mp3 b/tests/data/scanner/advanced/subdir1/song4.mp3 deleted file mode 120000 index 45812ac5..00000000 --- a/tests/data/scanner/advanced/subdir1/song4.mp3 +++ /dev/null @@ -1 +0,0 @@ -../../sample.mp3 \ No newline at end of file diff --git a/tests/data/scanner/advanced/subdir1/song4.mp3 b/tests/data/scanner/advanced/subdir1/song4.mp3 new file mode 100644 index 00000000..ad5aa37a Binary files /dev/null and b/tests/data/scanner/advanced/subdir1/song4.mp3 differ diff --git a/tests/data/scanner/advanced/subdir1/song5.mp3 b/tests/data/scanner/advanced/subdir1/song5.mp3 deleted file mode 120000 index 45812ac5..00000000 --- a/tests/data/scanner/advanced/subdir1/song5.mp3 +++ /dev/null @@ -1 +0,0 @@ -../../sample.mp3 \ No newline at end of file diff --git a/tests/data/scanner/advanced/subdir1/song5.mp3 b/tests/data/scanner/advanced/subdir1/song5.mp3 new file mode 100644 index 00000000..ad5aa37a Binary files /dev/null and b/tests/data/scanner/advanced/subdir1/song5.mp3 differ diff --git a/tests/data/scanner/advanced/subdir1/subsubdir/song8.mp3 b/tests/data/scanner/advanced/subdir1/subsubdir/song8.mp3 deleted file mode 120000 index e84bdc24..00000000 --- a/tests/data/scanner/advanced/subdir1/subsubdir/song8.mp3 +++ /dev/null @@ -1 +0,0 @@ -../../../sample.mp3 \ No newline at end of file diff --git a/tests/data/scanner/advanced/subdir1/subsubdir/song8.mp3 b/tests/data/scanner/advanced/subdir1/subsubdir/song8.mp3 new file mode 100644 index 00000000..ad5aa37a Binary files /dev/null and b/tests/data/scanner/advanced/subdir1/subsubdir/song8.mp3 differ diff --git a/tests/data/scanner/advanced/subdir1/subsubdir/song9.mp3 b/tests/data/scanner/advanced/subdir1/subsubdir/song9.mp3 deleted file mode 120000 index e84bdc24..00000000 --- a/tests/data/scanner/advanced/subdir1/subsubdir/song9.mp3 +++ /dev/null @@ -1 +0,0 @@ -../../../sample.mp3 \ No newline at end of file diff --git a/tests/data/scanner/advanced/subdir1/subsubdir/song9.mp3 b/tests/data/scanner/advanced/subdir1/subsubdir/song9.mp3 new file mode 100644 index 00000000..ad5aa37a Binary files /dev/null and b/tests/data/scanner/advanced/subdir1/subsubdir/song9.mp3 differ diff --git a/tests/data/scanner/advanced/subdir2/song6.mp3 b/tests/data/scanner/advanced/subdir2/song6.mp3 deleted file mode 120000 index 45812ac5..00000000 --- a/tests/data/scanner/advanced/subdir2/song6.mp3 +++ /dev/null @@ -1 +0,0 @@ -../../sample.mp3 \ No newline at end of file diff --git a/tests/data/scanner/advanced/subdir2/song6.mp3 b/tests/data/scanner/advanced/subdir2/song6.mp3 new file mode 100644 index 00000000..ad5aa37a Binary files /dev/null and b/tests/data/scanner/advanced/subdir2/song6.mp3 differ diff --git a/tests/data/scanner/advanced/subdir2/song7.mp3 b/tests/data/scanner/advanced/subdir2/song7.mp3 deleted file mode 120000 index 45812ac5..00000000 --- a/tests/data/scanner/advanced/subdir2/song7.mp3 +++ /dev/null @@ -1 +0,0 @@ -../../sample.mp3 \ No newline at end of file diff --git a/tests/data/scanner/advanced/subdir2/song7.mp3 b/tests/data/scanner/advanced/subdir2/song7.mp3 new file mode 100644 index 00000000..ad5aa37a Binary files /dev/null and b/tests/data/scanner/advanced/subdir2/song7.mp3 differ diff --git a/tests/data/scanner/simple/song1.mp3 b/tests/data/scanner/simple/song1.mp3 deleted file mode 120000 index 6896a7a2..00000000 --- a/tests/data/scanner/simple/song1.mp3 +++ /dev/null @@ -1 +0,0 @@ -../sample.mp3 \ No newline at end of file diff --git a/tests/data/scanner/simple/song1.mp3 b/tests/data/scanner/simple/song1.mp3 new file mode 100644 index 00000000..ad5aa37a Binary files /dev/null and b/tests/data/scanner/simple/song1.mp3 differ diff --git a/tests/data/song1.flac b/tests/data/song1.flac deleted file mode 120000 index e5e7c129..00000000 --- a/tests/data/song1.flac +++ /dev/null @@ -1 +0,0 @@ -blank.flac \ No newline at end of file diff --git a/tests/data/song1.flac b/tests/data/song1.flac new file mode 100644 index 00000000..ae18d36f Binary files /dev/null and b/tests/data/song1.flac differ diff --git a/tests/data/song1.mp3 b/tests/data/song1.mp3 deleted file mode 120000 index 03cdf66f..00000000 --- a/tests/data/song1.mp3 +++ /dev/null @@ -1 +0,0 @@ -blank.mp3 \ No newline at end of file diff --git a/tests/data/song1.mp3 b/tests/data/song1.mp3 new file mode 100644 index 00000000..ef159a70 Binary files /dev/null and b/tests/data/song1.mp3 differ diff --git a/tests/data/song1.ogg b/tests/data/song1.ogg deleted file mode 120000 index 33e773e1..00000000 --- a/tests/data/song1.ogg +++ /dev/null @@ -1 +0,0 @@ -blank.ogg \ No newline at end of file diff --git a/tests/data/song1.ogg b/tests/data/song1.ogg new file mode 100644 index 00000000..e67e428b Binary files /dev/null and b/tests/data/song1.ogg differ diff --git a/tests/data/song1.wav b/tests/data/song1.wav deleted file mode 120000 index 72a38fad..00000000 --- a/tests/data/song1.wav +++ /dev/null @@ -1 +0,0 @@ -blank.wav \ No newline at end of file diff --git a/tests/data/song1.wav b/tests/data/song1.wav new file mode 100644 index 00000000..0041c7ba Binary files /dev/null and b/tests/data/song1.wav differ diff --git a/tests/data/song2.flac b/tests/data/song2.flac deleted file mode 120000 index e5e7c129..00000000 --- a/tests/data/song2.flac +++ /dev/null @@ -1 +0,0 @@ -blank.flac \ No newline at end of file diff --git a/tests/data/song2.flac b/tests/data/song2.flac new file mode 100644 index 00000000..ae18d36f Binary files /dev/null and b/tests/data/song2.flac differ diff --git a/tests/data/song2.mp3 b/tests/data/song2.mp3 deleted file mode 120000 index 03cdf66f..00000000 --- a/tests/data/song2.mp3 +++ /dev/null @@ -1 +0,0 @@ -blank.mp3 \ No newline at end of file diff --git a/tests/data/song2.mp3 b/tests/data/song2.mp3 new file mode 100644 index 00000000..ef159a70 Binary files /dev/null and b/tests/data/song2.mp3 differ diff --git a/tests/data/song2.ogg b/tests/data/song2.ogg deleted file mode 120000 index 33e773e1..00000000 --- a/tests/data/song2.ogg +++ /dev/null @@ -1 +0,0 @@ -blank.ogg \ No newline at end of file diff --git a/tests/data/song2.ogg b/tests/data/song2.ogg new file mode 100644 index 00000000..e67e428b Binary files /dev/null and b/tests/data/song2.ogg differ diff --git a/tests/data/song2.wav b/tests/data/song2.wav deleted file mode 120000 index 72a38fad..00000000 --- a/tests/data/song2.wav +++ /dev/null @@ -1 +0,0 @@ -blank.wav \ No newline at end of file diff --git a/tests/data/song2.wav b/tests/data/song2.wav new file mode 100644 index 00000000..0041c7ba Binary files /dev/null and b/tests/data/song2.wav differ diff --git a/tests/data/song3.flac b/tests/data/song3.flac deleted file mode 120000 index e5e7c129..00000000 --- a/tests/data/song3.flac +++ /dev/null @@ -1 +0,0 @@ -blank.flac \ No newline at end of file diff --git a/tests/data/song3.flac b/tests/data/song3.flac new file mode 100644 index 00000000..ae18d36f Binary files /dev/null and b/tests/data/song3.flac differ diff --git a/tests/data/song3.mp3 b/tests/data/song3.mp3 deleted file mode 120000 index 03cdf66f..00000000 --- a/tests/data/song3.mp3 +++ /dev/null @@ -1 +0,0 @@ -blank.mp3 \ No newline at end of file diff --git a/tests/data/song3.mp3 b/tests/data/song3.mp3 new file mode 100644 index 00000000..ef159a70 Binary files /dev/null and b/tests/data/song3.mp3 differ diff --git a/tests/data/song3.ogg b/tests/data/song3.ogg deleted file mode 120000 index 33e773e1..00000000 --- a/tests/data/song3.ogg +++ /dev/null @@ -1 +0,0 @@ -blank.ogg \ No newline at end of file diff --git a/tests/data/song3.ogg b/tests/data/song3.ogg new file mode 100644 index 00000000..e67e428b Binary files /dev/null and b/tests/data/song3.ogg differ diff --git a/tests/data/song3.wav b/tests/data/song3.wav deleted file mode 120000 index 72a38fad..00000000 --- a/tests/data/song3.wav +++ /dev/null @@ -1 +0,0 @@ -blank.wav \ No newline at end of file diff --git a/tests/data/song3.wav b/tests/data/song3.wav new file mode 100644 index 00000000..0041c7ba Binary files /dev/null and b/tests/data/song3.wav differ diff --git a/tests/version_test.py b/tests/version_test.py index 7f204283..b060a9c6 100644 --- a/tests/version_test.py +++ b/tests/version_test.py @@ -17,8 +17,9 @@ class VersionTest(unittest.TestCase): self.assert_(SV('0.1.0') < SV('1.0.0')) self.assert_(SV('0.2.0') < SV('0.3.0')) self.assert_(SV('0.3.0') < SV('0.3.1')) - self.assert_(SV('0.3.1') < SV(get_plain_version())) - self.assert_(SV(get_plain_version()) < SV('0.4.1')) + self.assert_(SV('0.3.1') < SV('0.4.0')) + self.assert_(SV('0.4.0') < SV(get_plain_version())) + self.assert_(SV(get_plain_version()) < SV('0.5.1')) def test_get_platform_contains_platform(self): self.assert_(platform.platform() in get_platform())