def set_zone(self, id, name=None, source_id=None, mute=None, vol=None, disabled=None, force_update=False): """Configures a zone Args: id (int): any valid zone [0,p*6-1] (6 zones per preamp) name(str): friendly name for the zone, ie "bathroom" or "kitchen 1" source_id (int): source to connect to [0,4] mute (bool): mute the zone regardless of set volume vol (int): attenuation [-79,0] 0 is max volume, -79 is min volume disabled (bool): disable zone, for when the zone is not connected to any speakers and not in use force_update: bool, update source even if no changes have been made (for hw startup) Returns: 'None' on success, otherwise error (dict) """ idx = None for i, s in enumerate(self.status['zones']): if s['id'] == int(id): idx = i if idx is not None: try: z = self.status['zones'][idx] # TODO: use updated? value name, _ = utils.updated_val(name, z['name']) source_id, update_source_id = utils.updated_val( source_id, z['source_id']) mute, update_mutes = utils.updated_val(mute, z['mute']) vol, update_vol = utils.updated_val(vol, z['vol']) disabled, _ = utils.updated_val(disabled, z['disabled']) except Exception as e: return utils.error( 'failed to set zone, error getting current state: {}'. format(e)) try: sid = utils.parse_int(source_id, [0, 1, 2, 3, 4]) vol = utils.parse_int( vol, range(-79, 79) ) # hold additional state for group delta volume adjustments, output volume will be saturated to 0dB zones = self.status['zones'] # update non hw state z['name'] = name z['disabled'] = disabled # TODO: figure out an order of operations here, like does mute need to be done before changing sources? if update_source_id or force_update: zone_sources = [zone['source_id'] for zone in zones] zone_sources[idx] = sid if self._rt.update_zone_sources(idx, zone_sources): z['source_id'] = sid else: return utils.error( 'set zone failed: unable to update zone source') if update_mutes or force_update: mutes = [zone['mute'] for zone in zones] mutes[idx] = mute if self._rt.update_zone_mutes(idx, mutes): z['mute'] = mute else: return utils.error( 'set zone failed: unable to update zone mute') if update_vol or force_update: real_vol = utils.clamp(vol, -79, 0) if self._rt.update_zone_vol(idx, real_vol): z['vol'] = vol else: return utils.error( 'set zone failed: unable to update zone volume') # update the group stats (individual zone volumes, sources, and mute configuration can effect a group) self._update_groups() return None except Exception as e: return utils.error('set zone: ' + str(e)) else: return utils.error('set zone: index {} out of bounds'.format(idx))
def set_zone(self, zid, update: models.ZoneUpdate, force_update: bool = False, internal: bool = False) -> ApiResponse: """Reconfigures a zone Args: id: any valid zone [0,p*6-1] (6 zones per preamp) update: changes to zone force_update: update source even if no changes have been made (for hw startup) internal: called by a higher-level ctrl function Returns: ApiResponse """ idx, zone = utils.find(self.status.zones, zid) if idx is not None and zone is not None: name, _ = utils.updated_val(update.name, zone.name) source_id, update_source_id = utils.updated_val(update.source_id, zone.source_id) mute, update_mutes = utils.updated_val(update.mute, zone.mute) vol, update_vol = utils.updated_val(update.vol, zone.vol) disabled, _ = utils.updated_val(update.disabled, zone.disabled) try: sid = utils.parse_int(source_id, [0, 1, 2, 3]) vol = utils.parse_int(vol, range(-79, 79)) # hold additional state for group delta volume adjustments, output volume will be saturated to 0dB zones = self.status.zones # update non hw state zone.name = name zone.disabled = disabled if update_source_id or force_update: zone_sources = [zone.source_id for zone in zones] zone_sources[idx] = sid if self._rt.update_zone_sources(idx, zone_sources): zone.source_id = sid else: return ApiResponse.error('set zone failed: unable to update zone source') def set_mute(): mutes = [zone.mute for zone in zones] mutes[idx] = mute if self._rt.update_zone_mutes(idx, mutes): zone.mute = mute else: raise Exception('set zone failed: unable to update zone mute') def set_vol(): real_vol = utils.clamp(vol, -79, 0) if self._rt.update_zone_vol(idx, real_vol): zone.vol = vol else: raise Exception('set zone failed: unable to update zone volume') # To avoid potential unwanted loud output: # If muting, mute before setting volumes # If un-muting, set desired volume first try: if force_update or (update_mutes and update_vol): if mute: set_mute() set_vol() else: set_vol() set_mute() elif update_vol: set_vol() elif update_mutes: set_mute() except Exception as exc: return ApiResponse.error(str(exc)) if not internal: # update the group stats (individual zone volumes, sources, and mute configuration can effect a group) self._update_groups() self.mark_changes() return ApiResponse.ok() except Exception as exc: return ApiResponse.error('set zone: ' + str(exc)) else: return ApiResponse.error('set zone: index {} out of bounds'.format(idx))