diff --git a/docs/changes.rst b/docs/changes.rst index 21011139..855490f5 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -23,6 +23,7 @@ v0.6.0 (in development) - Replaced all of the MPD network code that was provided by asyncore with custom stack. This change was made to facilitate the future support of the `idle` command, and to reduce the number of event loops being used. +- Fix metadata update in Shoutcast streaming (Fixes: :issue:`122`) v0.5.0 (2011-06-15) diff --git a/mopidy/backends/spotify/session_manager.py b/mopidy/backends/spotify/session_manager.py index fd71d861..2c6509ed 100644 --- a/mopidy/backends/spotify/session_manager.py +++ b/mopidy/backends/spotify/session_manager.py @@ -118,6 +118,7 @@ class SpotifySessionManager(BaseThread, PyspotifySessionManager): 'channels': channels, } self.gstreamer.emit_data(capabilites, bytes(frames)) + return num_frames def play_token_lost(self, session): """Callback used by pyspotify""" diff --git a/mopidy/gstreamer.py b/mopidy/gstreamer.py index 43c5ea2b..edcb3084 100644 --- a/mopidy/gstreamer.py +++ b/mopidy/gstreamer.py @@ -274,10 +274,18 @@ class GStreamer(ThreadingActor): taglist = gst.TagList() artists = [a for a in (track.artists or []) if a.name] + # Default to blank data to trick shoutcast into clearing any previous + # values it might have. + taglist[gst.TAG_ARTIST] = u' ' + taglist[gst.TAG_TITLE] = u' ' + taglist[gst.TAG_ALBUM] = u' ' + if artists: taglist[gst.TAG_ARTIST] = u', '.join([a.name for a in artists]) + if track.name: taglist[gst.TAG_TITLE] = track.name + if track.album and track.album.name: taglist[gst.TAG_ALBUM] = track.album.name diff --git a/mopidy/settings.py b/mopidy/settings.py index 9ac63719..f3e012ed 100644 --- a/mopidy/settings.py +++ b/mopidy/settings.py @@ -26,7 +26,8 @@ BACKENDS = ( #: details on the format. CONSOLE_LOG_FORMAT = u'%(levelname)-8s %(message)s' -#: Which GStreamer bin description to use in :class:`mopidy.outputs.CustomOutput`. +#: Which GStreamer bin description to use in +#: :class:`mopidy.outputs.custom.CustomOutput`. #: #: Default:: #: diff --git a/mopidy/utils/__init__.py b/mopidy/utils/__init__.py index acbb4664..9d7532a0 100644 --- a/mopidy/utils/__init__.py +++ b/mopidy/utils/__init__.py @@ -18,9 +18,11 @@ def import_module(name): return sys.modules[name] def get_class(name): + logger.debug('Loading: %s', name) + if '.' not in name: + raise ImportError("Couldn't load: %s" % name) module_name = name[:name.rindex('.')] class_name = name[name.rindex('.') + 1:] - logger.debug('Loading: %s', name) try: module = import_module(module_name) class_object = getattr(module, class_name) diff --git a/mopidy/utils/settings.py b/mopidy/utils/settings.py index cab94089..3f7593af 100644 --- a/mopidy/utils/settings.py +++ b/mopidy/utils/settings.py @@ -53,6 +53,8 @@ class SettingsProxy(object): value = self.current[attr] if isinstance(value, basestring) and len(value) == 0: raise SettingsError(u'Setting "%s" is empty.' % attr) + if not value: + return value if attr.endswith('_PATH') or attr.endswith('_FILE'): value = os.path.expanduser(value) value = os.path.abspath(value) diff --git a/tests/utils/init_test.py b/tests/utils/init_test.py index fb38e2ea..70dd7e36 100644 --- a/tests/utils/init_test.py +++ b/tests/utils/init_test.py @@ -4,12 +4,13 @@ from mopidy.utils import get_class class GetClassTest(unittest.TestCase): def test_loading_module_that_does_not_exist(self): - test = lambda: get_class('foo.bar.Baz') - self.assertRaises(ImportError, test) + self.assertRaises(ImportError, get_class, 'foo.bar.Baz') def test_loading_class_that_does_not_exist(self): - test = lambda: get_class('unittest.FooBarBaz') - self.assertRaises(ImportError, test) + self.assertRaises(ImportError, get_class, 'unittest.FooBarBaz') + + def test_loading_incorrect_class_path(self): + self.assertRaises(ImportError, get_class, 'foobarbaz') def test_import_error_message_contains_complete_class_path(self): try: diff --git a/tests/utils/settings_test.py b/tests/utils/settings_test.py index 973c2280..ec470ea9 100644 --- a/tests/utils/settings_test.py +++ b/tests/utils/settings_test.py @@ -150,6 +150,14 @@ class SettingsProxyTest(unittest.TestCase): actual = self.settings.TEST self.assertEqual(actual, './test') + def test_value_ending_in_file_can_be_none(self): + self.settings.TEST_FILE = None + self.assertEqual(self.settings.TEST_FILE, None) + + def test_value_ending_in_path_can_be_none(self): + self.settings.TEST_PATH = None + self.assertEqual(self.settings.TEST_PATH, None) + def test_interactive_input_of_missing_defaults(self): self.settings.default['TEST'] = '' interactive_input = 'input'