#include "server.cmdline.h"
#include "server.h"
#include "vss.h"
-#include "afh.h"
#include "error.h"
#include "string.h"
#include "aac.h"
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)
{
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)
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;
}
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;
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;
&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)
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;
}
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;
}
/** \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
*
* 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
*
*/
void (*close_audio_file)(void);
};
+
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,
"%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)",
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],
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++;
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;
#include "server.cmdline.h"
#include "server.h"
#include "vss.h"
-#include "afh.h"
#include "error.h"
#include "fd.h"
#include "string.h"
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)
{
+ 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,
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;
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;
//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);
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;
}
return;
fclose(infile);
infile = NULL;
- free(chunk_table);
}
static const char* mp3_suffixes[] = {"mp3", NULL};
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;
}
#include "server.cmdline.h"
#include "server.h"
#include "vss.h"
-#include "afh.h"
#include "error.h"
#include "string.h"
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)
}
-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;
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);
* 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;
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;
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,
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;
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;
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);
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};
/**
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;
}
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();
/** \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 */
* - 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 */
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
#include <sys/time.h> /* gettimeofday */
#include "server.cmdline.h"
#include "afs.h"
-#include "afh.h"
#include "vss.h"
#include "send.h"
#include "error.h"
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;
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);
}
/**
{
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);
}
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]);
*/
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;
}
/**
{
if (mmd->audio_format < 0)
return NULL;
- return &afl[mmd->audio_format].chunk_tv;
+ return &mmd->afi.chunk_tv;
}
/**
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)
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;
}
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++;
}