Creating Sequences and Collections


To create a sequence or collection, a task must do the following:

This remainder of this section describes the steps for creating a sequence and a collection. It also lists the tag arguments used to set variables for each object type.

Creating a Sequence

Before creating a sequence, a task should create an event list that contains the event data. The task should also create an interpreter procedure appropriate for event list.

Creating an Event List

An event list is an array of event data structures. The event data structure contains a time value as its first element, followed by as many data elements as the interpreter procedure requires. For example, the data structure shown in Example 1 defines a simple event consisting of a time and a single data value.

Example 1: Simple event structure.

typedef struct
{
     Time    te_TimeStamp;
     uint32  te_Data;
} SimpleEvent;

Example 2 shows an array of simple event structures:

Example 2: Array of simple event structures.

SimpleEvent  TimeData[] =
{
     {   0, 56 },
     { 120, 58 },
     { 480, 54 }
};

Example 3 shows a more complex event structure that could be used for graphics events.

Example 3: Example of a custom graphics event.

typedef struct CustomGraphicsEvent
{
      uint32  cge_Time;
      int32    cge_XPos;    /* Where to draw CCB */
      int32    cge_YPos;
      CCB     *cge_CCB;
} CustomGraphicsEvent;

Creating the Interpreter Procedure

When the Juggler plays a sequence, the sequence sends each event to be played to the interpreter procedure. The interpreter procedure receives two pointers for each event: a pointer to the sequence object sending the event and a pointer to the event data structure. The interpreter procedure can examine the sequence object's variables or the data in the event data structure before playing the event.

Example 4 shows a simple interpreter procedure. This procedure prints the sequence's address, the timestamp stored in the event, and the single data value stored in the event.

Example 4: Simple interpreter procedure.

int32 UserInterpFunc ( Jugglee *Self, SimpleEvent *se )
{
     PRT(("TestEvent: Self = 0x%x, Time = %d, Data = %d\n", Self,
          se->se_TimeStamp, se->se_Data));
     return 0;
}

Not all interpreter procedures play audio events. The interpreter procedure in Example 4 plays print events.

Creating an Instance of a Sequence

create an instance of a sequence, the task uses the CreateObject() function. In Example 5, the task supplies a pointer to the sequence class, and stores the return value, a pointer to the newly created sequence, in the variable seq1.

Example 5: Creating an instance of a sequence.

seq1 = (Sequence *) CreateObject( &SequenceClass );

Note that SequenceClass is defined in the juggler.h header file. You must include juggler.h in code that creates a sequence.

Setting Sequence Variables With a Tag Argument List

When a sequence is created with CreateObject(), its object variables are set to default values. A task can change those values by creating a tag argument list and applying the list to the object.

A task must set the sequence variables that point to or describe the event list or the sequence cannot be played.

A task must set the following tag argument values for a sequence:

Sequence variables can also be set using the following tag arguments:

The task that created a sequence creates a tag argument list for the sequence using an array of the TagArg elements (the same data type used for item tag arguments). Example 6 shows an example of code to create a tag argument list.

Example 6: Creating a tag argument list.

TagArg tags[NTAGS];

tags[0].ta_Tag = JGLR_TAG_CONTEXT;
tags[0].ta_Arg = (TagData)scorecontext;
tags[1].ta_Tag = JGLR_TAG_MUTE;
tags[1].ta_Arg = (TagData)FALSE;
tags[2].ta_Tag = TAG_END;

Applying Tag Argument Values to a Sequence

After creating a tag argument list, the task applies them to the sequence by calling the sequence's SetInfo method. The following macro calls the SetInfo method:

int32 SetObjectInfo( CObject *obj, TagArg *tags )
See SetInfo for details on the SetInfo method.

Reading Tag Argument Values

To find out what the object variable values for an object are, a task creates a tag argument list with each tag argument value set to NULL. It then uses the following macro, which calls an object's GetInfo method to obtain the variable values:

int32 GetObjectInfo( CObject *obj, TagArg *tags )
See GetInfo for details on the GetInfo method.

Creating a Collection

Creating a collection is similar to creating a sequence, but a collection creates an assembly of Juggler objects in its object list instead of a sequence of events in an event list. The object list is part of the collection object. A sequence's event list, which is a data structure outside a sequence object, can be manipulated directly by a task. A collection's object list is created using collection method calls.

Creating Objects for the Collection

A collection must have Juggler objects to include in its object list. Therefore, a task must first create some sequences before it can create a collection. After a task has created one or more collections, it can create new collections that include existing collections.

Creating an Instance of a Collection

To create an instance of the collection class, the task uses the CreateObject() function. The task supplies a pointer to the collection class, and stores the pointer to the newly created collection as shown in this example:

col1 = (Collection *) CreateObject( &CollectionClass );
Note that CollectionClass is defined in the juggler.h header file. You must include juggler.h in code which creates a sequence.

Setting Collection Variables With Tag Argument Values

A collection's object variables can be changed using a list of tag argument values. However, most collections can use the default values. Collections accept the following tag arguments:

After a task has created tag argument values for a collection, it applies them with the SetObjectInfo() macro. To obtain current object variable values from a collection, a task uses the GetObjectInfo() macro.

Adding Objects to the Collection

After a task creates a collection and (if necessary) sets object variables with a tag argument list, it can then add objects to the collection using the collection's Add method. No macro currently exists for the Add method; it must be called directly by using its pointer within the collection, as follows:

*obj->Class->Add( Collection *Self, Jugglee *Child, int32 NumRepeats)
To call the method, *obj must be a pointer to the collection. The call accepts three arguments: *Self, a pointer to the collection accepting the object; *Child, a pointer to the object to be added to the collection; and NumRepeats, an integer specifying the number of times the added object should be repeated in playback.

When the Add method is executed, it adds the specified object to the end of the collection's object list and writes the number of repeats into the object's placeholder. The Add method returns 0 if successful, or a negative value (an error code) if unsuccessful.

The following example adds a sequence with the pointer sequencex to the object list of a collection specified by the pointer collectionx. The sequence is repeated three times during collection playback.

Result = collectionx->Class->Add( collectionx, sequencex, 3 );

Removing Objects From a Collection

To remove an object from a collection, a task uses the collection's RemoveNthFrom method, which is called using this macro:

int32 RemoveNthFromObject( CObject *obj, int32 N )
The call accepts two arguments: *obj, a pointer to the collection from which the object should be removed; and N, an integer that specifies the placeholder in the object list that points to the object to be removed. The first object in the placeholder list is object number 0. For example, the placeholder for the fifth object in an object list is 4.

When RemoveNthFromObject() executes, it removes the specified placeholder from the object list. It does not do anything to the object itself.

If successful, RemoveNthFromObject() returns 0. If unsuccessful, it returns a negative value (an error code).

Examining a Collection's Object List

To see what objects are included in a collection's object list, a task uses the collection's GetNthFrom method, which is called by this macro:

int32 GetNthFromObject( CObject *obj, int32 N, (void**) NthThing )
The call accepts three arguments: *obj, a pointer to the collection whose list is to be checked; N, the number of the placeholder to read in the object list; and NthThing, a pointer to a variable in which to store a pointer.

When it executes, the call looks at the Nth placeholder in the specified collection's object list. It finds the pointer stored in the placeholder and writes the pointer to the NthThing variable.

GetNthFromObject() returns 0 if successful. If unsuccessful, it returns a negative value (an error code).

The first object in the placeholder list is object number 0, the second is 1, and so on.