// ********************************************************* // -(OSC handler)------------------------------------------- int oscmulticast_handler(const char *path, const char *types, lo_arg ** argv, int argc, void *data, 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; } 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; }
// ********************************************************* // -(poll libmapper)---------------------------------------- void impmap_clear_snapshots(impmap *x) { while (x->snapshots) { t_snapshot temp = x->snapshots->next; free(x->snapshots->inputs); free(x->snapshots->outputs); x->snapshots = temp; } x->num_snapshots = 0; outlet_anything(x->outlet2, gensym("clear"), 0, 0); maxpd_atom_set_int(x->buffer_in, 0); outlet_anything(x->outlet3, gensym("numSnapshots"), 1, x->buffer_in); }
// ********************************************************* // -(connection handler)------------------------------------ void impmap_on_map(mapper_device dev, mapper_map map, mapper_record_event e) { // if connected involves current generic signal, create a new generic signal impmap *x = (void*)mapper_device_user_data(dev); if (!x) { post("error in connect handler: user_data is NULL"); return; } if (!x->ready) { post("error in connect handler: device not ready"); return; } // retrieve devices and signals mapper_slot slot = mapper_map_slot(map, MAPPER_LOC_SOURCE, 0); mapper_signal src_sig = mapper_slot_signal(slot); mapper_device src_dev = mapper_signal_device(src_sig); slot = mapper_map_slot(map, MAPPER_LOC_DESTINATION, 0); mapper_signal dst_sig = mapper_slot_signal(slot); mapper_device dst_dev = mapper_signal_device(dst_sig); // sanity check: don't allow self-connections if (src_dev == dst_dev) { mapper_map_release(map); return; } char full_name[256]; if (e == MAPPER_ADDED) { if (src_dev == x->device) { snprintf(full_name, 256, "%s/%s", mapper_device_name(dst_dev), mapper_signal_name(dst_sig)); if (strcmp(mapper_signal_name(src_sig), full_name) == 0) { // <thisDev>:<dstDevName>/<dstSigName> -> <dstDev>:<dstSigName> return; } if (mapper_device_num_signals(x->device, MAPPER_DIR_OUTGOING) >= MAX_LIST) { post("Max outputs reached!"); return; } // unmap the generic signal mapper_map_release(map); // add a matching output signal int i, length = mapper_signal_length(dst_sig); char type = mapper_signal_type(dst_sig); void *min = mapper_signal_minimum(dst_sig); void *max = mapper_signal_maximum(dst_sig); float *minf = 0, *maxf = 0; if (type == 'f') { minf = (float*)min; maxf = (float*)max; } else { if (min) { minf = alloca(length * sizeof(float)); if (type == 'i') { int *mini = (int*)min; for (i = 0; i < length; i++) minf[i] = (float)mini[i]; } else if (type == 'd') { double *mind = (double*)min; for (i = 0; i < length; i++) minf[i] = (float)mind[i]; } else minf = 0; } if (max) { maxf = alloca(length * sizeof(float)); if (type == 'i') { int *maxi = (int*)max; for (i = 0; i < length; i++) maxf[i] = (float)maxi[i]; } else if (type == 'd') { double *maxd = (double*)max; for (i = 0; i < length; i++) maxf[i] = (float)maxd[i]; } else maxf = 0; } } src_sig = mapper_device_add_output_signal(x->device, full_name, length, 'f', 0, minf, maxf); if (!src_sig) { post("error creating new source signal!"); return; } mapper_signal_set_callback(src_sig, impmap_on_query); // map the new signal map = mapper_map_new(1, &src_sig, 1, &dst_sig); mapper_map_set_mode(map, MAPPER_MODE_EXPRESSION); mapper_map_set_expression(map, "y=x"); mapper_map_push(map); impmap_update_output_vector_positions(x); //output numOutputs maxpd_atom_set_int(&x->msg_buffer, mapper_device_num_signals(x->device, MAPPER_DIR_OUTGOING) - 1); outlet_anything(x->outlet3, gensym("numOutputs"), 1, &x->msg_buffer); } else if (dst_dev == x->device) { snprintf(full_name, 256, "%s/%s", mapper_device_name(src_dev), mapper_signal_name(src_sig)); if (strcmp(mapper_signal_name(dst_sig), full_name) == 0) { // <srcDevName>:<srcSigName> -> <thisDev>:<srcDevName>/<srcSigName> return; } if (mapper_device_num_signals(x->device, MAPPER_DIR_INCOMING) >= MAX_LIST) { post("Max inputs reached!"); return; } // unmap the generic signal mapper_map_release(map); // add a matching input signal int i, length = mapper_signal_length(src_sig); char type = mapper_signal_type(src_sig); void *min = mapper_signal_minimum(src_sig); void *max = mapper_signal_maximum(src_sig); float *minf = 0, *maxf = 0; if (type == 'f') { minf = (float*)min; maxf = (float*)max; } else { if (min) { minf = alloca(length * sizeof(float)); if (type == 'i') { int *mini = (int*)min; for (i = 0; i < length; i++) minf[i] = (float)mini[i]; } else if (type == 'd') { double *mind = (double*)min; for (i = 0; i < length; i++) minf[i] = (float)mind[i]; } else minf = 0; } if (max) { maxf = alloca(length * sizeof(float)); if (type == 'i') { int *maxi = (int*)max; for (i = 0; i < length; i++) maxf[i] = (float)maxi[i]; } else if (type == 'd') { double *maxd = (double*)max; for (i = 0; i < length; i++) maxf[i] = (float)maxd[i]; } else maxf = 0; } } dst_sig = mapper_device_add_input_signal(x->device, full_name, length, 'f', 0, minf, maxf, impmap_on_input, 0); if (!dst_sig) { post("error creating new destination signal!"); return; } // map the new signal map = mapper_map_new(1, &src_sig, 1, &dst_sig); mapper_map_set_mode(map, MAPPER_MODE_EXPRESSION); mapper_map_set_expression(map, "y=x"); mapper_map_push(map); impmap_update_input_vector_positions(x); //output numInputs maxpd_atom_set_int(&x->msg_buffer, mapper_device_num_signals(x->device, MAPPER_DIR_INCOMING) - 1); outlet_anything(x->outlet3, gensym("numInputs"), 1, &x->msg_buffer); } } else if (e == MAPPER_REMOVED) { if (src_sig == x->dummy_input || src_sig == x->dummy_output || dst_sig == x->dummy_input || dst_sig == x->dummy_output) return; if (src_dev == x->device) { snprintf(full_name, 256, "%s/%s", mapper_device_name(dst_dev), mapper_signal_name(dst_sig)); if (strcmp(mapper_signal_name(src_sig), full_name) != 0) return; // remove signal mapper_device_remove_signal(x->device, src_sig); impmap_update_input_vector_positions(x); //output numOutputs maxpd_atom_set_int(&x->msg_buffer, mapper_device_num_signals(x->device, MAPPER_DIR_OUTGOING) - 1); outlet_anything(x->outlet3, gensym("numOutputs"), 1, &x->msg_buffer); } else if (dst_dev == x->device) { snprintf(full_name, 256, "%s/%s", mapper_device_name(src_dev), mapper_signal_name(src_sig)); if (strcmp(mapper_signal_name(dst_sig), full_name) != 0) return; // remove signal mapper_device_remove_signal(x->device, dst_sig); impmap_update_input_vector_positions(x); //output numInputs maxpd_atom_set_int(&x->msg_buffer, mapper_device_num_signals(x->device, MAPPER_DIR_INCOMING) - 1); outlet_anything(x->outlet3, gensym("numInputs"), 1, &x->msg_buffer); } } }
// ********************************************************* // -(new)--------------------------------------------------- void *impmap_new(t_symbol *s, int argc, t_atom *argv) { impmap *x = NULL; long i; const char *alias = NULL; const char *iface = NULL; #ifdef MAXMSP if ((x = object_alloc(mapper_class))) { x->outlet3 = listout((t_object *)x); x->outlet2 = listout((t_object *)x); x->outlet1 = listout((t_object *)x); #else if (x = (impmap *) pd_new(mapper_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->name = strdup("implicitmap"); for (i = 0; i < argc; i++) { if ((argv + i)->a_type == A_SYM) { if(strcmp(maxpd_atom_get_string(argv+i), "@alias") == 0) { if ((argv+i+1)->a_type == A_SYM) { alias = maxpd_atom_get_string(argv+i+1); i++; } } else if(strcmp(maxpd_atom_get_string(argv+i), "@interface") == 0) { if ((argv+i+1)->a_type == A_SYM) { iface = maxpd_atom_get_string(argv+i+1); i++; } } } } if (alias) { free(x->name); x->name = *alias == '/' ? strdup(alias+1) : strdup(alias); } if (impmap_setup_mapper(x, iface)) { post("implicitmap: Error initializing."); } else { x->ready = 0; x->mute = 0; x->new_in = 0; x->query_count = 0; x->num_snapshots = 0; x->snapshots = 0; // initialize input and output buffers for (i = 0; i < MAX_LIST; i++) { maxpd_atom_set_float(x->buffer_in+i, 0); maxpd_atom_set_float(x->buffer_out+i, 0); x->signals_in[i].x = x; x->signals_out[i].x = x; } x->size_in = 0; x->size_out = 0; #ifdef MAXMSP x->clock = clock_new(x, (method)impmap_poll); // Create the timing clock x->timeout = clock_new(x, (method)impmap_output_snapshot); #else x->clock = clock_new(x, (t_method)impmap_poll); x->timeout = clock_new(x, (t_method)impmap_output_snapshot); #endif clock_delay(x->clock, INTERVAL); // Set clock to go off after delay } } return (x); } // ********************************************************* // -(free)-------------------------------------------------- void impmap_free(impmap *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->device) { mapper_device_free(x->device); } if (x->name) { free(x->name); } impmap_clear_snapshots(x); } // ********************************************************* // -(print properties)-------------------------------------- void impmap_print_properties(impmap *x) { if (x->ready) { //output name maxpd_atom_set_string(&x->msg_buffer, mapper_device_name(x->device)); outlet_anything(x->outlet3, gensym("name"), 1, &x->msg_buffer); mapper_network net = mapper_device_network(x->device); //output interface maxpd_atom_set_string(&x->msg_buffer, (char *)mapper_network_interface(net)); outlet_anything(x->outlet3, gensym("interface"), 1, &x->msg_buffer); //output IP const struct in_addr *ip = mapper_network_ip4(net); if (ip) { maxpd_atom_set_string(&x->msg_buffer, inet_ntoa(*ip)); outlet_anything(x->outlet3, gensym("IP"), 1, &x->msg_buffer); } //output port maxpd_atom_set_int(&x->msg_buffer, mapper_device_port(x->device)); outlet_anything(x->outlet3, gensym("port"), 1, &x->msg_buffer); //output numInputs maxpd_atom_set_int(&x->msg_buffer, mapper_device_num_signals(x->device, MAPPER_DIR_INCOMING) - 1); outlet_anything(x->outlet3, gensym("numInputs"), 1, &x->msg_buffer); //output numOutputs maxpd_atom_set_int(&x->msg_buffer, mapper_device_num_signals(x->device, MAPPER_DIR_OUTGOING) - 1); outlet_anything(x->outlet3, gensym("numOutputs"), 1, &x->msg_buffer); } } // ********************************************************* // -(inlet/outlet assist - maxmsp only)--------------------- #ifdef MAXMSP void impmap_assist(impmap *x, void *b, long m, long a, char *s) { if (m == ASSIST_INLET) { // inlet sprintf(s, "OSC input"); } else { // outlet if (a == 0) { sprintf(s, "Mapped OSC inputs"); } else if (a == 1) { sprintf(s, "Snapshot data"); } else { sprintf(s, "Device information"); } } } #endif // ********************************************************* // -(snapshot)---------------------------------------------- void impmap_snapshot(impmap *x) { // if previous snapshot still in progress, output current snapshot status if (x->query_count) { post("still waiting for last snapshot"); return; } mapper_signal *psig; x->query_count = 0; // allocate a new snapshot if (x->ready) { t_snapshot new_snapshot = (t_snapshot)malloc(sizeof(t_snapshot)); new_snapshot->id = x->num_snapshots++; new_snapshot->next = x->snapshots; new_snapshot->inputs = calloc(x->size_in, sizeof(float)); new_snapshot->outputs = calloc(x->size_out, sizeof(float)); x->snapshots = new_snapshot; } // iterate through input signals and store their current values psig = mapper_device_signals(x->device, MAPPER_DIR_INCOMING); while (psig) { if (*psig != x->dummy_input) { void *value = (void*)mapper_signal_value(*psig, 0); t_signal_ref *ref = mapper_signal_user_data(*psig); int siglength = mapper_signal_length(*psig); int length = ref->offset + siglength < MAX_LIST ? siglength : MAX_LIST - ref->offset; // we can simply use memcpy here since all our signals are type 'f' memcpy(&x->snapshots->inputs[ref->offset], value, length * sizeof(float)); } psig = mapper_signal_query_next(psig); } mapper_timetag_now(&x->tt); mapper_device_start_queue(x->device, x->tt); // iterate through output signals and query the remote ends psig = mapper_device_signals(x->device, MAPPER_DIR_OUTGOING); while (psig) { if (*psig != x->dummy_output) { // query the remote value x->query_count += mapper_signal_query_remotes(*psig, MAPPER_NOW); } psig = mapper_signal_query_next(psig); } mapper_device_send_queue(x->device, x->tt); post("sent %i queries", x->query_count); if (x->query_count) clock_delay(x->timeout, 1000); // Set clock to go off after delay } // ********************************************************* // -(snapshot)---------------------------------------------- void impmap_output_snapshot(impmap *x) { if (x->query_count) { post("query timeout! setting query count to 0 and outputting current values."); x->query_count = 0; } maxpd_atom_set_int(x->buffer_in, x->snapshots->id+1); outlet_anything(x->outlet3, gensym("numSnapshots"), 1, x->buffer_in); maxpd_atom_set_float_array(x->buffer_in, x->snapshots->inputs, x->size_in); outlet_anything(x->outlet2, gensym("in"), x->size_in, x->buffer_in); maxpd_atom_set_float_array(x->buffer_out, x->snapshots->outputs, x->size_out); outlet_anything(x->outlet2, gensym("out"), x->size_out, x->buffer_out); maxpd_atom_set_int(x->buffer_in, x->snapshots->id); outlet_anything(x->outlet2, gensym("snapshot"), 1, x->buffer_in); } // ********************************************************* // -(mute output)------------------------------------------- void impmap_mute_output(impmap *x, t_symbol *s, int argc, t_atom *argv) { if (argc) { if (argv->a_type == A_FLOAT) x->mute = (int)atom_getfloat(argv); #ifdef MAXMSP else if (argv->a_type == A_LONG) x->mute = atom_getlong(argv); #endif } } // ********************************************************* // -(process)----------------------------------------------- void impmap_process(impmap *x) { outlet_anything(x->outlet2, gensym("process"), 0, 0); }