예제 #1
0
    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))
예제 #2
0
파일: ctrl.py 프로젝트: micro-nova/AmpliPi
  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))