2
* next generation[tm] xawtv capture interfaces
4
* (c) 2001 Gerd Knorr <kraxel@bytesex.org>
23
#include <sys/types.h>
28
# define RTLD_NOW RTLD_LAZY
34
int ng_log_bad_stream = 0;
35
int ng_log_resync = 0;
37
int ng_chromakey = 0x00ff00ff;
40
int ng_jpeg_quality = 75;
42
char ng_v4l_conf[256] = "v4l-conf";
44
/* --------------------------------------------------------------------- */
46
const unsigned int ng_vfmt_to_depth[VIDEO_FMT_COUNT] = {
69
const char* ng_vfmt_to_desc[VIDEO_FMT_COUNT] = {
71
"8 bit PseudoColor (dithering)",
73
"15 bit TrueColor (LE)",
74
"16 bit TrueColor (LE)",
75
"15 bit TrueColor (BE)",
76
"16 bit TrueColor (BE)",
77
"24 bit TrueColor (LE: bgr)",
78
"32 bit TrueColor (LE: bgr-)",
79
"24 bit TrueColor (BE: rgb)",
80
"32 bit TrueColor (BE: -rgb)",
81
"16 bit TrueColor (lut)",
82
"32 bit TrueColor (lut)",
83
"16 bit YUV 4:2:2 (packed, YUYV)",
84
"16 bit YUV 4:2:2 (planar)",
85
"12 bit YUV 4:2:0 (planar)",
88
"16 bit YUV 4:2:2 (packed, UYVY)",
92
/* --------------------------------------------------------------------- */
94
const unsigned int ng_afmt_to_channels[AUDIO_FMT_COUNT] = {
95
0, 1, 2, 1, 2, 1, 2, 0
97
const unsigned int ng_afmt_to_bits[AUDIO_FMT_COUNT] = {
98
0, 8, 8, 16, 16, 16, 16, 0
100
const char* ng_afmt_to_desc[AUDIO_FMT_COUNT] = {
111
/* --------------------------------------------------------------------- */
113
const char* ng_attr_to_desc[] = {
126
/* --------------------------------------------------------------------- */
128
void ng_init_video_buf(struct ng_video_buf *buf)
130
memset(buf,0,sizeof(*buf));
131
pthread_mutex_init(&buf->lock,NULL);
132
pthread_cond_init(&buf->cond,NULL);
135
void ng_release_video_buf(struct ng_video_buf *buf)
139
pthread_mutex_lock(&buf->lock);
141
release = (buf->refcount == 0);
142
pthread_mutex_unlock(&buf->lock);
143
if (release && NULL != buf->release)
147
void ng_print_video_buf(char *tag, struct ng_video_buf *buf)
149
fprintf(stderr,"buf %5s: %dx%d [%s]\n",
150
tag, buf->fmt.width, buf->fmt.height,
151
ng_vfmt_to_desc[buf->fmt.fmtid]);
154
void ng_copy_video_buf(struct ng_video_buf *dst, struct ng_video_buf *src)
156
memcpy(dst->data, src->data, src->size);
157
dst->size = src->size;
158
dst->info = src->info;
161
void ng_wakeup_video_buf(struct ng_video_buf *buf)
163
pthread_cond_signal(&buf->cond);
166
void ng_waiton_video_buf(struct ng_video_buf *buf)
168
pthread_mutex_lock(&buf->lock);
169
while (buf->refcount)
170
pthread_cond_wait(&buf->cond, &buf->lock);
171
pthread_mutex_unlock(&buf->lock);
174
static int malloc_video_bufs;
175
static int malloc_audio_bufs;
177
static void ng_free_video_buf(struct ng_video_buf *buf)
185
ng_malloc_video_buf(void *handle, struct ng_video_fmt *fmt)
187
struct ng_video_buf *buf;
189
buf = malloc(sizeof(*buf));
192
ng_init_video_buf(buf);
194
buf->size = fmt->height * fmt->bytesperline;
196
buf->size = fmt->width * fmt->height * 3;
197
buf->data = malloc(buf->size);
198
if (NULL == buf->data) {
203
buf->release = ng_free_video_buf;
209
ng_malloc_audio_buf(struct ng_audio_fmt *fmt, int size)
211
struct ng_audio_buf *buf;
213
buf = malloc(sizeof(*buf)+size);
214
memset(buf,0,sizeof(*buf));
217
buf->data = (char*)buf + sizeof(*buf);
222
void ng_free_audio_buf(struct ng_audio_buf *buf)
228
static void __fini malloc_bufs_check(void)
230
OOPS_ON(malloc_video_bufs > 0, "malloc_video_bufs is %d (expected 0)",
232
OOPS_ON(malloc_audio_bufs > 0, "malloc_audio_bufs is %d (expected 0)",
236
/* --------------------------------------------------------------------- */
239
ng_attr_byid(struct ng_devstate *dev, int id)
241
struct list_head *item;
242
struct ng_attribute *attr;
244
list_for_each(item, &dev->attrs) {
245
attr = list_entry(item, struct ng_attribute, device_list);
253
ng_attr_byname(struct ng_devstate *dev, char *name)
255
struct list_head *item;
256
struct ng_attribute *attr;
258
list_for_each(item, &dev->attrs) {
259
attr = list_entry(item, struct ng_attribute, device_list);
260
if (0 == strcasecmp(attr->name,name))
267
ng_attr_getstr(struct ng_attribute *attr, int value)
273
if (attr->type != ATTR_TYPE_CHOICE)
276
for (i = 0; attr->choices[i].str != NULL; i++)
277
if (attr->choices[i].nr == value)
278
return attr->choices[i].str;
283
ng_attr_getint(struct ng_attribute *attr, char *value)
289
if (attr->type != ATTR_TYPE_CHOICE)
292
for (i = 0; attr->choices[i].str != NULL; i++) {
293
if (0 == strcasecmp(attr->choices[i].str,value))
294
return attr->choices[i].nr;
297
if (isdigit(value[0])) {
298
/* Hmm. String not found, but starts with a digit.
299
Check if this is a valid number ... */
301
for (i = 0; attr->choices[i].str != NULL; i++)
302
if (val == attr->choices[i].nr)
303
return attr->choices[i].nr;
310
ng_attr_listchoices(struct ng_attribute *attr)
314
fprintf(stderr,"valid choices for \"%s\": ",attr->name);
315
for (i = 0; attr->choices[i].str != NULL; i++)
316
fprintf(stderr,"%s\"%s\"",
318
attr->choices[i].str);
319
fprintf(stderr,"\n");
323
ng_attr_int2percent(struct ng_attribute *attr, int value)
327
range = attr->max - attr->min;
328
percent = (value - attr->min) * 100 / range;
337
ng_attr_percent2int(struct ng_attribute *attr, int percent)
341
range = attr->max - attr->min;
342
value = percent * range / 100 + attr->min;
343
if (value < attr->min)
345
if (value > attr->max)
351
ng_attr_parse_int(struct ng_attribute *attr, char *str)
355
if (0 == sscanf(str,"%d%n",&value,&n))
359
value = ng_attr_percent2int(attr,value);
360
if (value < attr->min)
362
if (value > attr->max)
367
/* --------------------------------------------------------------------- */
370
ng_ratio_fixup(int *width, int *height, int *xoff, int *yoff)
375
if (0 == ng_ratio_x || 0 == ng_ratio_y)
377
if (w * ng_ratio_y < h * ng_ratio_x) {
378
*height = *width * ng_ratio_y / ng_ratio_x;
380
*yoff += (h-*height)/2;
381
} else if (w * ng_ratio_y > h * ng_ratio_x) {
382
*width = *height * ng_ratio_x / ng_ratio_y;
384
*xoff += (w-*width)/2;
389
ng_ratio_fixup2(int *width, int *height, int *xoff, int *yoff,
390
int ratio_x, int ratio_y, int up)
395
if (0 == ratio_x || 0 == ratio_y)
397
if ((!up && w * ratio_y < h * ratio_x) ||
398
(up && w * ratio_y > h * ratio_x)) {
399
*height = *width * ratio_y / ratio_x;
401
*yoff += (h-*height)/2;
402
} else if ((!up && w * ratio_y > h * ratio_x) ||
403
(up && w * ratio_y < h * ratio_x)) {
404
*width = *height * ratio_x / ratio_y;
406
*xoff += (w-*width)/2;
410
/* --------------------------------------------------------------------- */
414
LIST_HEAD(ng_filters);
415
LIST_HEAD(ng_writers);
416
LIST_HEAD(ng_readers);
417
LIST_HEAD(ng_vid_drivers);
418
LIST_HEAD(ng_dsp_drivers);
419
LIST_HEAD(ng_mix_drivers);
421
static int ng_check_magic(int magic, char *plugname, char *type)
425
h=strrchr(plugname,'/');
431
if (magic != NG_PLUGIN_MAGIC) {
432
fprintf(stderr, "ERROR: plugin magic mismatch [me=%x,%s=%x]\n",
433
NG_PLUGIN_MAGIC,h,magic);
438
fprintf(stderr,"plugins: %s registered by %s\n",type,plugname);
444
ng_conv_register(int magic, char *plugname,
445
struct ng_video_conv *list, int count)
449
if (0 != ng_check_magic(magic,plugname,"video converters"))
451
for (n = 0; n < count; n++)
452
list_add_tail(&(list[n].list),&ng_conv);
457
ng_aconv_register(int magic, char *plugname,
458
struct ng_audio_conv *list, int count)
462
if (0 != ng_check_magic(magic,plugname,"audio converters"))
464
for (n = 0; n < count; n++)
465
list_add_tail(&(list[n].list),&ng_aconv);
470
ng_filter_register(int magic, char *plugname, struct ng_video_filter *filter)
472
if (0 != ng_check_magic(magic,plugname,"filter"))
474
list_add_tail(&filter->list,&ng_filters);
479
ng_writer_register(int magic, char *plugname, struct ng_writer *writer)
481
if (0 != ng_check_magic(magic,plugname,"writer"))
483
list_add_tail(&writer->list,&ng_writers);
488
ng_reader_register(int magic, char *plugname, struct ng_reader *reader)
490
if (0 != ng_check_magic(magic,plugname,"reader"))
492
list_add_tail(&reader->list,&ng_readers);
497
ng_vid_driver_register(int magic, char *plugname, struct ng_vid_driver *driver)
499
struct list_head *item;
500
struct ng_vid_driver *drv;
502
if (0 != ng_check_magic(magic,plugname,"video drv"))
505
list_for_each(item,&ng_vid_drivers) {
506
drv = list_entry(item, struct ng_vid_driver, list);
507
if (drv->priority > driver->priority) {
508
list_add_tail(&driver->list,&drv->list);
512
list_add_tail(&driver->list,&ng_vid_drivers);
517
ng_dsp_driver_register(int magic, char *plugname, struct ng_dsp_driver *driver)
519
struct list_head *item;
520
struct ng_dsp_driver *drv;
522
if (0 != ng_check_magic(magic,plugname,"dsp drv"))
525
list_for_each(item,&ng_dsp_drivers) {
526
drv = list_entry(item, struct ng_dsp_driver, list);
527
if (drv->priority > driver->priority) {
528
list_add_tail(&driver->list,&drv->list);
532
list_add_tail(&driver->list,&ng_dsp_drivers);
537
ng_mix_driver_register(int magic, char *plugname, struct ng_mix_driver *driver)
539
struct list_head *item;
540
struct ng_mix_driver *drv;
542
if (0 != ng_check_magic(magic,plugname,"mixer drv"))
545
list_for_each(item,&ng_mix_drivers) {
546
drv = list_entry(item, struct ng_mix_driver, list);
547
if (drv->priority > driver->priority) {
548
list_add_tail(&driver->list,&drv->list);
552
list_add_tail(&driver->list,&ng_mix_drivers);
556
struct ng_video_conv*
557
ng_conv_find_to(unsigned int out, int *i)
559
struct list_head *item;
560
struct ng_video_conv *ret;
563
list_for_each(item,&ng_conv) {
568
ret = list_entry(item, struct ng_video_conv, list);
570
fprintf(stderr,"\tconv to: %-28s => %s\n",
571
ng_vfmt_to_desc[ret->fmtid_in],
572
ng_vfmt_to_desc[ret->fmtid_out]);
574
if (ret->fmtid_out == out) {
584
struct ng_video_conv*
585
ng_conv_find_from(unsigned int in, int *i)
587
struct list_head *item;
588
struct ng_video_conv *ret;
592
list_for_each(item,&ng_conv) {
597
ret = list_entry(item, struct ng_video_conv, list);
599
fprintf(stderr,"\tconv from: %-28s => %s\n",
600
ng_vfmt_to_desc[ret->fmtid_in],
601
ng_vfmt_to_desc[ret->fmtid_out]);
603
if (ret->fmtid_in == in) {
611
struct ng_video_conv*
612
ng_conv_find_match(unsigned int in, unsigned int out)
614
struct list_head *item;
615
struct ng_video_conv *ret = NULL;
617
list_for_each(item,&ng_conv) {
618
ret = list_entry(item, struct ng_video_conv, list);
619
if (ret->fmtid_in == in && ret->fmtid_out == out)
625
/* --------------------------------------------------------------------- */
627
int ng_vid_init(struct ng_devstate *dev, char *device)
629
struct list_head *item;
630
struct ng_vid_driver *drv;
631
struct ng_attribute *attr;
635
/* check all grabber drivers */
636
memset(dev,0,sizeof(*dev));
637
list_for_each(item,&ng_vid_drivers) {
638
drv = list_entry(item, struct ng_vid_driver, list);
640
fprintf(stderr,"vid-open: trying: %s... \n", drv->name);
641
if (NULL != (handle = drv->init(device)))
646
fprintf(stderr,"vid-open: failed: %s\n",drv->name);
648
if (item == &ng_vid_drivers)
651
fprintf(stderr,"vid-open: ok: %s\n", drv->name);
653
dev->type = NG_DEV_VIDEO;
655
dev->handle = handle;
656
dev->device = dev->v->devname(dev->handle);
657
dev->flags = dev->v->capabilities(dev->handle);
659
fprintf(stderr,"vid-open: flags: %x\n", dev->flags);
661
INIT_LIST_HEAD(&dev->attrs);
662
attr = dev->v->list_attrs(dev->handle);
663
for (i = 0; attr && attr[i].name; i++) {
665
attr[i].group = dev->device;
666
list_add_tail(&attr[i].device_list,&dev->attrs);
671
struct ng_devinfo* ng_vid_probe(char *driver)
673
struct list_head *item;
674
struct ng_vid_driver *drv;
676
/* check all grabber drivers */
677
list_for_each(item,&ng_vid_drivers) {
678
drv = list_entry(item, struct ng_vid_driver, list);
680
fprintf(stderr,"vid-probe: trying: %s... \n", drv->name);
681
if (strcmp(driver, drv->name))
684
return drv->probe(ng_debug);
690
int ng_dsp_init(struct ng_devstate *dev, char *device, int record)
692
struct list_head *item;
693
struct ng_dsp_driver *drv;
697
/* check all dsp drivers */
698
list_for_each(item,&ng_dsp_drivers) {
699
drv = list_entry(item, struct ng_dsp_driver, list);
700
if (record && NULL == drv->read)
702
if (!record && NULL == drv->write)
705
fprintf(stderr, "dsp-open: trying: %s... \n", drv->name);
706
if (NULL != (handle = drv->init(device, record)))
711
fprintf(stderr,"dsp-open: failed: %s\n", drv->name);
713
if (item == &ng_dsp_drivers)
716
fprintf(stderr,"dsp-open: ok: %s\n",drv->name);
718
memset(dev,0,sizeof(*dev));
719
dev->type = NG_DEV_DSP;
721
dev->handle = handle;
722
dev->device = dev->a->devname(dev->handle);
723
//dev->flags = dev->a->capabilities(dev->handle);
724
INIT_LIST_HEAD(&dev->attrs);
729
int ng_mix_init(struct ng_devstate *dev, char *device, char *control)
731
struct list_head *item;
732
struct ng_mix_driver *drv;
733
struct ng_attribute *attr;
737
/* check all dsp drivers */
738
list_for_each(item,&ng_mix_drivers) {
739
drv = list_entry(item, struct ng_mix_driver, list);
741
fprintf(stderr, "mix-open: trying: %s... \n", drv->name);
742
if (NULL != (handle = drv->init(device, control)))
747
fprintf(stderr,"mix-open: failed: %s\n", drv->name);
749
if (item == &ng_mix_drivers)
752
fprintf(stderr,"mix-open: ok: %s\n",drv->name);
754
memset(dev,0,sizeof(*dev));
755
dev->type = NG_DEV_MIX;
757
dev->handle = handle;
758
dev->device = dev->m->devname(dev->handle);
760
INIT_LIST_HEAD(&dev->attrs);
761
attr = dev->m->list_attrs(dev->handle);
762
for (i = 0; attr && attr[i].name; i++) {
764
attr[i].group = dev->device;
765
list_add_tail(&attr[i].device_list,&dev->attrs);
771
int ng_dev_fini(struct ng_devstate *dev)
778
dev->v->fini(dev->handle);
781
dev->a->fini(dev->handle);
784
dev->m->fini(dev->handle);
787
memset(dev,0,sizeof(*dev));
791
int ng_dev_open(struct ng_devstate *dev)
795
if (0 == dev->refcount) {
798
BUG_ON(1,"dev type NONE");
801
rc = dev->v->open(dev->handle);
804
rc = dev->a->open(dev->handle);
807
rc = dev->m->open(dev->handle);
814
fprintf(stderr,"%s: opened %s [refcount %d]\n",
815
__FUNCTION__, dev->device, dev->refcount);
820
int ng_dev_close(struct ng_devstate *dev)
823
BUG_ON(dev->refcount < 0, "refcount below 0");
825
if (0 == dev->refcount) {
828
BUG_ON(1,"dev type NONE");
831
dev->v->close(dev->handle);
834
dev->a->close(dev->handle);
837
dev->m->close(dev->handle);
842
fprintf(stderr,"%s: closed %s [refcount %d]\n",
843
__FUNCTION__, dev->device, dev->refcount);
847
int ng_dev_users(struct ng_devstate *dev)
849
return dev->refcount;
852
int ng_chardev_open(char *device, int flags, int major, int complain)
857
if (strncmp(device, "/dev/", 5)) {
859
fprintf(stderr,"%s: not below /dev\n",device);
862
if (-1 == (fd = open(device, flags))) {
864
fprintf(stderr,"open(%s): %s\n",device,strerror(errno));
867
if (-1 == fstat(fd,&st)) {
869
fprintf(stderr,"fstat(%s): %s\n",device,strerror(errno));
872
if (!S_ISCHR(st.st_mode)) {
874
fprintf(stderr,"%s: not a charcter device\n",device);
877
if (major(st.st_rdev) != major) {
879
fprintf(stderr,"%s: wrong major number (expected %d, got %d)\n",
880
device, major, major(st.st_rdev));
883
fcntl(fd,F_SETFD,FD_CLOEXEC);
892
/* --------------------------------------------------------------------- */
894
struct ng_reader* ng_find_reader_magic(char *filename)
896
struct list_head *item;
897
struct ng_reader *reader;
902
if (NULL == (fp = fopen(filename, "r"))) {
903
fprintf(stderr,"open %s: %s\n",filename,strerror(errno));
906
memset(blk,0,sizeof(blk));
907
fread(blk,1,sizeof(blk),fp);
910
list_for_each(item,&ng_readers) {
911
reader = list_entry(item, struct ng_reader, list);
912
for (m = 0; m < 8 && reader->mlen[m] > 0; m++) {
913
if (0 == memcmp(blk+reader->moff[m],reader->magic[m],
919
fprintf(stderr,"%s: no reader found [magic]\n",filename);
923
struct ng_reader* ng_find_reader_name(char *name)
925
struct list_head *item;
926
struct ng_reader *reader;
928
list_for_each(item,&ng_readers) {
929
reader = list_entry(item, struct ng_reader, list);
930
if (0 == strcasecmp(reader->name,name))
934
fprintf(stderr,"%s: no reader found [name]\n",name);
938
struct ng_writer* ng_find_writer_name(char *name)
940
struct list_head *item;
941
struct ng_writer *writer;
943
list_for_each(item,&ng_writers) {
944
writer = list_entry(item, struct ng_writer, list);
945
if (0 == strcasecmp(writer->name,name))
949
fprintf(stderr,"%s: no writer found [name]\n",name);
954
ng_tofday_to_timestamp(struct timeval *tv)
970
gettimeofday(&tv,NULL);
971
return ng_tofday_to_timestamp(&tv);
975
ng_filter_single(struct ng_video_filter *filter, struct ng_video_buf *in)
977
struct ng_video_buf *out = in;
980
if (NULL != filter && filter->fmts & (1 << in->fmt.fmtid)) {
981
handle = filter->init(&in->fmt);
983
BUG_ON(1,"not fixed yet");
984
out = filter->frame(handle,in);
985
filter->fini(handle);
991
/* --------------------------------------------------------------------- */
993
static void clip_dump(char *state, struct OVERLAY_CLIP *oc, int count)
997
fprintf(stderr,"clip: %s - %d clips\n",state,count);
998
for (i = 0; i < count; i++)
999
fprintf(stderr,"clip: %d: %dx%d+%d+%d\n",i,
1000
oc[i].x2 - oc[i].x1,
1001
oc[i].y2 - oc[i].y1,
1002
oc[i].x1, oc[i].y1);
1005
static void clip_drop(struct OVERLAY_CLIP *oc, int n, int *count)
1008
memmove(oc+n, oc+n+1, sizeof(struct OVERLAY_CLIP) * (*count-n));
1011
void ng_check_clipping(int width, int height, int xadjust, int yadjust,
1012
struct OVERLAY_CLIP *oc, int *count)
1017
fprintf(stderr,"clip: win=%dx%d xa=%d ya=%d\n",
1018
width,height,xadjust,yadjust);
1019
clip_dump("init",oc,*count);
1021
for (i = 0; i < *count; i++) {
1022
/* fixup coordinates */
1023
oc[i].x1 += xadjust;
1024
oc[i].x2 += xadjust;
1025
oc[i].y1 += yadjust;
1026
oc[i].y2 += yadjust;
1029
clip_dump("fixup adjust",oc,*count);
1031
for (i = 0; i < *count; i++) {
1037
if (oc[i].x1 > width)
1039
if (oc[i].x2 > width)
1045
if (oc[i].y1 > height)
1047
if (oc[i].y2 > height)
1051
clip_dump("fixup range",oc,*count);
1053
/* drop zero-sized clips */
1054
for (i = 0; i < *count;) {
1055
if (oc[i].x1 == oc[i].x2 || oc[i].y1 == oc[i].y2) {
1056
clip_drop(oc,i,count);
1062
clip_dump("zerosize done",oc,*count);
1064
/* try to merge clips */
1066
for (j = *count - 1; j >= 0; j--) {
1067
for (i = 0; i < *count; i++) {
1070
if (oc[i].x1 == oc[j].x1 &&
1071
oc[i].x2 == oc[j].x2 &&
1072
oc[i].y1 <= oc[j].y1 &&
1073
oc[i].y2 >= oc[j].y1) {
1075
fprintf(stderr,"clip: merge y %d,%d\n",i,j);
1076
if (oc[i].y2 < oc[j].y2)
1077
oc[i].y2 = oc[j].y2;
1078
clip_drop(oc,j,count);
1080
clip_dump("merge y done",oc,*count);
1083
if (oc[i].y1 == oc[j].y1 &&
1084
oc[i].y2 == oc[j].y2 &&
1085
oc[i].x1 <= oc[j].x1 &&
1086
oc[i].x2 >= oc[j].x1) {
1088
fprintf(stderr,"clip: merge x %d,%d\n",i,j);
1089
if (oc[i].x2 < oc[j].x2)
1090
oc[i].x2 = oc[j].x2;
1091
clip_drop(oc,j,count);
1093
clip_dump("merge x done",oc,*count);
1099
clip_dump("final",oc,*count);
1102
/* --------------------------------------------------------------------- */
1105
void ng_print_stacktrace(void)
1112
size = backtrace(array, DIMOF(array));
1113
strings = backtrace_symbols(array, size);
1115
for (i = 0; i < size; i++)
1116
fprintf(stderr, "\t%s\n", strings[i]);
1121
static int ng_plugins(char *dirname)
1123
struct dirent **list;
1124
char filename[1024];
1127
void (*initcall)(void);
1131
n = scandir(dirname,&list,NULL,alphasort);
1134
for (i = 0; i < n; i++) {
1135
if (0 != fnmatch("*.so",list[i]->d_name,0))
1137
sprintf(filename,"%s/%s",dirname,list[i]->d_name);
1138
if (NULL == (plugin = dlopen(filename,RTLD_NOW))) {
1139
fprintf(stderr,"dlopen: %s\n",dlerror());
1143
if (NULL == (initcall = dlsym(plugin,"ng_plugin_init"))) {
1144
if (NULL == (initcall = dlsym(plugin,"_ng_plugin_init"))) {
1145
fprintf(stderr,"dlsym[%s]: %s\n",filename,dlerror());
1154
for (i = 0; i < n; i++)
1167
fprintf(stderr,"panic: ng_init called twice\n");
1175
/* dirty hack: touch ng_dev to make ld _not_ drop devices.o, it is
1176
* needed by various plugins */
1177
if (!ng_dev.video[0])
1180
count += ng_plugins(LIBDIR);
1181
count += ng_plugins("./libng/plugins");
1182
count += ng_plugins("./libng/contrib-plugins");
1183
count += ng_plugins("../libng/plugins");
1184
count += ng_plugins("../libng/contrib-plugins");
1185
count += ng_plugins("./utils/linux/capture/libng/plugins");
1186
count += ng_plugins("./utils/linux/capture/libng/contrib-plugins");
1190
fprintf(stderr,"WARNING: no plugins found [%s]\n",LIBDIR);