diff --git a/mopidy/__main__.py b/mopidy/__main__.py index 12d27ed3..2086a2e8 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.dump) 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('--dump', + action='store_true', dest='dump', + help='dump debug log to file') return parser.parse_args()[0] -def _setup_logging(verbosity_level): +def _setup_logging(verbosity_level, dump): 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 dump: + return + + root = logging.getLogger('') + root.setLevel(logging.DEBUG) + + formatter = logging.Formatter(settings.DUMP_LOG_FORMAT) + + handler = logging.handlers.RotatingFileHandler( + settings.DUMP_LOG_FILENAME, maxBytes=102400, backupCount=3) + handler.setFormatter(formatter) + + root.addHandler(handler) + if __name__ == '__main__': try: main() 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/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) diff --git a/mopidy/settings.py b/mopidy/settings.py index 886e7189..a2ba88e5 100644 --- a/mopidy/settings.py +++ b/mopidy/settings.py @@ -29,6 +29,14 @@ 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. Default:: +#: DUMP_LOG_FILENAME = CONSOLE_LOG_FORMAT +DUMP_LOG_FORMAT = CONSOLE_LOG_FORMAT + +#: 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:: #: #: FRONTEND = u'mopidy.mpd.frontend.MpdFrontend' @@ -53,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``.