[zaptel-commits] tzafrir: trunk r2454 - /trunk/ztmonitor.c

zaptel-commits at lists.digium.com zaptel-commits at lists.digium.com
Wed Apr 25 10:23:53 MST 2007


Author: tzafrir
Date: Wed Apr 25 12:23:53 2007
New Revision: 2454

URL: http://svn.digium.com/view/zaptel?view=rev&rev=2454
Log:
fix style in ztmonitor's code:
* Use getopts for parsing the options.
* Fix incorrect test for "no output stream".
* Give names to some numbered file descriptors.
* A separate usage message function. That is being used.
* The sox message is back, and gives a working command.
* clean-ups.

Modified:
    trunk/ztmonitor.c

Modified: trunk/ztmonitor.c
URL: http://svn.digium.com/view/zaptel/trunk/ztmonitor.c?view=diff&rev=2454&r1=2453&r2=2454
==============================================================================
--- trunk/ztmonitor.c (original)
+++ trunk/ztmonitor.c Wed Apr 25 12:23:53 2007
@@ -51,10 +51,20 @@
 
 #define FRAG_SIZE 8
 
+#define PROG "ztmonitor"
+
 /* Put the ofh (output file handles) outside
  * the main loop in case we ever add a signal
  * handler.
  */
+
+enum ofh_type {
+	ofh_def = 0,
+	ofh_tx,
+	ofh_pre,
+	ofh_pretx,
+	ofh_last
+};
 static FILE*  ofh[4] = {0, 0, 0, 0};
 
 static int stereo = 0;
@@ -253,128 +263,138 @@
 	}
 }
 
+/** Print usage message */
+static void usage()
+{
+	fprintf(stderr, 
+		"" PROG ": monitor a zaptel channel.\n"
+		"Usage:\n"
+		"      " PROG " [options] <channel num>\n"
+		"Options:\n"
+		"        -v: Visual mode.  Implies -m.\n"
+		"        -vv: Visual/Verbose mode.  Implies -m.\n"
+		"        -m: Separate rx/tx streams.\n"
+		"        -o: Output audio via OSS.  Note: Only 'normal'\n"
+		"            combined rx/tx streams are output via OSS.\n"
+		"        -p: Get a pre-echocanceled stream.\n"
+		"        -f FILE: Save combined rx/tx stream to FILE.  \n"
+		"                 Cannot be used with -m.\n"
+		"        -r FILE: Save rx stream to FILE.  Implies -m.\n"
+		"        -t FILE: Save tx stream to FILE.  Implies -m.\n"
+		"        -F FILE: Save combined pre-echocanceled rx/tx\n"
+		"                 stream to FILE.  Cannot be used with -m.\n"  
+		"                 Implies -p.\n"
+		"        -R FILE: Save pre-echocanceled rx stream to FILE.  \n"
+		"                 Implies -m and -p.\n"
+		"        -T FILE: Save pre-echocanceled tx stream to FILE.  \n"
+		"                 Implies -m and -p.\n"
+		""
+		"At least one of -v, -o, -f -F, -r, -R, -t, -T must be\n" 
+		"used to set the output.\n"
+		"Examples:\n"
+		"Save a stream to a file:\n"
+		"        " PROG " 1 -f stream.raw\n"
+		"Visualize an rx/tx stream and save them to separate files:\n"
+		"        " PROG " 1 -v -r streamrx.raw -t streamtx.raw\n"
+		"Play a combined rx/tx stream via OSS and save it to a file\n"
+		"        " PROG " 1 -o -f stream.raw\n"
+		"Play a combined rx/tx stream via OSS and save them to separate files\n"
+		"        " PROG " 1 -m -o -r streamrx.raw -t streamtx.raw\n"
+		"Save a combined normal rx/tx stream and a combined 'preecho' rx/tx stream to files\n"
+		"        " PROG " 1 -m -p -f stream.raw -F streampreecho.raw\n"
+		"Save a normal rx/tx stream and a 'preecho' rx/tx stream to separate files\n"
+		"        " PROG " 1 -m -p -r streamrx.raw -t streamtx.raw -R streampreechorx.raw -T streampreechotx.raw\n"
+		"");
+}
+
+
+
 int main(int argc, char *argv[])
 {
 	int afd = -1;
 	int pfd[4] = {-1, -1, -1, -1};
 	short buf[8192];
 	short buf2[16384];
-	char  output_file[255];
+	char *output_file = NULL;
 	int res, res2;
 	int visual = 0;
 	int multichannel = 0;
 	int ossoutput = 0;
 	int preecho = 0;
-	int savefile = 0;
-	int x, i;
+	//int savefile = 0; replaced with: (output_file == NULL)
+	int x;
 	struct zt_confinfo zc;
-
-	if ((argc < 2) || (atoi(argv[1]) < 1)) {
-		fprintf(stderr, "Usage: ztmonitor <channel num> [-v[v]] [-m] [-o] [-p] [-f FILE | -r FILE1 -t FILE2] [-F FILE | -R FILE1 -T FILE2]\n");
-		fprintf(stderr, "Options:\n");
-		fprintf(stderr, "        -v: Visual mode.  Implies -m.\n");
-		fprintf(stderr, "        -vv: Visual/Verbose mode.  Implies -m.\n");
-		fprintf(stderr, "        -m: Separate rx/tx streams.\n");
-		fprintf(stderr, "        -o: Output audio via OSS.  Note: Only 'normal' combined rx/tx streams are output via OSS.\n");
-		fprintf(stderr, "        -p: Get a pre-echocanceled stream.\n");
-		fprintf(stderr, "        -f FILE: Save combined rx/tx stream to FILE.  Cannot be used with -m.\n");
-		fprintf(stderr, "        -r FILE: Save rx stream to FILE.  Implies -m.\n");
-		fprintf(stderr, "        -t FILE: Save tx stream to FILE.  Implies -m.\n");
-		fprintf(stderr, "        -F FILE: Save combined pre-echocanceled rx/tx stream to FILE.  Cannot be used with -m.  Implies -p.\n");
-		fprintf(stderr, "        -R FILE: Save pre-echocanceled rx stream to FILE.  Implies -m and -p.\n");
-		fprintf(stderr, "        -T FILE: Save pre-echocanceled tx stream to FILE.  Implies -m and -p.\n");
-		fprintf(stderr, "Examples:\n");
-		fprintf(stderr, "Save a stream to a file\n");
-		fprintf(stderr, "        ztmonitor 1 -f stream.raw\n");
-		fprintf(stderr, "Visualize an rx/tx stream and save them to separate files.\n");
-		fprintf(stderr, "        ztmonitor 1 -v -r streamrx.raw -t streamtx.raw\n");
-		fprintf(stderr, "Play a combined rx/tx stream via OSS and save it to a file\n");
-		fprintf(stderr, "        ztmonitor 1 -o -f stream.raw\n");
-		fprintf(stderr, "Play a combined rx/tx stream via OSS and save them to separate files\n");
-		fprintf(stderr, "        ztmonitor 1 -m -o -r streamrx.raw -t streamtx.raw\n");
-		fprintf(stderr, "Save a combined normal rx/tx stream and a combined 'preecho' rx/tx stream to files\n");
-		fprintf(stderr, "        ztmonitor 1 -m -p -f stream.raw -F streampreecho.raw\n");
-		fprintf(stderr, "Save a normal rx/tx stream and a 'preecho' rx/tx stream to separate files\n");
-		fprintf(stderr, "        ztmonitor 1 -m -p -r streamrx.raw -t streamtx.raw -R streampreechorx.raw -T streampreechotx.raw\n");
+	int opt;
+	int opt_visual = 0;
+	enum ofh_type ofh_type = ofh_def;
+	int chan_num = -1;
+
+	while((opt = getopt(argc, argv, "hvmopf:r:t:F:R:T:")) != -1) {
+		switch(opt) {
+			case 'h': usage(); exit(0); break;
+			case '?': usage(); exit(1); break;
+			case 'v': opt_visual++; break;
+			case 'm': multichannel=1; break;
+			case 'o': ossoutput=1; break;
+			case 'p': preecho=1; break;
+			case 'f': output_file = optarg; break;
+			case 'r': output_file = optarg; multichannel = 1; break;
+			case 't': output_file = optarg; multichannel = 1; ofh_type = ofh_tx; break;
+			case 'F': output_file = optarg; ofh_type = ofh_pre; preecho = 1; break;
+			case 'R': output_file = optarg; multichannel = 1; ofh_type = ofh_pre; preecho = 1; break;
+			case 'T': output_file = optarg; multichannel = 1; ofh_type = ofh_pretx; preecho = 1; break;
+		}
+	}
+	/* XXX: have a single "verbose" variable? or separate those 
+	 * two options? */
+	if (opt_visual >= 1)
+		visual = 1;
+	
+	if (opt_visual >= 2)
+		verbose = 1;
+	
+	if (output_file && ((ofh[ofh_type] = fopen(output_file, "w"))<0)) {
+		fprintf(stderr, PROG ": Could not open %s for writing: %s\n", 
+				output_file, strerror(errno));
 		exit(1);
 	}
-	for (i = 2; i < argc; ++i) {
-		if (!strcmp(argv[i], "-v")) {
-			if (visual)
-				verbose = 1;
-		        visual = 1;
-			multichannel = 1;
-		} else if (!strcmp(argv[i], "-vv")) {
-			visual = 1;
-			verbose = 1;
-			multichannel = 1;
-		} else if ((!strcmp(argv[i], "-f") || !strcmp(argv[i], "-r") || !strcmp(argv[i], "-t")
-				|| !strcmp(argv[i], "-F") || !strcmp(argv[i], "-R") || !strcmp(argv[i], "-T"))
-				&& (i+1) < argc) {
-			/* Set which file descriptor to use */
-			if (!strcmp(argv[i], "-f")) {
-				savefile = 1;
-				x = 0;
-			} else if (!strcmp(argv[i], "-r")) {
-				savefile = 1;
-				multichannel = 1;
-				x = 0;
-			} else if (!strcmp(argv[i], "-t")) {
-				savefile = 1;
-				multichannel = 1;
-				x = 1;
-			} else if (!strcmp(argv[i], "-F")) {
-				savefile = 1;
-				preecho = 1;
-				x = 2;
-			} else if (!strcmp(argv[i], "-R")) {
-				savefile = 1;
-				multichannel = 1;
-				preecho = 1;
-				x = 2;
-			} else if (!strcmp(argv[i], "-T")) {
-				savefile = 1;
-				multichannel = 1;
-				preecho = 1;
-				x = 3;
-			} else
-				x = 0;
-
-			++i; /* we care about the file name */
-			if (strlen(argv[i]) < 255 ) {
-				strcpy(output_file, argv[i]);
-				fprintf(stderr, "Output to %s\n", output_file);
-				if ((ofh[x] = fopen(output_file, "w"))<0) {
-					fprintf(stderr, "Could not open %s for writing: %s\n", output_file, strerror(errno));
-					exit(1);
-				}
-				fprintf(stderr, "Run e.g., 'sox -r 8000 -s -w -c 1 %s file.wav' to convert.\n", output_file);
-			} else {
-				fprintf(stderr, "File Name %s too long\n",argv[i+1]);
-			}
-		} else if (!strcmp(argv[i], "-m")) {
-			multichannel = 1;
-		} else if (!strcmp(argv[i], "-o")) {
-			ossoutput = 1;
-		} else if (!strcmp(argv[i], "-p")) {
-			preecho = 1;
-		}
+	if (output_file)
+		printf("Started recording. To stop: cress ctrl-C. "
+			"Recording a raw slinear file, to get a wav file:\n"
+			"  sox -r 8000 -s -w -c %d %s %s.wav\n", 
+			(multichannel)? 2:1, output_file, output_file);
+	
+	/* XXX: if POSIXLY_CORRECT is set, getopt will stop parsing at the 
+	 * first non-option argument. In the case of ztmonitor, the 
+	 * first argument used to be a non-option (the channel), hence
+	 * we rely on a posix-incompatibility.
+	 * Workaround: in the presence of POSIXLY_CORRECT, use:
+	 * ztmonitor [options] <CHAN_NUM>
+	 */
+	
+	if (argv[optind])
+		chan_num =atoi(argv[optind]); 
+	if (! chan_num < 1) {
+		fprintf(stderr,"Error: missing channel number\n");
+		usage();
+		exit(1);
 	}
 
 	if (ossoutput) {
 		if (multichannel) {
-			printf("Multi-channel audio is enabled.  OSS output will be disabled.\n");
+			fprintf(stderr, "Multi-channel audio is enabled.  OSS output will be disabled.\n");
 			ossoutput = 0;
 		} else {
 			/* Open audio */
 			if ((afd = audio_open()) < 0) {
-				printf("Cannot open audio ...\n");
+				fprintf(stderr, "Cannot open audio ...\n");
 				ossoutput = 0;
 			}
 		}
 	}
-	if (!ossoutput && !multichannel && !savefile) {
-		fprintf(stderr, "Nothing to do with the stream(s) ...\n");
+	if (!ossoutput || !multichannel || (output_file != NULL)) {
+		fprintf(stderr, "No output defined. Aborting.\n");
+		usage();
 		exit(1);
 	}
 
@@ -393,7 +413,7 @@
 	if (multichannel) {
 		memset(&zc, 0, sizeof(zc));
 		zc.chan = 0;
-		zc.confno = atoi(argv[1]);
+		zc.confno = chan_num;
 		/* Two pseudo's, one for tx, one for rx */
 		zc.confmode = ZT_CONF_MONITORTX;
 		if (ioctl(pfd[0], ZT_SETCONF, &zc) < 0) {
@@ -402,7 +422,7 @@
 		}
 		memset(&zc, 0, sizeof(zc));
 		zc.chan = 0;
-		zc.confno = atoi(argv[1]);
+		zc.confno = chan_num;
 		zc.confmode = ZT_CONF_MONITOR;
 		if (ioctl(pfd[1], ZT_SETCONF, &zc) < 0) {
 			fprintf(stderr, "Unable to monitor: %s\n", strerror(errno));
@@ -411,7 +431,7 @@
 		if (preecho) {
 			memset(&zc, 0, sizeof(zc));
 			zc.chan = 0;
-			zc.confno = atoi(argv[1]);
+			zc.confno = chan_num;
 			/* Two pseudo's, one for tx, one for rx */
 			zc.confmode = ZT_CONF_MONITOR_TX_PREECHO;
 			if (ioctl(pfd[2], ZT_SETCONF, &zc) < 0) {
@@ -420,7 +440,7 @@
 			}
 			memset(&zc, 0, sizeof(zc));
 			zc.chan = 0;
-			zc.confno = atoi(argv[1]);
+			zc.confno = chan_num;
 			zc.confmode = ZT_CONF_MONITOR_RX_PREECHO;
 			if (ioctl(pfd[3], ZT_SETCONF, &zc) < 0) {
 				fprintf(stderr, "Unable to monitor: %s\n", strerror(errno));
@@ -430,7 +450,7 @@
 	} else {
 		memset(&zc, 0, sizeof(zc));
 		zc.chan = 0;
-		zc.confno = atoi(argv[1]);
+		zc.confno = chan_num;
 		zc.confmode = ZT_CONF_MONITORBOTH;
 		if (ioctl(pfd[0], ZT_SETCONF, &zc) < 0) {
 			fprintf(stderr, "Unable to monitor: %s\n", strerror(errno));
@@ -439,7 +459,7 @@
 		if (preecho) {
 			memset(&zc, 0, sizeof(zc));
 			zc.chan = 0;
-			zc.confno = atoi(argv[1]);
+			zc.confno = chan_num;
 			zc.confmode = ZT_CONF_MONITORBOTH_PREECHO;
 			if (ioctl(pfd[2], ZT_SETCONF, &zc) < 0) {
 				fprintf(stderr, "Unable to monitor: %s\n", strerror(errno));
@@ -459,15 +479,15 @@
 		res = read(pfd[0], buf, sizeof(buf));
 		if (res < 1)
 			break;
-		if (ofh[0])
-			fwrite(buf, 1, res, ofh[0]);
+		if (ofh[ofh_def])
+			fwrite(buf, 1, res, ofh[ofh_def]);
 
 		if (multichannel) {
 			res2 = read(pfd[1], buf2, res);
 			if (res2 < 1)
 				break;
-			if (ofh[1])
-				fwrite(buf2, 1, res2, ofh[1]);
+			if (ofh[ofh_tx])
+				fwrite(buf2, 1, res2, ofh[ofh_tx]);
 
 			if (visual) {
 				if (res == res2)
@@ -481,15 +501,15 @@
 			res = read(pfd[2], buf, sizeof(buf));
 			if (res < 1)
 				break;
-			if (ofh[2])
-				fwrite(buf, 1, res, ofh[2]);
+			if (ofh[ofh_pre])
+				fwrite(buf, 1, res, ofh[ofh_pre]);
 
 			if (multichannel) {
 				res2 = read(pfd[3], buf2, res);
 				if (res2 < 1)
 					break;
-				if (ofh[3])
-					fwrite(buf2, 1, res, ofh[3]);
+				if (ofh[ofh_pretx])
+					fwrite(buf2, 1, res, ofh[ofh_pretx]);
 
 				/* XXX How are we going to visualize the preecho set of streams?
 				if (visual) {
@@ -510,9 +530,9 @@
 				write(afd, buf, res);
 		}
 	}
-	if (ofh[0]) fclose(ofh[0]);
-	if (ofh[1]) fclose(ofh[1]);
-	if (ofh[2]) fclose(ofh[2]);
-	if (ofh[3]) fclose(ofh[3]);
+
+	for (x=ofh_def; x < ofh_last; x++) 
+		if (ofh[x]) 
+			fclose(ofh[x]);
 	exit(0);
 }



More information about the zaptel-commits mailing list