Annotation of multiplexer/command.c, revision 1.31
1.1 oskar 1: /*
2: * ISO 13818 stream multiplexer
3: * Copyright (C) 2001 Convergence Integrated Media GmbH Berlin
1.27 oskar 4: * Copyright (C) 2004..2005 Oskar Schirmer (schirmer@scara.com)
1.21 oskar 5: *
6: * This program is free software; you can redistribute it and/or modify
7: * it under the terms of the GNU General Public License as published by
8: * the Free Software Foundation; either version 2 of the License, or
9: * (at your option) any later version.
10: *
11: * This program is distributed in the hope that it will be useful,
12: * but WITHOUT ANY WARRANTY; without even the implied warranty of
13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14: * GNU General Public License for more details.
15: *
16: * You should have received a copy of the GNU General Public License
17: * along with this program; if not, write to the Free Software
18: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1.1 oskar 19: */
20:
21: /*
22: * Module: Command
23: * Purpose: User interface.
24: */
25:
26: #include "global.h"
27: #include "error.h"
28: #include "input.h"
1.14 oskar 29: #include "output.h"
1.1 oskar 30: #include "command.h"
31: #include "splice.h"
32: #include "splitpes.h"
1.10 oskar 33: #include "splitts.h"
1.1 oskar 34: #include "dispatch.h"
1.8 oskar 35: #include "ts.h"
1.1 oskar 36:
37: static int argc, argi;
38: static char **argv;
39: static boolean first;
40:
41: static int cmdf;
42:
43: static byte combuf[MAX_DATA_COMB];
44: static int combln, comlln;
45: static char *comarg;
46:
1.6 oskar 47: static char *lastfile; /* Hold last filename used */
1.1 oskar 48:
1.5 oskar 49: static filerefer_list *filerefer;
50:
1.1 oskar 51: static command_list coms[] = {
1.8 oskar 52: {C_HELP,14,-1, "help", "display this help", ""},
53: {C_VERS,14,'V',"version","output version information", ""},
54: {C_QUIT,14,'Q',"quit", "quit this program", ""},
55: {C_VERB,8, 'v',"verbose","[<level>]", ""},
56: {0, 18,-1, NULL,
57: "verbose mode 0..6, default=2, initial=1", ""},
1.1 oskar 58: {C_OPES,4, 'p',"pes", "<file>%s", " <target program>"},
1.8 oskar 59: {0, 18,-1, NULL,
60: "open a PES input <file>%s", ", output as <target program>"},
1.1 oskar 61: {C_OPES,4, 'p',"pes", "<file'>%s <target stream id>", " <target program>"},
1.8 oskar 62: {0, 18,-1, NULL,
63: "open a PES input <file'>, output as <target stream id>", ""},
1.1 oskar 64: {C_OPS, 3, 'P',"ps", "<file>%s", " <target program>"},
1.8 oskar 65: {0, 18,-1, NULL,
66: "open a PS input <file>%s", ", output as <target program>"},
1.1 oskar 67: {C_OPS, 3, 'P',"ps",
68: "<file'>%s <source stream id> [<target stream id>]", " <target program>"},
1.8 oskar 69: {0, 18,-1, NULL,
1.1 oskar 70: "take a stream from PS, output as <target stream id>", ""},
1.8 oskar 71: {C_OTS, 3, 'T',"ts", "<file> open a TS input <file>", ""},
1.1 oskar 72: {C_OTS, 3, 'T',"ts", "<file'> <source program>%s", " [<target program>]"},
1.8 oskar 73: {0, 18,-1, NULL,
1.1 oskar 74: "open <source program>%s", ", output as <target program>"},
75: {C_OTS, 3, 'T',"ts",
1.19 oskar 76: "<file'> <source prog> %s<stream id> [<target stream id>]",
77: "<target prog> "},
1.8 oskar 78: {0, 18,-1, NULL,
1.1 oskar 79: "open <source prog>, take <stream id>, output%s", " in"},
1.8 oskar 80: {0, 18,-1, NULL, "%sas <target stream id>", "<target prog> "},
1.19 oskar 81: {C_OTS, 3, 'T',"ts", "<file'> 0 %s<source stream id> [<target stream id>]",
82: "<target prog> "},
83: {0, 18,-1, NULL,
84: "from a single-program TS with broken PSI, take a stream", ""},
1.8 oskar 85: {C_CLOS,6, 'c',"close", "<file> close <file> as if eof is reached", ""},
86: {C_APPE,7, 'a',"append","<file'> <file2> [<num>]", ""},
87: {0, 18,-1, NULL,
88: "append <file2> to open as soon as <file'> is done,", ""},
89: {0, 18,-1, NULL,
90: "set repeatition for <file2> to <num>, infinite=0", ""},
1.5 oskar 91: {C_FILE,5, 'f',"file", "<refnum> <filename>", ""},
1.8 oskar 92: {0, 18,-1, NULL,
1.5 oskar 93: "declare a number to be used instead of a file name", ""},
1.19 oskar 94: {C_CROP,5, 'x',"crop", "%s[<target stream id>]", "<target prog> "},
1.8 oskar 95: {0, 18,-1, NULL,
1.4 oskar 96: "crop %sprogram or a stream", "a "},
1.8 oskar 97: {C_REPT,7, 'r',"repeat","<file'> <num>", ""},
98: {0, 18,-1, NULL,
99: "set repeatition for <file'> to <num>, infinite=0", ""},
1.1 oskar 100: {C_FROP,7,'R',"reopen",
1.8 oskar 101: "... open the next file with new handle even if yet open", ""},
102: {C_TSSI,3, -1, "si",
103: "<file'> [<low> <high>]", NULL},
1.13 oskar 104: {0, 18,-1, NULL,
1.10 oskar 105: "in TS <file'> handle pids in <low>..<high> as SI-streams", NULL},
1.17 oskar 106: {C_TSSP,6, -1, "sipid",
107: "<target program> [<pid> [<stream type>]]", NULL},
108: {0, 18, -1, NULL,
109: "manually add/delete entry in PMT for <target program>", NULL},
1.18 oskar 110: {C_DSCR,6, -1, "descr",
111: "%s[<tag> [<length> <data>...]]", "<target_prog> "},
112: {0, 18, -1, NULL,
113: "add/inhibit/delete a descriptor (not stream specific)", ""},
114: {C_DSCS,7, -1, "sdescr",
115: "[%s[<stream_id> [<tag> [<length> <data>...]]]]", "<target_prog> "},
116: {0, 18, -1, NULL,
117: "add/inhibit/delete a descriptor for <stream_id>", ""},
118: {C_DSCP,7, -1, "pdescr",
119: "[<target_prog> [<pid> [<tag> [<length> <data>...]]]]", NULL},
120: {0, 18, -1, NULL,
121: "add/inhibit/delete a descriptor for <pid>", NULL},
1.1 oskar 122: {C_TSID,6, 'I',"ident",
1.8 oskar 123: "<num> set the output transport stream id", NULL},
124: {C_BUSY,5, 'B',"busy", "[0|1] if '1' do not stop if idle", ""},
125: {C_TIMD,14,-1, "timed",
1.1 oskar 126: "force delay timing even if solely diskfiles in use", ""},
127: {C_FPSI,5 ,'F',"fpsi",
1.8 oskar 128: "<msec> set psi table frequency, single=0, initial=0", ""},
1.16 oskar 129: {C_TRGI,7, -1, "trigin",
130: "<msec> set input buffer trigger timing, initial=250", ""},
131: {C_TRGO,8, -1, "trigout",
132: "<msec>", ""},
133: {0, 18,-1, NULL,
134: "set output buffer trigger timing, initial=250", ""},
1.13 oskar 135: {C_CONF,7 ,'C',"config",
1.18 oskar 136: "0..2 show current stream configuration (off=0, on=1, more=2)", ""},
1.13 oskar 137: {C_STAT,11,'S',"statistics",
138: "<msec>", ""},
139: {0, 18,-1, NULL,
140: "show load statistics periodically (off=0)", ""},
1.27 oskar 141: {C_NETW,4 ,-1, "nit",
142: "[<pid>] add/omit network pid to program association table", NULL},
1.8 oskar 143: {C_BSCR,14,-1, "badtiming",
1.1 oskar 144: "accept and maybe correct bad timing from DVB card", ""},
1.22 oskar 145: {C_CPID,17,-1, "conservativepids", "[0|1]", NULL},
146: {0, 18,-1, NULL,
147: "be conservative in pid assignment", NULL},
1.1 oskar 148: {0, 0, 0, NULL, NULL, NULL}
149: };
150:
1.6 oskar 151: /* Pop m characters from command input buffer by moving
152: * the rest to the left.
153: * Precondition: 0<=m<=cmbln
154: */
1.1 oskar 155: static void moveleft (int m)
156: {
157: combln -= m;
1.15 oskar 158: memmove (&combuf[0], &combuf[m], combln);
1.1 oskar 159: }
160:
1.6 oskar 161: /* Determine whether there is a complete command line
162: * available. If so, split into single words.
163: * Precondition: combln>=0
164: * Postcondition: argc==WordCount and argi==1 and comarg^==Word[0]
165: * and comlln==LineLength
166: * Return: TRUE, if line complete, FALSE otherwise.
167: */
1.1 oskar 168: static boolean line_complete (void)
169: {
170: int i;
171: i = 0;
172: while (i < combln) {
173: if (combuf[i] == '\n') {
174: argc = 1;
175: comlln = i;
176: while (i >= 0) {
177: if (combuf[i] <= ' ') {
178: combuf[i] = 0;
179: argi = argc;
180: } else {
181: comarg = &combuf[i];
182: argc = argi+1;
183: }
184: i -= 1;
185: }
186: argi = 1;
187: return (TRUE);
188: }
189: i += 1;
190: }
191: return (FALSE);
192: }
193:
1.6 oskar 194: /* Determine, if there is a tokenword available.
195: * Precondition: argc==Number_of_Words
196: * Return: Pointer to the word, if available, NULL otherwise.
197: */
1.1 oskar 198: static char *available_token (void)
199: {
200: char *r = NULL;
201: if (argi < argc) {
202: if (first) {
203: r = argv[argi];
204: } else {
205: r = comarg;
206: }
207: }
208: return (r);
209: }
210:
1.6 oskar 211: /* Scan to the next tokenword.
212: * Precondition: argc==WordCount and if !first: comarg^==Word[argi-1]
213: * Postcondition: dito.
214: */
1.1 oskar 215: static void next_token (void)
216: {
217: if (argi < argc) {
218: argi += 1;
219: if (!first) {
1.7 oskar 220: if (argi < argc) {
221: do {
222: comarg += 1;
223: } while (*comarg != 0);
224: do {
225: comarg += 1;
226: } while (*comarg == 0);
227: }
1.1 oskar 228: }
229: }
230: }
231:
1.6 oskar 232: /* Determine the token code for a word.
233: * If first: Decide for long command word, if double hyphen.
234: * If !first: Decide for long command word, if word length > 1
235: * Precondition: argc==WordCount and if !first: comarg^==Word[argi-1]
236: * Return: token>0, if found, -1 otherwise.
237: */
1.1 oskar 238: static int token_code (char *t)
239: {
240: command_list *l;
241: boolean islong;
242: if (t == NULL) {
243: return (0);
244: }
245: if (first) {
246: if (*t++ != '-') {
247: return (-1);
248: }
249: if ((islong = (*t == '-'))) {
250: t += 1;
251: }
252: } else {
253: islong = (t[1] != 0);
254: }
255: l = &coms[0];
256: while (l->width != 0) {
1.3 oskar 257: if (splice_multipleprograms || (l->explmulti != NULL)) {
258: if (l->comlong != NULL) {
259: if (islong ? (!strcmp(t,l->comlong))
260: : (*t == l->comshort)) {
261: return (l->token);
262: }
1.1 oskar 263: }
264: }
265: l += 1;
266: }
267: return (-1);
268: }
269:
1.6 oskar 270: /* Print usage information to stderr.
271: */
1.1 oskar 272: static void command_help (void)
273: {
274: command_list *l;
1.14 oskar 275: fprintf (stderr, "Usage: %s [COMMAND...]\n\n ", argv[0]);
1.1 oskar 276: l = &coms[0];
277: while (l->width != 0) {
278: if (splice_multipleprograms || (l->explmulti != NULL)) {
279: if (l->comshort > 0) {
1.14 oskar 280: fprintf (stderr, "-%c,", l->comshort);
1.1 oskar 281: } else {
1.14 oskar 282: fprintf (stderr, " ");
1.1 oskar 283: }
284: if (l->comlong != NULL) {
1.14 oskar 285: fprintf (stderr, " --%-*s", l->width, l->comlong);
1.1 oskar 286: } else {
1.14 oskar 287: fprintf (stderr, "%-*s", l->width, "");
1.1 oskar 288: }
1.14 oskar 289: fprintf (stderr, l->explain, splice_multipleprograms ? l->explmulti : "");
290: fprintf (stderr, "\n ");
1.1 oskar 291: }
292: l += 1;
293: }
294: fprintf (stderr, "\n"
295: "Any command may be fed to stdin omitting the leading (double) hyphen\n"
296: "during operation. '...' means following command wanted on same line.\n"
1.5 oskar 297: "Files may be specified by filename or reference number (set by --file).\n"
1.1 oskar 298: "<file'> may be replaced with '=' to use previously mentioned file.\n");
299: }
300:
1.6 oskar 301: /* Check the filerefer list for the given filerefnum
302: * Precondition: filerefnum>=0
303: * Return: Pointer to corresponding filename, if found, NULL otherwise.
304: */
1.5 oskar 305: static char *filerefer_name (int filerefnum)
306: {
307: filerefer_list *fref;
308: fref = filerefer;
309: while ((fref != NULL)
310: && (fref->filerefnum != filerefnum)) {
311: fref = fref->next;
312: }
313: if (fref != NULL) {
314: return (fref->filename);
315: } else {
316: return (input_filerefername (filerefnum));
317: }
318: }
319:
1.6 oskar 320: /* Add a pair of filerefnum and filename to the filerefer list.
321: * Replace a pair with same filerefnum, if found.
322: * Precondition: filerefnum>=0
323: * Postcondition: Only one entry with filerefnum is in the list.
324: */
1.5 oskar 325: static void filerefer_remind (int filerefnum,
326: char *filename)
327: {
328: filerefer_list *fref;
329: fref = filerefer;
330: while ((fref != NULL)
331: && (fref->filerefnum != filerefnum)) {
332: fref = fref->next;
333: }
334: if (fref == NULL) {
335: if ((fref = malloc (sizeof (filerefer_list))) != NULL) {
336: fref->next = filerefer;
337: fref->filerefnum = filerefnum;
338: filerefer = fref;
339: }
340: } else {
341: if (fref->filename != NULL) {
342: free (fref->filename);
343: }
344: }
345: if (fref != NULL) {
346: if ((fref->filename = malloc (strlen (filename) + 1)) != NULL) {
347: strcpy (fref->filename,filename);
348: }
349: }
350: }
351:
1.6 oskar 352: /* Remove a pair of filerefnum and filename from the filerefer list
353: * Precondition: Only one entry with filerefnum in the list.
354: * Postcondition: No entry with filerefnum in the list.
355: */
1.5 oskar 356: static void filerefer_forget (int filerefnum)
357: {
358: filerefer_list **rref;
359: rref = &filerefer;
360: while ((*rref != NULL)
361: && ((*rref)->filerefnum != filerefnum)) {
362: rref = &((*rref)->next);
363: }
364: if (*rref != NULL) {
365: filerefer_list *fref;
366: if ((*rref)->filename != NULL) {
367: free ((*rref)->filename);
368: }
369: fref = *rref;
370: *rref = (*rref)->next;
371: free (fref);
372: }
373: }
374:
1.6 oskar 375: /* Check for special token "=" that denotes "same file again"
376: * return: TRUE is name=="=", FALSE otherwise
377: */
1.1 oskar 378: static boolean fileagain (char *name)
379: {
1.7 oskar 380: if (name != NULL) {
381: return ((name[0] == '=') && (name[1] == 0));
382: } else {
383: return (FALSE);
384: }
1.1 oskar 385: }
386:
1.6 oskar 387: /* Remind the filename that was just used.
388: * Precondition: name!=NULL
389: */
1.5 oskar 390: static void set_lastfile (char *name)
391: {
1.20 oskar 392: char *lf;
393: if ((lf = malloc (strlen (name) + 1)) != NULL) {
394: strcpy (lf,name);
395: }
1.5 oskar 396: if (lastfile != NULL) {
397: free (lastfile);
398: }
1.20 oskar 399: lastfile = lf;
1.5 oskar 400: }
401:
1.6 oskar 402: /* Open a file given by name. If name is "=", use last filename, else
403: * set last filename. If opening succeeds, delete any corresponding
404: * entry from the filerefer list.
405: * Precondition: name!=NULL
406: * Return: File if opened, NULL otherwise.
407: */
1.1 oskar 408: static file_descr* openfile (char *name,
1.5 oskar 409: int filerefnum,
1.1 oskar 410: content_type content,
411: boolean automatic,
412: int programnb,
1.8 oskar 413: boolean forcereopen)
1.1 oskar 414: {
415: file_descr *f;
416: if (fileagain (name)) {
417: name = lastfile;
418: } else {
1.5 oskar 419: set_lastfile (name);
1.1 oskar 420: }
421: if (name != NULL) {
422: if ((!forcereopen)
423: && ((f = input_existfile (name)) != NULL)) {
424: warn (LIMP,"Open Existing",ECOM,3,2,f);
425: } else {
1.5 oskar 426: f = input_openfile (name,filerefnum,content,automatic,programnb);
427: if (f != NULL) {
428: filerefer_forget (filerefnum);
1.2 oskar 429: }
1.1 oskar 430: }
431: } else {
1.14 oskar 432: fprintf (stderr, "Missing file name\n");
1.2 oskar 433: f = NULL;
1.1 oskar 434: }
1.2 oskar 435: return (f);
1.1 oskar 436: }
437:
1.6 oskar 438: /* Parse a token word to see if it is a number in range low..high.
439: * high=-1 denotes upper limit = infinite.
440: * Precondition: low>=0
441: * Return: Number if parsed, -1 otherwise.
442: */
1.4 oskar 443: static long com_number (char *t,
1.1 oskar 444: long low,
445: long high)
446: {
1.4 oskar 447: long i;
1.5 oskar 448: char *e;
1.1 oskar 449: if (t == NULL) {
450: return (-1);
451: } else if (token_code (t) >= 0) {
452: return (-1);
453: }
454: errno = 0;
1.5 oskar 455: i = strtol (t,&e,0);
1.1 oskar 456: if (errno != 0) {
457: return (-1);
1.5 oskar 458: } else if (*e != 0) {
459: return (-1);
1.1 oskar 460: } else if ((i < low) || ((high >= low) && (i > high))) {
1.14 oskar 461: fprintf (stderr, "Number out of bounds: %ld\n", i);
1.1 oskar 462: return (-1);
463: } else {
464: return (i);
465: }
466: }
467:
468: static void command_toofew (void)
469: {
1.14 oskar 470: fprintf (stderr, "Too few or bad arguments.\n");
1.1 oskar 471: }
472:
1.6 oskar 473: /* Process one line of command words.
474: * Precondition: argc==WordCount and argi==1 and comarg^==Word[0]
475: * Return: TRUE, if processed ok, FALSE otherwise.
476: */
1.1 oskar 477: static boolean command (void)
478: {
479: char *fn;
1.5 oskar 480: int rn;
1.1 oskar 481: file_descr *f;
482: char *t;
483: boolean r;
484: boolean frop;
1.2 oskar 485: r = TRUE;
1.1 oskar 486: frop = FALSE;
487: t = available_token ();
488: while (r && (t != NULL)) {
489: next_token ();
490: warn (LIMP,"Command",ECOM,1,0,token_code(t));
491: switch (token_code (t)) {
492: case C_OPES:
493: fn = available_token ();
1.5 oskar 494: rn = com_number (fn,0,-1);
495: if (rn >= 0) {
496: fn = filerefer_name (rn);
497: }
1.1 oskar 498: if (fn != NULL) {
499: int tprg, tsid;
500: if (splice_multipleprograms) {
501: next_token ();
1.19 oskar 502: tprg = com_number (available_token (),0x0001L,0xFFFFL);
1.1 oskar 503: } else {
504: tprg = 0;
505: }
506: if (tprg >= 0) {
507: next_token ();
508: tsid = com_number (available_token (),0x00,0xFF);
509: if ((!fileagain (fn))
510: && (tsid < 0)) {
1.8 oskar 511: f = openfile (fn,rn,ct_packetized,TRUE,tprg,frop);
1.1 oskar 512: if (f == NULL) {
513: r = FALSE;
514: }
515: } else {
516: if (tsid >= 0) {
517: next_token ();
1.8 oskar 518: f = openfile (fn,rn,ct_packetized,FALSE,0,frop);
1.1 oskar 519: if (f != NULL) {
520: f->u.pes.stream =
521: connect_streamprog (
1.31 ! oskar 522: f,tprg,0,tsid,
! 523: guess_streamtype (tsid,-1),
! 524: f->u.pes.stream,
1.1 oskar 525: NULL,TRUE);
526: } else {
527: r = FALSE;
528: }
529: } else {
530: command_toofew ();
531: r = FALSE;
532: }
533: }
534: } else {
535: command_toofew ();
536: r = FALSE;
537: }
538: } else {
539: command_toofew ();
540: r = FALSE;
541: }
542: frop = FALSE;
543: break;
544: case C_OPS:
545: fn = available_token ();
1.5 oskar 546: rn = com_number (fn,0,-1);
547: if (rn >= 0) {
548: fn = filerefer_name (rn);
549: }
1.1 oskar 550: if (fn != NULL) {
551: int tprg, tsid, ssid;
552: if (splice_multipleprograms) {
553: next_token ();
1.19 oskar 554: tprg = com_number (available_token (),0x0001L,0xFFFFL);
1.1 oskar 555: } else {
556: tprg = 0;
557: }
558: if (tprg >= 0) {
559: next_token ();
560: ssid = com_number (available_token (),0x00,0xFF);
561: if ((!fileagain (fn))
562: && (ssid < 0)) {
1.8 oskar 563: f = openfile (fn,rn,ct_program,TRUE,tprg,frop);
1.1 oskar 564: if (f == NULL) {
565: r = FALSE;
566: }
567: } else {
568: if (ssid >= 0) {
569: next_token ();
1.8 oskar 570: f = openfile (fn,rn,ct_program,FALSE,0,frop);
1.1 oskar 571: if (f != NULL) {
572: tsid = com_number (available_token (),0x00,0xFF);
573: if (tsid >= 0) {
574: next_token ();
575: }
576: f->u.ps.stream[ssid] =
577: connect_streamprog (
578: f,tprg,ssid,tsid<0?-ssid:tsid,
1.31 ! oskar 579: guess_streamtype (tsid<0?ssid:tsid,-1),
1.1 oskar 580: f->u.ps.stream[ssid],f->u.ps.stream[0],TRUE);
581: } else {
582: r = FALSE;
583: }
584: } else {
585: command_toofew ();
586: r = FALSE;
587: }
588: }
589: } else {
590: command_toofew ();
591: r = FALSE;
592: }
593: } else {
594: command_toofew ();
595: r = FALSE;
596: }
597: frop = FALSE;
598: break;
599: case C_OTS:
600: fn = available_token ();
1.5 oskar 601: rn = com_number (fn,0,-1);
602: if (rn >= 0) {
603: fn = filerefer_name (rn);
604: }
1.1 oskar 605: if (fn != NULL) {
606: int sprg, tprg, tsid, ssid;
607: next_token ();
608: sprg = com_number (available_token (),0x0000L,0xFFFFL);
609: if ((!fileagain (fn))
610: && (sprg < 0)) {
1.8 oskar 611: f = openfile (fn,rn,ct_transport,TRUE,0,frop);
1.1 oskar 612: } else {
613: if (sprg >= 0) {
1.8 oskar 614: f = openfile (fn,rn,ct_transport,FALSE,0,frop);
1.1 oskar 615: if (splice_multipleprograms) {
616: next_token ();
1.19 oskar 617: tprg = com_number (available_token (),0x0001L,0xFFFFL);
1.1 oskar 618: } else {
619: tprg = 0;
620: }
621: if (tprg >= 0) {
622: next_token ();
623: ssid = com_number (available_token (),0x00,0xFF);
624: if (ssid >= 0) {
625: next_token ();
626: tsid = com_number (available_token (),0x00,0xFF);
627: if (tsid >= 0) {
628: next_token ();
629: } else {
630: tsid = -ssid;
631: }
632: /*
633: if (stream yet open somewhere) {
634: connect_streamprog (...);
635: f = NULL;
636: }
637: */
638: } else {
639: ssid = -1;
640: tsid = -1;
641: }
642: } else {
643: tprg = sprg;
644: ssid = -1;
645: tsid = -1;
646: }
1.19 oskar 647: if ((sprg == 0)
648: && (ssid < 0)) { /* if sprg=0, then tprg & ssid obligatory */
649: command_toofew ();
650: r = FALSE;
651: } else {
652: if (f != NULL) {
653: tsauto_descr *a;
654: a = malloc (sizeof (tsauto_descr));
655: if (a != NULL) {
656: a->next = f->u.ts.tsauto;
657: a->sprg = sprg;
658: a->tprg = tprg;
659: a->ssid = ssid;
660: a->tsid = tsid;
661: f->u.ts.tsauto = a;
662: }
1.1 oskar 663: }
664: }
665: } else {
666: command_toofew ();
667: r = FALSE;
668: }
669: }
670: } else {
671: command_toofew ();
672: r = FALSE;
673: }
674: frop = FALSE;
1.5 oskar 675: break;
676: case C_CLOS:
677: fn = available_token ();
678: rn = com_number (fn,0,-1);
679: if (rn >= 0) {
680: fn = filerefer_name (rn);
681: }
682: if (fn != NULL) {
683: next_token ();
684: f = input_filereferenced (rn,fn);
685: if (f != NULL) {
686: input_stopfile (f);
687: set_lastfile (fn);
688: } else {
689: warn (LWAR,"File not open",ECOM,1,4,0);
690: r = FALSE;
691: }
692: } else {
693: command_toofew ();
694: r = FALSE;
695: }
696: break;
697: case C_APPE:
698: fn = available_token ();
699: rn = com_number (fn,0,-1);
700: if (rn >= 0) {
701: fn = filerefer_name (rn);
702: }
703: if (fileagain (fn)) {
704: fn = lastfile;
705: }
706: if (fn != NULL) {
707: next_token ();
708: f = input_filereferenced (rn,fn);
709: if (f != NULL) {
710: fn = available_token ();
711: rn = com_number (fn,0,-1);
712: if (rn >= 0) {
713: fn = filerefer_name (rn);
714: }
715: if (fn != NULL) {
1.6 oskar 716: next_token ();
1.5 oskar 717: if (f->append_name != NULL) {
718: free (f->append_name);
719: }
720: if ((f->append_name = malloc (strlen (fn) + 1)) != NULL) {
1.8 oskar 721: int rept;
1.5 oskar 722: strcpy (f->append_name,fn);
723: f->append_filerefnum = rn;
1.6 oskar 724: filerefer_forget (rn);
1.8 oskar 725: rept = com_number (available_token (),0,-1);
1.5 oskar 726: if (rept >= 0) {
1.8 oskar 727: next_token ();
1.5 oskar 728: f->append_repeatitions = rept-1;
729: } else {
730: f->append_repeatitions = 0;
731: }
732: }
733: } else {
734: command_toofew ();
735: r = FALSE;
736: }
737: } else {
738: warn (LWAR,"File not open",ECOM,1,5,0);
739: r = FALSE;
740: }
741: } else {
742: command_toofew ();
743: r = FALSE;
744: }
745: break;
746: case C_FILE:
747: rn = com_number (available_token (),0,-1);
748: if (rn >= 0) {
749: next_token ();
750: fn = available_token ();
751: if (fn != NULL) {
752: filerefer_remind (rn,fn);
753: set_lastfile (fn);
1.14 oskar 754: next_token ();
1.5 oskar 755: } else {
756: command_toofew ();
757: r = FALSE;
758: }
759: } else {
760: command_toofew ();
761: r = FALSE;
762: }
1.1 oskar 763: break;
1.4 oskar 764: case C_CROP:
765: {
766: int tprg, tsid;
767: prog_descr *p;
768: stream_descr *s;
769: if (splice_multipleprograms) {
770: tprg = com_number (available_token (),0x0000L,0xFFFFL);
771: next_token ();
772: } else {
773: tprg = 0;
774: }
775: if (tprg >= 0) {
776: p = splice_getprog (tprg);
777: if (p != NULL) {
778: tsid = com_number (available_token (),0x00,0xFF);
779: if (tsid >= 0) {
780: next_token ();
781: s = get_streamprog (p,tsid);
782: if (s != NULL) {
783: remove_streamprog (s,p);
784: } else {
785: warn (LWAR,"Stream not found",ECOM,1,3,0);
786: r = FALSE;
787: }
788: } else {
789: splice_closeprog (p);
790: }
791: } else {
792: warn (LWAR,"Program not found",ECOM,1,2,0);
793: r = FALSE;
794: }
795: } else {
796: command_toofew ();
797: r = FALSE;
798: }
799: frop = FALSE;
800: }
801: break;
1.1 oskar 802: case C_VERB:
803: if ((verbose_level
804: = com_number (available_token (),0,LDEB)) >= 0) {
805: next_token ();
806: } else {
807: verbose_level = LWAR;
808: }
809: break;
810: case C_VERS:
1.30 oskar 811: fprintf (stderr, MPLEX_VERSION "\n");
1.1 oskar 812: if (first) {
813: force_quit = TRUE;
814: }
815: break;
816: case C_HELP:
817: command_help ();
818: if (first) {
1.4 oskar 819: r = FALSE;
1.1 oskar 820: }
821: break;
822: case C_QUIT:
823: force_quit = TRUE;
824: break;
825: case C_BUSY:
826: {
827: int busy;
828: busy = com_number (available_token (),0,1);
829: busy_work = (busy != 0);
830: if (busy >= 0) {
831: next_token ();
832: }
833: }
834: break;
835: case C_FROP:
836: frop = TRUE;
837: break;
1.2 oskar 838: case C_REPT:
1.8 oskar 839: fn = available_token ();
840: rn = com_number (fn,0,-1);
841: if (rn >= 0) {
842: fn = filerefer_name (rn);
843: }
844: if (fileagain (fn)) {
845: fn = lastfile;
846: }
847: if (fn != NULL) {
1.2 oskar 848: next_token ();
1.8 oskar 849: f = input_filereferenced (rn,fn);
850: if (f != NULL) {
851: int rept;
852: rept = com_number (available_token (),0,-1);
853: if (rept >= 0) {
854: if (rept != 1) {
855: if (S_ISREG (f->st_mode)) {
856: f->repeatitions = rept-1;
857: } else {
858: warn (LWAR,"Cannot repeat nonregular file",ECOM,1,6,0);
859: f->repeatitions = 0;
860: }
861: } else {
862: f->repeatitions = 0;
863: }
864: set_lastfile (fn);
1.14 oskar 865: next_token ();
1.8 oskar 866: } else {
867: command_toofew ();
868: r = FALSE;
869: }
870: } else {
871: warn (LWAR,"File not open",ECOM,1,7,0);
872: r = FALSE;
873: }
1.2 oskar 874: } else {
875: command_toofew ();
876: r = FALSE;
877: }
878: break;
1.1 oskar 879: case C_TIMD:
880: timed_io = TRUE;
881: break;
882: case C_FPSI:
883: {
884: int msec;
885: msec = com_number (available_token (),0,-1);
886: if (msec >= 0) {
887: splice_setpsifrequency (msec);
888: next_token ();
1.2 oskar 889: } else {
890: command_toofew ();
891: r = FALSE;
1.1 oskar 892: }
893: }
894: break;
1.16 oskar 895: case C_TRGI:
896: {
897: int msec;
898: msec = com_number (available_token (),0,-1);
899: if (msec >= 0) {
900: input_settriggertiming (msec);
901: next_token ();
902: } else {
903: command_toofew ();
904: r = FALSE;
905: }
906: }
907: break;
908: case C_TRGO:
909: {
910: int msec;
911: msec = com_number (available_token (),0,-1);
912: if (msec >= 0) {
913: output_settriggertiming (msec);
914: next_token ();
915: } else {
916: command_toofew ();
917: r = FALSE;
918: }
919: }
920: break;
1.1 oskar 921: case C_TSID:
1.18 oskar 922: {
1.1 oskar 923: int tsid;
924: tsid = com_number (available_token (),0x0000L,0xFFFFL);
925: if (tsid >= 0) {
926: splice_settransportstreamid (tsid);
927: next_token ();
1.3 oskar 928: } else {
929: command_toofew ();
930: r = FALSE;
1.1 oskar 931: }
932: }
1.16 oskar 933: break;
1.8 oskar 934: case C_TSSI:
935: fn = available_token ();
936: rn = com_number (fn,0,-1);
937: if (rn >= 0) {
938: fn = filerefer_name (rn);
939: }
940: if (fileagain (fn)) {
941: fn = lastfile;
942: }
943: if (fn != NULL) {
944: next_token ();
945: f = input_filereferenced (rn,fn);
946: if (f != NULL) {
1.10 oskar 947: if (f->content == ct_transport) {
948: int lower, upper;
1.17 oskar 949: lower = com_number (available_token (),0x0001,TS_PID_HIGHEST);
1.10 oskar 950: if (lower >= 0) {
1.8 oskar 951: next_token ();
1.10 oskar 952: upper = com_number (available_token (),lower,TS_PID_HIGHEST);
953: if (upper >= 0) {
1.17 oskar 954: splice_addsirange (f,lower,upper);
1.14 oskar 955: next_token ();
1.10 oskar 956: } else {
957: command_toofew ();
958: r = FALSE;
959: }
1.8 oskar 960: } else {
1.10 oskar 961: releasechain (tssi_descr,f->u.ts.tssi);
962: f->u.ts.tssi = NULL;
1.8 oskar 963: }
964: } else {
1.10 oskar 965: warn (LWAR,"File must be TS",ECOM,1,8,0);
966: r = FALSE;
1.8 oskar 967: }
968: } else {
1.10 oskar 969: warn (LWAR,"File not open",ECOM,1,9,0);
1.8 oskar 970: r = FALSE;
971: }
972: } else {
973: command_toofew ();
974: r = FALSE;
1.17 oskar 975: }
976: break;
977: case C_TSSP:
978: {
979: int tprg, tpid, ttyp;
980: tprg = com_number (available_token (),0x0000L,0xFFFFL);
981: if (tprg >= 0) {
982: next_token ();
983: tpid = com_number (available_token (),0x0001,TS_PID_HIGHEST);
984: if (tpid >= 0) {
985: next_token ();
986: ttyp = com_number (available_token (),0x00,0xFF);
987: if (ttyp >= 0) {
988: next_token ();
989: splice_createstump (tprg,tpid,ttyp);
990: } else {
991: releasechain (stump_descr,splice_getstumps (tprg,tpid));
992: }
993: } else {
994: releasechain (stump_descr,splice_getstumps (tprg,tpid));
995: }
996: } else {
997: command_toofew ();
998: r = FALSE;
999: }
1.13 oskar 1000: }
1001: break;
1.18 oskar 1002: case C_DSCR:
1003: {
1004: int tprg, dtag, dlen, dbyt, i;
1005: byte data[MAX_DESCR_LEN];
1006: if (splice_multipleprograms) {
1007: tprg = com_number (available_token (),0x0000L,0xFFFFL);
1008: next_token ();
1009: } else {
1010: tprg = 0;
1011: }
1012: if (tprg >= 0) {
1013: dtag = com_number (available_token (),0,NUMBER_DESCR-1);
1014: if (dtag >= 0) {
1015: next_token ();
1016: dlen = com_number (available_token (),0,MAX_DESCR_LEN);
1017: if (dlen >= 0) {
1018: i = 0;
1019: next_token ();
1020: while ((i < dlen)
1021: && ((dbyt = com_number (available_token (),0x00,0xFF))
1022: >= 0)) {
1023: data[i++] = dbyt;
1024: next_token ();
1025: }
1026: if (i == dlen) { /* <tprg> <dtag> <dlen> ... add/inhibit one */
1027: splice_modifytargetdescriptor (tprg,-1,-1,dtag,dlen,&data[0]);
1028: } else {
1029: command_toofew ();
1030: r = FALSE;
1031: }
1032: } else { /* <tprg> <dtag> del one */
1033: splice_modifytargetdescriptor (tprg,-1,-1,dtag,-1,NULL);
1034: }
1035: } else { /* <tprg> del all non-stream-specific */
1036: splice_modifytargetdescriptor (tprg,-1,-1,-1,-1,NULL);
1037: }
1038: } else {
1039: command_toofew ();
1040: r = FALSE;
1041: }
1042: }
1043: break;
1044: case C_DSCS:
1045: {
1046: int tprg, tsid, dtag, dlen, dbyt, i;
1047: byte data[MAX_DESCR_LEN];
1048: if (splice_multipleprograms) {
1049: tprg = com_number (available_token (),0x0000L,0xFFFFL);
1050: if (tprg >= 0) {
1051: next_token ();
1052: }
1053: } else {
1054: tprg = 0;
1055: }
1056: if (tprg >= 0) {
1057: tsid = com_number (available_token (),0x00,0xFF);
1058: if (tsid >= 0) {
1059: next_token ();
1060: dtag = com_number (available_token (),0,NUMBER_DESCR-1);
1061: if (dtag >= 0) {
1062: next_token ();
1063: dlen = com_number (available_token (),0,MAX_DESCR_LEN);
1064: if (dlen >= 0) {
1065: i = 0;
1066: next_token ();
1067: while ((i < dlen)
1068: && ((dbyt = com_number (available_token (),0x00,0xFF))
1069: >= 0)) {
1070: data[i++] = dbyt;
1071: next_token ();
1072: }
1073: if (i == dlen) { /* <tprg> <tsid> <dtag> <dlen> ... add/inh */
1074: splice_modifytargetdescriptor (tprg,tsid,-1,dtag,dlen,
1075: &data[0]);
1076: } else {
1077: command_toofew ();
1078: r = FALSE;
1079: }
1080: } else { /* <tprg> <tsid> <dtag> del one */
1081: splice_modifytargetdescriptor (tprg,tsid,-1,dtag,-1,NULL);
1082: }
1083: } else { /* <tprg> <tsid> del all for tsid */
1084: splice_modifytargetdescriptor (tprg,tsid,-1,-1,-1,NULL);
1085: }
1086: } else { /* <tprg> del all */
1087: splice_modifytargetdescriptor (tprg,-1,0,-1,-1,NULL);
1088: }
1089: } else {
1090: splice_modifytargetdescriptor (tprg,-1,0,-1,-1,NULL);
1091: }
1092: }
1093: break;
1094: case C_DSCP:
1095: {
1096: int tprg, tpid, dtag, dlen, dbyt, i;
1097: byte data[MAX_DESCR_LEN];
1098: tprg = com_number (available_token (),0x0000L,0xFFFFL);
1099: if (tprg >= 0) {
1100: next_token ();
1101: tpid = com_number (available_token (),0x0001,TS_PID_HIGHEST);
1102: if (tpid >= 0) {
1103: next_token ();
1104: dtag = com_number (available_token (),0,NUMBER_DESCR-1);
1105: if (dtag >= 0) {
1106: next_token ();
1107: dlen = com_number (available_token (),0,MAX_DESCR_LEN);
1108: if (dlen >= 0) {
1109: i = 0;
1110: next_token ();
1111: while ((i < dlen)
1112: && ((dbyt = com_number (available_token (),0x00,0xFF))
1113: >= 0)) {
1114: data[i++] = dbyt;
1115: next_token ();
1116: }
1117: if (i == dlen) { /* <tprg> <tpid> <dtag> <dlen> ... add/inh */
1118: splice_modifytargetdescriptor (tprg,-1,tpid,dtag,dlen,
1119: &data[0]);
1120: } else {
1121: command_toofew ();
1122: r = FALSE;
1123: }
1124: } else { /* <tprg> <tpid> <dtag> del one */
1125: splice_modifytargetdescriptor (tprg,-1,tpid,dtag,-1,NULL);
1126: }
1127: } else { /* <tprg> <tpid> del all for tpid */
1128: splice_modifytargetdescriptor (tprg,-1,tpid,-1,-1,NULL);
1129: }
1130: } else { /* <tprg> del all */
1131: splice_modifytargetdescriptor (tprg,-1,0,-1,-1,NULL);
1132: }
1133: } else {
1134: splice_modifytargetdescriptor (tprg,-1,0,-1,-1,NULL);
1135: }
1136: }
1137: break;
1.13 oskar 1138: case C_CONF:
1.14 oskar 1139: {
1140: int conf;
1.18 oskar 1141: conf = com_number (available_token (),0,2);
1.14 oskar 1142: if (conf >= 0) {
1.18 oskar 1143: splice_set_configuration (conf);
1.14 oskar 1144: next_token ();
1145: } else {
1146: command_toofew ();
1147: r = FALSE;
1148: }
1149: }
1.13 oskar 1150: break;
1151: case C_STAT:
1152: {
1153: int msec;
1154: msec = com_number (available_token (),0,-1);
1155: if (msec >= 0) {
1156: output_set_statistics (msec);
1157: next_token ();
1158: } else {
1159: command_toofew ();
1160: r = FALSE;
1161: }
1.8 oskar 1162: }
1163: break;
1.27 oskar 1164: case C_NETW:
1165: {
1166: int npid;
1167: npid = com_number (available_token (),1,TS_PID_HIGHEST);
1168: if (npid >= 0) {
1169: next_token ();
1170: }
1171: splice_setnetworkpid (npid);
1172: }
1173: break;
1.1 oskar 1174: case C_BSCR:
1175: accept_weird_scr = TRUE;
1.22 oskar 1176: break;
1177: case C_CPID:
1178: {
1179: int cpid;
1180: cpid = com_number (available_token (),0,1);
1181: conservative_pid_assignment = (cpid != 0);
1182: if (cpid >= 0) {
1183: next_token ();
1184: }
1185: }
1.1 oskar 1186: break;
1187: default:
1.14 oskar 1188: fprintf (stderr, "Unknown command: %s\n", t);
1.1 oskar 1189: if (first) {
1190: command_help ();
1191: } else {
1.14 oskar 1192: warn (LWAR,"Bad token",ECOM,1,1,*t);
1.1 oskar 1193: }
1194: r = FALSE;
1195: break;
1196: }
1197: t = available_token ();
1198: }
1199: return (r);
1200: }
1201:
1202: boolean command_init (int cargc,
1203: char **cargv)
1204: {
1205: verbose_level = LERR;
1206: argi = 1;
1207: argc = cargc;
1208: argv = cargv;
1209: combln = 0;
1210: lastfile = NULL;
1211: first = TRUE;
1212: if (!command ()) {
1213: return (FALSE);
1214: }
1215: first = FALSE;
1.4 oskar 1216: cmdf = STDIN_FILENO;
1.1 oskar 1217: return (cmdf >= 0);
1218: }
1219:
1.6 oskar 1220: /* Determine whether command input can be processed.
1221: * Set the poll-struct accordingly.
1222: * Return: TRUE, if command input is expected, FALSE otherwise.
1223: */
1.1 oskar 1224: boolean command_expected (unsigned int *nfds,
1225: struct pollfd *ufds)
1226: {
1227: if (cmdf >= 0) {
1228: ufds->fd = cmdf;
1229: ufds->events = POLLIN;
1230: *nfds += 1;
1231: }
1232: return (cmdf >= 0);
1233: }
1234:
1.6 oskar 1235: /* Read command input and process it.
1236: */
1.1 oskar 1237: void command_process (boolean readable)
1238: {
1239: int i;
1240: if (combln >= MAX_DATA_COMB-HIGHWATER_COM) {
1.14 oskar 1241: warn (LWAR,"Too long",ECOM,2,1,combln);
1.1 oskar 1242: moveleft (HIGHWATER_COM);
1243: }
1244: if (readable) {
1245: i = read (cmdf,&combuf[combln],MAX_DATA_COMB-combln);
1246: } else {
1247: i = 0;
1248: }
1.12 oskar 1249: if (i > 0) {
1.1 oskar 1250: combln += i;
1251: while (line_complete ()) {
1252: command ();
1253: moveleft (comlln+1);
1254: }
1255: }
1256: }
1257:
LinuxTV legacy CVS <linuxtv.org/cvs>