introduce struct audio_format_info
authorAndre Noll <maan@systemlinux.org>
Sun, 11 Mar 2007 16:34:00 +0000 (17:34 +0100)
committerAndre Noll <maan@systemlinux.org>
Sun, 11 Mar 2007 16:34:00 +0000 (17:34 +0100)
This further simplifies the audio format handlers. The chunk_table
and the header info is now contained in that struct which allows
to move the cleanup on eof from the audio format handlers to the
virtual streaming system.

aac_afh.c
afh.h
command.c
mp3_afh.c
ogg_afh.c
server.c
server.h
vss.c

index 956ff6d..5e5ea96 100644 (file)
--- a/aac_afh.c
+++ b/aac_afh.c
@@ -25,7 +25,6 @@
 #include "server.cmdline.h"
 #include "server.h"
 #include "vss.h"
-#include "afh.h"
 #include "error.h"
 #include "string.h"
 #include "aac.h"
@@ -37,7 +36,7 @@
 static struct audio_format_handler *af;
 static FILE *infile;
 static unsigned char *inbuf;
-static size_t inbuf_size, inbuf_len, *chunk_table, num_chunks;
+static size_t inbuf_size, inbuf_len, num_chunks;
 
 static void aac_close_audio_file(void)
 {
@@ -47,8 +46,6 @@ static void aac_close_audio_file(void)
        infile = NULL;
        free(inbuf);
        inbuf = NULL;
-       free(chunk_table);
-       chunk_table = NULL;
 }
 
 static int aac_find_stsz(unsigned char *buf, unsigned buflen, size_t *skip)
@@ -76,7 +73,7 @@ static int aac_find_stsz(unsigned char *buf, unsigned buflen, size_t *skip)
        return -E_STSZ;
 }
 
-static int read_chunk_table(size_t skip)
+static int read_chunk_table(struct audio_format_info *afi, size_t skip)
 {
        int ret, i;
        size_t sum = 0;
@@ -92,7 +89,7 @@ static int read_chunk_table(size_t skip)
        }
        num_chunks = ret;
        PARA_INFO_LOG("sz table has %zu entries\n", num_chunks);
-       chunk_table = para_malloc((num_chunks + 1) * sizeof(size_t));
+       afi->chunk_table = para_malloc((num_chunks + 1) * sizeof(size_t));
        for (i = 1; i <= num_chunks; i++) {
                if (skip + 4 > inbuf_len) {
                        skip = inbuf_len - skip;
@@ -105,33 +102,33 @@ static int read_chunk_table(size_t skip)
                        PARA_INFO_LOG("next buffer: %zu bytes\n", inbuf_len);
                }
                sum += aac_read_int32(inbuf + skip);
-               chunk_table[i] = sum;
+               afi->chunk_table[i] = sum;
                skip += 4;
                if (i < 10 || i + 10 > num_chunks)
-                       PARA_DEBUG_LOG("offset #%d: %zu\n", i, chunk_table[i]);
+                       PARA_DEBUG_LOG("offset #%d: %zu\n", i, afi->chunk_table[i]);
        }
        return 1;
 }
 
-static long unsigned aac_set_chunk_tv(mp4AudioSpecificConfig *mp4ASC)
+static long unsigned aac_set_chunk_tv(struct audio_format_info *afi,
+               mp4AudioSpecificConfig *mp4ASC)
 {
        float tmp = mp4ASC->sbr_present_flag == 1? 2047 : 1023,
                ms = 1000.0 * num_chunks * tmp / mp4ASC->samplingFrequency;
        struct timeval total;
 
        ms2tv(ms, &total);
-       tv_divide(num_chunks, &total, &af->chunk_tv);
+       tv_divide(num_chunks, &total, &afi->chunk_tv);
        PARA_INFO_LOG("%luHz, %fs (%zd x %lums)\n",
                mp4ASC->samplingFrequency, ms / 1000,
-               num_chunks, tv2ms(&af->chunk_tv));
+               num_chunks, tv2ms(&afi->chunk_tv));
        return ms / 1000;
 }
 
 /*
  * Init m4a file and write some tech data to given pointers.
  */
-static int aac_get_file_info(FILE *file, char *info_str, long unsigned *frames,
-       int *seconds, size_t **vss_chunk_table)
+static int aac_get_file_info(FILE *file, struct audio_format_info *afi)
 {
        int i, ret, decoder_len;
        size_t skip;
@@ -163,12 +160,11 @@ static int aac_get_file_info(FILE *file, char *info_str, long unsigned *frames,
                &mp4ASC);
        if (ret < 0)
                return -E_MP4ASC;
-       ret = read_chunk_table(skip);
+       ret = read_chunk_table(afi, skip);
        if (ret < 0)
                return ret;
-       *frames = num_chunks;
-       *seconds = aac_set_chunk_tv(&mp4ASC);
-       *vss_chunk_table = chunk_table;
+       afi->chunks_total = num_chunks;
+       afi->seconds_total = aac_set_chunk_tv(afi, &mp4ASC);
        for (;;) {
                ret = aac_find_entry_point(inbuf, inbuf_len, &skip);
                if (ret >= 0)
@@ -178,15 +174,15 @@ static int aac_get_file_info(FILE *file, char *info_str, long unsigned *frames,
                        return -E_AAC_READ;
                PARA_INFO_LOG("next buffer: %d bytes\n", ret);
        }
-       chunk_table[0] = ret;
+       afi->chunk_table[0] = ret;
        for (i = 1; i<= num_chunks; i++)
-               chunk_table[i] += ret;
-       sprintf(info_str, "audio_file_info1:%zu x %lums\n"
+               afi->chunk_table[i] += ret;
+       sprintf(afi->info_string, "audio_file_info1:%zu x %lums\n"
                "audio_file_info2:\n"
                "audio_file_info3:\n",
                num_chunks,
-               tv2ms(&af->chunk_tv));
-       tv_scale(20, &af->chunk_tv, &af->eof_tv);
+               tv2ms(&afi->chunk_tv));
+       tv_scale(20, &afi->chunk_tv, &afi->eof_tv);
        return 1;
 }
 
@@ -197,6 +193,5 @@ void aac_afh_init(struct audio_format_handler *p)
        af = p;
        af->get_file_info = aac_get_file_info,
        af->close_audio_file = aac_close_audio_file;
-       af->get_header_info = NULL;
        af->suffixes = aac_suffixes;
 }
diff --git a/afh.h b/afh.h
index 7787410..e7ca282 100644 (file)
--- a/afh.h
+++ b/afh.h
 
 /** \endcond */
 
+/** size of the  audio_file info string */
+#define AUDIO_FILE_INFO_SIZE 16384
+
+struct audio_format_info {
+       /** the number of chunks this audio file contains */
+       long unsigned chunks_total;
+       /** the length of the audio file in seconds */
+       int seconds_total;
+       /** a string that gets filled in by the audio format handler */
+       char info_string[AUDIO_FILE_INFO_SIZE];
+       /**
+        * the table that specifies the offset of the individual pieces in
+        * the current audio file.
+        */
+       size_t *chunk_table;
+       /** period of time between sending data chunks */
+       struct timeval chunk_tv;
+       /** end of file timeout - do not load new audio file until this time */
+       struct timeval eof_tv;
+       /**
+        * optional audio file header
+        *
+        * This is read from a sender in case a new client connects in the
+        * middle of the stream.  The audio format handler does not need to set
+        * this if the audio format does not need any special header treatment.
+        * If non-NULL, it must point to a buffer holding the current audio
+        * file header.
+        */
+       char *header;
+       /* the length of the header, ignored if \a header is \p NULL */
+       unsigned header_len;
+};
+
 /**
  * structure for audio format handling
  *
@@ -64,37 +97,18 @@ struct audio_format_handler {
         * Must initialize all function pointers and is assumed to succeed.
         */
        void (*init)(struct audio_format_handler*);
-       /**
-        * period of time between sending data chunks
-       */
-       struct timeval chunk_tv; /* length of one chunk of data */
-       /**
-        * end of file timeout - do not load new audio file until this time
-        *
-       */
-       struct timeval eof_tv; /* timeout on eof */
-       /**
-        * Pointer to the optional get-header function.
-        *
-        * This is called from a sender in case a new client connects in the middle of
-        * the stream.  The audio format handler may set this to NULL to indicate that
-        * this audio format does not need any special header treatment.  If non-NULL,
-        * the function it points to must return a pointer to a buffer holding the
-        * current audio file header, together with the header length.
-       */
-       char *(*get_header_info)(int *header_len);
        /**
         * check if this audio format handler can handle the file
         *
-        * This is a  pointer to a function returning whether a given file is valid for
-        * this audio format. A negative return value indicates that this audio format
-        * handler did not recognize the given file. On success, the function is
-        * expected to return a positive value and to fill in \arg info_str, \arg
-        * chunks and \arg seconds appropriately and to return the chunk table
-        * via \a vss_chunk_table.
+        * This is a  pointer to a function returning whether a given file is
+        * valid for this audio format. A negative return value indicates that
+        * this audio format handler did not recognize the given file. On
+        * success, the function must return a positive value and fill in the
+        * given struct audio_format_info.
+        *
+        * \sa struct audio_format_info
        */
-       int (*get_file_info)(FILE *audio_file, char *info_str,
-               long unsigned *chunks, int *seconds, size_t **vss_chunk_table);
+       int (*get_file_info)(FILE *audio_file, struct audio_format_info *afi);
        /**
         * cleanup function of this audio format handler
         *
@@ -104,3 +118,4 @@ struct audio_format_handler {
        */
        void (*close_audio_file)(void);
 };
+
index 77d3ef7..2fac5cc 100644 (file)
--- a/command.c
+++ b/command.c
@@ -114,14 +114,14 @@ static char *get_sb_string(struct misc_meta_data *nmmd)
                return para_strdup("");
        if (!base[0])
                return base;
-       if (nmmd->chunks_total) {
-               secs = (long long) nmmd->seconds_total * nmmd->chunks_sent
-                       / nmmd->chunks_total;
-               rsecs = (long long) nmmd->seconds_total *
-                       (nmmd->chunks_total - nmmd->chunks_sent)
-                       / nmmd->chunks_total;
+       if (nmmd->afi.chunks_total) {
+               secs = (long long) nmmd->afi.seconds_total * nmmd->chunks_sent
+                       / nmmd->afi.chunks_total;
+               rsecs = (long long) nmmd->afi.seconds_total *
+                       (nmmd->afi.chunks_total - nmmd->chunks_sent)
+                       / nmmd->afi.chunks_total;
                percent = 100 * ((nmmd->chunks_sent + 5) / 10)
-                       / ((nmmd->chunks_total + 5) / 10);
+                       / ((nmmd->afi.chunks_total + 5) / 10);
        }
        ret = make_message("%llu:%02llu [%llu:%02llu] (%llu%%) %s",
                secs / 60, secs % 60,
@@ -158,7 +158,7 @@ static char *get_status(struct misc_meta_data *nmmd)
                "%s:%s\n"       "%s:%lu.%lu\n"  "%s:%lu.%lu\n",
                status_item_list[SI_FILE_SIZE], nmmd->size / 1024,
                status_item_list[SI_MTIME], mtime,
-               status_item_list[SI_LENGTH], nmmd->seconds_total,
+               status_item_list[SI_LENGTH], nmmd->afi.seconds_total,
                status_item_list[SI_NUM_PLAYED], nmmd->num_played,
 
                status_item_list[SI_STATUS_BAR], bar ? bar : "(none)",
@@ -169,7 +169,7 @@ static char *get_status(struct misc_meta_data *nmmd)
                status_item_list[SI_OFFSET], offset,
                status_item_list[SI_FORMAT], audio_format_name(nmmd->audio_format),
                nmmd->selector_info,
-               nmmd->audio_file_info,
+               nmmd->afi.info_string,
 
                status_item_list[SI_UPTIME], ut,
                status_item_list[SI_STREAM_START],
@@ -649,20 +649,20 @@ int com_ff(__a_unused int fd, int argc, char **argv)
                backwards = 1; /* jmp backwards */
        mmd_lock();
        ret = -E_NO_AUDIO_FILE;
-       if (!mmd->chunks_total || !mmd->seconds_total)
+       if (!mmd->afi.chunks_total || !mmd->afi.seconds_total)
                goto out;
-       promille = (1000 * mmd->current_chunk) / mmd->chunks_total;
+       promille = (1000 * mmd->current_chunk) / mmd->afi.chunks_total;
        if (backwards)
-               promille -= 1000 * i / mmd->seconds_total;
+               promille -= 1000 * i / mmd->afi.seconds_total;
        else
-               promille += 1000 * i / mmd->seconds_total;
+               promille += 1000 * i / mmd->afi.seconds_total;
        if (promille < 0)
                promille = 0;
        if (promille >  1000) {
                mmd->new_vss_status_flags |= VSS_NEXT;
                goto out;
        }
-       mmd->repos_request = (mmd->chunks_total * promille) / 1000;
+       mmd->repos_request = (mmd->afi.chunks_total * promille) / 1000;
        mmd->new_vss_status_flags |= VSS_REPOS;
        mmd->new_vss_status_flags &= ~VSS_NEXT;
        mmd->events++;
@@ -684,12 +684,12 @@ int com_jmp(__a_unused int fd, int argc, char **argv)
                return -E_COMMAND_SYNTAX;
        mmd_lock();
        ret = -E_NO_AUDIO_FILE;
-       if (!mmd->chunks_total)
+       if (!mmd->afi.chunks_total)
                goto out;
        if (i > 100)
                i = 100;
        PARA_INFO_LOG("jumping to %lu%%\n", i);
-       mmd->repos_request = (mmd->chunks_total * i + 50)/ 100;
+       mmd->repos_request = (mmd->afi.chunks_total * i + 50)/ 100;
        PARA_INFO_LOG("sent: %lu,  offset before jmp: %lu\n",
                mmd->chunks_sent, mmd->offset);
        mmd->new_vss_status_flags |= VSS_REPOS;
index 7146124..898547f 100644 (file)
--- a/mp3_afh.c
+++ b/mp3_afh.c
@@ -31,7 +31,6 @@
 #include "server.cmdline.h"
 #include "server.h"
 #include "vss.h"
-#include "afh.h"
 #include "error.h"
 #include "fd.h"
 #include "string.h"
@@ -106,7 +105,7 @@ static const char *mode_text[] = {"stereo", "joint stereo", "dual channel", "mon
 static FILE *infile;
 static struct mp3info mp3;
 static struct audio_format_handler *af;
-static ssize_t *chunk_table, num_chunks;
+static ssize_t num_chunks;
 
 static int header_frequency(struct mp3header *h)
 {
@@ -144,16 +143,16 @@ static int frame_length(struct mp3header *header)
                + header->padding;
 }
 
-static void write_info_str(char *info_str)
+static void write_info_str(struct audio_format_info *afi)
 {
        int v = mp3.id3_isvalid;
 
-       snprintf(info_str, MMD_INFO_SIZE,
+       snprintf(afi->info_string, MMD_INFO_SIZE,
                "audio_file_info1:%d x %lums, %lu kbit/s (%cbr) %i KHz %s\n"
                "audio_file_info2:%s, by %s\n"
                "audio_file_info3:A: %s, Y: %s, C: %s\n",
                num_chunks,
-               tv2ms(&af->chunk_tv),
+               tv2ms(&afi->chunk_tv),
                mp3.br_average,
                mp3.vbr? 'v' : 'c',
                mp3.freq / 1000,
@@ -354,7 +353,7 @@ static int find_valid_start(void)
        return frame_len;
 }
 
-static int mp3_read_info(void)
+static int mp3_read_info(struct audio_format_info *afi)
 {
        long fl_avg = 0, freq_avg = 0, br_avg = 0;
        int ret, len = 0, old_br = -1;
@@ -362,7 +361,7 @@ static int mp3_read_info(void)
        unsigned chunk_table_size = 1000; /* gets increased on demand */
 
        num_chunks = 0;
-       chunk_table = para_malloc(chunk_table_size * sizeof(size_t));
+       afi->chunk_table = para_malloc(chunk_table_size * sizeof(size_t));
        ret = mp3_get_id3();
        if (ret < 0)
                goto err_out;
@@ -393,13 +392,13 @@ static int mp3_read_info(void)
                //PARA_DEBUG_LOG("%s: br: %d, freq: %d, fl: %d, cct: %lu\n", __func__, br, freq, fl, cct.tv_usec);
                if (num_chunks >= chunk_table_size) {
                        chunk_table_size *= 2;
-                       chunk_table = para_realloc(chunk_table,
+                       afi->chunk_table = para_realloc(afi->chunk_table,
                                chunk_table_size * sizeof(size_t));
                }
-               chunk_table[num_chunks] = ftell(infile);
+               afi->chunk_table[num_chunks] = ftell(infile);
                if (num_chunks < 10 || !(num_chunks % 1000))
                        PARA_INFO_LOG("chunk #%d: %zd\n", num_chunks,
-                               chunk_table[num_chunks]);
+                               afi->chunk_table[num_chunks]);
                num_chunks++;
                if (num_chunks == 1) {
 //                     entry = ftell(infile);
@@ -423,43 +422,41 @@ static int mp3_read_info(void)
        ret= para_fseek(infile, 0, SEEK_END);
        if (ret < 0)
                goto err_out;
-       chunk_table[num_chunks] = ftell(infile);
+       afi->chunk_table[num_chunks] = ftell(infile);
        mp3.br_average = br_avg;
        mp3.freq = freq_avg;
        mp3.seconds = (tv2ms(&total_time) + 500) / 1000;
-       tv_divide(num_chunks, &total_time, &af->chunk_tv);
+       tv_divide(num_chunks, &total_time, &afi->chunk_tv);
        rewind(infile);
-       PARA_DEBUG_LOG("%zu chunks, each %lums\n", num_chunks, tv2ms(&af->chunk_tv));
-       tv_scale(3, &af->chunk_tv, &af->eof_tv);
-       PARA_DEBUG_LOG("eof timeout: %lu\n", tv2ms(&af->eof_tv));
+       PARA_DEBUG_LOG("%zu chunks, each %lums\n", num_chunks, tv2ms(&afi->chunk_tv));
+       tv_scale(3, &afi->chunk_tv, &afi->eof_tv);
+       PARA_DEBUG_LOG("eof timeout: %lu\n", tv2ms(&afi->eof_tv));
        return 1;
 err_out:
        PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret));
-       free(chunk_table);
+       free(afi->chunk_table);
        return ret;
 }
 
 /*
  * Read mp3 information from audio file
  */
-static int mp3_get_file_info(FILE *audio_file, char *info_str,
-       long unsigned *frames, int *seconds, size_t **vss_chunk_table)
+static int mp3_get_file_info(FILE *audio_file, struct audio_format_info *afi)
 {
        int ret;
 
        if (!audio_file)
                return -E_MP3_NO_FILE;
        infile = audio_file;
-       ret = mp3_read_info();
+       ret = mp3_read_info(afi);
        if (ret < 0) {
                infile = NULL;
                return ret;
        }
-       write_info_str(info_str);
-       *frames = num_chunks;
-       *seconds = mp3.seconds;
-       *vss_chunk_table = chunk_table;
-       if (*seconds < 2 || !*frames)
+       write_info_str(afi);
+       afi->chunks_total = num_chunks;
+       afi->seconds_total = mp3.seconds;
+       if (afi->seconds_total < 2 || !afi->chunks_total)
                return -E_MP3_INFO;
        return 1;
 }
@@ -470,7 +467,6 @@ static void mp3_close_audio_file(void)
                return;
        fclose(infile);
        infile = NULL;
-       free(chunk_table);
 }
 
 static const char* mp3_suffixes[] = {"mp3", NULL};
@@ -485,9 +481,5 @@ void mp3_init(struct audio_format_handler *p)
        af = p;
        af->get_file_info = mp3_get_file_info;
        af->close_audio_file = mp3_close_audio_file;
-       af->get_header_info = NULL;
-       /* eof_tv gets overwritten in mp3_get_file_info() */
-       af->eof_tv.tv_sec = 0;
-       af->eof_tv.tv_usec = 100 * 1000;
        af->suffixes = mp3_suffixes;
 }
index dd0a540..f972c63 100644 (file)
--- a/ogg_afh.c
+++ b/ogg_afh.c
@@ -25,7 +25,6 @@
 #include "server.cmdline.h"
 #include "server.h"
 #include "vss.h"
-#include "afh.h"
 #include "error.h"
 #include "string.h"
 
@@ -34,9 +33,6 @@
 static double chunk_time = 0.25;
 
 FILE *audio_file;
-static int header_len;
-static char *header;
-static ssize_t *chunk_table;
 static struct audio_format_handler *af;
 
 static size_t cb_read(void *buf, size_t size, size_t nmemb, void *datasource)
@@ -86,7 +82,20 @@ int ogg_open_callbacks(void *datasource, OggVorbis_File *vf, ov_callbacks c)
 
 }
 
-static int ogg_compute_header_len(FILE *file)
+static int ogg_save_header(FILE *file, struct audio_format_info *afi)
+{
+       int ret;
+
+       afi->header = para_malloc(afi->header_len);
+       rewind(file);
+       ret = read(fileno(file), afi->header, afi->header_len);
+       if (ret == afi->header_len)
+               return 1;
+       free(afi->header);
+       return -E_OGG_READ;
+}
+
+static int ogg_compute_header_len(FILE *file, struct audio_format_info *afi)
 {
        int ret, len, in = fileno(file);
        unsigned int serial;
@@ -148,11 +157,11 @@ static int ogg_compute_header_len(FILE *file)
        ogg_stream_packetout(stream_in, &packet);
        ogg_stream_packetin(stream_out, &packet);
 
-       header_len = 0;
+       afi->header_len = 0;
        while (ogg_stream_flush(stream_out, &page))
-               header_len += page.body_len + page.header_len;
-       ret = len;
-       PARA_INFO_LOG("header_len = %d\n", header_len);
+               afi->header_len += page.body_len + page.header_len;
+       PARA_INFO_LOG("header_len = %d\n", afi->header_len);
+       ret = ogg_save_header(file, afi);
 err2:
        ogg_stream_destroy(stream_in);
        ogg_stream_destroy(stream_out);
@@ -169,7 +178,7 @@ err1:
  * CHUNK_TIME begins. Always successful.
  */
 static long unsigned ogg_compute_chunk_table(OggVorbis_File *of,
-       double time_total)
+       struct audio_format_info *afi, double time_total)
 {
        int i, ret, num;
        ssize_t max_chunk_len, pos = 0, min = 0, old_pos;
@@ -180,8 +189,8 @@ static long unsigned ogg_compute_chunk_table(OggVorbis_File *of,
        num = time_total / chunk_time + 3;
        PARA_DEBUG_LOG("chunk time: %g allocating %d chunk pointers\n",
                chunk_time, num);
-       chunk_table = para_malloc(num * sizeof(size_t));
-       chunk_table[0] = 0;
+       afi->chunk_table = para_malloc(num * sizeof(size_t));
+       afi->chunk_table[0] = 0;
        max_chunk_len = 0;
        for (i = 1; ret == 0; i++) {
                ogg_int64_t diff;
@@ -192,7 +201,7 @@ static long unsigned ogg_compute_chunk_table(OggVorbis_File *of,
                diff = pos - old_pos;
                max_chunk_len = PARA_MAX(max_chunk_len, diff);
                min = (i == 1)? diff : PARA_MIN(min, diff);
-               chunk_table[i] = pos;
+               afi->chunk_table[i] = pos;
                if (i < 11 || !((i - 1) % 1000)|| i > num - 11)
                        PARA_DEBUG_LOG("chunk #%d: %g secs, pos: %zd, "
                                "size: %zd\n", i - 1,
@@ -200,7 +209,7 @@ static long unsigned ogg_compute_chunk_table(OggVorbis_File *of,
                old_pos = pos;
        }
        num_chunks = i - 1;
-       chunk_table[i] = pos;
+       afi->chunk_table[i] = pos;
        PARA_INFO_LOG("%lu chunks (%fs), max chunk: %zd, min chunk: %zd\n",
                num_chunks, chunk_time, max_chunk_len, min);
        return num_chunks;
@@ -208,29 +217,13 @@ static long unsigned ogg_compute_chunk_table(OggVorbis_File *of,
 
 static void ogg_close_audio_file(void)
 {
-       free(header);
-       free(chunk_table);
        fclose(audio_file);
 }
 
-static int ogg_save_header(FILE *file, int len)
-{
-       int ret;
-
-       header = para_malloc(len);
-       rewind(file);
-       ret = read(fileno(file), header, len);
-       if (ret == len)
-               return 1;
-       free(header);
-       return -E_OGG_READ;
-}
-
 /*
  * Init oggvorbis file and write some tech data to given pointers.
  */
-static int ogg_get_file_info(FILE *file, char *info_str, long unsigned *frames,
-       int *seconds, size_t **vss_chunk_table)
+static int ogg_get_file_info(FILE *file, struct audio_format_info *afi)
 {
        int ret;
        double time_total;
@@ -247,10 +240,7 @@ static int ogg_get_file_info(FILE *file, char *info_str, long unsigned *frames,
 
        if (!file)
                return -E_OGG_NO_FILE;
-       ret = ogg_compute_header_len(file);
-       if (ret < 0)
-               return ret;
-       ret = ogg_save_header(file, header_len);
+       ret = ogg_compute_header_len(file, afi);
        if (ret < 0)
                return ret;
        rewind(file);
@@ -263,35 +253,32 @@ static int ogg_get_file_info(FILE *file, char *info_str, long unsigned *frames,
                goto err;
        time_total = ov_time_total(&of, -1);
        raw_total = ov_raw_total(&of, -1);
-       *seconds = time_total;
+       afi->seconds_total = time_total;
        vi_sampling_rate = vi->rate;
        vi_bitrate = ov_bitrate(&of, 0);
        rewind(file);
-       *frames = ogg_compute_chunk_table(&of, time_total);
+       afi->chunks_total = ogg_compute_chunk_table(&of, afi, time_total);
        rewind(file);
-       *vss_chunk_table = chunk_table;
-       sprintf(info_str, "audio_file_info1:%lu x %lu, %ldkHz, %d channels, %ldkbps\n"
+       sprintf(afi->info_string, "audio_file_info1:%lu x %lu, %ldkHz, "
+               "%d channels, %ldkbps\n"
                "audio_file_info2: \n"
                "audio_file_info3: \n",
-               *frames, (long unsigned) (chunk_time * 1000 * 1000),
+               afi->chunks_total, (long unsigned) (chunk_time * 1000 * 1000),
                vi_sampling_rate / 1000, vi->channels, vi_bitrate / 1000
                );
        rewind(file);
        audio_file = file;
+       afi->chunk_tv.tv_sec = 0;
+       afi->chunk_tv.tv_usec = 250 * 1000;
+       tv_scale(3, &afi->chunk_tv, &afi->eof_tv);
        ret = 1;
 err:
        ov_clear(&of); /* keeps the file open */
        if (ret < 0)
-               free(header);
+               free(afi->header);
        return ret;
 }
 
-static char *ogg_get_header_info(int *len)
-{
-       *len = header_len;
-       return header;
-}
-
 static const char* ogg_suffixes[] = {"ogg", NULL};
 
 /**
@@ -304,9 +291,5 @@ void ogg_init(struct audio_format_handler *p)
        af = p;
        af->get_file_info = ogg_get_file_info,
        af->close_audio_file = ogg_close_audio_file;
-       af->get_header_info = ogg_get_header_info;
-       af->chunk_tv.tv_sec = 0;
-       af->chunk_tv.tv_usec = 250 * 1000;
-       tv_scale(3, &af->chunk_tv, &af->eof_tv);
        af->suffixes = ogg_suffixes;
 }
index 41d9a2a..7e52fa5 100644 (file)
--- a/server.c
+++ b/server.c
@@ -369,6 +369,7 @@ static unsigned do_inits(int argc, char **argv)
        if (conf.daemon_given)
                daemon_init();
        init_selector();
+//     PARA_ERROR_LOG("num: %d\n", mmd->selector_num);
        PARA_NOTICE_LOG("%s", "initializing virtual streaming system\n");
        vss_init();
        mmd->server_pid = getpid();
index 9dee3e3..efee2db 100644 (file)
--- a/server.h
+++ b/server.h
@@ -19,6 +19,7 @@
 /** \file server.h common server data structures */
 
 #include "para.h"
+#include "afh.h"
 #include <openssl/pem.h>
 
 /** size of the selector_info and audio_file info strings of struct misc_meta_data */
@@ -72,7 +73,8 @@ struct sender_command_data{
  *     - The contents are listed in the stat command and have to be up to
  *     date.
  */
-struct misc_meta_data{
+struct misc_meta_data {
+       struct audio_format_info afi;
 /** the size of the current audio file in bytes */
        long unsigned int size;
 /** the full path of the current audio file */
@@ -87,20 +89,14 @@ struct misc_meta_data{
        unsigned int new_vss_status_flags;
 /** the number of data chunks sent for the current audio file */
        long unsigned chunks_sent;
-/** the number of chunks this audio file contains */
-       long unsigned chunks_total;
 /** set by the jmp/ff commands to the new position in chunks */
        long unsigned repos_request;
 /** the number of the chunk currently sent out*/
        long unsigned current_chunk;
 /** the milliseconds that have been skipped of the current audio file */
        long offset;
-/** the length of the audio file in seconds */
-       int seconds_total;
 /** the time para_server started to stream */
        struct timeval stream_start;
-/** a string that gets filled in by the audio format handler */
-       char audio_file_info[MMD_INFO_SIZE];
 /** the event counter
  *
  * commands may increase this to force a status update to be sent to all
diff --git a/vss.c b/vss.c
index 9aeff44..d0b21da 100644 (file)
--- a/vss.c
+++ b/vss.c
@@ -26,7 +26,6 @@
 #include <sys/time.h> /* gettimeofday */
 #include "server.cmdline.h"
 #include "afs.h"
-#include "afh.h"
 #include "vss.h"
 #include "send.h"
 #include "error.h"
@@ -44,7 +43,7 @@ extern struct misc_meta_data *mmd;
 extern struct audio_file_selector selectors[];
 extern struct sender senders[];
 static char *inbuf;
-static size_t *chunk_table, inbuf_size;
+static size_t inbuf_size;
 
 static FILE *audio_file = NULL;
 
@@ -186,8 +185,7 @@ void vss_init(void)
 
 static int get_file_info(int i)
 {
-       return  afl[i].get_file_info(audio_file, mmd->audio_file_info,
-               &mmd->chunks_total, &mmd->seconds_total, &chunk_table);
+       return  afl[i].get_file_info(audio_file, &mmd->afi);
 }
 
 /**
@@ -321,7 +319,7 @@ static void vss_next_chunk_time(struct timeval *due)
 {
        struct timeval tmp;
 
-       tv_scale(mmd->chunks_sent, &afl[mmd->audio_format].chunk_tv, &tmp);
+       tv_scale(mmd->chunks_sent, &mmd->afi.chunk_tv, &tmp);
        tv_add(&tmp, &mmd->stream_start, due);
 }
 
@@ -373,17 +371,22 @@ static void vss_eof(struct audio_format_handler *af)
                return;
        }
        gettimeofday(&now, NULL);
-       tv_add(&af->eof_tv, &now, &eof_barrier);
+       tv_add(&mmd->afi.eof_tv, &now, &eof_barrier);
        af->close_audio_file();
        audio_file = NULL;
        mmd->audio_format = -1;
        af = NULL;
        mmd->chunks_sent = 0;
        mmd->offset = 0;
-       mmd->seconds_total = 0;
+       mmd->afi.seconds_total = 0;
+       free(mmd->afi.chunk_table);
+       mmd->afi.chunk_table = NULL;
+       PARA_ERROR_LOG("freeing header %p\n", mmd->afi.header);
+       free(mmd->afi.header);
+       mmd->afi.header = NULL;
        tmp  = make_message("%s:\n%s:\n%s:\n", status_item_list[SI_AUDIO_INFO1],
                status_item_list[SI_AUDIO_INFO2], status_item_list[SI_AUDIO_INFO3]);
-       strcpy(mmd->audio_file_info, tmp);
+       strcpy(mmd->afi.info_string, tmp);
        free(tmp);
        tmp  = make_message("%s:\n%s:\n%s:\n", status_item_list[SI_DBINFO1],
                status_item_list[SI_DBINFO2], status_item_list[SI_DBINFO3]);
@@ -406,12 +409,10 @@ static void vss_eof(struct audio_format_handler *af)
  */
 char *vss_get_header(int *header_len)
 {
-       *header_len = 0;
        if (mmd->audio_format < 0)
                return NULL;
-       if (!afl[mmd->audio_format].get_header_info)
-               return NULL;
-       return afl[mmd->audio_format].get_header_info(header_len);
+       *header_len = mmd->afi.header_len;
+       return mmd->afi.header;
 }
 
 /**
@@ -436,7 +437,7 @@ struct timeval *vss_chunk_time(void)
 {
        if (mmd->audio_format < 0)
                return NULL;
-       return &afl[mmd->audio_format].chunk_tv;
+       return &mmd->afi.chunk_tv;
 }
 
 /**
@@ -479,7 +480,7 @@ again:
                        struct timeval now;
                        gettimeofday(&now, NULL);
                        if (!vss_paused() || mmd->chunks_sent)
-                               tv_add(&af->eof_tv, &now, &eof_barrier);
+                               tv_add(&mmd->afi.eof_tv, &now, &eof_barrier);
                        if (vss_repos())
                                tv_add(&now, &announce_tv, &data_send_barrier);
                        if (mmd->new_vss_status_flags & VSS_NOMORE)
@@ -517,15 +518,15 @@ ssize_t vss_read_chunk(void)
        int ret;
        long unsigned cc = mmd->current_chunk;
 
-       if (cc >= mmd->chunks_total) /* eof */
+       if (cc >= mmd->afi.chunks_total) /* eof */
                return 0;
-       len = chunk_table[cc + 1] - chunk_table[cc];
+       len = mmd->afi.chunk_table[cc + 1] - mmd->afi.chunk_table[cc];
        if (!len) /* nothing to send for this run */
                return -E_EMPTY_CHUNK;
-       pos = chunk_table[cc];
+       pos = mmd->afi.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);
+                       cc, mmd->afi.chunks_total, len);
                inbuf = para_realloc(inbuf, len);
                inbuf_size = len;
        }
@@ -586,7 +587,7 @@ void vss_send_chunk(void)
        if (!mmd->chunks_sent) {
                struct timeval tmp;
                gettimeofday(&mmd->stream_start, NULL);
-               tv_scale(mmd->current_chunk, &af->chunk_tv, &tmp);
+               tv_scale(mmd->current_chunk, &mmd->afi.chunk_tv, &tmp);
                mmd->offset = tv2ms(&tmp);
                mmd->events++;
        }