コード例 #1
0
std::string NonBlockOSCServer::getContent(const char* path, const char* types, lo_arg** argv, int argc, lo_address addr )
{
    std::ostringstream contents;

    contents << "[NonBlockOSCServer::"<< path << "]   ";
    for( int i = 0; i < argc; ++i )
    {
        contents << types[ i ] << "=";
        switch( types[ i ] )
        {
            case 's':
                contents << &argv[ i ]->s;
                break;
            case 'f':
                contents << argv[ i ]->f;
                break;
            case 'i':
                contents << argv[ i ]->i;
        }
        contents << "   ";
    }
    if ( addr != NULL ){
      contents << "from: ";
      contents << lo_address_get_url( addr);
//       contents << ":";
//       contents << lo_address_get_port( addr );
    }
    return contents.str();
}
コード例 #2
0
ファイル: osc.c プロジェクト: cmeon/xwax-1.5-osc
int osc_send_status(lo_address a, int d)
{
    struct deck *de;
    struct player *pl;
    struct track *tr;
    de = &osc_deck[d];
    pl = &de->player;
    tr = pl->track;
    
    char *path;
    if(tr->path)
        path = tr->path;
    else
        path = "";
    
    if(tr) {
        /* send a message to /xwax/status */
        if (lo_send(a, "/xwax/status", "isssfffi",
                de->ncontrol,           // deck number (int)
                path,               // track path (string)
                de->record->artist,     // artist name (string)
                de->record->title,      // track title (string)
                (float) tr->length / (float) tr->rate,  // track length in seconds (float)
                player_get_elapsed(pl),           // player position in seconds (float)
                pl->pitch,              // player pitch (float)
                pl->timecode_control)    // timecode activated or not (int)
            == -1) {
            printf("OSC error %d: %s\n", lo_address_errno(a),
                   lo_address_errstr(a));
        }
        printf("osc_send_status: sent deck %i status to %s\n", d, lo_address_get_url(a));            
    }
    
    return 0;    
}
コード例 #3
0
ファイル: osc.c プロジェクト: cmeon/xwax-1.5-osc
int osc_send_track_load(struct deck *de)
{
    struct player *pl;
    struct track *tr;
    pl = &de->player;
    tr = pl->track;
    
    if(tr) {
        /* send a message to /xwax/track_load with two arguments, report any
         * errors */
        int c;
        for(c = 0; c < osc_nclient%3; ++c) { 
            if (lo_send(address[c], "/xwax/track_load", "iissi",
                    de->ncontrol,
                    (int) tr,
                    de->record->artist, 
                    de->record->title,
                    tr->rate
                ) == -1) {
                printf("OSC error %d: %s\n", lo_address_errno(address[c]),
                       lo_address_errstr(address[c]));
            }
            printf("osc_send_track_load: sent track_load to %s\n", lo_address_get_url(address[c]));
            sleep(1); // Wierd bug in liblo that makes second track load not catched by client's track_load_handler if sent too fast
            
        }
    }
    
    return 0;
}
コード例 #4
0
ファイル: testlo.c プロジェクト: LibreGames/diggr-roguelike
int reply_handler(const char *path, const char *types, lo_arg **argv, int argc,
		 lo_message data, void *user_data)
{
    lo_address src = lo_message_get_source(data);
    char *url = lo_address_get_url(src);
    printf("Reply received from %s\n", url);
    free(url);
    reply_count++;

    return 0;
}
コード例 #5
0
ファイル: nsm-proxy.C プロジェクト: imv/non
int
osc_update ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
{
    lo_address to = lo_address_new_from_url( lo_address_get_url( lo_message_get_source( msg ) ));

    nsm_proxy->update( to );

    gui_addr = to;

    return 0;
}
コード例 #6
0
ファイル: subtest.c プロジェクト: AdbC99/OSCeleton
int subtest_handler(const char *path, const char *types, lo_arg **argv,
                    int argc, lo_message data, void *user_data)
{
    int i;
    lo_address a = lo_message_get_source(data);
    static char *uri = NULL;

    printf("subtest: got reply (%s)\n", path);
    if (!uri) {
	uri = lo_address_get_url(a);
    } else {
	char *new_uri = lo_address_get_url(a);

	if (strcmp(uri, new_uri)) {
	    printf("ERROR: %s != %s\n", uri, new_uri);

	    exit(1);
	}
	free(new_uri);
    }
    lo_send(a, "/subtest-reply", "i", 0xbaa);
    if (lo_address_errno(a)) {
	fprintf(stderr, "subtest error %d: %s\n", lo_address_errno(a),
		lo_address_errstr(a));

	exit(1);
    }

    for (i=0; i<10; i++) {
#ifdef WIN32
        /* TODO: Wait time of 2.233 not easily doable in Windows */
        Sleep(2);
#else
        usleep(2233);
#endif
	lo_send(a, "/subtest-reply", "i", 0xbaa+i);
    }

    return 0;
}
コード例 #7
0
ファイル: nsm-proxy.C プロジェクト: imv/non
int
osc_announce_reply ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
{
    if ( strcmp( "/nsm/server/announce", &argv[0]->s ) )
         return -1;

    printf( "Successfully registered. NSM says: %s", &argv[1]->s );
    
    nsm_is_active = 1;
    nsm_addr = lo_address_new_from_url( lo_address_get_url( lo_message_get_source( msg ) ) );
    
    return 0;
}
コード例 #8
0
ファイル: testlo.c プロジェクト: LibreGames/diggr-roguelike
int foo_handler(const char *path, const char *types, lo_arg **argv, int argc,
		 lo_message data, void *user_data)
{
    lo_server serv = (lo_server)user_data;
    lo_address src = lo_message_get_source(data);
    char *url = lo_address_get_url(src);
    char *server_url = lo_server_get_url(serv);
    printf("Address of us: %s\n", server_url);
    printf("%s <- f:%f, i:%d\n", path, argv[0]->f, argv[1]->i);
    if (lo_send_from(src, serv, LO_TT_IMMEDIATE, "/reply", "s", "a reply") == -1) {
	printf("OSC reply error %d: %s\nSending to %s\n", lo_address_errno(src), lo_address_errstr(src), url);
	exit(1);
    } else {
	printf("Reply sent to %s\n\n", url);
    }
    free(server_url);
    free(url);

    return 0;
}
コード例 #9
0
ファイル: mjosc.c プロジェクト: egasimus/madjack
static
int ping_handler(const char *path, const char *types, lo_arg **argv, int argc,
		 lo_message msg, void *user_data)
{
	lo_address src = lo_message_get_source( msg );
	lo_server serv = (lo_server)user_data;
	int result;
	
	// Display the address the ping came from
	if (verbose) {
		char *url = lo_address_get_url(src);
		printf( "Got ping from: %s\n", url);
		free(url);
	}

	// Send back reply
	result = lo_send_from( src, serv, LO_TT_IMMEDIATE, "/pong", "" );
	if (result<1) fprintf(stderr, "Error: sending reply failed: %s\n", lo_address_errstr(src));

    return 0;
}
コード例 #10
0
ファイル: port-checker.cpp プロジェクト: fundamental/rtosc
void port_checker::server::init(const char* target_url)
{
    target = lo_address_new_from_url(target_url);
    if(!target || !lo_address_get_url(target) ||
       !lo_address_get_port(target) ||
        lo_address_get_protocol(target) != LO_UDP)
        throw std::runtime_error("invalid address");

    srv = lo_server_new_with_proto(nullptr, LO_UDP, liblo_error_cb);
    if(srv == nullptr)
        throw std::runtime_error("Could not create lo server");
    lo_server_add_method(srv, nullptr, nullptr, handle_st, this);

    rtosc_arg_val_t hi[2];
    hi[0].type = hi[1].type = 's';
    hi[0].val.s = hi[1].val.s = "";
    send_msg("/path-search", 2, hi);
    std::vector<rtosc_arg_val_t> reply;
    std::vector<char> buf;
    wait_for_reply(&buf, &reply, "/paths");
}
コード例 #11
0
ファイル: osc.c プロジェクト: cmeon/xwax-1.5-osc
int osc_send_ppm_block(struct track *tr)
{
    if(tr) {
        int c;
        for(c = 0; c < osc_nclient%3; ++c) {
            int i = 0;
            while(i < tr->length) {
                int j = 0;
                unsigned char ppm_block[24575];
                
                while(j < 24575 && i < tr->length) {
                    ppm_block[j] = track_get_ppm(tr, i);
                    ++j;
                    i += 64;
                }
                
                /* build a blob object from some data */
                lo_blob blob = lo_blob_new(j, &ppm_block);

                //lo_server server = lo_server_thread_get_server(st_tcp);
                if (lo_send(address[c], "/xwax/ppm", "ibi", 
                    (int) tr, 
                    blob,
                    tr->length
                ) == -1) {
                    printf("OSC error %d: %s\n", lo_address_errno(address[c]),
                        lo_address_errstr(address[c]));
                }
                lo_blob_free(blob);
            }
            lo_send(address[c], "/xwax/ppm_end", "i", (int) tr);
            
            printf("Sent %p blocks to %s\n", tr, lo_address_get_url(address[c]));
            sleep(1); // Wierd bug in liblo that makes second track load not catched by client's track_load_handler if sent too fast
        }

    }
    return 0;
}
コード例 #12
0
ファイル: osc.c プロジェクト: cmeon/xwax-1.5-osc
int get_status_handler(const char *path, const char *types, lo_arg ** argv,
                int argc, void *data, void *user_data)
{
    /* example showing pulling the argument values out of the argv array */
    printf("%s <- deck:%i\n", path, argv[0]->i);
    fflush(stdout);
    
    int d = argv[0]->i;
    
    lo_address a = lo_message_get_source(data);
    
    char* url = lo_address_get_url(a);
    
    printf("%s\n", url);
    
    //url[strlen(url)-2] = 1;
    
    //printf("%s\n", url);
    
    osc_send_status(a, d);
    
}
コード例 #13
0
ファイル: InterfaceSim.cpp プロジェクト: EQ4/dimple
void InterfaceSim::on_add_receiver(const char *type)
{
    SimulationType t = str_type(type);
    if (t == ST_UNKNOWN) return;

    lo_address a = lo_message_get_source(m_msg);
    if (!a) return;

    char *url = lo_address_get_url(a);
    if (!url) return;

    // Physics can change object positions in any of the other
    // simulations
    if (t & ST_HAPTICS || t & ST_VISUAL)
        sendtotype(ST_PHYSICS, 0, "/world/add_receiver_url",
                   "ss", type, url);

    // Haptics can add force to objects in the physics simulation.
    if (t & ST_PHYSICS || t & ST_VISUAL)
        sendtotype(ST_HAPTICS, 0, "/world/add_receiver_url",
                   "ss", type, url);

    // Visual can send a message to haptics due to keyboard
    // shortcuts. (e.g. reset_workspace.)
    if (t & ST_HAPTICS)
        sendtotype(ST_VISUAL, 0, "/world/add_receiver_url",
                   "ss", type, url);

    // Interface can modify anything in any other simulation.
    add_receiver(0, url, t, false);

#ifdef DEBUG
    printf("[%s] add_receiver(): %s, source = %s\n", type_str(), type, url);
#endif
    free(url);
}
コード例 #14
0
ファイル: Client.C プロジェクト: grejppi/zynaddsubfx
    int
    Client::osc_announce_reply(const char *path,
                               const char *types,
                               lo_arg **argv,
                               int argc,
                               lo_message msg,
                               void *user_data)
    {
        if(strcmp(&argv[0]->s, "/nsm/server/announce"))
            return -1;

        NSM::Client *nsm = (NSM::Client *)user_data;

//        MESSAGE( "Successfully registered. NSM says: %s", &argv[1]->s );
        nsm->nsm_is_active = true;
        nsm->_session_manager_name = strdup(&argv[2]->s);
        nsm->nsm_addr =
            lo_address_new_from_url(lo_address_get_url(lo_message_get_source(
                                                           msg)));

        nsm->command_active(nsm->nsm_is_active);

        return 0;
    }
コード例 #15
0
ファイル: osc.c プロジェクト: cmeon/xwax-1.5-osc
int connect_handler(const char *path, const char *types, lo_arg ** argv,
                int argc, void *data, void *user_data)
{
    /* example showing pulling the argument values out of the argv array */
    printf("%s\n", path);
    fflush(stdout);
    
    lo_address a = lo_message_get_source(data);
    
    if(strcmp(lo_address_get_url(address[0]), lo_address_get_url(a)) == 0 || 
        strcmp(lo_address_get_url(address[1]), lo_address_get_url(a)) == 0) {
        // already stored as a client
    } else {
        address[osc_nconnection%2] = lo_address_new_from_url(lo_address_get_url(a));
        printf("OSC client %i address changed to:%s\n", osc_nconnection%2, lo_address_get_url(address[osc_nconnection%2]));
        
        
        ++osc_nconnection;
        if(osc_nclient < 2)
            ++osc_nclient;
    }

    struct deck *de;
    struct player *pl;

    fprintf(stderr, "osc_nclient %i osc_ndeck: %i\n", osc_nclient, osc_ndeck);
    int d;
    for(d = 0; d < osc_ndeck; ++d) {
        de = &osc_deck[d];
        pl = &de->player;
        osc_send_track_load(de);
        osc_send_ppm_block(pl->track);
    }
        
    
    return 0;
}
コード例 #16
0
char	*osc_get_uri(void *data)
{
	lo_address a = lo_message_get_source(data);
	char *uri = lo_address_get_url(a);
	return uri;
}
コード例 #17
0
ファイル: client.c プロジェクト: elcerdo/avr
int all_callback(const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data) {
	printf("got %s from %s\n",path,lo_address_get_url(lo_message_get_source(msg)));
	return 1;
}
コード例 #18
0
ファイル: testlo.c プロジェクト: LibreGames/diggr-roguelike
int main()
{
    lo_blob btest = lo_blob_new(sizeof(testdata), testdata);
    lo_server_thread st, sta, stb;
    lo_server s = lo_server_new(NULL, error);
    lo_bundle b;
    lo_message m1, m2;
    char *server_url, *path, *protocol, *host, *port;
    const char *host2, *port2;
    lo_address a;
    uint8_t midi_data[4] = {0xff, 0xf7, 0xAA, 0x00};
    union end_test32 et32;
    union end_test64 et64;
    lo_timetag tt = {0x1, 0x80000000}, sched;
    int count;
    int proto;
    char cmd[256];

    test_deserialise();

    sta = lo_server_thread_new("7591", error);
    stb = lo_server_thread_new("7591", rep_error);
    if (stb) {
	fprintf(stderr, "FAILED: create bad server thread object!\n");
	exit(1);
    }
    lo_server_thread_free(sta);

    /* leak check */
    st = lo_server_thread_new(NULL, error);
    lo_server_thread_start(st);
#ifdef WIN32
    Sleep(4);
#else
    usleep(4000);
#endif
    lo_server_thread_stop(st);
    lo_server_thread_free(st);
    st = lo_server_thread_new(NULL, error);
    lo_server_thread_start(st);
    lo_server_thread_stop(st);
    lo_server_thread_free(st);
    st = lo_server_thread_new(NULL, error);
    lo_server_thread_free(st);
    st = lo_server_thread_new(NULL, error);
    lo_server_thread_free(st);
    st = lo_server_thread_new(NULL, error);

    a = lo_address_new_from_url("osc://localhost/");
    TEST(a != NULL);
    lo_address_free(a);

    a = lo_address_new_from_url("osc.://localhost/");
    TEST(a == NULL);


    atexit(exitcheck);

    printf("type tests\n");
    TEST(sizeof(float) == sizeof(int32_t));
    TEST(sizeof(double) == sizeof(int64_t));

    et32.i = 0x23242526U;
    et32.i = lo_htoo32(et32.i);
    if (et32.c[0] != 0x23 || et32.c[1] != 0x24 || et32.c[2] != 0x25 ||
	et32.c[3] != 0x26) {
	fprintf(stderr, "failed 32bit endian conversion test\n");
	fprintf(stderr, "0x23242526 -> %X\n", et32.i);
	exit(1);
    } else {
	printf("passed 32bit endian conversion test\n");
    }

    et64.i = 0x232425262728292AULL;
    et64.i = lo_htoo64(et64.i);
    if (et64.c[0] != 0x23 || et64.c[1] != 0x24 || et64.c[2] != 0x25 ||
	et64.c[3] != 0x26 || et64.c[4] != 0x27 || et64.c[5] != 0x28 ||
	et64.c[6] != 0x29 || et64.c[7] != 0x2A) {
	fprintf(stderr, "failed 64bit endian conversion\n");
	fprintf(stderr, "0x232425262728292A -> %llX\n", (long long unsigned int)et64.i);
	exit(1);
    } else {
	printf("passed 64bit endian conversion\n");
    }
    printf("\n");

    /* OSC URL tests */
    path = lo_url_get_path("osc.udp://localhost:9999/a/path/is/here");
    if (strcmp(path, "/a/path/is/here")) {
	printf("failed lo_url_get_path() test1\n");
	printf("'%s' != '/a/path/is/here'\n", path);
	exit(1);
    } else {
	printf("passed lo_url_get_path() test1\n");
    }
    free(path);

    protocol = lo_url_get_protocol("osc.udp://localhost:9999/a/path/is/here");
    if (strcmp(protocol, "udp")) {
	printf("failed lo_url_get_protocol() test1\n");
	printf("'%s' != 'udp'\n", protocol);
	exit(1);
    } else {
	printf("passed lo_url_get_protocol() test1\n");
    }
    free(protocol);

    protocol = lo_url_get_protocol("osc.tcp://localhost:9999/a/path/is/here");
    if (strcmp(protocol, "tcp")) {
	printf("failed lo_url_get_protocol() test2\n");
	printf("'%s' != 'tcp'\n", protocol);
	exit(1);
    } else {
	printf("passed lo_url_get_protocol() test2\n");
    }
    free(protocol);
    
    protocol = lo_url_get_protocol("osc.udp://[::ffff:localhost]:9999/a/path/is/here");
    if (strcmp(protocol, "udp")) {
	printf("failed lo_url_get_protocol() test1 (IPv6)\n");
	printf("'%s' != 'udp'\n", protocol);
	exit(1);
    } else {
	printf("passed lo_url_get_protocol() test1 (IPv6)\n");
    }
    free(protocol);

    proto = lo_url_get_protocol_id("osc.udp://localhost:9999/a/path/is/here");
    if (proto != LO_UDP) {
	printf("failed lo_url_get_protocol_id() test1\n");
	printf("'%d' != LO_UDP\n", proto);
	exit(1);
    } else {
	printf("passed lo_url_get_protocol_id() test1\n");
    }

    proto = lo_url_get_protocol_id("osc.tcp://localhost:9999/a/path/is/here");
    if (proto != LO_TCP) {
	printf("failed lo_url_get_protocol_id() test2\n");
	printf("'%d' != LO_TCP\n", proto);
	exit(1);
    } else {
	printf("passed lo_url_get_protocol_id() test2\n");
    }
    
    proto = lo_url_get_protocol_id("osc.invalid://localhost:9999/a/path/is/here");
    if (proto != -1) {
	printf("failed lo_url_get_protocol_id() test3\n");
	printf("'%d' != -1\n", proto);
	exit(1);
    } else {
	printf("passed lo_url_get_protocol_id() test3\n");
    }
    
    proto = lo_url_get_protocol_id("osc.udp://[::ffff:localhost]:9999/a/path/is/here");
    if (proto != LO_UDP) {
	printf("failed lo_url_get_protocol_id() test1 (IPv6)\n");
	printf("'%d' != LO_UDP\n", proto);
	exit(1);
    } else {
	printf("passed lo_url_get_protocol_id() test1 (IPv6)\n");
    }

    host = lo_url_get_hostname("osc.udp://foo.example.com:9999/a/path/is/here");
    if (strcmp(host, "foo.example.com")) {
	printf("failed lo_url_get_hostname() test1\n");
	printf("'%s' != 'foo.example.com'\n", host);
	exit(1);
    } else {
	printf("passed lo_url_get_hostname() test1\n");
    }
    free(host);

    host = lo_url_get_hostname("osc.udp://[0000::::0001]:9999/a/path/is/here");
    if (strcmp(host, "0000::::0001")) {
	printf("failed lo_url_get_hostname() test2 (IPv6)\n");
	printf("'%s' != '0000::::0001'\n", host);
	exit(1);
    } else {
	printf("passed lo_url_get_hostname() test2 (IPv6)\n");
    }
    free(host);

    port = lo_url_get_port("osc.udp://localhost:9999/a/path/is/here");
    if (strcmp(port, "9999")) {
	printf("failed lo_url_get_port() test1\n");
	printf("'%s' != '9999'\n", port);
	exit(1);
    } else {
	printf("passed lo_url_get_port() test1\n");
    }
    free(port);
    
    port = lo_url_get_port("osc.udp://[::ffff:127.0.0.1]:9999/a/path/is/here");
    if (strcmp(port, "9999")) {
	printf("failed lo_url_get_port() test1 (IPv6)\n");
	printf("'%s' != '9999'\n", port);
	exit(1);
    } else {
	printf("passed lo_url_get_port() test1 (IPv6)\n");
    }
    free(port);
    printf("\n");
    
    
    
    
    
    a = lo_address_new_from_url("osc.tcp://foo.example.com:9999/");
    host2 = lo_address_get_hostname(a);
    if (strcmp(host2, "foo.example.com")) {
	printf("failed lo_address_get_hostname() test\n");
	printf("'%s' != 'foo.example.com'\n", host2);
	exit(1);
    } else {
	printf("passed lo_address_get_hostname() test\n");
    }

    port2 = lo_address_get_port(a);
    if (strcmp(port2, "9999")) {
	printf("failed lo_address_get_port() test\n");
	printf("'%s' != '9999'\n", port2);
	exit(1);
    } else {
	printf("passed lo_address_get_port() test\n");
    }

    proto = lo_address_get_protocol(a);
    if (proto != LO_TCP) {
	printf("failed lo_address_get_protocol() test\n");
	printf("'%d' != '%d'\n", proto, LO_TCP);
	exit(1);
    } else {
	printf("passed lo_address_get_protocol() test\n");
    }

    server_url = lo_address_get_url(a);
    if (strcmp(server_url, "osc.tcp://foo.example.com:9999/")) {
	printf("failed lo_address_get_url() test\n");
	printf("'%s' != '%s'\n", server_url, "osc.tcp://foo.example.com:9999/");
	exit(1);
    } else {
	printf("passed lo_address_get_url() test\n");
    }
    free(server_url);
    lo_address_free( a );
    printf("\n");
    

    /* Test blod sizes */
    if (lo_blob_datasize(btest) != 5 || lo_blobsize(btest) != 12) {
	printf("blob is %d (%d) bytes long, should be 5 (12)\n",
               lo_blob_datasize(btest), lo_blobsize(btest));
	lo_arg_pp(LO_BLOB, btest);
	printf(" <- blob\n");
	exit(1);
    }
    
    
    
    /* Server method handler tests */
    server_url = lo_server_thread_get_url(st);
    a = lo_address_new_from_url(server_url);
    printf("Server URL: %s\n", server_url);
    free(server_url);

    /* add method that will match the path /foo/bar, with two numbers, coerced
     * to float and int */

    lo_server_thread_add_method(st, "/foo/bar", "fi", foo_handler, lo_server_thread_get_server(st));

    lo_server_thread_add_method(st, "/reply", "s", reply_handler, NULL);

    lo_server_thread_add_method(st, "/lotsofformats", "fisbmhtdSccTFNI",
				lots_handler, NULL);

    lo_server_thread_add_method(st, "/coerce", "dfhiSs",
				coerce_handler, NULL);

    lo_server_thread_add_method(st, "/bundle", NULL,
				bundle_handler, NULL);
    lo_server_thread_add_method(st, "/timestamp", NULL,
				timestamp_handler, NULL);
    lo_server_thread_add_method(st, "/jitter", "ti",
				jitter_handler, NULL);

    lo_server_thread_add_method(st, "/pattern/foo", NULL,
				pattern_handler, "foo");
    lo_server_thread_add_method(st, "/pattern/bar", NULL,
				pattern_handler, "bar");
    lo_server_thread_add_method(st, "/pattern/baz", NULL,
				pattern_handler, "baz");

    lo_server_thread_add_method(st, "/subtest", "i",
				subtest_handler, st);

    lo_server_thread_add_method(st, "/subtest-reply", "i",
				subtest_reply_handler, NULL);

    /* add method that will match any path and args */
    lo_server_thread_add_method(st, NULL, NULL, generic_handler, NULL);

    /* add method that will match the path /quit with no args */
    lo_server_thread_add_method(st, "/quit", "", quit_handler, NULL);

    /* check that the thread restarts */
    lo_server_thread_start(st);
    lo_server_thread_stop(st);
    lo_server_thread_start(st);

    if (lo_send(a, "/foo/bar", "ff", 0.12345678f, 23.0f) == -1) {
	printf("OSC error A %d: %s\n", lo_address_errno(a), lo_address_errstr(a));
	exit(1);
    }

    if (lo_send(a, "/foo/bar", "ff", 0.12345678f, 23.0f) == -1) {
	printf("OSC error B %d: %s\n", lo_address_errno(a), lo_address_errstr(a));
	exit(1);
    }

    test_validation(a);
    test_multicast(st);

    lo_send(a, "/", "i", 242);
    lo_send(a, "/pattern/", "i", 243);

#ifndef _MSC_VER  /* MS compiler refuses to compile this case */
    lo_send(a, "/bar", "ff", 0.12345678f, 1.0/0.0);
#endif
    lo_send(a, "/lotsofformats", "fisbmhtdSccTFNI", 0.12345678f, 123, "123",
	    btest, midi_data, 0x0123456789abcdefULL, tt, 0.9999, "sym",
	    'X', 'Y');
    lo_send(a, "/coerce", "fdihsS", 0.1f, 0.2, 123, 124LL, "aaa", "bbb");
    lo_send(a, "/coerce", "ffffss", 0.1f, 0.2f, 123.0, 124.0, "aaa", "bbb");
    lo_send(a, "/coerce", "ddddSS", 0.1, 0.2, 123.0, 124.0, "aaa", "bbb");
    lo_send(a, "/a/b/c/d", "sfsff", "one", 0.12345678f, "three",
	    -0.00000023001f, 1.0);
    lo_send(a, "/a/b/c/d", "b", btest);

    TEST(test_varargs(a, "/lotsofformats", "fisbmhtdSccTFNI", 0.12345678f, 123,
                      "123", btest, midi_data, 0x0123456789abcdefULL, tt,
                      0.9999, "sym", 'X', 'Y', LO_ARGS_END) == 0);

#ifdef __GNUC__
    // Note: Lack of support for variable-argument macros in non-GCC compilers
    //       does not allow us to test for these conditions.

    // too many args
    TEST(test_varargs(a, "/lotsofformats", "f", 0.12345678f, 123,
                      "123", btest, midi_data, 0x0123456789abcdefULL, tt,
                      0.9999, "sym", 'X', 'Y', LO_ARGS_END) != 0);
    // too many types
    TEST(test_varargs(a, "/lotsofformats", "fisbmhtdSccTFNI", 0.12345678f, 123,
                      "123", btest, midi_data, 0x0123456789abcdefULL, tt, 0.5,
                      LO_ARGS_END) != 0);
#endif

    // test lo_message_add
    m1 = lo_message_new();
    TEST(lo_message_add(m1, "fisbmhtdSccTFNI", 0.12345678f, 123, "123",
                        btest, midi_data, 0x0123456789abcdefULL, tt, 0.9999, "sym",
                        'X', 'Y') == 0);
    lo_send_message(a, "/lotsofformats", m1);
    lo_message_free(m1);
 
    lo_blob_free(btest);

    lo_send(a, "/pattern/*", "s", "a");
    lo_send(a, "/pattern/ba[rz]", "s", "b");

    server_url = lo_server_thread_get_url(st);
    sprintf(cmd, "." PATHDELIM "subtest %s &", server_url);
    if (system(cmd) != 0) {
	fprintf(stderr, "Cannot execute subtest command\n");
	exit(1);
    }
    system(cmd);
    free(server_url);

#ifdef WIN32
    Sleep(2000);
#else
    sleep(2);
#endif
    TEST(reply_count == 3);
    TEST(pattern_count == 5);
    TEST(subtest_count == 2);
    TEST(subtest_reply_count == 22);
    printf("\n");

    {
        lo_timetag t = {10,0xFFFFFFFC};
        b = lo_bundle_new(t);
    }
    m1 = lo_message_new();
    lo_message_add_string(m1, "abcdefghijklmnopqrstuvwxyz");
    lo_message_add_string(m1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    lo_bundle_add_message(b, "/bundle", m1);
    lo_send_bundle(a, b);

    /* This should be safe for multiple copies of the same message. */
    lo_bundle_free_messages(b);

    {
        lo_timetag t = {1,2};
        b = lo_bundle_new(t);
    }
    m1 = lo_message_new();
    lo_message_add_int32(m1, 23);
    lo_message_add_string(m1, "23");
    lo_bundle_add_message(b, "/bundle", m1);
    m2 = lo_message_new();
    lo_message_add_string(m2, "24");
    lo_message_add_int32(m2, 24);
    lo_bundle_add_message(b, "/bundle", m2);
    lo_bundle_add_message(b, "/bundle", m1);

/* 
    lo_send_bundle(a, b);
    if (a->errnum) {
	printf("error %d: %s\n", a->errnum, a->errstr);
	exit(1);
    }
*/
    TEST(lo_send_bundle(a, b) == 88);

    /* Test freeing out-of-order copies of messages in a bundle. */
    lo_bundle_free_messages(b);

    {
        lo_timetag t = {10,0xFFFFFFFE};
        b = lo_bundle_new(t);
    }
    m1 = lo_message_new();
    lo_message_add_string(m1, "abcdefghijklmnopqrstuvwxyz");
    lo_message_add_string(m1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    lo_bundle_add_message(b, "/bundle", m1);
    lo_send_bundle(a, b);
    lo_message_free(m1);
    lo_bundle_free(b);

    lo_timetag_now(&sched);

    sched.sec += 5;
    b = lo_bundle_new(sched);
    m1 = lo_message_new();
    lo_message_add_string(m1, "future");
    lo_message_add_string(m1, "time");
    lo_message_add_string(m1, "test");
    lo_bundle_add_message(b, "/bundle", m1);

    lo_send_bundle(a, b);
    lo_message_free(m1);
    lo_bundle_free(b);

    lo_send_timestamped(a, sched, "/bundle", "s", "lo_send_timestamped() test");

    /* test bundle timestamp ends up in message struct (and doesn't end up in
       unbundled messages) */
    lo_timetag_now(&sched);    
    lo_send_timestamped(a, sched, "/timestamp", "it", 1, sched);
    lo_send(a, "/timestamp", "it", 0, sched);

#define JITTER_ITS 25
    /* jitter tests */
    {
	lo_timetag stamps[JITTER_ITS];
	lo_timetag now;
	int i;

	for (i=0; i<JITTER_ITS; i++) {
	    lo_timetag_now(&now);
	    stamps[i] = now;
	    stamps[i].sec += 1;
	    stamps[i].frac = rand();
	    lo_send_timestamped(a, stamps[i], "/jitter", "ti", stamps[i], i);
	}
    }

#ifdef WIN32
    Sleep(2000);
#else
    sleep(2);
#endif

    lo_address_free(a);

    TEST(lo_server_thread_events_pending(st));

    while (lo_server_thread_events_pending(st)) {
	printf("pending events, wait...\n");
#ifdef WIN32
	fflush(stdout);
	Sleep(1000);
#else
	sleep(1);
#endif
    }
    
    TEST(bundle_count == 7);
    printf("\n");

    printf("bundle timing jitter results:\n"
	   "max jitter = %fs\n"
	   "avg jitter = %fs\n"
           "min jitter = %fs\n\n",
           jitter_max, jitter_total/(float)jitter_count, jitter_min);

    server_url = lo_server_get_url(s);

    lo_server_add_method(s, NULL, NULL, generic_handler, NULL);
    a = lo_address_new_from_url(server_url);
    TEST(lo_server_recv_noblock(s, 0) == 0);
    printf("Testing noblock API on %s\n", server_url);
    lo_send(a, "/non-block-test", "f", 23.0);

    count = 0;
    while (!lo_server_recv_noblock(s, 10) && count++ < 1000) { }
    if (count >= 1000) {
	printf("lo_server_recv_noblock() test failed\n");

	exit(1);
    }

    /* Delete methods */
    lo_server_thread_del_method(st, "/coerce", "dfhiSs");
    lo_server_del_method(s, NULL, NULL);

    lo_address_free(a);
    lo_server_free(s);
    free(server_url);

#ifndef WIN32
    { /* UNIX domain tests */
	lo_address ua;
	lo_server us;
	char *addr;

	unlink("/tmp/testlo.osc");
	us = lo_server_new_with_proto("/tmp/testlo.osc", LO_UNIX, error);
	ua = lo_address_new_from_url("osc.unix:///tmp/testlo.osc");
	TEST(lo_server_get_protocol(us) == LO_UNIX);
	TEST(lo_send(ua, "/unix", "f", 23.0) == 16);
	TEST(lo_server_recv(us) == 16);
	addr = lo_server_get_url(us);
	TEST(!strcmp("osc.unix:////tmp/testlo.osc", addr));
	free(addr);
	lo_address_free(ua);
	ua = lo_address_new_with_proto(LO_UNIX, NULL, "/tmp/testlo.osc");
	TEST(lo_send(ua, "/unix", "f", 23.0) == 16);
	TEST(lo_server_recv(us) == 16);
	lo_server_free(us);
	lo_address_free(ua);
    }
#endif

    { /* TCP tests */
	lo_address ta;
	lo_server ts;
	char *addr;

	ts = lo_server_new_with_proto(NULL, LO_TCP, error);
	addr = lo_server_get_url(ts);
	ta = lo_address_new_from_url(addr);
	if (lo_address_errno(ta)) {
	    printf("err: %s\n", lo_address_errstr(ta));
	    exit(1);
	}
	TEST(lo_server_get_protocol(ts) == LO_TCP);
	TEST(lo_send(ta, "/tcp", "f", 23.0) == 16);
	TEST(lo_send(ta, "/tcp", "f", 23.0) == 16);
	TEST(lo_server_recv(ts) == 16);
	TEST(lo_server_recv(ts) == 16);
	free(addr);
	lo_server_free(ts);
	lo_address_free(ta);
    }

    server_url = lo_server_thread_get_url(st);
    a = lo_address_new_from_url(server_url);
    /* exit */
    lo_send(a, "/quit", NULL);
    lo_address_free(a);

    while (!done) {
#ifdef WIN32
    Sleep(1);
#else
	usleep(1000);
#endif
    }

    lo_server_thread_free(st);
    free(server_url);


    return 0;
}