int main() { lo_arg *args[20], **a; mapper_message_t msg; int port=1234, src_length=4, i; float r[4] = {1.0, 2.0, -15.0, 25.0}; int result = 0; printf("1: expected success\n"); args[0] = (lo_arg*)"@IP"; args[1] = (lo_arg*)"127.0.0.1"; args[2] = (lo_arg*)"@srcMin"; args[3] = (lo_arg*)&r[0]; args[4] = (lo_arg*)&r[1]; args[5] = (lo_arg*)&r[2]; args[6] = (lo_arg*)&r[3]; args[7] = (lo_arg*)"@port"; args[8] = (lo_arg*)&port; args[9] = (lo_arg*)"@srcType"; args[10] = (lo_arg*)"f"; args[11] = (lo_arg*)"@srcLength"; args[12] = (lo_arg*)&src_length; int rc = mapper_msg_parse_params(&msg, "/test", "sssffffsiscsi", 13, args); if (rc) { printf("1: Error parsing.\n"); return 1; } a = mapper_msg_get_param(&msg, AT_IP); if (!a) { printf("1: Could not get @IP param.\n"); return 1; } if (strcmp(&(*a)->s, "127.0.0.1")!=0) result |= 1; printf("1: @IP = \"%s\" %s\n", &(*a)->s, result ? "WRONG" : "(correct)"); if (result) return result; a = mapper_msg_get_param(&msg, AT_PORT); if (!a) { printf("1: Could not get @port param.\n"); return 1; } if ((*a)->i!=1234) result |= 1; printf("1: @port = %d %s\n", (*a)->i, result ? "WRONG" : "(correct)"); if (result) return result; a = mapper_msg_get_param(&msg, AT_SRC_MIN); int count = mapper_msg_get_length(&msg, AT_SRC_MIN); if (!a) { printf("1: Could not get @src_min param.\n"); return 1; } if (count != 4) { printf("1: Wrong count returned for @scr_min param.\n"); } for (i=0; i<count; i++) { if ((*a)->f!=r[i]) result |= 1; printf("1: @src_min[%d] = %f %s\n", i, (*a++)->f, result ? "WRONG" : "(correct)"); if (result) return result; } /*****/ printf("2: deliberately malformed message\n"); args[0] = (lo_arg*)"@port"; args[1] = (lo_arg*)&port; args[2] = (lo_arg*)"@IP"; rc = mapper_msg_parse_params(&msg, "/test", "sis", 3, args); if (rc) { printf("2: Error parsing.\n"); return 1; } a = mapper_msg_get_param(&msg, AT_PORT); if (!a) { printf("2: Could not get @port param.\n"); return 1; } a = mapper_msg_get_param(&msg, AT_IP); if (a) { printf("2: Error, should not have been able to retrieve @IP param.\n"); return 1; } /*****/ printf("Test PASSED.\n"); return 0; }
/* 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; }
int mapper_connection_set_from_message(mapper_connection c, mapper_message_t *msg) { int updated = 0; /* First record any provided parameters. */ /* Destination type. */ const char *dest_type = mapper_msg_get_param_if_char(msg, AT_TYPE); if (dest_type && c->props.dest_type != dest_type[0]) { // TODO: need to reinitialize connections using this destination signal c->props.dest_type = dest_type[0]; updated++; } /* Range information. */ updated += set_range(c, msg); if (c->props.range_known == CONNECTION_RANGE_KNOWN && c->props.mode == MO_LINEAR) { mapper_connection_set_mode_linear(c); } /* Muting. */ int muting; if (!mapper_msg_get_param_if_int(msg, AT_MUTE, &muting) && c->props.muted != muting) { c->props.muted = muting; updated++; } /* Range boundary actions. */ int bound_min = mapper_msg_get_boundary_action(msg, AT_BOUND_MIN); if (bound_min >= 0 && c->props.bound_min != bound_min) { c->props.bound_min = bound_min; updated++; } int bound_max = mapper_msg_get_boundary_action(msg, AT_BOUND_MAX); if (bound_max >= 0 && c->props.bound_max != bound_max) { c->props.bound_max = bound_max; updated++; } /* Expression. */ const char *expr = mapper_msg_get_param_if_string(msg, AT_EXPRESSION); if (expr && (!c->props.expression || strcmp(c->props.expression, expr))) { int input_history_size, output_history_size; if (!replace_expression_string(c, expr, &input_history_size, &output_history_size)) { if (c->props.mode == MO_EXPRESSION) { reallocate_connection_histories(c, input_history_size, output_history_size); } } updated++; } /* Instances. */ int send_as_instance; if (!mapper_msg_get_param_if_int(msg, AT_SEND_AS_INSTANCE, &send_as_instance) && c->props.send_as_instance != send_as_instance) { c->props.send_as_instance = send_as_instance; updated++; } /* Scopes. */ lo_arg **a_scopes = mapper_msg_get_param(msg, AT_SCOPE); int num_scopes = mapper_msg_get_length(msg, AT_SCOPE); mapper_db_connection_update_scope(&c->props.scope, a_scopes, num_scopes); /* Extra properties. */ updated += mapper_msg_add_or_update_extra_params(c->props.extra, msg); /* Now set the mode type depending on the requested type and * the known properties. */ int mode = mapper_msg_get_mode(msg); if (mode >= 0 && mode != c->props.mode) updated++; switch (mode) { case -1: /* No mode type specified; if mode not yet set, see if we know the range and choose between linear or direct connection. */ if (c->props.mode == MO_UNDEFINED) { if (c->props.range_known == CONNECTION_RANGE_KNOWN) { /* We have enough information for a linear connection. */ mapper_connection_set_mode_linear(c); } else /* No range, default to direct connection. */ mapper_connection_set_mode_direct(c); } break; case MO_BYPASS: mapper_connection_set_mode_direct(c); break; case MO_LINEAR: if (c->props.range_known == CONNECTION_RANGE_KNOWN) { mapper_connection_set_mode_linear(c); } break; case MO_CALIBRATE: if (c->props.range_known & (CONNECTION_RANGE_DEST_MIN | CONNECTION_RANGE_DEST_MAX)) mapper_connection_set_mode_calibrate(c); break; case MO_EXPRESSION: { if (!c->props.expression) { if (c->props.src_length == c->props.dest_length) c->props.expression = strdup("y=x"); else { char expr[256] = ""; if (c->props.src_length > c->props.dest_length) { // truncate source if (c->props.dest_length == 1) snprintf(expr, 256, "y=x[0]"); else snprintf(expr, 256, "y=x[0:%i]", c->props.dest_length-1); } else { // truncate destination if (c->props.src_length == 1) snprintf(expr, 256, "y[0]=x"); else snprintf(expr, 256, "y[0:%i]=x", c->props.src_length); } c->props.expression = strdup(expr); } } mapper_connection_set_mode_expression(c, c->props.expression); } break; case MO_REVERSE: mapper_connection_set_mode_reverse(c); break; default: trace("unknown result from mapper_msg_get_mode()\n"); break; } return updated; }
int main(int argc, char **argv) { lo_arg *args[20], **a; mapper_message_t msg; int port=1234, src_length=4; float r[4] = {1.0, 2.0, -15.0, 25.0}; int i, j, result = 0; // process flags for -v verbose, -h help for (i = 1; i < argc; i++) { if (argv[i] && argv[i][0] == '-') { int len = strlen(argv[i]); for (j = 1; j < len; j++) { switch (argv[i][j]) { case 'h': eprintf("testdb.c: possible arguments " "-q quiet (suppress output), " "-h help\n"); return 1; break; case 'q': verbose = 0; break; default: break; } } } } eprintf("1: expected success\n"); args[0] = (lo_arg*)"@IP"; args[1] = (lo_arg*)"127.0.0.1"; args[2] = (lo_arg*)"@srcMin"; args[3] = (lo_arg*)&r[0]; args[4] = (lo_arg*)&r[1]; args[5] = (lo_arg*)&r[2]; args[6] = (lo_arg*)&r[3]; args[7] = (lo_arg*)"@port"; args[8] = (lo_arg*)&port; args[9] = (lo_arg*)"@srcType"; args[10] = (lo_arg*)"f"; args[11] = (lo_arg*)"@srcLength"; args[12] = (lo_arg*)&src_length; int rc = mapper_msg_parse_params(&msg, "/test", "sssffffsiscsi", 13, args); if (rc) { eprintf("1: Error parsing.\n"); result = 1; goto done; } a = mapper_msg_get_param(&msg, AT_IP); if (!a) { eprintf("1: Could not get @IP param.\n"); result = 1; goto done; } if (strcmp(&(*a)->s, "127.0.0.1")!=0) result |= 1; eprintf("1: @IP = \"%s\" %s\n", &(*a)->s, result ? "WRONG" : "(correct)"); if (result) goto done; a = mapper_msg_get_param(&msg, AT_PORT); if (!a) { eprintf("1: Could not get @port param.\n"); result = 1; goto done; } if ((*a)->i!=1234) result |= 1; eprintf("1: @port = %d %s\n", (*a)->i, result ? "WRONG" : "(correct)"); if (result) goto done; a = mapper_msg_get_param(&msg, AT_SRC_MIN); int count = mapper_msg_get_length(&msg, AT_SRC_MIN); if (!a) { eprintf("1: Could not get @src_min param.\n"); result = 1; goto done; } if (count != 4) { eprintf("1: Wrong count returned for @scr_min param.\n"); } for (i=0; i<count; i++) { if (a[i]->f!=r[i]) result = 1; eprintf("1: @src_min[%d] = %f %s\n", i, a[i]->f, result ? "WRONG" : "(correct)"); if (result) goto done; } /*****/ eprintf("2: deliberately malformed message\n"); args[0] = (lo_arg*)"@port"; args[1] = (lo_arg*)&port; args[2] = (lo_arg*)"@IP"; rc = mapper_msg_parse_params(&msg, "/test", "sis", 3, args); if (rc) { eprintf("2: Error parsing.\n"); result = 1; goto done; } a = mapper_msg_get_param(&msg, AT_PORT); if (!a) { eprintf("2: Could not get @port param.\n"); result = 1; goto done; } a = mapper_msg_get_param(&msg, AT_IP); if (a) { eprintf("2: Error, should not have been able to retrieve @IP param.\n"); result = 1; goto done; } /*****/ done: if (!verbose) printf(".................................................."); printf("Test %s.\n", result ? "FAILED" : "PASSED"); return result; }