[Prev][Next][Index][Thread]

Huzzah for xqcam!



Huzzah for xqcam!  I convinced it to work for me by not using shared
memory.  Huzzah huzzah!  The patch below, made to the xqcam.c in
qcam-0.3, adds a new compile-time option to disable shared memory
completely, or to make it a command-line option, -S, that defaults to
no use of shared memory.  Oh, shoot -- I just noticed that I didn't
define away the -S option if NO_XSHM is defined, and I'm too lazy to
fix the diffs.



diff -u qcam-0.3.orig/xqcam.c qcam-0.3/xqcam.c
--- qcam-0.3/xqcam.c	Sat Jan  6 14:12:48 1996
+++ qcam-0.3.orig/xqcam.c	Wed Jan 10 16:36:00 1996
@@ -18,11 +18,13 @@
 #include <X11/keysym.h>
 #include <unistd.h>
 
+#ifndef NO_XSHM
 /** MIT Shared Memory Extension for X ************************/
 #include <sys/ipc.h>
 #include <sys/shm.h>
 #include <X11/extensions/XShm.h>
 XShmSegmentInfo SHMInfo;
+#endif
 
 
 /** QuickCam include files */
@@ -41,8 +43,10 @@
 GC gc;
 int screen_num;
 unsigned long white,black;
-int xstarted=0; 
 int quit=0;
+int shm_ckpnt = 0, use_shm = 0, xerror;
+
+static void unmap_shared_mem(void);
 
 /* Set a flag to exit the loop at the end */
 
@@ -51,6 +55,27 @@
   quit=1;
 }
  
+static int error_handler(Display *disp, XErrorEvent *event)
+{
+     xerror = 1;
+
+     return 0;
+}
+
+static void trap_errors(void)
+{
+     xerror = 0;
+     XSetErrorHandler(error_handler);
+}
+
+static int untrap_errors(void)
+{
+     XSync(disp,0);
+     XSetErrorHandler(NULL);
+     return xerror;
+}
+
+
 /** Initialize xwindows, and prepare a shared memory buffer for
  the image.  Returns pointer to shared memory buffer. */
  
@@ -64,6 +89,9 @@
   char *window_name="QuickCam";
   char *icon_name="QuickCam";
   XTextProperty windowName, iconName;
+  int result;
+  int majver, minver;
+  Bool sharedpix;
 
   width=q->width;
   height=q->height;
@@ -106,43 +134,93 @@
   XNextEvent(disp, &ev);
   
   gc = XCreateGC(disp, win, 0, &values);
-  
-  ximage = XShmCreateImage(disp, DefaultVisual(disp, screen_num), 
+
+  unmap_shared_mem();
+
+  if (!shm_ckpnt) atexit(unmap_shared_mem);
+  shm_ckpnt = 1;
+
+#ifndef NO_XSHM
+  if (use_shm && XShmQueryVersion(disp, &majver, &minver, &sharedpix)) {
+    printf("Using shared memory.\n");
+
+    trap_errors();
+    ximage = XShmCreateImage(disp, DefaultVisual(disp, screen_num), 
 			   8, ZPixmap, NULL, &SHMInfo, width, height);
-  if(!ximage) {
-    printf("CreateImage Failed\n");
-    return(NULL);
-  }
- 
-  SHMInfo.shmid=shmget(IPC_PRIVATE, 
-		       ximage->bytes_per_line*ximage->height,
-		       IPC_CREAT|0777);
-
-  if(SHMInfo.shmid < 0) {
-    perror("shmget failed:");
-    return (NULL);
-  }
- 
-  sbuf = ximage->data = SHMInfo.shmaddr = shmat(SHMInfo.shmid, 0, 0);
-  XShmAttach(disp, &SHMInfo);
+    if (untrap_errors()) {
+      unmap_shared_mem();
+      goto shmerror;
+    }
+    if (!ximage) {
+      printf("ShmCreateImage Failed\n");
+      return(NULL);
+    }
+    shm_ckpnt++;
+
+    SHMInfo.shmid=shmget(IPC_PRIVATE, 
+			 ximage->bytes_per_line*ximage->height,
+			 IPC_CREAT|0777);
+
+    if(SHMInfo.shmid < 0) {
+      unmap_shared_mem();
+      goto shmerror;
+    }
+    shm_ckpnt++;
+
+    sbuf = ximage->data = SHMInfo.shmaddr = shmat(SHMInfo.shmid, 0, 0);
+    if (ximage->data == ((char *) -1)) {
+      unmap_shared_mem();
+      goto shmerror;
+    }
+    shm_ckpnt++;
+
+    SHMInfo.readOnly = False;
+
+    trap_errors();
+    result = XShmAttach(disp, &SHMInfo);
+    if (untrap_errors() || !result) {
+      unmap_shared_mem();
+      goto shmerror;
+    }
+    shm_ckpnt++;
+  } else
+#endif
+    {
+
+    shmerror:
+      use_shm = 0;
+
+      sbuf = malloc(width * height);
+      ximage = XCreateImage(disp,
+			    DefaultVisual(disp,screen_num), 8,
+			    ZPixmap, 0, sbuf, width, height,
+			    8, 0);
+      if (ximage == NULL) {
+	printf("CreateImage Failed\n");
+	return(NULL);
+      }
+      shm_ckpnt++;
+    }
+
   signal(SIGHUP, quitprogram); 
   signal(SIGINT, quitprogram);
   signal(SIGQUIT, quitprogram); 
   signal(SIGTERM, quitprogram);
-  xstarted=1;
   return(sbuf);
 }
 
 
-void ExitXWindows(void)
+static void unmap_shared_mem(void)
 {
-  if(xstarted) {
-    XShmDetach(disp, &SHMInfo);
-    if(SHMInfo.shmaddr)
-      shmdt(SHMInfo.shmaddr);
-    if(SHMInfo.shmid > 0)
-      shmctl(SHMInfo.shmid, IPC_RMID, 0);
+#ifndef NO_XSHM
+  if (shm_ckpnt > 4) XShmDetach(disp, &SHMInfo);
+  if (shm_ckpnt > 3) shmdt(SHMInfo.shmaddr);
+  if (shm_ckpnt > 2) shmctl(SHMInfo.shmid, IPC_RMID, 0);
+#endif
+  if (shm_ckpnt > 1) {
+    XDestroyImage(ximage);
   }
+  if (shm_ckpnt > 0) shm_ckpnt = 1;
 }
 
 
@@ -155,6 +233,7 @@
   
   for(i=0; i<64; i++) {
     col.red =col.green = col.blue = i * 1024;
+    col.flags = DoRed | DoGreen | DoBlue;
     if (!XAllocColor(disp, cmap, &col)) {
       fprintf(stderr,"XAllocColor failed on %d\n",i);
     }
@@ -188,7 +267,15 @@
   
   free(scan);
   
-  XShmPutImage(disp, win, gc, ximage, 0,0,0,0,q->width, q->height, False);
+#ifndef NO_XSHM
+     if (use_shm)
+	  XShmPutImage(disp, win, gc, ximage, 0, 0, 0, 0,
+		       q->width, q->height, False);
+     else
+#endif
+	  XPutImage(disp, win, gc, ximage, 0, 0, 0, 0,
+                    q->width, q->height);
+
   XFlush(disp);
 }
 
@@ -207,6 +294,7 @@
   fprintf(stderr,"      -b val     Set brightness\n");
   fprintf(stderr,"      -V         Show version information\n");
   fprintf(stderr,"      -v         Verbose output\n");
+  fprintf(stderr,"      -S         Use shared memory\n");
   fprintf(stderr,"      -C         Use private colormap\n");
   
 
@@ -245,7 +333,7 @@
 
   /* Read command line */
 
-  while((arg=getopt(argc,argv,"hCvx:y:p:b:B:c:w:V"))>0) { 
+  while((arg=getopt(argc,argv,"hCvx:y:p:b:B:c:w:VS"))>0) { 
     switch (arg) {
     case 'x':
       q->width=atoi(optarg);
@@ -283,6 +371,9 @@
     case 'v':
       verbose=1;
       break;
+    case 'S':
+      use_shm=1;
+      break;
     default:
       fprintf(stderr,"%s: Unknown option or error in option\n",argv[0]);
       usage();
@@ -364,7 +455,7 @@
 
   }
 
-  ExitXWindows();
+  unmap_shared_mem();
 
   /* Release IO privileges */
   qc_close(q);

-russ <nelson@crynwr.com>    http://www.crynwr.com/~nelson
Crynwr Software   | Crynwr Software sells packet driver support | PGP ok
11 Grant St.      | +1 315 268 1925 voice | Good government is a contradiction
Potsdam, NY 13676 | +1 315 268 9201 FAX   | in terms.  Ask me for details.