From fc8b932723bdb32b961aaf01319b4282164cfbdb Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Wed, 5 May 2010 18:33:05 +0200 Subject: [PATCH 1/6] Add file based debug logger --- mopidy/__main__.py | 23 +++++++++++++++++++++-- mopidy/settings.py | 6 ++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/mopidy/__main__.py b/mopidy/__main__.py index 12d27ed3..0769d6b6 100644 --- a/mopidy/__main__.py +++ b/mopidy/__main__.py @@ -1,5 +1,6 @@ import asyncore import logging +import logging.handlers import multiprocessing import optparse import os @@ -16,7 +17,7 @@ logger = logging.getLogger('mopidy.main') def main(): options = _parse_options() - _setup_logging(options.verbosity_level) + _setup_logging(options.verbosity_level, options.debug) get_or_create_folder('~/.mopidy/') core_queue = multiprocessing.Queue() get_class(settings.SERVER)(core_queue) @@ -32,17 +33,35 @@ def _parse_options(): parser.add_option('-v', '--verbose', action='store_const', const=2, dest='verbosity_level', help='more output (debug level)') + parser.add_option('-d', '--debug', + action='store_true', dest='debug', + help='debug logging to file') return parser.parse_args()[0] -def _setup_logging(verbosity_level): +def _setup_logging(verbosity_level, debug): if verbosity_level == 0: level = logging.WARNING elif verbosity_level == 2: level = logging.DEBUG else: level = logging.INFO + logging.basicConfig(format=settings.CONSOLE_LOG_FORMAT, level=level) + if not debug: + return + + root = logging.getLogger('') + root.setLevel(logging.DEBUG) + + formatter = logging.Formatter(settings.DEBUG_LOG_FORMAT) + + handler = logging.handlers.RotatingFileHandler( + settings.DEBUG_LOG_FILENAME, maxBytes=102400, backupCount=3) + handler.setFormatter(formatter) + + root.addHandler(handler) + if __name__ == '__main__': try: main() diff --git a/mopidy/settings.py b/mopidy/settings.py index 886e7189..470bf2a2 100644 --- a/mopidy/settings.py +++ b/mopidy/settings.py @@ -29,6 +29,12 @@ BACKENDS = ( CONSOLE_LOG_FORMAT = u'%(levelname)-8s %(asctime)s' + \ ' [%(process)d:%(threadName)s] %(name)s\n %(message)s' +#: The log format used for debug log dumps. +DEBUG_LOG_FORMAT = u'%(asctime)s - %(levelname)-5s - %(name)s - %(message)s' + +#: The file to log debug data to. +DEBUG_LOG_FILENAME = u'debug.log' + #: Protocol frontend to use. Default:: #: #: FRONTEND = u'mopidy.mpd.frontend.MpdFrontend' From f0dfaaa363f6fa72a12f0896fad41b2ff4263ad5 Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Wed, 5 May 2010 18:33:19 +0200 Subject: [PATCH 2/6] Add client info to logs --- mopidy/mpd/server.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mopidy/mpd/server.py b/mopidy/mpd/server.py index bd37c998..80eca5f9 100644 --- a/mopidy/mpd/server.py +++ b/mopidy/mpd/server.py @@ -68,7 +68,8 @@ class MpdSession(asynchat.async_chat): data = ''.join(self.input_buffer).strip() self.input_buffer = [] request = data.decode(ENCODING) - logger.debug(u'Input: %s', indent(request)) + host, port = self.client_address + logger.debug(u'Input (%s:%s): %s', host, port, indent(request)) self.handle_request(request) def handle_request(self, request): @@ -87,7 +88,8 @@ class MpdSession(asynchat.async_chat): self.send_response(LINE_TERMINATOR.join(response)) def send_response(self, output): - logger.debug(u'Output: %s', indent(output)) + host, port = self.client_address + logger.debug(u'Output (%s:%s): %s', host, port, indent(output)) output = u'%s%s' % (output, LINE_TERMINATOR) data = output.encode(ENCODING) self.push(data) From 8361b137ccfacfcf3fbd318c23977e5b7b1f3de8 Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Wed, 5 May 2010 19:21:47 +0200 Subject: [PATCH 3/6] Rename debug option to dump --- mopidy/__main__.py | 10 +++++----- mopidy/settings.py | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/mopidy/__main__.py b/mopidy/__main__.py index 0769d6b6..a99d9ddc 100644 --- a/mopidy/__main__.py +++ b/mopidy/__main__.py @@ -33,9 +33,9 @@ def _parse_options(): parser.add_option('-v', '--verbose', action='store_const', const=2, dest='verbosity_level', help='more output (debug level)') - parser.add_option('-d', '--debug', - action='store_true', dest='debug', - help='debug logging to file') + parser.add_option('--dump', + action='store_true', dest='dump', + help='dump debug log to file') return parser.parse_args()[0] def _setup_logging(verbosity_level, debug): @@ -54,10 +54,10 @@ def _setup_logging(verbosity_level, debug): root = logging.getLogger('') root.setLevel(logging.DEBUG) - formatter = logging.Formatter(settings.DEBUG_LOG_FORMAT) + formatter = logging.Formatter(settings.DUMP_LOG_FORMAT) handler = logging.handlers.RotatingFileHandler( - settings.DEBUG_LOG_FILENAME, maxBytes=102400, backupCount=3) + settings.DUMP_LOG_FILENAME, maxBytes=102400, backupCount=3) handler.setFormatter(formatter) root.addHandler(handler) diff --git a/mopidy/settings.py b/mopidy/settings.py index 470bf2a2..6375568a 100644 --- a/mopidy/settings.py +++ b/mopidy/settings.py @@ -29,11 +29,11 @@ BACKENDS = ( CONSOLE_LOG_FORMAT = u'%(levelname)-8s %(asctime)s' + \ ' [%(process)d:%(threadName)s] %(name)s\n %(message)s' -#: The log format used for debug log dumps. -DEBUG_LOG_FORMAT = u'%(asctime)s - %(levelname)-5s - %(name)s - %(message)s' +#: The log format used for dump logs. +DUMP_LOG_FORMAT = CONSOLE_LOG_FORMAT -#: The file to log debug data to. -DEBUG_LOG_FILENAME = u'debug.log' +#: The file to dump debug log data to. +DUMP_LOG_FILENAME = u'dump.log' #: Protocol frontend to use. Default:: #: From 733f51fdc6701f27515d8574dab5b73b9476ab1c Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Wed, 5 May 2010 19:29:20 +0200 Subject: [PATCH 4/6] Add info about defaults for DUMP settings --- mopidy/settings.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mopidy/settings.py b/mopidy/settings.py index 6375568a..b1e2e7b2 100644 --- a/mopidy/settings.py +++ b/mopidy/settings.py @@ -29,10 +29,12 @@ BACKENDS = ( CONSOLE_LOG_FORMAT = u'%(levelname)-8s %(asctime)s' + \ ' [%(process)d:%(threadName)s] %(name)s\n %(message)s' -#: The log format used for dump logs. +#: The log format used for dump logs. Default:: +#: DUMP_LOG_FILENAME = CONSOLE_LOG_FORMAT DUMP_LOG_FORMAT = CONSOLE_LOG_FORMAT -#: The file to dump debug log data to. +#: The file to dump debug log data to. Default:: +#: DUMP_LOG_FILENAME = u'dump.log' DUMP_LOG_FILENAME = u'dump.log' #: Protocol frontend to use. Default:: From 1660cccbea464cdda5c585c43b86d51c01621131 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Wed, 5 May 2010 19:42:16 +0200 Subject: [PATCH 5/6] Fix missing options.debug --- mopidy/__main__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mopidy/__main__.py b/mopidy/__main__.py index a99d9ddc..2086a2e8 100644 --- a/mopidy/__main__.py +++ b/mopidy/__main__.py @@ -17,7 +17,7 @@ logger = logging.getLogger('mopidy.main') def main(): options = _parse_options() - _setup_logging(options.verbosity_level, options.debug) + _setup_logging(options.verbosity_level, options.dump) get_or_create_folder('~/.mopidy/') core_queue = multiprocessing.Queue() get_class(settings.SERVER)(core_queue) @@ -38,7 +38,7 @@ def _parse_options(): help='dump debug log to file') return parser.parse_args()[0] -def _setup_logging(verbosity_level, debug): +def _setup_logging(verbosity_level, dump): if verbosity_level == 0: level = logging.WARNING elif verbosity_level == 2: @@ -48,7 +48,7 @@ def _setup_logging(verbosity_level, debug): logging.basicConfig(format=settings.CONSOLE_LOG_FORMAT, level=level) - if not debug: + if not dump: return root = logging.getLogger('') From 429caf51aa75c275c3cba570e2ebd6c5404db384 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Wed, 5 May 2010 20:04:25 +0200 Subject: [PATCH 6/6] Add new setting MIXER_ALSA_CONTROL that overrides the control search in AlsaMixer --- mopidy/mixers/alsa.py | 32 +++++++++++++++++++++++--------- mopidy/settings.py | 6 ++++++ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/mopidy/mixers/alsa.py b/mopidy/mixers/alsa.py index 9bcd8b6f..4fd84fd2 100644 --- a/mopidy/mixers/alsa.py +++ b/mopidy/mixers/alsa.py @@ -1,6 +1,7 @@ import alsaaudio import logging +from mopidy import settings from mopidy.mixers import BaseMixer logger = logging.getLogger('mopidy.mixers.alsa') @@ -13,17 +14,30 @@ class AlsaMixer(BaseMixer): def __init__(self, *args, **kwargs): super(AlsaMixer, self).__init__(*args, **kwargs) - # A mixer named 'Master' does not always exist, so we fall back to - # using 'PCM'. If this turns out to be a bad solution, we should make - # it possible to override with a setting. - self._mixer = None - for mixer_name in (u'Master', u'PCM'): - if mixer_name in alsaaudio.mixers(): - logger.info(u'Mixer in use: %s', mixer_name) - self._mixer = alsaaudio.Mixer(mixer_name) - break + self._mixer = alsaaudio.Mixer(self._get_mixer_control()) assert self._mixer is not None + def _get_mixer_control(self): + """Returns the first mixer control candidate that is known to ALSA""" + candidates = self._get_mixer_control_candidates() + for control in candidates: + if control in alsaaudio.mixers(): + logger.info(u'Mixer control in use: %s', control) + return control + else: + logger.debug(u'Mixer control not found, skipping: %s', control) + logger.warning(u'No working mixer controls found. Tried: %s', candidates) + + def _get_mixer_control_candidates(self): + """ + A mixer named 'Master' does not always exist, so we fall back to using + 'PCM'. If this does not work for you, you may set + :attr:`mopidy.settings.MIXER_ALSA_CONTROL`. + """ + if settings.MIXER_ALSA_CONTROL: + return [settings.MIXER_ALSA_CONTROL] + return [u'Master', u'PCM'] + def _get_volume(self): return self._mixer.getvolume()[0] diff --git a/mopidy/settings.py b/mopidy/settings.py index b1e2e7b2..a2ba88e5 100644 --- a/mopidy/settings.py +++ b/mopidy/settings.py @@ -61,6 +61,12 @@ if sys.platform == 'linux2': elif sys.platform == 'darwin': MIXER = u'mopidy.mixers.osa.OsaMixer' +#: ALSA mixer only. What mixer control to use. If set to :class:`False`, first +#: ``Master`` and then ``PCM`` will be tried. +#: +#: Example: ``Master Front``. *Default:* :class:`False` +MIXER_ALSA_CONTROL = False + #: External mixers only. Which port the mixer is connected to. #: #: This must point to the device port like ``/dev/ttyUSB0``.