Add volume control support to BaseBackend through alsaaudio.Mixer

This commit is contained in:
Stein Magnus Jodal 2010-02-22 19:47:25 +01:00
parent f9a9a0e82b
commit 0a6545f6d0
5 changed files with 48 additions and 14 deletions

View File

@ -14,6 +14,7 @@ Dependencies
============ ============
* Python >= 2.5 * Python >= 2.5
* pyalsaaudio >= 0.2 (Debian/Ubuntu: python-alsaaudio)
* Dependencies for at least one Mopidy backend: * Dependencies for at least one Mopidy backend:
* :ref:`despotify` * :ref:`despotify`

View File

@ -3,6 +3,8 @@ import logging
import random import random
import time import time
import alsaaudio
from mopidy.models import Playlist from mopidy.models import Playlist
logger = logging.getLogger('backends.base') logger = logging.getLogger('backends.base')
@ -242,13 +244,10 @@ class BasePlaybackController(object):
#: The current track is played once. #: The current track is played once.
repeat = False repeat = False
#: The audio volume as an int in the range [0, 100]. :class:`None` if def __init__(self, backend, mixer=alsaaudio.Mixer):
#: unknown.
volume = None
def __init__(self, backend):
self.backend = backend self.backend = backend
self._state = self.STOPPED self._state = self.STOPPED
self._mixer = mixer()
@property @property
def next_track(self): def next_track(self):
@ -325,6 +324,19 @@ class BasePlaybackController(object):
def _play_time_resume(self): def _play_time_resume(self):
self._play_time_started = int(time.time()) self._play_time_started = int(time.time())
@property
def volume(self):
"""
The audio volume as an int in the range [0, 100].
:class:`None` if unknown.
"""
return self._mixer.getvolume()[0]
@volume.setter
def volume(self, volume):
self._mixer.setvolume(volume)
def new_playlist_loaded_callback(self): def new_playlist_loaded_callback(self):
"""Tell the playback controller that a new playlist has been loaded.""" """Tell the playback controller that a new playlist has been loaded."""
self.current_track = None self.current_track = None

View File

@ -7,7 +7,7 @@ class DummyBackend(BaseBackend):
def __init__(self): def __init__(self):
self.current_playlist = DummyCurrentPlaylistController(backend=self) self.current_playlist = DummyCurrentPlaylistController(backend=self)
self.library = DummyLibraryController(backend=self) self.library = DummyLibraryController(backend=self)
self.playback = DummyPlaybackController(backend=self) self.playback = DummyPlaybackController(backend=self, mixer=DummyMixer)
self.stored_playlists = DummyStoredPlaylistsController(backend=self) self.stored_playlists = DummyStoredPlaylistsController(backend=self)
self.uri_handlers = [u'dummy:'] self.uri_handlers = [u'dummy:']
@ -37,3 +37,12 @@ class DummyPlaybackController(BasePlaybackController):
class DummyStoredPlaylistsController(BaseStoredPlaylistsController): class DummyStoredPlaylistsController(BaseStoredPlaylistsController):
def search(self, query): def search(self, query):
return [Playlist(name=query)] return [Playlist(name=query)]
class DummyMixer(object):
volume = 0
def getvolume(self):
return [self.volume, self.volume]
def setvolume(self, volume):
self.volume = volume

View File

@ -419,14 +419,15 @@ class MpdHandler(object):
def _seekid(self, songid, seconds): def _seekid(self, songid, seconds):
raise MpdNotImplemented # TODO raise MpdNotImplemented # TODO
@register(r'^setvol "(?P<volume>-*\d+)"$') @register(r'^setvol (?P<volume>[-+]*\d+)$')
@register(r'^setvol "(?P<volume>[-+]*\d+)"$')
def _setvol(self, volume): def _setvol(self, volume):
volume = int(volume) volume = int(volume)
if volume < 0: if volume < 0:
volume = 0 volume = 0
if volume > 100: if volume > 100:
volume = 100 volume = 100
raise MpdNotImplemented # TODO self.backend.playback.volume = volume
@register(r'^shuffle$') @register(r'^shuffle$')
@register(r'^shuffle "(?P<start>\d+):(?P<end>\d+)*"$') @register(r'^shuffle "(?P<start>\d+):(?P<end>\d+)*"$')

View File

@ -290,7 +290,8 @@ class StatusHandlerTest(unittest.TestCase):
class PlaybackOptionsHandlerTest(unittest.TestCase): class PlaybackOptionsHandlerTest(unittest.TestCase):
def setUp(self): def setUp(self):
self.h = handler.MpdHandler(backend=DummyBackend()) self.b = DummyBackend()
self.h = handler.MpdHandler(backend=self.b)
def test_consume_off(self): def test_consume_off(self):
result = self.h.handle_request(u'consume "0"') result = self.h.handle_request(u'consume "0"')
@ -322,23 +323,33 @@ class PlaybackOptionsHandlerTest(unittest.TestCase):
def test_setvol_below_min(self): def test_setvol_below_min(self):
result = self.h.handle_request(u'setvol "-10"') result = self.h.handle_request(u'setvol "-10"')
self.assert_(u'ACK Not implemented' in result) self.assert_(u'OK' in result)
self.assertEqual(0, self.b.playback.volume)
def test_setvol_min(self): def test_setvol_min(self):
result = self.h.handle_request(u'setvol "0"') result = self.h.handle_request(u'setvol "0"')
self.assert_(u'ACK Not implemented' in result) self.assert_(u'OK' in result)
self.assertEqual(0, self.b.playback.volume)
def test_setvol_middle(self): def test_setvol_middle(self):
result = self.h.handle_request(u'setvol "50"') result = self.h.handle_request(u'setvol "50"')
self.assert_(u'ACK Not implemented' in result) self.assert_(u'OK' in result)
self.assertEqual(50, self.b.playback.volume)
def test_setvol_max(self): def test_setvol_max(self):
result = self.h.handle_request(u'setvol "100"') result = self.h.handle_request(u'setvol "100"')
self.assert_(u'ACK Not implemented' in result) self.assert_(u'OK' in result)
self.assertEqual(100, self.b.playback.volume)
def test_setvol_above_max(self): def test_setvol_above_max(self):
result = self.h.handle_request(u'setvol "110"') result = self.h.handle_request(u'setvol "110"')
self.assert_(u'ACK Not implemented' in result) self.assert_(u'OK' in result)
self.assertEqual(100, self.b.playback.volume)
def test_setvol_plus_is_ignored(self):
result = self.h.handle_request(u'setvol "+10"')
self.assert_(u'OK' in result)
self.assertEqual(10, self.b.playback.volume)
def test_single_off(self): def test_single_off(self):
result = self.h.handle_request(u'single "0"') result = self.h.handle_request(u'single "0"')