All its parameters are known globally within vss.c, so omit them.
Also, return an int instead of the pointer to the inbuffer which is
also known to the caller.
This patch also introduces para_fseek() in fd.c which is used by
mp3.c and vss.c and changes the mp3 audio format handler so that it
uses the new function and always check the return value.
- PARA_ERROR(FREAD, "fread error"), \
- PARA_ERROR(FSEEK, "fseek error"), \
PARA_ERROR(FRAME, "invalid mp3 frame"), \
PARA_ERROR(FRAME_LENGTH, "invalid frame length"), \
PARA_ERROR(MP3_NO_FILE, "invalid mp3 file pointer"), \
PARA_ERROR(FRAME, "invalid mp3 frame"), \
PARA_ERROR(FRAME_LENGTH, "invalid frame length"), \
PARA_ERROR(MP3_NO_FILE, "invalid mp3 file pointer"), \
#define VSS_ERRORS \
PARA_ERROR(AUDIO_FORMAT, "audio format not recognized"), \
PARA_ERROR(FSTAT, "failed to fstat() audio file"), \
#define VSS_ERRORS \
PARA_ERROR(AUDIO_FORMAT, "audio format not recognized"), \
PARA_ERROR(FSTAT, "failed to fstat() audio file"), \
+ PARA_ERROR(EMPTY_CHUNK, "empty chunk"), \
PARA_ERROR(F_GETFL, "failed to get fd flags"), \
PARA_ERROR(F_SETFL, "failed to set fd flags"), \
PARA_ERROR(FGETS, "fgets error"), \
PARA_ERROR(F_GETFL, "failed to get fd flags"), \
PARA_ERROR(F_SETFL, "failed to set fd flags"), \
PARA_ERROR(FGETS, "fgets error"), \
+ PARA_ERROR(FSEEK, "fseek error"), \
+ PARA_ERROR(FREAD, "fread error"), \
-* paraslash's wrapper for fgets(3)
+* paraslash's wrapper for fgets(3)
* \param line pointer to the buffer to store the line
* \param size the size of the buffer given by \a line
* \param f the stream to read from
* \param line pointer to the buffer to store the line
* \param size the size of the buffer given by \a line
* \param f the stream to read from
clearerr(f);
goto again;
}
clearerr(f);
goto again;
}
+
+int para_fseek(FILE *stream, long offset, int whence)
+{
+ int ret = fseek(stream, offset, whence);
+ return ret < 0? -E_FSEEK : ret;
+}
__must_check int para_fread(void *dest, size_t nbytes, size_t nmemb,
FILE *stream);
__must_check int para_fgets(char *line, int size, FILE *f);
__must_check int para_fread(void *dest, size_t nbytes, size_t nmemb,
FILE *stream);
__must_check int para_fgets(char *line, int size, FILE *f);
+int para_fseek(FILE *stream, long offset, int whence);
*/
static int mp3_seek_next_header(void)
{
*/
static int mp3_seek_next_header(void)
{
- int k, l = 0, c, first_len;
+ int k, l = 0, c, first_len, ret;
struct mp3header h, h2;
long valid_start = 0;
struct mp3header h, h2;
long valid_start = 0;
first_len = get_header(infile, &h);
if (first_len <= 0)
continue;
first_len = get_header(infile, &h);
if (first_len <= 0)
continue;
- if (fseek(infile, first_len - FRAME_HEADER_SIZE, SEEK_CUR) < 0)
- return -E_FSEEK;
+ ret = para_fseek(infile, first_len - FRAME_HEADER_SIZE, SEEK_CUR);
+ if (ret < 0)
+ return ret;
for (k = 1; k < MIN_CONSEC_GOOD_FRAMES; k++) {
if ((l = get_header(infile, &h2)) <= 0)
break;
if (!compare_headers(&h, &h2))
break;
for (k = 1; k < MIN_CONSEC_GOOD_FRAMES; k++) {
if ((l = get_header(infile, &h2)) <= 0)
break;
if (!compare_headers(&h, &h2))
break;
- fseek(infile, l - FRAME_HEADER_SIZE, SEEK_CUR);
+ ret = para_fseek(infile, l - FRAME_HEADER_SIZE, SEEK_CUR);
+ if (ret < 0)
+ return ret;
}
if (k == MIN_CONSEC_GOOD_FRAMES) {
}
if (k == MIN_CONSEC_GOOD_FRAMES) {
- fseek(infile, valid_start, SEEK_SET);
+ ret = para_fseek(infile, valid_start, SEEK_SET);
+ if (ret < 0)
+ return ret;
memcpy(&(mp3.header), &h2, sizeof(struct mp3header));
return first_len;
}
memcpy(&(mp3.header), &h2, sizeof(struct mp3header));
return first_len;
}
static int mp3_get_id3(void)
{
char fbuf[4];
static int mp3_get_id3(void)
{
char fbuf[4];
mp3.id3_isvalid = 0;
mp3.id3.title[0] = '\0';
mp3.id3_isvalid = 0;
mp3.id3.title[0] = '\0';
mp3.id3.album[0] = '\0';
mp3.id3.comment[0] = '\0';
mp3.id3.year[0] = '\0';
mp3.id3.album[0] = '\0';
mp3.id3.comment[0] = '\0';
mp3.id3.year[0] = '\0';
- if (fseek(infile, -128, SEEK_END))
- return -E_FSEEK;
+ ret = para_fseek(infile, -128, SEEK_END);
+ if (ret < 0 )
+ return ret;
if (para_fread(fbuf, 1, 3, infile) < 0)
return -E_FREAD;
fbuf[3] = '\0';
if (para_fread(fbuf, 1, 3, infile) < 0)
return -E_FREAD;
fbuf[3] = '\0';
PARA_INFO_LOG("%s", "no id3 tag\n");
return 0;
}
PARA_INFO_LOG("%s", "no id3 tag\n");
return 0;
}
- if (fseek(infile, -125, SEEK_END) < 0)
- return -E_FSEEK;
+ ret = para_fseek(infile, -125, SEEK_END);
+ if (ret < 0)
+ return ret;
if (para_fread(mp3.id3.title, 1, 30, infile) != 30)
return -E_FREAD;
mp3.id3.title[30] = '\0';
if (para_fread(mp3.id3.title, 1, 30, infile) != 30)
return -E_FREAD;
mp3.id3.title[30] = '\0';
static int find_valid_start(void)
{
static int find_valid_start(void)
{
if (!infile)
return -E_MP3_NO_FILE;
if (!infile)
return -E_MP3_NO_FILE;
frame_len = mp3_seek_next_header();
if (frame_len <= 0)
return frame_len;
frame_len = mp3_seek_next_header();
if (frame_len <= 0)
return frame_len;
- } else
- if (fseek(infile, -FRAME_HEADER_SIZE, SEEK_CUR) < 0)
- return -E_FSEEK;
+ } else {
+ ret = para_fseek(infile, -FRAME_HEADER_SIZE, SEEK_CUR);
+ if (ret < 0)
+ return ret;
+ }
if (frame_len <= 1)
return -E_FRAME_LENGTH;
return frame_len;
if (frame_len <= 1)
return -E_FRAME_LENGTH;
return frame_len;
int freq, br, fl;
struct timeval tmp, cct; /* current chunk time */
if (len > 0) {
int freq, br, fl;
struct timeval tmp, cct; /* current chunk time */
if (len > 0) {
- ret = -E_FSEEK;
- if (fseek(infile, len, SEEK_CUR) < 0)
+ ret = para_fseek(infile, len, SEEK_CUR);
+ if (ret < 0)
goto err_out;
}
len = find_valid_start();
goto err_out;
}
len = find_valid_start();
ret = -E_MP3_INFO;
if (!num_chunks || !freq_avg || !br_avg)
goto err_out;
ret = -E_MP3_INFO;
if (!num_chunks || !freq_avg || !br_avg)
goto err_out;
- ret = -E_FSEEK;
- if (fseek(infile, 0, SEEK_END) < 0)
+ ret= para_fseek(infile, 0, SEEK_END);
+ if (ret < 0)
goto err_out;
chunk_table[num_chunks] = ftell(infile);
mp3.br_average = br_avg;
goto err_out;
chunk_table[num_chunks] = ftell(infile);
mp3.br_average = br_avg;
-static char *vss_read_chunk(long unsigned current_chunk, ssize_t *len)
+/**
+ * read a chunk of data from the current audio file
+ *
+ * \param current_chunk the chunk number to read
+ *
+ * \return The length of the chunk on success, zero on end of file, negative on
+ * errors. Note: If the current chunk is of length zero, but the end of the
+ * file is not yet reached, this function returns -E_EMPTY_CHUNK.
+ * */
+ssize_t vss_read_chunk(void)
-
- *len = 0;
- if (current_chunk >= mmd->chunks_total)
- return NULL;
- *len = chunk_table[current_chunk + 1] - chunk_table[current_chunk];
- if (!*len) /* nothing to send for this run */
- return inbuf;
- pos = chunk_table[current_chunk];
- if (inbuf_size < *len) {
- PARA_INFO_LOG("increasing inbuf for chunk #%lu/%lu to %zd bytes\n",
- current_chunk, mmd->chunks_total, *len);
- inbuf = para_realloc(inbuf, *len);
- inbuf_size = *len;
+ int ret;
+ long unsigned cc = mmd->current_chunk;
+
+ if (cc >= mmd->chunks_total) /* eof */
+ return 0;
+ len = chunk_table[cc + 1] - chunk_table[cc];
+ if (!len) /* nothing to send for this run */
+ return -E_EMPTY_CHUNK;
+ pos = chunk_table[cc];
+ if (inbuf_size < len) {
+ PARA_INFO_LOG("increasing inbuf for chunk #%lu/%lu to %zu bytes\n",
+ cc, mmd->chunks_total, len);
+ inbuf = para_realloc(inbuf, len);
+ inbuf_size = len;
-// PARA_DEBUG_LOG("reading chunk #%lu@%zd (%zd bytes)\n", current_chunk,
-// pos, *len);
- ret = fseek(audio_file, pos, SEEK_SET);
+ ret = para_fseek(audio_file, pos, SEEK_SET);
- return NULL;
- ret = para_fread(inbuf, *len, 1, audio_file);
- if (ret != *len)
- return NULL;
- return inbuf;
+ return ret;
+ return para_fread(inbuf, len, 1, audio_file);
{
int i;
struct audio_format_handler *af;
{
int i;
struct audio_format_handler *af;
ssize_t ret;
struct timeval now, due;
ssize_t ret;
struct timeval now, due;
if (chk_barrier("data send", &now, &data_send_barrier,
&due, 1) < 0)
return;
if (chk_barrier("data send", &now, &data_send_barrier,
&due, 1) < 0)
return;
- buf = vss_read_chunk(mmd->current_chunk, &ret);
mmd->new_vss_status_flags &= ~VSS_REPOS;
mmd->new_vss_status_flags &= ~VSS_REPOS;
- if (!buf) {
- if (ret < 0)
+ if (!ret || (ret < 0 && ret != -E_EMPTY_CHUNK)) {
+ if (ret < 0) {
mmd->new_vss_status_flags = VSS_NEXT;
mmd->new_vss_status_flags = VSS_NEXT;
+ PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret));
+ } else
mmd->new_vss_status_flags |= VSS_NEXT;
vss_eof(af);
return;
}
mmd->new_vss_status_flags |= VSS_NEXT;
vss_eof(af);
return;
}
+ /*
+ * We call the send function also in case of empty chunks as they
+ * might have still some data queued which can be sent in this case.
+ */
+ if (ret < 0)
+ ret = 0;
if (!mmd->chunks_sent) {
struct timeval tmp;
gettimeofday(&mmd->stream_start, NULL);
if (!mmd->chunks_sent) {
struct timeval tmp;
gettimeofday(&mmd->stream_start, NULL);
mmd->events++;
}
for (i = 0; senders[i].name; i++)
mmd->events++;
}
for (i = 0; senders[i].name; i++)
- senders[i].send(mmd->current_chunk, mmd->chunks_sent, buf, ret);
+ senders[i].send(mmd->current_chunk, mmd->chunks_sent, inbuf, ret);
mmd->new_vss_status_flags |= VSS_PLAYING;
mmd->chunks_sent++;
mmd->current_chunk++;
mmd->new_vss_status_flags |= VSS_PLAYING;
mmd->chunks_sent++;
mmd->current_chunk++;