Beispiel #1
0
static void message_add_coerced_signal_value(lo_message m,
                                             mapper_signal sig,
                                             mapper_signal_instance si,
                                             const char coerce_type)
{
    int i;
    if (sig->props.type == 'f') {
        float *v = si->value;
        if (coerce_type == 'f') {
            for (i = 0; i < sig->props.length; i++)
                lo_message_add_float(m, v[i]);
        }
        else if (coerce_type == 'i') {
            for (i = 0; i < sig->props.length; i++)
                lo_message_add_int32(m, (int)v[i]);
        }
        else if (coerce_type == 'd') {
            for (i = 0; i < sig->props.length; i++)
                lo_message_add_double(m, (double)v[i]);
        }
    }
    else if (sig->props.type == 'i') {
        int *v = si->value;
        if (coerce_type == 'i') {
            for (i = 0; i < sig->props.length; i++)
                lo_message_add_int32(m, v[i]);
        }
        else if (coerce_type == 'f') {
            for (i = 0; i < sig->props.length; i++)
                lo_message_add_float(m, (float)v[i]);
        }
        else if (coerce_type == 'd') {
            for (i = 0; i < sig->props.length; i++)
                lo_message_add_double(m, (double)v[i]);
        }
    }
    else if (sig->props.type == 'd') {
        double *v = si->value;
        if (coerce_type == 'd') {
            for (i = 0; i < sig->props.length; i++)
                lo_message_add_double(m, (int)v[i]);
        }
        else if (coerce_type == 'i') {
            for (i = 0; i < sig->props.length; i++)
                lo_message_add_int32(m, (int)v[i]);
        }
        else if (coerce_type == 'f') {
            for (i = 0; i < sig->props.length; i++)
                lo_message_add_float(m, (float)v[i]);
        }
    }
}
Beispiel #2
0
static void sendOsc(const char *s, float *f,int n){
    lo_message msg = lo_message_new();
    for(int i=0;i<n;i++)
        lo_message_add_float(msg,f[i]);
    int ret = lo_send_message(lo,s,msg);
    lo_message_free(msg);
}
Beispiel #3
0
void Client::send( const osc::Message &message )
{
	lo_message msg = lo_message_new();

	for ( size_t i = 0; i < message.getNumArgs(); i++ )
	{
		switch ( message.getArgType( i ) )
		{
			case 'i':
				lo_message_add_int32( msg, message.getArg< int32_t >( i ) );
				break;

			case 'f':
				lo_message_add_float( msg, message.getArg< float >( i ) );
				break;

			case 's':
				lo_message_add_string( msg, message.getArg< std::string >( i ).c_str() );
				break;

			default:
				break;
		}
	}

	lo_send_message( mAddress, message.getAddressPattern().c_str(), msg );
	lo_message_free( msg );
}
void osc_controller::handle_set_param_node(world_node& obj, int param_id)
{
    if (!m_skip) {
	int local_id(obj.get_id ());
	pair<int,int> net_id = m_net_id[local_id];

	lo_message msg = lo_message_new();

	lo_message_add_int32(msg, net_id.first);
	lo_message_add_int32(msg, net_id.second);
	lo_message_add_int32(msg, param_id);

	switch(obj.get_param_type(param_id)) {
	case graph::node_param::INT: {
	    int val;
	    obj.get_param(param_id, val);
	    lo_message_add_int32(msg, val);
	    break;
	}
	case graph::node_param::FLOAT: {
	    float val;
	    obj.get_param(param_id, val);
	    lo_message_add_float(msg, val);
	    break;
	}
	case graph::node_param::STRING: {
	    string val;
	    obj.get_param(param_id, val);
	    lo_message_add_string(msg, val.c_str());
	    break;
	}
	case graph::node_param::VECTOR2F: {
	    base::vector_2f val;
	    obj.get_param(param_id, val);
	    lo_message_add_float(msg, val.x);
	    lo_message_add_float(msg, val.y);
	    break;
	}
	default:
	    break;
	}

	broadcast_message(PSYNTH_OSC_MSG_PARAM, msg);

	lo_message_free(msg);
    }
}
Beispiel #5
0
// Generate OSC message with default format
void genOscMsg(lo_bundle *bundle, char *name, int buffIndex) {

	if (handMode || posConfidence >= 0.5f)
	{
      lo_message msg = lo_message_new();

      lo_message_add_string(msg, name);

      if (!kitchenMode)
        lo_message_add_int32(msg, userID);

	  for (int i = 0; i < nDimensions; i++)
        lo_message_add_float(msg, jointCoords[i]);

	  lo_bundle_add_message(*bundle, "/joint", msg);
	}

	if (!kitchenMode && sendOrient && orientConfidence  >= 0.5f)
	{
	  lo_message msg = lo_message_new();

	  lo_message_add_string(msg, name);

	  if (!kitchenMode)
	    lo_message_add_int32(msg, userID);

	  // x data is in first column
	  lo_message_add_float(msg, jointOrients[0]);
	  lo_message_add_float(msg, jointOrients[0+3]);
	  lo_message_add_float(msg, jointOrients[0+6]);

	  // y data is in 2nd column
	  lo_message_add_float(msg, jointOrients[1]);
	  lo_message_add_float(msg, jointOrients[1+3]);
	  lo_message_add_float(msg, jointOrients[1+6]);

	  // z data is in 3rd column
	  lo_message_add_float(msg, jointOrients[2]);
	  lo_message_add_float(msg, jointOrients[2+3]);
	  lo_message_add_float(msg, jointOrients[2+6]);

	  lo_bundle_add_message(*bundle, "/orient", msg);
	}
}
Beispiel #6
0
//=========================================================
void io_simple_float(char *path, float f)
{
	if(io_())
	{
		lo_message msgio=lo_message_new();
		lo_message_add_float(msgio, f);
		lo_send_message(loio, path, msgio);
		lo_message_free(msgio);
	}
}
Beispiel #7
0
// parse a list of Prolog terms and add arguments to an OSC message 
static int add_msg_args(lo_message msg, term_t list)
{
	term_t 	head=PL_new_term_ref();

	// copy term ref so as not to modify original
	list=PL_copy_term_ref(list);

	while (PL_get_list(list,head,list)) {
		atom_t name;
		int	 arity;
		const char  *type;

		if (!PL_get_name_arity(head,&name,&arity)) return type_error(head,"term");
		type=PL_atom_chars(name);
		switch (arity) {
		case 1: {
				term_t a1=PL_new_term_ref();
				PL_get_arg(1,head,a1);

				if (!strcmp(type,"int")) {
					int x;
					if (!PL_get_integer(a1,&x)) return type_error(a1,"integer");
					lo_message_add_int32(msg,x);
				} else if (!strcmp(type,"double")) {
					double x;
					if (!PL_get_float(a1,&x)) return type_error(a1,"float");
					lo_message_add_double(msg,x);
				} else if (!strcmp(type,"string")) {
					char *x;
					if (!PL_get_chars(a1,&x,CVT_ATOM|CVT_STRING)) return type_error(a1,"string");
					lo_message_add_string(msg,x);
				} else if (!strcmp(type,"symbol")) {
					char *x;
					if (!PL_get_chars(a1,&x,CVT_ATOM)) return type_error(a1,"atom");
					lo_message_add_symbol(msg,x);
				} else if (!strcmp(type,"float")) {
					double x;
					if (!PL_get_float(a1,&x)) return type_error(a1,"float");
					lo_message_add_float(msg,(float)x);
				}
				break;
			}
		case 0: {
				if (!strcmp(type,"true")) lo_message_add_true(msg);
				else if (!strcmp(type,"false")) lo_message_add_false(msg);
				else if (!strcmp(type,"nil")) lo_message_add_nil(msg);
				else if (!strcmp(type,"inf")) lo_message_add_infinitum(msg);
				break;
			}
		}
	}
	if (!PL_get_nil(list)) return type_error(list,"nil");
	return TRUE;
}
Beispiel #8
0
int text_read(char **_path, lo_message *_m, lo_timetag *_tt)
{
    const char *delim = " \r\n";
    char str[1024];
    if (!fgets(str, 1024, input_file))
        return 1;

    char *t, *p, *s = strtok_r(str, delim, &p);
    lo_timetag tt;
    lo_message m = lo_message_new();
    char *path;

    if (s) {
        tt.sec = atoi(s);
    }
    s = strtok_r(0, delim, &p);
    if (s) {
        tt.frac = atoi(s);
    }
    s = strtok_r(0, delim, &p);
    if (s) {
        path = s;
    }
    s = strtok_r(0, delim, &p);
    if (s) {
        t = s;
    }

    while ((s = strtok_r(0, delim, &p))) {
        switch (*t) {
        case 'i':
            lo_message_add_int32(m, atoi(s));
            break;
        case 'f':
            lo_message_add_float(m, atof(s));
            break;
        case 's':
            lo_message_add_string(m, s);
            break;
        }
        if (*(t+1))
            t++;
    }

    _tt->sec = tt.sec;
    _tt->frac = tt.frac;

    *_m = m;
    *_path = strdup(path);

    return 0;
}
Beispiel #9
0
// Generate OSC message with Quartz Composer format - based on Steve Elbows's code ;)
void genQCMsg(lo_bundle *bundle, char *name, int buffIndex) {

	if (handMode || posConfidence >= 0.5f)
	{
	  sprintf(oscPositionAddressBuff[buffIndex], "/joint/%s/%d", name, userID);
      lo_message msg = lo_message_new();

	  for (int i = 0; i < nDimensions; i++)
		  lo_message_add_float(msg, jointCoords[i]);

	  if (lo_bundle_add_message(*bundle, oscPositionAddressBuff[buffIndex], msg) != 0) printf ("lo_bundle_add_message error\n");
	} else {
		printf("confidence below threshold for %s: %f\n", name, posConfidence);
	}

	if (sendOrient && orientConfidence  >= 0.5f)
	{
	  sprintf(oscOrientationAddressBuff[buffIndex], "/orient/%s/%d", name, userID);

	  lo_message msg = lo_message_new();

	  // x data is in first column
	  lo_message_add_float(msg, jointOrients[0]);
	  lo_message_add_float(msg, jointOrients[0+3]);
	  lo_message_add_float(msg, jointOrients[0+6]);

	  // y data is in 2nd column
	  lo_message_add_float(msg, jointOrients[1]);
	  lo_message_add_float(msg, jointOrients[1+3]);
	  lo_message_add_float(msg, jointOrients[1+6]);

	  // z data is in 3rd column
	  lo_message_add_float(msg, jointOrients[2]);
	  lo_message_add_float(msg, jointOrients[2+3]);
	  lo_message_add_float(msg, jointOrients[2+6]);

	  lo_bundle_add_message(*bundle, oscOrientationAddressBuff[buffIndex], msg);
	}
}
Beispiel #10
0
void sendUserPosMsg(XnUserID id) {
	XnPoint3D com;
	sprintf(oscPositionAddressBuff[0], "/user/%d", id);
	lo_bundle bundle = lo_bundle_new(LO_TT_IMMEDIATE);
	lo_message msg = lo_message_new();

	userGenerator.GetCoM(id, com);

	if (!raw)
	{
		lo_message_add_float(msg, (float)(off_x + (mult_x * (1280 - com.X) / 2560)));
		lo_message_add_float(msg, (float)(off_y + (mult_y * (1280 - com.Y) / 2560)));
		lo_message_add_float(msg, (float)(off_z + (mult_z * com.Z * 7.8125 / 10000)));
	}
	else
	{
		lo_message_add_float(msg,com.X);
		lo_message_add_float(msg,com.Y);
		lo_message_add_float(msg,com.Z);
	}

	lo_bundle_add_message(bundle, oscPositionAddressBuff[0], msg);
	lo_send_bundle(addr, bundle);
}
Beispiel #11
0
void test_deserialise()
{
    char *buf, *buf2, *tmp;
    const char *types = NULL, *path;
    lo_arg **argv = NULL;
    size_t len, size;
    char data[256];
    int result = 0;

    lo_blob btest = lo_blob_new(sizeof(testdata), testdata);
    uint8_t midi_data[4] = {0xff, 0xf7, 0xAA, 0x00};
    lo_timetag tt = {0x1, 0x80000000};
    lo_blob b = NULL;

    // build a message
    lo_message msg = lo_message_new();
    TEST(0 == lo_message_get_argc(msg));
    lo_message_add_float(msg, 0.12345678f);             // 0  f
    lo_message_add_int32(msg, 123);                     // 1  i
    lo_message_add_string(msg, "123");                  // 2  s
    lo_message_add_blob(msg, btest);                    // 3  b
    lo_message_add_midi(msg, midi_data);                // 4  m
    lo_message_add_int64(msg, 0x0123456789abcdefULL);   // 5  h
    lo_message_add_timetag(msg, tt);                    // 6  t
    lo_message_add_double(msg, 0.9999);                 // 7  d
    lo_message_add_symbol(msg, "sym");                  // 8  S
    lo_message_add_char(msg, 'X');                      // 9  c
    lo_message_add_char(msg, 'Y');                      // 10 c
    lo_message_add_true(msg);                           // 11 T
    lo_message_add_false(msg);                          // 12 F
    lo_message_add_nil(msg);                            // 13 N
    lo_message_add_infinitum(msg);                      // 14 I

    // test types, args
    TEST(15 == lo_message_get_argc(msg));
    types = lo_message_get_types(msg);
    TEST(NULL != types);
    argv = lo_message_get_argv(msg);
    TEST(NULL != argv);
    TEST('f' == types[0] && fabs(argv[0]->f - 0.12345678f) < FLT_EPSILON);
    TEST('i' == types[1] && 123 == argv[1]->i);
    TEST('s' == types[2] && !strcmp(&argv[2]->s, "123"));
    TEST('b' == types[3]);
    b = (lo_blob)argv[3];
    TEST(lo_blob_datasize(b) == sizeof(testdata));
    TEST(12 == lo_blobsize(b));
    TEST(!memcmp(lo_blob_dataptr(b), &testdata, sizeof(testdata)));
    TEST('m' == types[4]  && !memcmp(&argv[4]->m, midi_data, 4));
    TEST('h' == types[5]  && 0x0123456789abcdefULL == argv[5]->h);
    TEST('t' == types[6]  && 1 == argv[6]->t.sec && 0x80000000 == argv[6]->t.frac);
    TEST('d' == types[7]  && fabs(argv[7]->d - 0.9999) < FLT_EPSILON);
    TEST('S' == types[8]  && !strcmp(&argv[8]->s, "sym"));
    TEST('c' == types[9]  && 'X' == argv[9]->c);
    TEST('c' == types[10] && 'Y' == argv[10]->c);
    TEST('T' == types[11] && NULL == argv[11]);
    TEST('F' == types[12] && NULL == argv[12]);
    TEST('N' == types[13] && NULL == argv[13]);
    TEST('I' == types[14] && NULL == argv[14]);

    // serialise it
    len = lo_message_length(msg, "/foo");
    printf("serialise message_length=%d\n", (int)len);
    buf = calloc(len, sizeof(char));
    size = 0;
    tmp = lo_message_serialise(msg, "/foo", buf, &size);
    TEST(tmp == buf && size == len && 92 == len);
    lo_message_free(msg);

    // deserialise it
    printf("deserialise\n");
    path = lo_get_path(buf, len);
    TEST(NULL != path && !strcmp(path, "/foo"));
    msg = lo_message_deserialise(buf, size, NULL);
    TEST(NULL != msg);

    // repeat same test as above
    TEST(15 == lo_message_get_argc(msg));
    types = lo_message_get_types(msg);
    TEST(NULL != types);
    argv = lo_message_get_argv(msg);
    TEST(NULL != argv);
    TEST('f' == types[0] && fabs(argv[0]->f - 0.12345678f) < FLT_EPSILON);
    TEST('i' == types[1] && 123 == argv[1]->i);
    TEST('s' == types[2] && !strcmp(&argv[2]->s, "123"));
    TEST('b' == types[3]);
    b = (lo_blob)argv[3];
    TEST(lo_blob_datasize(b) == sizeof(testdata));
    TEST(12 == lo_blobsize(b));
    TEST(!memcmp(lo_blob_dataptr(b), &testdata, sizeof(testdata)));
    TEST('m' == types[4]  && !memcmp(&argv[4]->m, midi_data, 4));
    TEST('h' == types[5]  && 0x0123456789abcdefULL == argv[5]->h);
    TEST('t' == types[6]  && 1 == argv[6]->t.sec && 0x80000000 == argv[6]->t.frac);
    TEST('d' == types[7]  && fabs(argv[7]->d - 0.9999) < FLT_EPSILON);
    TEST('S' == types[8]  && !strcmp(&argv[8]->s, "sym"));
    TEST('c' == types[9]  && 'X' == argv[9]->c);
    TEST('c' == types[10] && 'Y' == argv[10]->c);
    TEST('T' == types[11] && NULL == argv[11]);
    TEST('F' == types[12] && NULL == argv[12]);
    TEST('N' == types[13] && NULL == argv[13]);
    TEST('I' == types[14] && NULL == argv[14]);

    // serialise it again, compare
    len = lo_message_length(msg, "/foo");
    printf("serialise message_length=%d\n", (int)len);
    buf2 = calloc(len, sizeof(char));
    size = 0;
    tmp = lo_message_serialise(msg, "/foo", buf2, &size);
    TEST(tmp == buf2 && size == len && 92 == len);
    TEST(!memcmp(buf, buf2, len));
    lo_message_free(msg);

    lo_blob_free(btest);
    free(buf);
    free(buf2);

    // deserialise failure tests with invalid message data

    msg = lo_message_deserialise(data, 0, &result); // 0 size
    TEST(NULL == msg && LO_ESIZE == result);

    snprintf(data, 256, "%s", "/foo"); // unterminated path string
    msg = lo_message_deserialise(data, 4, &result);
    TEST(NULL == msg && LO_EINVALIDPATH == result);

    snprintf(data, 256, "%s", "/f_o"); // non-0 in pad area
    msg = lo_message_deserialise(data, 4, &result);
    TEST(NULL == msg && LO_EINVALIDPATH == result);

    snprintf(data, 256, "%s", "/t__"); // types missing
    replace_char(data, 4, '_', '\0');
    msg = lo_message_deserialise(data, 4, &result);
    TEST(NULL == msg && LO_ENOTYPE == result);

    snprintf(data, 256, "%s%s", "/t__", "____"); // types empty
    replace_char(data, 8, '_', '\0');
    msg = lo_message_deserialise(data, 8, &result);
    TEST(NULL == msg && LO_EBADTYPE == result);

    snprintf(data, 256, "%s%s", "/t__", ",f_"); // short message
    replace_char(data, 7, '_', '\0');
    msg = lo_message_deserialise(data, 7, &result);
    TEST(NULL == msg && LO_EINVALIDTYPE == result);

    snprintf(data, 256, "%s%s", "/t__", "ifi_"); // types missing comma
    replace_char(data, 8, '_', '\0');
    msg = lo_message_deserialise(data, 8, &result);
    TEST(NULL == msg && LO_EBADTYPE == result);

    snprintf(data, 256, "%s%s", "/t__", ",ifi"); // types unterminated
    replace_char(data, 8, '_', '\0');
    msg = lo_message_deserialise(data, 8, &result);
    TEST(NULL == msg && LO_EINVALIDTYPE == result);

    snprintf(data, 256, "%s%s", "/t__", ",ii_"); // not enough arg data
    replace_char(data, 8, '_', '\0');
    msg = lo_message_deserialise(data, 12, &result);
    TEST(NULL == msg && LO_EINVALIDARG == result);

    snprintf(data, 256, "%s%s", "/t__", ",ii_"); // not enough arg data again
    replace_char(data, 8, '_', '\0');
    msg = lo_message_deserialise(data, 15, &result);
    TEST(NULL == msg && LO_EINVALIDARG == result);

    snprintf(data, 256, "%s%s", "/t__", ",f__"); // too much arg data
    replace_char(data, 8, '_', '\0');
    msg = lo_message_deserialise(data, 16, &result);
    TEST(NULL == msg && LO_ESIZE == result);

    snprintf(data, 256, "%s%s", "/t__", ",bs_"); // blob longer than msg length
    replace_char(data, 8, '_', '\0');
    *(uint32_t *)(data + 8) = lo_htoo32((uint32_t)99999);
    msg = lo_message_deserialise(data, 256, &result);
    TEST(NULL == msg && LO_EINVALIDARG == result);
}
Beispiel #12
0
void moNetOSCOut::SendDataMessage( int i, moDataMessage &datamessage ) {
#ifdef OSCPACK
    if (packetStream==NULL) {
        cout << "moNetOSCOut::SendDataMessage > error: packetStream is NULL" << endl;
        return;
    }
#endif

	//cout << "moNetOSCOut::SendDataMessage > start" << endl;
#ifdef OSCPACK
	packetStream->Clear();
	//cout << "moNetOSCOut::SendDataMessage > Clear() ok." << endl;

    (*packetStream) << osc::BeginBundleImmediate;
    //cout << "moNetOSCOut::SendDataMessage > BeginBundleImmediate ok." << endl;

    (*packetStream) << osc::BeginMessage( moText("")+ IntToStr(datamessage.Count()) );
    //cout << "moNetOSCOut::SendDataMessage > data in messages:" << datamessage.Count() << endl;
#else
lo_timetag timetag;
lo_timetag_now(&timetag);
lo_bundle bundle = lo_bundle_new(timetag);
lo_message ms = lo_message_new();
moText oscpath = "";
#endif
    moData data;
    int nfields = 0;
    int error = 0;
    try {
      for(int j=0; j< datamessage.Count(); j++) {
          data = datamessage[j];
          if (debug_is_on) MODebug2->Message( moText("moNetOSCOut::SendDataMessage "+GetLabelName()+" > data:") + IntToStr(j) );
          switch(data.Type()) {
          #ifdef OSCPACK
              case MO_DATA_NUMBER_FLOAT:
                  (*packetStream) << data.Float();
                  break;
              case MO_DATA_NUMBER_INT:
                  (*packetStream) << data.Int();
                  break;
              case MO_DATA_NUMBER_LONG:
                  (*packetStream) << data.Long();
                  break;
              case MO_DATA_NUMBER_DOUBLE:
                  (*packetStream) << data.Double();
                  break;
              case MO_DATA_TEXT:
                  (*packetStream) << (char*)data.Text();
                  break;
          #else
              case MO_DATA_NUMBER_FLOAT:
                  error = lo_message_add_float( ms , data.Float());
                  nfields++;
                  break;
              case MO_DATA_NUMBER_INT:
                  error = lo_message_add_int32( ms , data.Int());
                  nfields++;
                  break;
              case MO_DATA_NUMBER_LONG:
                  error = lo_message_add_int64( ms , data.Long());
                  nfields++;
                  break;
              case MO_DATA_NUMBER_DOUBLE:
                  error = lo_message_add_double( ms , data.Double());
                  nfields++;
                  break;
              case MO_DATA_TEXT:
                  if (oscpath=="") {
                    oscpath = data.Text();
                    moText mot = data.Text().Left(50000);
                    error = lo_message_add_string( ms , (char*)mot);
                    nfields++;
                  } else {
                    moText mot = data.Text().Left(50000);
                    error = lo_message_add_string( ms , (char*)mot);
                    nfields++;
                  }
                  break;

          #endif


          }
        if (error<0)
          MODebug2->Error(moText("moNetOSCOut > data error adding value: ") + data.ToText() );
      }
#ifdef OSCPACK
    } catch(osc::Exception E) {
      MODebug2->Error( moText("moNetOSCOut > Exception: ") + E.what()
                      + " packet actual size: (" + IntToStr( (*packetStream).Size() ) + ") "
                      + " Data too long for buffer: (max OUTPUT_BUFFER_SIZE:" + IntToStr(OUTPUT_BUFFER_SIZE) + ") "
                      + data.ToText()
                      + " (size:"+ IntToStr(data.ToText().Length())+" )"
                      + " (total size:" + IntToStr( data.ToText().Length() + (*packetStream).Size() ) + ")" );
    }
  (*packetStream) << osc::EndMessage;
    //cout << "moNetOSCOut::SendDataMessage > osc::EndMessage ok" << endl;
    //cout << "osc::EndBundle: " << endl;
    //cout << osc::EndBundle << endl;

    #ifdef MO_WIN32
        (*packetStream) << osc::EndBundle;
    #endif
    //cout << "moNetOSCOut::SendDataMessage > osc::EndBundle ok" << endl;

    //cout << "moNetOSCOut::SendDataMessage > sending." << endl;

    if (transmitSockets[i]) {
        //MODebug2->Message(moText("moNetOSCOut > sending ") + IntToStr(i) + " size:" + IntToStr(packetStream->Size()) );
        transmitSockets[i]->Send( packetStream->Data(), packetStream->Size() );

    }
#else
    } catch(...) {
Beispiel #13
0
// /offer
//sender offers audio
int offer_handler(const char *path, const char *types, lo_arg **argv, int argc,
	void *data, void *user_data)
{
	if(shutdown_in_progress==1)
	{
		return 0;
	}

	float offered_format_version=argv[0]->f;

	int offered_sample_rate=argv[1]->i;
	int offered_bytes_per_sample=argv[2]->i;
	int offered_period_size=argv[3]->i;
	int offered_channel_count=argv[4]->i;

	float offered_data_rate=argv[5]->f;
	uint64_t request_counter=argv[6]->h;

	lo_message msg=lo_message_new();
	lo_address loa= lo_message_get_source(data);

	fprintf(stderr,"\nsender sample rate: %d\n",offered_sample_rate);
	fprintf(stderr,"sender bytes per sample: %d\n",offered_bytes_per_sample);

	//re-use for forwarding
	sample_rate=offered_sample_rate;
	bytes_per_sample=offered_bytes_per_sample;

	//check if compatible with sender
	//could check more stuff (channel count, data rate, sender host/port, ...)
	if(
		offered_sample_rate==sample_rate
		&& offered_bytes_per_sample==bytes_per_sample
		&& offered_format_version==format_version

		//new: support non-matching period sizes
		//&& offered_period_size==period_size
	)
	{
		remote_sample_rate=sample_rate;
		remote_period_size=offered_period_size;

		strcpy(sender_host,lo_address_get_hostname(loa));
		strcpy(sender_port,lo_address_get_port(loa));

		//sending accept will tell the sender to start transmission
		lo_send_message (loa, "/accept", msg);

		/*
		fprintf(stderr,"\nreceiving from %s:%s",
			lo_address_get_hostname(loa),lo_address_get_port(loa));
		*/

		starting_transmission=1;
	}


	//data is incompatible, handle depending on --close
	else if(close_on_incomp==0)
	{
		//sending deny will tell sender to stop/quit
		lo_message_add_float(msg,format_version);
		lo_message_add_int32(msg,sample_rate);
		lo_message_add_int32(msg,bytes_per_sample);
		lo_send_message (loa, "/deny", msg);

		fprintf(stderr,"\ndenying transmission from %s:%s\nincompatible JACK settings or format version on sender:\nformat version: %.2f\nSR: %d\nbytes per sample: %d\ntelling sender to stop.\n",
			lo_address_get_hostname(loa),lo_address_get_port(loa),offered_format_version,offered_sample_rate,offered_bytes_per_sample
		);

		fflush(stderr);

		//shutting down is not a good strategy for the receiver in this case
		//shutdown_in_progress=1;
	}


	lo_message_free(msg);

	return 0;
} //end offer_handler
Beispiel #14
0
static int osc_send(CSOUND *csound, OSCSEND *p)
{
    /* Types I allow at present:
       0) int
       1) float
       2) string
       3) double
       4) char
       5) table as blob
    */
    char port[8];
    char *pp = port;
    char *hh;

    if (*p->port<0)
      pp = NULL;
    else
      snprintf(port, 8, "%d", (int) MYFLT2LRND(*p->port));
    hh = (char*) p->host->data;
    if (*hh=='\0') hh = NULL;
    if(p->addr != NULL)
      lo_address_free(p->addr);
    p->addr = lo_address_new(hh, pp);

    if (p->cnt++ ==0 || *p->kwhen!=p->last) {
      int i=0;
      int msk = 0x20;           /* First argument */
      lo_message msg = lo_message_new();
      char *type = (char*)p->type->data;
      MYFLT **arg = p->arg;
      p->last = *p->kwhen;
      for (i=0; type[i]!='\0'; i++, msk <<=1) {
        /* Need to add type checks */
        switch (type[i]) {
        case 'i':
          lo_message_add_int32(msg, (int32_t) MYFLT2LRND(*arg[i]));
          break;
        case 'l':
        case 'h':
          lo_message_add_int64(msg, (int64_t) MYFLT2LRND(*arg[i]));
          break;
        case 'c':
          lo_message_add_char(msg, (char) (*arg[i] + FL(0.5)));
          break;
        case 'm':
          {
            union a {
              int32_t  x;
              uint8_t  m[4];
            } mm;
            mm.x = *arg[i]+FL(0.5);
            lo_message_add_midi(msg, mm.m);
            break;
          }
        case 'f':
          lo_message_add_float(msg, (float)(*arg[i]));
          break;
        case 'd':
          lo_message_add_double(msg, (double)(*arg[i]));
          break;
        case 's':
            lo_message_add_string(msg, ((STRINGDAT *)arg[i])->data);
          break;
        case 'b':               /* Boolean */
          if (*arg[i]==FL(0.0)) lo_message_add_true(msg);
          else lo_message_add_false(msg);
          break;
        case 't':               /* timestamp */
          {
            lo_timetag tt;
            tt.sec = (uint32_t)(*arg[i]+FL(0.5));
            msk <<= 1; i++;
            if (UNLIKELY(type[i]!='t'))
              return csound->PerfError(csound, p->h.insdshead,
                                       Str("Time stamp is two values"));
            tt.frac = (uint32_t)(*arg[i]+FL(0.5));
            lo_message_add_timetag(msg, tt);
            break;
          }
          //#ifdef SOMEFINEDAY
        case 'G':               /* fGen Table/blob */
          {
            lo_blob myblob;
            int     len, olen;
            FUNC    *ftp;
            void *data;
            /* make sure fn exists */
            if (LIKELY((ftp=csound->FTnp2Find(csound,arg[i]))!=NULL)) {
              len = ftp->flen;        /* and set it up */
              data = csound->Malloc(csound,
                                    olen=sizeof(FUNC)-sizeof(MYFLT*)+
                                         sizeof(MYFLT)*len);
              memcpy(data, ftp, sizeof(FUNC)-sizeof(MYFLT*));
              memcpy(data+sizeof(FUNC)-sizeof(MYFLT*),
                     ftp->ftable, sizeof(MYFLT)*len);
            }
            else {
              return csound->PerfError(csound, p->h.insdshead,
                                       Str("ftable %.2f does not exist"), *arg[i]);
            }
            myblob = lo_blob_new(olen, data);
            lo_message_add_blob(msg, myblob);
            csound->Free(csound, data);
            lo_blob_free(myblob);
            break;
          }
          //#endif
        case 'a':               /* Audio as blob */
          {
            lo_blob myblob;
            MYFLT *data = csound->Malloc(csound, sizeof(MYFLT)*(CS_KSMPS+1));
            data[0] = CS_KSMPS;
            memcpy(&data[1], arg[i], data[0]);
            myblob = lo_blob_new(sizeof(MYFLT)*(CS_KSMPS+1), data);
            lo_message_add_blob(msg, myblob);
            csound->Free(csound, data);
            lo_blob_free(myblob);
            break;
          }
        case 'A':               /* Array/blob */
          {
            lo_blob myblob;
            int     len = 1;
            ARRAYDAT *ss;
            /* make sure fn exists */
            if (LIKELY((ss = (ARRAYDAT*)arg[i]) !=NULL &&
                       ss->data != NULL)) {
              int j, d;
              for (j=0,d=ss->dimensions; d>0; j++, d--)
                len *= ss->sizes[j];
              len *= sizeof(MYFLT);
            }
            else {
              return csound->PerfError(csound, p->h.insdshead,
                                       Str("argument %d is not an array"), i);
            }
            // two parts needed
            {
              void *dd = malloc(len+sizeof(int)*(1+ss->dimensions));
              memcpy(dd, &ss->dimensions, sizeof(int));
              memcpy(dd+sizeof(int), ss->sizes, sizeof(int)*ss->dimensions);
              memcpy(dd+sizeof(int)*(1+ss->dimensions), ss->data, len);
      /* printf("dd length = %d dimensions = %d, %d %d %.8x %.8x %.8x %.8x\n", */
      /*        len+sizeof(int)*(1+ss->dimensions), ss->dimensions, */
      /*        ((int*)dd)[0], ((int*)dd)[1], ((int*)dd)[2], ((int*)dd)[3], */
      /*        ((int*)dd)[4], ((int*)dd)[5]); */
              myblob = lo_blob_new(len, dd);
              free(dd);
            }
            lo_message_add_blob(msg, myblob);
            lo_blob_free(myblob);
            break;
          }
        case 'S': csound->Warning(csound, "S unimplemented"); break;
          //#endif
        default:
          csound->Warning(csound, Str("Unknown OSC type %c\n"), type[1]);
        }
      }
      lo_send_message(p->addr, (char*)p->dest->data, msg);
      lo_message_free(msg);
    }
    return OK;
}
Beispiel #15
0
static int osc_send(CSOUND *csound, OSCSEND *p)
{
    /* Types I allow at present:
       0) int
       1) float
       2) string
       3) double
       4) char
       5) table as blob
    */
    if (p->cnt++ ==0 || *p->kwhen!=p->last) {
      int i=0;
      int msk = 0x20;           /* First argument */
      lo_message msg = lo_message_new();
      char *type = (char*)p->type->data;
      MYFLT **arg = p->arg;
      p->last = *p->kwhen;
      for (i=0; type[i]!='\0'; i++, msk <<=1) {
        /* Need to add type checks */
        switch (type[i]) {
        case 'i':
          lo_message_add_int32(msg, (int32_t) MYFLT2LRND(*arg[i]));
          break;
        case 'l':
          lo_message_add_int64(msg, (int64_t) MYFLT2LRND(*arg[i]));
          break;
        case 'c':
          lo_message_add_char(msg, (char) (*arg[i] + FL(0.5)));
          break;
        case 'm':
          {
            union a {
              int32_t  x;
              uint8_t  m[4];
            } mm;
            mm.x = *arg[i]+FL(0.5);
            lo_message_add_midi(msg, mm.m);
            break;
          }
        case 'f':
          lo_message_add_float(msg, (float)(*arg[i]));
          break;
        case 'd':
          lo_message_add_double(msg, (double)(*arg[i]));
          break;
        case 's':
            lo_message_add_string(msg, ((STRINGDAT *)arg[i])->data);
          break;
        case 'b':               /* Boolean */
          if (*arg[i]==FL(0.0)) lo_message_add_true(msg);
          else lo_message_add_false(msg);
          break;
        case 't':               /* timestamp */
          {
            lo_timetag tt;
            tt.sec = (uint32_t)(*arg[i]+FL(0.5));
            msk <<= 1; i++;
            if (UNLIKELY(type[i]!='t'))
              return csound->PerfError(csound, p->h.insdshead,
                                       Str("Time stamp is two values"));
            tt.frac = (uint32_t)(*arg[i]+FL(0.5));
            lo_message_add_timetag(msg, tt);
            break;
          }
          //#ifdef SOMEFINEDAY
        case 'T':               /* Table/blob */
          {
            lo_blob myblob;
            int     len;
            FUNC    *ftp;
            void *data;
            /* make sure fn exists */
            if (LIKELY((ftp=csound->FTnp2Find(csound,arg[i]))!=NULL)) {
              data = ftp->ftable;
              len = ftp->flen-1;        /* and set it up */
            }
            else {
              return csound->PerfError(csound, p->h.insdshead,
                                       Str("ftable %.2f does not exist"), *arg[i]);
            }
            myblob = lo_blob_new(sizeof(MYFLT)*len, data);
            lo_message_add_blob(msg, myblob);
            lo_blob_free(myblob);
            break;
          }
          //#endif
        default:
          csound->Warning(csound, Str("Unknown OSC type %c\n"), type[1]);
        }
      }
      lo_send_message(p->addr, (char*)p->dest->data, msg);
      lo_message_free(msg);
    }
    return OK;
}
// *********************************************************
// -(new)---------------------------------------------------
void *oscmulticast_new(t_symbol *s, int argc, t_atom *argv)
{
	t_oscmulticast *x = NULL;
    int i, got_port = 0;
    char address[64];

#ifdef MAXMSP
    if ((x = object_alloc(oscmulticast_class))) {
        x->outlet3 = listout((t_object *)x);
        x->outlet2 = listout((t_object *)x);
        x->outlet1 = listout((t_object *)x);
#else
    if (x = (t_oscmulticast *) pd_new(oscmulticast_class)) {
        x->outlet1 = outlet_new(&x->ob, gensym("list"));
        x->outlet2 = outlet_new(&x->ob, gensym("list"));
        x->outlet3 = outlet_new(&x->ob, gensym("list"));
#endif

        x->group = NULL;
        x->iface = NULL;

        if (argc < 4) {
            post("oscmulticast: not enough arguments!\n");
            return NULL;
        }
        for (i = 0; i < argc; i++) {
            if(strcmp(maxpd_atom_get_string(argv+i), "@group") == 0) {
                if ((argv+i+1)->a_type == A_SYM) {
                    x->group = strdup(maxpd_atom_get_string(argv+i+1));
                    i++;
                }
            }
            else if (strcmp(maxpd_atom_get_string(argv+i), "@port") == 0) {
                if ((argv+i+1)->a_type == A_FLOAT) {
                    snprintf(x->port, 10, "%i", (int)maxpd_atom_get_float(argv+i+1));
                    got_port = 1;
                    i++;
                }
#ifdef MAXMSP
                else if ((argv+i+1)->a_type == A_LONG) {
                    snprintf(x->port, 10, "%i", (int)atom_getlong(argv+i+1));
                    got_port = 1;
                    i++;
                }
#endif
            }
            else if(strcmp(maxpd_atom_get_string(argv+i), "@interface") == 0) {
                if ((argv+i+1)->a_type == A_SYM) {
                    x->iface = strdup(maxpd_atom_get_string(argv+i+1));
                    i++;
                }
            }
        }

        if (!x->group || !got_port) {
            post("oscmulticast: need to specify group and port!");
            return NULL;
        }

        /* Open address */
        snprintf(address, 64, "osc.udp://%s:%s", x->group, x->port);
        x->address = lo_address_new_from_url(address);
        if (!x->address) {
            post("oscmulticast: could not create lo_address.");
            return NULL;
        }

        /* Set TTL for packet to 1 -> local subnet */
        lo_address_set_ttl(x->address, 1);

        /* Specify the interface to use for multicasting */
        if (x->iface) {
            if (lo_address_set_iface(x->address, x->iface, 0)) {
                post("oscmulticast: could not create lo_address.");
                return NULL;
            }
            x->server = lo_server_new_multicast_iface(x->group, x->port, x->iface, 0, 0);
        }
        else {
            x->server = lo_server_new_multicast(x->group, x->port, 0);
        }

        if (!x->server) {
            post("oscmulticast: could not create lo_server");
            lo_address_free(x->address);
            return NULL;
        }

        // Disable liblo message queueing
        lo_server_enable_queue(x->server, 0, 1);

        if (x->iface)
            post("oscmulticast: using interface %s", lo_address_get_iface(x->address));
        else
            post("oscmulticast: using default interface");
        lo_server_add_method(x->server, NULL, NULL, oscmulticast_handler, x);

#ifdef MAXMSP
        x->clock = clock_new(x, (method)oscmulticast_poll);	// Create the timing clock
#else
        x->clock = clock_new(x, (t_method)oscmulticast_poll);
#endif
        clock_delay(x->clock, INTERVAL);  // Set clock to go off after delay
    }
	return (x);
}

// *********************************************************
// -(free)--------------------------------------------------
void oscmulticast_free(t_oscmulticast *x)
{
    if (x->clock) {
        clock_unset(x->clock);	// Remove clock routine from the scheduler
        clock_free(x->clock);		// Frees memory used by clock
    }
    if (x->server) {
        lo_server_free(x->server);
    }
    if (x->address) {
        lo_address_free(x->address);
    }
    if (x->iface) {
        free(x->iface);
    }
    if (x->group) {
        free(x->group);
    }
}

// *********************************************************
// -(inlet/outlet assist - maxmsp only)---------------------
#ifdef MAXMSP
void oscmulticast_assist(t_oscmulticast *x, void *b, long m, long a, char *s)
{
	if (m == ASSIST_INLET) { // inlet
		sprintf(s, "OSC to be sent to multicast bus");
	}
	else {	// outlet
        sprintf(s, "OSC from multicast bus");
	}
}
#endif

// *********************************************************
// -(interface)---------------------------------------------
static void oscmulticast_interface(t_oscmulticast *x, t_symbol *s, int argc, t_atom *argv)
{
    const char *iface = 0;

    if (argc < 1)
        return;

    if (argv->a_type != A_SYM)
        return;

    iface = maxpd_atom_get_string(argv);

    if (lo_address_set_iface(x->address, iface, 0)) {
        post("oscmulticast: could not create lo_address.");
        return;
    }

    if (x->server)
        lo_server_free(x->server);
    x->server = lo_server_new_multicast_iface(x->group, x->port, iface, 0, 0);

    if (!x->server) {
        post("oscmulticast: could not create lo_server");
        return;
    }

    post("oscmulticast: using interface %s", lo_address_get_iface(x->address));
    lo_server_add_method(x->server, NULL, NULL, oscmulticast_handler, x);
}

// *********************************************************
// -(anything)----------------------------------------------
void oscmulticast_anything(t_oscmulticast *x, t_symbol *s, int argc, t_atom *argv)
{
    lo_message m = lo_message_new();
    if (!m) {
        post("lo_message_new() error");
        return;
    }

    int i;
    for (i=0; i<argc; i++)
    {
        switch ((argv + i)->a_type)
        {
			case A_FLOAT:
                lo_message_add_float(m, atom_getfloat(argv + i));
                break;
#ifdef MAXMSP
            case A_LONG:
                lo_message_add_int32(m, (int)atom_getlong(argv + i));
                break;
#endif
            case A_SYM:
                lo_message_add_string(m, maxpd_atom_get_string(argv + i));
                break;
        }
    }
    //set timetag?

    lo_send_message(x->address, s->s_name, m);
    lo_message_free(m);
}
Beispiel #17
0
int lo_message_add_varargs_internal(lo_message msg, const char *types,
                                    va_list ap, const char *file, int line)
{
    int count = 0;
    int ret = 0;

    while (types && *types) {
        count++;

        switch (*types++) {

        case LO_INT32:{
                int32_t i = va_arg(ap, int32_t);
                lo_message_add_int32(msg, i);
                break;
            }

        case LO_FLOAT:{
                float f = (float) va_arg(ap, double);
                lo_message_add_float(msg, f);
                break;
            }

        case LO_STRING:{
                char *s = va_arg(ap, char *);
#ifndef USE_ANSI_C
                if (s == (char *) LO_MARKER_A) {
                    fprintf(stderr,
                            "liblo error: lo_send or lo_message_add called with "
                            "invalid string pointer for arg %d, probably arg mismatch\n"
                            "at %s:%d, exiting.\n", count, file, line);
                }
#endif
                lo_message_add_string(msg, s);
                break;
            }

        case LO_BLOB:{
                lo_blob b = va_arg(ap, lo_blob);
                lo_message_add_blob(msg, b);
                break;
            }

        case LO_INT64:{
                int64_t i64 = va_arg(ap, int64_t);
                lo_message_add_int64(msg, i64);
                break;
            }

        case LO_TIMETAG:{
                lo_timetag tt = va_arg(ap, lo_timetag);
                lo_message_add_timetag(msg, tt);
                break;
            }

        case LO_DOUBLE:{
                double d = va_arg(ap, double);
                lo_message_add_double(msg, d);
                break;
            }

        case LO_SYMBOL:{
                char *s = va_arg(ap, char *);
#ifndef USE_ANSI_C
                if (s == (char *) LO_MARKER_A) {
                    fprintf(stderr,
                            "liblo error: lo_send or lo_message_add called with "
                            "invalid symbol pointer for arg %d, probably arg mismatch\n"
                            "at %s:%d, exiting.\n", count, file, line);
                    va_end(ap);
                    return -2;
                }
#endif
                lo_message_add_symbol(msg, s);
                break;
            }

        case LO_CHAR:{
                char c = va_arg(ap, int);
                lo_message_add_char(msg, c);
                break;
            }

        case LO_MIDI:{
                uint8_t *m = va_arg(ap, uint8_t *);
                lo_message_add_midi(msg, m);
                break;
            }

        case LO_TRUE:
            lo_message_add_true(msg);
            break;

        case LO_FALSE:
            lo_message_add_false(msg);
            break;

        case LO_NIL:
            lo_message_add_nil(msg);
            break;

        case LO_INFINITUM:
            lo_message_add_infinitum(msg);
            break;

        case '$':
            if (*types == '$') {
                // type strings ending in '$$' indicate not to perform
                // LO_MARKER checking
                va_end(ap);
                return 0;
            }
            // fall through to unknown type

        default:{
                ret = -1;       // unknown type
                fprintf(stderr,
                        "liblo warning: unknown type '%c' at %s:%d\n",
                        *(types - 1), file, line);
                break;
            }
        }
    }
#ifndef USE_ANSI_C
    void *i = va_arg(ap, void *);
    if (((unsigned long)i & 0xFFFFFFFFUL)
	!= ((unsigned long)LO_MARKER_A & 0xFFFFFFFFUL))
    {
        ret = -2;               // bad format/args
        fprintf(stderr,
                "liblo error: lo_send, lo_message_add, or lo_message_add_varargs called with "
                "mismatching types and data at\n%s:%d, exiting.\n", file,
                line);
        va_end(ap);
        return ret;
    }
    i = va_arg(ap, void *);
    if (((unsigned long)i & 0xFFFFFFFFUL)
	!= ((unsigned long)LO_MARKER_B & 0xFFFFFFFFUL))
    {
        ret = -2;               // bad format/args
        fprintf(stderr,
                "liblo error: lo_send, lo_message_add, or lo_message_add_varargs called with "
                "mismatching types and data at\n%s:%d, exiting.\n", file,
                line);
    }
#endif
    va_end(ap);

    return ret;
}
//================================================================
int main(int argc, char *argv[])
{
	//jack
	const char **ports;
	//jack_options_t options = JackNullOption;
	jack_status_t status;

//options struct was here

	if(argc-optind<1)
	{
		print_header("jack_audio_receive");
		fprintf(stderr, "Missing arguments, see --help.\n\n");
		exit(1);
	}

	int opt;
 	//do until command line options parsed
	while(1)
	{
		/* getopt_long stores the option index here. */
		int option_index=0;

		opt=getopt_long(argc, argv, "", long_options, &option_index);

		/* Detect the end of the options. */
		if(opt==-1)
		{
			break;
		}
		switch(opt)
		{
			case 0:

			 /* If this option set a flag, do nothing else now. */
			if(long_options[option_index].flag!=0)
			{
				break;
			}

			case 'h':
				print_header("jack_audio_receive");
				print_help();
				break;

			case 'v':
				print_version();
				break;

			case 'x':
				print_header("jack_audio_receive");
				check_lo_props(1);
				return 1;

			case 'o':
				output_port_count=atoi(optarg);

				if(output_port_count>max_channel_count)
				{
					output_port_count=max_channel_count;
				}
				port_count=fmin(input_port_count,output_port_count);
				break;

			case 'f':
				channel_offset=atoi(optarg);
				break;

			case 'y':
				bytes_per_sample=2;
				break;

			case 'n':
				client_name=optarg;
				break;

			case 's':
				server_name=optarg;
				jack_opts |= JackServerName;
				break;

			case 'b':
				pre_buffer_size=fmax(1,(uint64_t)atoll(optarg));
				break;

			case 'm':
				max_buffer_size=fmax(1,(uint64_t)atoll(optarg));
				break;

			case 'u':
				update_display_every_nth_cycle=fmax(1,(uint64_t)atoll(optarg));
				break;

			case 'l':
				receive_max=fmax(1,(uint64_t)atoll(optarg));
				test_mode=1;
				break;

			case 'a':
				io_host=optarg;
				break;

			case 'c':
				io_port=optarg;
				break;

			case 't':
				use_tcp=1;
				remote_tcp_server_port=optarg;
				break;

			case '?': //invalid commands
				/* getopt_long already printed an error message. */
				print_header("jack_audio_receive");
				fprintf(stderr, "Wrong arguments, see --help.\n\n");
				exit(1);

				break;
 	 
			default:
				break;
		 } //end switch op
	}//end while(1)


	//remaining non optional parameters listening port
	if(argc-optind!=1)
	{
		print_header("jack_audio_receive");
		fprintf(stderr, "Wrong arguments, see --help.\n\n");
		exit(1);
	}

	localPort=argv[optind];

	//for commuication with a gui / other controller / visualizer
	loio=lo_address_new_with_proto(LO_UDP, io_host, io_port);

	//if was set to use random port
	if(atoi(localPort)==0)
	{
		//for lo_server_thread_new_with_proto
		localPort=NULL;
	}

	//add osc hooks & start osc server early (~right after cmdline parsing)
	registerOSCMessagePatterns(localPort);

	lo_server_thread_start(lo_st);

	//read back port (in case of random)
	//could use 
	//int lo_server_thread_get_port(lo_server_thread st)
	const char *osc_server_url=lo_server_get_url(lo_server_thread_get_server(lo_st));
	localPort=lo_url_get_port(osc_server_url);
	//int lport=lo_server_thread_get_port(lo_st);

	//notify osc gui
	if(io_())
	{
		lo_message msgio=lo_message_new();
		lo_message_add_float(msgio, version);
		lo_message_add_float(msgio, format_version);
		lo_send_message(loio, "/startup", msgio);
		lo_message_free(msgio);
	}

	if(check_lo_props(0)>0)
	{
		return 1;
	}


	if(use_tcp==1)
	{
		lo_proto=LO_TCP;
	}

	if(shutup==0)
	{
		print_header("jack_audio_receive");

		if(output_port_count>max_channel_count)
		{
			fprintf(stderr,"/!\\ limiting playback ports to %d, sry\n",max_channel_count);
		}

		if(test_mode==1)
		{
			fprintf(stderr,"/!\\ limiting number of messages: %" PRId64 "\n",receive_max);
		}
	}

	//check for default jack server env var
	char *evar=getenv("JACK_DEFAULT_SERVER");
	if(evar==NULL || strlen(evar)<1)
	{
#ifndef _WIN
		unsetenv("JACK_DEFAULT_SERVER");
#endif
	}

	else if(server_name==NULL)
	{
		//use env var if no server was given with --sname
		server_name=evar;
	}

	if(server_name==NULL || strlen(server_name)<=0)
	{
		server_name="default";
	}

	if(client_name==NULL)
	{
		client_name="receive";
	}

	if(have_libjack()!=0)
	{
		fprintf(stderr,"/!\\ libjack not found (JACK not installed?). this is fatal: jack_audio_receive needs JACK to run.\n");
		io_quit("nolibjack");
		exit(1);
	}

	//initialize time
	gettimeofday(&tv, NULL);
	tt_prev.sec=tv.tv_sec;
	tt_prev.frac=tv.tv_usec;

	//create an array of input ports
	ioPortArray=(jack_port_t**) malloc(output_port_count * sizeof(jack_port_t*));

	//open a client connection to the JACK server
	client=jack_client_open(client_name, jack_opts, &status, server_name);
	if(client==NULL) 
		{
		fprintf(stderr,"jack_client_open() failed, status = 0x%2.0x\n", status);
		if(status & JackServerFailed) 
		{
			fprintf(stderr,"Unable to connect to JACK server.\n");
			io_quit("nojack");
		}
		exit(1);
	}

	if(use_tcp==1)
	{

		if(shutup==0)
		{
			fprintf(stderr,"receiving on TCP port: %s\n",localPort);
		}
	}
	else
	{
		if(shutup==0)
		{
			fprintf(stderr,"receiving on UDP port: %s\n",localPort);
	}
	}

	client_name=jack_get_client_name(client);

	if(shutup==0)
	{
		fprintf(stderr,"started JACK client '%s' on server '%s'\n",client_name,server_name);
		if(status & JackNameNotUnique) 
		{
			fprintf(stderr, "/!\\ name '%s' was automatically assigned\n", client_name);
		}
	}

	if(status & JackNameNotUnique) 
	{
		io_simple("/client_name_changed");
	}

	//print startup info

	read_jack_properties();

	if(shutup==0)
	{
		print_common_jack_properties();

		fprintf(stderr,"channels (playback): %d\n",output_port_count);
		fprintf(stderr,"channel offset: %d\n",channel_offset);

		print_bytes_per_sample();

		fprintf(stderr,"multi-channel period size: %d bytes\n",
			output_port_count*period_size*bytes_per_sample
		);

		char *strat="fill with zero (silence)";
		if(zero_on_underflow==0)
		{
			strat="re-use last available period";
		}

		fprintf(stderr,"underflow strategy: %s\n",strat);

		if(rebuffer_on_restart==1)
		{
			fprintf(stderr,"rebuffer on sender restart: yes\n");
		}
		else
		{
			fprintf(stderr,"rebuffer on sender restart: no\n");
		}

		if(rebuffer_on_underflow==1)
		{
			fprintf(stderr,"rebuffer on underflow: yes\n");
		}
		else
		{
			fprintf(stderr,"rebuffer on underflow: no\n");
		}

		if(allow_remote_buffer_control==1)
		{
			fprintf(stderr,"allow external buffer control: yes\n");
		}
		else
		{
			fprintf(stderr,"allow external buffer control: no\n");
		}

		if(close_on_incomp==1)
		{
			fprintf(stderr,"shutdown receiver when incompatible data received: yes\n");
		}
		else
		{
			fprintf(stderr,"shutdown receiver when incompatible data received: no\n");
		}

	}//end cond. print

	char buf[64];
	format_seconds(buf,(float)pre_buffer_size*period_size/(float)sample_rate);

	uint64_t rb_size_pre=pre_buffer_size*output_port_count*period_size*bytes_per_sample;

	if(shutup==0)
	{
		fprintf(stderr,"initial buffer size: %" PRId64 " mc periods (%s, %" PRId64 " bytes, %.2f MB)\n",
			pre_buffer_size,
			buf,
			rb_size_pre,
			(float)rb_size_pre/1000/1000
		);
	}
	buf[0]='\0';

	//ringbuffer size bytes
	uint64_t rb_size;

	//ringbuffer mc periods
	int max_buffer_mc_periods;

	//max given as param (user knows best. if pre=max, overflows are likely)
	if(max_buffer_size>0)
	{
		max_buffer_mc_periods=fmax(pre_buffer_size,max_buffer_size);
		rb_size=max_buffer_mc_periods
			*output_port_count*period_size*bytes_per_sample;
	}
	else //"auto"
	{
		//make max buffer 0.5 seconds larger than pre buffer
		max_buffer_mc_periods=pre_buffer_size+ceil(0.5*(float)sample_rate/period_size);
		rb_size=max_buffer_mc_periods
			*output_port_count*period_size*bytes_per_sample;
	}

	max_buffer_size=max_buffer_mc_periods;

	format_seconds(buf,(float)max_buffer_mc_periods*period_size/sample_rate);
	if(shutup==0)
	{
		fprintf(stderr,"allocated buffer size: %" PRId64 " mc periods (%s, %" PRId64 " bytes, %.2f MB)\n",
			max_buffer_size,
			buf,
			rb_size,
			(float)rb_size/1000/1000
		);
	}
	buf[0]='\0';

	io_dump_config();

	//====================================
	//main ringbuffer osc blobs -> jack output
	rb=jack_ringbuffer_create(rb_size);
	//helper ringbuffer: used when remote period size < local period size
	rb_helper=jack_ringbuffer_create(rb_size);

	if(rb==NULL)
	{
		fprintf(stderr,"could not create a ringbuffer with that size.\n");
		fprintf(stderr,"try --max <smaller size>.\n");
		io_quit("ringbuffer_too_large");
		exit(1);
	}

	//JACK will call process() for every cycle (given by JACK)
	//NULL could be config/data struct
	jack_set_process_callback(client, process, NULL);

	jack_set_xrun_callback(client, xrun_handler, NULL);

	//register hook to know when JACK shuts down or the connection 
	//was lost (i.e. client zombified)
	jack_on_shutdown(client, jack_shutdown_handler, 0);

	// Register each output port
	int port;
	for(port=0; port<output_port_count; port ++)
	{
		// Create port name
		char* portName;
		if(asprintf(&portName, "output_%d", (port+1)) < 0) 
		{
			fprintf(stderr,"Could not create portname for port %d", port);
			io_quit("port_error");
			exit(1);
		}

		// Register the output port
		ioPortArray[port]=jack_port_register(client, portName, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
		if(ioPortArray[port]==NULL) 
		{
			fprintf(stderr,"Could not create output port %d\n", (port+1));
			io_quit("port_error");
			exit(1);
		}
	}

	/* Tell the JACK server that we are ready to roll. Our
	 * process() callback will start running now. */
	if(jack_activate(client)) 
	{
		fprintf(stderr, "cannot activate client");
		io_quit("cannot_activate_client");
		exit(1);
	}

	/* Connect the ports. You can't do this before the client is
	 * activated, because we can't make connections to clients
	 * that aren't running. Note the confusing (but necessary)
	 * orientation of the driver backend ports: playback ports are
	 * "input" to the backend, and capture ports are "output" from
	 * it.
	 */
	//prevent to get physical midi ports
	const char* pat="audio";

	ports=jack_get_ports(client, NULL, pat, JackPortIsPhysical|JackPortIsInput);

	if(ports==NULL) 
	{
		if(shutup==0)		
		{
			fprintf(stderr,"no physical playback ports\n");
		}
		//exit(1);
	}
	
	if(autoconnect==1)
	{
		fprintf(stderr, "\n");

		int j=0;
		int i;
		for(i=0;i<output_port_count;i++)
		{
			if(ports[i]!=NULL 
				&& ioPortArray[j]!=NULL 
				&& jack_port_name(ioPortArray[j])!=NULL)
			{
				if(!jack_connect(client, jack_port_name(ioPortArray[j]), ports[i]))
				{
					if(shutup==0)
					{
						fprintf(stderr, "autoconnect: %s -> %s\n",
							jack_port_name(ioPortArray[j]),ports[i]
						);
					}
					io_simple_string_double("/autoconnect",jack_port_name(ioPortArray[j]),ports[i]);
					j++;
				}
				else
				{
					if(shutup==0)
					{
						fprintf(stderr, "autoconnect: failed: %s -> %s\n",
							jack_port_name(ioPortArray[j]),ports[i]
						);
					}
				}
			}
			else
			{
				//no more playback ports
				break;
			}
		}//end for all output ports

		if(shutup==0)
		{
			fprintf(stderr, "\n");
		}
	}

	free(ports);

	fflush(stderr);

	/* install a signal handler to properly quits jack client */
#ifndef _WIN
	signal(SIGQUIT, signal_handler);
	signal(SIGHUP, signal_handler);
#endif
	signal(SIGTERM, signal_handler);
	signal(SIGINT, signal_handler);

	if(use_tcp==1)
	{
		//10 MB max
		int desired_max_tcp_size=10000000;

		lo_server s=lo_server_thread_get_server(lo_st);
		int ret_set_size=lo_server_max_msg_size(s, desired_max_tcp_size);

		if(shutup==0)
		{
			printf("set tcp max size return: %d\n",ret_set_size);
			io_simple("/tcp_max_size_xxxx");
		}
	}

	not_yet_ready=0;

	io_simple("/start_main_loop");

	//run possibly forever until not interrupted by any means
	while(1) 
	{
		//possibly clean shutdown without any glitches
		if(shutdown_in_progress==1)
		{
			signal_handler(42);
		}
#ifdef WIN_
		Sleep(1000);
#else
		sleep(1);
#endif
	}

	exit(0);
}//end main
//================================================================
// /audio
//handler for audio messages
int osc_audio_handler(const char *path, const char *types, lo_arg **argv, int argc,
	void *data, void *user_data)
{
	if(shutdown_in_progress==1 || not_yet_ready==1)
	{
		return 0;
	}

	//init to 0, increment before use
	msg_received_counter++;

	gettimeofday(&tv, NULL);

	//first blob is at data_offset+1 (one-based)
	int data_offset=4;

	//ignore first n channels/blobs
	data_offset+=channel_offset;

	message_number_prev=message_number;

	//the messages are numbered sequentially. first msg is numberd 1
	message_number=argv[0]->h;

	if(message_number_prev<message_number-1)
	{
		fprintf(stderr,"\ngap in message sequence! possibly lost %" PRId64" message(s) on the way.\n"
			,message_number-message_number_prev-1);
		fflush(stderr);
	}

	//total args count minus metadata args count = number of blobs
	input_port_count=argc-data_offset;

	//only process useful number of channels
	port_count=fmin(input_port_count,output_port_count);

	if(port_count < 1)
	{
		fprintf(stderr,"channel offset %d >= available input channels %d! (nothing to receive). shutting down...\n"
			,channel_offset
			,channel_offset+input_port_count);
		fflush(stderr);
		shutdown_in_progress=1;
		return 0;
	}

	//check sample rate and period size if sender (re)started or values not yet initialized (=no /offer received)
	if(message_number_prev>message_number || message_number==1 || remote_sample_rate==0 || remote_period_size==0 )
	{
		lo_address loa;

		if(use_tcp==1)
		{
			lo_address loa_=lo_message_get_source(data);
			loa=lo_address_new_with_proto(lo_proto,lo_address_get_hostname(loa_),remote_tcp_server_port);
		}
		else
		{
			loa=lo_message_get_source(data);
		}

		strcpy(sender_host,lo_address_get_hostname(loa));
		strcpy(sender_port,lo_address_get_port(loa));

		//option --rebuff
		if(rebuffer_on_restart==1)
		{
			uint64_t can_read_count=jack_ringbuffer_read_space(rb);
			pre_buffer_counter=fmax(0,(float)can_read_count/(float)bytes_per_sample/(float)period_size/(float)port_count);
			//start buffering
			process_enabled=0;
		}
		else
		{
			pre_buffer_counter=0;
		}

		remote_sample_rate=argv[3]->i;

		if(sample_rate!=remote_sample_rate)
		{
			if(close_on_incomp==0)
			{
				//sending deny will tell sender to stop/quit
				lo_message msg=lo_message_new();


				lo_message_add_float(msg,format_version);
				lo_message_add_int32(msg,sample_rate);
// /deny as reply to /audio should be the same as for /deny as reply to /offer
//will need change of /audio (add format, bytes_per_sample)
///////
				lo_message_add_int32(msg,99);

				lo_send_message(loa, "/deny", msg);
				lo_message_free(msg);

				fprintf(stderr,"\ndenying transmission from %s:%s\n(incompatible JACK settings on sender: SR: %d). telling sender to stop.\n",
					lo_address_get_hostname(loa),lo_address_get_port(loa),remote_sample_rate
				);
				fflush(stderr);

				message_number=0;
				message_number_prev=0;
				remote_sample_rate=0;
				remote_period_size=0;
				//pre_buffer_counter=0;
			}
			else
			{
				lo_address loa;

				if(use_tcp==1)
				{
					lo_address loa_=lo_message_get_source(data);
					loa=lo_address_new_with_proto(lo_proto,lo_address_get_hostname(loa_),remote_tcp_server_port);
				}
				else
				{
					loa=lo_message_get_source(data);
				}

				fprintf(stderr,"\ndenying transmission from %s:%s\nincompatible JACK settings on sender: SR: %d.\nshutting down (see option --close)...\n",
					lo_address_get_hostname(loa),lo_address_get_port(loa),remote_sample_rate
				);
				fflush(stderr);

				shutdown_in_progress=1;
				return 0;
			}
		}

		remote_period_size=lo_blob_datasize((lo_blob)argv[0+data_offset])/bytes_per_sample;

		if(shutup==0 && quiet==0)
		{
			fprintf(stderr,"\nsender was (re)started. ");

			lo_address loa=lo_message_get_source(data);
			fprintf(stderr,"receiving from %s:%s\n",lo_address_get_hostname(loa),lo_address_get_port(loa));
		}

		io_simple("/sender_restarted");

		if(shutup==0 && quiet==0)
		{
			if(remote_period_size!=period_size)
			{
				fprintf(stderr,"sender period size: %d samples (%.3f x local)\n\n",remote_period_size,(float)remote_period_size/period_size);
			}
			else
			{
				fprintf(stderr,"equal sender and receiver period size\n\n");
			}

			fflush(stderr);
		}

	}//end if "no-offer init" was needed

	remote_xrun_counter=argv[1]->h;

	lo_timetag tt=argv[2]->t;

	double msg_time=tt.sec+(double)tt.frac/1000000;
	double msg_time_prev=tt_prev.sec+(double)tt_prev.frac/1000000;
//unused for now
//	double time_now=tv.tv_sec+(double)tv.tv_usec/1000000;

	time_interval=msg_time-msg_time_prev;

	time_interval_sum+=time_interval;
	time_interval_avg=(float)time_interval_sum/msg_received_counter;

	tt_prev=tt;

	//reset avg calc, check and reset after use
	if(msg_received_counter>=avg_calc_interval)
	{
		msg_received_counter=0;
		time_interval_sum=0;
	}

	if(pre_buffer_counter>=pre_buffer_size && process_enabled==0)
	{
		//if buffer filled, start to output audio in process()
		process_enabled=1;
	}

	int mc_period_bytes=period_size*bytes_per_sample*port_count;

	//check if a whole mc period can be written to the ringbuffer
	uint64_t can_write_count=jack_ringbuffer_write_space(rb);
	if(can_write_count < mc_period_bytes)
	{
			buffer_overflow_counter++;
			/////////////////
			if(shutup==0 && quiet==0)
			{
				fprintf(stderr,"\rBUFFER OVERFLOW! this is bad -----%s","\033[0J");
			}
			return 0;
	}

	//========================================
	//new: support different period sizes on sender / receiver (still need same SR)
	//this needs more tests and optimization
	if(period_size==remote_period_size)
	{
		int i;
		//don't read more channels than we have outputs
		for(i=0;i < port_count;i++)
		{
			//get blob (=one period of one channel)
			unsigned char *data=lo_blob_dataptr((lo_blob)argv[i+data_offset]);
			//fprintf(stderr,"size %d\n",lo_blob_datasize((lo_blob)argv[i+data_offset]));

			//write to ringbuffer
			//==========================================
			//int cnt=
			jack_ringbuffer_write(rb, (void *) data, 
				period_size*bytes_per_sample);
		}
		pre_buffer_counter++;
	}
	else if(period_size>remote_period_size)
	{
		int i;
		//don't read more channels than we have outputs
		for(i=0;i < port_count;i++)
		{
			//get blob (=one period of one channel)
			unsigned char *data=lo_blob_dataptr((lo_blob)argv[i+data_offset]);
			//fprintf(stderr,"size %d\n",lo_blob_datasize((lo_blob)argv[i+data_offset]));

			//write to temporary ringbuffer until there is enough data
			//==========================================
			//int cnt=
			jack_ringbuffer_write(rb_helper, (void *) data, 
				remote_period_size*bytes_per_sample);
		}

		//if enough data collected for one larger multichannel period

		while(jack_ringbuffer_read_space(rb_helper)	>=mc_period_bytes
		&& jack_ringbuffer_write_space(rb)		>=mc_period_bytes)
		{
			//transfer from helper to main ringbuffer
			unsigned char* data;
			data=malloc(				mc_period_bytes);
			//store orig pointer
			unsigned char* orig_data=data;
			jack_ringbuffer_read(rb_helper,data,	mc_period_bytes);

			for(i=0;i < port_count;i++)
			{
				int k;
				for(k=0;k<(period_size/remote_period_size);k++)
				{
					//reset pointer
					data=orig_data;
					//position in helper buffer for next sample for main buffer
					data+=	k*remote_period_size*bytes_per_sample*port_count
							+ i*remote_period_size*bytes_per_sample;

					//write one channel snipped (remote_period_size) to main buffer
					//int w=
					jack_ringbuffer_write(rb,(void *)data,remote_period_size*bytes_per_sample);
				}
			}
			data=orig_data;
			free(data);

			pre_buffer_counter++;
		}
	}
	else if(period_size<remote_period_size)
	{
		int k;
		for(k=0;k<(remote_period_size/period_size);k++)
		{

			int i;
			//don't read more channels than we have outputs
			for(i=0;i < port_count;i++)
			{
				//get blob (=one period of one channel)
				unsigned char *data=lo_blob_dataptr((lo_blob)argv[i+data_offset]);
				//fprintf(stderr,"size %d\n",lo_blob_datasize((lo_blob)argv[i+data_offset]));

				//write to ringbuffer
				//==========================================
				data+=k*period_size*bytes_per_sample;

				//int cnt=
				jack_ringbuffer_write(rb, (void *) data, 
					period_size*bytes_per_sample);
			}
			pre_buffer_counter++;
		}
	}

	return 0;
}//end osc_audio_handler
ValueWrapper SceneManagerCallback_script( const char* symName, const char* method,
                                          boost::python::list& argList, int cascadeEvents )
{
    //int i;
    std::string    theMethod( method );
    cppintrospection::ValueList theArgs;
    //printf("SceneManagerCallback_script: hi! %s, %s, [%s]\n", symName, types, args.c_str());
    t_symbol *s = gensym( symName );

    if (!s->s_thing)
    {
        //std::cout << "oscParser: Could not find referenced object named: " << symName << std::endl;
        return ValueWrapper(0);
    }

    // get osgInrospection::Value from passed UserData by casting as the proper
    // referenced object pointer:
    cppintrospection::Value classInstance;
    if (s->s_type == REFERENCED_STATESET)
        classInstance = cppintrospection::Value(dynamic_cast<ReferencedStateSet*>(s->s_thing));
    else
        classInstance = cppintrospection::Value(dynamic_cast<ReferencedNode*>(s->s_thing));

    // the getInstanceType() method however, gives us the real type being pointed at:
    const cppintrospection::Type &classType = classInstance.getInstanceType();

    if (! classType.isDefined())
    {
        std::cout << "ERROR: oscParser cound not process message '" << symName
                  << ". cppintrospection has no data for that node." << std::endl;
        return ValueWrapper(0);
    }

    size_t nbArgs = boost::python::len( argList );
    double da; float fa; int ia; std::string sa;

    for ( size_t i = 0; i < nbArgs; i++ )
    {

        if ( pyextract( argList[i], &da ) )
            theArgs.push_back( (double) da );
        else if ( pyextract( argList[i], &fa ) )
            theArgs.push_back( (float) fa );
        else if ( pyextract( argList[i], &ia ) )
            theArgs.push_back( (int) ia );
        else
        {
            sa = pyextract( argList[i] );
            if (sa != "" )
                theArgs.push_back( (const char*) sa.c_str() );
        }
    }

    // invoke the method on the node, and if it doesn't work, then just forward
    // the message:
    cppintrospection::Value v;
    bool eventScriptCalled = false;
    if (cascadeEvents)
    {
        if (s->s_type == REFERENCED_NODE)
        {
            //printf("calling eventscript...\n");
            eventScriptCalled = dynamic_cast<ReferencedNode*>(s->s_thing)->callEventScript( theMethod, theArgs );
        }
    }

    if (eventScriptCalled)
    { // cascaded event script called successful, do not invokeMethod, return nothing to the python script
        return ValueWrapper(0);
    }
    else
    { // no cascaded event assigned to theMethod or cascaded event script failed.  call invokeMethod and return result to python script
        if (invokeMethod(classInstance, classType, theMethod, theArgs, v))
        {
            return ValueWrapper(v);
        }
        else
        {
            if (spinApp::Instance().getContext()->isServer())
            {
                lo_message msg = lo_message_new();
                lo_message_add_string(msg, theMethod.c_str());
                for ( size_t i = 0; i < nbArgs; i++ )
                {
                    if ( pyextract( argList[i], &da ) ) lo_message_add_float(msg, (float) da );
                    else if ( pyextract( argList[i], &fa ) ) lo_message_add_float(msg, (float) fa );
                    else if ( pyextract( argList[i], &ia ) ) lo_message_add_float(msg, (float) ia );
                    else
                    {
                        sa = pyextract( argList[i] );
                        if (sa != "" ) lo_message_add_string(msg, (const char*) sa.c_str() );
                    }
                }
                std::string path = "/SPIN/" + spinApp::Instance().getSceneID() + "/" + s->s_name;
                std::vector<lo_address>::iterator addrIter;
                for (addrIter = spinApp::Instance().getContext()->lo_txAddrs_.begin(); addrIter != spinApp::Instance().getContext()->lo_txAddrs_.end(); ++addrIter)
                {
                    lo_send_message_from((*addrIter), spinApp::Instance().getContext()->lo_infoServ_, path.c_str(), msg);
                }
            }
        }

    }
    //pthread_mutex_unlock(&sceneMutex);
    return ValueWrapper(0);
}
Beispiel #21
0
int main(int argc, char **argv)
{
    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("testdatabase.c: possible arguments "
                                "-q quiet (suppress output), "
                                "-h help\n");
                        return 1;
                        break;
                    case 'q':
                        verbose = 0;
                        break;
                    default:
                        break;
                }
            }
        }
    }

    lo_message lom;
    mapper_message msg;
    uint64_t id = 1;
    mapper_network net = mapper_network_new(0, 0, 0);
    mapper_database db = &net->database;

    mapper_device dev, *pdev, *pdev2;
    mapper_signal sig, *psig, *psig2;
    mapper_map *pmap, *pmap2;

    /* Test the database functions */

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }
    lo_message_add_string(lom, "@port");
    lo_message_add_int32(lom, 1234);
    lo_message_add_string(lom, "@host");
    lo_message_add_string(lom, "localhost");
    lo_message_add_string(lom, "@num_inputs");
    lo_message_add_int32(lom, 2);
    lo_message_add_string(lom, "@num_outputs");
    lo_message_add_int32(lom, 2);

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    mapper_database_add_or_update_device(db, "testdatabase.1", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }
    lo_message_add_string(lom, "@port");
    lo_message_add_int32(lom, 1234);
    lo_message_add_string(lom, "@host");
    lo_message_add_string(lom, "localhost");
    lo_message_add_string(lom, "@num_inputs");
    lo_message_add_int32(lom, 2);
    lo_message_add_string(lom, "@num_outputs");
    lo_message_add_int32(lom, 1);

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    mapper_database_add_or_update_device(db, "testdatabase__.2", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }
    lo_message_add_string(lom, "@port");
    lo_message_add_int32(lom, 3000);
    lo_message_add_string(lom, "@host");
    lo_message_add_string(lom, "192.168.0.100");

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    mapper_database_add_or_update_device(db, "testdatabase.3", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }
    lo_message_add_string(lom, "@port");
    lo_message_add_int32(lom, 5678);
    lo_message_add_string(lom, "@host");
    lo_message_add_string(lom, "192.168.0.100");

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    mapper_database_add_or_update_device(db, "testdatabase__.4", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }
    lo_message_add_string(lom, "@direction");
    lo_message_add_string(lom, "input");
    lo_message_add_string(lom, "@type");
    lo_message_add_char(lom, 'f');
    lo_message_add_string(lom, "@id");
    lo_message_add_int64(lom, id);

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    mapper_database_add_or_update_signal(db, "in1", "testdatabase.1", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }

    id++;
    lo_message_add_string(lom, "@direction");
    lo_message_add_string(lom, "input");
    lo_message_add_string(lom, "@type");
    lo_message_add_char(lom, 'f');
    lo_message_add_string(lom, "@id");
    lo_message_add_int64(lom, id);

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    mapper_database_add_or_update_signal(db, "in2", "testdatabase.1", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }

    id++;
    lo_message_add_string(lom, "@direction");
    lo_message_add_string(lom, "output");
    lo_message_add_string(lom, "@type");
    lo_message_add_char(lom, 'f');
    lo_message_add_string(lom, "@id");
    lo_message_add_int64(lom, id);

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    mapper_database_add_or_update_signal(db, "out1", "testdatabase.1", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }

    id++;
    lo_message_add_string(lom, "@direction");
    lo_message_add_string(lom, "output");
    lo_message_add_string(lom, "@type");
    lo_message_add_char(lom, 'f');
    lo_message_add_string(lom, "@id");
    lo_message_add_int64(lom, id);

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    mapper_database_add_or_update_signal(db, "out2", "testdatabase.1", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }

    id++;
    lo_message_add_string(lom, "@direction");
    lo_message_add_string(lom, "output");
    lo_message_add_string(lom, "@type");
    lo_message_add_char(lom, 'f');
    lo_message_add_string(lom, "@id");
    lo_message_add_int64(lom, id);

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    mapper_database_add_or_update_signal(db, "out1", "testdatabase__.2", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }

    id++;
    lo_message_add_string(lom, "@mode");
    lo_message_add_string(lom, "bypass");
    lo_message_add_string(lom, "@dst@bound_min");
    lo_message_add_string(lom, "none");
    lo_message_add_string(lom, "@id");
    lo_message_add_int64(lom, id);

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    const char *src_sig_name = "testdatabase.1/out2";
    mapper_database_add_or_update_map(db, 1, &src_sig_name,
                                      "testdatabase__.2/in1", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }

    id++;
    lo_message_add_string(lom, "@mode");
    lo_message_add_string(lom, "bypass");
    lo_message_add_string(lom, "@dst@bound_min");
    lo_message_add_string(lom, "none");
    lo_message_add_string(lom, "@id");
    lo_message_add_int64(lom, id);

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    src_sig_name = "testdatabase__.2/out1";
    mapper_database_add_or_update_map(db, 1, &src_sig_name,
                                      "testdatabase.1/in1", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }

    id++;
    lo_message_add_string(lom, "@mode");
    lo_message_add_string(lom, "expression");
    lo_message_add_string(lom, "@expression");
    lo_message_add_string(lom, "(x-10)*80");
    lo_message_add_string(lom, "@dst@bound_min");
    lo_message_add_string(lom, "clamp");
    lo_message_add_string(lom, "@src@min");
    lo_message_add_float(lom, 0.f);
    lo_message_add_float(lom, 1.f);
    lo_message_add_string(lom, "@src@max");
    lo_message_add_float(lom, 1.f);
    lo_message_add_float(lom, 2.f);
    lo_message_add_string(lom, "@id");
    lo_message_add_int64(lom, id);

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    src_sig_name = "testdatabase.1/out1";
    mapper_database_add_or_update_map(db, 1, &src_sig_name,
                                      "testdatabase__.2/in2", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }

    id++;
    lo_message_add_string(lom, "@mode");
    lo_message_add_string(lom, "expression");
    lo_message_add_string(lom, "@expression");
    lo_message_add_string(lom, "(x-10)*80");
    lo_message_add_string(lom, "@dst@bound_min");
    lo_message_add_string(lom, "clamp");
    lo_message_add_string(lom, "@src@min");
    lo_message_add_float(lom, 0.f);
    lo_message_add_float(lom, 1.f);
    lo_message_add_string(lom, "@src@max");
    lo_message_add_float(lom, 1.f);
    lo_message_add_float(lom, 2.f);
    lo_message_add_string(lom, "@id");
    lo_message_add_int64(lom, id);

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    src_sig_name = "testdatabase.1/out1";
    mapper_database_add_or_update_map(db, 1, &src_sig_name,
                                      "testdatabase__.2/in1", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    /*********/

    if (verbose) {
        eprintf("Dump:\n");
        mapper_database_print(db);
    }

    /*********/

    eprintf("\n--- Devices ---\n");

    eprintf("\nWalk the whole database:\n");
    pdev = mapper_database_devices(db);
    int count=0;
    if (!pdev) {
        eprintf("mapper_database_devices() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pdev) {
        eprintf("mapper_database_devices() returned something "
               "which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pdev) {
        count ++;
        printdevice(*pdev);
        pdev = mapper_device_query_next(pdev);
    }

    if (count != 4) {
        eprintf("Expected 4 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind device named 'testdatabase.3':\n");

    dev = mapper_database_device_by_name(db, "testdatabase.3");
    if (!dev) {
        eprintf("Not found.\n");
        result = 1;
        goto done;
    }

    printdevice(dev);

    /*********/

    eprintf("\nFind device named 'dummy':\n");

    dev = mapper_database_device_by_name(db, "dummy");
    if (dev) {
        eprintf("unexpected found 'dummy': %p\n", dev);
        result = 1;
        goto done;
    }
    eprintf("  not found, good.\n");

    /*********/

    eprintf("\nFind devices matching '__':\n");

    pdev = mapper_database_devices_by_name(db, "*__*");

    count=0;
    if (!pdev) {
        eprintf("mapper_database_devices_by_name() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pdev) {
        eprintf("mapper_database_devices_by_name() returned something "
                "which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pdev) {
        count ++;
        printdevice(*pdev);
        pdev = mapper_device_query_next(pdev);
    }

    if (count != 2) {
        eprintf("Expected 2 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind devices with property 'host'=='192.168.0.100':\n");

    pdev = mapper_database_devices_by_property(db, "host", 1, 's',
                                               "192.168.0.100", MAPPER_OP_EQUAL);

    count=0;
    if (!pdev) {
        eprintf("mapper_database_devices_by_property() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pdev) {
        eprintf("mapper_database_devices_by_property() returned something "
                "which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pdev) {
        count ++;
        printdevice(*pdev);
        pdev = mapper_device_query_next(pdev);
    }

    if (count != 2) {
        eprintf("Expected 2 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind devices with property 'port'<5678:\n");

    int port = 5678;
    pdev = mapper_database_devices_by_property(db, "port", 1, 'i', &port,
                                               MAPPER_OP_LESS_THAN);

    count=0;
    if (!pdev) {
        eprintf("mapper_database_devices_by_property() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pdev) {
        eprintf("mapper_database_devices_by_property() returned something "
                "which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pdev) {
        count ++;
        printdevice(*pdev);
        pdev = mapper_device_query_next(pdev);
    }

    if (count != 3) {
        eprintf("Expected 3 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind devices with property 'num_outputs'==2:\n");
    int temp = 2;
    pdev = mapper_database_devices_by_property(db, "num_outputs", 1, 'i', &temp,
                                               MAPPER_OP_EQUAL);

    count=0;
    if (!pdev) {
        eprintf("mapper_database_devices_by_property() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pdev) {
        eprintf("mapper_database_devices_by_property() returned something "
                "which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pdev) {
        count ++;
        printdevice(*pdev);
        pdev = mapper_device_query_next(pdev);
    }

    if (count != 1) {
        eprintf("Expected 1 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind devices with properties 'host'!='localhost' AND 'port'>=4000:\n");

    pdev = mapper_database_devices_by_property(db, "host", 1, 's', "localhost",
                                               MAPPER_OP_NOT_EQUAL);
    pdev2 = mapper_database_devices_by_property(db, "port", 1, 'i', &port,
                                                MAPPER_OP_GREATER_THAN_OR_EQUAL);
    pdev = mapper_device_query_intersection(pdev, pdev2);

    count=0;
    if (!pdev) {
        eprintf("mapper_database_devices_by_property() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pdev) {
        eprintf("mapper_database_devices_by_property() returned something "
                "which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pdev) {
        count ++;
        printdevice(*pdev);
        pdev = mapper_device_query_next(pdev);
    }

    if (count != 1) {
        eprintf("Expected 1 record, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\n--- Signals ---\n");

    eprintf("\nFind all signals for device 'testdatabase.1':\n");

    dev = mapper_database_device_by_name(db, "testdatabase.1");
    psig = mapper_device_signals(dev, MAPPER_DIR_ANY);

    count=0;
    if (!psig) {
        eprintf("mapper_device_signals() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*psig) {
        eprintf("mapper_device_signals() returned something "
                "which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (psig) {
        count ++;
        printsignal(*psig);
        psig = mapper_signal_query_next(psig);
    }

    if (count != 4) {
        eprintf("Expected 4 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind all signals for device 'testdatabase__xx.2':\n");

    dev = mapper_database_device_by_name(db, "testdatabase__xx.2");
    psig = mapper_device_signals(dev, MAPPER_DIR_ANY);

    count=0;
    if (psig) {
        eprintf("mapper_device_signals() incorrectly found something.\n");
        printsignal(*psig);
        mapper_signal_query_done(psig);
        result = 1;
        goto done;
    }
    else
        eprintf("  correctly returned 0.\n");

    /*********/

    eprintf("\nFind all outputs for device 'testdatabase__.2':\n");

    dev = mapper_database_device_by_name(db, "testdatabase__.2");
    psig = mapper_device_signals(dev, MAPPER_DIR_ANY);

    count=0;
    if (!psig) {
        eprintf("mapper_device_signals() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*psig) {
        eprintf("mapper_device_signals() returned something "
                "which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (psig) {
        count ++;
        printsignal(*psig);
        psig = mapper_signal_query_next(psig);
    }

    if (count != 3) {
        eprintf("Expected 3 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind signal matching 'in' for device 'testdatabase.1':\n");

    dev = mapper_database_device_by_name(db, "testdatabase.1");
    psig = mapper_device_signals(dev, MAPPER_DIR_ANY);
    psig2 = mapper_database_signals_by_name(db, "*in*");
    psig = mapper_signal_query_intersection(psig, psig2);

    count=0;
    if (!psig) {
        eprintf("intersection of mapper_device_signals() and "
                "mapper_database_signals_by_name() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*psig) {
        eprintf("intersection of mapper_device_signals() and "
                "mapper_database_signals_by_name() returned something "
                "which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (psig) {
        count ++;
        printsignal(*psig);
        psig = mapper_signal_query_next(psig);
    }

    if (count != 2) {
        eprintf("Expected 2 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind signal matching 'out' for device 'testdatabase.1':\n");

    dev = mapper_database_device_by_name(db, "testdatabase.1");
    psig = mapper_device_signals(dev, MAPPER_DIR_ANY);
    psig2 = mapper_database_signals_by_name(db, "*out*");
    psig = mapper_signal_query_intersection(psig, psig2);

    count=0;
    if (!psig) {
        eprintf("intersection of mapper_device_signals() and "
                "mapper_database_signals_by_name() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*psig) {
        eprintf("intersection of mapper_device_signals() and "
                "mapper_database_signals_by_name() returned something "
                "which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (psig) {
        count ++;
        printsignal(*psig);
        psig = mapper_signal_query_next(psig);
    }

    if (count != 2) {
        eprintf("Expected 2 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind signal matching 'out' for device 'testdatabase__.2':\n");

    dev = mapper_database_device_by_name(db, "testdatabase__.2");
    psig = mapper_device_signals(dev, MAPPER_DIR_ANY);
    psig2 = mapper_database_signals_by_name(db, "*out*");
    psig = mapper_signal_query_intersection(psig, psig2);

    count=0;
    if (!psig) {
        eprintf("intersection of mapper_device_signals() and "
                "mapper_database_signals_by_name() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*psig) {
        eprintf("intersection of mapper_device_signals() and "
                "mapper_database_signals_by_name() returned something "
                "which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (psig) {
        count ++;
        printsignal(*psig);
        psig = mapper_signal_query_next(psig);
    }

    if (count != 1) {
        eprintf("Expected 1 record, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\n--- maps ---\n");

    eprintf("\nFind maps with source 'out1':\n");

    psig = mapper_database_signals_by_name(db, "out1");
    pmap = 0;
    while (psig) {
        pmap2 = mapper_signal_maps(*psig, MAPPER_DIR_OUTGOING);
        pmap = mapper_map_query_union(pmap, pmap2);
        psig = mapper_signal_query_next(psig);
    }

    count=0;
    if (!pmap) {
        eprintf("combined query returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pmap) {
        eprintf("combined query returned something which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pmap) {
        count ++;
        printmap(*pmap);
        pmap = mapper_map_query_next(pmap);
    }

    if (count != 3) {
        eprintf("Expected 3 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind maps for device 'testdatabase.1', source 'out1':\n");

    dev = mapper_database_device_by_name(db, "testdatabase.1");
    sig = mapper_device_signal_by_name(dev, "out1");
    pmap = mapper_signal_maps(sig, 0);

    count=0;
    if (!pmap) {
        eprintf("mapper_signal_maps() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pmap) {
        eprintf("mapper_signal_maps() returned something which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pmap) {
        count ++;
        printmap(*pmap);
        pmap = mapper_map_query_next(pmap);
    }

    if (count != 2) {
        eprintf("Expected 2 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind maps with destination signal named 'in2':\n");

    psig = mapper_database_signals_by_name(db, "in2");
    pmap = 0;
    while (psig) {
        pmap2 = mapper_signal_maps(*psig, MAPPER_DIR_INCOMING);
        pmap = mapper_map_query_union(pmap, pmap2);
        psig = mapper_signal_query_next(psig);
    }

    count=0;
    if (!pmap) {
        eprintf("combined query returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pmap) {
        eprintf("combined query returned something which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pmap) {
        count ++;
        printmap(*pmap);
        pmap = mapper_map_query_next(pmap);
    }

    if (count != 1) {
        eprintf("Expected 1 record, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind maps for device 'testdatabase__.2', destination 'in1':\n");

    dev = mapper_database_device_by_name(db, "testdatabase__.2");
    sig = mapper_device_signal_by_name(dev, "in1");
    pmap = mapper_signal_maps(sig, MAPPER_DIR_INCOMING);

    count=0;
    if (!pmap) {
        eprintf("mapper_signal_maps() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pmap) {
        eprintf("mapper_signal_maps() returned something which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pmap) {
        count ++;
        printmap(*pmap);
        pmap = mapper_map_query_next(pmap);
    }

    if (count != 2) {
        eprintf("Expected 2 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind maps for source device 'testdatabase__.2', signal 'out1'"
            "\n          AND dest device 'testdatabase.1', signal 'in1':\n");

    // get maps with source signal
    dev = mapper_database_device_by_name(db, "testdatabase__.2");
    sig = mapper_device_signal_by_name(dev, "out1");
    pmap = mapper_signal_maps(sig, MAPPER_DIR_OUTGOING);

    // get maps with destination signal
    dev = mapper_database_device_by_name(db, "testdatabase.1");
    sig = mapper_device_signal_by_name(dev, "in1");
    pmap2 = mapper_signal_maps(sig, MAPPER_DIR_INCOMING);

    // intersect map queries
    pmap = mapper_map_query_intersection(pmap, pmap2);

    count=0;
    if (!pmap) {
        eprintf("combined query returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pmap) {
        eprintf("combined query returned something which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pmap) {
        count ++;
        printmap(*pmap);
        pmap = mapper_map_query_next(pmap);
    }

    if (count != 1) {
        eprintf("Expected 1 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind maps for source device 'testdatabase__.2', signals matching 'out',"
            "\n          AND dest device 'testdatabase.1', all signals:\n");

    // build source query
    dev = mapper_database_device_by_name(db, "testdatabase__.2");
    psig = mapper_device_signals(dev, MAPPER_DIR_ANY);
    psig2 = mapper_database_signals_by_name(db, "*out*");
    psig = mapper_signal_query_intersection(psig, psig2);

    pmap = 0;
    while (psig) {
        pmap2 = mapper_signal_maps(*psig, MAPPER_DIR_OUTGOING);
        pmap = mapper_map_query_union(pmap, pmap2);
        psig = mapper_signal_query_next(psig);
    }

    // build destination query
    dev = mapper_database_device_by_name(db, "testdatabase.1");
    pmap2 = mapper_device_maps(dev, MAPPER_DIR_ANY);

    // intersect queries
    pmap = mapper_map_query_intersection(pmap, pmap2);

    count=0;
    if (!pmap) {
        eprintf("combined query returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pmap) {
        eprintf("combined query returned something which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pmap) {
        count ++;
        printmap(*pmap);
        pmap = mapper_map_query_next(pmap);
    }

    if (count != 1) {
        eprintf("Expected 1 record, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/
done:
    mapper_network_free(net);
    if (!verbose)
        printf("..................................................");
    printf("Test %s.\n", result ? "FAILED" : "PASSED");
    return result;
}
//================================================================
void print_info()
{
	uint64_t can_read_count=jack_ringbuffer_read_space(rb);

	char* offset_string;
	if(channel_offset>0)
	{
		asprintf(&offset_string, "(%d+)", (channel_offset));
	}
	else
	{
		offset_string="";
	}

	//this is per channel, not per cycle. *port_count
	if(relaxed_display_counter>=update_display_every_nth_cycle*port_count
		|| last_test_cycle==1
	)
	{

		if(shutup==0 && quiet==0)
		{
			fprintf(stderr,"\r# %" PRId64 " i: %s%d f: %.1f b: %" PRId64 " s: %.4f i: %.2f r: %" PRId64 
				" l: %" PRId64 " d: %" PRId64 " o: %" PRId64 " p: %.1f%s",
				message_number,
				offset_string,
				input_port_count,
				(float)can_read_count/(float)bytes_per_sample/(float)period_size/(float)port_count,
				can_read_count,
				(float)can_read_count/(float)port_count/(float)bytes_per_sample/(float)sample_rate,
				time_interval_avg*1000,
				remote_xrun_counter,
				local_xrun_counter,
				multi_channel_drop_counter,
				buffer_overflow_counter,
				(float)frames_since_cycle_start_avg/(float)period_size,
				"\033[0J"
			);
		}

		if(io_())
		{

			lo_message msgio=lo_message_new();

			lo_message_add_int64(msgio,message_number);
			lo_message_add_int32(msgio,input_port_count);
			lo_message_add_int32(msgio,channel_offset);

			lo_message_add_float(msgio,
				(float)can_read_count/(float)bytes_per_sample/(float)period_size/(float)port_count
			);

			lo_message_add_int64(msgio,can_read_count);

			lo_message_add_float(msgio,
				(float)can_read_count/(float)port_count/(float)bytes_per_sample/(float)sample_rate
			);

			lo_message_add_float(msgio,time_interval_avg*1000);
			lo_message_add_int64(msgio,remote_xrun_counter);
			lo_message_add_int64(msgio,local_xrun_counter);
			lo_message_add_int64(msgio,multi_channel_drop_counter);
			lo_message_add_int64(msgio,buffer_overflow_counter);

			lo_message_add_float(msgio,
				(float)frames_since_cycle_start_avg/(float)period_size
			);

			lo_send_message(loio, "/status", msgio);
			lo_message_free(msgio);
		}

		fflush(stderr);

		relaxed_display_counter=0;
	}
	relaxed_display_counter++;
}//end print_info
Beispiel #23
0
int main()
{
    //clean buffer
    memset(buffer1, 0xc3, sizeof(buffer1));

    //generate liblo message 1
    size_t len = 128;
    lo_message message = lo_message_new();
    assert_non_null(message, "Generating A Liblo Message 1 (int/float)", __LINE__);
    lo_message_add_float(message, 24.0);
    lo_message_add_int32(message, 42);
    lo_message_serialise(message, "/path", buffer1, &len);

    assert_str_eq("/path", buffer1, "Verifying Path From Message 1", __LINE__);
    assert_f32_eq(24.0f, rtosc_argument(buffer1, 0).f,
            "Verifying Float From Message 1", __LINE__);
    assert_int_eq(42, rtosc_argument(buffer1, 1).i,
            "Verifying Int From Message 1", __LINE__);
    assert_int_eq(20, rtosc_message_length(buffer1, 128),
            "Verifying Length From Message 1", __LINE__);


    //Message 2
    size_t len2 = rtosc_message(buffer2, 1024, "/li", "bb", 4, buffer1, 4, buffer1);
    assert_int_eq(24, len2, "Generate A Rtosc Message 2 (bb)", __LINE__);
    lo_message msg2 = lo_message_deserialise((void*)buffer2, len2, &result_var);
    if(assert_non_null(msg2, "Deserialize Message 2 To Liblo", __LINE__))
        printf("# Liblo Did Not Accept the Rtosc Message [error '%d']\n", result_var);

    //Message 3
    size_t len3 = rtosc_message(buffer3+4, 2048, "/close-ui", "");
    assert_int_eq(16, len3, "Generate A Rtosc Message 3 ()", __LINE__);
    lo_message msg3 = lo_message_deserialise((void*)(buffer3+4), len3, &result_var);
    if(assert_non_null(msg2, "Deserialize Message 3 To Liblo", __LINE__))
        printf("#Liblo Did Not Accept the Rtosc Message [error '%d']\n", result_var);

    //Bundle 4
    size_t len4 = rtosc_bundle(buffer4, 2048, 0xdeadbeefcafebaad, 3, buffer1, buffer2, buffer3+4);
    assert_int_eq(88, len4, "Generate A Bundle 4", __LINE__);

    //Bundle 5
    lo_timetag time;
    time.sec  = 0xdeadbeef;
    time.frac = 0xcafebaad;
    lo_bundle ms4 = lo_bundle_new(time);
    lo_bundle_add_message(ms4, "/path",     message);
    lo_bundle_add_message(ms4, "/li",       msg2);
    lo_bundle_add_message(ms4, "/close-ui", msg3);
    size_t len5 = 2048;
    lo_bundle_serialise(ms4,(void*)buffer5, &len5);

    //Verify 4 == 5
    assert_non_null(ms4, "Generate A Liblo Bundle 5", __LINE__);
    assert_hex_eq(buffer5, buffer4, len5, len4,
            "Verify Liblo Style Bundles", __LINE__);

    //Cleanup
    lo_message_free(message);
    lo_message_free(msg2);
    lo_message_free(msg3);
    lo_bundle_free(ms4);

    return test_summary();
}
int osc_controller::_param_cb(const char* path, const char* types,
                              lo_arg** argv, int argc, lo_message msg)
{
    if (argc < 4)
        return 0;

    if (!m_restricted || is_target(lo_message_get_source(msg))) {
	pair<int,int> net_id(argv[0]->i, argv[1]->i);

	map<pair<int,int>, int>::iterator it = m_local_id.find(net_id);
	world_node obj;

	if (it != m_local_id.end() &&
	    !(obj = m_world->find_node(it->second)).is_null()) {



	    m_skip++;
            int param_type = 0;

            // TODO: CLEAN this shit!
            switch (types[2])
            {
            case 'i':
            {
                int param_id = argv[2]->i;
                switch(param_type = obj.get_param_type(param_id)) {
                case graph::node_param::FLOAT:
                    m_world->set_param_node(obj, param_id, argv[3]->f);
                    break;
                case graph::node_param::INT:
                    m_world->set_param_node(obj, param_id, argv[3]->i);
                    break;
                case graph::node_param::STRING:
                    m_world->set_param_node(obj, param_id, string(&argv[3]->s));
                    break;
                case graph::node_param::VECTOR2F:
                    if (argc < 5)
                        return 0;
                    m_world->set_param_node(
                        obj, param_id, base::vector_2f(argv[3]->f, argv[4]->f));
                    break;
                default:
                    return 0;
                }
                break;
            }

            case 's':
            {
                std::string param_id = &argv[2]->s;
                switch(param_type = obj.get_param_type(param_id)) {
                case graph::node_param::FLOAT:
                    m_world->set_param_node(obj, param_id, argv[3]->f);
                    break;
                case graph::node_param::INT:
                    m_world->set_param_node(obj, param_id, argv[3]->i);
                    break;
                case graph::node_param::STRING:
                    m_world->set_param_node(obj, param_id, string(&argv[3]->s));
                    break;
                case graph::node_param::VECTOR2F:
                    if (argc < 5)
                        return 0;
                    m_world->set_param_node(
                        obj, param_id, base::vector_2f(argv[3]->f, argv[4]->f));
                    break;
                default:
                    return 0;
                }
                break;
            }

            default:
                return 0;
            }


	    m_skip--;

	    if (m_broadcast) {
		lo_message newmsg = lo_message_new();
		lo_message_add_int32(newmsg, argv[0]->i);
		lo_message_add_int32(newmsg, argv[1]->i);
		lo_message_add_int32(newmsg, argv[2]->i);

		switch(param_type) {
		case graph::node_param::FLOAT:
		    lo_message_add_float(newmsg, argv[3]->f);
		    break;
		case graph::node_param::INT:
		    lo_message_add_int32(newmsg, argv[3]->i);
		    break;
		case graph::node_param::STRING:
		    lo_message_add_string(newmsg, &argv[3]->s);
		    break;
		case graph::node_param::VECTOR2F:
		    lo_message_add_float(newmsg, argv[3]->f);
		    lo_message_add_float(newmsg, argv[4]->f);
		    break;
		default:
		    break;
		}

		broadcast_message_from(PSYNTH_OSC_MSG_PARAM, newmsg, lo_message_get_source(msg));
		lo_message_free(newmsg);
	    }
	}
    }

    return 0;
}