예제 #1
0
파일: connection.c 프로젝트: EQ4/libmapper
/* 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;
}
예제 #2
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 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;
}