From f8555e70610df47b726e20f312be5beba67f8435 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Sun, 22 Aug 2010 13:08:00 +0200 Subject: [PATCH 1/7] Create BaseThread as copy of BaseProcess but with different superclass --- mopidy/utils/process.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/mopidy/utils/process.py b/mopidy/utils/process.py index 73224840..16c07629 100644 --- a/mopidy/utils/process.py +++ b/mopidy/utils/process.py @@ -1,5 +1,6 @@ import logging import multiprocessing +import multiprocessing.dummy from multiprocessing.reduction import reduce_connection import pickle import sys @@ -37,3 +38,25 @@ class BaseProcess(multiprocessing.Process): def run_inside_try(self): raise NotImplementedError + + +class BaseThread(multiprocessing.dummy.Process): + def run(self): + logger.debug(u'%s: Starting process', self.name) + try: + self.run_inside_try() + except KeyboardInterrupt: + logger.info(u'%s: Interrupted by user', self.name) + sys.exit(0) + except SettingsError as e: + logger.error(e.message) + sys.exit(1) + except ImportError as e: + logger.error(e) + sys.exit(1) + except Exception as e: + logger.exception(e) + raise e + + def run_inside_try(self): + raise NotImplementedError From 80c9e1e5797da396e28840c844762cf38f8688d5 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Sun, 22 Aug 2010 13:33:09 +0200 Subject: [PATCH 2/7] Add destroy() to BaseProcess and BaseThread --- mopidy/utils/process.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mopidy/utils/process.py b/mopidy/utils/process.py index 16c07629..09446c93 100644 --- a/mopidy/utils/process.py +++ b/mopidy/utils/process.py @@ -39,6 +39,9 @@ class BaseProcess(multiprocessing.Process): def run_inside_try(self): raise NotImplementedError + def destroy(self): + self.terminate() + class BaseThread(multiprocessing.dummy.Process): def run(self): @@ -60,3 +63,6 @@ class BaseThread(multiprocessing.dummy.Process): def run_inside_try(self): raise NotImplementedError + + def destroy(self): + pass From 865f7df86b89f1e4f7b5a8c95c29c48345912699 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Sun, 22 Aug 2010 13:53:22 +0200 Subject: [PATCH 3/7] Rewrite GStreamerOutput to use BaseThread --- mopidy/outputs/gstreamer.py | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/mopidy/outputs/gstreamer.py b/mopidy/outputs/gstreamer.py index 453747d6..c0ffd0c0 100644 --- a/mopidy/outputs/gstreamer.py +++ b/mopidy/outputs/gstreamer.py @@ -9,7 +9,7 @@ import logging import threading from mopidy import settings -from mopidy.utils.process import BaseProcess, unpickle_connection +from mopidy.utils.process import BaseThread, unpickle_connection logger = logging.getLogger('mopidy.outputs.gstreamer') @@ -17,21 +17,32 @@ class GStreamerOutput(object): """ Audio output through GStreamer. - Starts the :class:`GStreamerProcess`. + Starts :class:`GStreamerMessagesThread` and :class:`GStreamerPlayerThread`. """ def __init__(self, core_queue, output_queue): - self.process = GStreamerProcess(core_queue, output_queue) - self.process.start() + # Start a helper thread that can run the gobject.MainLoop + self.messages_thread = GStreamerMessagesThread() + self.messages_thread.start() + + # Start a helper thread that can process the output_queue + self.player_thread = GStreamerPlayerThread(core_queue, output_queue) + self.player_thread.start() def destroy(self): - self.process.terminate() + self.messages_thread.destroy() + self.player_thread.destroy() -class GStreamerMessagesThread(threading.Thread): - def run(self): +class GStreamerMessagesThread(BaseThread): + def __init__(self): + super(GStreamerMessagesThread, self).__init__() + self.name = u'GStreamerMessagesThread' + self.daemon = True + + def run_inside_try(self): gobject.MainLoop().run() -class GStreamerProcess(BaseProcess): +class GStreamerPlayerThread(BaseThread): """ A process for all work related to GStreamer. @@ -44,7 +55,9 @@ class GStreamerProcess(BaseProcess): """ def __init__(self, core_queue, output_queue): - super(GStreamerProcess, self).__init__(name='GStreamerProcess') + super(GStreamerPlayerThread, self).__init__() + self.name = u'GStreamerPlayerThread' + self.daemon = True self.core_queue = core_queue self.output_queue = output_queue self.gst_pipeline = None @@ -58,11 +71,6 @@ class GStreamerProcess(BaseProcess): def setup(self): logger.debug(u'Setting up GStreamer pipeline') - # Start a helper thread that can run the gobject.MainLoop - messages_thread = GStreamerMessagesThread() - messages_thread.daemon = True - messages_thread.start() - self.gst_pipeline = gst.parse_launch(' ! '.join([ 'audioconvert name=convert', 'volume name=volume', From ce7f4339acac84d023bbbd1b4f7300f7072e5856 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Sun, 22 Aug 2010 13:57:58 +0200 Subject: [PATCH 4/7] Rewrite MPD frontend to run in thread instead of process --- mopidy/frontends/mpd/__init__.py | 8 ++++---- mopidy/frontends/mpd/process.py | 18 ------------------ mopidy/frontends/mpd/thread.py | 20 ++++++++++++++++++++ 3 files changed, 24 insertions(+), 22 deletions(-) delete mode 100644 mopidy/frontends/mpd/process.py create mode 100644 mopidy/frontends/mpd/thread.py diff --git a/mopidy/frontends/mpd/__init__.py b/mopidy/frontends/mpd/__init__.py index 02e3ab5f..2361d2bf 100644 --- a/mopidy/frontends/mpd/__init__.py +++ b/mopidy/frontends/mpd/__init__.py @@ -1,5 +1,5 @@ from mopidy.frontends.mpd.dispatcher import MpdDispatcher -from mopidy.frontends.mpd.process import MpdProcess +from mopidy.frontends.mpd.thread import MpdThread class MpdFrontend(object): """ @@ -7,7 +7,7 @@ class MpdFrontend(object): """ def __init__(self): - self.process = None + self.thred = None self.dispatcher = None def start_server(self, core_queue): @@ -17,8 +17,8 @@ class MpdFrontend(object): :param core_queue: the core queue :type core_queue: :class:`multiprocessing.Queue` """ - self.process = MpdProcess(core_queue) - self.process.start() + self.thread = MpdThread(core_queue) + self.thread.start() def create_dispatcher(self, backend): """ diff --git a/mopidy/frontends/mpd/process.py b/mopidy/frontends/mpd/process.py deleted file mode 100644 index 7bd95900..00000000 --- a/mopidy/frontends/mpd/process.py +++ /dev/null @@ -1,18 +0,0 @@ -import asyncore -import logging - -from mopidy.frontends.mpd.server import MpdServer -from mopidy.utils.process import BaseProcess - -logger = logging.getLogger('mopidy.frontends.mpd.process') - -class MpdProcess(BaseProcess): - def __init__(self, core_queue): - super(MpdProcess, self).__init__(name='MpdProcess') - self.core_queue = core_queue - - def run_inside_try(self): - logger.debug(u'Starting MPD server process') - server = MpdServer(self.core_queue) - server.start() - asyncore.loop() diff --git a/mopidy/frontends/mpd/thread.py b/mopidy/frontends/mpd/thread.py new file mode 100644 index 00000000..0fb048ec --- /dev/null +++ b/mopidy/frontends/mpd/thread.py @@ -0,0 +1,20 @@ +import asyncore +import logging + +from mopidy.frontends.mpd.server import MpdServer +from mopidy.utils.process import BaseThread + +logger = logging.getLogger('mopidy.frontends.mpd.thread') + +class MpdThread(BaseThread): + def __init__(self, core_queue): + super(MpdThread, self).__init__() + self.name = u'MpdThread' + self.daemon = True + self.core_queue = core_queue + + def run_inside_try(self): + logger.debug(u'Starting MPD server thread') + server = MpdServer(self.core_queue) + server.start() + asyncore.loop() From 2850a760ced45e9e44f046ac476f2da2f4b77421 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Sun, 22 Aug 2010 19:31:18 +0200 Subject: [PATCH 5/7] Convert LibspotifySessionManager to a subclass of BaseThread --- mopidy/backends/libspotify/session_manager.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/mopidy/backends/libspotify/session_manager.py b/mopidy/backends/libspotify/session_manager.py index 22cbb0a0..58c4a795 100644 --- a/mopidy/backends/libspotify/session_manager.py +++ b/mopidy/backends/libspotify/session_manager.py @@ -5,12 +5,13 @@ import threading from spotify.manager import SpotifySessionManager from mopidy import get_version, settings -from mopidy.models import Playlist from mopidy.backends.libspotify.translator import LibspotifyTranslator +from mopidy.models import Playlist +from mopidy.utils.process import BaseThread logger = logging.getLogger('mopidy.backends.libspotify.session_manager') -class LibspotifySessionManager(SpotifySessionManager, threading.Thread): +class LibspotifySessionManager(SpotifySessionManager, BaseThread): cache_location = os.path.expanduser(settings.SPOTIFY_LIB_CACHE) settings_location = os.path.expanduser(settings.SPOTIFY_LIB_CACHE) appkey_file = os.path.join(os.path.dirname(__file__), 'spotify_appkey.key') @@ -18,7 +19,8 @@ class LibspotifySessionManager(SpotifySessionManager, threading.Thread): def __init__(self, username, password, core_queue, output_queue): SpotifySessionManager.__init__(self, username, password) - threading.Thread.__init__(self, name='LibspotifySessionManagerThread') + BaseThread.__init__(self) + self.name = 'LibspotifySessionManagerThread' # Run as a daemon thread, so Mopidy won't wait for this thread to exit # before Mopidy exits. self.daemon = True @@ -27,7 +29,7 @@ class LibspotifySessionManager(SpotifySessionManager, threading.Thread): self.connected = threading.Event() self.session = None - def run(self): + def run_inside_try(self): self.connect() def logged_in(self, session, error): From fee4735626dd9e97fce68090d076e4c0a04d37f8 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Thu, 26 Aug 2010 18:53:41 +0200 Subject: [PATCH 6/7] Remove unused import --- mopidy/outputs/gstreamer.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mopidy/outputs/gstreamer.py b/mopidy/outputs/gstreamer.py index 55ff131a..346f6254 100644 --- a/mopidy/outputs/gstreamer.py +++ b/mopidy/outputs/gstreamer.py @@ -7,7 +7,6 @@ import gst import logging import multiprocessing -import threading from mopidy import settings from mopidy.outputs.base import BaseOutput From ee4cef19887ee9715ef10e8b56cb66b588b8abf3 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Thu, 26 Aug 2010 18:56:36 +0200 Subject: [PATCH 7/7] Threadify Last.fm frontend --- mopidy/frontends/lastfm.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mopidy/frontends/lastfm.py b/mopidy/frontends/lastfm.py index 13a8f6b4..e0f1c978 100644 --- a/mopidy/frontends/lastfm.py +++ b/mopidy/frontends/lastfm.py @@ -11,7 +11,7 @@ except ImportError as e: from mopidy import get_version, settings, SettingsError from mopidy.frontends.base import BaseFrontend -from mopidy.utils.process import BaseProcess +from mopidy.utils.process import BaseThread logger = logging.getLogger('mopidy.frontends.lastfm') @@ -45,22 +45,22 @@ class LastfmFrontend(BaseFrontend): def __init__(self, *args, **kwargs): super(LastfmFrontend, self).__init__(*args, **kwargs) (self.connection, other_end) = multiprocessing.Pipe() - self.process = LastfmFrontendProcess(other_end) + self.thread = LastfmFrontendThread(other_end) def start(self): - self.process.start() + self.thread.start() def destroy(self): - self.process.destroy() + self.thread.destroy() def process_message(self, message): self.connection.send(message) -class LastfmFrontendProcess(BaseProcess): +class LastfmFrontendThread(BaseThread): def __init__(self, connection): - super(LastfmFrontendProcess, self).__init__() - self.name = u'LastfmFrontendProcess' + super(LastfmFrontendThread, self).__init__() + self.name = u'LastfmFrontendThread' self.daemon = True self.connection = connection self.lastfm = None