Programs that use live video need to be notified when the setup or status of the IndigoVideo board changes. This chapter explains how to use either the X Window System or IRIS GL event mechanisms to provide your application with notification of status changes to the IndigoVideo board.
The X and IRIS GL event mechanisms are different, but they serve the same purpose. X event handling methods distinguish between video activity events and parameter change events; IRIS GL event handling methods lump these event classes together as a single pseudodevice. Wherever possible, X event handling should be used rather than IRIS GL event handling to provide greater portability and flexibility. See the IRIS IM Programming Guide, which you can read online using the IRIS InSight viewer, for more details about X event handling versus IRIS GL event handling.
In this chapter:
“IndigoVideo Event Handling Basics” provides an overview of video events and the event-handling routines in the IndigoVideo library.
“X Event Handling” describes some event handling methods provided by the X Window System. To learn more about these methods, and to find out about other methods, consult the references recommended at the beginning of this guide.
“IRIS GL Event Handling” describes pure IRIS GL event handling. Skip this section if you are developing a new IndigoVideo application, and use the methods described in “X Event Handling” instead.
Programs receive video activity events only if they use live video, that is, only if they have executed an svBindWindow() or svBindGLWindow() call.
The four reasons for which the window system generates a video activity event are:
video started
This event indicates that video has started in this window. It is generated when your program succeeds in turning on video using svBindWindow() or svBindGLWindow().
video stopped
This event indicates that video has stopped in this window. It is generated when your program turns off video using svBindWindow() or svBindGLWindow() with an argument of SV_IN_OFF.
video busy
Your program tried to turn on video in this window using svBindWindow() or svBindGLWindow(), but failed because another program had exclusive use of the IndigoVideo board.
video preempted
Your program had video running in this window, but it was preempted by another program calling svBindWindow() or svBindGLWindow().
These event reasons are identified by global variables, listed in Table 21-1.
Table 21-1. Video Activity Event Variable Names
Reason | Variable Name |
|---|---|
Video started | SvVideoStarted |
Video stopped | SvVideoStopped |
Video busy | SvVideoBusy |
Video preempted | SvVideoPreempted |
The five types of parameter change events are:
active attribute change
This event indicates that a process has given up live video input; for example, by exiting, or by calling svBindWindow() or svBindGLWindow() with an argument of SV_IN_OFF.
signal change
This event is generated whenever a process changes the broadcast standard and/or video mode by calling svSetParam(). Changing input sources can also generate this event, as IndigoVideo changes to the default broadcast standard and video mode for the new input source.
video frozen/unfrozen
This event is generated whenever a process freezes or unfreezes video by calling svSetParam().
input source changed
This event is generated whenever a process changes the input source by calling svSetParam().
other parameters changed
This event is generated whenever a process changes any other variable by calling svSetParam().
These event reasons are identified by the global variables listed in Table 21-2.
Table 21-2. Video Parameter Change Event Variable Names
Reason | Variable Name |
|---|---|
Active attribute | SvActiveAttribute |
Signal change | SvEncodingAttribute |
Video frozen/unfrozen | SvFreezeAttribute |
Source change | SvSourceAttribute |
Other parameter change | SvParamChangeAttribute |
To provide X event handling, you must include the appropriate X11 header files, and you must link your program with the X extensions library (-lXext), the X shared library (-lX11_s), and any X toolkits that you use.
Before your program can receive video-related X events, you must call the svSelectXEvents() function.
There are two types of video events, indicated by the following variables:
| SvVideoActivityEventNumber | | ||||||||||||||||
| SvParamChangeEventNumber |
Table 21-3. Encoding Attribute Values
|
Example 21-1 contains a listing of xevents.c, which demonstrates the use of X events. First, an event mask is set up, to establish interest in exposure, key, and video related events. A connection to the X server is established and a video device is opened with the proper window size for the signal being received. The program prints status messages about the events as they occur.
Example 21-1. X Event Handling for IndigoVideo events: xevents.c
/*
* xevents.c
*
* This X11 program displays live video from the IndigoVideo board and shows
* how to decode X11 video-related event information.
*
* Hit the escape or the 'q' keys to exit.
*/
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <svideo.h> /* must be included after <X11/Xlib.h> */
/* We're interested in exposure, key and video-related events */
#define EVENTMASK (ExposureMask|KeyPressMask|StructureNotifyMask)
main(int argc, char *argv[])
{
Window rootwin, win;
Display *display;
XEvent event;
int screen, width, height;
SVhandle V;
long param[2];
/* Open connection to X server */
if ((display = XOpenDisplay(0)) == NULL) {
fprintf(stderr, "%s: cannot connect to X server", argv[0]);
if (getenv("DISPLAY") == NULL)
fprintf(stderr,
", `DISPLAY' environment variable not set.\n");
else
fprintf(stderr, " %s\n", XDisplayName(0));
exit(1);
}
/* Open video device */
if ((V = svOpenVideo()) == NULL) {
svPerror("open");
exit(1);
}
/* Determine the window size from the signal standard */
param[0] = SV_BROADCAST;
svGetParam(V, param, 2);
if (param[1] == SV_PAL) {
width = SV_PAL_XMAX;
height = SV_PAL_YMAX;
} else {
width = SV_NTSC_XMAX;
height = SV_NTSC_YMAX;
}
printf("Default window size: %d by %d\n", width, height);
/* Create appropriate-sized window */
screen = DefaultScreen(display);
rootwin = RootWindow(display, screen);
win = XCreateSimpleWindow(display, rootwin, 100, 100, width, height,
5, BlackPixel(display, screen), BlackPixel(display, screen));
/* Set the window and icon names for the window manager before mapping it */
XStoreName(display, win, "X Video Event Handler");
XSetIconName(display, win, argv[0]);
XSelectInput(display, win, EVENTMASK);
XMapWindow(display, win);
/* Associate video with window */
if (svBindWindow(V, display, win, SV_IN_REPLACE) < 0) {
svPerror("bindwindow");
svCloseVideo(V);
exit(1);
}
/* Receive video-related X events */
svSelectXEvents(V, display);
/* Event loop */
while (1) {
XNextEvent(display, &event);
if (event.type == Expose) {
printf("Expose event\n");
if (svBindWindow(V, display, win, SV_IN_REPLACE) < 0) {
svPerror("bindwindow");
svCloseVideo(V);
exit(1);
}
} else if (event.type == KeyPress) { /* See if we're done */
XKeyEvent *kev = (XKeyEvent *) &event;
KeySym keysym;
char buf[4];
XLookupString(kev, buf, 1, &keysym, 0);
printf("Key pressed: '%c' (%d)\n", buf[0], buf[0]);
if (buf[0] == 'Q' || buf[0] == 'q' || buf[0] == '\033') {
printf("Quitting...\n");
svCloseVideo(V);
exit(0);
}
} else if (event.type == SvVideoActivityEventNumber) {
SVvideoActivityEvent *ev = (SVvideoActivityEvent *) & event;
if (ev->reason == SvVideoStarted) {
printf("Video started\n");
} else if (ev->reason == SvVideoStopped) {
printf("Video stopped\n");
} else if (ev->reason == SvVideoBusy) {
printf("Video busy\n");
} else if (ev->reason == SvVideoPreempted) {
printf("Lost video\n");
} else {
printf("unknown video activity (%d)?\n", ev->reason);
}
} else if (event.type == SvParamChangeEventNumber) {
SVparamChangeEvent *ev = (SVparamChangeEvent *) &event;
if (ev->attribute == SvActiveAttribute) {
/* value always 0 */
if (svBindWindow(V, display, win, SV_IN_REPLACE) < 0) {
svPerror("bindwindow");
svCloseVideo(V);
exit(1);
}
printf("Active attribute: re-bound video\n");
} else if (ev->attribute == SvEncodingAttribute) {
printf("Encoding change: %d = ", ev->value);
if (ev->value == SvNTSCComposite) {
printf("NTSC composite\n");
} else if (ev->value == SvPALComposite) {
printf("PAL composite\n");
} else if (ev->value == SvNTSCSVideo) {
printf("NTSC SVideo\n");
} else if (ev->value == SvPALSVideo) {
printf("PAL SVideo\n");
} else {
printf("?\n");
}
} else if (ev->attribute == SvFreezeAttribute) {
printf("Freeze attribute: %s\n", ev->value ? "on" : "off");
} else if (ev->attribute == SvSourceAttribute) {
printf("Input source change: %d\n", ev->value + 1);
} else if (ev->attribute == SvParamChangeAttribute) {
printf("Parameter changed\n"); /* value always 1 */
} else {
printf("unknown param attribute (%d) ?\n", ev->attribute);
}
}
}
}
|
Handling IRIS GL events is fairly simple. To receive video-related events, use the IRIS GL qdevice() function to queue events from the VIDEO pseudodevice, and use qread() to read the events from the queue.
When you get an event from the event queue using the IRIS GL qread() function, you must pass the function a pointer to a short integer. qread() returns a value indicating the device that generated the event, and fills in the reason for the event in the space pointed to by the argument. In the case of a video event, the reason will correspond to one of the constants listed in Table 21-1 or Table 21-2.
The event loop in Example 21-2 handles video events, printing a message when video is preempted by another process and rebinding the video when it is released by another process.
Example 21-2. Handling Video Events with IRIS GL Routines