Digital Music Programming II: bang
This lab demonstrate how to create an object with one inlet
and one outlet. Compile the following program in CodeWarrior and
try it out in Max/MSP (you should have already done this in the previous lab). For this lab, you should study the
example program and understand the basic components used in creating a
Max external object. Read pages 3-6 of Ich's Tutorial (see the Reading List).
bang.c (code with comments)
#include "ext.h"
typedef struct {
t_object max_data;
void* output;
} MyObject;
void *object_data;
void main (void);
void* create_object (void);
void InputBang (MyObject* mo);
void main(void) {
setup((t_messlist**)&object_data, (method)create_object,
NULL, (short)sizeof(MyObject), NULL, A_NOTHING);
addbang((method)InputBang);
}
void* create_object(void) {
MyObject *mo;
mo = (MyObject*)newobject(object_data);
mo->output = bangout(mo);
return mo;
}
void InputBang(MyObject* mo) {
outlet_bang(mo->output);
}
|
Notice that there are three colored sections in the
bang.c source code. Each color represents
a particular part of the program:
- black -- basic setup
instructions. Included files, global variables, function definitions,
and data type definitions belong in this section of the code.
- red -- initialization functions which
will be called when the object is first created in a patcher window in
Max.
- blue -- behavior functions which
will be run when input messages are received in the object.
More elaborate explanations of each section are given below:
Setup Section
The setup section consists usually of four pieces:
- 1. include files
-
Max object must include the file ext.h.
This file contains all of the functions that Max gives you
to communicate with it. View the file ext.h to get a sense for what is inside of it.
Other header files may be included if needed for defining
other library or system functions.
- 2. object's data structure
-
Your program communicates with Max/MSP via a data structure,
which in this case is:
typedef struct {
t_object max_data;
void* output;
} MyObject;
|
The only requirement for the data structure which you must
follow is that the first variable in the struct must be the
data type t_object. The name of the t_object is not
important and can be anything you give it. In this case the
t_object's variable name is max_data. This variable
holds information that Max uses to communicate between itself and your
object. The t_object variable must come first in your data
struct because Max will communicate only with the t_object
field of your data struct, and will ignore/does not know the rest of
the data struct variables. If the t_object data structure
were not first in the struct, then Max would become confused because
it does have any other information about your data structure. Try
moving it from the first position in the data struct, and see what
Max does when you try to use it.
After the t_object variable comes all of your
variables for storing information about the object. In this case
there is only one variable: void* output. This variable
is used to communicate with the outlet at the bottom of the
object. It is setup in the function create_object.
It is used in this program in the InputBang function
when the Max function outlet_bang is called.
- 3. global variables
-
There is one global data pointer in your object which will
eventually point to storage for your data struct. You do not point to it
directly, but rather allow the setup() function in
main() to do that for you. The name of the pointer
in this case is object_data. This name is arbitrary
and can be anything you like. The name of the pointer must match
the first parameter name in the setup function call in the
main function.
The data type of the pointer
must be void* because it will be used to point to
several data types. In your object, you will use it as a
MyObject pointer. Max will use it as a t_object
and t_messlist pointer.
- 4. function declarations
-
void main (void);
void* create_object (void);
void InputBang (MyObject* mo);
|
The last part of the setup section contains a brief
description of every function in the following sections. The
compiler needs to know about the functions before using them
in the rest of the program. These descriptions of the
functions are called the function declarations.
You are declaring that you will be defining these functions
in the rest of the code. Notice that there are three functions
declared here: main, create_object, and
InputBang. The only function name which is significant
to Max communication is main.
Initialization Section
There are two functions in the initialization section of the
program code: main and create_object. These
functions can come in any order in the program.
The main function's name is special. This is the first
function which will be called when the object is used.
Step 8h. in the previous lab is where you
told CodeWarrior to put this function at the start of the object when
it compiles it, so this function name must match the one you give in
step 8h of the previous lab.
Here is the code for the main function with
numbers to the left of the code indicating the line numbers:
1. void main(void) {
2. setup((t_messlist**)&object_data, (method)create_object,
3. NULL, (short)sizeof(MyObject), NULL, A_NOTHING);
4. addbang((method)InputBang);
5. }
|
The name of the create_object function is arbitrary, but
must match the name of the function pointer given as the second
parameter in the setup function called in main.
The create_object function will create the data storage
for the object and initialize all of its data elements.
Here is the code for the create_object function with
numbers to the left of the code indicating the line numbers:
1 void* create_object(void) {
2 MyObject *mo;
3 mo = (MyObject*)newobject(object_data);
4 mo->output = bangout(mo);
5 return mo;
6 } |
line one of the program indicates that the initialization
function does not need any default parameters when the object is
created. It is possible to have several default parameters which
will be explained in further labs. In this case, there are no
inputs, so the input parameters list is (void).
The create_object function must return a void pointer.
The function will be creating storage space for your object using the
struct you defined in the setup section of the code. Eventually the
setup function call in the main function will be
taking this pointer and assigning it to your global pointer
object_data.
Line 2 of the create_object function creates a temporary
pointer for use inside the function. The pointer must be to your
data struct, which in this case is MyObject. Note that you
can give any name to your data structure other than MyObject.
Line 3 of the create_object function does a very
significant thing: it creates storage space in the computer's memory
to store your object data structured (called MyObject).
Behavior Section
There is one function in the behavior section called
InputBang. This function is called whenever a bang is
received by the object. To tell the compiler that this function
is to be called whenever a bang enters the object, the line
addbang((method)InputBang);
is necessary in the main function.
There is one line in the InputBang function:
outlet_bang(mo->output);
This line sends a bang to the outlet of the object, which is
stored in the variable mo->output.
|