Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * (c) 1998-2002 Gerd Knorr
  3  *
  4  *    capture a image, compress as jpeg and upload to the webserver
  5  *    using the ftp utility or ssh
  6  *
  7  */
  8 
  9 #include <stdio.h>
 10 #include <stdlib.h>
 11 #include <string.h>
 12 #include <unistd.h>
 13 #include <errno.h>
 14 #include <fcntl.h>
 15 #include <limits.h>
 16 #include <pthread.h>
 17 #include <math.h>
 18 #include <sys/time.h>
 19 #include <sys/mman.h>
 20 #include <sys/ioctl.h>
 21 #include <sys/stat.h>
 22 
 23 #include "grab-ng.h"
 24 #include "jpeglib.h"
 25 #include "ftp.h"
 26 #include "parseconfig.h"
 27 #include "list.h"
 28 
 29 
 30 /* ---------------------------------------------------------------------- */
 31 /* configuration                                                          */
 32 
 33 int   daemonize = 0;
 34 char  *archive  = NULL;
 35 char  *tmpdir;
 36 struct list_head connections;
 37 
 38 char  *grab_text   = "webcam %Y-%m-%d %H:%M:%S"; /* strftime */
 39 char  *grab_infofile = NULL;
 40 int   grab_width  = 320;
 41 int   grab_height = 240;
 42 int   grab_delay  = 3;
 43 int   grab_wait   = 0;
 44 int   grab_rotate = 0;
 45 int   grab_top    = -1;
 46 int   grab_left   = -1;
 47 int   grab_bottom = -1;
 48 int   grab_right  = -1;
 49 int   grab_quality= 75;
 50 int   grab_trigger= 0;
 51 int   grab_times  = -1;
 52 int   grab_fg_r   = 255;
 53 int   grab_fg_g   = 255;
 54 int   grab_fg_b   = 255;
 55 int   grab_bg_r   = -1;
 56 int   grab_bg_g   = -1;
 57 int   grab_bg_b   = -1;
 58 char  *grab_input = NULL;
 59 char  *grab_norm  = NULL;
 60 
 61 /* ---------------------------------------------------------------------- */
 62 /* jpeg stuff                                                             */
 63 
 64 static int
 65 write_file(int fd, unsigned char *data, int width, int height)
 66 {
 67     struct jpeg_compress_struct cinfo;
 68     struct jpeg_error_mgr jerr;
 69     FILE *fp;
 70     int i;
 71     unsigned char *line;
 72 
 73     fp = fdopen(fd,"w");
 74     cinfo.err = jpeg_std_error(&jerr);
 75     jpeg_create_compress(&cinfo);
 76     jpeg_stdio_dest(&cinfo, fp);
 77     cinfo.image_width = width;
 78     cinfo.image_height = height;
 79     cinfo.input_components = 3;
 80     cinfo.in_color_space = JCS_RGB;
 81     jpeg_set_defaults(&cinfo);
 82     jpeg_set_quality(&cinfo, grab_quality, TRUE);
 83     jpeg_start_compress(&cinfo, TRUE);
 84 
 85     for (i = 0, line = data; i < height; i++, line += width*3)
 86         jpeg_write_scanlines(&cinfo, &line, 1);
 87     
 88     jpeg_finish_compress(&(cinfo));
 89     jpeg_destroy_compress(&(cinfo));
 90     fclose(fp);
 91 
 92     return 0;
 93 }
 94 
 95 /* ---------------------------------------------------------------------- */
 96 /* image transfer                                                         */
 97 
 98 struct xfer_ops;
 99 
100 struct xfer_state {
101     char              *name;
102     struct list_head  list;
103 
104     /* xfer options */
105     char              *host;
106     char              *user;
107     char              *pass;
108     char              *dir;
109     char              *file;
110     char              *tmpfile;
111     int               debug;
112 
113     /* ftp options */
114     int               passive,autologin;
115 
116     /* function pointers + private date */
117     struct xfer_ops   *ops;
118     void              *data;
119 };
120 
121 struct xfer_ops {
122     int  (*open)(struct xfer_state*);
123     void (*info)(struct xfer_state*);
124     int  (*xfer)(struct xfer_state*, char *image, int width, int height);
125     void (*close)(struct xfer_state*);
126 };
127 
128 static int ftp_open(struct xfer_state *s)
129 {
130     s->data = ftp_init(s->name,s->autologin,s->passive,s->debug);
131     ftp_connect(s->data,s->host,s->user,s->pass,s->dir);
132     return 0;
133 }
134 
135 static void ftp_info(struct xfer_state *s)
136 {
137     fprintf(stderr,"ftp config [%s]:\n  %s@%s:%s\n  %s => %s\n",
138             s->name,s->user,s->host,s->dir,s->tmpfile,s->file);
139 }
140 
141 static int ftp_xfer(struct xfer_state *s, char *image, int width, int height)
142 {
143     char filename[1024];
144     int fh;
145     
146     sprintf(filename,"%s/webcamXXXXXX",tmpdir);
147     if (-1 == (fh = mkstemp(filename))) {
148         perror("mkstemp");
149         exit(1);
150     }
151     write_file(fh, image, width, height);
152     if (ftp_connected(s->data))
153         ftp_connect(s->data,s->host,s->user,s->pass,s->dir);
154     ftp_upload(s->data,filename,s->file,s->tmpfile);
155     unlink(filename);
156     return 0;
157 }
158 
159 static void ftp_close(struct xfer_state *s)
160 {
161     ftp_fini(s->data);
162 }
163 
164 static struct xfer_ops ftp_ops = {
165     open:  ftp_open,
166     info:  ftp_info,
167     xfer:  ftp_xfer,
168     close: ftp_close,
169 };
170 
171 static int ssh_open(struct xfer_state *s)
172 {
173     s->data = malloc(strlen(s->user)+strlen(s->host)+strlen(s->tmpfile)*2+
174                      strlen(s->dir)+strlen(s->file)+32);
175     sprintf(s->data, "ssh %s@%s \"cat >%s && mv %s %s/%s\"",
176             s->user,s->host,s->tmpfile,s->tmpfile,s->dir,s->file);
177     return 0;
178 }
179 
180 static void ssh_info(struct xfer_state *s)
181 {
182     fprintf(stderr,"ssh config [%s]:\n  %s@%s:%s\n  %s => %s\n",
183             s->name,s->user,s->host,s->dir,s->tmpfile,s->file);
184 }
185 
186 static int ssh_xfer(struct xfer_state *s, char *image, int width, int height)
187 {
188     char filename[1024];
189     char *cmd = s->data;
190     unsigned char buf[4096];
191     FILE *sshp, *imgdata;
192     int len,fh;
193     
194     sprintf(filename,"%s/webcamXXXXXX",tmpdir);
195     if (-1 == (fh = mkstemp(filename))) {
196         perror("mkstemp");
197         exit(1);
198     }
199     write_file(fh, image, width, height);
200 
201     if ((sshp=popen(cmd, "w")) == NULL) {
202         perror("popen");
203         exit(1);
204     }
205     if ((imgdata = fopen(filename,"rb"))==NULL) {
206         perror("fopen");
207         exit(1);
208     }
209     for (;;) {
210         len = fread(buf,1,sizeof(buf),imgdata);
211         if (len <= 0)
212             break;
213         fwrite(buf,1,len,sshp);
214     }
215     fclose(imgdata);
216     pclose(sshp);
217 
218     unlink(filename);
219     return 0;
220 }
221 
222 static void ssh_close(struct xfer_state *s)
223 {
224     char *cmd = s->data;
225     free(cmd);
226 }
227 
228 static struct xfer_ops ssh_ops = {
229     open:  ssh_open,
230     info:  ssh_info,
231     xfer:  ssh_xfer,
232     close: ssh_close,
233 };
234 
235 static int local_open(struct xfer_state *s)
236 {
237     char *t;
238     
239     if (s->dir != NULL && s->dir[0] != '\0' ) {
240         t = malloc(strlen(s->tmpfile)+strlen(s->dir)+2);
241         sprintf(t, "%s/%s", s->dir, s->tmpfile);
242         s->tmpfile = t;
243         
244         t = malloc(strlen(s->file)+strlen(s->dir)+2);
245         sprintf(t, "%s/%s", s->dir, s->file);
246         s->file = t;
247     }
248     return 0;
249 }
250 
251 static void local_info(struct xfer_state *s)
252 {
253     fprintf(stderr,"write config [%s]:\n  local transfer %s => %s\n",
254             s->name,s->tmpfile,s->file);
255 }
256 
257 static int local_xfer(struct xfer_state *s, char *image, int width, int height)
258 {
259     int fh;
260     
261     if (-1 == (fh = open(s->tmpfile,O_CREAT|O_WRONLY|O_TRUNC,0666))) {
262         fprintf(stderr,"open %s: %s\n",s->tmpfile,strerror(errno));
263         exit(1);
264     }
265     write_file(fh, image, width, height);
266     if (rename(s->tmpfile, s->file) ) {
267         fprintf(stderr, "can't move %s -> %s\n", s->tmpfile, s->file);
268         exit(1);
269     }
270     return 0;
271 }
272 
273 static void local_close(struct xfer_state *s)
274 {
275     /* nothing */
276 }
277 
278 static struct xfer_ops local_ops = {
279     open:  local_open,
280     info:  local_info,
281     xfer:  local_xfer,
282     close: local_close,
283 };
284 
285 /* ---------------------------------------------------------------------- */
286 /* capture stuff                                                          */
287 
288 const struct ng_vid_driver  *drv;
289 void                        *h_drv;
290 struct ng_video_fmt         fmt,gfmt;
291 struct ng_video_conv        *conv;
292 void                        *hconv;
293 
294 static void
295 grab_init(void)
296 {
297     struct ng_attribute *attr;
298     int val,i;
299     
300     drv = ng_vid_open(ng_dev.video,NULL,NULL,0,&h_drv);
301     if (NULL == drv) {
302         fprintf(stderr,"no grabber device available\n");
303         exit(1);
304     }
305     if (!(drv->capabilities(h_drv) & CAN_CAPTURE)) {
306         fprintf(stderr,"device does'nt support capture\n");
307         exit(1);
308     }
309 
310     if (grab_input) {
311         attr = ng_attr_byid(drv->list_attrs(h_drv),ATTR_ID_INPUT);
312         val  = ng_attr_getint(attr,grab_input);
313         if (-1 == val) {
314             fprintf(stderr,"invalid input: %s\n",grab_input);
315             exit(1);
316         }
317         attr->write(attr,val);
318     }
319     if (grab_norm) {
320         attr = ng_attr_byid(drv->list_attrs(h_drv),ATTR_ID_NORM);
321         val  = ng_attr_getint(attr,grab_norm);
322         if (-1 == val) {
323             fprintf(stderr,"invalid norm: %s\n",grab_norm);
324             exit(1);
325         }
326         attr->write(attr,val);
327     }
328 
329     /* try native */
330     fmt.fmtid  = VIDEO_RGB24;
331     fmt.width  = grab_width;
332     fmt.height = grab_height;
333     if (0 == drv->setformat(h_drv,&fmt))
334         return;
335     
336     /* check all available conversion functions */
337     fmt.bytesperline = fmt.width*ng_vfmt_to_depth[fmt.fmtid]/8;
338     for (i = 0;;) {
339         conv = ng_conv_find_to(fmt.fmtid, &i);
340         if (NULL == conv)
341             break;
342         gfmt = fmt;
343         gfmt.fmtid = conv->fmtid_in;
344         gfmt.bytesperline = 0;
345         if (0 == drv->setformat(h_drv,&gfmt)) {
346             fmt.width  = gfmt.width;
347             fmt.height = gfmt.height;
348             hconv = conv->init(&fmt,conv->priv);
349             return;
350         }
351     }
352     fprintf(stderr,"can't get rgb24 data\n");
353     exit(1);
354 }
355 
356 static unsigned char*
357 grab_one(int *width, int *height)
358 {
359     static struct ng_video_buf *cap,*buf;
360 
361     if (NULL != buf)
362         ng_release_video_buf(buf);
363     if (NULL == (cap = drv->getimage(h_drv))) {
364         fprintf(stderr,"capturing image failed\n");
365         exit(1);
366     }
367 
368     if (NULL != conv) {
369         buf = ng_malloc_video_buf(&fmt,3*fmt.width*fmt.height);
370         conv->frame(hconv,buf,cap);
371         buf->info = cap->info;
372         ng_release_video_buf(cap);
373     } else {
374         buf = cap;
375     }
376     
377     *width  = buf->fmt.width;
378     *height = buf->fmt.height;
379     return buf->data;
380 }
381 
382 /* ---------------------------------------------------------------------- */
383 
384 #define MSG_MAXLEN   256
385 
386 #define CHAR_HEIGHT  11
387 #define CHAR_WIDTH   6
388 #define CHAR_START   4
389 #include "font-6x11.h"
390 
391 static char*
392 get_message(void)
393 {
394     static char buffer[MSG_MAXLEN+1];
395     FILE *fp;
396     char *p;
397     
398     if (NULL == grab_infofile)
399         return grab_text;
400 
401     if (NULL == (fp = fopen(grab_infofile, "r"))) {
402         fprintf(stderr,"open %s: %s\n",grab_infofile,strerror(errno));
403         return grab_text;
404     }
405 
406     fgets(buffer, MSG_MAXLEN, fp);
407     fclose(fp);
408     if (NULL != (p = strchr(buffer,'\n')))
409         *p = '\0';
410     return buffer;
411 }
412 
413 static void
414 add_text(char *image, int width, int height)
415 {
416     time_t      t;
417     struct tm  *tm;
418     char        line[MSG_MAXLEN+1],*ptr;
419     int         i,x,y,f,len;
420 
421     time(&t);
422     tm = localtime(&t);
423     len = strftime(line,MSG_MAXLEN,get_message(),tm);
424     // fprintf(stderr,"%s\n",line);
425 
426     for (y = 0; y < CHAR_HEIGHT; y++) {
427         ptr = image + 3 * width * (height-CHAR_HEIGHT-2+y) + 12;
428         for (x = 0; x < len; x++) {
429             f = fontdata[line[x] * CHAR_HEIGHT + y];
430             for (i = CHAR_WIDTH-1; i >= 0; i--) {
431                 if (f & (CHAR_START << i)) {
432                     ptr[0] = grab_fg_r;
433                     ptr[1] = grab_fg_g;
434                     ptr[2] = grab_fg_b;
435                 } else if (grab_bg_r != -1) {
436                     ptr[0] = grab_bg_r;
437                     ptr[1] = grab_bg_g;
438                     ptr[2] = grab_bg_b;
439                 }
440                 ptr += 3;
441             }
442         }
443     }
444 }
445 
446 /* ---------------------------------------------------------------------- */
447 /* Frederic Helin <Frederic.Helin@inrialpes.fr> - 15/07/2002              */
448 /* Correction fonction of stereographic radial distortion                 */
449 
450 int grab_dist_on = 0; 
451 int grab_dist_k = 700;
452 int grab_dist_cx = -1; 
453 int grab_dist_cy = -1;
454 int grab_dist_zoom = 50;
455 int grab_dist_sensorw = 640;
456 int grab_dist_sensorh = 480;
457 
458 static unsigned char *
459 correct_distor(unsigned char * in, int width, int height,
460                int grab_zoom, int grap_k, int cx, int cy,
461                int grab_sensorw, int grab_sensorh)
462 {
463     static unsigned char * corrimg = NULL;
464     
465     int i, j, di, dj;
466     float dr, cr,ca, sensor_w, sensor_h, sx, zoom, k;
467     
468     sensor_w = grab_dist_sensorw/100.0;
469     sensor_h = grab_dist_sensorh/100.0;
470     zoom = grab_zoom / 100.0;
471     k = grap_k / 100.0;
472     
473     if (corrimg == NULL && (corrimg = malloc(width*height*3)) == NULL ) {
474         fprintf(stderr, "out of memory\n");
475         exit(1);
476     }
477     
478     sensor_w = 6.4;
479     sensor_h = 4.8;
480     
481     // calc ratio x/y
482     sx = width * sensor_h / (height * sensor_w);
483     
484     // calc new value of k in the coordonates systeme of computer
485     k = k * height / sensor_h;
486     
487     // Clear image
488     for (i = 0; i < height*width*3; i++) corrimg[i] = 255;
489     
490     for (j = 0; j < height ; j++) {
491         for (i = 0; i < width ; i++) {  
492             
493             // compute radial distortion / parameters of center of image 
494             cr  = sqrt((i-cx)/sx*(i-cx)/sx+(j-cy)*(j-cy));
495             ca  = atan(cr/k/zoom);
496             dr = k * tan(ca/2); 
497             
498             if (i == cx && j == cy) {di = cx; dj = cy;}
499             else {
500                 di = (i-cx) * dr / cr + cx;
501                 dj = (j-cy) * dr / cr + cy;
502             }
503             
504             if (dj<height && di < width && di >= 0  && dj >= 0 &&
505                 j<height &&  i < width &&  i >= 0  &&  j >= 0 ) {
506                 corrimg[3*(j*width + i)  ] = in[3*(dj*width + di)  ];
507                 corrimg[3*(j*width + i)+1] = in[3*(dj*width + di)+1];
508                 corrimg[3*(j*width + i)+2] = in[3*(dj*width + di)+2];   
509             }
510         }
511     }
512     return corrimg;     
513 }
514 
515 /* ---------------------------------------------------------------------- */
516 
517 static unsigned int
518 compare_images(unsigned char *last, unsigned char *current,
519                int width, int height)
520 {
521     unsigned char *p1 = last;
522     unsigned char *p2 = current;
523     int avg, diff, max, i = width*height*3;
524 
525     for (max = 0, avg = 0; --i; p1++,p2++) {
526         diff = (*p1 < *p2) ? (*p2 - *p1) : (*p1 - *p2);
527         avg += diff;
528         if (diff > max)
529             max = diff;
530     }
531     avg = avg / width / height;
532     fprintf(stderr,"compare: max=%d,avg=%d\n",max,avg);
533     /* return avg */
534     return max;
535 }
536 
537 
538 static unsigned char *
539 rotate_image(unsigned char * in, int *wp, int *hp, int rot,
540              int top, int left, int bottom, int right)
541 {
542     static unsigned char * rotimg = NULL;
543 
544     int i, j;
545 
546     int w = *wp;
547     int ow = (right-left);
548     int oh = (bottom-top);
549 
550     if (rotimg == NULL && (rotimg = malloc(ow*oh*3)) == NULL ) {
551         fprintf(stderr, "out of memory\n");
552         exit(1);
553     }
554     switch (rot) {
555     default:
556     case 0:
557         for (j = 0; j < oh; j++) {
558             int ir = (j+top)*w+left;
559             int or = j*ow;
560             for (i = 0; i < ow; i++) {
561                 rotimg[3*(or + i)]   = in[3*(ir+i)];
562                 rotimg[3*(or + i)+1] = in[3*(ir+i)+1];
563                 rotimg[3*(or + i)+2] = in[3*(ir+i)+2];
564             }
565         }
566         *wp = ow;
567         *hp = oh;
568         break;
569     case 1:
570         for (i = 0; i < ow; i++) {
571             int rr = (ow-1-i)*oh;
572             int ic = i+left;
573             for (j = 0; j < oh; j++) {
574                 rotimg[3*(rr+j)]   = in[3*((j+top)*w+ic)];
575                 rotimg[3*(rr+j)+1] = in[3*((j+top)*w+ic)+1];
576                 rotimg[3*(rr+j)+2] = in[3*((j+top)*w+ic)+2];
577             }
578         }
579         *wp = oh;
580         *hp = ow;
581         break;
582     case 2:
583         for (j = 0; j < oh; j++) {
584             int ir = (j+top)*w;
585             for (i = 0; i < ow; i++) {
586                 rotimg[3*((oh-1-j)*ow + (ow-1-i))] = in[3*(ir+i+left)];
587                 rotimg[3*((oh-1-j)*ow + (ow-1-i))+1] = in[3*(ir+i+left)+1];
588                 rotimg[3*((oh-1-j)*ow + (ow-1-i))+2] = in[3*(ir+i+left)+2];
589             }
590         }
591         *wp = ow;
592         *hp = oh;
593         break;
594     case 3:
595         for (i = 0; i < ow; i++) {
596             int rr = i*oh;
597             int ic = i+left;
598             rr += oh-1;
599             for (j = 0; j < oh; j++) {
600                 rotimg[3*(rr-j)]   = in[3*((j+top)*w+ic)];
601                 rotimg[3*(rr-j)+1] = in[3*((j+top)*w+ic)+1];
602                 rotimg[3*(rr-j)+2] = in[3*((j+top)*w+ic)+2];
603             }
604         }
605         *wp = oh;
606         *hp = ow;
607         break;
608     }
609     return rotimg;      
610 }
611 
612 
613 /* ---------------------------------------------------------------------- */
614 
615 static int make_dirs(char *filename)
616 {
617     char *dirname,*h;
618     int retval = -1;
619 
620     dirname = strdup(filename);
621     if (NULL == dirname)
622         goto done;
623     h = strrchr(dirname,'/');
624     if (NULL == h)
625         goto done;
626     *h = 0;
627 
628     if (-1 == (retval = mkdir(dirname,0777)))
629         if (ENOENT == errno)
630             if (0 == make_dirs(dirname))
631                 retval = mkdir(dirname,0777);
632     
633  done:
634     free(dirname);
635     return retval;
636 }
637 
638 int
639 main(int argc, char *argv[])
640 {
641     unsigned char *image,*val,*gimg,*lastimg = NULL;
642     int width, height, i, fh;
643     char filename[1024];
644     char **sections;
645     struct list_head *item;
646     struct xfer_state *s;
647 
648     /* read config */
649     if (argc > 1) {
650         strcpy(filename,argv[1]);
651     } else {
652         sprintf(filename,"%s/%s",getenv("HOME"),".webcamrc");
653     }
654     fprintf(stderr,"reading config file: %s\n",filename);
655     cfg_parse_file(filename);
656     ng_init();
657 
658     if (NULL != (val = cfg_get_str("grab","device")))
659         ng_dev.video = val;
660     if (NULL != (val = cfg_get_str("grab","text")))
661         grab_text = val;
662     if (NULL != (val = cfg_get_str("grab","infofile")))
663         grab_infofile = val;
664     if (NULL != (val = cfg_get_str("grab","input")))
665         grab_input = val;
666     if (NULL != (val = cfg_get_str("grab","norm")))
667         grab_norm = val;
668     if (-1 != (i = cfg_get_int("grab","width")))
669         grab_width = i;
670     if (-1 != (i = cfg_get_int("grab","height")))
671         grab_height = i;
672     if (-1 != (i = cfg_get_int("grab","delay")))
673         grab_delay = i;
674     if (-1 != (i = cfg_get_int("grab","wait")))
675         grab_wait = i;
676     if (-1 != (i = cfg_get_int("grab","rotate")))
677         grab_rotate = i;
678     if (-1 != (i = cfg_get_int("grab","top")))
679         grab_top = i;
680     if (-1 != (i = cfg_get_int("grab","left")))
681         grab_left = i;
682     grab_bottom = cfg_get_int("grab","bottom");
683     grab_right = cfg_get_int("grab","right");
684     if (-1 != (i = cfg_get_int("grab","quality")))
685         grab_quality = i;
686     if (-1 != (i = cfg_get_int("grab","trigger")))
687         grab_trigger = i;
688     if (-1 != (i = cfg_get_int("grab","once")))
689         if (i > 0)
690             grab_times = 1;
691     if (-1 != (i = cfg_get_int("grab","times")))
692         grab_times = i;
693     if (NULL != (val = cfg_get_str("grab","archive")))
694         archive = val;
695 
696     if (-1 != (i = cfg_get_int("grab","fg_red")))
697         if (i >= 0 && i <= 255)
698             grab_fg_r = i;
699     if (-1 != (i = cfg_get_int("grab","fg_green")))
700         if (i >= 0 && i <= 255)
701             grab_fg_g = i;
702     if (-1 != (i = cfg_get_int("grab","fg_blue")))
703         if (i >= 0 && i <= 255)
704             grab_fg_b = i;
705     if (-1 != (i = cfg_get_int("grab","bg_red")))
706         if (i >= 0 && i <= 255)
707             grab_bg_r = i;
708     if (-1 != (i = cfg_get_int("grab","bg_green")))
709         if (i >= 0 && i <= 255)
710             grab_bg_g = i;
711     if (-1 != (i = cfg_get_int("grab","bg_blue")))
712         if (i >= 0 && i <= 255)
713             grab_bg_b = i;
714     
715     if (-1 != (i = cfg_get_int("grab","distor")))
716       grab_dist_on = i;
717     if (-1 != (i = cfg_get_int("grab","distor_k")))
718       grab_dist_k = i;
719     if (-1 != (i = cfg_get_int("grab","distor_cx")))
720       grab_dist_cx = i;
721     if (-1 != (i = cfg_get_int("grab","distor_cy")))
722       grab_dist_cy = i;
723     if (-1 != (i = cfg_get_int("grab","distor_zoom")))
724       grab_dist_zoom =i;
725     if (-1 != (i = cfg_get_int("grab","distor_sensorw")))
726       grab_dist_sensorw = i;
727     if (-1 != (i = cfg_get_int("grab","distor_sensorh")))
728       grab_dist_sensorh = i;
729 
730     /* defaults */
731     if (grab_top < 0)    grab_top    = 0;
732     if (grab_left < 0)   grab_left   = 0;
733     if (grab_bottom < 0) grab_bottom = grab_height;
734     if (grab_right < 0)  grab_right  = grab_width;
735 
736     if (grab_bottom > grab_height) grab_bottom = grab_height;
737     if (grab_right > grab_width)   grab_right  = grab_width;
738 
739     if (grab_top >= grab_bottom) {
740         fprintf(stderr, "config error: top must be smaller than bottom\n");
741         exit(1);
742     }
743     if (grab_left >= grab_right) {
744         fprintf(stderr, "config error: left must be smaller than right\n");
745         exit(1);
746     }
747 
748     if (grab_dist_k < 1 || grab_dist_k > 10000)
749         grab_dist_k = 700;
750     if (grab_dist_cx < 0 || grab_dist_cx > grab_width)
751         grab_dist_cx = grab_width / 2;
752     if (grab_dist_cy < 0 || grab_dist_cy > grab_height)
753         grab_dist_cy = grab_height / 2;
754     if (grab_dist_zoom < 1 || grab_dist_zoom > 1000)
755         grab_dist_zoom = 100;
756     if (grab_dist_sensorw < 1 ||  grab_dist_sensorw >9999)
757         grab_dist_sensorw = 640;
758     if (grab_dist_sensorh < 1 ||  grab_dist_sensorh >9999)
759         grab_dist_sensorh = 480;
760 
761     INIT_LIST_HEAD(&connections);
762     for (sections = cfg_list_sections(); *sections != NULL; sections++) {
763         if (0 == strcasecmp(*sections,"grab"))
764             continue;
765 
766         /* init + set defaults */
767         s = malloc(sizeof(*s));
768         memset(s,0,sizeof(*s));
769         s->name      = *sections;
770         s->host      = "www";
771         s->user      = "webcam";
772         s->pass      = "xxxxxx";
773         s->dir       = "public_html/images";
774         s->file      = "webcam.jpeg";
775         s->tmpfile   = "uploading.jpeg";
776         s->passive   = 1;
777         s->autologin = 0;
778         s->ops       = &ftp_ops;
779 
780         /* from config */
781         if (NULL != (val = cfg_get_str(*sections,"host")))
782             s->host = val;
783         if (NULL != (val = cfg_get_str(*sections,"user")))
784             s->user = val;
785         if (NULL != (val = cfg_get_str(*sections,"pass")))
786             s->pass = val;
787         if (NULL != (val = cfg_get_str(*sections,"dir")))
788             s->dir = val;
789         if (NULL != (val = cfg_get_str(*sections,"file")))
790             s->file = val;
791         if (NULL != (val = cfg_get_str(*sections,"tmp")))
792             s->tmpfile = val;
793         if (-1 != (i = cfg_get_int(*sections,"passive")))
794             s->passive = i;
795         if (-1 != (i = cfg_get_int(*sections,"auto")))
796             s->autologin = i;
797         if (-1 != (i = cfg_get_int(*sections,"debug")))
798             s->debug = i;
799         if (-1 != (i = cfg_get_int(*sections,"local")))
800             if (i)
801                 s->ops = &local_ops;
802         if (-1 != (i = cfg_get_int(*sections,"ssh")))
803             if (i)
804                 s->ops = &ssh_ops;
805 
806         /* all done */
807         list_add_tail(&s->list,&connections);
808     }
809 
810     /* init everything */
811     grab_init();
812     sleep(grab_wait);
813     tmpdir = (NULL != getenv("TMPDIR")) ? getenv("TMPDIR") : "/tmp";
814     list_for_each(item,&connections) {
815         s = list_entry(item, struct xfer_state, list);
816         s->ops->open(s);
817     }
818 
819     /* print config */
820     fprintf(stderr,"video4linux webcam v1.5 - (c) 1998-2002 Gerd Knorr\n");
821     fprintf(stderr,"grabber config:\n  size %dx%d [%s]\n",
822             fmt.width,fmt.height,ng_vfmt_to_desc[gfmt.fmtid]);
823     fprintf(stderr,"  input %s, norm %s, jpeg quality %d\n",
824             grab_input,grab_norm, grab_quality);
825     fprintf(stderr,"  rotate=%d, top=%d, left=%d, bottom=%d, right=%d\n",
826            grab_rotate, grab_top, grab_left, grab_bottom, grab_right);
827     list_for_each(item,&connections) {
828         s = list_entry(item, struct xfer_state, list);
829         s->ops->info(s);
830     }
831 
832     /* run as daemon - detach from terminal */
833     if (daemonize) {
834         switch (fork()) {
835         case -1:
836             perror("fork");
837             exit(1);
838         case 0:
839             close(0); close(1); close(2); setsid();
840             break;
841         default:
842             exit(0);
843         }
844     }
845 
846     /* main loop */
847     for (;;) {
848         /* grab a new one */
849         gimg = grab_one(&width,&height);
850 
851         if (grab_dist_on)
852             gimg = correct_distor(gimg, width, height,
853                                   grab_dist_zoom, grab_dist_k,
854                                   grab_dist_cx, grab_dist_cy,
855                                   grab_dist_sensorw, grab_dist_sensorh);
856         
857         image = rotate_image(gimg, &width, &height, grab_rotate,
858                              grab_top, grab_left, grab_bottom, grab_right);
859 
860         if (grab_trigger) {
861             /* look if it has changed */
862             if (NULL != lastimg) {
863                 i = compare_images(lastimg,image,width,height);
864                 if (i < grab_trigger)
865                     continue;
866             } else {
867                 lastimg = malloc(width*height*3);
868             }
869             memcpy(lastimg,image,width*height*3);
870         }
871 
872         /* ok, label it and upload */
873         add_text(image,width,height);
874         list_for_each(item,&connections) {
875             s = list_entry(item, struct xfer_state, list);
876             s->ops->xfer(s,image,width,height);
877         }
878         if (archive) {
879             time_t      t;
880             struct tm  *tm;
881 
882             time(&t);
883             tm = localtime(&t);
884             strftime(filename,sizeof(filename)-1,archive,tm);
885         again:
886             if (-1 == (fh = open(filename,O_CREAT|O_WRONLY|O_TRUNC,0666))) {
887                 if (ENOENT == errno) {
888                     if (0 == make_dirs(filename))
889                         goto again;
890                 }
891                 fprintf(stderr,"open %s: %s\n",filename,strerror(errno));
892                 exit(1);
893             }
894             write_file(fh, image, width, height);
895         }
896 
897         if (-1 != grab_times && --grab_times == 0)
898             break;
899         if (grab_delay > 0)
900             sleep(grab_delay);
901     }
902     list_for_each(item,&connections) {
903         s = list_entry(item, struct xfer_state, list);
904         s->ops->close(s);
905     }
906     return 0;
907 }
908 
  This page was automatically generated by the LXR engine.