Add volume control support to BaseBackend through alsaaudio.Mixer
This commit is contained in:
parent
f9a9a0e82b
commit
0a6545f6d0
@ -14,6 +14,7 @@ Dependencies
|
||||
============
|
||||
|
||||
* Python >= 2.5
|
||||
* pyalsaaudio >= 0.2 (Debian/Ubuntu: python-alsaaudio)
|
||||
* Dependencies for at least one Mopidy backend:
|
||||
|
||||
* :ref:`despotify`
|
||||
|
||||
@ -3,6 +3,8 @@ import logging
|
||||
import random
|
||||
import time
|
||||
|
||||
import alsaaudio
|
||||
|
||||
from mopidy.models import Playlist
|
||||
|
||||
logger = logging.getLogger('backends.base')
|
||||
@ -242,13 +244,10 @@ class BasePlaybackController(object):
|
||||
#: The current track is played once.
|
||||
repeat = False
|
||||
|
||||
#: The audio volume as an int in the range [0, 100]. :class:`None` if
|
||||
#: unknown.
|
||||
volume = None
|
||||
|
||||
def __init__(self, backend):
|
||||
def __init__(self, backend, mixer=alsaaudio.Mixer):
|
||||
self.backend = backend
|
||||
self._state = self.STOPPED
|
||||
self._mixer = mixer()
|
||||
|
||||
@property
|
||||
def next_track(self):
|
||||
@ -325,6 +324,19 @@ class BasePlaybackController(object):
|
||||
def _play_time_resume(self):
|
||||
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):
|
||||
"""Tell the playback controller that a new playlist has been loaded."""
|
||||
self.current_track = None
|
||||
|
||||
@ -7,7 +7,7 @@ class DummyBackend(BaseBackend):
|
||||
def __init__(self):
|
||||
self.current_playlist = DummyCurrentPlaylistController(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.uri_handlers = [u'dummy:']
|
||||
|
||||
@ -37,3 +37,12 @@ class DummyPlaybackController(BasePlaybackController):
|
||||
class DummyStoredPlaylistsController(BaseStoredPlaylistsController):
|
||||
def search(self, 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
|
||||
|
||||
@ -419,14 +419,15 @@ class MpdHandler(object):
|
||||
def _seekid(self, songid, seconds):
|
||||
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):
|
||||
volume = int(volume)
|
||||
if volume < 0:
|
||||
volume = 0
|
||||
if volume > 100:
|
||||
volume = 100
|
||||
raise MpdNotImplemented # TODO
|
||||
self.backend.playback.volume = volume
|
||||
|
||||
@register(r'^shuffle$')
|
||||
@register(r'^shuffle "(?P<start>\d+):(?P<end>\d+)*"$')
|
||||
|
||||
@ -290,7 +290,8 @@ class StatusHandlerTest(unittest.TestCase):
|
||||
|
||||
class PlaybackOptionsHandlerTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.h = handler.MpdHandler(backend=DummyBackend())
|
||||
self.b = DummyBackend()
|
||||
self.h = handler.MpdHandler(backend=self.b)
|
||||
|
||||
def test_consume_off(self):
|
||||
result = self.h.handle_request(u'consume "0"')
|
||||
@ -322,23 +323,33 @@ class PlaybackOptionsHandlerTest(unittest.TestCase):
|
||||
|
||||
def test_setvol_below_min(self):
|
||||
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):
|
||||
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):
|
||||
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):
|
||||
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):
|
||||
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):
|
||||
result = self.h.handle_request(u'single "0"')
|
||||
|
||||
Loading…
Reference in New Issue
Block a user