// // Modified By: Craig Stuart Sapp // Creation Date: Fri Feb 28 18:41:42 PST 2003 // Last Modified: Sun Mar 9 12:16:33 PST 2003 // Filename: floatmetro.c // Source: David Zicarelli: Writing External Objects for Max // 4.0 and MSP 2.0, revision 11 (2001), pages 55-56 // Web Address: http://peabody.sapp.org/class/dmp2/lab/floatmetro/floatmetro.c // Syntax: C; Max4/MSP2 External Object; CodeWarrior 6.0 // OS: Mac OS 9; PPC // // Description: Demonstration of event scheduling with a floating // point number input into the metro object. // #include "ext.h" typedef struct { t_object max_data; // must always be the first field; used by Max void* clock; // clock data structure pointer float duration; // duration between output bangs void* output; // pointer to outlet, need one for each outlet } MyObject; void* object_data; // pointer to data for object (created in setup()); // function declarations: void main (void); void* create_object (float defaultDuration); void destroy_object (MyObject *mo); void InputBang (MyObject* mo); void InputInt (MyObject* mo, long value); void InputDuration (MyObject* mo, float value); void ClockTick (MyObject *mo); void MessageStop (MyObject *mo); void MessageStart (MyObject *mo); ////////////////////////////////////////////////////////////////////////// // // Initialization functions: // void main(void) { setup((t_messlist**)&object_data, (method)create_object, (method)destroy_object, (short)sizeof(MyObject), NULL, A_DEFFLOAT, A_NOTHING); addbang((method)InputBang); addint((method)InputInt); addftx((method)InputDuration, 1); addmess((method)MessageStop, "stop", A_NOTHING); addmess((method)MessageStart, "start", A_NOTHING); } ////////////////////////////// // // create_object -- // void* create_object(float defaultInterval) { MyObject *mo = (MyObject*)newobject(object_data); mo->clock = clock_new(mo, (method)ClockTick); if (defaultInterval < 20.0) { defaultInterval = 100.0; } mo->duration = defaultInterval; mo->output = bangout(mo); floatin(mo, 1); return mo; } ////////////////////////////// // // destroy_object -- what to do when the object is deleted from the patch. // In this case, you must free the clock object. // void destroy_object(MyObject *mo) { freeobject((t_object*)mo->clock); } ////////////////////////////////////////////////////////////////////////// // // Behavior functions: // ////////////////////////////// // // InputInt -- turn on the metronome when a non-zero positive value is // received, or turn it off when a zero or a negative value is received. // void InputInt(MyObject* mo, long value) { if (value > 0) { MessageStart(mo); } else { MessageStop(mo); } } ////////////////////////////// // // InputBang -- What to do when a bang message arrives into the object: // if a bang is received from the object input, then send out a bang. // void InputBang(MyObject* mo) { MessageStart(mo); } ////////////////////////////// // // InputDuration -- // void InputDuration(MyObject* mo, float value) { if (value < 1.0) { value = 1.0; } mo->duration = value; } ////////////////////////////// // // ClockTick -- what to do when the event scheduler is ready. // void ClockTick(MyObject *mo) { clock_fdelay(mo->clock, mo->duration); // schedule another metronome tick outlet_bang(mo->output); // send out a bang message } ////////////////////////////// // // MessageStop -- what to do when a "stop" message arrives // void MessageStop(MyObject *mo) { clock_unset(mo->clock); } ////////////////////////////// // // MessageStart -- what to do when a "start" message arrives // void MessageStart(MyObject *mo) { clock_fdelay(mo->clock, 0.0); }