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
|
* 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`
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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+)*"$')
|
||||||
|
|||||||
@ -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"')
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user