~ubuntu-branches/ubuntu/maverick/tvtime/maverick

« back to all changes in this revision

Viewing changes to src/tvtimeconf.c

  • Committer: Bazaar Package Importer
  • Author(s): Simon Law
  • Date: 2004-01-13 18:00:36 UTC
  • Revision ID: james.westby@ubuntu.com-20040113180036-h996q67t476jymsu
Tags: upstream-0.9.12
ImportĀ upstreamĀ versionĀ 0.9.12

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * Copyright (C) 2002, 2003 Doug Bell <drbell@users.sourceforge.net>
 
3
 * Copyright (C) 2003 Alexander Belov <asbel@mail.ru>
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation; either version 2, or (at your option)
 
8
 * any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software Foundation,
 
17
 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
18
 */
 
19
 
 
20
#define _GNU_SOURCE
 
21
#include <stdlib.h>
 
22
#include <stdio.h>
 
23
#include <string.h>
 
24
#include <getopt.h>
 
25
#include <sys/types.h>
 
26
#include <sys/stat.h>
 
27
#include <fcntl.h>
 
28
#include <ctype.h>
 
29
#include <unistd.h>
 
30
#include <dirent.h>
 
31
#include <langinfo.h>
 
32
#include <pwd.h>
 
33
#include <errno.h>
 
34
#include <libxml/parser.h>
 
35
#ifdef HAVE_CONFIG_H
 
36
# include "config.h"
 
37
#endif
 
38
#ifdef ENABLE_NLS
 
39
# define _(string) gettext (string)
 
40
# include "gettext.h"
 
41
#else
 
42
# define _(string) string
 
43
#endif
 
44
#include "tvtimeconf.h"
 
45
#include "input.h"
 
46
#include "station.h"
 
47
#include "utils.h"
 
48
 
 
49
#define MAX_KEYSYMS 350
 
50
#define MAX_BUTTONS 10
 
51
 
 
52
/* Mode list. */
 
53
typedef struct tvtime_modelist_s tvtime_modelist_t;
 
54
 
 
55
struct config_s
 
56
{
 
57
    int outputheight;
 
58
    int verbose;
 
59
    int aspect;
 
60
    int debug;
 
61
    int fullscreen;
 
62
    int priority;
 
63
    int ntsc_mode;
 
64
    int send_fields;
 
65
    char *output_driver;
 
66
    int apply_luma_correction;
 
67
    double luma_correction;
 
68
    int useposition;
 
69
    int fspos;
 
70
    int x;
 
71
    int y;
 
72
    int picsaverestore;
 
73
    int brightness;
 
74
    int contrast;
 
75
    int colour;
 
76
    int hue;
 
77
    int invert;
 
78
    int cc;
 
79
    int mirror;
 
80
 
 
81
    int keymap[ 8 * MAX_KEYSYMS ];
 
82
    char *keymap_arg[ 8 * MAX_KEYSYMS ];
 
83
    int keymapmenu[ 8 * MAX_KEYSYMS ];
 
84
    char *keymapmenu_arg[ 8 * MAX_KEYSYMS ];
 
85
    int buttonmap[ MAX_BUTTONS ];
 
86
    char *buttonmap_arg[ MAX_BUTTONS ];
 
87
    int buttonmapmenu[ MAX_BUTTONS ];
 
88
    char *buttonmapmenu_arg[ MAX_BUTTONS ];
 
89
 
 
90
    int inputwidth;
 
91
    int inputnum;
 
92
    char *v4ldev;
 
93
    char *norm;
 
94
    char *freq;
 
95
    char *ssdir;
 
96
    char *timeformat;
 
97
    char *audiomode;
 
98
    char *xmltvfile;
 
99
    unsigned int channel_text_rgb;
 
100
    unsigned int other_text_rgb;
 
101
 
 
102
    uid_t uid;
 
103
 
 
104
    char *rvr_filename;
 
105
    char *mpeg_filename;
 
106
 
 
107
    char *mixerdev;
 
108
 
 
109
    char *deinterlace_method;
 
110
    int check_freq_present;
 
111
 
 
112
    int use_xds;
 
113
    char *vbidev;
 
114
 
 
115
    int start_channel;
 
116
    int prev_channel;
 
117
    int framerate;
 
118
    int slave_mode;
 
119
 
 
120
    double overscan;
 
121
 
 
122
    char *config_filename;
 
123
    xmlDocPtr doc;
 
124
 
 
125
    int nummodes;
 
126
    tvtime_modelist_t *modelist;
 
127
};
 
128
 
 
129
/* Mode list. */
 
130
struct tvtime_modelist_s
 
131
{
 
132
    config_t settings;
 
133
    char *name;
 
134
    tvtime_modelist_t *next;
 
135
};
 
136
 
 
137
static void copy_config( config_t *dest, config_t *src )
 
138
{
 
139
    (*dest) = (*src);
 
140
 
 
141
    /* Some of these I am keeping invalid for now. */
 
142
    dest->v4ldev = 0;
 
143
    dest->vbidev = 0;
 
144
    dest->rvr_filename = 0;
 
145
    dest->mpeg_filename = 0;
 
146
    dest->mixerdev = 0;
 
147
    dest->config_filename = 0;
 
148
    dest->modelist = 0;
 
149
    dest->nummodes = 0;
 
150
    dest->doc = 0;
 
151
    dest->output_driver = 0;
 
152
    dest->audiomode = 0;
 
153
    dest->xmltvfile = 0;
 
154
 
 
155
    /* Useful strings must be copied. */
 
156
    dest->norm = strdup( src->norm );
 
157
    dest->freq = strdup( src->freq );
 
158
    dest->ssdir = strdup( src->ssdir );
 
159
    dest->timeformat = strdup( src->timeformat );
 
160
    dest->deinterlace_method = strdup( src->timeformat );
 
161
 
 
162
    memset( dest->keymap_arg, 0, sizeof( dest->keymap_arg ) );
 
163
    memset( dest->keymapmenu_arg, 0, sizeof( dest->keymapmenu_arg ) );
 
164
    memset( dest->buttonmap_arg, 0, sizeof( dest->buttonmap_arg ) );
 
165
    memset( dest->buttonmapmenu_arg, 0, sizeof( dest->buttonmapmenu_arg ) );
 
166
}
 
167
 
 
168
static unsigned int parse_colour( const char *str )
 
169
{
 
170
    unsigned int a, r, g, b;
 
171
    int ret;
 
172
    
 
173
    if( !str || !*str ) return 0;
 
174
 
 
175
    if( strlen( str ) == 1 ) return (unsigned int)atoi( str );
 
176
 
 
177
    if( str[0] == '0' && str[1] == 'x' ) {
 
178
        ret = sscanf( str, "0x%x", &a );
 
179
    } else {
 
180
        ret = sscanf( str, "%u %u %u %u", &a, &r, &g, &b );
 
181
    }
 
182
 
 
183
    if( ret == 1 ) {
 
184
        return a;
 
185
    } else if( ret == 2 ) {
 
186
        return 0xff000000 | ( (a & 0xff) << 8 ) | (r & 0xff);
 
187
    } else if( ret == 3 ) {
 
188
        return 0xff000000 | ( (a & 0xff) << 16 ) | ( (r & 0xff) << 8 ) | ( g & 0xff);
 
189
    } else if( ret == 4 ) {
 
190
        return ( (a & 0xff) << 24 ) | ( (r & 0xff) << 16 ) | ( ( g & 0xff) << 8 ) | (b & 0xff);
 
191
    }
 
192
 
 
193
    return 0;
 
194
}
 
195
 
 
196
static xmlNodePtr find_option( xmlNodePtr node, const char *optname )
 
197
{
 
198
    while( node ) {
 
199
        if( !xmlStrcasecmp( node->name, BAD_CAST "option" ) ) {
 
200
            xmlChar *name = xmlGetProp( node, BAD_CAST "name" );
 
201
 
 
202
            if( name && !xmlStrcasecmp( name, BAD_CAST optname ) ) {
 
203
                xmlFree( name );
 
204
                return node;
 
205
            }
 
206
            if( name ) xmlFree( name );
 
207
        }
 
208
 
 
209
        node = node->next;
 
210
    }
 
211
 
 
212
    return 0;
 
213
}
 
214
 
 
215
static void parse_option( config_t *ct, xmlNodePtr node )
 
216
{
 
217
    xmlChar *name;
 
218
    xmlChar *value;
 
219
 
 
220
    name = xmlGetProp( node, BAD_CAST "name" );
 
221
    value = xmlGetProp( node, BAD_CAST "value" );
 
222
 
 
223
    if( name && value ) {
 
224
        char *curval = (char *) value;
 
225
 
 
226
        if( !xmlStrcasecmp( name, BAD_CAST "OutputHeight" ) ) {
 
227
            if( tolower( curval[ 0 ] ) == 'f' ) {
 
228
                ct->outputheight = -1;
 
229
            } else {
 
230
                ct->outputheight = atoi( curval );
 
231
            }
 
232
        }
 
233
 
 
234
        if( !xmlStrcasecmp( name, BAD_CAST "UseWindowPosition" ) ) {
 
235
            ct->useposition = atoi( curval );
 
236
        }
 
237
 
 
238
        if( !xmlStrcasecmp( name, BAD_CAST "WindowX" ) ) {
 
239
            ct->x = atoi( curval );
 
240
        }
 
241
 
 
242
        if( !xmlStrcasecmp( name, BAD_CAST "WindowY" ) ) {
 
243
            ct->y = atoi( curval );
 
244
        }
 
245
 
 
246
        if( !xmlStrcasecmp( name, BAD_CAST "InputWidth" ) ) {
 
247
            ct->inputwidth = atoi( curval );
 
248
        }
 
249
 
 
250
        if( !xmlStrcasecmp( name, BAD_CAST "Verbose" ) ) {
 
251
            ct->verbose = atoi( curval );
 
252
        }
 
253
 
 
254
        if( !xmlStrcasecmp( name, BAD_CAST "SaveAndRestorePictureSettings" ) ) {
 
255
            ct->picsaverestore = atoi( curval );
 
256
        }
 
257
 
 
258
        if( !xmlStrcasecmp( name, BAD_CAST "DefaultBrightness" ) ) {
 
259
            ct->brightness = atoi( curval );
 
260
        }
 
261
 
 
262
        if( !xmlStrcasecmp( name, BAD_CAST "DefaultContrast" ) ) {
 
263
            ct->contrast = atoi( curval );
 
264
        }
 
265
 
 
266
        if( !xmlStrcasecmp( name, BAD_CAST "DefaultColour" ) ) {
 
267
            ct->colour = atoi( curval );
 
268
        }
 
269
 
 
270
        if( !xmlStrcasecmp( name, BAD_CAST "DefaultHue" ) ) {
 
271
            ct->hue = atoi( curval );
 
272
        }
 
273
 
 
274
        if( !xmlStrcasecmp( name, BAD_CAST "ColourInvert" ) ) {
 
275
            ct->invert = atoi( curval );
 
276
        }
 
277
 
 
278
        if( !xmlStrcasecmp( name, BAD_CAST "MirrorInput" ) ) {
 
279
            ct->mirror = atoi( curval );
 
280
        }
 
281
 
 
282
        if( !xmlStrcasecmp( name, BAD_CAST "ShowCC" ) ) {
 
283
            ct->cc = atoi( curval );
 
284
        }
 
285
 
 
286
        if( !xmlStrcasecmp( name, BAD_CAST "DFBSendFields" ) ) {
 
287
            ct->send_fields = atoi( curval );
 
288
        }
 
289
 
 
290
        if( !xmlStrcasecmp( name, BAD_CAST "AudioMode" ) ) {
 
291
            if( ct->audiomode ) free( ct->audiomode );
 
292
            ct->audiomode = strdup( curval );
 
293
        }
 
294
 
 
295
        if( !xmlStrcasecmp( name, BAD_CAST "XMLTVFile" ) ) {
 
296
            if( ct->xmltvfile ) free( ct->xmltvfile );
 
297
            ct->xmltvfile = expand_user_path( curval );
 
298
        }
 
299
 
 
300
        if( !xmlStrcasecmp( name, BAD_CAST "OutputDriver" ) ) {
 
301
            if( ct->output_driver ) free( ct->output_driver );
 
302
            ct->output_driver = strdup( curval );
 
303
        }
 
304
 
 
305
        if( !xmlStrcasecmp( name, BAD_CAST "FullscreenPosition" ) ) {
 
306
            if( tolower( curval[ 0 ] ) == 't' ) {
 
307
                ct->fspos = 1;
 
308
            } else if( tolower( curval[ 0 ] ) == 'b' ) {
 
309
                ct->fspos = 2;
 
310
            } else {
 
311
                ct->fspos = 0;
 
312
            }
 
313
        }
 
314
 
 
315
        if( !xmlStrcasecmp( name, BAD_CAST "Widescreen" ) ) {
 
316
            ct->aspect = atoi( curval );
 
317
        }
 
318
 
 
319
        if( !xmlStrcasecmp( name, BAD_CAST "DebugMode" ) ) {
 
320
            ct->debug = atoi( curval );
 
321
        }
 
322
 
 
323
        if( !xmlStrcasecmp( name, BAD_CAST "ApplyLumaCorrection" ) ) {
 
324
            ct->apply_luma_correction = atoi( curval );
 
325
        }
 
326
 
 
327
        if( !xmlStrcasecmp( name, BAD_CAST "LumaCorrection" ) ) {
 
328
            ct->luma_correction = atof( curval );
 
329
        }
 
330
 
 
331
        if( !xmlStrcasecmp( name, BAD_CAST "V4LDevice" ) ) {
 
332
            if( ct->v4ldev ) free( ct->v4ldev );
 
333
            ct->v4ldev = strdup( curval );
 
334
        }
 
335
 
 
336
        if( !xmlStrcasecmp( name, BAD_CAST "VBIDevice" ) ) {
 
337
            if( ct->vbidev ) free( ct->vbidev );
 
338
            ct->vbidev = strdup( curval );
 
339
        }
 
340
 
 
341
        if( !xmlStrcasecmp( name, BAD_CAST "V4LInput" ) ) {
 
342
            ct->inputnum = atoi( curval );
 
343
        }
 
344
 
 
345
        if( !xmlStrcasecmp( name, BAD_CAST "UseXDS" ) ) {
 
346
            ct->use_xds = atoi( curval );
 
347
        }
 
348
 
 
349
        if( !xmlStrcasecmp( name, BAD_CAST "ProcessPriority" ) ) {
 
350
            ct->priority = atoi( curval );
 
351
        }
 
352
 
 
353
        if( !xmlStrcasecmp( name, BAD_CAST "Fullscreen" ) ) {
 
354
            ct->fullscreen = atoi( curval );
 
355
        }
 
356
 
 
357
        if( !xmlStrcasecmp( name, BAD_CAST "FramerateMode" ) ) {
 
358
            ct->framerate = atoi( curval );
 
359
        }
 
360
 
 
361
        if( !xmlStrcasecmp( name, BAD_CAST "Norm" ) ) {
 
362
            if( ct->norm ) free( ct->norm );
 
363
            ct->norm = strdup( curval );
 
364
        }
 
365
 
 
366
        if( !xmlStrcasecmp( name, BAD_CAST "Frequencies" ) ) {
 
367
            if( ct->freq ) free( ct->freq );
 
368
            ct->freq = strdup( curval );
 
369
        }
 
370
 
 
371
        if( !xmlStrcasecmp( name, BAD_CAST "TimeFormat" ) ) {
 
372
            if( ct->timeformat ) free( ct->timeformat );
 
373
            ct->timeformat = strdup( curval );
 
374
        }
 
375
 
 
376
        if( !xmlStrcasecmp( name, BAD_CAST "ScreenShotDir" ) ) {
 
377
            if( ct->ssdir ) free( ct->ssdir );
 
378
            ct->ssdir = expand_user_path( curval );
 
379
        }
 
380
 
 
381
        if( !xmlStrcasecmp( name, BAD_CAST "ChannelTextFG" ) ) {
 
382
            ct->channel_text_rgb = parse_colour( curval );
 
383
        }
 
384
 
 
385
        if( !xmlStrcasecmp( name, BAD_CAST "OtherTextFG" ) ) {
 
386
            ct->other_text_rgb = parse_colour( curval );
 
387
        }
 
388
 
 
389
        if( !xmlStrcasecmp( name, BAD_CAST "PrevChannel" ) ) {
 
390
            ct->prev_channel = atoi( curval );
 
391
        }
 
392
 
 
393
        if( !xmlStrcasecmp( name, BAD_CAST "Channel" ) ) {
 
394
            ct->start_channel = atoi( curval );
 
395
        }
 
396
 
 
397
        if( !xmlStrcasecmp( name, BAD_CAST "NTSCCableMode" ) ) {
 
398
            if( !xmlStrcasecmp( value, BAD_CAST "IRC" ) ) {
 
399
                ct->ntsc_mode = NTSC_CABLE_MODE_IRC;
 
400
            } else if( !xmlStrcasecmp( value, BAD_CAST "HRC" ) ) {
 
401
                ct->ntsc_mode = NTSC_CABLE_MODE_HRC;
 
402
            } else {
 
403
                ct->ntsc_mode = NTSC_CABLE_MODE_STANDARD;
 
404
            }
 
405
        }
 
406
 
 
407
        if( !xmlStrcasecmp( name, BAD_CAST "DeinterlaceMethod" ) ) {
 
408
            if( ct->deinterlace_method ) free( ct->deinterlace_method );
 
409
            ct->deinterlace_method = strdup( curval );
 
410
        }
 
411
 
 
412
        if( !xmlStrcasecmp( name, BAD_CAST "CheckForSignal" ) ) {
 
413
            ct->check_freq_present = atoi( curval );
 
414
        }
 
415
 
 
416
        if( !xmlStrcasecmp( name, BAD_CAST "Overscan" ) ) {
 
417
            ct->overscan = ( atof( curval ) / 2.0 ) / 100.0;
 
418
        }
 
419
 
 
420
        if( !xmlStrcasecmp( name, BAD_CAST "MixerDevice" ) ) {
 
421
            if( ct->mixerdev ) free( ct->mixerdev );
 
422
            ct->mixerdev = strdup( curval );
 
423
        }
 
424
    }
 
425
 
 
426
    if( name ) xmlFree( name );
 
427
    if( value ) xmlFree( value );
 
428
}
 
429
 
 
430
static void parse_bind( config_t *ct, xmlNodePtr node )
 
431
{
 
432
    xmlChar *command = xmlGetProp( node, BAD_CAST "command" );
 
433
    xmlChar *arg = xmlGetProp( node, BAD_CAST "argument" );
 
434
 
 
435
    if( command ) {
 
436
        xmlNodePtr binding = node->xmlChildrenNode;
 
437
 
 
438
        while( binding ) {
 
439
            if( !xmlStrcasecmp( binding->name, BAD_CAST "keyboard" ) ) {
 
440
                xmlChar *key = xmlGetProp( binding, BAD_CAST "key" );
 
441
 
 
442
                if( key ) {
 
443
                    int keycode, command_id;
 
444
 
 
445
                    keycode = input_string_to_special_key( (const char *) key );
 
446
                    if( !keycode ) {
 
447
                        keycode = (*key);
 
448
                    }
 
449
 
 
450
                    command_id = tvtime_string_to_command( (const char *) command );
 
451
                    if( tvtime_is_menu_command( command_id ) ) {
 
452
                        ct->keymapmenu[ keycode ] = command_id;
 
453
                        if( arg ) ct->keymapmenu_arg[ keycode ] = strdup( (const char *) arg );
 
454
                    } else if( command_id != TVTIME_NOCOMMAND ) {
 
455
                        ct->keymap[ keycode ] = command_id;
 
456
                        if( arg ) ct->keymap_arg[ keycode ] = strdup( (const char *) arg );
 
457
                    }
 
458
                }
 
459
            } else if( !xmlStrcasecmp( binding->name, BAD_CAST "mouse" ) ) {
 
460
                xmlChar *button = xmlGetProp( binding, BAD_CAST "button" );
 
461
                if( button ) {
 
462
                    int id = atoi( (const char *) button );
 
463
                    if( (id > 0) && (id < MAX_BUTTONS) ) {
 
464
                        int command_id = tvtime_string_to_command( (const char *) command );
 
465
                        if( tvtime_is_menu_command( command_id ) ) {
 
466
                            ct->buttonmapmenu[ id ] = command_id;
 
467
                            if( arg ) ct->buttonmapmenu_arg[ id ] = strdup( (const char *) arg );
 
468
                        } else {
 
469
                            ct->buttonmap[ id ] = command_id;
 
470
                            if( arg ) ct->buttonmap_arg[ id ] = strdup( (const char *) arg );
 
471
                        }
 
472
                    }
 
473
                    xmlFree( button );
 
474
                }
 
475
            }
 
476
            binding = binding->next;
 
477
        }
 
478
 
 
479
        xmlFree( command );
 
480
    }
 
481
    if( arg ) xmlFree( arg );
 
482
}
 
483
 
 
484
static void parse_mode( config_t *ct, xmlNodePtr node )
 
485
{
 
486
    xmlChar *name = xmlGetProp( node, BAD_CAST "name" );
 
487
 
 
488
    if( name ) {
 
489
        tvtime_modelist_t *mode = malloc( sizeof( tvtime_modelist_t ) );
 
490
        if( mode ) {
 
491
 
 
492
            /* Start with the default settings from the config file. */
 
493
            copy_config( &(mode->settings), ct );
 
494
 
 
495
            node = node->xmlChildrenNode;
 
496
            while( node ) {
 
497
                if( !xmlIsBlankNode( node ) ) {
 
498
                    if( !xmlStrcasecmp( node->name, BAD_CAST "option" ) ) {
 
499
                        parse_option( &(mode->settings), node );
 
500
                    }
 
501
                }
 
502
                node = node->next;
 
503
            }
 
504
 
 
505
            mode->name = strdup( (char *) name );
 
506
            mode->next = ct->modelist;
 
507
            ct->modelist = mode;
 
508
            ct->nummodes++;
 
509
        }
 
510
        xmlFree( name );
 
511
    }
 
512
}
 
513
 
 
514
static int conf_xml_parse( config_t *ct, char *configFile )
 
515
{
 
516
    xmlDocPtr doc;
 
517
    xmlNodePtr top, node;
 
518
 
 
519
    doc = xmlParseFile( configFile );
 
520
    if( !doc ) {
 
521
        lfprintf( stderr, _("Error parsing configuration file %s.\n"),
 
522
                  configFile );
 
523
        return 0;
 
524
    }
 
525
 
 
526
    top = xmlDocGetRootElement( doc );
 
527
    if( !top ) {
 
528
        lfprintf( stderr, _("No XML root element found in %s.\n"),
 
529
                  configFile );
 
530
        xmlFreeDoc( doc );
 
531
        return 0;
 
532
    }
 
533
 
 
534
    if( xmlStrcasecmp( top->name, BAD_CAST "tvtime" ) ) {
 
535
        lfprintf( stderr,
 
536
                  _("%s is not a tvtime configuration file.\n"),
 
537
                  configFile );
 
538
        xmlFreeDoc( doc );
 
539
        return 0;
 
540
    }
 
541
 
 
542
    node = top->xmlChildrenNode;
 
543
    while( node ) {
 
544
        if( !xmlIsBlankNode( node ) ) {
 
545
            if( !xmlStrcasecmp( node->name, BAD_CAST "option" ) ) {
 
546
                parse_option( ct, node );
 
547
            } else if( !xmlStrcasecmp( node->name, BAD_CAST "bind" ) ) {
 
548
                parse_bind( ct, node );
 
549
            } else if( !xmlStrcasecmp( node->name, BAD_CAST "mode" ) ) {
 
550
                parse_mode( ct, node );
 
551
            }
 
552
        }
 
553
        node = node->next;
 
554
    }
 
555
 
 
556
    xmlFreeDoc( doc );
 
557
    return 1;
 
558
}
 
559
 
 
560
/* Attempt to parse the file for key elements and create them if they don't exist */
 
561
static xmlDocPtr configsave_open( const char *config_filename )
 
562
{
 
563
    xmlDocPtr doc;
 
564
    xmlNodePtr top;
 
565
    int create_file = 0;
 
566
 
 
567
    doc = xmlParseFile( config_filename );
 
568
    if( !doc ) {
 
569
        if( file_is_openable_for_read( config_filename ) ) {
 
570
            lfputs( _("Config file cannot be parsed. "
 
571
                      "Settings will not be saved.\n"), stderr );
 
572
            return 0;
 
573
        } else {
 
574
            /* Config file doesn't exist, create a new one. */
 
575
            doc = xmlNewDoc( BAD_CAST "1.0" );
 
576
            if( !doc ) {
 
577
                lfputs( _("Could not create new config file.\n"), stderr );
 
578
                return 0;
 
579
            }
 
580
            create_file = 1;
 
581
        }
 
582
    }
 
583
 
 
584
    top = xmlDocGetRootElement( doc );
 
585
    if( !top ) {
 
586
        /* Set the DTD */
 
587
        xmlDtdPtr dtd;
 
588
        dtd = xmlNewDtd( doc, BAD_CAST "tvtime",
 
589
                         BAD_CAST "-//tvtime//DTD tvtime 1.0//EN",
 
590
                         BAD_CAST "http://tvtime.sourceforge.net/DTD/tvtime1.dtd" );
 
591
        doc->intSubset = dtd;
 
592
        if( !doc->children ) {
 
593
            xmlAddChild( (xmlNodePtr) doc, (xmlNodePtr) dtd );
 
594
        } else {
 
595
            xmlAddPrevSibling( doc->children, (xmlNodePtr) dtd );
 
596
        }
 
597
 
 
598
        /* Create the root node */
 
599
        top = xmlNewDocNode( doc, 0, BAD_CAST "tvtime", 0 );
 
600
        if( !top ) {
 
601
            lfputs( _("Error creating configuration file.\n"), stderr );
 
602
            xmlFreeDoc( doc );
 
603
            return 0;
 
604
        } else {
 
605
            xmlDocSetRootElement( doc, top );
 
606
            xmlNewProp( top, BAD_CAST "xmlns",
 
607
                        BAD_CAST "http://tvtime.sourceforge.net/DTD/" );
 
608
        }
 
609
    }
 
610
 
 
611
    if( xmlStrcasecmp( top->name, BAD_CAST "tvtime" ) ) {
 
612
        lfprintf( stderr, _("%s is not a tvtime configuration file.\n"),
 
613
                  config_filename );
 
614
        xmlFreeDoc( doc );
 
615
        return 0;
 
616
    }
 
617
 
 
618
    xmlKeepBlanksDefault( 0 );
 
619
    xmlSaveFormatFile( config_filename, doc, 1 );
 
620
    if( create_file ) {
 
621
        if( chown( config_filename, getuid(), getgid() ) < 0 ) {
 
622
            lfprintf( stderr, _("Cannot change owner of %s: %s.\n"),
 
623
                      config_filename, strerror( errno ) );
 
624
        }
 
625
    }
 
626
    return doc;
 
627
}
 
628
 
 
629
static void print_copyright( void )
 
630
{
 
631
    lfputs (_("\n"
 
632
              "tvtime is free software, written by Billy Biggs, Doug Bell and many\n"
 
633
              "others.  For details and copying conditions, please see our website\n"
 
634
              "at http://tvtime.net/\n"
 
635
              "\n"
 
636
              "tvtime is Copyright (C) 2001, 2002, 2003 by Billy Biggs, Doug Bell,\n"
 
637
              "Alexander S. Belov, and Achim Schneider.\n"), stderr );
 
638
}
 
639
 
 
640
static void print_usage( char **argv )
 
641
{
 
642
    lfprintf( stderr, _("usage: %s [OPTION]...\n\n"), argv[ 0 ] );
 
643
    lfputs( _("  -a, --widescreen           16:9 mode.\n"), stderr );
 
644
    lfputs( _("  -b, --vbidevice=DEVICE     VBI device (defaults to /dev/vbi0).\n"), stderr );
 
645
    lfputs( _("  -c, --channel=CHANNEL      Tune to the specified channel on startup.\n"), stderr );
 
646
    lfputs( _("  -d, --device=DEVICE        video4linux device (defaults to /dev/video0).\n"), stderr );
 
647
    lfputs( _("  -D, --driver=NAME          Output driver to use: Xv, DirectFB, mga,\n"
 
648
              "                             matroxtv or SDL (defaults to Xv).\n"), stderr );
 
649
    lfputs( _("  -f, --frequencies=NAME     The frequency table to use for the tuner.\n"
 
650
              "                             (defaults to us-cable).\n\n"
 
651
              "                             Valid values are:\n"
 
652
              "                                 us-cable\n"
 
653
              "                                 us-cable100\n"
 
654
              "                                 us-broadcast\n"
 
655
              "                                 china-broadcast\n"
 
656
              "                                 japan-cable\n"
 
657
              "                                 japan-broadcast\n"
 
658
              "                                 europe\n"
 
659
              "                                 australia\n"
 
660
              "                                 australia-optus\n"
 
661
              "                                 newzealand\n"
 
662
              "                                 france\n"
 
663
              "                                 russia\n"
 
664
              "                                 custom (first run tvtime-scanner)\n\n"), stderr );
 
665
    lfputs( _("  -F, --configfile=FILE      Additional config file to load settings from.\n"), stderr );
 
666
    lfputs( _("  -h, --help                 Show this help message.\n"), stderr );
 
667
    lfputs( _("  -H, --height=HEIGHT        Output window height (defaults to 576 pixels).\n"), stderr );
 
668
    lfputs( _("  -i, --input=INPUTNUM       video4linux input number (defaults to 0).\n"), stderr );
 
669
    lfputs( _("  -I, --inputwidth=SAMPLING  Horizontal resolution of input\n"
 
670
              "                             (defaults to 720 pixels).\n"), stderr );
 
671
    lfputs( _("  -k, --slave                Disables input handling in tvtime (slave mode).\n"), stderr );
 
672
    lfputs( _("  -m, --fullscreen           Start tvtime in fullscreen mode.\n"), stderr );
 
673
    lfputs( _("  -M, --window               Start tvtime in window mode.\n"), stderr );
 
674
    lfputs( _("  -n, --norm=NORM            The norm to use for the input.  tvtime supports:\n"
 
675
              "                             NTSC, NTSC-JP, SECAM, PAL, PAL-Nc, PAL-M,\n"
 
676
              "                             PAL-N or PAL-60 (defaults to NTSC).\n"), stderr );
 
677
    lfputs( _("  -p, --fspos=POS            Set the fullscreen position: top, bottom or\n"
 
678
              "                             centre (default).\n"), stderr );
 
679
    lfputs( _("  -r, --rvr=FILE             RVR recorded file to play (for debugging).\n"), stderr );
 
680
    lfputs( _("  -s, --showdrops            Print stats on frame drops (for debugging).\n"), stderr );
 
681
    lfputs( _("  -S, --saveoptions          Save command line options to the config file.\n"), stderr );
 
682
    lfputs( _("  -t, --xmltv=FILE           Read XMLTV listings from the given file.\n"), stderr );
 
683
    lfputs( _("  -v, --verbose              Print debugging messages to stderr.\n"), stderr );
 
684
    lfputs( _("  -x, --mixer=DEVICE[:CH]    The mixer device and channel to control.\n"
 
685
              "                             (defaults to /dev/mixer:line)\n\n"
 
686
              "                             Valid channels are:\n"
 
687
              "                                 vol, bass, treble, synth, pcm, speaker, line,\n"
 
688
              "                                 mic, cd, mix, pcm2, rec, igain, ogain, line1,\n"
 
689
              "                                 line2, line3, dig1, dig2, dig3, phin, phout,\n"
 
690
              "                                 video, radio, monitor\n"), stderr );
 
691
}
 
692
 
 
693
static void print_config_usage( char **argv )
 
694
{
 
695
    lfprintf( stderr, _("usage: %s [OPTION]...\n\n"), argv[ 0 ] );
 
696
    lfputs( _("  -a, --widescreen           16:9 mode.\n"), stderr );
 
697
    lfputs( _("  -b, --vbidevice=DEVICE     VBI device (defaults to /dev/vbi0).\n"), stderr );
 
698
    lfputs( _("  -c, --channel=CHANNEL      Tune to the specified channel on startup.\n"), stderr );
 
699
    lfputs( _("  -d, --device=DEVICE        video4linux device (defaults to /dev/video0).\n"), stderr );
 
700
    lfputs( _("  -D, --driver=NAME          Output driver to use: Xv, DirectFB, mga,\n"
 
701
              "                             matroxtv or SDL (defaults to Xv).\n"), stderr );
 
702
    lfputs( _("  -f, --frequencies=NAME     The frequency table to use for the tuner.\n"
 
703
              "                             (defaults to us-cable).\n\n"
 
704
              "                             Valid values are:\n"
 
705
              "                                 us-cable\n"
 
706
              "                                 us-cable100\n"
 
707
              "                                 us-broadcast\n"
 
708
              "                                 china-broadcast\n"
 
709
              "                                 japan-cable\n"
 
710
              "                                 japan-broadcast\n"
 
711
              "                                 europe\n"
 
712
              "                                 australia\n"
 
713
              "                                 australia-optus\n"
 
714
              "                                 newzealand\n"
 
715
              "                                 france\n"
 
716
              "                                 russia\n"
 
717
              "                                 custom (first run tvtime-scanner)\n\n"), stderr );
 
718
    lfputs( _("  -F, --configfile=FILE      Additional config file to load settings from.\n"), stderr );
 
719
    lfputs( _("  -h, --help                 Show this help message.\n"), stderr );
 
720
    lfputs( _("  -H, --height=HEIGHT        Output window height (defaults to 576 pixels).\n"), stderr );
 
721
    lfputs( _("  -i, --input=INPUTNUM       video4linux input number (defaults to 0).\n"), stderr );
 
722
    lfputs( _("  -I, --inputwidth=SAMPLING  Horizontal resolution of input\n"
 
723
              "                             (defaults to 720 pixels).\n"), stderr );
 
724
    lfputs( _("  -m, --fullscreen           Start tvtime in fullscreen mode.\n"), stderr );
 
725
    lfputs( _("  -M, --window               Start tvtime in window mode.\n"), stderr );
 
726
    lfputs( _("  -n, --norm=NORM            The norm to use for the input.  tvtime supports:\n"
 
727
              "                             NTSC, NTSC-JP, SECAM, PAL, PAL-Nc, PAL-M,\n"
 
728
              "                             PAL-N or PAL-60 (defaults to NTSC).\n"), stderr );
 
729
    lfputs( _("  -p, --fspos=POS            Set the fullscreen position: top, bottom or\n"
 
730
              "                             centre (default).\n"), stderr );
 
731
    lfputs( _("  -R, --priority=PRI         Sets the process priority to run tvtime at.\n"), stderr );
 
732
    lfputs( _("  -t, --xmltv=FILE           Read XMLTV listings from the given file.\n"), stderr );
 
733
    lfputs( _("  -X, --display=DISPLAY      Use the given X display to connect to.\n"), stderr );
 
734
    lfputs( _("  -x, --mixer=DEVICE[:CH]    The mixer device and channel to control.\n"
 
735
              "                             (defaults to /dev/mixer:line)\n\n"
 
736
              "                             Valid channels are:\n"
 
737
              "                                 vol, bass, treble, synth, pcm, speaker, line,\n"
 
738
              "                                 mic, cd, mix, pcm2, rec, igain, ogain, line1,\n"
 
739
              "                                 line2, line3, dig1, dig2, dig3, phin, phout,\n"
 
740
              "                                 video, radio, monitor\n"), stderr );
 
741
}
 
742
 
 
743
static void print_scanner_usage( char **argv )
 
744
{
 
745
    lfprintf( stderr, _("usage: %s [OPTION]...\n\n"), argv[ 0 ]);
 
746
    lfputs( _("  -d, --device=DEVICE        video4linux device (defaults to /dev/video0).\n"), stderr );
 
747
    lfputs( _("  -F, --configfile=FILE      Additional config file to load settings from.\n"), stderr );
 
748
    lfputs( _("  -h, --help                 Show this help message.\n"), stderr );
 
749
    lfputs( _("  -i, --input=INPUTNUM       video4linux input number (defaults to 0).\n"), stderr );
 
750
    lfputs( _("  -n, --norm=NORM            The norm to use for the input.  tvtime supports:\n"
 
751
              "                             NTSC, NTSC-JP, SECAM, PAL, PAL-Nc, PAL-M,\n"
 
752
              "                             PAL-N or PAL-60 (defaults to NTSC).\n"), stderr );
 
753
}
 
754
 
 
755
config_t *config_new( void )
 
756
{
 
757
    char *temp_dirname;
 
758
    char *base;
 
759
 
 
760
    config_t *ct = malloc( sizeof( config_t ) );
 
761
    if( !ct ) {
 
762
        return 0;
 
763
    }
 
764
 
 
765
    /* Default settings. */
 
766
    ct->outputheight = 576;
 
767
    ct->verbose = 0;
 
768
    ct->aspect = 0;
 
769
    ct->debug = 0;
 
770
    ct->fullscreen = 0;
 
771
    ct->priority = -19;
 
772
    ct->ntsc_mode = 0;
 
773
    ct->send_fields = 0;
 
774
    ct->output_driver = strdup( "xv" );
 
775
    ct->apply_luma_correction = 0;
 
776
    ct->luma_correction = 1.0;
 
777
    ct->useposition = 0;
 
778
    ct->fspos = 0;
 
779
    ct->x = 320;
 
780
    ct->y = 240;
 
781
    ct->picsaverestore = 1;
 
782
    ct->brightness = -1;
 
783
    ct->contrast = -1;
 
784
    ct->colour = -1;
 
785
    ct->hue = -1;
 
786
    ct->invert = 0;
 
787
    ct->cc = 0;
 
788
    ct->mirror = 0;
 
789
 
 
790
    memset( ct->keymap, 0, sizeof( ct->keymap ) );
 
791
    memset( ct->keymap_arg, 0, sizeof( ct->keymap_arg ) );
 
792
    memset( ct->keymapmenu, 0, sizeof( ct->keymapmenu ) );
 
793
    memset( ct->keymapmenu_arg, 0, sizeof( ct->keymapmenu_arg ) );
 
794
    memset( ct->buttonmap, 0, sizeof( ct->buttonmap ) );
 
795
    memset( ct->buttonmap_arg, 0, sizeof( ct->buttonmap_arg ) );
 
796
    memset( ct->buttonmapmenu, 0, sizeof( ct->buttonmapmenu ) );
 
797
    memset( ct->buttonmapmenu_arg, 0, sizeof( ct->buttonmapmenu_arg ) );
 
798
 
 
799
    ct->inputwidth = 720;
 
800
    ct->inputnum = 0;
 
801
    ct->v4ldev = strdup( "/dev/video0" );
 
802
    ct->norm = strdup( "ntsc" );
 
803
    ct->freq = strdup( "us-cable" );
 
804
    temp_dirname = getenv( "HOME" );
 
805
    if( temp_dirname ) {
 
806
        ct->ssdir = strdup( temp_dirname );
 
807
    } else {
 
808
        ct->ssdir = 0;
 
809
    }
 
810
    ct->audiomode = strdup( "stereo" );
 
811
    ct->xmltvfile = strdup( "none" );
 
812
    ct->timeformat = strdup( "%X" );
 
813
    ct->channel_text_rgb = 0xffffff00; /* opaque yellow */
 
814
    ct->other_text_rgb = 0xfff5deb3;   /* opaque wheat */
 
815
 
 
816
    ct->uid = getuid();
 
817
 
 
818
    ct->rvr_filename = 0;
 
819
    ct->mpeg_filename = 0;
 
820
    ct->mixerdev = strdup( "/dev/mixer:line" );
 
821
 
 
822
    ct->deinterlace_method = strdup( "GreedyH" );
 
823
    ct->check_freq_present = 1;
 
824
 
 
825
    ct->use_xds = 0;
 
826
    ct->vbidev = strdup( "/dev/vbi0" );
 
827
 
 
828
    ct->start_channel = 1;
 
829
    ct->prev_channel = 1;
 
830
    ct->framerate = FRAMERATE_FULL;
 
831
    ct->slave_mode = 0;
 
832
 
 
833
    ct->overscan = 0.0;
 
834
 
 
835
    ct->config_filename = 0;
 
836
    ct->doc = 0;
 
837
 
 
838
    ct->nummodes = 0;
 
839
    ct->modelist = 0;
 
840
 
 
841
    /* Default key bindings. */
 
842
    ct->keymap[ 0 ] = TVTIME_NOCOMMAND;
 
843
    ct->keymap[ I_ESCAPE ] = TVTIME_QUIT;
 
844
    ct->keymap[ 'q' ] = TVTIME_QUIT;
 
845
    ct->keymap[ I_UP ] = TVTIME_UP;
 
846
    ct->keymap[ I_DOWN ] = TVTIME_DOWN;
 
847
    ct->keymap[ I_LEFT ] = TVTIME_LEFT;
 
848
    ct->keymap[ I_RIGHT ] = TVTIME_RIGHT;
 
849
    ct->keymap[ I_BACKSPACE ] = TVTIME_CHANNEL_PREV;
 
850
    ct->keymap[ 'c' ] = TVTIME_TOGGLE_CC;
 
851
    ct->keymap[ 'm' ] = TVTIME_TOGGLE_MUTE;
 
852
    ct->keymap[ '-' ] = TVTIME_MIXER_DOWN;
 
853
    ct->keymap[ '+' ] = TVTIME_MIXER_UP;
 
854
    ct->keymap[ ' ' ] = TVTIME_AUTO_ADJUST_PICT;
 
855
    ct->keymap[ I_ENTER ] = TVTIME_ENTER;
 
856
    ct->keymap[ I_F1 ] = TVTIME_SHOW_MENU;
 
857
    ct->keymap[ 'h' ] = TVTIME_SHOW_MENU;
 
858
    ct->keymap[ '\t' ] = TVTIME_SHOW_MENU;
 
859
    ct->keymap[ I_F5 ] = TVTIME_PICTURE;
 
860
    ct->keymap[ I_F6 ] = TVTIME_PICTURE_DOWN;
 
861
    ct->keymap[ I_F7 ] = TVTIME_PICTURE_UP;
 
862
    ct->keymap[ 'r' ] = TVTIME_CHANNEL_RENUMBER;
 
863
    ct->keymap[ 'd' ] = TVTIME_SHOW_STATS;
 
864
    ct->keymap[ 'f' ] = TVTIME_TOGGLE_FULLSCREEN;
 
865
    ct->keymap[ 'i' ] = TVTIME_TOGGLE_INPUT;
 
866
    ct->keymap[ 'a' ] = TVTIME_TOGGLE_ASPECT;
 
867
    ct->keymap[ 's' ] = TVTIME_SCREENSHOT;
 
868
    ct->keymap[ 't' ] = TVTIME_TOGGLE_DEINTERLACER;
 
869
    ct->keymap[ 'p' ] = TVTIME_TOGGLE_PULLDOWN_DETECTION;
 
870
    ct->keymap[ ',' ] = TVTIME_MIXER_TOGGLE_MUTE;
 
871
    ct->keymap[ '`' ] = TVTIME_TOGGLE_CONSOLE;
 
872
    ct->keymap[ I_PGUP ] = TVTIME_SCROLL_CONSOLE_UP;
 
873
    ct->keymap[ I_PGDN ] = TVTIME_SCROLL_CONSOLE_DOWN;
 
874
    ct->keymap[ '=' ] = TVTIME_TOGGLE_FRAMERATE;
 
875
    ct->keymap[ I_END ] = TVTIME_TOGGLE_PAUSE;
 
876
    ct->keymap[ 'e' ] = TVTIME_TOGGLE_AUDIO_MODE;
 
877
    ct->keymap[ '<' ] = TVTIME_OVERSCAN_DOWN;
 
878
    ct->keymap[ '>' ] = TVTIME_OVERSCAN_UP;
 
879
    ct->keymap[ 'b' ] = TVTIME_TOGGLE_BARS;
 
880
    ct->keymap[ '*' ] = TVTIME_TOGGLE_MODE;
 
881
    ct->keymap[ '/' ] = TVTIME_AUTO_ADJUST_WINDOW;
 
882
    ct->keymap[ I_INSERT ] = TVTIME_TOGGLE_MATTE;
 
883
    ct->keymap[ 'v' ] = TVTIME_TOGGLE_ALWAYSONTOP;
 
884
    ct->keymap[ 'o' ] = TVTIME_TOGGLE_COLOUR_INVERT;
 
885
    ct->keymap[ '0' ] = TVTIME_CHANNEL_0;
 
886
    ct->keymap[ '1' ] = TVTIME_CHANNEL_1;
 
887
    ct->keymap[ '2' ] = TVTIME_CHANNEL_2;
 
888
    ct->keymap[ '3' ] = TVTIME_CHANNEL_3;
 
889
    ct->keymap[ '4' ] = TVTIME_CHANNEL_4;
 
890
    ct->keymap[ '5' ] = TVTIME_CHANNEL_5;
 
891
    ct->keymap[ '6' ] = TVTIME_CHANNEL_6;
 
892
    ct->keymap[ '7' ] = TVTIME_CHANNEL_7;
 
893
    ct->keymap[ '8' ] = TVTIME_CHANNEL_8;
 
894
    ct->keymap[ '9' ] = TVTIME_CHANNEL_9;
 
895
 
 
896
    ct->buttonmap[ 1 ] = TVTIME_DISPLAY_INFO;
 
897
    ct->buttonmap[ 2 ] = TVTIME_TOGGLE_MUTE;
 
898
    ct->buttonmap[ 3 ] = TVTIME_SHOW_MENU;
 
899
    ct->buttonmap[ 4 ] = TVTIME_CHANNEL_INC;
 
900
    ct->buttonmap[ 5 ] = TVTIME_CHANNEL_DEC;
 
901
 
 
902
    /* Menu keys. */
 
903
    ct->keymapmenu[ I_UP ] = TVTIME_MENU_UP;
 
904
    ct->keymapmenu[ I_DOWN ] = TVTIME_MENU_DOWN;
 
905
    ct->keymapmenu[ I_LEFT ] = TVTIME_MENU_BACK;
 
906
    ct->keymapmenu[ I_RIGHT ] = TVTIME_MENU_ENTER;
 
907
    ct->keymapmenu[ I_ENTER ] = TVTIME_MENU_ENTER;
 
908
    ct->keymapmenu[ I_F1 ] = TVTIME_MENU_EXIT;
 
909
    ct->keymapmenu[ '\t' ] = TVTIME_MENU_EXIT;
 
910
    ct->keymapmenu[ 'q' ] = TVTIME_MENU_EXIT;
 
911
    ct->keymapmenu[ I_ESCAPE ] = TVTIME_MENU_EXIT;
 
912
    ct->buttonmapmenu[ 1 ] = TVTIME_MENU_ENTER;
 
913
    ct->buttonmapmenu[ 3 ] = TVTIME_MENU_EXIT;
 
914
    ct->buttonmapmenu[ 4 ] = TVTIME_MENU_UP;
 
915
    ct->buttonmapmenu[ 5 ] = TVTIME_MENU_DOWN;
 
916
 
 
917
    /* Make the ~/.tvtime directory every time on startup, to be safe. */
 
918
    if( asprintf( &temp_dirname, "%s/.tvtime", getenv( "HOME" ) ) < 0 ) {
 
919
        /* FIXME: Clean up ?? */
 
920
        return 0;
 
921
    }
 
922
    mkdir_and_force_owner( temp_dirname, ct->uid, getgid() );
 
923
    free( temp_dirname );
 
924
 
 
925
    /* First read in global settings. */
 
926
    asprintf( &base, "%s/tvtime.xml", CONFDIR );
 
927
    if( file_is_openable_for_read( base ) ) {
 
928
        fprintf( stderr, _("Reading configuration from %s\n"), base );
 
929
        conf_xml_parse( ct, base );
 
930
    }
 
931
    free( base );
 
932
 
 
933
    /* Then read in local settings. */
 
934
    asprintf( &base, "%s/.tvtime/tvtime.xml", getenv( "HOME" ) );
 
935
    ct->config_filename = strdup( base );
 
936
    if( file_is_openable_for_read( base ) ) {
 
937
        fprintf( stderr, _("Reading configuration from %s\n"), base );
 
938
        conf_xml_parse( ct, base );
 
939
    }
 
940
    free( base );
 
941
 
 
942
    return ct;
 
943
}
 
944
 
 
945
int config_parse_tvtime_command_line( config_t *ct, int argc, char **argv )
 
946
{
 
947
    static struct option long_options[] = {
 
948
        { "help", 0, 0, 'h' },
 
949
        { "verbose", 0, 0, 'v' },
 
950
        { "height", 1, 0, 'H' },
 
951
        { "saveoptions", 0, 0, 'S' },
 
952
        { "inputwidth", 1, 0, 'I' },
 
953
        { "driver", 1, 0, 'D' },
 
954
        { "input", 1, 0, 'i' },
 
955
        { "channel", 1, 0, 'c' },
 
956
        { "configfile", 1, 0, 'F' },
 
957
        { "norm", 1, 0, 'n' },
 
958
        { "frequencies", 1, 0, 'f' },
 
959
        { "vbidevice", 1, 0, 'b' },
 
960
        { "device", 1, 0, 'd' },
 
961
        { "mixer", 1, 0, 'x' },
 
962
        { "showdrops", 0, 0, 's' },
 
963
        { "fullscreen", 0, 0, 'm' },
 
964
        { "window", 0, 0, 'M' },
 
965
        { "slave", 0, 0, 'k' },
 
966
        { "widescreen", 0, 0, 'a' },
 
967
        { "rvr", 1, 0, 'r' },
 
968
        { "mpeg", 1, 0, 'g' },
 
969
        { "fspos", 1, 0, 'p' },
 
970
        { "xmltv", 1, 0, 't' },
 
971
        { "display", 1, 0, 'X' },
 
972
        { "version", 0, 0, 'Q' },
 
973
        { 0, 0, 0, 0 }
 
974
    };
 
975
    int option_index = 0;
 
976
    int saveoptions = 0;
 
977
    char c;
 
978
 
 
979
    if( argc ) {
 
980
        while( (c = getopt_long( argc, argv, "ahkmMsSvF:r:H:I:d:b:i:c:n:D:f:x:p:X:t:Qg:",
 
981
                long_options, &option_index )) != -1 ) {
 
982
            switch( c ) {
 
983
            case 'a': ct->aspect = 1; break;
 
984
            case 'k': ct->slave_mode = 1; break;
 
985
            case 'm': ct->fullscreen = 1; break;
 
986
            case 'M': ct->fullscreen = 0; break;
 
987
            case 's': ct->debug = 1; break;
 
988
            case 'S': saveoptions = 1; break;
 
989
            case 'v': ct->verbose = 1; break;
 
990
            case 't': if( ct->xmltvfile ) { free( ct->xmltvfile ); }
 
991
                      ct->xmltvfile = expand_user_path( optarg ); break;
 
992
            case 'F': if( ct->config_filename ) free( ct->config_filename );
 
993
                      ct->config_filename = expand_user_path( optarg );
 
994
                      if( ct->config_filename ) {
 
995
                          lfprintf
 
996
                              ( stderr,
 
997
                                _("Reading configuration from %s\n"),
 
998
                                ct->config_filename );
 
999
                          conf_xml_parse( ct, ct->config_filename );
 
1000
                      }
 
1001
                      break;
 
1002
            case 'r': if( ct->rvr_filename ) { free( ct->rvr_filename ); }
 
1003
                      ct->rvr_filename = strdup( optarg ); break;
 
1004
            case 'g': if( ct->mpeg_filename ) { free( ct->mpeg_filename ); }
 
1005
                      ct->mpeg_filename = strdup( optarg ); break;
 
1006
            case 'x': if( ct->mixerdev ) { free( ct->mixerdev ); }
 
1007
                      ct->mixerdev = strdup( optarg ); break;
 
1008
            case 'X': setenv( "DISPLAY", optarg, 1 ); break;
 
1009
            case 'H': if( tolower( optarg[ 0 ] ) == 'f' ) {
 
1010
                          ct->outputheight = -1;
 
1011
                      } else {
 
1012
                          ct->outputheight = atoi( optarg );
 
1013
                      }
 
1014
                      break;
 
1015
            case 'I': ct->inputwidth = atoi( optarg ); break;
 
1016
            case 'd': free( ct->v4ldev ); ct->v4ldev = strdup( optarg ); break;
 
1017
            case 'b': free( ct->vbidev ); ct->vbidev = strdup( optarg ); break;
 
1018
            case 'i': ct->inputnum = atoi( optarg ); break;
 
1019
            case 'c': ct->prev_channel = ct->start_channel;
 
1020
                      ct->start_channel = atoi( optarg ); break;
 
1021
            case 'n': free( ct->norm ); ct->norm = strdup( optarg ); break;
 
1022
            case 'D': if( ct->output_driver ) { free( ct->output_driver ); }
 
1023
                      ct->output_driver = strdup( optarg ); break;
 
1024
            case 'p': if( tolower( optarg[ 0 ] ) == 't' ) {
 
1025
                          ct->fspos = 1;
 
1026
                      } else if( tolower( optarg[ 0 ] ) == 'b' ) {
 
1027
                          ct->fspos = 2;
 
1028
                      } else {
 
1029
                          ct->fspos = 0;
 
1030
                      }
 
1031
                      break;
 
1032
            case 'f': free( ct->freq ); ct->freq = strdup( optarg ); break;
 
1033
            case 'Q': print_copyright(); return 0;
 
1034
            default:
 
1035
                print_usage( argv );
 
1036
                return 0;
 
1037
            }
 
1038
        }
 
1039
    }
 
1040
 
 
1041
    ct->doc = configsave_open( ct->config_filename );
 
1042
 
 
1043
    if( ct->doc && saveoptions ) {
 
1044
        char tempstring[ 32 ];
 
1045
        lfputs( _("Saving command line options.\n"), stderr );
 
1046
 
 
1047
        /**
 
1048
         * Options that aren't specified on the command line
 
1049
         * will match the config file anyway, so save everything that
 
1050
         * you can save on the command line.
 
1051
         */
 
1052
        snprintf( tempstring, sizeof( tempstring ), "%d", ct->aspect );
 
1053
        config_save( ct, "Widescreen", tempstring );
 
1054
 
 
1055
        snprintf( tempstring, sizeof( tempstring ), "%d", ct->fullscreen );
 
1056
        config_save( ct, "Fullscreen", tempstring );
 
1057
 
 
1058
        snprintf( tempstring, sizeof( tempstring ), "%d", ct->verbose );
 
1059
        config_save( ct, "Verbose", tempstring );
 
1060
 
 
1061
        config_save( ct, "OutputDriver", ct->output_driver );
 
1062
 
 
1063
        if( ct->fspos == 0 ) {
 
1064
            config_save( ct, "FullscreenPosition", "Centre" );
 
1065
        } else if( ct->fspos == 1 ) {
 
1066
            config_save( ct, "FullscreenPosition", "Top" );
 
1067
        } else if( ct->fspos == 2 ) {
 
1068
            config_save( ct, "FullscreenPosition", "Bottom" );
 
1069
        }
 
1070
 
 
1071
        snprintf( tempstring, sizeof( tempstring ), "%d", ct->outputheight );
 
1072
        config_save( ct, "OutputHeight", tempstring );
 
1073
 
 
1074
        snprintf( tempstring, sizeof( tempstring ), "%d", ct->inputwidth );
 
1075
        config_save( ct, "InputWidth", tempstring );
 
1076
 
 
1077
        config_save( ct, "V4LDevice", ct->v4ldev );
 
1078
        config_save( ct, "VBIDevice", ct->vbidev );
 
1079
 
 
1080
        snprintf( tempstring, sizeof( tempstring ), "%d", ct->inputnum );
 
1081
        config_save( ct, "V4LInput", tempstring );
 
1082
 
 
1083
        config_save( ct, "Norm", ct->norm );
 
1084
        config_save( ct, "Frequencies", ct->freq );
 
1085
 
 
1086
        config_save( ct, "MixerDevice", ct->mixerdev );
 
1087
 
 
1088
        config_save( ct, "XMLTVFile", ct->xmltvfile );
 
1089
    }
 
1090
 
 
1091
    return 1;
 
1092
}
 
1093
 
 
1094
int config_parse_tvtime_config_command_line( config_t *ct, int argc, char **argv )
 
1095
{
 
1096
    static struct option long_options[] = {
 
1097
        { "help", 0, 0, 'h' },
 
1098
        { "height", 1, 0, 'H' },
 
1099
        { "inputwidth", 1, 0, 'I' },
 
1100
        { "driver", 1, 0, 'D' },
 
1101
        { "input", 2, 0, 'i' },
 
1102
        { "channel", 1, 0, 'c' },
 
1103
        { "configfile", 1, 0, 'F' },
 
1104
        { "norm", 2, 0, 'n' },
 
1105
        { "frequencies", 2, 0, 'f' },
 
1106
        { "vbidevice", 2, 0, 'b' },
 
1107
        { "device", 2, 0, 'd' },
 
1108
        { "mixer", 1, 0, 'x' },
 
1109
        { "fullscreen", 0, 0, 'm' },
 
1110
        { "window", 0, 0, 'M' },
 
1111
        { "widescreen", 0, 0, 'a' },
 
1112
        { "fspos", 1, 0, 'p' },
 
1113
        { "xmltv", 2, 0, 't' },
 
1114
        { "priority", 2, 0, 'R' },
 
1115
        { 0, 0, 0, 0 }
 
1116
    };
 
1117
    int option_index = 0;
 
1118
    char c;
 
1119
 
 
1120
    if( argc == 1 ) {
 
1121
        print_config_usage( argv );
 
1122
        return 0;
 
1123
    }
 
1124
 
 
1125
    while( (c = getopt_long( argc, argv, "ahmMF:H:I:d:b:i:c:n:D:f:x:p:t:R:",
 
1126
            long_options, &option_index )) != -1 ) {
 
1127
        switch( c ) {
 
1128
        case 'a': ct->aspect = 1; break;
 
1129
        case 'm': ct->fullscreen = 1; break;
 
1130
        case 'M': ct->fullscreen = 0; break;
 
1131
        case 'F': if( ct->config_filename ) free( ct->config_filename );
 
1132
                  ct->config_filename = expand_user_path( optarg );
 
1133
                  if( ct->config_filename ) {
 
1134
                      lfprintf( stderr,
 
1135
                                _("Reading configuration from %s\n"),
 
1136
                                ct->config_filename );
 
1137
                      conf_xml_parse( ct, ct->config_filename );
 
1138
                  }
 
1139
                  break;
 
1140
        case 'x': if( ct->mixerdev ) { free( ct->mixerdev ); }
 
1141
                  ct->mixerdev = strdup( optarg ); break;
 
1142
        case 'H': if( tolower( optarg[ 0 ] ) == 'f' ) {
 
1143
                      ct->outputheight = -1;
 
1144
                  } else {
 
1145
                      ct->outputheight = atoi( optarg );
 
1146
                  }
 
1147
                  break;
 
1148
        case 'I': ct->inputwidth = atoi( optarg ); break;
 
1149
        case 'd': if( !optarg ) {
 
1150
                      fprintf( stdout, "V4LDevice:%s\n",
 
1151
                               config_get_v4l_device( ct ) );
 
1152
                  } else {
 
1153
                      free( ct->v4ldev );
 
1154
                      ct->v4ldev = strdup( optarg );
 
1155
                  }
 
1156
                  break;
 
1157
        case 'b': if( !optarg ) {
 
1158
                      fprintf( stdout, "VBIDevice:%s\n",
 
1159
                               config_get_vbi_device( ct ) );
 
1160
                  } else {
 
1161
                      free( ct->vbidev );
 
1162
                      ct->vbidev = strdup( optarg );
 
1163
                  }
 
1164
                  break;
 
1165
        case 'i': if( !optarg ) {
 
1166
                      fprintf( stdout, "V4LInput:%d\n",
 
1167
                               config_get_inputnum( ct ) );
 
1168
                  } else {
 
1169
                      ct->inputnum = atoi( optarg );
 
1170
                  }
 
1171
                  break;
 
1172
        case 'c': ct->prev_channel = ct->start_channel;
 
1173
                  ct->start_channel = atoi( optarg ); break;
 
1174
        case 't': if( !optarg ) {
 
1175
                      fprintf( stdout, "XMLTVFile:%s\n",
 
1176
                               config_get_xmltv_file( ct ) );
 
1177
                  } else {
 
1178
                      if( ct->xmltvfile ) free( ct->xmltvfile );
 
1179
                      ct->xmltvfile = expand_user_path( optarg );
 
1180
                  }
 
1181
                  break;
 
1182
        case 'n': if( !optarg ) {
 
1183
                      fprintf( stdout, "Norm:%s\n", config_get_v4l_norm( ct ) );
 
1184
                  } else {
 
1185
                      free( ct->norm );
 
1186
                      ct->norm = strdup( optarg );
 
1187
                  }
 
1188
                  break;
 
1189
        case 'D': if( ct->output_driver ) { free( ct->output_driver ); }
 
1190
                  ct->output_driver = strdup( optarg ); break;
 
1191
        case 'p': if( tolower( optarg[ 0 ] ) == 't' ) {
 
1192
                      ct->fspos = 1;
 
1193
                  } else if( tolower( optarg[ 0 ] ) == 'b' ) {
 
1194
                      ct->fspos = 2;
 
1195
                  } else {
 
1196
                      ct->fspos = 0;
 
1197
                  }
 
1198
                  break;
 
1199
        case 'f': if( !optarg ) {
 
1200
                      fprintf( stdout, "Frequencies:%s\n",
 
1201
                               config_get_v4l_freq( ct ) );
 
1202
                  } else {
 
1203
                      free( ct->freq );
 
1204
                      ct->freq = strdup( optarg );
 
1205
                  }
 
1206
                  break;
 
1207
        case 'R': if( !optarg ) {
 
1208
                      fprintf( stdout, "Priority:%d\n",
 
1209
                               config_get_priority( ct ) );
 
1210
                  } else {
 
1211
                      ct->priority = atoi( optarg );
 
1212
                  }
 
1213
                  break;
 
1214
        default:
 
1215
            print_config_usage( argv );
 
1216
            return 0;
 
1217
        }
 
1218
    }
 
1219
 
 
1220
    ct->doc = configsave_open( ct->config_filename );
 
1221
 
 
1222
    if( ct->doc ) {
 
1223
        char tempstring[ 32 ];
 
1224
 
 
1225
        /**
 
1226
         * Options that aren't specified on the command line
 
1227
         * will match the config file anyway, so save everything that
 
1228
         * you can save on the command line.
 
1229
         */
 
1230
        snprintf( tempstring, sizeof( tempstring ), "%d", ct->aspect );
 
1231
        config_save( ct, "Widescreen", tempstring );
 
1232
 
 
1233
        snprintf( tempstring, sizeof( tempstring ), "%d", ct->fullscreen );
 
1234
        config_save( ct, "Fullscreen", tempstring );
 
1235
 
 
1236
        snprintf( tempstring, sizeof( tempstring ), "%d", ct->verbose );
 
1237
        config_save( ct, "Verbose", tempstring );
 
1238
 
 
1239
        config_save( ct, "OutputDriver", ct->output_driver );
 
1240
 
 
1241
        if( ct->fspos == 0 ) {
 
1242
            config_save( ct, "FullscreenPosition", "Centre" );
 
1243
        } else if( ct->fspos == 1 ) {
 
1244
            config_save( ct, "FullscreenPosition", "Top" );
 
1245
        } else if( ct->fspos == 2 ) {
 
1246
            config_save( ct, "FullscreenPosition", "Bottom" );
 
1247
        }
 
1248
 
 
1249
        snprintf( tempstring, sizeof( tempstring ), "%d", ct->outputheight );
 
1250
        config_save( ct, "OutputHeight", tempstring );
 
1251
 
 
1252
        snprintf( tempstring, sizeof( tempstring ), "%d", ct->inputwidth );
 
1253
        config_save( ct, "InputWidth", tempstring );
 
1254
 
 
1255
        config_save( ct, "V4LDevice", ct->v4ldev );
 
1256
 
 
1257
        config_save( ct, "VBIDevice", ct->vbidev );
 
1258
 
 
1259
        snprintf( tempstring, sizeof( tempstring ), "%d", ct->inputnum );
 
1260
        config_save( ct, "V4LInput", tempstring );
 
1261
 
 
1262
        config_save( ct, "Norm", ct->norm );
 
1263
        config_save( ct, "Frequencies", ct->freq );
 
1264
 
 
1265
        config_save( ct, "MixerDevice", ct->mixerdev );
 
1266
 
 
1267
        config_save( ct, "XMLTVFile", ct->xmltvfile );
 
1268
 
 
1269
        snprintf( tempstring, sizeof( tempstring ), "%d", ct->priority );
 
1270
        config_save( ct, "ProcessPriority", tempstring );
 
1271
    }
 
1272
 
 
1273
    return 1;
 
1274
}
 
1275
 
 
1276
int config_parse_tvtime_scanner_command_line( config_t *ct, int argc,
 
1277
                                              char **argv )
 
1278
{
 
1279
    static struct option long_options[] = {
 
1280
        { "help", 0, 0, 'h' },
 
1281
        { "height", 1, 0, 'H' },
 
1282
        { "input", 1, 0, 'i' },
 
1283
        { "configfile", 1, 0, 'F' },
 
1284
        { "norm", 1, 0, 'n' },
 
1285
        { "device", 1, 0, 'd' },
 
1286
        { 0, 0, 0, 0 }
 
1287
    };
 
1288
    int option_index = 0;
 
1289
    char c;
 
1290
 
 
1291
    while( (c = getopt_long( argc, argv, "hF:d:i:n:",
 
1292
            long_options, &option_index )) != -1 ) {
 
1293
        switch( c ) {
 
1294
        case 'F': if( ct->config_filename ) free( ct->config_filename );
 
1295
                  ct->config_filename = expand_user_path( optarg );
 
1296
                  if( ct->config_filename ) {
 
1297
                      lfprintf( stderr,
 
1298
                                _("Reading configuration from %s\n"),
 
1299
                                ct->config_filename );
 
1300
                      conf_xml_parse( ct, ct->config_filename );
 
1301
                  }
 
1302
                  break;
 
1303
        case 'd': free( ct->v4ldev ); ct->v4ldev = strdup( optarg ); break;
 
1304
        case 'i': ct->inputnum = atoi( optarg ); break;
 
1305
        case 'n': free( ct->norm ); ct->norm = strdup( optarg ); break;
 
1306
        default:
 
1307
            print_scanner_usage( argv );
 
1308
            return 0;
 
1309
        }
 
1310
    }
 
1311
 
 
1312
    return 1;
 
1313
}
 
1314
 
 
1315
 
 
1316
 
 
1317
void config_free_data( config_t *ct )
 
1318
{
 
1319
    if( ct->doc ) xmlFreeDoc( ct->doc );
 
1320
    if( ct->v4ldev ) free( ct->v4ldev );
 
1321
    if( ct->norm ) free( ct->norm );
 
1322
    if( ct->freq ) free( ct->freq );
 
1323
    if( ct->ssdir ) free( ct->ssdir );
 
1324
    if( ct->audiomode ) free( ct->audiomode );
 
1325
    if( ct->xmltvfile ) free( ct->xmltvfile );
 
1326
    if( ct->timeformat ) free( ct->timeformat );
 
1327
    if( ct->output_driver ) free( ct->output_driver );
 
1328
    if( ct->rvr_filename ) free( ct->rvr_filename );
 
1329
    if( ct->mpeg_filename ) free( ct->mpeg_filename );
 
1330
    if( ct->mixerdev ) free( ct->mixerdev );
 
1331
    if( ct->vbidev ) free( ct->vbidev );
 
1332
    if( ct->config_filename ) free( ct->config_filename );
 
1333
    if( ct->deinterlace_method ) free( ct->deinterlace_method );
 
1334
}
 
1335
 
 
1336
void config_delete( config_t *ct )
 
1337
{
 
1338
    int i;
 
1339
 
 
1340
    while( ct->modelist ) {
 
1341
        tvtime_modelist_t *mode = ct->modelist;
 
1342
        ct->modelist = mode->next;
 
1343
        config_free_data( &(mode->settings) );
 
1344
        free( mode->name );
 
1345
        free( mode );
 
1346
    }
 
1347
 
 
1348
    for( i = 0; i < 8 * MAX_KEYSYMS; i++ ) {
 
1349
        if( ct->keymap_arg[ i ] ) free( ct->keymap_arg[ i ] );
 
1350
        if( ct->keymapmenu_arg[ i ] ) free( ct->keymapmenu_arg[ i ] );
 
1351
    }
 
1352
 
 
1353
    for( i = 0; i < MAX_BUTTONS; i++ ) {
 
1354
        if( ct->buttonmap_arg[ i ] ) free( ct->buttonmap_arg[ i ] );
 
1355
        if( ct->buttonmapmenu_arg[ i ] ) free( ct->buttonmapmenu_arg[ i ] );
 
1356
    }
 
1357
 
 
1358
    config_free_data( ct );
 
1359
    free( ct );
 
1360
}
 
1361
 
 
1362
void config_save( config_t *ct, const char *name, const char *value )
 
1363
{
 
1364
    xmlNodePtr top, node;
 
1365
 
 
1366
    if( !ct->doc ) return;
 
1367
 
 
1368
    top = xmlDocGetRootElement( ct->doc );
 
1369
    if( !top ) {
 
1370
        return;
 
1371
    }
 
1372
 
 
1373
    node = find_option( top->xmlChildrenNode, name );
 
1374
    if( !node ) {
 
1375
        node = xmlNewTextChild( top, 0, BAD_CAST "option", 0 );
 
1376
        xmlNewProp( node, BAD_CAST "name", BAD_CAST name );
 
1377
        xmlNewProp( node, BAD_CAST "value", BAD_CAST value );
 
1378
    } else {
 
1379
        xmlSetProp( node, BAD_CAST "value", BAD_CAST value );
 
1380
    }
 
1381
 
 
1382
    xmlKeepBlanksDefault( 0 );
 
1383
    xmlSaveFormatFile( ct->config_filename, ct->doc, 1 );
 
1384
}
 
1385
 
 
1386
int config_key_to_command( config_t *ct, int key )
 
1387
{
 
1388
    if( key ) {
 
1389
        if( ct->keymap[ MAX_KEYSYMS*((key & 0x70000)>>16) + (key & 0x1ff) ] ) {
 
1390
            return ct->keymap[ MAX_KEYSYMS*((key & 0x70000)>>16) + (key & 0x1ff) ];
 
1391
        }
 
1392
 
 
1393
        if( isalnum( key & 0x1ff ) ) {
 
1394
            return TVTIME_CHANNEL_CHAR;
 
1395
        }
 
1396
    }
 
1397
        
 
1398
    return TVTIME_NOCOMMAND;
 
1399
}
 
1400
 
 
1401
const char *config_key_to_command_argument( config_t *ct, int key )
 
1402
{
 
1403
    if( key ) {
 
1404
        if( ct->keymap_arg[ MAX_KEYSYMS*((key & 0x70000)>>16) + (key & 0x1ff) ] ) {
 
1405
            return ct->keymap_arg[ MAX_KEYSYMS*((key & 0x70000)>>16) + (key & 0x1ff) ];
 
1406
        }
 
1407
    }
 
1408
    return 0;
 
1409
}
 
1410
 
 
1411
int config_key_to_menu_command( config_t *ct, int key )
 
1412
{
 
1413
    if( key ) {
 
1414
        int cmd;
 
1415
 
 
1416
        if( ct->keymapmenu[ MAX_KEYSYMS*((key & 0x70000)>>16) + (key & 0x1ff) ] ) {
 
1417
            return ct->keymapmenu[ MAX_KEYSYMS*((key & 0x70000)>>16) + (key & 0x1ff) ];
 
1418
        }
 
1419
 
 
1420
        /* Fall back to standard commands. */
 
1421
        cmd = config_key_to_command( ct, key );
 
1422
        if( cmd != TVTIME_NOCOMMAND ) {
 
1423
            return cmd;
 
1424
        }
 
1425
 
 
1426
        if( isalnum( key & 0x1ff ) ) {
 
1427
            return TVTIME_CHANNEL_CHAR;
 
1428
        }
 
1429
    }
 
1430
        
 
1431
    return TVTIME_NOCOMMAND;
 
1432
}
 
1433
 
 
1434
const char *config_key_to_menu_command_argument( config_t *ct, int key )
 
1435
{
 
1436
    if( key ) {
 
1437
        if( ct->keymapmenu_arg[ MAX_KEYSYMS*((key & 0x70000)>>16) + (key & 0x1ff) ] ) {
 
1438
            return ct->keymapmenu_arg[ MAX_KEYSYMS*((key & 0x70000)>>16) + (key & 0x1ff) ];
 
1439
        }
 
1440
 
 
1441
        return config_key_to_command_argument( ct, key );
 
1442
    }
 
1443
 
 
1444
    return 0;
 
1445
}
 
1446
 
 
1447
int config_command_to_key( config_t *ct, int command )
 
1448
{
 
1449
    int i;
 
1450
 
 
1451
    for( i = 0; i < 8 * MAX_KEYSYMS; i++ ) {
 
1452
        if( ct->keymap[ i ] == command ) return i;
 
1453
    }
 
1454
 
 
1455
    return 0;
 
1456
}
 
1457
 
 
1458
int config_button_to_command( config_t *ct, int button )
 
1459
{
 
1460
    if( button < 0 || button >= MAX_BUTTONS ) {
 
1461
        return 0;
 
1462
    } else {
 
1463
        return ct->buttonmap[ button ];
 
1464
    }
 
1465
}
 
1466
 
 
1467
const char *config_button_to_command_argument( config_t *ct, int button )
 
1468
{
 
1469
    if( button < 0 || button >= MAX_BUTTONS ) {
 
1470
        return 0;
 
1471
    } else {
 
1472
        return ct->buttonmap_arg[ button ];
 
1473
    }
 
1474
}
 
1475
 
 
1476
int config_button_to_menu_command( config_t *ct, int button )
 
1477
{
 
1478
    if( button < 0 || button >= MAX_BUTTONS ) {
 
1479
        return 0;
 
1480
    } else {
 
1481
        if( ct->buttonmapmenu[ button ] ) {
 
1482
            return ct->buttonmapmenu[ button ];
 
1483
        } else {
 
1484
            return ct->buttonmap[ button ];
 
1485
        }
 
1486
    }
 
1487
}
 
1488
 
 
1489
const char *config_button_to_menu_command_argument( config_t *ct, int button )
 
1490
{
 
1491
    if( button < 0 || button >= MAX_BUTTONS ) {
 
1492
        return 0;
 
1493
    } else {
 
1494
        if( ct->buttonmapmenu_arg[ button ] ) {
 
1495
            return ct->buttonmapmenu_arg[ button ];
 
1496
        } else {
 
1497
            return ct->buttonmap_arg[ button ];
 
1498
        }
 
1499
    }
 
1500
}
 
1501
 
 
1502
int config_get_num_modes( config_t *ct )
 
1503
{
 
1504
    return ct->nummodes;
 
1505
}
 
1506
 
 
1507
config_t *config_get_mode_info( config_t *ct, int mode )
 
1508
{
 
1509
    tvtime_modelist_t *cur = ct->modelist;
 
1510
 
 
1511
    if( !cur ) {
 
1512
        /* No modes. */
 
1513
        return 0;
 
1514
    }
 
1515
 
 
1516
    while( mode && cur->next ) {
 
1517
        cur = cur->next;
 
1518
        mode--;
 
1519
    }
 
1520
 
 
1521
    return &(cur->settings);
 
1522
}
 
1523
 
 
1524
int config_get_verbose( config_t *ct )
 
1525
{
 
1526
    return ct->verbose;
 
1527
}
 
1528
 
 
1529
int config_get_send_fields( config_t *ct )
 
1530
{
 
1531
    return ct->send_fields;
 
1532
}
 
1533
 
 
1534
const char *config_get_output_driver( config_t *ct )
 
1535
{
 
1536
    return ct->output_driver;
 
1537
}
 
1538
 
 
1539
int config_get_debug( config_t *ct )
 
1540
{
 
1541
    return ct->debug;
 
1542
}
 
1543
 
 
1544
int config_get_outputheight( config_t *ct )
 
1545
{
 
1546
    return ct->outputheight;
 
1547
}
 
1548
 
 
1549
int config_get_useposition( config_t *ct )
 
1550
{
 
1551
    return ct->useposition;
 
1552
}
 
1553
 
 
1554
int config_get_output_x( config_t *ct )
 
1555
{
 
1556
    return ct->x;
 
1557
}
 
1558
 
 
1559
int config_get_output_y( config_t *ct )
 
1560
{
 
1561
    return ct->y;
 
1562
}
 
1563
 
 
1564
int config_get_inputwidth( config_t *ct )
 
1565
{
 
1566
    return ct->inputwidth;
 
1567
}
 
1568
 
 
1569
int config_get_aspect( config_t *ct )
 
1570
{
 
1571
    return ct->aspect;
 
1572
}
 
1573
 
 
1574
int config_get_start_channel( config_t *ct )
 
1575
{
 
1576
    return ct->start_channel;
 
1577
}
 
1578
 
 
1579
int config_get_prev_channel( config_t *ct )
 
1580
{
 
1581
    return ct->prev_channel;
 
1582
}
 
1583
 
 
1584
int config_get_inputnum( config_t *ct )
 
1585
{
 
1586
    return ct->inputnum;
 
1587
}
 
1588
 
 
1589
int config_get_apply_luma_correction( config_t *ct )
 
1590
{
 
1591
    return ct->apply_luma_correction;
 
1592
}
 
1593
 
 
1594
const char *config_get_deinterlace_method( config_t *ct )
 
1595
{
 
1596
    return ct->deinterlace_method;
 
1597
}
 
1598
 
 
1599
double config_get_luma_correction( config_t *ct )
 
1600
{
 
1601
    return ct->luma_correction;
 
1602
}
 
1603
 
 
1604
const char *config_get_v4l_device( config_t *ct )
 
1605
{
 
1606
    return ct->v4ldev;
 
1607
}
 
1608
 
 
1609
const char *config_get_v4l_norm( config_t *ct )
 
1610
{
 
1611
    return ct->norm;
 
1612
}
 
1613
 
 
1614
int config_get_fullscreen( config_t *ct )
 
1615
{
 
1616
    return ct->fullscreen;
 
1617
}
 
1618
 
 
1619
int config_get_priority( config_t *ct )
 
1620
{
 
1621
    return ct->priority;
 
1622
}
 
1623
 
 
1624
const char *config_get_v4l_freq( config_t *ct )
 
1625
{
 
1626
    return ct->freq;
 
1627
}
 
1628
 
 
1629
const char *config_get_vbi_device( config_t *ct )
 
1630
{
 
1631
    return ct->vbidev;
 
1632
}
 
1633
 
 
1634
const char *config_get_timeformat( config_t *ct )
 
1635
{
 
1636
    return ct->timeformat;
 
1637
}
 
1638
 
 
1639
unsigned int config_get_channel_text_rgb( config_t *ct )
 
1640
{
 
1641
    return ct->channel_text_rgb;
 
1642
}
 
1643
 
 
1644
unsigned int config_get_other_text_rgb( config_t *ct )
 
1645
{
 
1646
    return ct->other_text_rgb;
 
1647
}
 
1648
 
 
1649
uid_t config_get_uid( config_t *ct )
 
1650
{
 
1651
    return ct->uid;
 
1652
}
 
1653
 
 
1654
int config_get_usexds( config_t *ct )
 
1655
{
 
1656
    return ct->use_xds;
 
1657
}
 
1658
 
 
1659
int config_get_check_freq_present( config_t *ct )
 
1660
{
 
1661
    return ct->check_freq_present;
 
1662
}
 
1663
 
 
1664
double config_get_overscan( config_t *ct )
 
1665
{
 
1666
    return ct->overscan;
 
1667
}
 
1668
 
 
1669
int config_get_ntsc_cable_mode( config_t *ct )
 
1670
{
 
1671
    return ct->ntsc_mode;
 
1672
}
 
1673
 
 
1674
const char *config_get_screenshot_dir( config_t *ct )
 
1675
{
 
1676
    return ct->ssdir;
 
1677
}
 
1678
 
 
1679
const char *config_get_rvr_filename( config_t *ct )
 
1680
{
 
1681
    return ct->rvr_filename;
 
1682
}
 
1683
 
 
1684
const char *config_get_mpeg_filename( config_t *ct )
 
1685
{
 
1686
    return ct->mpeg_filename;
 
1687
}
 
1688
 
 
1689
int config_get_framerate_mode( config_t *ct )
 
1690
{
 
1691
    return ct->framerate;
 
1692
}
 
1693
 
 
1694
int config_get_slave_mode( config_t *ct )
 
1695
{
 
1696
    return ct->slave_mode;
 
1697
}
 
1698
 
 
1699
const char *config_get_mixer_device( config_t *ct )
 
1700
{
 
1701
    return ct->mixerdev;
 
1702
}
 
1703
 
 
1704
int config_get_fullscreen_position( config_t *ct )
 
1705
{
 
1706
    return ct->fspos;
 
1707
}
 
1708
 
 
1709
int config_get_save_restore_picture( config_t *ct )
 
1710
{
 
1711
    return ct->picsaverestore;
 
1712
}
 
1713
 
 
1714
int config_get_global_brightness( config_t *ct )
 
1715
{
 
1716
    return ct->brightness;
 
1717
}
 
1718
 
 
1719
int config_get_global_contrast( config_t *ct )
 
1720
{
 
1721
    return ct->contrast;
 
1722
}
 
1723
 
 
1724
int config_get_global_colour( config_t *ct )
 
1725
{
 
1726
    return ct->colour;
 
1727
}
 
1728
 
 
1729
int config_get_global_hue( config_t *ct )
 
1730
{
 
1731
    return ct->hue;
 
1732
}
 
1733
 
 
1734
const char *config_get_audio_mode( config_t *ct )
 
1735
{
 
1736
    return ct->audiomode;
 
1737
}
 
1738
 
 
1739
const char *config_get_xmltv_file( config_t *ct )
 
1740
{
 
1741
    return ct->xmltvfile;
 
1742
}
 
1743
 
 
1744
int config_get_invert( config_t *ct )
 
1745
{
 
1746
    return ct->invert;
 
1747
}
 
1748
 
 
1749
int config_get_cc( config_t *ct )
 
1750
{
 
1751
    return ct->cc;
 
1752
}
 
1753
 
 
1754
int config_get_mirror( config_t *ct )
 
1755
{
 
1756
    return ct->mirror;
 
1757
}
 
1758