/** * Set the output port by name. * If the name is valid, this object will pass messages received to it's first inlet to the MIDI port. * If the name is invalid, an error is printed to the Max console and nothing else happens. * As a special behavior, sending the [outport " "] message will close the port. This plays nice with the way we build the umenu port list. */ void output(long inlet, t_symbol *s, long ac, t_atom *av) { t_symbol *portName = _sym_nothing; // TODO: maybe handle ints (and floats cast to int) and use it to lookup a port by index. // Could be a useful for someone with devices with duplicate names. // See simplemax_new for an example of how to check the atom type if( atom_arg_getsym(&portName, 0, ac, av) == MAX_ERR_NONE ) { if (midiout) { int portIndex = getPortIndex(outPortMap, portName); if(portIndex >= 0 || portName == SYM_NONE) { midiout->closePort(); outPortName = NULL; } if(portIndex >= 0) { midiout->openPort( portIndex ); // TODO? midiout->setErrorCallback() outPortName = portName; } else if(portName != SYM_NONE) { object_error((t_object *)this, "Output port not found: %s", *portName); } } // else we already printed an error in the constructor } else { object_error((t_object *)this, "Invalid output. A portname is required. Or use (output <none>) to close the port."); } }
// Create void *init_new(t_symbol *s, long argc, t_atom *argv) { long attrstart = attr_args_offset(argc, argv); // support normal arguments t_init *x = (t_init *)object_alloc(g_init_class); t_symbol *relativeAddress = _sym_nothing; // could be used to binds on a sub level j.hub if (attrstart && argv) atom_arg_getsym(&relativeAddress, 0, attrstart, argv); if (x) { x->outlets = (TTHandle)sysmem_newptr(sizeof(TTPtr) * 2); x->outlets[end_out] = bangout(x); x->outlets[start_out] = bangout(x); x->patcherNode = NULL; x->address = TTAddress(jamoma_parse_dieze((t_object*)x, relativeAddress)->s_name); attr_args_process(x, argc, argv); // handle attribute args // The following must be deferred because we have to interrogate our box, // and our box is not yet valid until we have finished instantiating the object. // Trying to use a loadbang method instead is also not fully successful (as of Max 5.0.6) defer_low((t_object*)x, (method)init_subscribe, NULL, 0, 0); } return (x); // Return the pointer }
void *buffi_new(t_symbol *msg, short argc, t_atom *argv) { t_buffi *x = (t_buffi *)object_alloc(buffi_class); dsp_setup((t_pxobject *)x,1); outlet_new((t_object *)x, "signal"); if(argc < 3){ error("%s: you must provide three buffer names: src1, src2, and dest",OBJECT_NAME); return NIL; } atom_arg_getsym(&x->src1,0,argc,argv); atom_arg_getsym(&x->src2,1,argc,argv); atom_arg_getsym(&x->dest,2,argc,argv); buffi_set(x, msg); srandom(clock()); return x; }
void *multigrain_new(t_symbol *msg, short argc, t_atom *argv) { t_multigrain *x = (t_multigrain *)object_alloc(multigrain_class); float f = 2; int i; dsp_setup((t_pxobject *)x,1); srand(time(0)); //need "seed" message x->pitchscale = (float *) t_getbytes(MAXSCALE * sizeof(float)); x->grains = (t_grain *) t_getbytes(MAXGRAINS * sizeof(t_grain)); // default names x->wavename = gensym("waveform"); x->windowname = gensym("window"); if( argc < 2){ error("Must enter wave buffer, window buffer, and output channel count"); return NULL; } if(argc > 0) atom_arg_getsym(&x->wavename,0,argc,argv); if(argc > 1) atom_arg_getsym(&x->windowname,1,argc,argv); if(argc > 2) atom_arg_getfloat(&f,2,argc,argv); x->output_channels = (long) f; for(i = 0; i < x->output_channels; i++){ outlet_new((t_pxobject *)x, "signal"); } x->wavebuf = buffer_ref_new((t_object*)x, x->wavename); x->windowbuf = buffer_ref_new((t_object*)x, x->windowname); multigrain_init(x,0); return x; }
/* The new and free instance routines *****************************************/ void *bed_new(t_symbol *s, short argc, t_atom *argv) { /* Instantiate a new object */ t_bed *x = (t_bed *)object_alloc(bed_class); /* Parse passed argument */ atom_arg_getsym(&x->b_name, 0, argc, argv); /* Initialize some state variables */ x->undo_cut = 0; /* Print message to Max window */ post("bed • Object was created"); /* Return a pointer to the new object */ return x; }
void *return_new(t_symbol *s, long argc, t_atom *argv) { long attrstart = attr_args_offset(argc, argv); t_return* x = (t_return *)object_alloc(return_class); t_symbol* name = _sym_nothing; ObjectPtr patcher = NULL; if (attrstart && argv) atom_arg_getsym(&name, 0, attrstart, argv); else name = symbol_unique(); // for instances buried inside of another object: // we pass a second argument which is a pointer to the patcher if (attrstart>1 && argv) patcher = ObjectPtr(atom_getobj(argv+1)); if (x) { x->outlets[k_outlet_dumpout] = outlet_new(x, 0L); object_obex_store((void *)x, _sym_dumpout, (t_object *)x->outlets[k_outlet_dumpout]); x->outlets[k_outlet_thru] = outlet_new(x, 0L); jcom_core_subscriber_new_extended(&x->common, name, jps_subscribe_return); atom_setsym(&x->output[0], name); x->output_len = 1; x->attrEnable = true; x->attrDataspace = jps_none; x->attrUnitNative = jps_none; if (patcher) x->common.container = patcher; attr_args_process(x, argc, argv); jcom_core_subscriber_subscribe((t_jcom_core_subscriber_common*)x); return_makesend(x); } return (x); }
void *hub_new(t_symbol *s, long argc, t_atom *argv) { short i; long attrstart = attr_args_offset(argc, argv); t_hub *x = (t_hub *)object_alloc(s_hub_class); t_symbol *name = _sym_nothing; t_atom a[2]; if(attrstart && argv) atom_arg_getsym(&name, 0, attrstart, argv); else{ t_object* patcher = jamoma_object_getpatcher((t_object*)x); t_symbol* filepath = object_attr_getsym(patcher, _sym_filepath); char pathstr[MAX_PATH_CHARS]; char* filename = 0; strncpy_zero(pathstr, filepath->s_name, MAX_PATH_CHARS); filename = strrchr(pathstr, '.'); if(filename) { *filename = 0; // strip the suffix by setting '.' to terminating NULL char filename = strrchr(pathstr, '/'); if (filename) { // Our module name is the patchers name since the patcher is typically located // at /some/where/nameToUseForModule.maxpat filename++; // get rid of slash name = gensym(filename); } else name = gensym(pathstr); } else { // We are an unnamed jcom.hub inserted into an unsaved max patcher which has // no '.' in it's filename. Just leave as untitled, at least until it is saved. name = gensym("Untitled"); } } if(x){ for(i=k_num_outlets; i > 0; i--) x->outlets[i-1] = outlet_new(x, 0); object_obex_store((void *)x, _sym_dumpout, (t_object *)x->outlets[k_outlet_dumpout]); x->init_qelem = qelem_new(x, (method)hub_qfn_init); // set default attributes x->attr_name = name; x->osc_name = _sym_nothing; x->attr_type = jps_control; x->attr_description = _sym_nothing; x->attr_algorithm_type = jps_default; // poly for audio, jitter for video, control for control x->attr_size = jps_1U_half; x->attr_inspector = 0; x->using_wildcard = false; x->in_object = NULL; // module MUST have a jcom.in object x->out_object = NULL; // the jcom.out object is optional x->gui_object = NULL; // jcom.remote in the gui x->num_parameters = 0; for(i=0; i<MAX_NUM_CHANNELS; i++) x->meter_object[i] = NULL; x->preset = new presetList; // begin with no presets x->subscriber = new subscriberList; // ... and no subscribers attr_args_process(x, argc, argv); // handle attribute args x->jcom_send = NULL; x->jcom_receive = NULL; atom_setsym(a, jps_jcom_remote_fromModule); x->jcom_send = (t_object*)object_new_typed(_sym_box, jps_jcom_send, 1, a); atom_setsym(a, jps_jcom_remote_toModule); x->jcom_receive = (t_object*)object_new_typed(_sym_box, jps_jcom_receive, 1, a); object_method(x->jcom_receive, jps_setcallback, &hub_receive_callback, x); if(!g_jcom_send_notifications){ atom_setsym(a, gensym("notifications")); g_jcom_send_notifications = (t_object*)object_new_typed(_sym_box, jps_jcom_send, 1, a); } x->container = jamoma_object_getpatcher((t_object*)x); // The following must be deferred because we have to interrogate our box, // and our box is not yet valid until we have finished instantiating the object. // Trying to use a loadbang method instead is also not fully successful (as of Max 5.0.6) defer_low(x, (method)hub_examine_context, 0, 0, 0); } return x; }