ref: a4f3a22ccee9bcba30327351e06da900d4b013c9
parent: ccc58a54fc18e88f6ed1765286d2b9480c71b002
author: rrt <rrt>
date: Sat Nov 11 19:10:27 EST 2006
Make start_effects take a return value of ST_EOF from a start method as a signal to abort effects processing: don't run flow or drain in this case. This seems natural and prevents a segfault in rabbit (and possibly other effects) if the start method fails.
--- a/src/sox.c
+++ b/src/sox.c
@@ -103,7 +103,7 @@
static st_sample_t volumechange(st_sample_t *buf, st_ssize_t ct, double vol);
static void parse_effects(int argc, char **argv);
static void check_effects(void);
-static void start_effects(void);
+static int start_effects(void);
static void reserve_effect_buf(void);
static int flow_effect_out(void);
static int flow_effect(int);
@@ -147,7 +147,7 @@
*
* If one was to support effects for quad-channel files, there would
* need to be an effect table for each channel to handle effects
- * that done st ST_EFF_MCHAN.
+ * that don't set ST_EFF_MCHAN.
*/
static struct st_effect efftab[MAX_EFF]; /* left/mono channel effects */
@@ -596,7 +596,7 @@
check_effects();
/* Start all effects */
- start_effects();
+ flowstatus = start_effects();
/* Reserve an output buffer for all effects */
reserve_effect_buf();
@@ -644,29 +644,35 @@
for(e = 1; e < neffects; e++)
efftab[e].odone = efftab[e].olen = 0;
- /* Run input data through effects and get more until olen == 0
- * (or ST_EOF).
- */
- do {
+ /* If start functions set flowstatus to ST_EOF, skip both flow and
+ drain; we have to have this "if" because after flow flowstatus is
+ supposed to be ST_EOF, so we can't test that in order to know
+ whether to drain. */
+ if (flowstatus == 0) {
+
+ /* Run input data through effects and get more until olen == 0
+ * (or ST_EOF).
+ */
+ do {
#ifndef SOXMIX
ilen = st_read(file_desc[current_input], efftab[0].obuf,
(st_ssize_t)ST_BUFSIZ);
if (ilen > ST_BUFSIZ)
- {
+ {
st_warn("WARNING: Corrupt value of %d! Assuming 0 bytes read.\n", ilen);
ilen = 0;
- }
-
+ }
+
if (ilen == ST_EOF)
- {
+ {
efftab[0].olen = 0;
if (file_desc[current_input]->st_errno)
- {
+ {
fprintf(stderr, file_desc[current_input]->st_errstr);
- }
- }
+ }
+ }
else
- efftab[0].olen = ilen;
+ efftab[0].olen = ilen;
read_samples += efftab[0].olen;
@@ -675,53 +681,53 @@
* input file.
*/
if (ilen == ST_EOF || efftab[0].olen == 0)
- {
+ {
if (current_input < input_count-1)
- {
+ {
current_input++;
input_samples = file_desc[current_input]->length;
read_samples = 0;
if (status)
- print_input_status(current_input);
+ print_input_status(current_input);
continue;
- }
- }
+ }
+ }
/* Adjust input side volume based on value specified
* by user for this file.
*/
if (file_opts[current_input]->volume != 1.0)
- clipped += volumechange(efftab[0].obuf,
- efftab[0].olen,
- file_opts[current_input]->volume);
+ clipped += volumechange(efftab[0].obuf,
+ efftab[0].olen,
+ file_opts[current_input]->volume);
#else
for (f = 0; f < input_count; f++)
- {
+ {
ilen[f] = st_read(file_desc[f], ibuf[f], (st_ssize_t)ST_BUFSIZ);
if (ilen[f] == ST_EOF)
- {
+ {
ilen[f] = 0;
if (file_desc[f]->st_errno)
- {
+ {
fprintf(stderr, file_desc[f]->st_errstr);
- }
- }
+ }
+ }
/* Only count read samples for first file in mix */
if (f == 0)
- read_samples += efftab[0].olen;
+ read_samples += efftab[0].olen;
/* Adjust input side volume based on value specified
* by user for this file.
*/
if (file_opts[f]->volume != 1.0)
- clipped += volumechange(ibuf[f],
- ilen[f],
- file_opts[f]->volume);
- }
+ clipped += volumechange(ibuf[f],
+ ilen[f],
+ file_opts[f]->volume);
+ }
/* FIXME: Should report if the size of the reads are not
* the same.
@@ -728,11 +734,11 @@
*/
efftab[0].olen = 0;
for (f = 0; f < input_count; f++)
- if ((st_size_t)ilen[f] > efftab[0].olen)
- efftab[0].olen = ilen[f];
+ if ((st_size_t)ilen[f] > efftab[0].olen)
+ efftab[0].olen = ilen[f];
for (s = 0; s < efftab[0].olen; s++)
- {
+ {
/* Mix data together by summing samples together.
* It is assumed that input side volume adjustments
* will take care of any possible overflow.
@@ -742,20 +748,20 @@
* occur because of this.
*/
for (f = 0; f < input_count; f++)
- {
+ {
if (f == 0)
- efftab[0].obuf[s] =
- (s<(st_size_t)ilen[f]) ? ibuf[f][s] : 0;
+ efftab[0].obuf[s] =
+ (s<(st_size_t)ilen[f]) ? ibuf[f][s] : 0;
else
- if (s < (st_size_t)ilen[f])
+ if (s < (st_size_t)ilen[f])
{
- double sample;
- sample = efftab[0].obuf[s] + ibuf[f][s];
- ST_SAMPLE_CLIP_COUNT(sample, clipped);
- efftab[0].obuf[s] = sample;
+ double sample;
+ sample = efftab[0].obuf[s] + ibuf[f][s];
+ ST_SAMPLE_CLIP_COUNT(sample, clipped);
+ efftab[0].obuf[s] = sample;
}
- }
- }
+ }
+ }
#endif
efftab[0].odone = 0;
@@ -764,33 +770,32 @@
* useful to print out info about input file header and quiet.
*/
if (!writing && neffects == 1)
- efftab[0].olen = 0;
+ efftab[0].olen = 0;
if (efftab[0].olen == 0)
- break;
+ break;
flowstatus = flow_effect_out();
if (status)
- update_status();
+ update_status();
- /* Quite reading/writing on user aborts. This will close
+ /* Quit reading/writing on user aborts. This will close
* done the files nicely as if an EOF was reached on read.
*/
if (user_abort)
- break;
+ break;
- /* Negative flowstatus says no more output will ever be generated. */
- if (flowstatus == ST_EOF ||
- (writing && file_desc[file_count-1]->st_errno))
- break;
+ /* If writing and there's an error, don't try to write more. */
+ if (writing && file_desc[file_count-1]->st_errno)
+ break;
+ } while (flowstatus == 0);
- } while (1);
-
- /* This will drain the effects */
- /* Don't write if output is indicating errors. */
- if (writing && file_desc[file_count-1]->st_errno == 0)
+ /* This will drain the effects */
+ /* Don't write if output is indicating errors. */
+ if (writing && file_desc[file_count-1]->st_errno == 0)
drain_effect_out();
+ }
#ifdef SOXMIX
/* Free input buffers now that they are not used */
@@ -1086,15 +1091,19 @@
}
}
-static void start_effects(void)
+static int start_effects(void)
{
- int e;
+ int e, ret = ST_SUCCESS;
for(e = 1; e < neffects; e++) {
- (*efftab[e].h->start)(&efftab[e]);
+ if ((ret = (*efftab[e].h->start)(&efftab[e])) == ST_EOF)
+ break;
if (efftabR[e].name)
- (*efftabR[e].h->start)(&efftabR[e]);
+ if ((ret = (*efftabR[e].h->start)(&efftabR[e])) == ST_EOF)
+ break;
}
+
+ return ret;
}
static void reserve_effect_buf(void)