Merge branch 'maint' into next
[paraslash.git] / vss.c
diff --git a/vss.c b/vss.c
index 6304fc5..40a18e5 100644 (file)
--- a/vss.c
+++ b/vss.c
@@ -11,7 +11,9 @@
  * senders.
  */
 
+#include <regex.h>
 #include <dirent.h>
+#include <osl.h>
 
 #include "para.h"
 #include "error.h"
@@ -232,6 +234,17 @@ static int num_slices(long unsigned bytes, struct fec_client *fc, uint8_t *resul
        return 1;
 }
 
+static void set_slice_duration(struct fec_client *fc, struct fec_group *g)
+{
+       struct timeval group_duration, *chunk_tv = vss_chunk_time();
+
+       tv_scale(g->num_chunks, chunk_tv, &group_duration);
+       tv_divide(fc->fcp->slices_per_group + fc->num_extra_slices,
+               &group_duration, &g->slice_duration);
+       PARA_DEBUG_LOG("durations (group/chunk/slice): %lu/%lu/%lu\n",
+               tv2ms(&group_duration), tv2ms(chunk_tv), tv2ms(&g->slice_duration));
+}
+
 static int setup_next_fec_group(struct fec_client *fc, struct vss_task *vsst)
 {
        int ret, i, k, data_slices;
@@ -275,6 +288,8 @@ static int setup_next_fec_group(struct fec_client *fc, struct vss_task *vsst)
                g->first_chunk = mmd->current_chunk;
                g->num = 0;
        } else {
+               /* use duration of the previous group for the timing of this group */
+               set_slice_duration(fc, g);
                g->first_chunk += g->num_chunks;
                g->num++;
        }
@@ -301,6 +316,8 @@ static int setup_next_fec_group(struct fec_client *fc, struct vss_task *vsst)
        g->num_chunks = i - g->first_chunk;
        assert(g->num_chunks);
        fc->current_slice_num = 0;
+       if (g->num == 0)
+               set_slice_duration(fc, g);
 
        /* setup header slices */
        buf = vsst->header_buf;
@@ -332,23 +349,20 @@ static int setup_next_fec_group(struct fec_client *fc, struct vss_task *vsst)
                for (; i < k; i++)
                        fc->src_data[i] = (const unsigned char *)buf;
        }
-
-       /* setup group timing */
-       tv_scale(g->first_chunk - fc->first_stream_chunk, chunk_tv, &tmp);
-       tv_add(&fc->stream_start, &tmp, &g->start);
-       if (g->num) /* quick hack to avoid buffer underruns */
-               g->start.tv_sec--;
-       tv_scale(g->num_chunks, chunk_tv, &tmp); /* group duration */
-       tv_divide(fc->fcp->slices_per_group + fc->num_extra_slices,
-               &tmp, &g->slice_duration);
-
-       PARA_DEBUG_LOG("FEC group %d: %d chunks (%d - %d), %d header slices, %d data slices\n",
+       PARA_DEBUG_LOG("FEC group %d: %d chunks (%d - %d), "
+               "%d header slices, %d data slices\n",
                g->num, g->num_chunks, g->first_chunk,
                g->first_chunk + g->num_chunks - 1,
                g->num_header_slices, data_slices
        );
-       PARA_DEBUG_LOG("durations (group/chunk/slice): %lu/%lu/%lu\n",
-               tv2ms(&tmp), tv2ms(chunk_tv), tv2ms(&g->slice_duration));
+       /* set group start */
+       if (g->num != 0 && vsst->header_len != 0 && fc->first_stream_chunk == 0)
+               /* chunk #0 is the audio file header */
+               tv_scale(g->first_chunk - 1, chunk_tv, &tmp);
+       else
+               tv_scale(g->first_chunk - fc->first_stream_chunk,
+                       chunk_tv, &tmp);
+       tv_add(&fc->stream_start, &tmp, &g->start);
        return 1;
 }
 
@@ -486,8 +500,7 @@ static void compute_slice_timeout(struct timeval *timeout)
 static void set_eof_barrier(struct vss_task *vsst)
 {
        struct fec_client *fc;
-       struct timeval timeout = mmd->afd.afhi.eof_tv,
-               *chunk_tv = vss_chunk_time();
+       struct timeval timeout = {1, 0}, *chunk_tv = vss_chunk_time();
 
        if (!chunk_tv)
                goto out;
@@ -629,10 +642,6 @@ static void vss_eof(struct vss_task *vsst)
        mmd->afd.afhi.chunk_tv.tv_usec = 0;
        free(mmd->afd.afhi.chunk_table);
        mmd->afd.afhi.chunk_table = NULL;
-       free(mmd->afd.afhi.info_string);
-       mmd->afd.afhi.info_string = make_message("%s:\n%s:\n%s:\n", status_item_list[SI_AUDIO_FILE_INFO],
-               status_item_list[SI_TAGINFO1], status_item_list[SI_TAGINFO2]);
-       make_empty_status_items(mmd->afd.verbose_ls_output);
        mmd->mtime = 0;
        mmd->size = 0;
        mmd->events++;
@@ -781,7 +790,6 @@ static void recv_afs_result(struct vss_task *vsst)
        if (passed_fd < 0)
                goto err;
        shmid = afs_data;
-       free(mmd->afd.afhi.info_string);
        ret = load_afd(shmid, &mmd->afd);
        if (ret < 0)
                goto err;
@@ -827,7 +835,7 @@ err:
  */
 static void vss_send(struct vss_task *vsst)
 {
-       int i, sent_something = 0;
+       int i, fec_active = 0;
        struct timeval due;
        struct fec_client *fc, *tmp_fc;
 
@@ -841,8 +849,10 @@ static void vss_send(struct vss_task *vsst)
        list_for_each_entry_safe(fc, tmp_fc, &fec_client_list, node) {
                if (fc->error < 0)
                        continue;
-               if (!next_slice_is_due(fc, NULL))
+               if (!next_slice_is_due(fc, NULL)) {
+                       fec_active = 1;
                        continue;
+               }
                if (compute_next_fec_slice(fc, vsst) <= 0)
                        continue;
                PARA_DEBUG_LOG("sending %d:%d (%u bytes)\n", fc->group.num,
@@ -851,10 +861,10 @@ static void vss_send(struct vss_task *vsst)
                        fc->fcp->max_slice_bytes,
                        fc->fcp->private_data);
                fc->current_slice_num++;
-               sent_something = 1;
+               fec_active = 1;
        }
        if (mmd->current_chunk >= mmd->afd.afhi.chunks_total) { /* eof */
-               if (!sent_something)
+               if (!fec_active)
                        mmd->new_vss_status_flags |= VSS_NEXT;
                return;
        }
@@ -956,7 +966,6 @@ void init_vss_task(int afs_socket)
        free(hn);
        free(home);
        mmd->sender_cmd_data.cmd_num = -1;
-       make_empty_status_items(mmd->afd.verbose_ls_output);
        if (conf.autoplay_given) {
                struct timeval tmp;
                mmd->vss_status_flags |= VSS_PLAYING;