/****************************************************************************** * * PROGRAM: vidout.c * * * AUTHOR: Tom Bouril (October 1997) * * DESCRIPTION: Displays live video on in a window, and also outputs * the live video in that windo to an output to be viewed * on another monitor. * * ******************************************************************************/ #include #include #include #include /****************************************************************************** * * FUNCTION: main() * * live video. Graphics are drawn/erased over video by pressing * the left/right mouse buttons. * ******************************************************************************/ void main(int argc, char **argv) { Window win; Display *display; char *progname = argv[0]; int InputWire, screen, mask, videowidth, videoheight; GC gcVideoIn, gcVideoOut; plx_signal *plxsignal = NULL; plx_IO *plxio = NULL; XEvent event; XSetWindowAttributes attr; XVisualInfo *visualInfo; // Open X display server. display = XOpenDisplay(getenv("DISPLAY")); if (display == NULL) { printf("%s: Can't connect to X Server Display: %s\n", progname, XDisplayName(getenv("DISPLAY"))); exit (0); } // Get default screen. screen = (int) XDefaultScreen(display); // Obtain information about the video display. visualInfo = XPlxGetVideoVisual(screen, display); if (TrueColor == visualInfo->class) { // Parallax card has a frame buffer. // Create a colormap for this window. attr.colormap = XCreateColormap(display, XRootWindow(display, screen), visualInfo->visual, AllocNone); } else { // Parallax card is an overlay card. Get colormap used // by the frame buffer. attr.colormap = XDefaultColormap(display, screen); } // Set up colormap so it will work when window depth is different // than root depth. This is done by setting Border Pixel and // Background Pixel. mask = CWBackPixel | CWColormap | CWBorderPixel; attr.background_pixel = BlackPixel(display, DefaultScreen(display)); attr.border_pixel = WhitePixel(display, DefaultScreen(display)); // Create tiny window for Parallax video. Resize it later to // fit exact size of Parallax video. win = XCreateWindow(display, RootWindow(display, screen), 0, 0, 1, 1, 1, (int) visualInfo->depth, InputOutput, visualInfo->visual, mask, &attr); gcVideoIn = XCreateGC(display, win, 0, 0); XFlush(display); // Send all buffered requests to the XServer. // Query Parallax card for hardware config. parameters. plxio = XPlxQueryConfig(display, win, gcVideoIn); // Select wire to be used for video input... // 0 = Composite-In No. 1, // 1 = Composite-In No. 2. InputWire = 0; // Select Parallax video input parameters. XPlxVideoInputSelect(display, win, gcVideoIn, PLX_INPUT_0, PLX_NTSC, (InputWire << 16) | PLX_COMP, PLX_RGB24); // Determine if channel selected by XPlxVideoInputSelect() // contains a valid sync signal. plxsignal = XPlxQueryVideo(display, win, gcVideoIn); while (!plxsignal->sync_ok) { // Loop until XPlxQueryVideo() finds a valid sync signal. puts("Sync Absent - Hook up a video input source."); XPlxSleep(500000); // Wait 0.5 seconds plxsignal = XPlxQueryVideo(display, win, gcVideoIn); } // Obtain video screen's width and height from value returned // by XPlxQueryVideo(). videowidth = plxsignal->w; videoheight = plxsignal->h - plxsignal->b; // Set the tag for the video GC. XPlxVideoTag(display, win, gcVideoIn, PLX_VIDEO); /***********************************************************/ // Video out function calls HERE and in the event loop. gcVideoOut = XCreateGC(display, win, 0, 0); XPlxVideoOutputSelect(display, win, gcVideoOut, PLX_OUTPUT_0, PLX_NTSC, PLX_COMP, PLX_RGB24); /***********************************************************/ // Select event type(s) sent to the video window. ExposureMask enables // Expose events, which occur when any part of the window becomes visible. XSelectInput(display, win, ExposureMask | ButtonPressMask | StructureNotifyMask); // Resize window to fit video image. XResizeWindow(display, win, videowidth, videoheight); // Display the window just created. XMapWindow(display, win); // EVENT LOOP. while (1) { // Get next event in event queue, XNextEvent(display, &event); switch(event.type) { case Expose: // Previously invisible part of window becomes visible. XPlxVideoScaleOutput(display, win, gcVideoOut, 0, 0, videowidth, videoheight, 0, plxsignal->b, videowidth, videoheight); // Previously invisible part of window becomes visible. // Put live video onto window. XPlxVideoLive(display, win, gcVideoIn, 0, plxsignal->b, 0, 0, videowidth, videoheight); break; case ConfigureNotify: // Window has been moved. Rescale the output. XPlxVideoScaleOutput(display, win, gcVideoOut, 0, 0, videowidth, videoheight, 0, plxsignal->b, videowidth, videoheight); break; case ButtonPress: if (event.xbutton.button == 1) { // Left mouse button pressed. } else if (event.xbutton.button == 2) { // Middle mouse button pressed. } else if (event.xbutton.button == 3) { // Right mouse button pressed. } break; default: break; } } // End: while(1) loop. return; }