diff options
Diffstat (limited to 'ztmonitor.c')
-rw-r--r-- | ztmonitor.c | 246 |
1 files changed, 198 insertions, 48 deletions
diff --git a/ztmonitor.c b/ztmonitor.c index 6098b66..07b7755 100644 --- a/ztmonitor.c +++ b/ztmonitor.c @@ -51,11 +51,11 @@ #define FRAG_SIZE 8 -/* Put the ofh (output file handle) outside +/* Put the ofh (output file handles) outside * the main loop in case we ever add a signal - * hanlder. + * handler. */ -static FILE* ofh = 0; +static FILE* ofh[4] = {0, 0, 0, 0}; static int stereo = 0; static int verbose = 0; @@ -255,62 +255,148 @@ void visualize(short *tx, short *rx, int cnt) int main(int argc, char *argv[]) { - int afd = -1, pfd, pfd2 = -1; + int afd = -1; + int pfd[4] = {-1, -1, -1, -1}; short buf[8192]; short buf2[16384]; char output_file[255]; int res, res2; int visual = 0; - int x,i; + int multichannel = 0; + int ossoutput = 0; + int preecho = 0; + int savefile = 0; + int x, i; struct zt_confinfo zc; if ((argc < 2) || (atoi(argv[1]) < 1)) { - fprintf(stderr, "Usage: ztmonitor <channel num> [-v[v]] [-f FILE]\n"); + 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"); exit(1); } for (i = 2; i < argc; ++i) { if (!strcmp(argv[i], "-v")) { - if (visual) - verbose = 1; + if (visual) + verbose = 1; visual = 1; + multichannel = 1; } else if (!strcmp(argv[i], "-vv")) { visual = 1; verbose = 1; - } else if (!strcmp(argv[i], "-f") && (i+1) < argc) { - ++i; /*we care about hte file name */ + 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 = fopen(output_file, "w"))<0) { + if ((ofh[x] = fopen(output_file, "w"))<0) { fprintf(stderr, "Could not open %s for writing: %s\n", output_file, strerror(errno)); - exit(0); + exit(1); } - fprintf(stderr, "Run e.g., 'sox -r 8000 -s -w -c 1 file.raw file.wav' to convert.\n"); + 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 (!visual) { - /* Open audio */ - if ((afd = audio_open()) < 0) { - printf("Cannot open audio ...\n"); - if (!ofh) exit(0); + + if (ossoutput) { + if (multichannel) { + printf("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"); + ossoutput = 0; + } } } + if (!ossoutput && !multichannel && !savefile) { + fprintf(stderr, "Nothing to do with the stream(s) ...\n"); + exit(1); + } + /* Open Pseudo device */ - if ((pfd = pseudo_open()) < 0) + if ((pfd[0] = pseudo_open()) < 0) exit(1); - if (visual && ((pfd2 = pseudo_open()) < 0)) + if (multichannel && ((pfd[1] = pseudo_open()) < 0)) exit(1); + if (preecho) { + if ((pfd[2] = pseudo_open()) < 0) + exit(1); + if (multichannel && ((pfd[3] = pseudo_open()) < 0)) + exit(1); + } /* Conference them */ - memset(&zc, 0, sizeof(zc)); - zc.chan = 0; - zc.confno = atoi(argv[1]); - if (visual) { + if (multichannel) { + memset(&zc, 0, sizeof(zc)); + zc.chan = 0; + zc.confno = atoi(argv[1]); /* Two pseudo's, one for tx, one for rx */ zc.confmode = ZT_CONF_MONITORTX; - if (ioctl(pfd, ZT_SETCONF, &zc) < 0) { + if (ioctl(pfd[0], ZT_SETCONF, &zc) < 0) { fprintf(stderr, "Unable to monitor: %s\n", strerror(errno)); exit(1); } @@ -318,16 +404,48 @@ int main(int argc, char *argv[]) zc.chan = 0; zc.confno = atoi(argv[1]); zc.confmode = ZT_CONF_MONITOR; - if (ioctl(pfd2, ZT_SETCONF, &zc) < 0) { + if (ioctl(pfd[1], ZT_SETCONF, &zc) < 0) { fprintf(stderr, "Unable to monitor: %s\n", strerror(errno)); exit(1); } + if (preecho) { + memset(&zc, 0, sizeof(zc)); + zc.chan = 0; + zc.confno = atoi(argv[1]); + /* Two pseudo's, one for tx, one for rx */ + zc.confmode = ZT_CONF_MONITOR_TX_PREECHO; + if (ioctl(pfd[2], ZT_SETCONF, &zc) < 0) { + fprintf(stderr, "Unable to monitor: %s\n", strerror(errno)); + exit(1); + } + memset(&zc, 0, sizeof(zc)); + zc.chan = 0; + zc.confno = atoi(argv[1]); + zc.confmode = ZT_CONF_MONITOR_RX_PREECHO; + if (ioctl(pfd[3], ZT_SETCONF, &zc) < 0) { + fprintf(stderr, "Unable to monitor: %s\n", strerror(errno)); + exit(1); + } + } } else { + memset(&zc, 0, sizeof(zc)); + zc.chan = 0; + zc.confno = atoi(argv[1]); zc.confmode = ZT_CONF_MONITORBOTH; - if (ioctl(pfd, ZT_SETCONF, &zc) < 0) { + if (ioctl(pfd[0], ZT_SETCONF, &zc) < 0) { fprintf(stderr, "Unable to monitor: %s\n", strerror(errno)); exit(1); } + if (preecho) { + memset(&zc, 0, sizeof(zc)); + zc.chan = 0; + zc.confno = atoi(argv[1]); + zc.confmode = ZT_CONF_MONITORBOTH_PREECHO; + if (ioctl(pfd[2], ZT_SETCONF, &zc) < 0) { + fprintf(stderr, "Unable to monitor: %s\n", strerror(errno)); + exit(1); + } + } } if (visual) { printf("\nVisual Audio Levels.\n"); @@ -338,31 +456,63 @@ int main(int argc, char *argv[]) } /* Now, copy from pseudo to audio */ for (;;) { - res = read(pfd, buf, sizeof(buf)); - if (res < 1) + res = read(pfd[0], buf, sizeof(buf)); + if (res < 1) break; - if (visual) { - res2 = read(pfd2, buf2, res); - if (res2 < 1) + if (ofh[0]) + fwrite(buf, 1, res, ofh[0]); + + if (multichannel) { + res2 = read(pfd[1], buf2, res); + if (res2 < 1) break; - if (res == res2) - visualize((short *)buf, (short *)buf2, res/2); - else - printf("Huh? res = %d, res2 = %d?\n", res, res2); - - } else { - if (ofh) - fwrite(buf, 1, res, ofh); - if (afd) { - if (stereo) { - for (x=0;x<res;x++) - buf2[x<<1] = buf2[(x<<1) + 1] = buf[x]; - write(afd, buf2, res << 1); - } else - write(afd, buf, res); + if (ofh[1]) + fwrite(buf2, 1, res2, ofh[1]); + + if (visual) { + if (res == res2) + visualize((short *)buf, (short *)buf2, res/2); + else + printf("Huh? res = %d, res2 = %d?\n", res, res2); } } + + if (preecho) { + res = read(pfd[2], buf, sizeof(buf)); + if (res < 1) + break; + if (ofh[2]) + fwrite(buf, 1, res, ofh[2]); + + if (multichannel) { + res2 = read(pfd[3], buf2, res); + if (res2 < 1) + break; + if (ofh[3]) + fwrite(buf2, 1, res, ofh[3]); + + /* XXX How are we going to visualize the preecho set of streams? + if (visual) { + if (res == res2) + visualize((short *)buf, (short *)buf2, res/2); + else + printf("Huh? res = %d, res2 = %d?\n", res, res2); + } */ + } + } + + if (ossoutput && afd) { + if (stereo) { + for (x=0;x<res;x++) + buf2[x<<1] = buf2[(x<<1) + 1] = buf[x]; + write(afd, buf2, res << 1); + } else + write(afd, buf, res); + } } - if (ofh) fclose(ofh); /*Never Reached */ + if (ofh[0]) fclose(ofh[0]); + if (ofh[1]) fclose(ofh[1]); + if (ofh[2]) fclose(ofh[2]); + if (ofh[3]) fclose(ofh[3]); exit(0); } |