/** * $Id:$ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * The contents of this file may be used under the terms of either the GNU * General Public License Version 2 or later (the "GPL", see * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or * later (the "BL", see http://www.blender.org/BL/ ) which has to be * bought from the Blender Foundation to become active, in which case the * above mentioned GPL option does not apply. * * The Original Code is Copyright (C) 1997 by Ton Roosendaal, Frank van Beek and Joeri Kassenaar. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ /* * Xinit.c: Does X / gl initialization. * * * Silicon Graphics Inc., June 1994 */ #include /* sigset(), kill() */ #include /* getppid() */ #include "play.h" /* *Sproc include files */ #include #include #include #include XtAppContext appContext; Atom protocol, deleteWindow; /* *Local Prototype definitions */ static void doItWindow (Widget , XEvent *, String *, Cardinal *); static void doIt (); static void handleEvents (); static String fallback_resources[] = { "*frame*shadowType: SHADOW_IN", NULL }; static XtActionsRec actionsTable[] = { {"doItWindow", doItWindow}, }; static char defaultTranslations[] = " : doItWindow() \n\ : doItWindow() \n\ : doItWindow() \n"; static GLXconfig glxConfig [] = { { GLX_NORMAL, GLX_DOUBLE, FALSE }, { GLX_NORMAL, GLX_RGB, TRUE }, { GLX_NORMAL, GLX_ZSIZE, GLX_NOCONFIG }, { 0, 0, 0 } }; /* *Sproc'd processes pids' */ int inputthread = -1; /* *X globals. */ static Widget glw, toplevel, form, frame; int winWidth, winHeight; /* *doIt: Starts all the threads of the application, namely * - video producer * - video consumer (if display = GRAPHICS) * - audio producer (only if Cosmo and display = VIDEO) * */ void doIt ( void ) { playstate.advanceVideo = 1; playstate.advanceAudio = 1; } /* *doItWindow: Callback on pressing key 's' or a * */ void doItWindow (Widget w, XEvent *event, String *params, Cardinal *num_params) { doIt (); } /* *exposeWindow: called during an expose event. Clears the window on expose. * On the first expose event, it calls doIt() to start the * application. It also maps the widget into a video window and * sets up the transfer of data from the camera to the * Indy/Galileo video board. * * NOTE: The first expose event is assumed to happen immediately * with the map notify event (when the window is mapped by the X * server.), which is normally the case. */ void exposeWindow (Widget w, caddr_t client_data, caddr_t call_data) { static int first = 1; Window dummyWin; Display *dpy; int x,y; int ret; VLControlValue val; int stat; pid_t ppid; GC gc; /* X11 graphics context */ XGCValues gcvalue; /* graphics context value */ dpy = XtDisplay(glw); /*Get the origin of the window in coordinate (x,y). */ XTranslateCoordinates(dpy, XtWindow(glw), RootWindow(dpy, DefaultScreen(dpy)), 0, 0, &x, &y, &dummyWin); if (first) { first = 0; /* ** first thing ... clear out whatever is in this window */ gcvalue.foreground = 0; /* better be black ... */ gcvalue.fill_style = FillSolid; gc=XCreateGC(dpy, XtWindow(glw), (GCForeground|GCFillStyle), &gcvalue); XFillRectangle( dpy, XtWindow(glw), gc, 0, 0, val.xyVal.x, val.xyVal.y); if (image.display == GRAPHICS) doIt (); else { val.intVal = XtWindow(glw); vlSetControl(video.svr, video.path, video.drn, VL_WINDOW, &val); /* * Trim off top and bottom three lines */ vlGetControl(video.svr, video.path, video.drn, VL_SIZE, &val); val.xyVal.y -= 6; vlSetControl(video.svr, video.path, video.drn, VL_SIZE, &val); vlGetControl(video.svr, video.path, video.drn, VL_OFFSET, &val); val.xyVal.y -= 3; vlSetControl(video.svr, video.path, video.drn, VL_OFFSET, &val); } /* *Once the window is mapped, vl/gl can begin transfer, thus start the *video application, i.e. streamDecompress() */ if ((ppid = getppid ()) == -1) { perror("Unable to find video thread"); exit (1); } if (unblockproc (ppid) == -1) { perror("Unable to start video thread"); exit(1); } } } /* *initWindow: initializes window. */ void initWindow (Widget w, caddr_t client_data, caddr_t call_data) { GLXwinset (XtDisplay (w), XtWindow (w)); pixmode (PM_TTOB, 1); /*Force top to bottom draw. */ } /* *motionWindow: Callback to track the video display, with the displacement * of the X window on the screen. * *NOTE: This method would work only if you have one video window * on the screen only. * */ void motionWindow (Widget w, caddr_t client_data, caddr_t call_data) { Window dummyWin; Display *dpy; VLControlValue val; dpy = XtDisplay(glw); XTranslateCoordinates(dpy, XtWindow(glw), RootWindow(dpy, DefaultScreen(dpy)), 0, 0, &val.xyVal.x, &val.xyVal.y, &dummyWin); if (image.display == GRAPHICS) return; vlSetControl(video.svr, video.path, video.drn, VL_ORIGIN, &val); } /* *stopAllThreads (): Attempts to gracefully exit all the threads. */ void stopAllThreads () { if (video.timingActive == 1) { video.timingActive = 0; vlDestroyPath(video.svr, video.timingPath); } exit (0); } /* * Initialize X toplevel widget ... * Parse X and User options... * Load resources */ void Xinit(int *argc, char *argv[]) { /* XXX what is "4DgiftsGlx" ? */ Arg args[20]; int n; n=0; XtSetArg(args[n], XmNmwmDecorations, MWM_DECOR_ALL | MWM_DECOR_RESIZEH | MWM_DECOR_MAXIMIZE); n++; XtSetArg(args[n], XmNmwmFunctions, MWM_FUNC_ALL | MWM_FUNC_RESIZE | MWM_FUNC_MAXIMIZE); n++; toplevel = XtAppInitialize(&appContext, "4DgiftsGlx", (XrmOptionDescList)NULL, 0, argc, (String*)argv, fallback_resources, args, n); } /* *Create a window for display */ void Xgo( void ) { Arg args[20]; XtTranslations transTable; int n; VLControlValue val; /* *to get Client message ID and message_type tag for the *quit/close button on the window, to exit the app. */ protocol = XInternAtom (XtDisplay (toplevel), "WM_PROTOCOLS", False); deleteWindow = XInternAtom (XtDisplay (toplevel), "WM_DELETE_WINDOW", False); XtAppAddActions(appContext, actionsTable, XtNumber(actionsTable)); transTable = XtParseTranslationTable(defaultTranslations); n = 0; form = XmCreateForm(toplevel, "form", args, n); XtManageChild(form); n = 0; XtSetArg(args[n], XtNx, 30); n++; XtSetArg(args[n], XtNy, 30); n++; XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++; XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++; XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++; XtSetArg(args[n], XmNleftOffset, 0); n++; XtSetArg(args[n], XmNtopOffset, 0); n++; XtSetArg(args[n], XmNbottomOffset, 0); n++; XtSetArg(args[n], XmNrightOffset, 0); n++; XtSetArg(args[n], XmNshadowThickness, 0); n++; frame = XmCreateFrame (form, "frame", args, n); XtManageChild (frame); n = 0; XtSetArg(args[n], GlxNglxConfig, glxConfig); n++; if (image.display != GRAPHICS) { /* * Trim off top and bottom three lines */ vlGetControl(video.svr, video.path, video.drn, VL_SIZE, &val); winHeight = val.xyVal.y-6; winWidth = val.xyVal.x; } else { winWidth = image.width; if (image.interlacing == DM_IMAGE_NONINTERLACED) winHeight = 2*image.height; else winHeight = image.height; } XtSetArg(args[n], XmNwidth, winWidth); n++; XtSetArg(args[n], XmNheight, winHeight); n++; glw = GlxCreateMDraw(frame, "glwidget", args, n); XtManageChild (glw); XtAddCallback(glw, GlxNginitCallback, (XtCallbackProc)initWindow, 0); XtAddCallback(glw, GlxNexposeCallback,(XtCallbackProc)exposeWindow, 0); if ((image.display == VIDEO_1_FIELD) || (image.display == VIDEO_2_FIELD)) { XtAddEventHandler(toplevel, SubstructureNotifyMask, FALSE, (XtEventHandler)motionWindow, toplevel); } XtOverrideTranslations(glw, transTable); XtRealizeWidget(toplevel); if ((inputthread = sproc ((void (*)(void *))handleEvents, PR_SADDR | PR_BLOCK)) == -1) { fprintf (stderr, "Unable to sproc to handle X events\n"); perror ("sproc"); stopAllThreads (); } streamDecompress(); } static void handleEvents () { XEvent ev; pid_t ppid = -1; /* * Tell kernel to send us SIGHUP when our parent goes * away. */ sigset(SIGHUP, SIG_DFL); prctl(PR_TERMCHILD); for (;;) { XtAppNextEvent(appContext, &ev); switch(ev.type) { case KeyPress: { XKeyEvent *kev = (XKeyEvent *)&ev; KeySym keysym; int buf; XLookupString(kev, (char *)&buf, 1, &keysym, 0); switch (keysym) { case XK_s: /* Single Step */ doIt (); break; case XK_Escape: if (video.timingActive == 1) { video.timingActive = 0; vlDestroyPath(video.svr, video.timingPath); } if ((ppid = getppid ()) == -1) { perror("Unable to find video thread"); } else if (ppid != 1) kill ((pid_t)ppid, SIGTERM); exit(0); break; } } break; case ClientMessage: if (ev.xclient.message_type == protocol && ev.xclient.data.l[0] == deleteWindow) { if (video.timingActive == 1) { video.timingActive = 0; vlDestroyPath(video.svr, video.timingPath); } if ((ppid = getppid ()) == -1) { perror("Unable to find video thread"); } else if (ppid != 1) kill ((pid_t)ppid, SIGTERM); exit(0); } break; default: XtDispatchEvent (&ev); break; } } }