1 /*
2 channel for Bt848 frame grabber driver
3
4 Copyright (C) 1996,97 Marcus Metzler (mocm@thp.uni-koeln.de)
5 (c) 1998-2003 Gerd Knorr <kraxel@bytesex.org>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "config.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <ctype.h>
29 #include <math.h>
30 #include <pthread.h>
31
32 #ifndef NO_X11
33 # include <X11/Xlib.h>
34 # include <X11/Intrinsic.h>
35 # include <X11/StringDefs.h>
36 # include <X11/Xaw/XawInit.h>
37 # include <X11/Xaw/Command.h>
38 # include <X11/Xaw/Paned.h>
39 #endif
40
41 #include "grab-ng.h"
42 #include "channel.h"
43 #include "commands.h"
44 #include "frequencies.h"
45 #include "sound.h"
46 #include "parseconfig.h"
47 #include "event.h"
48
49 /* ----------------------------------------------------------------------- */
50 /* misc common stuff, not only channel related */
51
52 struct CHANNEL defaults = {
53 name: "defaults",
54 group: "main",
55 capture: CAPTURE_ON,
56 channel: -1,
57 audio: -1,
58 color: -1,
59 bright: -1,
60 hue: -1,
61 contrast: -1,
62 };
63
64 struct CHANNEL **channels = NULL;
65 int count = 0;
66 int alloc_count = 0;
67
68 int last_sender = -1, cur_sender = -1, cur_channel = -1, cur_fine = 0;
69 int cur_freq;
70 struct ng_filter *cur_filter;
71
72 int cur_capture = CAPTURE_OFF;
73 int have_config;
74 int keypad_ntsc = 0;
75 int keypad_partial = 1;
76 int use_wm_fullscreen = 1;
77 int use_osd = 1;
78 int osd_x = 30;
79 int osd_y = 20;
80 int fs_width,fs_height,fs_xoff,fs_yoff;
81 int pix_width=128, pix_height=96, pix_cols=1;
82
83 char *mov_driver = NULL;
84 char *mov_video = NULL;
85 char *mov_fps = NULL;
86 char *mov_audio = NULL;
87 char *mov_rate = NULL;
88
89 #ifndef NO_X11
90 extern Widget chan_box, chan_viewport, tv, opt_paned, launch_paned;
91 #endif
92
93 static char *mixer = NULL;
94 char mixerdev[32],mixerctl[16];
95 char *midi = NULL;
96
97 struct LAUNCH *launch = NULL;
98 int nlaunch = 0;
99
100 /* ----------------------------------------------------------------------- */
101
102 int lookup_channel(char *channel)
103 {
104 #if 0
105 /* Hmm, why the heck that used to be that complex?
106 * Any good reason I forgot ? */
107 int i,nr1,nr2;
108 char tag1[5],tag2[5];
109
110 if (NULL == channel)
111 return -1;
112
113 if (isdigit(channel[0])) {
114 tag1[0] = 0;
115 nr1 = atoi(channel);
116 } else {
117 sscanf(channel,"%4[A-Za-z]%d",tag1,&nr1);
118 }
119
120 for (i = 0; i < chancount; i++) {
121 if (isdigit(chanlist[i].name[0])) {
122 tag2[0] = 0;
123 nr2 = atoi(chanlist[i].name);
124 } else {
125 sscanf(chanlist[i].name,"%4[A-Za-z]%d",tag2,&nr2);
126 }
127 if (tag1[0] && tag2[0])
128 if (nr1 == nr2 && 0 == strcmp(tag1,tag2))
129 break;
130 if (!tag1[0] && !tag2[0])
131 if (nr1 == nr2)
132 break;
133 }
134 if (i == chancount)
135 return -1;
136
137 return i;
138 #else
139 int i;
140
141 if (NULL == channel)
142 return -1;
143 for (i = 0; i < chancount; i++)
144 if (0 == strcasecmp(chanlist[i].name,channel))
145 break;
146 if (i == chancount)
147 return -1;
148 return i;
149 #endif
150 }
151
152 int get_freq(int i)
153 {
154 if (i < 0 || i >= chancount)
155 return -1;
156 return chanlist[i].freq*16/1000;
157 }
158
159 int cf2freq(char *name, int fine)
160 {
161 int i;
162
163 if (-1 == (i = lookup_channel(name)))
164 return -1;
165 return get_freq(i)+fine;
166 }
167
168 /* ----------------------------------------------------------------------- */
169
170 struct STRTAB captab[] = {
171 { CAPTURE_ON, "on" },
172 { CAPTURE_ON, "yes" },
173 { CAPTURE_ON, "true" },
174 { CAPTURE_OFF, "off" },
175 { CAPTURE_OFF, "no" },
176 { CAPTURE_OFF, "false" },
177 { CAPTURE_OVERLAY, "over" },
178 { CAPTURE_OVERLAY, "overlay" },
179 { CAPTURE_GRABDISPLAY, "grab" },
180 { CAPTURE_GRABDISPLAY, "grabdisplay" },
181 { -1, NULL, },
182 };
183
184 /* just malloc memory for a new channel ... */
185 struct CHANNEL*
186 add_channel(char *name)
187 {
188 struct CHANNEL *channel;
189
190 if (alloc_count == count) {
191 alloc_count += 16;
192 if (alloc_count == 16)
193 channels = malloc(sizeof(struct CHANNEL*)*alloc_count);
194 else
195 channels = realloc(channels,sizeof(struct CHANNEL*)*alloc_count);
196 }
197 channel = channels[count++] = malloc(sizeof(struct CHANNEL));
198 memcpy(channel,&defaults,sizeof(struct CHANNEL));
199 channel->name = strdup(name);
200 return channel;
201 }
202
203 #ifndef NO_X11
204
205 #define PANED_FIX \
206 XtNallowResize, False, \
207 XtNshowGrip, False, \
208 XtNskipAdjust, True
209
210 void hotkey_channel(struct CHANNEL *channel)
211 {
212 char str[100],key[32],ctrl[16];
213
214 if (NULL == channel->key)
215 return;
216 if (2 == sscanf(channel->key,"%15[A-Za-z0-9_]+%31[A-Za-z0-9_]",
217 ctrl,key))
218 sprintf(str,"%s<Key>%s: Command(setstation,\"%s\")",
219 ctrl,key,channel->name);
220 else
221 sprintf(str,"<Key>%s: Command(setstation,\"%s\")",
222 channel->key,channel->name);
223 XtOverrideTranslations(tv,XtParseTranslationTable(str));
224 XtOverrideTranslations(opt_paned,XtParseTranslationTable(str));
225 XtOverrideTranslations(chan_viewport,XtParseTranslationTable(str));
226 }
227
228 static void
229 launch_cb(Widget widget, XtPointer clientdata, XtPointer call_data)
230 {
231 char *argv[2];
232
233 argv[0] = (char*)clientdata;
234 argv[1] = NULL;
235 XtCallActionProc(widget,"Launch",NULL,argv,1);
236 }
237
238 static void
239 hotkey_launch(struct LAUNCH *launch)
240 {
241 Widget c;
242 char str[100],key[32],ctrl[16],label[64];
243
244 if (NULL == launch->key)
245 return;
246 if (2 == sscanf(launch->key,"%15[A-Za-z0-9_]+%31[A-Za-z0-9_]",
247 ctrl,key))
248 sprintf(str,"%s<Key>%s: Launch(\"%s\")",ctrl,key,launch->name);
249 else
250 sprintf(str,"<Key>%s: Launch(\"%s\")",launch->key,launch->name);
251 XtOverrideTranslations(tv,XtParseTranslationTable(str));
252 XtOverrideTranslations(opt_paned,XtParseTranslationTable(str));
253 XtOverrideTranslations(chan_viewport,XtParseTranslationTable(str));
254
255 sprintf(label,"%-20s %s",launch->name,launch->key);
256 c = XtVaCreateManagedWidget(launch->name, commandWidgetClass,
257 launch_paned,
258 PANED_FIX,
259 XtNlabel,label,
260 NULL);
261 XtAddCallback(c,XtNcallback,launch_cb,(XtPointer)(launch->name));
262 }
263
264 static void
265 button_cb(Widget widget, XtPointer clientdata, XtPointer call_data)
266 {
267 struct CHANNEL *channel = clientdata;
268 do_va_cmd(2,"setstation",channel->name);
269 }
270
271 /* ... and initalize later */
272 void configure_channel(struct CHANNEL *channel)
273 {
274 channel->button =
275 XtVaCreateManagedWidget(channel->name,
276 commandWidgetClass, chan_box,
277 XtNwidth,pix_width,
278 XtNheight,pix_height,
279 NULL);
280 XtAddCallback(channel->button,XtNcallback,button_cb,(XtPointer*)channel);
281 hotkey_channel(channel);
282 }
283 #endif
284
285 /* delete channel */
286 void
287 del_channel(int i)
288 {
289 free(channels[i]->name);
290 if (channels[i]->key)
291 free(channels[i]->key);
292 free(channels[i]);
293 count--;
294 if (i < count)
295 memmove(channels+i,channels+i+1,(count-i)*sizeof(struct CHANNEL*));
296 }
297
298 void
299 calc_frequencies()
300 {
301 int i;
302
303 for (i = 0; i < count; i++) {
304 if (NULL == channels[i]->cname)
305 continue;
306 channels[i]->channel = lookup_channel(channels[i]->cname);
307 if (-1 == channels[i]->channel)
308 channels[i]->freq = -1;
309 else
310 channels[i]->freq = get_freq(channels[i]->channel)
311 + channels[i]->fine;
312 }
313 }
314
315 /* ----------------------------------------------------------------------- */
316
317 static void
318 init_channel(char *name, struct CHANNEL *c)
319 {
320 struct ng_attribute *attr;
321 char *val; int n,i;
322
323 if (NULL != (val = cfg_get_str(name,"capture"))) {
324 if (-1 != (i = str_to_int(val,captab)))
325 c->capture = i;
326 else
327 fprintf(stderr,"config: invalid value for capture: %s\n",val);
328 }
329 if (NULL != (attr = ng_attr_byid(attrs,ATTR_ID_INPUT)) &&
330 (NULL != (val = cfg_get_str(name,"input")) ||
331 NULL != (val = cfg_get_str(name,"source")))) { /* obsolete */
332 if (-1 != (i = ng_attr_getint(attr,val)))
333 c->input = i;
334 else {
335 fprintf(stderr,"config: invalid value for input: %s\n",val);
336 ng_attr_listchoices(attr);
337 }
338 }
339 if (NULL != (attr = ng_attr_byid(attrs,ATTR_ID_NORM)) &&
340 NULL != (val = cfg_get_str(name,"norm"))) {
341 if (-1 != (i = ng_attr_getint(attr,val)))
342 c->norm = i;
343 else {
344 fprintf(stderr,"config: invalid value for norm: %s\n",val);
345 ng_attr_listchoices(attr);
346 }
347 }
348 if (NULL != (attr = ng_attr_byid(attrs,ATTR_ID_AUDIO_MODE)) &&
349 NULL != (val = cfg_get_str(name,"audio"))) {
350 if (-1 != (i = ng_attr_getint(attr,val)))
351 c->audio = i;
352 else {
353 fprintf(stderr,"config: invalid value for audio: %s\n",val);
354 ng_attr_listchoices(attr);
355 }
356 }
357
358 if (NULL != (val = cfg_get_str(name,"channel")))
359 c->cname = strdup(val);
360 if (NULL != (val = cfg_get_str(name,"freq")))
361 c->freq = (int)(atof(val)*16);
362 if (0 != (n = cfg_get_signed_int(name,"fine")))
363 c->fine = n;
364
365 if (NULL != (val = cfg_get_str(name,"key")))
366 c->key = strdup(val);
367 if (NULL != (val = cfg_get_str(name,"group")))
368 c->group = strdup(val);
369 if (NULL != (val = cfg_get_str(name,"midi")))
370 c->midi = atoi(val);
371
372 attr = ng_attr_byid(attrs,ATTR_ID_COLOR);
373 if (attr && NULL != (val = cfg_get_str(name,"color")))
374 c->color = ng_attr_parse_int(attr,val);
375 attr = ng_attr_byid(attrs,ATTR_ID_BRIGHT);
376 if (attr && NULL != (val = cfg_get_str(name,"bright")))
377 c->bright = ng_attr_parse_int(attr,val);
378 attr = ng_attr_byid(attrs,ATTR_ID_HUE);
379 if (attr && NULL != (val = cfg_get_str(name,"hue")))
380 c->hue = ng_attr_parse_int(attr,val);
381 attr = ng_attr_byid(attrs,ATTR_ID_CONTRAST);
382 if (attr && NULL != (val = cfg_get_str(name,"contrast")))
383 c->contrast = ng_attr_parse_int(attr,val);
384 }
385
386 void
387 read_config(char *conffile, int *argc, char **argv)
388 {
389 struct list_head *item;
390 char filename[100];
391 char *val;
392 int i;
393
394 if (conffile) {
395 if (0 == cfg_parse_file(conffile))
396 have_config = 1;
397 } else {
398 sprintf(filename,"%.*s/%s",(int)sizeof(filename)-8,
399 getenv("HOME"),".xawtv");
400 if (0 == cfg_parse_file(CONFIGFILE))
401 have_config = 1;
402 if (0 == cfg_parse_file(filename))
403 have_config = 1;
404 }
405 if (argc)
406 cfg_parse_options(argc,argv);
407
408 /* misc global settings */
409 if (NULL != (val = cfg_get_str("global","mixer"))) {
410 mixer = strdup(val);
411 if (2 != sscanf(mixer,"%31[^:]:%15s",mixerdev,mixerctl)) {
412 strcpy(mixerdev,ng_dev.mixer);
413 strncpy(mixerctl,val,15);
414 mixerctl[15] = 0;
415 }
416 }
417
418 if (NULL != (val = cfg_get_str("global","midi")))
419 midi = strdup(val);
420
421 if (NULL != (val = cfg_get_str("global","freqtab"))) {
422 for (i = 0; chanlists[i].name != NULL; i++)
423 if (0 == strcasecmp(val,chanlists[i].name))
424 break;
425 if (chanlists[i].name != NULL) {
426 freq_newtab(i);
427 } else
428 fprintf(stderr,"invalid value for freqtab: %s\n",val);
429 }
430
431 if (NULL != (val = cfg_get_str("global","fullscreen"))) {
432 if (2 != sscanf(val,"%d x %d",&fs_width,&fs_height)) {
433 fprintf(stderr,"invalid value for fullscreen: %s\n",val);
434 fs_width = fs_height = 0;
435 }
436 }
437
438 if (NULL != (val = cfg_get_str("global","pixsize"))) {
439 if (2 != sscanf(val,"%d x %d",&pix_width,&pix_height)) {
440 fprintf(stderr,"invalid value for pixsize: %s\n",val);
441 pix_width = 128;
442 pix_height = 96;
443 }
444 }
445 if (-1 != (i = cfg_get_int("global","pixcols")))
446 pix_cols = i;
447
448 if (NULL != (val = cfg_get_str("global","wm-off-by"))) {
449 if (2 != sscanf(val,"%d %d",&fs_xoff,&fs_yoff)) {
450 fprintf(stderr,"invalid value for wm-off-by: %s\n",val);
451 fs_xoff = fs_yoff = 0;
452 }
453 }
454 if (NULL != (val = cfg_get_str("global","ratio"))) {
455 if (2 != sscanf(val,"%d:%d",&ng_ratio_x,&ng_ratio_y)) {
456 fprintf(stderr,"invalid value for ratio: %s\n",val);
457 ng_ratio_x = ng_ratio_y = 0;
458 }
459 }
460
461 if (-1 != (i = cfg_get_int("global","jpeg-quality")))
462 ng_jpeg_quality = i;
463
464 if (NULL != (val = cfg_get_str("global","keypad-ntsc")))
465 if (-1 != (i = str_to_int(val,booltab)))
466 keypad_ntsc = i;
467 if (NULL != (val = cfg_get_str("global","keypad-partial")))
468 if (-1 != (i = str_to_int(val,booltab)))
469 keypad_partial = i;
470 if (NULL != (val = cfg_get_str("global","osd")))
471 if (-1 != (i = str_to_int(val,booltab)))
472 use_osd = i;
473 if (NULL != (val = cfg_get_str("global","osd-position")))
474 if (2 != sscanf(val,"%d , %d",&osd_x,&osd_y))
475 fprintf(stderr,"invalid values for osd-position: %s\n",val);
476 if (NULL != (val = cfg_get_str("global","use-wm-fullscreen")))
477 if (-1 != (i = str_to_int(val,booltab)))
478 use_wm_fullscreen = i;
479
480 if (NULL != (val = cfg_get_str("global","mov-driver")))
481 mov_driver = val;
482 if (NULL != (val = cfg_get_str("global","mov-video")))
483 mov_video = val;
484 if (NULL != (val = cfg_get_str("global","mov-fps")))
485 mov_fps = val;
486 if (NULL != (val = cfg_get_str("global","mov-audio")))
487 mov_audio = val;
488 if (NULL != (val = cfg_get_str("global","mov-rate")))
489 mov_rate = val;
490
491 if (NULL != (val = cfg_get_str("global","filter"))) {
492 list_for_each(item,&ng_filters) {
493 struct ng_filter *f = list_entry(item, struct ng_filter, list);
494 if (0 == strcasecmp(f->name, val))
495 cur_filter = f;
496 }
497 }
498 }
499
500 void
501 parse_config(void)
502 {
503 char key[16], cmdline[128];
504 char **list,*val;
505 #ifndef NO_X11
506 int i;
507 #endif
508
509 /* launch */
510 list = cfg_list_entries("launch");
511 if (NULL != list) {
512 for (; *list != NULL; list++) {
513 if (NULL != (val = cfg_get_str("launch",*list)) &&
514 2 == sscanf(val,"%15[^,], %127[^\n]",
515 key,cmdline)) {
516 launch = realloc(launch,sizeof(struct LAUNCH)*(nlaunch+1));
517 launch[nlaunch].name = strdup(*list);
518 launch[nlaunch].key = strdup(key);
519 launch[nlaunch].cmdline = strdup(cmdline);
520 #ifndef NO_X11
521 hotkey_launch(launch+nlaunch);
522 #endif
523 nlaunch++;
524 } else {
525 fprintf(stderr,"invalid value in section [launch]: %s\n",val);
526 }
527 }
528 }
529
530 /* events */
531 event_readconfig();
532
533 /* channels */
534 init_channel("defaults",&defaults);
535 for (list = cfg_list_sections(); *list != NULL; list++) {
536 if (0 == strcmp(*list,"defaults")) continue;
537 if (0 == strcmp(*list,"global")) continue;
538 if (0 == strcmp(*list,"launch")) continue;
539 if (0 == strcmp(*list,"eventmap")) continue;
540 init_channel(*list,add_channel(*list));
541 }
542
543 /* calculate channel frequencies */
544 defaults.channel = lookup_channel(defaults.cname);
545 defaults.freq = get_freq(defaults.channel) + defaults.fine;
546 calc_frequencies();
547 #ifndef NO_X11
548 for (i = 0; i < count; i++)
549 configure_channel(channels[i]);
550 #endif
551 }
552
553 /* ----------------------------------------------------------------------- */
554
555 void
556 save_config()
557 {
558 struct ng_attribute *attr;
559 char filename1[100], filename2[100];
560 FILE *fp;
561 int i;
562
563 sprintf(filename1,"%s/%s",getenv("HOME"),".xawtv");
564 sprintf(filename2,"%s/%s",getenv("HOME"),".xawtv~");
565
566 /* delete old backup */
567 unlink(filename2);
568
569 /* current becomes backup */
570 if (0 == link(filename1,filename2))
571 unlink(filename1);
572
573 /* write new one... */
574 fp = fopen(filename1,"w");
575 if (NULL == fp) {
576 fprintf(stderr,"can't open config file %s\n",filename1);
577 return;
578 }
579
580 fprintf(fp,"[global]\n");
581 if (fs_width && fs_height)
582 fprintf(fp,"fullscreen = %d x %d\n",fs_width,fs_height);
583 if (fs_xoff || fs_yoff)
584 fprintf(fp,"wm-off-by = %+d%+d\n",fs_xoff,fs_yoff);
585 if (ng_ratio_x || ng_ratio_y)
586 fprintf(fp,"ratio = %d:%d\n",ng_ratio_x,ng_ratio_y);
587 fprintf(fp,"freqtab = %s\n",chanlists[chantab].name);
588 fprintf(fp,"pixsize = %d x %d\n",pix_width,pix_height);
589 fprintf(fp,"pixcols = %d\n",pix_cols);
590 fprintf(fp,"jpeg-quality = %d\n",ng_jpeg_quality);
591 fprintf(fp,"keypad-ntsc = %s\n",int_to_str(keypad_ntsc,booltab));
592 fprintf(fp,"keypad-partial = %s\n",int_to_str(keypad_partial,booltab));
593 fprintf(fp,"osd = %s\n",int_to_str(use_osd,booltab));
594 fprintf(fp,"osd-position = %d , %d\n",osd_x,osd_y);
595 fprintf(fp,"use-wm-fullscreen = %s\n",
596 int_to_str(use_wm_fullscreen,booltab));
597 if (mixer)
598 fprintf(fp,"mixer = %s\n",mixer);
599 if (midi)
600 fprintf(fp,"midi = %s\n",midi);
601
602 if (mov_driver)
603 fprintf(fp,"mov-driver = %s\n",mov_driver);
604 if (mov_video)
605 fprintf(fp,"mov-video = %s\n",mov_video);
606 if (mov_fps)
607 fprintf(fp,"mov-fps = %s\n",mov_fps);
608 if (mov_audio)
609 fprintf(fp,"mov-audio = %s\n",mov_audio);
610 if (mov_rate)
611 fprintf(fp,"mov-rate = %s\n",mov_rate);
612
613 fprintf(fp,"\n");
614
615 if (nlaunch > 0) {
616 fprintf(fp,"[launch]\n");
617 for (i = 0; i < nlaunch; i++) {
618 fprintf(fp,"%s = %s, %s\n",
619 launch[i].name,launch[i].key,launch[i].cmdline);
620 }
621 fprintf(fp,"\n");
622 }
623
624 /* events */
625 event_writeconfig(fp);
626
627 /* write help */
628 fprintf(fp,"# [Station name]\n");
629 fprintf(fp,"# capture = overlay | grabdisplay | on | off\n");
630 fprintf(fp,"# input = Television | Composite1 | S-Video | ...\n");
631 fprintf(fp,"# norm = PAL | NTSC | SECAM | ... \n");
632 fprintf(fp,"# channel = #\n");
633 fprintf(fp,"# fine = # (-128..+127)\n");
634 fprintf(fp,"# key = keysym | modifier+keysym\n");
635 fprintf(fp,"# color = #\n");
636 fprintf(fp,"# bright = #\n");
637 fprintf(fp,"# hue = #\n");
638 fprintf(fp,"# contrast = #\n");
639 fprintf(fp,"\n");
640
641 /* write defaults */
642 fprintf(fp,"[defaults]\n");
643 fprintf(fp,"group = %s\n",defaults.group);
644
645 fprintf(fp,"norm = %s\n",
646 ng_attr_getstr(ng_attr_byid(attrs,ATTR_ID_NORM),
647 cur_attrs[ATTR_ID_NORM]));
648 fprintf(fp,"input = %s\n",
649 ng_attr_getstr(ng_attr_byid(attrs,ATTR_ID_INPUT),
650 cur_attrs[ATTR_ID_INPUT]));
651 fprintf(fp,"capture = %s\n",int_to_str(cur_capture,captab));
652
653 attr = ng_attr_byid(attrs,ATTR_ID_COLOR);
654 if (attr && attr->defval != cur_attrs[ATTR_ID_COLOR])
655 fprintf(fp,"color = %d%%\n",
656 ng_attr_int2percent(attr,cur_attrs[ATTR_ID_COLOR]));
657 attr = ng_attr_byid(attrs,ATTR_ID_BRIGHT);
658 if (attr && attr->defval != cur_attrs[ATTR_ID_BRIGHT])
659 fprintf(fp,"bright = %d%%\n",
660 ng_attr_int2percent(attr,cur_attrs[ATTR_ID_BRIGHT]));
661 attr = ng_attr_byid(attrs,ATTR_ID_HUE);
662 if (attr && attr->defval != cur_attrs[ATTR_ID_HUE])
663 fprintf(fp,"hue = %d%%\n",
664 ng_attr_int2percent(attr,cur_attrs[ATTR_ID_HUE]));
665 attr = ng_attr_byid(attrs,ATTR_ID_CONTRAST);
666 if (attr && attr->defval != cur_attrs[ATTR_ID_CONTRAST])
667 fprintf(fp,"contrast = %d%%\n",
668 ng_attr_int2percent(attr,cur_attrs[ATTR_ID_CONTRAST]));
669 fprintf(fp,"\n");
670
671 /* write channels */
672 for (i = 0; i < count; i++) {
673 fprintf(fp,"[%s]\n",channels[i]->name);
674 if (NULL != channels[i]->cname) {
675 fprintf(fp,"channel = %s\n",chanlist[channels[i]->channel].name);
676 if (0 != channels[i]->fine)
677 fprintf(fp,"fine = %+d\n", channels[i]->fine);
678 } else {
679 fprintf(fp,"freq = %.2f\n",(float)(channels[i]->freq)/16);
680 }
681
682 if ( channels[i]->norm != cur_attrs[ATTR_ID_NORM])
683 fprintf(fp,"norm = %s\n",
684 ng_attr_getstr(ng_attr_byid(attrs,ATTR_ID_NORM),
685 channels[i]->norm));
686 if (channels[i]->input != cur_attrs[ATTR_ID_INPUT])
687 fprintf(fp,"input = %s\n",
688 ng_attr_getstr(ng_attr_byid(attrs,ATTR_ID_INPUT),
689 channels[i]->input));
690
691 if (channels[i]->key != NULL)
692 fprintf(fp,"key = %s\n",channels[i]->key);
693 if (0 != strcmp(channels[i]->group,defaults.group))
694 fprintf(fp,"group = %s\n",channels[i]->group);
695 if (channels[i]->midi != 0)
696 fprintf(fp,"midi = %d\n",channels[i]->midi);
697 if (channels[i]->capture != cur_capture)
698 fprintf(fp,"capture = %s\n",
699 int_to_str(channels[i]->capture,captab));
700
701 attr = ng_attr_byid(attrs,ATTR_ID_COLOR);
702 if (attr && cur_attrs[ATTR_ID_COLOR] != channels[i]->color)
703 fprintf(fp,"color = %d%%\n",
704 ng_attr_int2percent(attr,channels[i]->color));
705 attr = ng_attr_byid(attrs,ATTR_ID_BRIGHT);
706 if (attr && cur_attrs[ATTR_ID_BRIGHT] != channels[i]->bright)
707 fprintf(fp,"bright = %d%%\n",
708 ng_attr_int2percent(attr,channels[i]->bright));
709 attr = ng_attr_byid(attrs,ATTR_ID_HUE);
710 if (attr && cur_attrs[ATTR_ID_HUE] != channels[i]->hue)
711 fprintf(fp,"hue = %d%%\n",
712 ng_attr_int2percent(attr,channels[i]->hue));
713 attr = ng_attr_byid(attrs,ATTR_ID_CONTRAST);
714 if (attr && cur_attrs[ATTR_ID_CONTRAST] != channels[i]->contrast)
715 fprintf(fp,"contrast = %d%%\n",
716 ng_attr_int2percent(attr,channels[i]->contrast));
717
718 fprintf(fp,"\n");
719 }
720 fclose(fp);
721 }
722
723 /* ----------------------------------------------------------------------- */
724
725 struct STRTAB booltab[] = {
726 { 0, "no" },
727 { 0, "false" },
728 { 0, "off" },
729 { 1, "yes" },
730 { 1, "true" },
731 { 1, "on" },
732 { -1, NULL }
733 };
734
735 int
736 str_to_int(char *str, struct STRTAB *tab)
737 {
738 int i;
739
740 if (str[0] >= '' && str[0] <= '9')
741 return atoi(str);
742 for (i = 0; tab[i].str != NULL; i++)
743 if (0 == strcasecmp(str,tab[i].str))
744 return(tab[i].nr);
745 return -1;
746 }
747
748 const char*
749 int_to_str(int n, struct STRTAB *tab)
750 {
751 int i;
752
753 for (i = 0; tab[i].str != NULL; i++)
754 if (tab[i].nr == n)
755 return tab[i].str;
756 return NULL;
757 }
758
|
This page was automatically generated by the
LXR engine.
|