Ejemplo n.º 1
0
void mapper_connection_set_expression(mapper_connection c,
                                      mapper_signal sig,
                                      const char *expr)
{
    if (replace_expression_string(c, sig, expr))
        return;

    c->props.mode = MO_EXPRESSION;
}
Ejemplo n.º 2
0
void mapper_connection_set_mode_expression(mapper_connection c,
                                           const char *expr)
{
    int input_history_size, output_history_size;
    if (replace_expression_string(c, expr, &input_history_size,
                                  &output_history_size))
        return;

    c->props.mode = MO_EXPRESSION;
    reallocate_connection_histories(c, input_history_size,
                                    output_history_size);
    /* Special case: if we are the receiver and the new expression
     * evaluates to a constant we can update immediately. */
    /* TODO: should call handler for all instances updated
     * through this connection. */
    mapper_signal sig = c->parent->signal;
    if (!sig->props.is_output && mapper_expr_constant_output(c->expr)
        && !c->props.send_as_instance) {
        int index = 0;
        mapper_timetag_t now;
        mapper_clock_now(&sig->device->admin->clock, &now);
        if (!sig->id_maps[0].instance)
            index = msig_get_instance_with_local_id(sig, 0, 1, &now);
        if (index < 0)
            return;
        mapper_signal_instance si = sig->id_maps[index].instance;

        // evaluate expression
        mapper_signal_history_t h;
        h.type = sig->props.type;
        h.value = si->value;
        h.position = -1;
        h.length = sig->props.length;
        h.size = 1;
        char typestring[h.length];
        mapper_expr_evaluate(c->expr, 0, &c->expr_vars[si->index],
                             &h, typestring);

        // call handler if it exists
        if (sig->handler)
            sig->handler(sig, &sig->props, 0, si->value, 1, &now);
    }
}
Ejemplo n.º 3
0
void mapper_connection_set_linear_range(mapper_connection c,
                                        mapper_signal sig,
                                        mapper_connection_range_t *r)
{
    char expr[256] = "";
    const char *e = expr;

    if (r->known
        & (CONNECTION_RANGE_SRC_MIN | CONNECTION_RANGE_SRC_MAX))
    {
        if (r->src_min == r->src_max)
            snprintf(expr, 256, "y=%g", r->src_min);

        else if (r->known == CONNECTION_RANGE_KNOWN
                 && r->src_min == r->dest_min
                 && r->src_max == r->dest_max)
            e = strdup("y=x");

        else if (r->known == CONNECTION_RANGE_KNOWN) {
            float scale = ((r->dest_min - r->dest_max)
                           / (r->src_min - r->src_max));
            float offset =
                ((r->dest_max * r->src_min
                  - r->dest_min * r->src_max)
                 / (r->src_min - r->src_max));

            snprintf(expr, 256, "y=x*(%g)+(%g)", scale, offset);
        }
        else
            e = 0;
    }
    else
        e = 0;

    if (&c->props.range != r)
        memcpy(&c->props.range, r,
               sizeof(mapper_connection_range_t));

    // If everything is successful, replace the connection's expression.
    if (e && !replace_expression_string(c, sig, e))
        c->props.mode = MO_LINEAR;
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
void mapper_connection_set_mode_linear(mapper_connection c)
{
    int i, len;
    char expr[256] = "";
    const char *e = expr;

    if (c->props.range_known != CONNECTION_RANGE_KNOWN)
        return;

    int min_length = c->props.src_length < c->props.dest_length ?
                     c->props.src_length : c->props.dest_length;
    double src_min, src_max, dest_min, dest_max;

    if (c->props.dest_length == c->props.src_length)
        snprintf(expr, 256, "y=x*");
    else if (c->props.dest_length > c->props.src_length) {
        if (min_length == 1)
            snprintf(expr, 256, "y[0]=x*");
        else
            snprintf(expr, 256, "y[0:%i]=x*", min_length-1);
    }
    else {
        if (min_length == 1)
            snprintf(expr, 256, "y=x[0]*");
        else
            snprintf(expr, 256, "y=x[0:%i]*", min_length-1);
    }

    if (min_length > 1) {
        len = strlen(expr);
        snprintf(expr+len, 256-len, "[");
    }

    for (i = 0; i < min_length; i++) {
        // get multiplier
        src_min = propval_get_double(c->props.src_min, c->props.src_type, i);
        src_max = propval_get_double(c->props.src_max, c->props.src_type, i);

        len = strlen(expr);
        if (src_min == src_max)
            snprintf(expr+len, 256-len, "0,");
        else {
            dest_min = propval_get_double(c->props.dest_min, c->props.dest_type, i);
            dest_max = propval_get_double(c->props.dest_max, c->props.dest_type, i);
            if ((src_min == dest_min) && (src_max == dest_max)) {
                snprintf(expr+len, 256-len, "1,");
            }
            else {
                double scale = ((dest_min - dest_max) / (src_min - src_max));
                snprintf(expr+len, 256-len, "%g,", scale);
            }
        }
    }
    len = strlen(expr);
    if (min_length > 1)
        snprintf(expr+len-1, 256-len+1, "]+[");
    else
        snprintf(expr+len-1, 256-len+1, "+");

    // add offset
    for (i=0; i<min_length; i++) {
        src_min = propval_get_double(c->props.src_min, c->props.src_type, i);
        src_max = propval_get_double(c->props.src_max, c->props.src_type, i);

        len = strlen(expr);
        if (src_min == src_max)
            snprintf(expr+len, 256-len, "%g,", dest_min);
        else {
            dest_min = propval_get_double(c->props.dest_min, c->props.dest_type, i);
            dest_max = propval_get_double(c->props.dest_max, c->props.dest_type, i);
            if ((src_min == dest_min) && (src_max == dest_max)) {
                snprintf(expr+len, 256-len, "0,");
            }
            else {
                double offset = ((dest_max * src_min - dest_min * src_max)
                                 / (src_min - src_max));
                snprintf(expr+len, 256-len, "%g,", offset);
            }
        }
    }
    len = strlen(expr);
    if (min_length > 1)
        snprintf(expr+len-1, 256-len+1, "]");
    else
        expr[len-1] = '\0';

    // If everything is successful, replace the connection's expression.
    if (e) {
        int input_history_size, output_history_size;
        if (!replace_expression_string(c, e, &input_history_size,
                                       &output_history_size)) {
            reallocate_connection_histories(c, 1, 1);
            c->props.mode = MO_LINEAR;
        }
    }
}
Ejemplo n.º 6
0
void mapper_connection_set_from_message(mapper_connection c,
                                        mapper_signal sig,
                                        mapper_message_t *msg)
{
    /* 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];

    /* Range information. */

    float range[4];
    int range_known = get_range(sig, c, msg, range);

    if (range_known & CONNECTION_RANGE_SRC_MIN) {
        c->props.range.known |= CONNECTION_RANGE_SRC_MIN;
        c->props.range.src_min = range[0];
    }

    if (range_known & CONNECTION_RANGE_SRC_MAX) {
        c->props.range.known |= CONNECTION_RANGE_SRC_MAX;
        c->props.range.src_max = range[1];
    }

    if (range_known & CONNECTION_RANGE_DEST_MIN) {
        c->props.range.known |= CONNECTION_RANGE_DEST_MIN;
        c->props.range.dest_min = range[2];
    }

    if (range_known & CONNECTION_RANGE_DEST_MAX) {
        c->props.range.known |= CONNECTION_RANGE_DEST_MAX;
        c->props.range.dest_max = range[3];
    }
    
    // TO DO: test if range has actually changed
    if (c->props.range.known == CONNECTION_RANGE_KNOWN 
        && c->props.mode == MO_LINEAR) {
        mapper_connection_set_linear_range(c, sig, &c->props.range);
    }

    /* Muting. */
    int muting;
    if (!mapper_msg_get_param_if_int(msg, AT_MUTE, &muting))
        c->props.muted = muting;
    
    /* Clipping. */
    int clip_min = mapper_msg_get_clipping(msg, AT_CLIPMIN);
    if (clip_min >= 0)
        c->props.clip_min = clip_min;

    int clip_max = mapper_msg_get_clipping(msg, AT_CLIPMAX);
    if (clip_max >= 0)
        c->props.clip_max = clip_max;
    
    /* Expression. */
    const char *expr = mapper_msg_get_param_if_string(msg, AT_EXPRESSION);
    if (expr)
        replace_expression_string(c, sig, expr);

    /* Now set the mode type depending on the requested type and
     * the known properties. */

    int mode = mapper_msg_get_mode(msg);

    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 (range_known == CONNECTION_RANGE_KNOWN) {
                    /* We have enough information for a linear connection. */
                    mapper_connection_range_t r;
                    r.src_min = range[0];
                    r.src_max = range[1];
                    r.dest_min = range[2];
                    r.dest_max = range[3];
                    r.known = range_known;
                    mapper_connection_set_linear_range(c, sig, &r);
                } else
                    /* No range, default to direct connection. */
                    mapper_connection_set_direct(c);
            }
        break;
    case MO_BYPASS:
        mapper_connection_set_direct(c);
        break;
    case MO_LINEAR:
        if (range_known == CONNECTION_RANGE_KNOWN) {
            mapper_connection_range_t r;
            r.src_min = range[0];
            r.src_max = range[1];
            r.dest_min = range[2];
            r.dest_max = range[3];
            r.known = range_known;
            mapper_connection_set_linear_range(c, sig, &r);
        }
        break;
    case MO_CALIBRATE:
        if (range_known & (CONNECTION_RANGE_DEST_MIN
                           | CONNECTION_RANGE_DEST_MAX))
            mapper_connection_set_calibrate(c, sig, range[2], range[3]);
        break;
    case MO_EXPRESSION:
        {
            if (!c->props.expression)
                c->props.expression = strdup("y=x");
            mapper_connection_set_expression(c, sig, c->props.expression);
        }
        break;
    default:
        trace("unknown result from mapper_msg_get_mode()\n");
        break;
    }
}