Merge pull request #328 from ethanaward/feature/issues-303

Add configurable volume levels (Fixes #303)
pull/330/head
Arron Atchison 2016-08-16 15:35:41 -05:00 committed by GitHub
commit 3993934b4b
2 changed files with 73 additions and 59 deletions

View File

@ -92,7 +92,9 @@ repeat_time = 60 # in seconds
extended_delay = 60 # in seconds extended_delay = 60 # in seconds
[VolumeSkill] [VolumeSkill]
default_volume = 70 # 0-100 default_level = 6 # 0-11
min_volume = 0 # 0 - 100
max_volume = 100
[AudioRecordSkill] [AudioRecordSkill]
filename = /tmp/mycroft-recording.wav filename = /tmp/mycroft-recording.wav

View File

@ -21,8 +21,6 @@ from alsaaudio import Mixer
from os.path import dirname, join from os.path import dirname, join
from adapt.intent import IntentBuilder from adapt.intent import IntentBuilder
from mycroft.client.enclosure import enclosure
from mycroft.skills.core import MycroftSkill from mycroft.skills.core import MycroftSkill
from mycroft.util import play_wav from mycroft.util import play_wav
from mycroft.util.log import getLogger from mycroft.util.log import getLogger
@ -33,12 +31,24 @@ LOGGER = getLogger(__name__)
class VolumeSkill(MycroftSkill): class VolumeSkill(MycroftSkill):
VOLUMES = {0: 0, 1: 15, 2: 25, 3: 35, 4: 45, 5: 55, 6: 65, 7: 70, 8: 80, """
9: 90, 10: 95, 11: 100} "Level" refers to the custom units from 0 to 11
"Volume" refers to the ALSA mixer setting from 0 to 100
"""
MIN_LEVEL = 0
MAX_LEVEL = 11
VOLUME_WORDS = {
'loud': 9,
'normal': 6,
'quiet': 3
}
def __init__(self): def __init__(self):
super(VolumeSkill, self).__init__(name="VolumeSkill") super(VolumeSkill, self).__init__(name="VolumeSkill")
self.default_volume = int(self.config.get('default_volume')) self.default_level = int(self.config.get('default_level'))
self.min_volume = self.config.get('min_volume')
self.max_volume = self.config.get('max_volume')
self.volume_sound = join(dirname(__file__), "blop-mark-diangelo.wav") self.volume_sound = join(dirname(__file__), "blop-mark-diangelo.wav")
def initialize(self): def initialize(self):
@ -68,9 +78,9 @@ class VolumeSkill(MycroftSkill):
def handle_set_volume(self, message): def handle_set_volume(self, message):
mixer = Mixer() mixer = Mixer()
code, volume = self.get_volume(message, mixer.getvolume()[0]) level = self.get_volume_level(message, mixer.getvolume()[0])
mixer.setvolume(volume) mixer.setvolume(self.level_to_volume(level))
self.speak_dialog('set.volume', data={'volume': code}) self.speak_dialog('set.volume', data={'volume': level})
def communicate_volume_change(self, message, dialog, code, changed): def communicate_volume_change(self, message, dialog, code, changed):
play_sound = message.metadata.get('play_sound', False) play_sound = message.metadata.get('play_sound', False)
@ -96,66 +106,68 @@ class VolumeSkill(MycroftSkill):
Mixer().setvolume(0) Mixer().setvolume(0)
def handle_reset_volume(self, message): def handle_reset_volume(self, message):
Mixer().setvolume(self.default_volume) Mixer().setvolume(self.level_to_volume(self.default_level))
self.speak_dialog( self.speak_dialog('reset.volume', data={'volume': self.default_level})
'reset.volume',
data={'volume': self.get_volume_code(self.default_volume)})
def __update_volume(self, level=0): def volume_to_level(self, volume):
"""
:param volume: min_volume..max_volume
:rtype int
"""
range = self.MAX_LEVEL - self.MIN_LEVEL
proportion = float(volume - self.min_volume) / self.max_volume
level = int(round(self.MIN_LEVEL + range * proportion))
if level > self.MAX_LEVEL:
level = self.MAX_LEVEL
elif level < self.MIN_LEVEL:
level = self.MIN_LEVEL
return level
def level_to_volume(self, level):
"""
:param level: 0..MAX_LEVEL
:rtype int
"""
range = self.max_volume - self.min_volume
proportion = float(level) / self.MAX_LEVEL
volume = int(round(self.min_volume + range * proportion))
return volume
@staticmethod
def bound_level(level):
if level > VolumeSkill.MAX_LEVEL:
level = VolumeSkill.MAX_LEVEL
elif level < VolumeSkill.MIN_LEVEL:
level = VolumeSkill.MIN_LEVEL
return level
def __update_volume(self, change=0):
""" """
Tries to change volume level Tries to change volume level
:param level: +1 or -1; the step to change by :param change: +1 or -1; the step to change by
:return: new code (0..11), whether volume changed :return: new code (0..11), whether volume changed
""" """
mixer = Mixer() mixer = Mixer()
volume = mixer.getvolume()[0] old_level = self.volume_to_level(mixer.getvolume()[0])
old_code = self.get_volume_code(volume) new_level = self.bound_level(old_level + change)
mixer.setvolume(self.level_to_volume(new_level))
return new_level, new_level != old_level
new_code = self.fix_code(old_code + level) def get_volume_level(self, message, default=None):
if new_code in self.VOLUMES: level_str = message.metadata.get('VolumeAmount', default)
volume = self.VOLUMES[new_code] level = self.default_level
self.enclosure.eyes_volume(new_code)
mixer.setvolume(volume)
return new_code, new_code != old_code
def get_volume(self, message, default=None): try:
amount = message.metadata.get('VolumeAmount', default) level = self.VOLUME_WORDS[level_str]
if not amount: except KeyError:
return self.default_volume
if amount in ['loud']:
amount = 9
elif amount in ['normal']:
amount = 6
elif amount in ['quiet']:
amount = 3
elif amount in ['two']:
amount = 2
elif amount in ['one']:
amount = 1
elif amount in ['zero']:
amount = 0
else:
try: try:
amount = int(amount) level = int(level_str)
except: except ValueError:
return self.default_volume pass
amount = self.fix_code(amount) level = self.bound_level(level)
return amount, self.VOLUMES[amount] return level
def get_volume_code(self, volume):
for k, v in self.VOLUMES.iteritems():
if volume <= v:
return k
@staticmethod
def fix_code(code):
if code > 11:
code = 11
elif code < 0:
code = 0
return code
def stop(self): def stop(self):
pass pass