ref: f0983536cf684f309aa689a3a4b3b168f115bbec
parent: 5f51f5f57e775b2329f7fee5bdecf36604b4e20e
author: rrt <rrt>
date: Mon Jan 8 23:15:51 EST 2007
Add --play and --record
--- a/src/sox.c
+++ b/src/sox.c
@@ -86,7 +86,7 @@
} *file_info_t;
/* local forward declarations */
-static bool doopts(file_info_t fo, int, char **);
+static bool doopts(file_info_t fo, int, char **, bool *play, bool *record);
static void usage(char const *) NORET;
static void usage_effect(char *) NORET;
static void process(void);
@@ -103,7 +103,7 @@
static void stop_effects(void);
#define MAX_INPUT_FILES 32
-#define MAX_FILES MAX_INPUT_FILES + 1
+#define MAX_FILES MAX_INPUT_FILES + 2 /* 1 output file plus record input */
/* Arrays tracking input and output files */
static file_info_t file_opts[MAX_FILES];
@@ -205,18 +205,57 @@
user_abort = 1;
}
+static file_info_t make_file_info(void)
+{
+ file_info_t fo = xcalloc(sizeof(*fo), 1);
+
+ fo->signal.size = -1;
+ fo->signal.encoding = ST_ENCODING_UNKNOWN;
+ fo->signal.channels = 0;
+ fo->signal.swap_bytes = ST_SWAP_DEFAULT;
+ fo->signal.compression = HUGE_VAL;
+ fo->volume = HUGE_VAL;
+ fo->volume_clips = 0;
+
+ return fo;
+}
+
+static void set_device(file_info_t fo)
+{
+#if defined(HAVE_ALSA)
+ fo->filetype = "alsa";
+ fo->filename = xstrdup("default");
+#elif defined(HAVE_OSS)
+ fo->filetype = "ossdsp";
+ fo->filename = xstrdup("/dev/dsp");
+#elif defined (HAVE_SUN_AUDIO)
+ fo->filetype = "sunau";
+ fo->filename = xstrdup("/dev/audio");
+#endif
+}
+
int main(int argc, char **argv)
{
size_t i;
+ bool play = false, record = false;
myname = argv[0];
atexit(cleanup);
st_output_message_handler = sox_output_message;
+ i = strlen(myname);
+ if (i >= sizeof("play") - 1 &&
+ strcmp(myname + i - (sizeof("play") - 1), "play") == 0) {
+ play = true;
+ } else if (i >= sizeof("rec") - 1 &&
+ strcmp(myname + i - (sizeof("record") - 1), "record") == 0) {
+ record = true;
+ }
+
/* Loop over arguments and filenames, stop when an effect name is
* found. */
while (optind < argc && !is_effect_name(argv[optind])) {
- file_info_t fo;
+ file_info_t fo = make_file_info();
struct file_info fo_none;
if (file_count >= MAX_FILES) {
@@ -224,17 +263,9 @@
exit(1);
}
- fo = xcalloc(sizeof(*fo), 1);
- fo->signal.size = -1;
- fo->signal.encoding = ST_ENCODING_UNKNOWN;
- fo->signal.channels = 0;
- fo->signal.swap_bytes = ST_SWAP_DEFAULT;
- fo->signal.compression = HUGE_VAL;
- fo->volume = HUGE_VAL;
- fo->volume_clips = 0;
fo_none = *fo;
- if (doopts(fo, argc, argv) == true) { /* is null file? */
+ if (doopts(fo, argc, argv, &play, &record)) { /* is null file? */
if (fo->filetype != NULL && strcmp(fo->filetype, "null") != 0)
st_warn("Ignoring \"-t %s\".", fo->filetype);
fo->filetype = "null";
@@ -251,6 +282,35 @@
file_opts[file_count++] = fo;
}
+ if (record) {
+ file_info_t fo = make_file_info();
+ st_size_t i;
+
+ if (file_count >= MAX_FILES) {
+ st_fail("Too many filenames; maximum is %d input files and 1 output file", MAX_INPUT_FILES);
+ exit(1);
+ }
+ file_count++;
+
+ for (i = 0; i < file_count; i++)
+ file_opts[i + 1] = file_opts[i];
+
+ set_device(fo);
+ file_opts[0] = fo;
+ }
+
+ if (play) {
+ file_info_t fo = make_file_info();
+
+ if (file_count >= MAX_FILES) {
+ st_fail("Too many filenames; maximum is %d input files and 1 output file", MAX_INPUT_FILES);
+ exit(1);
+ }
+
+ set_device(fo);
+ file_opts[file_count++] = fo;
+ }
+
/* Make sure we got at least the required # of input filenames */
input_count = file_count ? file_count - 1 : 0;
if (input_count < (combine_method == SOX_CONCAT ? 1 : 2))
@@ -361,6 +421,8 @@
{"endian" , required_argument, NULL, 0},
{"interactive" , no_argument, NULL, 0},
{"help-effect" , required_argument, NULL, 0},
+ {"play" , no_argument, NULL, 0},
+ {"record" , no_argument, NULL, 0},
{"version" , no_argument, NULL, 0},
{"channels" , required_argument, NULL, 'c'},
@@ -379,17 +441,15 @@
{NULL, 0, NULL, 0}
};
-static bool doopts(file_info_t fo, int argc, char **argv)
+static bool doopts(file_info_t fo, int argc, char **argv, bool *play, bool *record)
{
- while (true) {
+ bool isnull = false;
+ int option_index, c;
+
+ while ((c = getopt_long(argc, argv, getoptstr, long_options, &option_index)) != -1) {
int i; /* Needed since scanf %u allows negative numbers :( */
char dummy; /* To check for extraneous chars in optarg. */
- int option_index;
- int c = getopt_long(argc, argv, getoptstr, long_options, &option_index);
- if (c == -1) /* No more options. */
- return false; /* Is not null file. */
-
switch (c) {
case 0: /* Long options with no short equivalent. */
switch (option_index) {
@@ -419,6 +479,14 @@
break;
case 5:
+ *play = true;
+ break;
+
+ case 6:
+ *record = true;
+ break;
+
+ case 7:
printf("%s: v%s\n", myname, st_version());
exit(0);
break;
@@ -438,7 +506,8 @@
break;
case 'e': case 'n':
- return true; /* Is null file. */
+ isnull = true; /* Is null file. */
+ break;
case 'o':
globalinfo.octave_plot_effect = true;
@@ -445,7 +514,7 @@
break;
case 'h': case '?':
- usage((char *) 0); /* No return */
+ usage(NULL); /* No return */
break;
case 't':
@@ -549,16 +618,17 @@
break;
}
}
+
+ return isnull;
}
static int compare_input(ft_t ft1, ft_t ft2)
{
- if (ft1->signal.rate != ft2->signal.rate)
- return ST_EOF;
- if (ft1->signal.channels != ft2->signal.channels)
- return ST_EOF;
+ if ((ft1->signal.rate == ft2->signal.rate) &&
+ (ft1->signal.channels == ft2->signal.channels))
+ return ST_SUCCESS;
- return ST_SUCCESS;
+ return ST_EOF;
}
/*
@@ -1556,7 +1626,9 @@
"-m, --mix mix multiple input files (instead of concatenating)\n"
"-M, --merge merge multiple input files (instead of concatenating)\n"
"-o generate Octave commands to plot response of filter effect\n"
+ "--play output to the default sound device; set if SoX run as `play'\n"
"-q run in quiet mode; opposite of -S\n"
+ "--record input from the default sound device; set if SoX run as `rec'\n"
"-S display status while processing audio data\n"
"--version display version number of SoX and exit\n"
"-V[level] increment or set verbosity level (default 2); levels are:\n"