Monitoring Events Through the Event Broker


Waiting for Event Messages on the Reply Port

After a task is connected as a listener, it can choose either of the following methods for event notification:

The Event Broker Trigger Mechanism

While listeners wait for event notification, the event broker checks the pods once per field for events. The event broker checks occurring events against the trigger mask of each connected listener. If an event matches a set bit in a listener's trigger mask and the listener has the input focus (if required), the event broker sends an event notification to the listener.

When the event broker sends an event notification, it uses its own event messages, which it creates as necessary. After the event broker creates an event message, it copies the information into the message's data block. The information contains a report of the status of each event type that matches a set bit in either the listener of the trigger or capture masks. You can think of the event message data block as a snapshot of the status of all listener-specified events during the field. Only events specified in the trigger mask can trigger the snapshot, but the status of all events specified in either mask is reported in the message.

For example, consider a listener that specifies the "Gun Button Pressed" event type in its trigger mask, and the "Control Button Update" and "Keyboard Update" event types in its capture mask. When any gun attached to the control port is pressed during a field, the event broker prepares an event message for the listener. The event message's data field reports a gun button press and the status of the Control Button Update and Keyboard Update events (indicating whether or not either of those events occurred during the field). If the "gun button pressed" event had not occurred, the event broker would not have sent an event message to the listener, even if keyboard or controller pad button updates occurred, because those event types were in the capture mask but not in the trigger mask.

Retrieving and Replying to Event Messages

After a listener has been notified of an incoming event message from the event broker, it must retrieve the message to read the reported events. To do so, it uses the GetMsg() call. The listener can then read the message's data block (described in Reading an Event Message Data Block below), and either act on the data or store it for later use.

After a listener has processed the event data in an event message, the listener must reply to the event broker. Its reply tells the event broker that the event message is once again free for use. If the listener does not reply to an event message, the event broker assumes that the message was not processed. Each unprocessed event message is one element in the listener's event queue. When the number of unprocessed event messages exceeds the maximum event queue depth, the event broker stops reporting events to the listener. Consequently, the listener loses events until it can process and free up messages in its queue. If the listener asks to be notified of an event queue overflow, the event broker reports it as soon as an event message is free. The update event types (EB_ControlButtonUpdate, EB_MouseUpdate, and so on) are all reported as occurring, because an event queue overflow is considered an update.

To reply to an event message and return it to the event broker, a listener uses the ReplyMsg() call. Always pass NULL as the data pointer, and 0 as the data size parameter to ReplyMsg().

Reading an Event Message Data Block

When a listener receives an event message from the event broker, a pointer to the event data block is in the msg_DataPtr field of the message structure, and the size in bytes of the data block in the msg_DataSize field. To interpret the event data stored in the event message, the listener task must be able to read the data structures used in the data block.

Event Data Block Structure

When the event broker reports events in an event data block, it can report one or more events. Therefore, it must have a flexible data arrangement within the data block to report any number of events. An event data block starts with an EventBrokerHeader structure that specifies the message flavor as EB_EventRecord and follows with one or more EventFrame structures, each containing the report of a single event. (Each event report is called an event frame.) The final structure in the data block is a degenerate EventFrame data structure, which indicates the end of the event frames.

The EventFrame Data Structure

The EventFrame data structure is defined in event.h as follows:

typedef struct EventFrame
{
    uint32            ef_ByteCount;                        /* total size of EventFrame */
    uint32            ef_SystemID;                        /* 3DO machine ID, or 0=local */
    uint32            ef_SystemTimeStamp;                        /* event-count timestamp */
    int32            ef_Submitter;                        /* Item of event sender, or 0 */
    uint8            ef_EventNumber;                        /* event code, [0,255] */
    uint8            ef_PodNumber;                        /* CP pod number, or 0 */
    uint8            ef_PodPosition;                        /* CP position on daisychain, or 0 */
    uint8            ef_GenericPosition;                        /* Nth generic device of type, or 0 */
    uint8            ef_Trigger;                        /* 1 for trigger, 0 for capture */
    uint8            rfu1[3];
    uint32            rfu2;
    uint32            ef_EventData[1];                        /* first word of event data */
} EventFrame;


The Final (Degenerate) Event Frame

The final event frame within an event data block must be a degenerate event frame, which contains the value 0 for the ef_ByteCount field. The rest of the EventFrame data structure cannot be present.

Reading Event Data

The event data array at the end of each full event frame is a data structure that determines the type of device reporting the event. For example, an event occurring on a controller pad uses a structure designed to report control pad data. An event occurring on a mouse uses a structure designed to report mouse data.

Control Pad Data Structure

The data structure that reports control pad data is ControlPadEventData, defined in event.h as follows:

typedef struct ControlPadEventData
{
  uint32 cped_ButtonBits;  /* left justified, zero fill */
} ControlPadEventData;



Mouse and Trackball Data

The data structure used to report mouse and trackball data is MouseEventData, defined in event.h as follows:

typedef struct MouseEventData
{
  uint32    med_ButtonBits;   /* left justified, zero fill */
  int32     med_HorizPosition;
  int32     med_VertPosition;
} MouseEventData;



Light Gun Data Structure

The data structure that reports light gun data is LightGunData, defined in event.h as follows:

typedef struct LightGunEventData
{
  uint32  lged_ButtonBits;      /* left justified, zero fill */
  uint32  lged_Counter;         /*cunter at top-center of hit */
  uint32  lged_LinePulseCount;   /* # of scan lines which were hit */
} LightGunEventData;


Joystick Data

The data structure used to report joystick data is StickEventData, defined in event.h as follows:

typedef struct StickEventData
{
  uint32            stk_ButtonBits;                  /* left justified, zero fill */
  int32            stk_HorizPosition;
  int32            stk_VertPosition;
  int32            stk_DepthPosition;
} StickEventData;


Device State Data Structure

When media is inserted or removed from a device, EVENTNUM_DeviceOnline or EVENTNUM_DeviceOffline respectively, the DeviceStateEventData structure contains the Item number of the device, and the unit number within the device that has gone on-line or off-line. The DeviceStateEventData structure is defined as follows:

typedef struct DeviceStateEventData
{
  Item    dsed_DeviceItem;
  uint32  dsed_DeviceUnit;
} DeviceStateEventData;

Filesystem State Data Structure

When a filesystem is mounted, dismounted, or placed off-line, EVENTNUM_FilesystemMounted, EVENTNUM_FilesystemDismounted, or EVENTNUM_FilesystemOffline, the FileSystemEventData structure contains the Item number of the Filesystem node, and the name of the filesystem which is changing state. The FileSystemEventData structure is defined as follows:

typedef struct FilesystemEventData
{
  Item  fsed_FilesystemItem;
  char  fsed_Name[FILESYSTEM_MAX_NAME_LEN];
} FilesystemEventData;