Creating an Item


To create an item, use the CreateItem() function call:

Item CreateItem( int32 ct, const TagArg *p )
CreateItem() takes two arguments. The first, ct, specifies the type of folio in which the item is used and, the type of item within that folio. This value must always be present-it defines the item type. To generate this value, use the MkNodeID() macro (described later), which accepts the folio type and folio item values, and then returns the proper value for CreateItem().

The second argument, p, is a pointer to additional arguments that define the characteristics of the item. These arguments, known as tag arguments, are specific to each item type, and are discussed later in the chapter.

CreateItem() returns the item number of the newly created item or an error code (a negative value) if an error occurs.

Specifying the Item Type

To come up with the item type value for CreateItem(), use MkNodeID():

int32 MkNodeID( Int32 folioNum, Int32 itemTypeNum )
The macro accepts two values: folioNum, which specifies the number of the folio responsible for the item, and itemTypeNum, which specifies the item type for the item being created. This item type number is folio-specific. Both values are set by constants defined within the header file for the appropriate folio. For example, audio.h defines AUDIONODE as the constant that specifies the Audio folio, and lists audio folio item constants such as AUDIO_TEMPLATE_NODE. The Portfolio I/O Model lists the constants for all the folio types and folio items used for each folio. To use those constants, you must be sure to include the .h file of the proper folio. The constants for kernel items, such as message ports or tasks, are in the kernelnodes.h file.

User tasks can't create the following items: drivers, devices, firqs, and timers. These items can only be created by privileged tasks.

Tag Arguments

The values of the tag arguments determine the values of the fields in an item's ItemNode structure. CreateItem() creates an ItemNode structure for a new item. The call reads the values of the tag arguments, interprets them, and writes the corresponding values in the ItemNode fields.

All item types use a standard set of tag arguments defined in item.h. Many items also use additional tag arguments to specify properties that are unique to those item types.

To define values for an item's associated tag arguments, you must first declare an array of type TagArg, which is defined in types.h as follows:

Example 1: Defining values for an item's associated tag argument.

typedef struct TagArg
{
    uint32  ta_Tag;
    TagData ta_Arg;
} TagArg, *TagArgP;

The first field, ta_Tag, is a value that specifies the type of tag argument. The second field, ta_Arg, is a 32-bit value that contains the actual argument.

The standard tag argument types for all items are defined in item.h. They include:

The value for each of these arguments is precisely the same as the value for corresponding fields in ItemNode. When an item is created, these values are simply written into the appropriate ItemNode fields.

You'll find custom tag arguments used for each item type in Portfolio Items, in the 3DO System Programmer's Reference.

When you provide tag arguments for an item, some of the arguments for that item, are required and some are optional. You must provide values for required tag arguments. You must also provide specific values for optional tag arguments, because any values that you do not provide are filled in with default values by the operating system when it creates the item. Defaults aren't guaranteed to be 0, so you must provide the value of 0 if that's what you want set for a tag argument.

If an entire array of tag arguments is optional and you want to use the system default values for all the arguments, then you do not need to declare the TagArg array in your application. Instead, pass NULL as the pointer to the tag arguments argument. When you create a tag arguments array, its general format is:

Example 2: Tag arguments array.

TagArg            TagArrayName[] =
{
    command tag,    value assigned,
    ...    ...
    TAG_END,    0
};

TagArrayName is the name of the array for the tag argument values; command tag is the name of the tag argument, and value assigned is the value assigned to that tag argument. The last tag argument in an array is always called TAG_END, and must be set to 0. This signals the end of the tag argument list.

VarArgs Tag Arguments

Most functions in Portfolio that accept tag arguments have a split personality. The standard version of a function has a parameter of type const TagArg *. A varargs version of a function, which is denoted with the VA suffix, CreateItemVA() for example. The varargs functions offer a much more convenient way to provide the system with tag arguments.

When you use the varargs versions of a function, you do not need to create arrays of TagArg structures to pass to the function. Instead, you can construct a tag list on the stack directly within the function call. Example 3 shows a standard call with TagArg structures:

Example 3: A standard function call with TagArg structures.

{
TagArg tags[3];

    tags[0].ta_Tag = CREATEMSG_TAG_REPLYPORT;
    tags[0].ta_Arg = (void *)replyPort;
    tags[1].ta_Tag = CREATEMSG_TAG_MSG_IS_SMALL;
    tags[1].ta_Arg = 0;
    tags[2].ta_Tag = TAG_END;

    item = CreateItem(MKNODEID(KERNELNODE,MESSAGENODE),tags);
}

Instead of this cumbersome and error prone array, you can build the tag list on the stack using the CreateItemVA() function as shown in Example 4:

Example 4: Using VarArgs to provide tag arguments.

{
  item = CreateItemVA(MKNODEID(KERNELNODE,MESSAGENODE),
                        CREATEMSG_TAG_REPLYPORT,   replyPort,
                        CREATEMSG_TAG_MSG_IS_SMALL, 0,
                        TAG_END);
}

As you can see, this method of providing tag arguments is much easier to read and maintain. There is no casting needed, no array to maintain, and so on.

The Item Number

Once an item is created, the call that creates it returns a positive 32-bit number, which is the unique item number for the new item. A task uses this number whenever it needs to refer to the item in later calls-this item number is important, and should be stashed away in a handy variable. If an error occurs, a negative number is returned.

The Easy Way Out

Now that you've seen the details of creating items using CreateItem(), you should know that most folios provide higher-level convenience calls that do the same thing for commonly used items in a folio, which makes programming much easier. The convenience calls usually take arguments that define the characteristics of the item, translate arguments into the appropriate tag arguments, and then call a lower-level item creation call to create the item. Some of those calls include:

Generally, use a convenience call whenever one is available for the type of item you want to create. You'll find details about these calls in the 3DO System Programmer's Reference and in the chapters of this volume that discuss specific folios.