From e96751aa4688464be2d63e97323b6d57dfbedfc0 Mon Sep 17 00:00:00 2001 From: Kristian Date: Wed, 10 Mar 2010 12:43:11 +0100 Subject: [PATCH 01/21] Added Denon mixer support --- mopidy/mixers/denon.py | 27 +++++++++++++++++++++++++++ mopidy/settings/default.py | 16 ++++++++++++++++ tests/__main__.py | 1 + tests/mixers/denontest.py | 31 +++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 mopidy/mixers/denon.py create mode 100644 tests/mixers/denontest.py diff --git a/mopidy/mixers/denon.py b/mopidy/mixers/denon.py new file mode 100644 index 00000000..2acfa619 --- /dev/null +++ b/mopidy/mixers/denon.py @@ -0,0 +1,27 @@ +from serial import Serial + +from mopidy.mixers import BaseMixer +from mopidy.settings import MIXER_PORT + + +class DenonMixer(BaseMixer): + def __init__(self): + self._device = Serial(port=MIXER_PORT) + self._levels = ['99']+["%(#)02d"% {'#': v} for v in range(0,99)] + self._volume = None + + def _get_volume(self): + # The Denon spec doesnt seem to document + # how to query the volume, so we keep the + # state internally + return self._volume + + def _set_volume(self, volume): + # Clamp according to Denon-spec + if not volume: + volume = 0 + elif volume > 99: + volume = 99 + + self._volume = volume + self._device.write('MV%s\r'% self._levels[volume]) diff --git a/mopidy/settings/default.py b/mopidy/settings/default.py index 96d5cd23..d6e18503 100644 --- a/mopidy/settings/default.py +++ b/mopidy/settings/default.py @@ -38,12 +38,28 @@ CONSOLE_LOG_FORMAT = u'%(levelname)-8s %(asctime)s [%(threadName)s] %(name)s\n #: Default on other operating systems:: #: #: MIXER = u'mopidy.mixers.dummy.DummyMixer' +#: +#: *Using external mixers* +#: +#: Using external mixers depends on the pyserial-library, +#: so make sure you have it installed. It also adds one +#: more setting, MIXER_PORT. This must point to the device +#: port like /dev/tty1 or similar. +#: +#: Available external Mixers:: +#: +#: +#: MIXER = u'mopidy.mixers.denon.DenonMixer' +#: MIXER_PORT = u'/dev/tty0' # Verify this manually +#: MIXER = u'mopidy.mixers.dummy.DummyMixer' if sys.platform == 'linux2': MIXER = u'mopidy.mixers.alsa.AlsaMixer' elif sys.platform == 'darwin': MIXER = u'mopidy.mixers.osa.OsaMixer' +MIXER_PORT=None + #: Which address Mopidy should bind to. Examples: #: #: ``localhost`` diff --git a/tests/__main__.py b/tests/__main__.py index 11677b0e..d3adfca0 100644 --- a/tests/__main__.py +++ b/tests/__main__.py @@ -10,6 +10,7 @@ def main(): os.path.abspath(os.path.join(os.path.dirname(__file__), '../'))) r = CoverageTestRunner() r.add_pair('mopidy/mixers/dummy.py', 'tests/mixers/dummytest.py') + r.add_pair('mopidy/mixers/denon.py', 'tests/mixers/denontest.py') r.add_pair('mopidy/models.py', 'tests/modelstest.py') r.add_pair('mopidy/mpd/handler.py', 'tests/mpd/handlertest.py') r.run() diff --git a/tests/mixers/denontest.py b/tests/mixers/denontest.py new file mode 100644 index 00000000..a862e402 --- /dev/null +++ b/tests/mixers/denontest.py @@ -0,0 +1,31 @@ +import unittest +import os + +from mopidy.mixers.denon import DenonMixer + +class DenonMixerTest(unittest.TestCase): + def setUp(self): + self.m = DenonMixer() + self.m._device = os.tmpfile() # "Mock" :-) + + def tearDown(self): + self.m._device.close() + + def test_volume_is_None_initially(self): + self.assertEqual(self.m.volume, None) + + def test_volume_set_to_min(self): + self.m.volume = 0 + self.assertEqual(self.m.volume, 0) + + def test_volume_set_to_max(self): + self.m.volume = 100 + self.assertEqual(self.m.volume, 99) + + def test_volume_set_to_below_min_results_in_min(self): + self.m.volume = -10 + self.assertEqual(self.m.volume, 0) + + def test_volume_set_to_above_max_results_in_max(self): + self.m.volume = 110 + self.assertEqual(self.m.volume, 99) From 867c8fbc507f53e2921a5217cdec48d38104fe3a Mon Sep 17 00:00:00 2001 From: Kristian Date: Wed, 10 Mar 2010 13:16:56 +0100 Subject: [PATCH 02/21] Added reading of volume from Denon devices that support it, and reopen socket if needed --- mopidy/mixers/denon.py | 17 ++++++++++++----- tests/mixers/denontest.py | 24 ++++++++++++++++++++---- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/mopidy/mixers/denon.py b/mopidy/mixers/denon.py index 2acfa619..78bb27a0 100644 --- a/mopidy/mixers/denon.py +++ b/mopidy/mixers/denon.py @@ -6,14 +6,19 @@ from mopidy.settings import MIXER_PORT class DenonMixer(BaseMixer): def __init__(self): - self._device = Serial(port=MIXER_PORT) + self._device = Serial(port=MIXER_PORT, timeout=0.2) self._levels = ['99']+["%(#)02d"% {'#': v} for v in range(0,99)] self._volume = None def _get_volume(self): - # The Denon spec doesnt seem to document - # how to query the volume, so we keep the - # state internally + try: + self._device.write('MV?\r') + vol = self._device.read(2) + if vol: + return self._levels.index(int(vol)) + except: + pass # No support for volume query on device + return self._volume def _set_volume(self, volume): @@ -23,5 +28,7 @@ class DenonMixer(BaseMixer): elif volume > 99: volume = 99 - self._volume = volume + if not self._device.isOpen(): + self._device.open() self._device.write('MV%s\r'% self._levels[volume]) + self._volume = volume diff --git a/tests/mixers/denontest.py b/tests/mixers/denontest.py index a862e402..6256ac38 100644 --- a/tests/mixers/denontest.py +++ b/tests/mixers/denontest.py @@ -3,13 +3,24 @@ import os from mopidy.mixers.denon import DenonMixer +class DenonMixerDeviceMock(object): + def __init__(self): + self._open = True + self.ret_val = bytes('00') + + def write(self, x): + pass + def read(self, x): + return self.ret_val + def isOpen(self): + return self._open + def open(self): + self._open = True + class DenonMixerTest(unittest.TestCase): def setUp(self): self.m = DenonMixer() - self.m._device = os.tmpfile() # "Mock" :-) - - def tearDown(self): - self.m._device.close() + self.m._device = DenonMixerDeviceMock() def test_volume_is_None_initially(self): self.assertEqual(self.m.volume, None) @@ -29,3 +40,8 @@ class DenonMixerTest(unittest.TestCase): def test_volume_set_to_above_max_results_in_max(self): self.m.volume = 110 self.assertEqual(self.m.volume, 99) + + def test_reopen_device(self): + self.m._device._open = False + self.m.volume = 10 + self.assertTrue(self.m._device._open) From 9e411e4de32b4e76e9987e952385f677566bed85 Mon Sep 17 00:00:00 2001 From: Kristian Date: Wed, 10 Mar 2010 19:27:57 +0100 Subject: [PATCH 03/21] External mixers dont have undefined volume --- tests/mixers/denontest.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/mixers/denontest.py b/tests/mixers/denontest.py index 6256ac38..a26dcff0 100644 --- a/tests/mixers/denontest.py +++ b/tests/mixers/denontest.py @@ -22,9 +22,6 @@ class DenonMixerTest(unittest.TestCase): self.m = DenonMixer() self.m._device = DenonMixerDeviceMock() - def test_volume_is_None_initially(self): - self.assertEqual(self.m.volume, None) - def test_volume_set_to_min(self): self.m.volume = 0 self.assertEqual(self.m.volume, 0) From eee09a54d2efbbdccf4868f52b915fed76a9c24f Mon Sep 17 00:00:00 2001 From: Kristian Date: Wed, 10 Mar 2010 19:28:31 +0100 Subject: [PATCH 04/21] Ask device for volume. Remove internal state. --- mopidy/mixers/denon.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/mopidy/mixers/denon.py b/mopidy/mixers/denon.py index 78bb27a0..ba6efd86 100644 --- a/mopidy/mixers/denon.py +++ b/mopidy/mixers/denon.py @@ -11,15 +11,9 @@ class DenonMixer(BaseMixer): self._volume = None def _get_volume(self): - try: - self._device.write('MV?\r') - vol = self._device.read(2) - if vol: - return self._levels.index(int(vol)) - except: - pass # No support for volume query on device - - return self._volume + self._device.write('MV?\r') + vol = self._device.read(20)[2:4] + return self._levels.index(vol) def _set_volume(self, volume): # Clamp according to Denon-spec From 49171eec5b318788343d04c9abaadac6c943126d Mon Sep 17 00:00:00 2001 From: Kristian Date: Wed, 10 Mar 2010 19:29:14 +0100 Subject: [PATCH 05/21] Denon devices return the current volume on set. --- mopidy/mixers/denon.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mopidy/mixers/denon.py b/mopidy/mixers/denon.py index ba6efd86..8b9b7ef1 100644 --- a/mopidy/mixers/denon.py +++ b/mopidy/mixers/denon.py @@ -25,4 +25,5 @@ class DenonMixer(BaseMixer): if not self._device.isOpen(): self._device.open() self._device.write('MV%s\r'% self._levels[volume]) - self._volume = volume + vol = self._device.read(20)[2:4] + self._volume = self._levels.index(vol) From 631983a14f941fa745b6e7f4b32fe1ef697d5703 Mon Sep 17 00:00:00 2001 From: Kristian Date: Wed, 10 Mar 2010 19:29:54 +0100 Subject: [PATCH 06/21] Update denon device mock to reflect mixer changes --- tests/mixers/denontest.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/mixers/denontest.py b/tests/mixers/denontest.py index a26dcff0..ad7743ce 100644 --- a/tests/mixers/denontest.py +++ b/tests/mixers/denontest.py @@ -6,10 +6,11 @@ from mopidy.mixers.denon import DenonMixer class DenonMixerDeviceMock(object): def __init__(self): self._open = True - self.ret_val = bytes('00') + self.ret_val = bytes('MV00\r') def write(self, x): - pass + if x[2] != '?': + self.ret_val = bytes(x) def read(self, x): return self.ret_val def isOpen(self): From 6f13a49e199dc25e377ba9bb5b31e0e99ef2b906 Mon Sep 17 00:00:00 2001 From: Kristian Date: Wed, 10 Mar 2010 21:19:31 +0100 Subject: [PATCH 07/21] Log volume on _get_volume --- mopidy/mixers/denon.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mopidy/mixers/denon.py b/mopidy/mixers/denon.py index 8b9b7ef1..236a33a9 100644 --- a/mopidy/mixers/denon.py +++ b/mopidy/mixers/denon.py @@ -1,8 +1,11 @@ +import logging + from serial import Serial from mopidy.mixers import BaseMixer from mopidy.settings import MIXER_PORT +logger = logging.get_logger(u'mopidy.mixers.denon') class DenonMixer(BaseMixer): def __init__(self): @@ -13,6 +16,7 @@ class DenonMixer(BaseMixer): def _get_volume(self): self._device.write('MV?\r') vol = self._device.read(20)[2:4] + logger.debug(u'Volume: %s' % self._levels.index(vol)) return self._levels.index(vol) def _set_volume(self, volume): From 5e7b61449fad0221342f32ba0a650a1a6ba01e58 Mon Sep 17 00:00:00 2001 From: Kristian Date: Wed, 10 Mar 2010 21:20:36 +0100 Subject: [PATCH 08/21] Volume filtered by contract --- mopidy/mixers/denon.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mopidy/mixers/denon.py b/mopidy/mixers/denon.py index 236a33a9..b3b23771 100644 --- a/mopidy/mixers/denon.py +++ b/mopidy/mixers/denon.py @@ -21,9 +21,7 @@ class DenonMixer(BaseMixer): def _set_volume(self, volume): # Clamp according to Denon-spec - if not volume: - volume = 0 - elif volume > 99: + if volume > 99: volume = 99 if not self._device.isOpen(): From 85c47977808cfa29472c7fcd0063703e77aa0c80 Mon Sep 17 00:00:00 2001 From: Kristian Date: Wed, 10 Mar 2010 21:21:12 +0100 Subject: [PATCH 09/21] Ensure device connection is open on write and read --- mopidy/mixers/denon.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/mopidy/mixers/denon.py b/mopidy/mixers/denon.py index b3b23771..64d3db4d 100644 --- a/mopidy/mixers/denon.py +++ b/mopidy/mixers/denon.py @@ -14,6 +14,7 @@ class DenonMixer(BaseMixer): self._volume = None def _get_volume(self): + self.ensure_open_device() self._device.write('MV?\r') vol = self._device.read(20)[2:4] logger.debug(u'Volume: %s' % self._levels.index(vol)) @@ -24,8 +25,13 @@ class DenonMixer(BaseMixer): if volume > 99: volume = 99 - if not self._device.isOpen(): - self._device.open() + self.ensure_open_device() self._device.write('MV%s\r'% self._levels[volume]) vol = self._device.read(20)[2:4] self._volume = self._levels.index(vol) + logger.debug(u'Volume: %s' % self._volume) + + def ensure_open_device(self): + if not self._device.isOpen(): + logger.debug(u'(re)connecting to Denon device') + self._device.open() From b9809411724c20d3198bd4c35e08593186e91e63 Mon Sep 17 00:00:00 2001 From: Kristian Date: Wed, 10 Mar 2010 21:21:57 +0100 Subject: [PATCH 10/21] Volume starts as 0 --- mopidy/mixers/denon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mopidy/mixers/denon.py b/mopidy/mixers/denon.py index 64d3db4d..895ae36b 100644 --- a/mopidy/mixers/denon.py +++ b/mopidy/mixers/denon.py @@ -11,7 +11,7 @@ class DenonMixer(BaseMixer): def __init__(self): self._device = Serial(port=MIXER_PORT, timeout=0.2) self._levels = ['99']+["%(#)02d"% {'#': v} for v in range(0,99)] - self._volume = None + self._volume = 0 def _get_volume(self): self.ensure_open_device() From cd5c2ed8837fbd05998664e2f0fe31008b6a2fcf Mon Sep 17 00:00:00 2001 From: Kristian Date: Wed, 10 Mar 2010 22:38:10 +0100 Subject: [PATCH 11/21] Ensure thread-safety on serialport IO. And fixed logging --- mopidy/mixers/denon.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/mopidy/mixers/denon.py b/mopidy/mixers/denon.py index 895ae36b..0537609a 100644 --- a/mopidy/mixers/denon.py +++ b/mopidy/mixers/denon.py @@ -1,35 +1,39 @@ import logging +from threading import Lock from serial import Serial from mopidy.mixers import BaseMixer from mopidy.settings import MIXER_PORT -logger = logging.get_logger(u'mopidy.mixers.denon') +logger = logging.getLogger(u'mopidy.mixers.denon') class DenonMixer(BaseMixer): def __init__(self): self._device = Serial(port=MIXER_PORT, timeout=0.2) self._levels = ['99']+["%(#)02d"% {'#': v} for v in range(0,99)] self._volume = 0 + self._lock = Lock() def _get_volume(self): + self._lock.acquire(); self.ensure_open_device() self._device.write('MV?\r') - vol = self._device.read(20)[2:4] - logger.debug(u'Volume: %s' % self._levels.index(vol)) + vol = self._device.readline()[2:4] + self._lock.release() + logger.debug(u'_get_volume() = %s' % vol) return self._levels.index(vol) def _set_volume(self, volume): # Clamp according to Denon-spec if volume > 99: volume = 99 - + self._lock.acquire() self.ensure_open_device() self._device.write('MV%s\r'% self._levels[volume]) - vol = self._device.read(20)[2:4] + vol = self._device.readline()[2:4] + self._lock.release() self._volume = self._levels.index(vol) - logger.debug(u'Volume: %s' % self._volume) def ensure_open_device(self): if not self._device.isOpen(): From ed2b64448aaf3608ea6ed826b255e048964ffd81 Mon Sep 17 00:00:00 2001 From: Kristian Date: Wed, 10 Mar 2010 22:39:20 +0100 Subject: [PATCH 12/21] Ensure we have proper variable types for lookups. --- mopidy/mixers/denon.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mopidy/mixers/denon.py b/mopidy/mixers/denon.py index 0537609a..45647b72 100644 --- a/mopidy/mixers/denon.py +++ b/mopidy/mixers/denon.py @@ -19,12 +19,13 @@ class DenonMixer(BaseMixer): self._lock.acquire(); self.ensure_open_device() self._device.write('MV?\r') - vol = self._device.readline()[2:4] + vol = str(self._device.readline()[2:4]) self._lock.release() logger.debug(u'_get_volume() = %s' % vol) return self._levels.index(vol) def _set_volume(self, volume): + volume = int(volume) # Clamp according to Denon-spec if volume > 99: volume = 99 From 2e1e595bbc55162cb9c39e969744c300fd5e32ad Mon Sep 17 00:00:00 2001 From: Kristian Date: Wed, 10 Mar 2010 22:50:17 +0100 Subject: [PATCH 13/21] Add Kristian Klette to AUTHORS --- AUTHORS.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.rst b/AUTHORS.rst index 65e7d950..357cb311 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -6,3 +6,4 @@ Contributors to Mopidy in the order of appearance: * Stein Magnus Jodal * Johannes Knutsen * Thomas Adamcik +* Kristian Klette From 39cfb9a07f271ff7bbc05a3872538d281d3ebd9b Mon Sep 17 00:00:00 2001 From: Kristian Date: Wed, 10 Mar 2010 22:50:48 +0100 Subject: [PATCH 14/21] Fixed doc styling on external mixers part --- mopidy/settings/default.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/mopidy/settings/default.py b/mopidy/settings/default.py index d6e18503..a89bc3a6 100644 --- a/mopidy/settings/default.py +++ b/mopidy/settings/default.py @@ -44,13 +44,15 @@ CONSOLE_LOG_FORMAT = u'%(levelname)-8s %(asctime)s [%(threadName)s] %(name)s\n #: Using external mixers depends on the pyserial-library, #: so make sure you have it installed. It also adds one #: more setting, MIXER_PORT. This must point to the device -#: port like /dev/tty1 or similar. +#: port like /dev/tty1 or similar. Example:: #: -#: Available external Mixers:: +#: MIXER_PORT = u'/dev/ttyUSB0' # Verify this manually #: +#: **Available external Mixers** +#: +#: Denon AVR/AVC via RS-232:: #: #: MIXER = u'mopidy.mixers.denon.DenonMixer' -#: MIXER_PORT = u'/dev/tty0' # Verify this manually #: MIXER = u'mopidy.mixers.dummy.DummyMixer' if sys.platform == 'linux2': @@ -58,7 +60,7 @@ if sys.platform == 'linux2': elif sys.platform == 'darwin': MIXER = u'mopidy.mixers.osa.OsaMixer' -MIXER_PORT=None +MIXER_PORT = None #: Which address Mopidy should bind to. Examples: #: From 5f0511aeaea20c7ce99016a0b8baf7c378942147 Mon Sep 17 00:00:00 2001 From: Kristian Date: Wed, 10 Mar 2010 23:07:35 +0100 Subject: [PATCH 15/21] Add space before % --- mopidy/mixers/denon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mopidy/mixers/denon.py b/mopidy/mixers/denon.py index 45647b72..78ed0983 100644 --- a/mopidy/mixers/denon.py +++ b/mopidy/mixers/denon.py @@ -11,7 +11,7 @@ logger = logging.getLogger(u'mopidy.mixers.denon') class DenonMixer(BaseMixer): def __init__(self): self._device = Serial(port=MIXER_PORT, timeout=0.2) - self._levels = ['99']+["%(#)02d"% {'#': v} for v in range(0,99)] + self._levels = ['99']+["%(#)02d" % {'#': v} for v in range(0,99)] self._volume = 0 self._lock = Lock() From 2818e9de59f824ce041d026130f805166773473e Mon Sep 17 00:00:00 2001 From: Kristian Date: Wed, 10 Mar 2010 23:18:02 +0100 Subject: [PATCH 16/21] Update external mixer documentation --- mopidy/settings/default.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/mopidy/settings/default.py b/mopidy/settings/default.py index a89bc3a6..94c5ffdb 100644 --- a/mopidy/settings/default.py +++ b/mopidy/settings/default.py @@ -39,16 +39,10 @@ CONSOLE_LOG_FORMAT = u'%(levelname)-8s %(asctime)s [%(threadName)s] %(name)s\n #: #: MIXER = u'mopidy.mixers.dummy.DummyMixer' #: -#: *Using external mixers* +#: **Available external mixers** #: -#: Using external mixers depends on the pyserial-library, -#: so make sure you have it installed. It also adds one -#: more setting, MIXER_PORT. This must point to the device -#: port like /dev/tty1 or similar. Example:: -#: -#: MIXER_PORT = u'/dev/ttyUSB0' # Verify this manually -#: -#: **Available external Mixers** +#: .. note:: +#: Using external mixers depends on the pyserial library. #: #: Denon AVR/AVC via RS-232:: #: @@ -60,6 +54,8 @@ if sys.platform == 'linux2': elif sys.platform == 'darwin': MIXER = u'mopidy.mixers.osa.OsaMixer' +#: Which port a mixer is connected to if using an external mixer. +#: This must point to the device port like ``/dev/ttyUSB0`` or similar. MIXER_PORT = None #: Which address Mopidy should bind to. Examples: From ea45bb899332965a39621670393df3f643f7b6e3 Mon Sep 17 00:00:00 2001 From: Kristian Date: Wed, 10 Mar 2010 23:19:13 +0100 Subject: [PATCH 17/21] Fix typo in external mixer documentation --- mopidy/settings/default.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mopidy/settings/default.py b/mopidy/settings/default.py index 94c5ffdb..7f6d1d88 100644 --- a/mopidy/settings/default.py +++ b/mopidy/settings/default.py @@ -54,7 +54,7 @@ if sys.platform == 'linux2': elif sys.platform == 'darwin': MIXER = u'mopidy.mixers.osa.OsaMixer' -#: Which port a mixer is connected to if using an external mixer. +#: Which port the mixer is connected to if using an external mixer. #: This must point to the device port like ``/dev/ttyUSB0`` or similar. MIXER_PORT = None From 850277afd190e69a4a8feb533a9eec312da8f37f Mon Sep 17 00:00:00 2001 From: Kristian Date: Wed, 10 Mar 2010 23:21:14 +0100 Subject: [PATCH 18/21] Style fix. Add some spacing --- mopidy/mixers/denon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mopidy/mixers/denon.py b/mopidy/mixers/denon.py index 78ed0983..118abf28 100644 --- a/mopidy/mixers/denon.py +++ b/mopidy/mixers/denon.py @@ -11,7 +11,7 @@ logger = logging.getLogger(u'mopidy.mixers.denon') class DenonMixer(BaseMixer): def __init__(self): self._device = Serial(port=MIXER_PORT, timeout=0.2) - self._levels = ['99']+["%(#)02d" % {'#': v} for v in range(0,99)] + self._levels = ['99'] + ["%(#)02d" % {'#': v} for v in range(0, 99)] self._volume = 0 self._lock = Lock() From 11ad608c75a7175f24e72e5f9d2337511527235d Mon Sep 17 00:00:00 2001 From: Kristian Date: Wed, 10 Mar 2010 23:21:40 +0100 Subject: [PATCH 19/21] Remove redundant type-conversion --- mopidy/mixers/denon.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mopidy/mixers/denon.py b/mopidy/mixers/denon.py index 118abf28..de0968a9 100644 --- a/mopidy/mixers/denon.py +++ b/mopidy/mixers/denon.py @@ -25,7 +25,6 @@ class DenonMixer(BaseMixer): return self._levels.index(vol) def _set_volume(self, volume): - volume = int(volume) # Clamp according to Denon-spec if volume > 99: volume = 99 From 55fe11046fe043648f69534410b91832ab598a88 Mon Sep 17 00:00:00 2001 From: Kristian Date: Wed, 10 Mar 2010 23:29:25 +0100 Subject: [PATCH 20/21] Added some module documentation to DenonMixer --- mopidy/mixers/denon.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/mopidy/mixers/denon.py b/mopidy/mixers/denon.py index de0968a9..374875b9 100644 --- a/mopidy/mixers/denon.py +++ b/mopidy/mixers/denon.py @@ -8,6 +8,23 @@ from mopidy.settings import MIXER_PORT logger = logging.getLogger(u'mopidy.mixers.denon') +#: Mixer for controlling Denon recivers and amplifiers using the RS-232 protocol. +#: +#: Connects using the serial specifications from +#: Denon's RS-232 Protocol specification. +#: +#: Communication speed : 9600bps +#: Character length : 8 bits +#: Parity control : None +#: Start bit : 1 bit +#: Stop bit : 1 bit +#: Communication procedure : Non procedural +#: Communication data length : 135 bytes (maximum) +#: +#: The external mixer is the authoritative source for the current volume. +#: This allows the user to use his remote control the volume without +#: mopidy cancelling the volume setting. + class DenonMixer(BaseMixer): def __init__(self): self._device = Serial(port=MIXER_PORT, timeout=0.2) From cb6a2b18495c9731b47d14a983b4f42ddbd07bad Mon Sep 17 00:00:00 2001 From: Kristian Date: Wed, 10 Mar 2010 23:32:13 +0100 Subject: [PATCH 21/21] Convert DenonMixer module doc to docstring --- mopidy/mixers/denon.py | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/mopidy/mixers/denon.py b/mopidy/mixers/denon.py index 374875b9..426b2db3 100644 --- a/mopidy/mixers/denon.py +++ b/mopidy/mixers/denon.py @@ -8,22 +8,24 @@ from mopidy.settings import MIXER_PORT logger = logging.getLogger(u'mopidy.mixers.denon') -#: Mixer for controlling Denon recivers and amplifiers using the RS-232 protocol. -#: -#: Connects using the serial specifications from -#: Denon's RS-232 Protocol specification. -#: -#: Communication speed : 9600bps -#: Character length : 8 bits -#: Parity control : None -#: Start bit : 1 bit -#: Stop bit : 1 bit -#: Communication procedure : Non procedural -#: Communication data length : 135 bytes (maximum) -#: -#: The external mixer is the authoritative source for the current volume. -#: This allows the user to use his remote control the volume without -#: mopidy cancelling the volume setting. +""" + Mixer for controlling Denon recivers and amplifiers using the RS-232 protocol. + + Connects using the serial specifications from + Denon's RS-232 Protocol specification. + + Communication speed : 9600bps + Character length : 8 bits + Parity control : None + Start bit : 1 bit + Stop bit : 1 bit + Communication procedure : Non procedural + Communication data length : 135 bytes (maximum) + + The external mixer is the authoritative source for the current volume. + This allows the user to use his remote control the volume without + mopidy cancelling the volume setting. +""" class DenonMixer(BaseMixer): def __init__(self):