int osc_controller::_add_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) { if (!m_restricted || is_target(lo_message_get_source(msg))) { pair<int,int> net_id(argv[0]->i, argv[1]->i); m_skip++; world_node obj = m_world->add_node(std::string(&argv[2]->s)); m_skip--; if (!obj.is_null()) { int local_id = obj.get_id (); m_net_id[local_id] = net_id; m_local_id[net_id] = local_id; 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_string(newmsg, &argv[2]->s); broadcast_message_from(PSYNTH_OSC_MSG_ADD, newmsg, lo_message_get_source(msg)); lo_message_free(newmsg); } } } return 0; }
int osc_controller::_deactivate_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) { 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++; m_world->deactivate_node(obj); 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); broadcast_message_from(PSYNTH_OSC_MSG_DEACTIVATE, newmsg, lo_message_get_source(msg)); lo_message_free(newmsg); } } } return 0; }
int OscReceiver::messageCB(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg, void* user_data) { OscReceiver* receiver = (OscReceiver*) user_data; return receiver->processMessage(ReceivedMessage((std::string) path, (std::string) types, argv, argc, msg), MessageSource(lo_message_get_source(msg))); }
int StreamMulticaster::onStreamPingI(const char *path, const char *types, lo_arg **argv, int argc, lo_message msg) { // send pong reply: lowrappers::Address replyTo(lo_message_get_source(msg), false); replyTo.sendFrom(streamIn_, streamPath_ + "pong" , "i", argv[0]->i); return 1; // returning 1 ensures that the call will also be passed to forwardMessage }
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; }
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; }
inline int lo_generic_handler(const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data) { int i; printf("--- OSC Message ---\n"); printf("from host: %s\n", lo_address_get_hostname(lo_message_get_source(msg))); printf("from port: %s\n", lo_address_get_port(lo_message_get_source(msg))); printf("path: <%s>\n", path); for (i=0; i<argc; i++) { printf("arg %d '%c' ", i, types[i]); lo_arg_pp((lo_type)types[i], argv[i]); printf("\n"); } printf("\n"); fflush(stdout); return 1; }
int StreamMulticaster::onUnknownConnectIn(const char *path, const char *types, lo_arg **argv, int argc, lo_message msg) { // create a reply adress from msg: WonderOscSender replyTo(lo_message_get_source(msg), false); // send reply: const std::string pathStr(path); replyTo.sendReply(pathStr, 1, "Unknown command: " + pathStr); return 0; }
int VSReceiver::onStreamVisualPingI(const char *path, const char *types,lo_arg **argv, int argc, lo_message msg) { if(pingHandler_ == nullptr){ return 0; } else { // the lo_address returned from lo_message_get_source will be free'd along // with msg, so we need to set ownership to false: WonderOscServerSender replyAddress(lo_message_get_source(msg), *this, false); return pingHandler_->onStreamVisualPing(argv[0]->i, &replyAddress); } }
int subtest_handler(const char *path, const char *types, lo_arg **argv, int argc, lo_message data, void *user_data) { lo_address a = lo_message_get_source(data); subtest_count++; printf("got subtest message %d\n", subtest_count); lo_send_from(a, lo_server_thread_get_server(user_data), LO_TT_IMMEDIATE, "/subtest", "i", subtest_count); return 0; }
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; }
static int osc_message ( const char *path, const char * /*types*/, lo_arg **argv, int /*argc*/, void *data, void * /*user_data*/ ) { QMutexLocker locker(&g_oscMutex); #ifdef CONFIG_DEBUG_0 printf("osc_message: path \"%s\"", path); for (int i = 0; i < argc; ++i) { printf(", arg %d '%c' ", i, types[i]); lo_arg_pp(lo_type(types[i]), argv[i]); } printf(", data %p, user_data %p\n", data, user_data); #endif if (::strncmp(path, "/dssi", 5)) return 1; const QString sPath = path; const QString& sLabel = sPath.section('/', 2, 2); DssiEditor *pDssiEditor = osc_find_editor(sLabel); if (pDssiEditor == NULL) return 1; if (pDssiEditor->busy > 0) return 1; lo_message message = lo_message(data); lo_address source = lo_message_get_source(message); const QString& sMethod = sPath.section('/', 3, 3); if (sMethod == "update") return osc_update(pDssiEditor, argv, source); else if (sMethod == "configure") return osc_configure(pDssiEditor, argv); else if (sMethod == "control") return osc_control(pDssiEditor, argv); else if (sMethod == "program") return osc_program(pDssiEditor, argv); else if (sMethod == "midi") return osc_midi(pDssiEditor, argv); else if (sMethod == "exiting") return osc_exiting(pDssiEditor); return 1; }
static int get_version_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; // Send back reply result = lo_send_from( src, serv, LO_TT_IMMEDIATE, "/version", "ss", PACKAGE_NAME, PACKAGE_VERSION ); if (result<1) fprintf(stderr, "Error: sending reply failed: %s\n", lo_address_errstr(src)); return 0; }
static int position_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; // Send back reply result = lo_send_from( src, serv, LO_TT_IMMEDIATE, "/deck/position", "f", input_file->position ); if (result<1) fprintf(stderr, "Error: sending reply failed: %s\n", lo_address_errstr(src)); return 0; }
static int filepath_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; // Send back reply if (input_file->filepath) { result = lo_send_from( src, serv, LO_TT_IMMEDIATE, "/deck/filepath", "s", input_file->filepath ); } else { // Empty filepath result = lo_send_from( src, serv, LO_TT_IMMEDIATE, "/deck/filepath", "s", "" ); } if (result<1) fprintf(stderr, "Error: sending reply failed: %s\n", lo_address_errstr(src)); return 0; }
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; }
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; }
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; }
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); }
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; }
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); }
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; }
//================================================================ // /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
int OSCServer::genericHandler( const char *path, const char *types, lo_arg **argv, int argc, void *data) { UNUSED(argc); UNUSED(types); if(!contacted) { firstContact(lo_message_get_source((lo_message)data)); contacted = true; } //find out what this message is for (track bus or master) std::string pathStr(path); pathStr = pathStr.substr(1); pathStr = pathStr.substr(pathStr.find("/") + 1); std::string object = pathStr.substr(0,pathStr.find("/")); pathStr = pathStr.substr(pathStr.find("/") + 1); std::string controllable = pathStr.substr(0,pathStr.find("/")); if(object == "track") { if(controllable == "fader") { //get the track number pathStr= pathStr.substr(pathStr.find("/") + 1); //build a midi event from the fader value and track number char data[3]; if(pthread_mutex_lock(&idMutex) == 0) { data[0] = (char) CC_MASK; data[1] = trackIds[atoi(pathStr.c_str()) - 1]; data[2] = (char) ((int) argv[0]->f); pthread_mutex_unlock(&idMutex); } MidiEvent midiEvent(data,true); //Send it to the jack client to handle send to Ardour if(!((unsigned char)data[1] == 0xFF)){ jack_ringbuffer_write(controllerBuffer, (char *) &midiEvent,sizeof(MidiEvent)); } } if(controllable == "bank") { if (argv[0]->f > 0.5){ pathStr= pathStr.substr(pathStr.find("/") + 1); if(pathStr == "up"){ int tb = getTrackBank(); if((tb+1) < numTrackBanks) { sendTrackBank(tb+1); setTrackBank(tb+1); } } else if(pathStr == "down"){ int tb = getTrackBank(); if(tb > 0) { sendTrackBank(tb-1); setTrackBank(tb-1); } } } } } else if (object == "bus") { if(controllable == "fader") { //get the bus number(void *)this pathStr= pathStr.substr(pathStr.find("/") + 1); char data[3]; if(pthread_mutex_lock(&idMutex) == 0) { data[0] = (char) CC_MASK; data[1] = busIds[atoi(pathStr.c_str()) - 1]; data[2] = (char) ((int) argv[0]->f); pthread_mutex_unlock(&idMutex); } MidiEvent midiEvent(data,true); //Send it to the jack client to handle send to Ardour //Send it to the jack client to handle send to Ardour if(!((unsigned char)data[1] == 0xFF)){ jack_ringbuffer_write(controllerBuffer, (char *) &midiEvent,sizeof(MidiEvent)); } } if(controllable == "bank") { if (argv[0]->f > 0.5){ pathStr= pathStr.substr(pathStr.find("/") + 1); if(pathStr == "up"){ int bb = getBusBank(); if((bb+1) < numBusBanks) { setBusBank(bb+1); sendBusBank(bb+1); } } else if(pathStr == "down"){ int bb = getBusBank(); if(bb > 0) { setBusBank(bb-1); sendBusBank(bb-1); } } } } } else if (object == "master") { if(controllable == "fader") { //build a midi event from the fader value and track number char data[3] = {(char) CC_MASK,MASTER_CC,(char)((int) argv[0]->f)}; MidiEvent midiEvent(data,true); //Send it to the jack client to handle send to Ardour jack_ringbuffer_write(controllerBuffer, (char *) &midiEvent,sizeof(MidiEvent)); } } else if (object == "scene") { } return 0; }
// /audio //handler for audio messages int audio_handler(const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) { if(shutdown_in_progress==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 and channel offset 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,"\n\nchannel offset %d >= available input channels %d! (nothing to receive). shutting down...\n" ,channel_offset ,(argc-data_offset+channel_offset)); fflush(stderr); shutdown_in_progress=1; return 0; } //need to warn when offset + outchannels limited //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; loa = lo_message_get_source(data); strcpy(sender_host,lo_address_get_hostname(loa)); strcpy(sender_port,lo_address_get_port(loa)); remote_sample_rate=argv[3]->i; remote_period_size=lo_blob_datasize((lo_blob)argv[0+data_offset])/bytes_per_sample; fprintf(stderr,"\nsender was (re)started. "); if(remote_period_size!=period_size) { fprintf(stderr,"sender period size: %d samples (%.3f x forward period size)\n\n",remote_period_size,(float)remote_period_size/period_size); } else { fprintf(stderr,"equal sender and receiver period size\n\n"); } }//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; 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; } fflush(stderr); // 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=rb_can_write(rb); if(can_write_count < mc_period_bytes) { buffer_overflow_counter++; ///////////////// fprintf(stderr,"\nBUFFER OVERFLOW! this is bad -----%s\n","\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=rb_write(rb, (void *) data, period_size*bytes_per_sample); } } 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=rb_write(rb_helper, (void *) data, remote_period_size*bytes_per_sample); } //if enough data collected for one larger multichannel period while(rb_can_read(rb_helper) >=mc_period_bytes && rb_can_write(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; rb_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=rb_write(rb,(void *)data,remote_period_size*bytes_per_sample); } } data=orig_data; free(data); } } 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=rb_write(rb, (void *) data, period_size*bytes_per_sample); } } } return 0; }//end audio_handler
// /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
char *osc_get_uri(void *data) { lo_address a = lo_message_get_source(data); char *uri = lo_address_get_url(a); return uri; }
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; }
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; }
// ********************************************************* // -(OSC handler)------------------------------------------- int oscmulticast_handler(const char *path, const char *types, lo_arg ** argv, int argc, lo_message msg, void *user_data) { t_oscmulticast *x = (t_oscmulticast *)user_data; int i, j; char my_string[2]; j=0; if (!x->buffer) { post("Error receiving message!"); return 0; } lo_address address = lo_message_get_source(msg); if (address) { maxpd_atom_set_int(x->buffer, atoi(lo_address_get_port(address))); outlet_anything(x->outlet3, gensym("int"), 1, x->buffer); maxpd_atom_set_string(x->buffer, lo_address_get_hostname(address)); outlet_anything(x->outlet2, gensym("symbol"), 1, x->buffer); } if (argc > MAXSIZE) { post("Truncating received message to 256 elements!"); argc = MAXSIZE; } for (i=0; i<argc; i++) { switch (types[i]) { case 'i': maxpd_atom_set_int(x->buffer+j, argv[i]->i); j++; break; case 'h': maxpd_atom_set_int(x->buffer+j, argv[i]->h); j++; break; case 'f': maxpd_atom_set_float(x->buffer+j, argv[i]->f); j++; break; case 'd': maxpd_atom_set_float(x->buffer+j, (float)argv[i]->d); j++; break; case 's': maxpd_atom_set_string(x->buffer+j, (const char *)&argv[i]->s); j++; break; case 'S': maxpd_atom_set_string(x->buffer+j, (const char *)&argv[i]->s); j++; break; case 'c': snprintf(my_string, 2, "%c", argv[i]->c); maxpd_atom_set_string(x->buffer+j, (const char *)my_string); j++; break; case 't': //output timetag from a second outlet? break; } } outlet_anything(x->outlet1, gensym((char *)path), j, x->buffer); return 0; }