Skip to content

Commit 79f3a0f

Browse files
committed
Service volume control for hardware platforms (FAST-AUD)
1 parent 99ca177 commit 79f3a0f

File tree

2 files changed

+53
-18
lines changed

2 files changed

+53
-18
lines changed

mpf/modes/service/code/service.py

+40-13
Original file line numberDiff line numberDiff line change
@@ -188,11 +188,22 @@ async def _adjustments_menu(self):
188188
# Audio
189189
def _load_audio_menu_entries(self) -> List[ServiceMenuEntry]:
190190
"""Return the audio menu items with label and callback."""
191-
return [
191+
items = [
192192
ServiceMenuEntry("Software Levels", self._volume_menu)
193-
# TODO: Add hardware platform volume control
194193
]
195194

195+
self.debug_log("Looking for platform volumes: %s", self.machine.hardware_platforms)
196+
for p, platform in self.machine.hardware_platforms.items():
197+
# TODO: Define an AudioInterface base class
198+
if getattr(platform, "audio_interface", None):
199+
self.debug_log("Found '%s' platform audio for volume: %s", p, platform)
200+
# TODO: find a good way to get a name of a platform
201+
name = p.title()
202+
items.append(ServiceMenuEntry(f"{name} Levels", partial(self._volume_menu, platform)))
203+
else:
204+
self.debug_log("Platform '%s' has no audio to configure volume: %s", p, platform)
205+
return items
206+
196207
async def _audio_menu(self):
197208
await self._make_menu(self._load_audio_menu_entries())
198209

@@ -453,16 +464,25 @@ def _load_software_sound_menu_entries(self) -> List[ServiceMenuEntry]:
453464
for track, config in self.machine.config["sound_system"]["tracks"].items()
454465
]
455466

456-
async def _volume_menu(self):
467+
async def _volume_menu(self, platform=None):
457468
position = 0
469+
if platform:
470+
item_configs = platform.audio_interface.amps
471+
else:
472+
item_configs = self.machine.config["sound_system"]["tracks"]
458473
items = [{**config, "name": track, "label": config.get("label", track),
459-
"value": int((self.machine.variables.get_machine_var(f"{track}_volume") or config['volume']) * 100)
460-
} for track, config in self.machine.config["sound_system"]["tracks"].items()]
474+
"value": (self.machine.variables.get_machine_var(f"{track}_volume") or config['volume'])
475+
} for track, config in item_configs.items()]
461476

462477
# do not crash if no items
463478
if not items: # pragma: no cover
464479
return
465480

481+
# Convert floats to ints for systems that use 0.0-1.0 for volume
482+
for item in items:
483+
if isinstance(item['value'], float):
484+
item['value'] = int(item['value'] * 100)
485+
466486
self._update_volume_slide(items, position)
467487

468488
while True:
@@ -481,31 +501,38 @@ async def _volume_menu(self):
481501
self._update_volume_slide(items, position)
482502
elif key == 'ENTER':
483503
# change setting
484-
await self._volume_change(items, position)
504+
await self._volume_change(items, position, focus_change="enter")
485505

486506
self.machine.events.post("service_volume_stop")
487507

488508

489-
def _update_volume_slide(self, items, position, is_change=False):
509+
def _update_volume_slide(self, items, position, is_change=False, focus_change=None):
490510
config = items[position]
491511
event = "service_volume_{}".format("edit" if is_change else "start")
512+
# The 'focus_change' argument can be used to start/stop sound files playing
513+
# during the service menu, to test volume.
492514
self.machine.events.post(event,
493515
settings_label=config["label"],
494-
value_label="%d%%" % config["value"])
516+
value_label=config["value"],
517+
track=config["name"],
518+
focus_change=focus_change)
495519

496-
async def _volume_change(self, items, position):
497-
self._update_volume_slide(items, position)
520+
async def _volume_change(self, items, position, focus_change=None):
521+
self._update_volume_slide(items, position, focus_change=focus_change)
498522

499-
# Use ints for values to avoid floating-point comparisons
500-
values = [int((0.05 * i) * 100) for i in range(0,21)]
523+
if items[position].get("levels_list"):
524+
values = items[position]["levels_list"]
525+
else:
526+
# Use ints for values to avoid floating-point comparisons
527+
values = [int((0.05 * i) * 100) for i in range(0,21)]
501528
value_position = values.index(items[position]["value"])
502529
self._update_volume_slide(items, position, is_change=True)
503530

504531
while True:
505532
key = await self._get_key()
506533
new_value = None
507534
if key == 'ESC':
508-
self._update_volume_slide(items, position)
535+
self._update_volume_slide(items, position, focus_change="exit")
509536
break
510537
if key == 'UP':
511538
value_position += 1

mpf/platforms/fast/fast_audio.py

+13-5
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ def __init__(self, platform, communicator):
1212
self.platform = platform
1313
self.machine = platform.machine
1414
self.communicator = communicator
15-
self.amps = {'main': {}, 'sub': {}, 'headphones': {}}
15+
self.amps = {
16+
'main': { 'label': "Speakers" },
17+
'sub': { 'label': "Subwoofer" },
18+
'headphones': { 'label': "Headphones" }
19+
}
1620
self.control_pin_pulse_times = list()
1721

1822
# need to get this in before the soft_reset(), but after machine vars load
@@ -45,6 +49,7 @@ def _init_amps(self):
4549
self.amps[amp]['max_volume'] = self.communicator.config[f'max_hw_volume_{amp}']
4650
self.amps[amp]['levels_list'] = self.communicator.config[f'{amp}_levels_list']
4751
self.amps[amp]['link_to_main'] = self.communicator.config[f'link_{amp}_to_main']
52+
self.amps[amp]['volume'] = self.get_volume(amp)
4853

4954
# Just set everything here. The communicator will send the
5055
# config as part of its init process later
@@ -144,16 +149,19 @@ def set_volume(self, amp, value=0, **kwargs):
144149
value = 0
145150

146151
self.send_volume_to_hw(amp)
152+
self._set_machine_var_volume(amp, value)
147153

148-
for other_amp in self.amps.keys():
149-
if self.amps[other_amp]['link_to_main'] and other_amp != amp:
150-
self._set_machine_var_volume(other_amp, self.amps[amp]['levels_list'][value])
151-
self.send_volume_to_hw(other_amp)
154+
if amp == self.amps['main']:
155+
for other_amp in self.amps.keys():
156+
if self.amps[other_amp]['link_to_main'] and other_amp != amp:
157+
self._set_machine_var_volume(other_amp, self.amps[amp]['levels_list'][value])
158+
self.send_volume_to_hw(other_amp)
152159

153160
def get_volume(self, amp, **kwargs):
154161
return self.machine.variables.get_machine_var(f'fast_audio_{amp}_volume')
155162

156163
def _set_machine_var_volume(self, amp, value):
164+
amp['volume'] = value
157165
self.machine.variables.set_machine_var(f'fast_audio_{amp}_volume', value)
158166

159167
def temp_volume(self, amp, change=1, **kwargs):

0 commit comments

Comments
 (0)