From 02d14b8dab5d70d73402fb12a6bd642f70287b52 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Sun, 4 Mar 2007 23:22:43 +0100 Subject: [PATCH] simplify vss_read_chunk() 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. --- error.h | 5 ++-- fd.c | 8 ++++++- fd.h | 1 + mp3_afh.c | 44 +++++++++++++++++++++-------------- vss.c | 69 ++++++++++++++++++++++++++++++++----------------------- 5 files changed, 78 insertions(+), 49 deletions(-) diff --git a/error.h b/error.h index 537aca57..45485e1d 100644 --- a/error.h +++ b/error.h @@ -264,8 +264,6 @@ extern const char **para_errlist[]; #define MP3_AFH_ERRORS \ - 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"), \ @@ -303,6 +301,7 @@ extern const char **para_errlist[]; #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"), \ #define AFS_ERRORS \ @@ -401,6 +400,8 @@ extern const char **para_errlist[]; 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"), \ #define WRITE_ERRORS \ diff --git a/fd.c b/fd.c index d53a3b45..df7921b4 100644 --- a/fd.c +++ b/fd.c @@ -141,7 +141,7 @@ __must_check int para_fread(void *dest, size_t nbytes, size_t nmemb, FILE *strea return -E_FREAD; } /** -* 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 @@ -166,3 +166,9 @@ 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; +} diff --git a/fd.h b/fd.h index 6cb3cbad..5ae3331f 100644 --- a/fd.h +++ b/fd.h @@ -26,3 +26,4 @@ void para_fd_set(int fd, fd_set *fds, int *max_fileno); __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); diff --git a/mp3_afh.c b/mp3_afh.c index 691f1f09..4eaad087 100644 --- a/mp3_afh.c +++ b/mp3_afh.c @@ -252,7 +252,7 @@ static int get_header(FILE *file, struct mp3header *header) */ 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; @@ -266,17 +266,22 @@ static int mp3_seek_next_header(void) 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; - 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) { - 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; } @@ -286,6 +291,7 @@ static int mp3_seek_next_header(void) static int mp3_get_id3(void) { char fbuf[4]; + int ret; mp3.id3_isvalid = 0; mp3.id3.title[0] = '\0'; @@ -293,8 +299,9 @@ static int mp3_get_id3(void) 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'; @@ -302,8 +309,9 @@ static int mp3_get_id3(void) 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'; @@ -330,7 +338,7 @@ static int mp3_get_id3(void) static int find_valid_start(void) { - int frame_len; + int ret, frame_len; if (!infile) return -E_MP3_NO_FILE; @@ -341,9 +349,11 @@ static int find_valid_start(void) 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; @@ -370,8 +380,8 @@ static int mp3_read_info(void) 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(); @@ -417,8 +427,8 @@ static int mp3_read_info(void) 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; diff --git a/vss.c b/vss.c index f1dbfb97..9aeff44f 100644 --- a/vss.c +++ b/vss.c @@ -501,33 +501,38 @@ again: return ret; } -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) { - int ret; + ssize_t len; size_t pos; - - *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); if (ret < 0) - 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); } /** @@ -546,7 +551,6 @@ void vss_send_chunk(void) { int i; struct audio_format_handler *af; - char *buf; ssize_t ret; struct timeval now, due; @@ -562,16 +566,23 @@ void vss_send_chunk(void) if (chk_barrier("data send", &now, &data_send_barrier, &due, 1) < 0) return; - buf = vss_read_chunk(mmd->current_chunk, &ret); + ret= vss_read_chunk(); 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; - else + PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret)); + } else 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); @@ -580,7 +591,7 @@ void vss_send_chunk(void) 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++; -- 2.39.5