/* Helper to fill in the range (src_min, src_max, dest_min, dest_max) * based on message parameters and known connection and signal * properties; return flags to indicate which parts of the range were * found. */ static int set_range(mapper_connection c, mapper_message_t *msg) { lo_arg **args = NULL; const char *types = NULL; int i, length = 0, updated = 0, result; if (!c) return 0; /* The logic here is to first try to use information from the * message, starting with @srcMax, @srcMin, @destMax, @destMin, * and then @min and @max. * Next priority is already-known properties of the connection. * Lastly, we fill in source range from the signal. */ /* @srcMax */ args = mapper_msg_get_param(msg, AT_SRC_MAX); types = mapper_msg_get_type(msg, AT_SRC_MAX); length = mapper_msg_get_length(msg, AT_SRC_MAX); if (args && types && is_number_type(types[0])) { if (length == c->props.src_length) { if (!c->props.src_max) c->props.src_max = calloc(1, length * c->props.src_type); c->props.range_known |= CONNECTION_RANGE_SRC_MAX; for (i=0; i<length; i++) { result = propval_set_from_lo_arg(c->props.src_max, c->props.src_type, args[i], types[i], i); if (result == -1) { c->props.range_known &= ~CONNECTION_RANGE_SRC_MAX; break; } else updated += result; } } else c->props.range_known &= ~CONNECTION_RANGE_SRC_MAX; } /* @srcMin */ args = mapper_msg_get_param(msg, AT_SRC_MIN); types = mapper_msg_get_type(msg, AT_SRC_MIN); length = mapper_msg_get_length(msg, AT_SRC_MIN); if (args && types && is_number_type(types[0])) { if (length == c->props.src_length) { if (!c->props.src_min) c->props.src_min = calloc(1, length * c->props.src_type); c->props.range_known |= CONNECTION_RANGE_SRC_MIN; for (i=0; i<length; i++) { result = propval_set_from_lo_arg(c->props.src_min, c->props.src_type, args[i], types[i], i); if (result == -1) { c->props.range_known &= ~CONNECTION_RANGE_SRC_MIN; break; } else updated += result; } } else c->props.range_known &= ~CONNECTION_RANGE_SRC_MIN; } /* @destMax */ args = mapper_msg_get_param(msg, AT_DEST_MAX); types = mapper_msg_get_type(msg, AT_DEST_MAX); length = mapper_msg_get_length(msg, AT_DEST_MAX); if (args && types && is_number_type(types[0])) { if (length == c->props.dest_length) { if (!c->props.dest_max) c->props.dest_max = calloc(1, length * c->props.dest_type); c->props.range_known |= CONNECTION_RANGE_DEST_MAX; for (i=0; i<length; i++) { result = propval_set_from_lo_arg(c->props.dest_max, c->props.dest_type, args[i], types[i], i); if (result == -1) { c->props.range_known &= ~CONNECTION_RANGE_DEST_MAX; break; } else updated += result; } } else c->props.range_known &= ~CONNECTION_RANGE_DEST_MAX; } /* @destMin */ args = mapper_msg_get_param(msg, AT_DEST_MIN); types = mapper_msg_get_type(msg, AT_DEST_MIN); length = mapper_msg_get_length(msg, AT_DEST_MIN); if (args && types && is_number_type(types[0])) { if (length == c->props.dest_length) { if (!c->props.dest_min) c->props.dest_min = calloc(1, length * c->props.dest_type); c->props.range_known |= CONNECTION_RANGE_DEST_MIN; for (i=0; i<length; i++) { result = propval_set_from_lo_arg(c->props.dest_min, c->props.dest_type, args[i], types[i], i); if (result == -1) { c->props.range_known &= ~CONNECTION_RANGE_DEST_MIN; break; } else updated += result; } } else c->props.range_known &= ~CONNECTION_RANGE_DEST_MIN; } /* @min, @max */ if (!(c->props.range_known & CONNECTION_RANGE_DEST_MIN)) { args = mapper_msg_get_param(msg, AT_MIN); types = mapper_msg_get_type(msg, AT_MIN); length = mapper_msg_get_length(msg, AT_MIN); if (args && types && is_number_type(types[0])) { if (length == c->props.dest_length) { if (!c->props.dest_min) c->props.dest_min = calloc(1, length * c->props.dest_type); c->props.range_known |= CONNECTION_RANGE_DEST_MIN; for (i=0; i<length; i++) { result = propval_set_from_lo_arg(c->props.dest_min, c->props.dest_type, args[i], types[i], i); if (result == -1) { c->props.range_known &= ~CONNECTION_RANGE_DEST_MIN; break; } else updated += result; } } else c->props.range_known &= ~CONNECTION_RANGE_DEST_MIN; } } if (!(c->props.range_known & CONNECTION_RANGE_DEST_MAX)) { args = mapper_msg_get_param(msg, AT_MAX); types = mapper_msg_get_type(msg, AT_MAX); length = mapper_msg_get_length(msg, AT_MAX); if (args && types && is_number_type(types[0])) { if (length == c->props.dest_length) { if (!c->props.dest_max) c->props.dest_max = calloc(1, length * c->props.dest_type); c->props.range_known |= CONNECTION_RANGE_DEST_MAX; for (i=0; i<length; i++) { result = propval_set_from_lo_arg(c->props.dest_max, c->props.dest_type, args[i], types[i], i); if (result == -1) { c->props.range_known &= ~CONNECTION_RANGE_DEST_MAX; break; } else updated += result; } } else c->props.range_known &= ~CONNECTION_RANGE_DEST_MAX; } } /* Signal */ mapper_signal sig = c->parent->signal; /* If parent signal is an output it must be the "source" of this connection, * if it is an input it must be the "destination". According to the protocol * for negotiating new connections, we will only fill-in ranges for the * "source" signal.*/ if (!sig || !sig->props.is_output) return updated; if (!c->props.src_min && sig->props.minimum) { c->props.src_min = malloc(msig_vector_bytes(sig)); memcpy(c->props.src_min, sig->props.minimum, msig_vector_bytes(sig)); c->props.range_known |= CONNECTION_RANGE_SRC_MIN; updated++; } if (!c->props.src_max && sig->props.maximum) { c->props.src_max = malloc(msig_vector_bytes(sig)); memcpy(c->props.src_max, sig->props.maximum, msig_vector_bytes(sig)); c->props.range_known |= CONNECTION_RANGE_SRC_MAX; updated++; } return updated; }
/* Helper to fill in the range (src_min, src_max, dest_min, dest_max) * based on message parameters and known connection and signal * properties; return flags to indicate which parts of the range were * found. */ static int get_range(mapper_signal sig, mapper_connection connection, mapper_message_t *msg, float range[4]) { lo_arg **a_range = mapper_msg_get_param(msg, AT_RANGE); const char* t_range = mapper_msg_get_type(msg, AT_RANGE); lo_arg **a_min = mapper_msg_get_param(msg, AT_MIN); const char* t_min = mapper_msg_get_type(msg, AT_MIN); lo_arg **a_max = mapper_msg_get_param(msg, AT_MAX); const char* t_max = mapper_msg_get_type(msg, AT_MAX); int range_known = 0; /* The logic here is to first try to use information from the * message, starting with @range, then @min and @max. Next * priority is already-known properties of the connection. * Lastly, we fill in source range from the signal. */ /* @range */ if (a_range && t_range) { int i, known[] = { CONNECTION_RANGE_SRC_MIN, CONNECTION_RANGE_SRC_MAX, CONNECTION_RANGE_DEST_MIN, CONNECTION_RANGE_DEST_MAX }; for (i=0; i<4; i++) { if (t_range[i] == 'f') { range_known |= known[i]; range[i] = a_range[i]->f; } else if (t_range[i] == 'i') { range_known |= known[i]; range[i] = (float)a_range[i]->i; } } } /* @min, @max */ if (!(range_known & CONNECTION_RANGE_DEST_MIN) && a_min && t_min) { if (t_min[0]=='f') { range_known |= CONNECTION_RANGE_DEST_MIN; range[2] = (*a_min)->f; } else if (t_min[0]=='i') { range_known |= CONNECTION_RANGE_DEST_MIN; range[2] = (float)(*a_min)->i; } } if (!(range_known & CONNECTION_RANGE_DEST_MAX) && a_max && t_max) { if (t_max[0]=='f') { range_known |= CONNECTION_RANGE_DEST_MAX; range[3] = (*a_max)->f; } else if (t_max[0]=='i') { range_known |= CONNECTION_RANGE_DEST_MAX; range[3] = (float)(*a_max)->i; } } /* connection */ if (connection) { if (!(range_known & CONNECTION_RANGE_SRC_MIN) && (connection->props.range.known & CONNECTION_RANGE_SRC_MIN)) { range_known |= CONNECTION_RANGE_SRC_MIN; range[0] = connection->props.range.src_min; } if (!(range_known & CONNECTION_RANGE_SRC_MAX) && (connection->props.range.known & CONNECTION_RANGE_SRC_MAX)) { range_known |= CONNECTION_RANGE_SRC_MAX; range[1] = connection->props.range.src_max; } if (!(range_known & CONNECTION_RANGE_DEST_MIN) && (connection->props.range.known & CONNECTION_RANGE_DEST_MIN)) { range_known |= CONNECTION_RANGE_DEST_MIN; range[2] = connection->props.range.dest_min; } if (!(range_known & CONNECTION_RANGE_DEST_MAX) && (connection->props.range.known & CONNECTION_RANGE_DEST_MAX)) { range_known |= CONNECTION_RANGE_DEST_MAX; range[3] = connection->props.range.dest_max; } } /* Signal */ if (sig) { if (!(range_known & CONNECTION_RANGE_SRC_MIN) && sig->props.minimum) { if (sig->props.type == 'f') { range_known |= CONNECTION_RANGE_SRC_MIN; range[0] = sig->props.minimum->f; } else if (sig->props.type == 'i') { range_known |= CONNECTION_RANGE_SRC_MIN; range[0] = sig->props.minimum->i32; } } if (!(range_known & CONNECTION_RANGE_SRC_MAX) && sig->props.maximum) { if (sig->props.type == 'f') { range_known |= CONNECTION_RANGE_SRC_MAX; range[1] = sig->props.maximum->f; } else if (sig->props.type == 'i') { range_known |= CONNECTION_RANGE_SRC_MAX; range[1] = sig->props.maximum->i32; } } } return range_known; }