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  * next generation[tm] xawtv capture interfaces
  3  *
  4  * (c) 2001 Gerd Knorr <kraxel@bytesex.org>
  5  *
  6  */
  7 
  8 #define NG_PRIVATE
  9 #include "config.h"
 10 
 11 #include <stdio.h>
 12 #include <stdlib.h>
 13 #include <unistd.h>
 14 #include <string.h>
 15 #include <pthread.h>
 16 #include <dirent.h>
 17 #include <fnmatch.h>
 18 #include <errno.h>
 19 #include <ctype.h>
 20 #include <inttypes.h>
 21 #include <sys/time.h>
 22 #include <sys/types.h>
 23 
 24 #include <dlfcn.h>
 25 #ifndef RTLD_NOW
 26 # define RTLD_NOW RTLD_LAZY
 27 #endif
 28 
 29 #include "grab-ng.h"
 30 
 31 int  ng_debug          = 0;
 32 int  ng_chromakey      = 0x00ff00ff;
 33 int  ng_jpeg_quality   = 75;
 34 int  ng_ratio_x        = 4;
 35 int  ng_ratio_y        = 3;
 36 
 37 char ng_v4l_conf[256]  = "v4l-conf";
 38 
 39 /* --------------------------------------------------------------------- */
 40 
 41 const unsigned int ng_vfmt_to_depth[] = {
 42     0,               /* unused   */
 43     8,               /* RGB8     */
 44     8,               /* GRAY8    */
 45     16,              /* RGB15 LE */
 46     16,              /* RGB16 LE */
 47     16,              /* RGB15 BE */
 48     16,              /* RGB16 BE */
 49     24,              /* BGR24    */
 50     32,              /* BGR32    */
 51     24,              /* RGB24    */
 52     32,              /* RGB32    */
 53     16,              /* LUT2     */
 54     32,              /* LUT4     */
 55     16,              /* YUYV     */
 56     16,              /* YUV422P  */
 57     12,              /* YUV420P  */
 58     0,               /* MJPEG    */
 59     0,               /* JPEG     */
 60     16,              /* UYVY     */
 61 };
 62 
 63 const char* ng_vfmt_to_desc[] = {
 64     "none",
 65     "8 bit PseudoColor (dithering)",
 66     "8 bit StaticGray",
 67     "15 bit TrueColor (LE)",
 68     "16 bit TrueColor (LE)",
 69     "15 bit TrueColor (BE)",
 70     "16 bit TrueColor (BE)",
 71     "24 bit TrueColor (LE: bgr)",
 72     "32 bit TrueColor (LE: bgr-)",
 73     "24 bit TrueColor (BE: rgb)",
 74     "32 bit TrueColor (BE: -rgb)",
 75     "16 bit TrueColor (lut)",
 76     "32 bit TrueColor (lut)",
 77     "16 bit YUV 4:2:2 (packed, YUYV)",
 78     "16 bit YUV 4:2:2 (planar)",
 79     "12 bit YUV 4:2:0 (planar)",
 80     "MJPEG (AVI)",
 81     "JPEG (JFIF)",
 82     "16 bit YUV 4:2:2 (packed, UYVY)",
 83 };
 84 
 85 /* --------------------------------------------------------------------- */
 86 
 87 const unsigned int   ng_afmt_to_channels[] = {
 88     0,  1,  2,  1,  2,  1,  2, 0
 89 };
 90 const unsigned int   ng_afmt_to_bits[] = {
 91     0,  8,  8, 16, 16, 16, 16, 0
 92 };
 93 const char* ng_afmt_to_desc[] = {
 94     "none",
 95     "8bit mono",
 96     "8bit stereo",
 97     "16bit mono (LE)",
 98     "16bit stereo (LE)",
 99     "16bit mono (BE)",
100     "16bit stereo (BE)",
101     "mp3 compressed audio",
102 };
103 
104 /* --------------------------------------------------------------------- */
105 
106 const char* ng_attr_to_desc[] = {
107     "none",
108     "norm",
109     "input",
110     "volume",
111     "mute",
112     "audio mode",
113     "color",
114     "bright",
115     "hue",
116     "contrast",
117 };
118 
119 /* --------------------------------------------------------------------- */
120 
121 void ng_init_video_buf(struct ng_video_buf *buf)
122 {
123     memset(buf,0,sizeof(*buf));
124     pthread_mutex_init(&buf->lock,NULL);    
125     pthread_cond_init(&buf->cond,NULL);
126 }
127 
128 void ng_release_video_buf(struct ng_video_buf *buf)
129 {
130     int release;
131 
132     pthread_mutex_lock(&buf->lock);
133     buf->refcount--;
134     release = (buf->refcount == 0);
135     pthread_mutex_unlock(&buf->lock);
136     if (release && NULL != buf->release)
137         buf->release(buf);
138 }
139 
140 void ng_wakeup_video_buf(struct ng_video_buf *buf)
141 {
142     pthread_cond_signal(&buf->cond);
143 }
144 
145 void ng_waiton_video_buf(struct ng_video_buf *buf)
146 {
147     pthread_mutex_lock(&buf->lock);
148     while (buf->refcount)
149         pthread_cond_wait(&buf->cond, &buf->lock);
150     pthread_mutex_unlock(&buf->lock);
151 }
152 
153 static void ng_free_video_buf(struct ng_video_buf *buf)
154 {
155     free(buf->data);
156     free(buf);
157 }
158 
159 struct ng_video_buf*
160 ng_malloc_video_buf(struct ng_video_fmt *fmt, int size)
161 {
162     struct ng_video_buf *buf;
163 
164     buf = malloc(sizeof(*buf));
165     if (NULL == buf)
166         return NULL;
167     ng_init_video_buf(buf);
168     buf->fmt  = *fmt;
169     buf->size = size;
170     buf->data = malloc(size);
171     if (NULL == buf->data) {
172         free(buf);
173         return NULL;
174     }
175     buf->refcount = 1;
176     buf->release  = ng_free_video_buf;
177     return buf;
178 }
179 
180 /* --------------------------------------------------------------------- */
181 
182 struct ng_audio_buf*
183 ng_malloc_audio_buf(struct ng_audio_fmt *fmt, int size)
184 {
185     struct ng_audio_buf *buf;
186 
187     buf = malloc(sizeof(*buf)+size);
188     memset(buf,0,sizeof(*buf));
189     buf->fmt  = *fmt;
190     buf->size = size;
191     buf->data = (char*)buf + sizeof(*buf);
192     return buf;
193 }
194 
195 /* --------------------------------------------------------------------- */
196 
197 struct ng_attribute*
198 ng_attr_byid(struct ng_attribute *attrs, int id)
199 {
200     if (NULL == attrs)
201         return NULL;
202     for (;;) {
203         if (NULL == attrs->name)
204             return NULL;
205         if (attrs->id == id)
206             return attrs;
207         attrs++;
208     }
209 }
210 
211 struct ng_attribute*
212 ng_attr_byname(struct ng_attribute *attrs, char *name)
213 {
214     if (NULL == attrs)
215         return NULL;
216     for (;;) {
217         if (NULL == attrs->name)
218             return NULL;
219         if (0 == strcasecmp(attrs->name,name))
220             return attrs;
221         attrs++;
222     }
223 }
224 
225 const char*
226 ng_attr_getstr(struct ng_attribute *attr, int value)
227 {
228     int i;
229     
230     if (NULL == attr)
231         return NULL;
232     if (attr->type != ATTR_TYPE_CHOICE)
233         return NULL;
234 
235     for (i = 0; attr->choices[i].str != NULL; i++)
236         if (attr->choices[i].nr == value)
237             return attr->choices[i].str;
238     return NULL;
239 }
240 
241 int
242 ng_attr_getint(struct ng_attribute *attr, char *value)
243 {
244     int i,val;
245     
246     if (NULL == attr)
247         return -1;
248     if (attr->type != ATTR_TYPE_CHOICE)
249         return -1;
250 
251     for (i = 0; attr->choices[i].str != NULL; i++) {
252         if (0 == strcasecmp(attr->choices[i].str,value))
253             return attr->choices[i].nr;
254     }
255 
256     if (isdigit(value[0])) {
257         /* Hmm.  String not found, but starts with a digit.
258            Check if this is a valid number ... */
259         val = atoi(value);
260         for (i = 0; attr->choices[i].str != NULL; i++)
261             if (val == attr->choices[i].nr)
262                 return attr->choices[i].nr;
263         
264     }
265     return -1;
266 }
267 
268 void
269 ng_attr_listchoices(struct ng_attribute *attr)
270 {
271     int i;
272     
273     fprintf(stderr,"valid choices for \"%s\": ",attr->name);
274     for (i = 0; attr->choices[i].str != NULL; i++)
275         fprintf(stderr,"%s\"%s\"",
276                 i ? ", " : "",
277                 attr->choices[i].str);
278     fprintf(stderr,"\n");
279 }
280 
281 int
282 ng_attr_int2percent(struct ng_attribute *attr, int value)
283 {
284     int range,percent;
285 
286     range   = attr->max - attr->min;
287     percent = (value - attr->min) * 100 / range;
288     if (percent < 0)
289         percent = 0;
290     if (percent > 100)
291         percent = 100;
292     return percent;
293 }
294 
295 int
296 ng_attr_percent2int(struct ng_attribute *attr, int percent)
297 {
298     int range,value;
299 
300     range = attr->max - attr->min;
301     value = percent * range / 100 + attr->min;
302     if (value < attr->min)
303         value = attr->min;
304     if (value > attr->max)
305         value = attr->max;
306     return value;
307 }
308 
309 int
310 ng_attr_parse_int(struct ng_attribute *attr, char *str)
311 {
312     int value,n;
313 
314     if (0 == sscanf(str,"%d%n",&value,&n))
315         /* parse error */
316         return attr->defval;
317     if (str[n] == '%')
318         value = ng_attr_percent2int(attr,value);
319     if (value < attr->min)
320         value = attr->min;
321     if (value > attr->max)
322         value = attr->max;
323     return value;
324 }
325 
326 /* --------------------------------------------------------------------- */
327 
328 void
329 ng_ratio_fixup(int *width, int *height, int *xoff, int *yoff)
330 {
331     int h = *height;
332     int w = *width;
333 
334     if (0 == ng_ratio_x || 0 == ng_ratio_y)
335         return;
336     if (w * ng_ratio_y < h * ng_ratio_x) {
337         *height = *width * ng_ratio_y / ng_ratio_x;
338         if (yoff)
339             *yoff  += (h-*height)/2;
340     } else if (w * ng_ratio_y > h * ng_ratio_x) {
341         *width  = *height * ng_ratio_x / ng_ratio_y;
342         if (yoff)
343             *xoff  += (w-*width)/2;
344     }
345 }
346 
347 void
348 ng_ratio_fixup2(int *width, int *height, int *xoff, int *yoff,
349                 int ratio_x, int ratio_y, int up)
350 {
351     int h = *height;
352     int w = *width;
353 
354     if (0 == ratio_x || 0 == ratio_y)
355         return;
356     if ((!up  &&  w * ratio_y < h * ratio_x) ||
357         (up   &&  w * ratio_y > h * ratio_x)) {
358         *height = *width * ratio_y / ratio_x;
359         if (yoff)
360             *yoff  += (h-*height)/2;
361     } else if ((!up  &&  w * ratio_y > h * ratio_x) ||
362                (up   &&  w * ratio_y < h * ratio_x)) {
363         *width  = *height * ratio_x / ratio_y;
364         if (yoff)
365             *xoff  += (w-*width)/2;
366     }
367 }
368 
369 /* --------------------------------------------------------------------- */
370 
371 LIST_HEAD(ng_conv);
372 LIST_HEAD(ng_aconv);
373 LIST_HEAD(ng_filters);
374 LIST_HEAD(ng_writers);
375 LIST_HEAD(ng_readers);
376 LIST_HEAD(ng_vid_drivers);
377 LIST_HEAD(ng_dsp_drivers);
378 LIST_HEAD(ng_mix_drivers);
379 
380 static int ng_check_magic(int magic, char *plugname, char *type)
381 {
382     if (magic != NG_PLUGIN_MAGIC) {
383         fprintf(stderr, "ERROR: plugin magic mismatch [xawtv=%d,%s=%d]\n",
384                 NG_PLUGIN_MAGIC,plugname,magic);
385         return -1;
386     }
387 #if 0
388     if (ng_debug)
389         fprintf(stderr,"plugins: %s registered by %s\n",type,plugname);
390 #endif
391     return 0;
392 }
393 
394 int
395 ng_conv_register(int magic, char *plugname,
396                  struct ng_video_conv *list, int count)
397 {
398     int n;
399 
400     if (0 != ng_check_magic(magic,plugname,"video converters"))
401         return -1;
402     for (n = 0; n < count; n++)
403         list_add_tail(&(list[n].list),&ng_conv);
404     return 0;
405 }
406 
407 int
408 ng_aconv_register(int magic, char *plugname,
409                   struct ng_audio_conv *list, int count)
410 {
411     int n;
412     
413     if (0 != ng_check_magic(magic,plugname,"audio converters"))
414         return -1;
415     for (n = 0; n < count; n++)
416         list_add_tail(&(list[n].list),&ng_aconv);
417     return 0;
418 }
419 
420 int
421 ng_filter_register(int magic, char *plugname, struct ng_filter *filter)
422 {
423     if (0 != ng_check_magic(magic,plugname,"filter"))
424         return -1;
425     list_add_tail(&filter->list,&ng_filters);
426     return 0;
427 }
428 
429 int
430 ng_writer_register(int magic, char *plugname, struct ng_writer *writer)
431 {
432     if (0 != ng_check_magic(magic,plugname,"writer"))
433         return -1;
434     list_add_tail(&writer->list,&ng_writers);
435     return 0;
436 }
437 
438 int
439 ng_reader_register(int magic, char *plugname, struct ng_reader *reader)
440 {
441     if (0 != ng_check_magic(magic,plugname,"reader"))
442         return -1;
443     list_add_tail(&reader->list,&ng_readers);
444     return 0;
445 }
446 
447 int
448 ng_vid_driver_register(int magic, char *plugname, struct ng_vid_driver *driver)
449 {
450     if (0 != ng_check_magic(magic,plugname,"video drv"))
451         return -1;
452     list_add_tail(&driver->list,&ng_vid_drivers);
453     return 0;
454 }
455 
456 int
457 ng_dsp_driver_register(int magic, char *plugname, struct ng_dsp_driver *driver)
458 {
459     if (0 != ng_check_magic(magic,plugname,"dsp drv"))
460         return -1;
461     list_add_tail(&driver->list,&ng_dsp_drivers);
462     return 0;
463 }
464 
465 int
466 ng_mix_driver_register(int magic, char *plugname, struct ng_mix_driver *driver)
467 {
468     if (0 != ng_check_magic(magic,plugname,"mixer drv"))
469         return -1;
470     list_add_tail(&driver->list,&ng_mix_drivers);
471     return 0;
472 }
473 
474 struct ng_video_conv*
475 ng_conv_find_to(unsigned int out, int *i)
476 {
477     struct list_head *item;
478     struct ng_video_conv *ret;
479     int j = 0;
480 
481     list_for_each(item,&ng_conv) {
482         if (j < *i) {
483             j++;
484             continue;
485         }
486         ret = list_entry(item, struct ng_video_conv, list);
487 #if 0
488         fprintf(stderr,"\tconv to:  %-28s =>  %s\n",
489                 ng_vfmt_to_desc[ret->fmtid_in],
490                 ng_vfmt_to_desc[ret->fmtid_out]);
491 #endif
492         if (ret->fmtid_out == out) {
493             (*i)++;
494             return ret;
495         }
496         (*i)++;
497         j++;
498     }
499     return NULL;
500 }
501 
502 struct ng_video_conv*
503 ng_conv_find_from(unsigned int in, int *i)
504 {
505     struct list_head *item;
506     struct ng_video_conv *ret;
507     
508     int j = 0;
509 
510     list_for_each(item,&ng_conv) {
511         if (j < *i) {
512             j++;
513             continue;
514         }
515         ret = list_entry(item, struct ng_video_conv, list);
516 #if 0
517         fprintf(stderr,"\tconv from:  %-28s =>  %s\n",
518                 ng_vfmt_to_desc[ret->fmtid_in],
519                 ng_vfmt_to_desc[ret->fmtid_out]);
520 #endif
521         if (ret->fmtid_in == in) {
522             (*i)++;
523             return ret;
524         }
525     }
526     return NULL;
527 }
528 
529 struct ng_video_conv*
530 ng_conv_find_match(unsigned int in, unsigned int out)
531 {
532     struct list_head *item;
533     struct ng_video_conv *ret = NULL;
534     
535     list_for_each(item,&ng_conv) {
536         ret = list_entry(item, struct ng_video_conv, list);
537         if (ret->fmtid_in  == in && ret->fmtid_out == out)
538             return ret;
539     }
540     return NULL;
541 }
542 
543 /* --------------------------------------------------------------------- */
544 
545 const struct ng_vid_driver*
546 ng_vid_open(char *device, char *driver, struct ng_video_fmt *screen,
547             void *base, void **handle)
548 {
549     struct list_head *item;
550     struct ng_vid_driver *drv;
551 
552 #ifdef __linux__
553     if (NULL != screen) {
554         switch (system(ng_v4l_conf)) {
555         case -1: /* can't run */
556             fprintf(stderr,"could'nt start v4l-conf\n");
557             break;
558         case 0: /* ok */
559             break;
560         default: /* non-zero return */
561             fprintf(stderr,"v4l-conf had some trouble, "
562                     "trying to continue anyway\n");
563             break;
564         }
565     }
566 #endif
567 
568     /* check all grabber drivers */
569     list_for_each(item,&ng_vid_drivers) {
570         drv = list_entry(item, struct ng_vid_driver, list);
571         if (driver && 0 != strcasecmp(driver, drv->name))
572             continue;
573         if (ng_debug)
574             fprintf(stderr,"vid-open: trying: %s... \n", drv->name);
575         if (NULL != (*handle = drv->open(device)))
576             break;
577         if (ng_debug)
578             fprintf(stderr,"vid-open: failed: %s\n",drv->name);
579     }
580     if (item == &ng_vid_drivers)
581         return NULL;
582     if (ng_debug)
583         fprintf(stderr,"vid-open: ok: %s\n",drv->name);
584     if (NULL != screen && drv->capabilities(*handle) & CAN_OVERLAY)
585         drv->setupfb(*handle,screen,base);
586     return drv;
587 }
588 
589 const struct ng_dsp_driver*
590 ng_dsp_open(char *device, struct ng_audio_fmt *fmt, int record, void **handle)
591 {
592     struct list_head *item;
593     struct ng_dsp_driver *drv;
594 
595     /* check all dsp drivers */
596     list_for_each(item,&ng_dsp_drivers) {
597         drv = list_entry(item, struct ng_dsp_driver, list);
598         if (NULL == drv->name)
599             continue;
600         if (record && NULL == drv->read)
601             continue;
602         if (!record && NULL == drv->write)
603             continue;
604         if (ng_debug)
605             fprintf(stderr,"dsp-open: trying: %s... \n", drv->name);
606         if (NULL != (*handle = drv->open(device,fmt,record)))
607             break;
608         if (ng_debug)
609             fprintf(stderr,"dsp-open: failed: %s\n", drv->name);
610     }
611     if (item == &ng_dsp_drivers)
612         return NULL;
613     if (ng_debug)
614         fprintf(stderr,"dsp-open: ok: %s\n",drv->name);
615     return drv;
616 }
617 
618 struct ng_attribute*
619 ng_mix_init(char *device, char *channel)
620 {
621     struct list_head *item;
622     struct ng_mix_driver *drv = NULL;
623     struct ng_attribute *attrs = NULL;
624     void *handle;
625     
626     /* check all mixer drivers */
627     list_for_each(item, &ng_mix_drivers) {
628         drv = list_entry(item, struct ng_mix_driver, list);
629         if (ng_debug)
630             fprintf(stderr,"mix-init: trying: %s... \n", drv->name);
631         if (NULL != (handle = drv->open(device))) {
632             if (NULL != (attrs = drv->volctl(handle,channel)))
633                 break;
634             drv->close(handle);
635         }
636         if (ng_debug)
637             fprintf(stderr,"mix-init: failed: %s\n",drv->name);
638     }
639     if (ng_debug && NULL != attrs)
640         fprintf(stderr,"mix-init: ok: %s\n",drv->name);
641     return attrs;
642 }
643 
644 struct ng_reader* ng_find_reader(char *filename)
645 {
646     struct list_head *item;
647     struct ng_reader *reader;
648     char blk[512];
649     FILE *fp;
650     int m;
651 
652     if (NULL == (fp = fopen(filename, "r"))) {
653         fprintf(stderr,"open %s: %s\n",filename,strerror(errno));
654         return NULL;
655     }
656     memset(blk,0,sizeof(blk));
657     fread(blk,1,sizeof(blk),fp);
658     fclose(fp);
659 
660     list_for_each(item,&ng_readers) {
661         reader = list_entry(item, struct ng_reader, list);
662         for (m = 0; m < 4 && reader->mlen[m] > 0; m++) {
663             if (0 == memcmp(blk+reader->moff[m],reader->magic[m],
664                             reader->mlen[m]))
665                 return reader;
666         }
667     }
668     if (ng_debug)
669         fprintf(stderr,"%s: no reader found\n",filename);
670     return NULL;
671 }
672 
673 int64_t
674 ng_tofday_to_timestamp(struct timeval *tv)
675 {
676     long long ts;
677 
678     ts  = tv->tv_sec;
679     ts *= 1000000;
680     ts += tv->tv_usec;
681     ts *= 1000;
682     return ts;
683 }
684 
685 int64_t
686 ng_get_timestamp()
687 {
688     struct timeval tv;
689 
690     gettimeofday(&tv,NULL);
691     return ng_tofday_to_timestamp(&tv);
692 }
693 
694 struct ng_video_buf*
695 ng_filter_single(struct ng_filter *filter, struct ng_video_buf *in)
696 {
697     struct ng_video_buf *out = in;
698     void *handle;
699 
700     if (NULL != filter  &&  filter->fmts & (1 << in->fmt.fmtid)) {
701         handle = filter->init(&in->fmt);
702         out = filter->frame(handle,in);
703         filter->fini(handle);
704     }
705     return out;
706 }
707 
708 /* --------------------------------------------------------------------- */
709 
710 static void clip_dump(char *state, struct OVERLAY_CLIP *oc, int count)
711 {
712     int i;
713 
714     fprintf(stderr,"clip: %s - %d clips\n",state,count);
715     for (i = 0; i < count; i++)
716         fprintf(stderr,"clip:   %d: %dx%d+%d+%d\n",i,
717                 oc[i].x2 - oc[i].x1,
718                 oc[i].y2 - oc[i].y1,
719                 oc[i].x1, oc[i].y1);
720 }
721 
722 static void clip_drop(struct OVERLAY_CLIP *oc, int n, int *count)
723 {
724     (*count)--;
725     memmove(oc+n, oc+n+1, sizeof(struct OVERLAY_CLIP) * (*count-n));
726 }
727 
728 void ng_check_clipping(int width, int height, int xadjust, int yadjust,
729                        struct OVERLAY_CLIP *oc, int *count)
730 {
731     int i,j;
732 
733     if (ng_debug > 1) {
734         fprintf(stderr,"clip: win=%dx%d xa=%d ya=%d\n",
735                 width,height,xadjust,yadjust);
736         clip_dump("init",oc,*count);
737     }
738     for (i = 0; i < *count; i++) {
739         /* fixup coordinates */
740         oc[i].x1 += xadjust;
741         oc[i].x2 += xadjust;
742         oc[i].y1 += yadjust;
743         oc[i].y2 += yadjust;
744     }
745     if (ng_debug > 1)
746         clip_dump("fixup adjust",oc,*count);
747 
748     for (i = 0; i < *count; i++) {
749         /* fixup borders */
750         if (oc[i].x1 < 0)
751             oc[i].x1 = 0;
752         if (oc[i].x2 < 0)
753             oc[i].x2 = 0;
754         if (oc[i].x1 > width)
755             oc[i].x1 = width;
756         if (oc[i].x2 > width)
757             oc[i].x2 = width;
758         if (oc[i].y1 < 0)
759             oc[i].y1 = 0;
760         if (oc[i].y2 < 0)
761             oc[i].y2 = 0;
762         if (oc[i].y1 > height)
763             oc[i].y1 = height;
764         if (oc[i].y2 > height)
765             oc[i].y2 = height;
766     }
767     if (ng_debug > 1)
768         clip_dump("fixup range",oc,*count);
769 
770     /* drop zero-sized clips */
771     for (i = 0; i < *count;) {
772         if (oc[i].x1 == oc[i].x2 || oc[i].y1 == oc[i].y2) {
773             clip_drop(oc,i,count);
774             continue;
775         }
776         i++;
777     }
778     if (ng_debug > 1)
779         clip_dump("zerosize done",oc,*count);
780 
781     /* try to merge clips */
782  restart_merge:
783     for (j = *count - 1; j >= 0; j--) {
784         for (i = 0; i < *count; i++) {
785             if (i == j)
786                 continue;
787             if (oc[i].x1 == oc[j].x1 &&
788                 oc[i].x2 == oc[j].x2 &&
789                 oc[i].y1 <= oc[j].y1 &&
790                 oc[i].y2 >= oc[j].y1) {
791                 if (ng_debug > 1)
792                     fprintf(stderr,"clip: merge y %d,%d\n",i,j);
793                 if (oc[i].y2 < oc[j].y2)
794                     oc[i].y2 = oc[j].y2;
795                 clip_drop(oc,j,count);
796                 if (ng_debug > 1)
797                     clip_dump("merge y done",oc,*count);
798                 goto restart_merge;
799             }
800             if (oc[i].y1 == oc[j].y1 &&
801                 oc[i].y2 == oc[j].y2 &&
802                 oc[i].x1 <= oc[j].x1 &&
803                 oc[i].x2 >= oc[j].x1) {
804                 if (ng_debug > 1)
805                     fprintf(stderr,"clip: merge x %d,%d\n",i,j);
806                 if (oc[i].x2 < oc[j].x2)
807                     oc[i].x2 = oc[j].x2;
808                 clip_drop(oc,j,count);
809                 if (ng_debug > 1)
810                     clip_dump("merge x done",oc,*count);
811                 goto restart_merge;
812             }
813         }
814     }
815     if (ng_debug)
816         clip_dump("final",oc,*count);
817 }
818 
819 /* --------------------------------------------------------------------- */
820 
821 static int ng_plugins(char *dirname)
822 {
823     struct dirent **list;
824     char filename[1024];
825     void *plugin;
826     void (*initcall)(void);
827     int i,n = 0,l = 0;
828 
829     n = scandir(dirname,&list,NULL,alphasort);
830     if (n <= 0)
831         return 0;
832     for (i = 0; i < n; i++) {
833         if (0 != fnmatch("*.so",list[i]->d_name,0))
834             continue;
835         sprintf(filename,"%s/%s",dirname,list[i]->d_name);
836         if (NULL == (plugin = dlopen(filename,RTLD_NOW))) {
837             fprintf(stderr,"dlopen: %s\n",dlerror());
838             continue;
839         }
840         if (NULL == (initcall = dlsym(plugin,"ng_plugin_init"))) {
841             if (NULL == (initcall = dlsym(plugin,"_ng_plugin_init"))) {
842                 fprintf(stderr,"dlsym[%s]: %s\n",filename,dlerror());
843                 continue;
844             }
845         }
846         initcall();
847         l--;
848     }
849     for (i = 0; i < n; i++)
850         free(list[i]);
851     free(list);
852     return l;
853 }
854 
855 void
856 ng_init(void)
857 {
858     static int once=0;
859     int count=0;
860 
861     if (once++) {
862         fprintf(stderr,"panic: ng_init called twice\n");
863         exit(1);
864     }
865     ng_device_init();
866     ng_color_packed_init();
867     ng_color_yuv2rgb_init();
868     ng_writefile_init();
869 
870     count += ng_plugins(LIBDIR);
871     if (0 == count) {
872         /* nice for development */
873         count += ng_plugins("../libng/plugins");
874         count += ng_plugins("../libng/contrib-plugins");
875     }
876     if (0 == count)
877         fprintf(stderr,"WARNING: no plugins found [%s]\n",LIBDIR);
878 }
879 
  This page was automatically generated by the LXR engine.