示例#1
0
t_plugtastic* plugtastic_new()
{
	t_plugtastic*	self = (t_plugtastic*)(object_alloc(sPlugtasticClass));
	t_atom			a;
	t_class*		c;
	t_object*		p;

	c = class_findbyname(_sym_box, _sym_forward);
	if (!c) {
		p = (t_object*)newinstance(_sym_forward, 0, NULL);
		if (p) {
			c = class_findbyname(_sym_box, _sym_forward);
			freeobject(p);
			p = NULL;
		}
	}
	atom_setsym(&a, GENSYM("plugtastic_extra_toggle"));
	self->forward = (t_object*)object_new_typed(CLASS_BOX, _sym_forward, 1, &a);
	
	self->openSplash = &sPlugtasticSplash;
	a.a_type = 0;
	preferences_getatomforkey(GENSYM("plugtastic_splash"), &a);
	if (a.a_type)
		*self->openSplash = atom_getlong(&a);
		
	return self;
}
示例#2
0
MaxErr PlugOutNotify(PlugOutPtr self, SymbolPtr s, SymbolPtr msg, ObjectPtr sender, TTPtr data)
{
	if (sender == self->patcherview) {
		if (msg == _sym_attr_modified) {
			SymbolPtr name = (SymbolPtr)object_method((ObjectPtr)data, _sym_getname);
			if (name == _sym_dirty) {
				qelem_set(self->qelem);
			}
		}
		else if (msg == _sym_free)
			self->patcherview = NULL;
	}
	else {
		if (msg == _sym_free) {
			ObjectPtr	sourceBox;	
			ObjectPtr	sourceObject;
			long		sourceOutlet;
			ObjectPtr	destBox;		
			ObjectPtr	destObject;	
			long		destInlet;

			if (self->patcherview)
				goto out; // if there is no patcherview, then we are freeing the whole thing and can skip this

			#ifdef DEBUG_NOTIFICATIONS
			object_post(SELF, "patch line deleted");
			#endif // DEBUG_NOTIFICATIONS

			// get boxes and inlets
			sourceBox = jpatchline_get_box1(sender);
			if (!sourceBox)
				goto out;
			sourceObject = jbox_get_object(sourceBox);
			sourceOutlet = jpatchline_get_outletnum(sender);
			destBox = jpatchline_get_box2(sender);
			if (!destBox)
				goto out;
			destObject = jbox_get_object(destBox);
			destInlet = jpatchline_get_inletnum(sender);

			// if both boxes are audio graph objects 
			if ( zgetfn(sourceObject, GENSYM("audio.object")) && zgetfn(destObject, GENSYM("audio.object")) ) {
				#ifdef DEBUG_NOTIFICATIONS
				object_post(SELF, "deleting audio graph patchline!");
				#endif // DEBUG_NOTIFICATIONS

				object_method(destObject, GENSYM("audio.drop"), destInlet, sourceObject, sourceOutlet);
			}
		out:		
			;
		}
	}
	return MAX_ERR_NONE;
}
示例#3
0
void PlugOutIterateSetupCallback(PlugOutPtr self, ObjectPtr obj)
{
	method audioSetupMethod = zgetfn(obj, GENSYM("audio.setup"));

	if (audioSetupMethod)
		audioSetupMethod(obj);
}
示例#4
0
TTErr PlugOutSetup(PlugOutPtr self)
{
	Atom a[2];
	
	atom_setobj(a+0, ObjectPtr(self->audioGraphObject));
	atom_setlong(a+1, 0);
	outlet_anything(self->audioGraphOutlet, GENSYM("audio.connect"), 2, a);
	return kTTErrNone;
}
示例#5
0
void PlugOutIterateResetCallback(PlugOutPtr self, ObjectPtr obj)
{
	TTUInt32	vectorSize;
	method		audioResetMethod = zgetfn(obj, GENSYM("audio.reset"));

	if (audioResetMethod) {
		self->audioGraphObject->getUnitGenerator()->getAttributeValue(TT("vectorSize"), vectorSize);
		audioResetMethod(obj, vectorSize);
	}
}
示例#6
0
TTErr OpDropAudio(OpPtr self, long inletNumber, ObjectPtr sourceMaxObject, long sourceOutletNumber)
{
	TTAudioGraphObjectPtr	sourceObject = NULL;
	TTErr 					err;
	
	if (inletNumber == 1)
		self->audioGraphObject->setAttributeValue(TT("numAudioInlets"), 1);
	err = (TTErr)int(object_method(sourceMaxObject, GENSYM("audio.object"), &sourceObject));
	if (self->audioGraphObject && sourceObject && !err)
		err = self->audioGraphObject->dropAudio(sourceObject, sourceOutletNumber, inletNumber);	
	return err;
}
示例#7
0
PlugOutPtr PlugOutNew(SymbolPtr msg, AtomCount argc, AtomPtr argv)
{
    PlugOutPtr	self = PlugOutPtr(object_alloc(sPlugOutClass));
	TTValue		v;
	TTErr		err;

    if (self) {
		v.setSize(2);
		v.set(0, TT("plugtastic.output"));
		v.set(1, 2);
		err = TTObjectBaseInstantiate(TT("audio.object"), (TTObjectBasePtr*)&self->audioGraphObject, v);

		v = TTPtr(self->audioGraphObject);

		object_obex_store((void*)self, _sym_dumpout, (object*)outlet_new(self, NULL));
		self->audioGraphOutlet = outlet_new(self, "audio.connect");
		self->qelem = qelem_new(self, (method)PlugOutQFn);
		
		object_obex_lookup(self, GENSYM("#P"), &self->patcher);
		self->pluginName = object_attr_getsym(self->patcher, _sym_name);
		self->pluginVersion = GENSYM("1.0");
		self->pluginVersionHex = GENSYM("0x00010000");
		self->pluginManufacturer = GENSYM("Plugtastic");
		self->pluginManufacturerCode = GENSYM("74Ob");
		self->pluginID = GENSYM("ftmp");
		
		attr_args_process(self, argc, argv);
	}
	return self;
}
示例#8
0
TTErr PlugOutBuildGraph(PlugOutPtr self)
{
	MaxErr					err;
	ObjectPtr				patcher = NULL;
	ObjectPtr				parent = NULL;
	long					result = 0;
	
	err = object_obex_lookup(self, GENSYM("#P"), &patcher);
	
	// first find the top-level patcher
	err = object_obex_lookup(self, GENSYM("#P"), &patcher);
	parent = patcher;
	while (parent) {
		patcher = parent;
		parent = object_attr_getobj(patcher, _sym_parentpatcher);
	}
	
	//object_method(patcher, gensym("iterate"), (method)PlugOutIterateResetCallback, self, PI_DEEP, &result);
	object_method(patcher, GENSYM("iterate"), (method)PlugOutIterateSetupCallback, self, PI_DEEP, &result);
	
	return kTTErrNone;
}
示例#9
0
// Qelem function, which clumps together dirty notifications before making the new connections
void PlugOutQFn(PlugOutPtr self)
{
	t_atom result;

	#ifdef DEBUG_NOTIFICATIONS
	object_post(SELF, "patcher dirtied");
	#endif // DEBUG_NOTIFICATIONS

	object_method(self->patcher, GENSYM("iterate"), (method)PlugOutIterateSetupCallback, self, PI_DEEP, &result);

	// attach to all of the patch cords so we will know if one is deleted
	// we are not trying to detach first -- hopefully this is okay and multiple attachments will be filtered (?)
	PlugOutAttachToPatchlinesForPatcher(self, self->patcher);
}
示例#10
0
MaxErr PlugOutSetVersion(PlugOutPtr self, void* attr, AtomCount argc, AtomPtr argv)
{
	if (argc) {
		char	str[16];
		int		major = 0;
		int		minor = 0;
		int		revision = 0;
		
		self->pluginVersion = atom_getsym(argv);
		sscanf(self->pluginVersion->s_name, "%i.%i.%i", &major, &minor, &revision);
		snprintf(str, 16, "0x00%02i%02i%02i", major, minor, revision);
		self->pluginVersionHex = GENSYM(str);
	}
	return MAX_ERR_NONE;
}
示例#11
0
void plug_setup_db(void)
{
	t_atom a[4];
	
	// This ugly hack not needed as of Max 5.1.7
	//	if (sDeferCount) {
	//		sDeferCount--;
	//		defer_low(sMaxObject, (method)plug_setup_db, NULL, 0, NULL);
	//		return;
	//	}
	
	// OBJECTS
	
	plug_alias_register("adc≈",					"jcom.adc≈",				"Audio",			"Audio input");
	plug_alias_register("adsr≈",				"jcom.adsr≈",				"Audio",			"ADSR Envelope Generator");
	plug_alias_register("audiounit≈",			"jcom.audiounit≈",			"Audio",			"Host an AudioUnit plug-in");
	plug_alias_register("dac≈",					"jcom.dac≈",				"Audio",			"Audio output");
	plug_alias_register("dcblocker≈",			"jcom.dcblocker≈",			"Audio",			"Eliminate DC offsets");
	plug_alias_register("degrade≈",				"jcom.degrade≈",			"Audio",			"Distortion effect");
	plug_alias_register("delay≈",				"jcom.delay≈",				"Audio",			"Delay audio by a specified time");
	plug_alias_register("fft≈",					"jcom.fft≈",				"Audio",			"Convert a signal into the frequency domain");
	plug_alias_register("filter≈",				"jcom.filter≈",				"Audio",			"Swiss-Army knife of audio filters");
	plug_alias_register("gain≈",				"jcom.gain≈",				"Audio",			"Amplify or attenuate audio");
	plug_alias_register("hilbert≈",				"jcom.hilbert≈",			"Audio",			"Phase quadrature filter");
	plug_alias_register("info≈",				"jcom.info≈",				"Audio",			"Get properties of an audio signal");
	plug_alias_register("join≈",				"jcom.join≈",				"Audio",			"Join multiple signals together into a single signal");
	plug_alias_register("limiter≈",				"jcom.limiter≈",			"Audio",			"Lookahead dynamics processor");
	plug_alias_register("matrix≈",				"jcom.matrix≈",				"Audio",			"Mix and route channels within a signal");
	plug_alias_register("matrixmixer≈",			"jcom.matrixmixer≈",		"Audio",			"Mix and route multiple channels with each other");
	plug_alias_register("noise≈",				"jcom.noise≈",				"Audio",			"Generate various kinds of noise");
	plug_alias_register("op≈",					"jcom.op≈",					"Audio",			"Perform mathematical operations");
	plug_alias_register("overdrive≈",			"jcom.overdrive≈",			"Audio",			"Saturation effect");
	plug_alias_register("pack≈",				"jcom.pack≈",				"Audio",			"Bridge from MSP audio signals to Plugtastic");
	plug_alias_register("phasor≈",				"jcom.phasor≈",				"Audio",			"Oscillator ramping linearly from 0.0 to 1.0");
	plug_alias_register("pulsesub≈",			"jcom.pulsesub≈",			"Audio",			"Apply a cyclic ADSR envelope onto an input signal");
	plug_alias_register("resample≈",			"jcom.resample≈",			"Audio",			"Up/Downsample an audio signal");
	plug_alias_register("sig≈",					"jcom.sig≈",				"Audio",			"Create a signal from a constant value");
	plug_alias_register("soundfile.player≈",	"jcom.soundfile.player≈",	"Audio",			"Play a Soundfile");
	plug_alias_register("soundfile.recorder≈",	"jcom.soundfile.recorder≈",	"Audio",			"Record a Soundfile");
	plug_alias_register("split≈",				"jcom.split≈",				"Audio",			"Break a multichannel audio signal into smaller signals");
	plug_alias_register("unpack≈",				"jcom.unpack≈",				"Audio",			"Bridge from Plugtastic to MSP audio signals");
	plug_alias_register("wavetable≈",			"jcom.wavetable≈",			"Audio",			"Wavetable oscillator with several waveform options");
	plug_alias_register("window≈",				"jcom.window≈",				"Audio",			"Generate/Apply a window function for signal vector");

	plug_alias_register("in≈",					"plug.in≈",					"Environment",		"Audio input from the plug-in host environment");
	plug_alias_register("out≈",					"plug.out≈",				"Environment",		"Audio output to the plug-in host environment");
	plug_alias_register("parameter#",			"plug.parameter#",			"Environment",		"Define a parameter to be controlled in the host environment");

	plug_alias_register("append#",				"jcom.append#",				"Control",			"Add/Replace named data in a dictionary");
	plug_alias_register("dataspace#",			"jcom.dataspace#",			"Control",			"Convert values expressed in one unit into another unit.");
	plug_alias_register("iter#",				"jcom.iter#",				"Control",			"Output all key/value sets from a dictionary to Max messages.");
	plug_alias_register("log#",					"jcom.log#",				"Control",			"Print input to the Max window.");
	plug_alias_register("midi.in#",				"jcom.midi.in#",			"Control",			"MIDI Input from a device, or from the plug-in host environment");
	plug_alias_register("midi.out#",			"jcom.midi.out#",			"Control",			"MIDI Output to a device");
	plug_alias_register("midi.filter#",			"jcom.midi.filter#",		"Control",			"Parse raw MIDI events");
	plug_alias_register("midi.format#",			"jcom.midi.format#",		"Control",			"Format dictionaries into raw MIDI events");
	plug_alias_register("op#",					"jcom.op#",					"Control",			"Perform mathematical operations on a dictionary");
	plug_alias_register("pack#",				"jcom.pack#",				"Control",			"Convert native Max data into a Plugtastic dictionary");
	plug_alias_register("unpack#",				"jcom.unpack#",				"Control",			"Convert a Plugtastic dictionary into native Max data");

	// backwards compatibility
	//plug_alias_register("parameter!",			"plug.parameter#",			"Environment",		"Define a parameter to be controlled in the host environment");
	//plug_alias_register("append!",				"jcom.append#",				"Control",			"Add/Replace named data in a dictionary");
	//plug_alias_register("op!",					"jcom.op#",					"Control",			"Perform mathematical operations on a dictionary");
	//plug_alias_register("pack!",				"jcom.pack#",				"Control",			"Convert native Max data into a Plugtastic dictionary");
	//plug_alias_register("unpack!",				"jcom.unpack#",				"Control",			"Convert a Plugtastic dictionary into native Max data");

	// CLIPPINGS
	
	atom_setsym(a+1, _sym_clipping);
	atom_setsym(a+2, _sym_tag);

	atom_setsym(a+3, GENSYM("Plugtastic"));
	atom_setsym(a+0, GENSYM("plug.input"));
	object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL);
	atom_setsym(a+0, GENSYM("plug.output"));
	object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL);
	atom_setsym(a+0, GENSYM("plug.param"));
	object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL);
	
	atom_setsym(a+3, GENSYM("Environment"));	
	atom_setsym(a+0, GENSYM("plug.input"));
	object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL);
	atom_setsym(a+0, GENSYM("plug.output"));
	object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL);
	atom_setsym(a+0, GENSYM("plug.param"));
	object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL);
	
	atom_setsym(a+2, _sym_description);

	atom_setsym(a+0, GENSYM("plug.input"));
	atom_setsym(a+3, GENSYM("Input stage for developing a plug-in"));
	object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL);
	
	atom_setsym(a+0, GENSYM("plug.output"));
	atom_setsym(a+3, GENSYM("Output stage for developing a plug-in"));
	object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL);
	
	atom_setsym(a+0, GENSYM("plug.param"));
	atom_setsym(a+3, GENSYM("Expanded parameter with a number box"));
	object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL);
	
	// EXAMPLES
	
	atom_setsym(a+1, _sym_patcher);
	atom_setsym(a+2, _sym_tag);
	
	atom_setsym(a+3, GENSYM("Plugtastic"));
	atom_setsym(a+0, GENSYM("My Plugtastic Adventure"));
	object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL);
	
	atom_setsym(a+3, GENSYM("Example"));	
	atom_setsym(a+0, GENSYM("My Plugtastic Adventure"));
	object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL);
}
示例#12
0
void plug_alias_register(const char* plugtastic_name, const char* original_name, const char* category, const char* description)
{
	t_atom		a[4];
	TTString	str = "Plugtastic ";
	
	// create alias
	object_method(sMaxObject, ps_objectfile, GENSYM(plugtastic_name), GENSYM(original_name), GENSYM(original_name));

	// add to autocompletion
	atom_setsym(a, GENSYM(plugtastic_name));
	object_method_typed(sMaxObject, ps_db_object_addinternal, 1, a, NULL);
	
	// add to object list
	str += category;
	object_method(sMaxObject, ps_oblist, GENSYM(str.c_str()), GENSYM(plugtastic_name));	
	
	atom_setsym(a+0, GENSYM(plugtastic_name));
	atom_setsym(a+1, _sym_object);
	atom_setsym(a+2, _sym_tag);
	atom_setsym(a+3, GENSYM("Plugtastic"));
	object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL);
	
	atom_setsym(a+0, GENSYM(plugtastic_name));
	atom_setsym(a+1, _sym_object);
	atom_setsym(a+2, _sym_tag);
	atom_setsym(a+3, GENSYM(category));
	object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL);
	
	atom_setsym(a+0, GENSYM(plugtastic_name));
	atom_setsym(a+1, _sym_object);
	atom_setsym(a+2, _sym_description);
	atom_setsym(a+3, GENSYM(description));
	object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL);
}
示例#13
0
int main(void)
{
	common_symbols_init();
	PlugtasticInit();

	plugtastic_classinit();
	sPlugtasticObject = (t_object*)plugtastic_new();
	ps_plugtastic = GENSYM("plugtastic");
	ps_plugtastic->s_thing = sPlugtasticObject;

	sMaxObject = _sym_max->s_thing;
	ps_objectfile				= GENSYM("objectfile");
	ps_db_object_addinternal	= GENSYM("db.object_addinternal");
	ps_oblist					= GENSYM("oblist");
	ps_db_addmetadata			= GENSYM("db.addmetadata");
	
	//defer_low(sMaxObject, (method)plug_setup_db, NULL, 0, NULL);
	plug_setup_db();
	
	post("Plugtastic                                            Version %s | 74Objects.com", PLUGTASTIC_VERSION);
	

	// This tells Max 5.0.6 and higher that we want the patcher files to be saved such that they are sorted.
	// Having the saved this way makes our SVN diffs much more meaningful.
	object_method_long(sMaxObject, GENSYM("sortpatcherdictonsave"), 1, NULL);
	
	// This tells Max 4.5.7 and higher to take any posts to the Max window and also make the
	// post to the system console, which greatly aids in debugging problems and crashes
	object_method_long(sMaxObject, GENSYM("setmirrortoconsole"), 1, NULL);
	
	
	// OPEN THE SPLASH
	
	if (sPlugtasticSplash) {
		char			name[MAX_FILENAME_CHARS];
		short			path = 0;
		long			type = 0;
		long			typelist[2] = {'JSON', 'TEXT'};
		short			err;
		t_dictionary*	d;
		t_object*		p;
		t_atom			a[2];
		
		strncpy_zero(name, "Plugtastic.maxpat", MAX_FILENAME_CHARS);
		err = locatefile_extended(name, &path, &type, typelist, 2);
		dictionary_read(name, path, &d);
		
		atom_setobj(a, d);
		p = (t_object*)object_new_typed(_sym_nobox, _sym_jpatcher, 1, a);
		object_attr_setlong(p, _sym_locked, 1);			// start out locked
		object_attr_setchar(p, _sym_enablehscroll, 0);		// turn off scroll bars
		object_attr_setchar(p, _sym_enablevscroll, 0);
		object_attr_setchar(p, _sym_toolbarvisible, 0);	
		object_attr_setsym(p, _sym_title, gensym("Welcome to Plugtastic"));		
		object_attr_setparse(p, _sym_rect, "271 170 799 489");
		object_attr_setparse(p, _sym_defrect, "271 170 799 489");

		object_method(p, _sym_vis);	// "vis" happens immediately, "front" is defer_lowed
		object_method(p, _sym_loadbang);

//		object_method_parse(p, _sym_window, "constrain 799 489 799 489", NULL);
		object_method_parse(p, _sym_window, "flags nozoom", NULL);
		object_method_parse(p, _sym_window, "flags nogrow", NULL);
		object_method_parse(p, _sym_window, "exec", NULL);
	}	
	
	
	return 0;
}
示例#14
0
int script_lua_atoms_from_args(lua_State *L, int index_start, t_atom **args)
{
	int i, n;
	int num_args = 0;
	
	n = lua_gettop(L);
	
	//count the number of arguments
	for(i=index_start; i <= n; i++) {
		int type = lua_type(L, i);
		
		switch(type)
		{
			case LUA_TTABLE:
					num_args += luaL_getn(L, i);
					break;
			
			case LUA_TSTRING:
			case LUA_TNUMBER:
			case LUA_TUSERDATA:
					num_args++;
					break;

			default:
					break;
		}
	}
	
	*args = (t_atom *)jit_getbytes(num_args*sizeof(t_atom));

	{
		int arg_index=0;	//index of current argument
		
		//iterate over the number of stack elements
		for(i=index_start; i <= n; i++) {
			int type = lua_type(L, i);
			
			switch(type)
			{
				case LUA_TSTRING:
						jit_atom_setsym(*args+arg_index, GENSYM(lua_tostring(L, i)));
						arg_index++;
						break;
					
				case LUA_TNUMBER:
						jit_atom_setfloat(*args+arg_index, lua_tonumber(L, i));
						arg_index++;
						break;
				
				case LUA_TUSERDATA:
						(*args+arg_index)->a_w.w_obj = toJitobj(L, i);
						(*args+arg_index)->a_type = A_OBJ;
						arg_index++;
						break;
				
				case LUA_TTABLE:
						{
							int j;
							int table_type;
							
							//doesn't account for tables of userdata yet
							for(j=1; j <= luaL_getn(L, i); j++) {
								lua_rawgeti(L, i, j);
								table_type = lua_type(L, -1);
								
								switch(table_type)
								{
									case LUA_TSTRING:
											jit_atom_setsym(*args+arg_index, GENSYM(lua_tostring(L, -1)));
											arg_index++;
											break;
											
									case LUA_TNUMBER:
											jit_atom_setfloat(*args+arg_index, lua_tonumber(L, -1));
											arg_index++;
											break;
									
									case LUA_TUSERDATA:
											(*args+arg_index)->a_w.w_obj = toJitobj(L, -1);
											(*args+arg_index)->a_type = A_OBJ;
											arg_index++;
											break;
											
									default:
											break;
								}
								
							}
						}
						
						break;
						
				default:
					break;
			}
		}
	}
	
	return num_args;
}