]> git.tuebingen.mpg.de Git - paraslash.git/commitdiff
Merge branch 't/testsuite'
authorAndre Noll <maan@systemlinux.org>
Sun, 20 Mar 2011 11:20:29 +0000 (12:20 +0100)
committerAndre Noll <maan@systemlinux.org>
Sun, 20 Mar 2011 11:20:29 +0000 (12:20 +0100)
29 files changed:
Makefile.in
NEWS
afh.c
afh.h
afh_common.c
afs.c
afs.h
aft.c
audiod.c
audiod.cmd
audiod.h
command.c
configure.ac
crypt.c
error.h
fade.c
gcc-compat.h
ggo/audiod.m4
gui.c
ogg_afh.c
ogg_afh_common.c
ogg_afh_common.h
para.h
score.c
server.c
spx_afh.c
stdin.h
vss.c
wma_afh.c

index a246f4c161832b7f182ea5a457cdc6d435768c4b..e6b6ecc27367d12f46d189c3c75036d09acc1bb6 100644 (file)
@@ -101,9 +101,10 @@ else
        Q =
 endif
 
-.PHONY: all clean distclean maintainer-clean install man tarball\
+.PHONY: dep all clean distclean maintainer-clean install man tarball\
        .FORCE-GIT-VERSION-FILE
-all: @executables@ $(man_pages)
+all: dep @executables@ $(man_pages)
+dep: $(deps)
 man: $(man_pages)
 tarball: $(tarball)
 
@@ -226,8 +227,10 @@ all_objs := $(recv_objs) $(filter_objs) $(client_objs) $(gui_objs) \
        $(audiod_objs) $(audioc_objs) $(fade_objs) $(server_objs) \
        $(write_objs) $(afh_objs)
 
+deps := $(all_objs:.o=.d)
+
 ifeq ($(findstring clean, $(MAKECMDGOALS)),)
--include $(all_objs:.o=.d)
+-include $(deps)
 endif
 
 para_recv: $(recv_objs)
diff --git a/NEWS b/NEWS
index dcc4393b517df293c8eb90344d6471af48dab833..e6309e4a9fea5f4ec15f89a858fd9c0a0cbd4804 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,14 +2,21 @@
 0.4.6 (to be announced) "deterministic entropy"
 -----------------------------------------------
 
+Lots of ogg/vorbis improvements, enhancements for para_gui and a fair
+amount of other bug fixes.
+
        - For DCCP/OGG streams the audio file header is only sent once
          at the beginning of the stream rather than periodically
          every five seconds. This reduces network traffic and the
          FEC group size.
-       - aacdec error message cleanups
-       - simplified color error handling
+       - The vorbis comment header is replaced by an empty dummy header
+         before the header is sent over the network. This also results in
+         less network traffic and smaller FEC groups.
+       - ogg timing fixes and performance improvements
        - para_gui: New option --theme to select a startup theme. Several
          other improvements and fixes.
+       - aacdec error message cleanups
+       - simplified color error handling
 
 --------------------------------------------
 0.4.5 (2010-12-17) "symmetric randomization"
diff --git a/afh.c b/afh.c
index 5ce6cfc5a13c383030fe10c240eba8468add021c..c5d7aec296a7a44b2fedfd2532ad838f89654e6c 100644 (file)
--- a/afh.c
+++ b/afh.c
@@ -83,15 +83,16 @@ static void print_chunk_table(struct afh_info *afhi)
        }
 }
 
-static int cat_file(void *audio_file_data, struct afh_info *afhi)
+static int cat_file(struct afh_info *afhi, int audio_format_id,
+               void *audio_file_data, size_t audio_file_size)
 {
        int ret;
        struct timeval stream_start;
        long unsigned i, first_chunk, last_chunk;
        const char *buf;
+       char *header;
        size_t size;
 
-
        if (conf.begin_chunk_arg < 0) {
                if (-conf.begin_chunk_arg > afhi->chunks_total)
                        return -ERRNO_TO_PARA_ERROR(EINVAL);
@@ -114,14 +115,18 @@ static int cat_file(void *audio_file_data, struct afh_info *afhi)
                return -ERRNO_TO_PARA_ERROR(EINVAL);
        if (!afhi->chunks_total)
                return 1;
-       afh_get_header(afhi, audio_file_data, &buf, &size);
-       if (size && first_chunk && !conf.no_header_given) {
-               PARA_INFO_LOG("writing audio file header (%zu bytes)\n", size);
-               ret = write(STDOUT_FILENO, buf, size);
-               if (ret < 0)
-                       return ret;
-               if (ret != size)
-                       return -E_AFH_SHORT_WRITE;
+       if (first_chunk > 0 && !conf.no_header_given) {
+               afh_get_header(afhi, audio_format_id, audio_file_data, audio_file_size,
+                       &header, &size);
+               if (size > 0) {
+                       PARA_INFO_LOG("writing header (%zu bytes)\n", size);
+                       ret = write(STDOUT_FILENO, header, size); /* FIXME */
+                       afh_free_header(header, audio_format_id);
+                       if (ret < 0)
+                               return ret;
+                       if (ret != size)
+                               return -E_AFH_SHORT_WRITE;
+               }
        }
        PARA_NOTICE_LOG("writing chunks %lu - %lu\n", first_chunk, last_chunk);
        gettimeofday(&stream_start, NULL);
@@ -184,23 +189,25 @@ int main(int argc, char **argv)
                        fd, &afhi);
                if (ret < 0)
                        goto out;
+
                audio_format_num = ret;
                if (conf.stream_given)
-                       ret = cat_file(audio_file_data, &afhi);
+                       ret = cat_file(&afhi, audio_format_num,
+                               audio_file_data, audio_file_size);
                else {
                        printf("File %d: %s\n", i + 1, conf.inputs[i]);
                        print_info(audio_format_num, &afhi);
                        if (conf.chunk_table_given)
                                print_chunk_table(&afhi);
-                       free(afhi.techinfo);
-                       free(afhi.tags.artist);
-                       free(afhi.tags.title);
-                       free(afhi.tags.year);
-                       free(afhi.tags.album);
-                       free(afhi.tags.comment);
-                       free(afhi.chunk_table);
                        printf("\n");
                }
+               free(afhi.techinfo);
+               free(afhi.tags.artist);
+               free(afhi.tags.title);
+               free(afhi.tags.year);
+               free(afhi.tags.album);
+               free(afhi.tags.comment);
+               free(afhi.chunk_table);
                ret2 = para_munmap(audio_file_data, audio_file_size);
                if (ret2 < 0 && ret >= 0)
                        ret = ret2;
diff --git a/afh.h b/afh.h
index 8f74e236501189de420d1eec75a9a40b952b1707..8b747f8a436b0da18f3cd83a8e90c50e23e7ea83 100644 (file)
--- a/afh.h
+++ b/afh.h
  * for all supported audio formats.
  */
 struct taginfo {
-       /** TPE1 (id3v2) / ARTIST (vorbis) / ©ART (aac) */
+       /** TPE1 (id3v2) / ARTIST (vorbis) / ART (aac)/ author(spx) */
        char *artist;
-       /** TIT2/TITLE/©nam */
+       /** TIT2/TITLE/nam */
        char *title;
-       /** TDRC/YEAR/©day */
+       /** TDRC/YEAR/day */
        char *year;
-       /** TALB/ALBUM/©alb */
+       /** TALB/ALBUM/alb */
        char *album;
-       /** COMM/COMMENT/©cmt */
+       /** COMM/COMMENT/cmt */
        char *comment;
 };
 
@@ -42,11 +42,6 @@ struct afh_info {
        uint32_t *chunk_table;
        /** Period of time between sending data chunks. */
        struct timeval chunk_tv;
-       /**
-        * The position of the header within the audio file. Ignored if \a
-        * header_len equals zero.
-        */
-       uint32_t header_offset;
        /**
         * The header is needed by senders in case a new client connects in the
         * middle of the stream. The length of the header defaults to zero
@@ -95,6 +90,8 @@ struct audio_format_handler {
         */
        int (*get_file_info)(char *map, size_t numbytes, int fd,
                struct afh_info *afi);
+
+       void (*get_header)(void *map, size_t mapsize, char **buf, size_t *len);
 };
 
 void afh_init(void);
@@ -104,4 +101,7 @@ int compute_afhi(const char *path, char *data, size_t size,
 const char *audio_format_name(int);
 void afh_get_chunk(long unsigned chunk_num, struct afh_info *afhi,
                void *map, const char **buf, size_t *len);
-void afh_get_header(struct afh_info *afhi, void *map, const char **buf, size_t *len);
+uint32_t afh_get_largest_chunk_size(struct afh_info *afhi);
+void afh_get_header(struct afh_info *afhi, uint8_t audio_format_id,
+               void *map, size_t mapsize, char **buf, size_t *len);
+void afh_free_header(char *header_buf, uint8_t audio_format_id);
index dd2ae6507e7510da3d1e57c95e03cda51fbf74ca..7ecab4e47a9bd7e47bcc7e378043d62d663cf343 100644 (file)
@@ -160,7 +160,6 @@ int compute_afhi(const char *path, char *data, size_t size, int fd,
 {
        int ret, i, format;
 
-       afhi->header_offset = 0;
        afhi->header_len = 0;
        afhi->techinfo = NULL;
        afhi->tags.artist = NULL;
@@ -249,21 +248,52 @@ void afh_get_chunk(long unsigned chunk_num, struct afh_info *afhi,
  * Get the header of an audio file.
  *
  * \param afhi The audio file handler data describing the file.
+ * \param audio_format_id Determines the audio format handler.
  * \param map The data of the audio file.
+ * \param mapsize The amount of bytes of the mmapped audio file.
  * \param buf The length of the header is stored here.
  * \param len Points to a buffer containing the header on return.
  *
  * This function sets \a buf to \p NULL and \a len to zero if \a map or \a
  * afhi is \p NULL, or if the current audio format does not need special
  * header treatment.
+ *
+ * Otherwise, it is checked whether the audio format handler given by
+ * \a audio_format_id defines a ->get_header() method. If it does, this
+ * method is called to obtain the header. If ->get_header() is \p NULL,
+ * a reference to the first chunk of the audio file is returned.
+ *
+ * Once the header is no longer needed, the caller must call \ref
+ * afh_free_header() to free the resources allocated by this function.
  */
-void afh_get_header(struct afh_info *afhi, void *map, const char **buf, size_t *len)
+void afh_get_header(struct afh_info *afhi, uint8_t audio_format_id,
+               void *map, size_t mapsize, char **buf, size_t *len)
 {
+       struct audio_format_handler *afh = afl + audio_format_id;
+
        if (!map || !afhi || !afhi->header_len) {
                *buf = NULL;
                *len = 0;
                return;
        }
-       *len = afhi->header_len;
-       *buf = map + afhi->header_offset;
+       if (!afh->get_header) {
+               *len = afhi->header_len;
+               *buf = map;
+               return;
+       }
+       afh->get_header(map, mapsize, buf, len);
+}
+
+/**
+ * Deallocate any resources obtained from afh_get_header().
+ *
+ * \param header_buf Pointer obtained via afh_get_header().
+ * \param audio_format_id Determines the audio format handler.
+ */
+void afh_free_header(char *header_buf, uint8_t audio_format_id)
+{
+       struct audio_format_handler *afh = afl + audio_format_id;
+
+       if (afh->get_header)
+               free(header_buf);
 }
diff --git a/afs.c b/afs.c
index 2fb28b71eeabca63194400731ef19499b83806ca..0464eb77de8918f8b38d5a41c5a792212a271c5f 100644 (file)
--- a/afs.c
+++ b/afs.c
@@ -468,7 +468,6 @@ again:
        }
        ret = open_and_update_audio_file(aft_row, score, &afd);
        if (ret < 0) {
-               PARA_ERROR_LOG("%s\n", para_strerror(-ret));
                ret = score_delete(aft_row);
                if (ret < 0) {
                        PARA_ERROR_LOG("%s\n", para_strerror(-ret));
@@ -951,7 +950,7 @@ static void register_command_task(uint32_t cookie)
 
        ct->task.pre_select = command_pre_select;
        ct->task.post_select = command_post_select;
-       sprintf(ct->task.status, "command task");
+       sprintf(ct->task.status, "afs command task");
        register_task(&ct->task);
 }
 
diff --git a/afs.h b/afs.h
index 699998b03979abb33afa8eb9fae5db709ddffd2a..96da2da027cf27268c7b5ad1b4af6755b593f7e6 100644 (file)
--- a/afs.h
+++ b/afs.h
@@ -21,7 +21,7 @@ struct afs_info {
        uint32_t image_id;
        /** Lyrics blob associated with this file (foreign key). */
        uint32_t lyrics_id;
-       /** Mp3, ogg or aac. */
+       /** Mp3, ogg, aac, wma, spx. */
        uint8_t audio_format_id;
        /** Amplification value. */
        uint8_t amp;
@@ -131,6 +131,8 @@ struct audio_file_data {
        struct afh_info afhi;
        /** Size of the largest chunk. */
        uint32_t max_chunk_size;
+       /** Needed to get the audio file header. */
+       uint8_t audio_format_id;
 };
 
 /**
diff --git a/aft.c b/aft.c
index 412318b27eb656acabbb5c66faa352c8f56494c3..b3dde1379997bb6f69647255d0ac53fb703fce09 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -344,16 +344,16 @@ enum afhi_offsets {
        AFHI_BITRATE_OFFSET = 4,
        /** Position of the frequency. */
        AFHI_FREQUENCY_OFFSET = 8,
-       /** Location of the audio file header. */
-       AFHI_HEADER_OFFSET_OFFSET = 12,
+       /** Was: Location of the audio file header. */
+       AFHI_UNUSED1_OFFSET = 12,
        /* Length of the audio file header. Zero means: No header. */
        AFHI_HEADER_LEN_OFFSET = 16,
        /** The total number of chunks (4 bytes). */
        CHUNKS_TOTAL_OFFSET = 20,
        /** The length of the audio file header (4 bytes). */
        HEADER_LEN_OFFSET = 24,
-       /** The start of the audio file header (4 bytes). */
-       HEADER_OFFSET_OFFSET = 28,
+       /** Was: The start of the audio file header (4 bytes). */
+       AFHI_UNUSED2_OFFSET = 28,
        /** The seconds part of the chunk time (4 bytes). */
        CHUNK_TV_TV_SEC_OFFSET = 32,
        /** The microseconds part of the chunk time (4 bytes). */
@@ -388,12 +388,12 @@ static void save_afhi(struct afh_info *afhi, char *buf)
        write_u32(buf + AFHI_SECONDS_TOTAL_OFFSET, afhi->seconds_total);
        write_u32(buf + AFHI_BITRATE_OFFSET, afhi->bitrate);
        write_u32(buf + AFHI_FREQUENCY_OFFSET, afhi->frequency);
-       write_u32(buf + AFHI_HEADER_OFFSET_OFFSET, afhi->header_offset);
+       write_u32(buf + AFHI_UNUSED1_OFFSET, 0);
        write_u32(buf + AFHI_HEADER_LEN_OFFSET, afhi->header_len);
        write_u8(buf + AFHI_CHANNELS_OFFSET, afhi->channels);
        write_u32(buf + CHUNKS_TOTAL_OFFSET, afhi->chunks_total);
        write_u32(buf + HEADER_LEN_OFFSET, afhi->header_len);
-       write_u32(buf + HEADER_OFFSET_OFFSET, afhi->header_offset);
+       write_u32(buf + AFHI_UNUSED2_OFFSET, 0);
        write_u32(buf + CHUNK_TV_TV_SEC_OFFSET, afhi->chunk_tv.tv_sec);
        write_u32(buf + CHUNK_TV_TV_USEC_OFFSET, afhi->chunk_tv.tv_usec);
        p = buf + AFHI_INFO_STRING_OFFSET;
@@ -411,12 +411,10 @@ static void load_afhi(const char *buf, struct afh_info *afhi)
        afhi->seconds_total = read_u32(buf + AFHI_SECONDS_TOTAL_OFFSET);
        afhi->bitrate = read_u32(buf + AFHI_BITRATE_OFFSET);
        afhi->frequency = read_u32(buf + AFHI_FREQUENCY_OFFSET);
-       afhi->header_offset = read_u32(buf + AFHI_HEADER_OFFSET_OFFSET);
        afhi->header_len = read_u32(buf + AFHI_HEADER_LEN_OFFSET);
        afhi->channels = read_u8(buf + AFHI_CHANNELS_OFFSET);
        afhi->chunks_total = read_u32(buf + CHUNKS_TOTAL_OFFSET);
        afhi->header_len = read_u32(buf + HEADER_LEN_OFFSET);
-       afhi->header_offset = read_u32(buf + HEADER_OFFSET_OFFSET);
        afhi->chunk_tv.tv_sec = read_u32(buf + CHUNK_TV_TV_SEC_OFFSET);
        afhi->chunk_tv.tv_usec = read_u32(buf + CHUNK_TV_TV_USEC_OFFSET);
        afhi->techinfo = (char *)buf + AFHI_INFO_STRING_OFFSET;
@@ -1126,6 +1124,7 @@ int open_and_update_audio_file(struct osl_row *aft_row, long score,
        new_afsi.last_played = time(NULL);
        save_afsi(&new_afsi, &afsi_obj); /* in-place update */
 
+       afd->audio_format_id = old_afsi.audio_format_id;
        load_chunk_table(&afd->afhi, chunk_table_obj.data);
        ret = make_status_items(afd, &old_afsi, path, score, file_hash);
        if (ret < 0)
@@ -1137,6 +1136,8 @@ int open_and_update_audio_file(struct osl_row *aft_row, long score,
 err:
        free(afd->afhi.chunk_table);
        osl_close_disk_object(&chunk_table_obj);
+       if (ret < 0)
+               PARA_ERROR_LOG("%s: %s\n", path, para_strerror(-ret));
        return ret;
 }
 
index 8b17d95fba692db0b2dd9126226cb8fb2cb682d5..e66373cc87ed475682655a9dac17baec92144496 100644 (file)
--- a/audiod.c
+++ b/audiod.c
@@ -167,7 +167,7 @@ struct command_task {
  * \return The audio format number on success, -E_UNSUPPORTED_AUDIO_FORMAT if
  * \a name is not a supported audio format.
  */
-int get_audio_format_num(const char *name)
+static int get_audio_format_num(const char *name)
 {
        int i;
 
@@ -469,20 +469,6 @@ static int get_empty_slot(void)
        return -E_NO_MORE_SLOTS;
 }
 
-/**
- * get the number of filters
- *
- * \param audio_format_num the number identifying the audio format
- *
- * \return the number of filters for the given audio format
- *
- * \sa struct filter;
- */
-int num_filters(int audio_format_num)
-{
-       return afi[audio_format_num].num_filters;
-}
-
 static void open_filters(struct slot_info *s)
 {
        struct audio_format_info *a = afi + s->format;
index 7ffe98e7d249368992568f42dcb1bc816eb7afb5..759f19173c111ac3aeff55b660eefc1c8b1d58da 100644 (file)
@@ -14,7 +14,7 @@ H: on -> standby -> off -> on
 N: grab
 D: grab the audio stream
 L:
-U: -- grab [-m[{s|p|a}]] [-p=<parent>] [-n=<name>] [-o]
+U: -- grab [-m[{s|p|a}]] [-p=PARENT] [-n=NAME] [-o]
 H:
 H: grab ('splice') the audio stream at any position in the buffer
 H: tree and send that data back to the client.
@@ -35,7 +35,7 @@ H:    ready for writing (i.e. would block). Sloppy mode ignores
 H:     the write, pedantic mode aborts and aggressive mode tries
 H:     to write anyway.
 H:
-H: -p  Grab output of node <parent> of the buffer tree.
+H: -p  Grab output of node PARENT of the buffer tree.
 H:
 H: -n  Name of the new buffer tree node. Defaults to 'grab'.
 H:
index 94399602b22280afbe88304cad8d832349f26780..4c3212228ba5ad75dac7241d10c47ebdb0478652 100644 (file)
--- a/audiod.h
+++ b/audiod.h
@@ -7,9 +7,6 @@
 /** \file audiod.h symbols exported from audiod.c */
 
 
-int num_filters(int audio_format_num);
-int get_audio_format_num(const char *name);
-
 /** enum of audio formats supported by para_audiod */
 enum {AUDIOD_AUDIO_FORMATS_ENUM};
 
index f462016b2e572f6a58691362cb52c9bdb280ea91..5217f9b487cd260aebe5d5a986f4fd8e957b0270 100644 (file)
--- a/command.c
+++ b/command.c
@@ -255,7 +255,8 @@ int com_si(struct rc4_context *rc4c, int argc, __a_unused char * const * argv)
                free(info);
        }
        ut = uptime_str();
-       ret = rc4_send_va_buffer(rc4c, "up: %s\nplayed: %u\n"
+       ret = rc4_send_va_buffer(rc4c, "version: " GIT_VERSION "\n"
+               "up: %s\nplayed: %u\n"
                "server_pid: %d\n"
                "afs_pid: %d\n"
                "connections (active/accepted/total): %u/%u/%u\n"
@@ -743,24 +744,24 @@ __noreturn void handle_connect(int fd, const char *peername)
        /* we need a blocking fd here as recv() might return EAGAIN otherwise. */
        ret = mark_fd_blocking(fd);
        if (ret < 0)
-               goto err_out;
+               goto net_err;
        /* send Welcome message */
        ret = send_va_buffer(fd, "This is para_server, version "
                PACKAGE_VERSION  ".\n" );
        if (ret < 0)
-               goto err_out;
+               goto net_err;
        /* recv auth request line */
        ret = recv_buffer(fd, buf, sizeof(buf));
        if (ret < 0)
-               goto err_out;
+               goto net_err;
        if (ret < 10) {
                ret = -E_AUTH_REQUEST;
-               goto err_out;
+               goto net_err;
        }
        numbytes = ret;
        ret = -E_AUTH_REQUEST;
        if (strncmp(buf, AUTH_REQUEST_MSG, strlen(AUTH_REQUEST_MSG)))
-               goto err_out;
+               goto net_err;
        p = buf + strlen(AUTH_REQUEST_MSG);
        PARA_DEBUG_LOG("received auth request for user %s\n", p);
        ret = -E_BAD_USER;
@@ -770,7 +771,7 @@ __noreturn void handle_connect(int fd, const char *peername)
                ret = para_encrypt_buffer(u->rsa, rand_buf, sizeof(rand_buf),
                        (unsigned char *)buf);
                if (ret < 0)
-                       goto err_out;
+                       goto net_err;
                numbytes = ret;
        } else {
                /*
index f3a2d1333f457f2cae6c313456a7fe295a479279..e8b2118cdede3d2a1ebabbe751cbaf2b2b741cec 100644 (file)
@@ -133,7 +133,7 @@ server_errlist_objs="server afh_common mp3_afh vss command net string signal
        ipc dccp_send fd user_list chunk_queue afs aft mood score attribute
        blob playlist sha1 sched acl send_common udp_send color fec
        server_command_list afs_command_list wma_afh wma_common"
-server_ldflags="-losl"
+server_ldflags=""
 server_audio_formats="mp3 wma"
 
 write_cmdline_objs="add_cmdline(write file_write)"
@@ -268,7 +268,7 @@ else
        extras="$extras server"
        executables="$executables server"
        AC_SUBST(osl_cppflags)
-       server_ldflags="$server_ldflags -L$with_osl_libs"
+       server_ldflags="$server_ldflags $osl_libs -losl"
 fi
 CPPFLAGS="$OLD_CPPFLAGS"
 LDFLAGS="$OLD_LDFLAGS"
diff --git a/crypt.c b/crypt.c
index 917948c6185710fb828b441025b8d46a0fdc2924..cdcb6149d04254a0def3bcc903823f71ae3a89e5 100644 (file)
--- a/crypt.c
+++ b/crypt.c
@@ -203,6 +203,8 @@ int para_encrypt_buffer(RSA *rsa, unsigned char *inbuf,
        return ret < 0? -E_ENCRYPT : ret;
 }
 
+#define RC4_ALIGN 8
+
 /**
  * Encrypt and send a buffer.
  *
@@ -218,10 +220,16 @@ int rc4_send_bin_buffer(struct rc4_context *rc4c, const char *buf, size_t len)
 {
        int ret;
        unsigned char *tmp;
+       static unsigned char remainder[RC4_ALIGN];
+       size_t l1 = ROUND_DOWN(len, RC4_ALIGN), l2 = ROUND_UP(len, RC4_ALIGN);
 
        assert(len);
-       tmp = para_malloc(len + 8);
-       RC4(&rc4c->send_key, len, (const unsigned char *)buf, tmp);
+       tmp = para_malloc(l2);
+       RC4(&rc4c->send_key, l1, (const unsigned char *)buf, tmp);
+       if (len > l1) {
+               memcpy(remainder, buf + l1, len - l1);
+               RC4(&rc4c->send_key, len - l1, remainder, tmp + l1);
+       }
        ret = write_all(rc4c->fd, (char *)tmp, &len);
        free(tmp);
        return ret;
diff --git a/error.h b/error.h
index 3dfee0dda071d56462fc2ab93d81390bc6002c3c..5a2e39b468fa58d7cb66bc3ca07f71012b02c2e2 100644 (file)
--- a/error.h
+++ b/error.h
@@ -351,6 +351,8 @@ extern const char **para_errlist[];
 
 #define OGG_AFH_ERRORS \
        PARA_ERROR(VORBIS, "vorbis synthesis header-in error (not vorbis?)"), \
+       PARA_ERROR(OGG_PACKET_IN, "ogg_stream_packetin() failed"), \
+       PARA_ERROR(OGG_STREAM_FLUSH, "ogg_stream_flush() failed"), \
 
 
 #define VSS_ERRORS \
diff --git a/fade.c b/fade.c
index 8eeb79e7d3f335b08ed1d2b8f3606e2fdec4cd6d..5fbd0dd48027ad990345aa5d8f86fa0d952e6188 100644 (file)
--- a/fade.c
+++ b/fade.c
@@ -125,6 +125,7 @@ static void fixup_mixer_channel_arg(void)
                case mixer_channel_arg_reclev: val = SOUND_MIXER_RECLEV; break;
                case mixer_channel_arg_igain: val = SOUND_MIXER_IGAIN; break;
                case mixer_channel_arg_ogain: val = SOUND_MIXER_OGAIN; break;
+               default: break;
        }
        conf.mixer_channel_arg = val;
 }
@@ -344,15 +345,15 @@ int main(int argc, char *argv[])
        }
        fixup_mixer_channel_arg();
        switch (conf.mode_arg) {
-       case mode_arg_sleep:
-               ret = sweet_dreams();
-               break;
        case mode_arg_fade:
                ret = fade(conf.fade_vol_arg, conf.fade_time_arg);
                break;
        case mode_arg_snooze:
                ret = snooze();
                break;
+       default: /* sleep mode */
+               ret = sweet_dreams();
+               break;
        }
        if (ret < 0)
                PARA_EMERG_LOG("%s\n", para_strerror(-ret));
index ffd714f7c7c36a085e24d20e2ecd0a680af0406a..45d9c9ba8dcf1497001014a6fa06841c427d08be 100644 (file)
@@ -23,3 +23,4 @@
 # endif
 
 #define _static_inline_ static inline
+
index 289917c3fddfb96debfd9e8425b005b97276b532..2659b93af07006787b4e1731c4349d94d594d285 100644 (file)
@@ -136,22 +136,23 @@ option "no_default_filters" D
 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 "Configure filters manually"
 flag off
-details="
+details = "
        If (and only if) this option is set, the --filter options
-       (see below) take effect. Otherwise, the compiled-in default
-       filters mp3dec, oggdec and aacdec are activated for mp3, ogg,
-       aac streams respectively.
-
-       You have to configure filters manually if you want to use
-       the amp filter or the compress filter which are not activated
-       by default.
-
-       Playing udp streams also requires that the output of the udp
-       receiver must be fed into the fecdec filter first to produce
-       a stream which can be decoded by the appropriate decoder
-       (mp3dec, oggdec, aacdec, wmadec). In other words, the fecdec
-       filter should be specified as the first filter of the filter
-       configuration for udp streaming.
+       (see below) take effect. Otherwise, the compiled-in defaults
+       apply.  These defaults depend on the receiver being used as
+       described below.
+
+       For http streams, only a single filter per audio format,
+       the decoder for that format, is activated. On the other hand,
+       since udp and dccp streams are sent fec-encoded by para_server,
+       the client side must feed the output of the receiver into
+       the fecdec filter first. Therefore the default for udp and
+       dccp streams is to activate the fecdec filter, followed by
+       the appropriate decoder.
+
+       You must give this option if you want to use any other filter,
+       for example the amp or the compress filter.
+
 "
 
 option "filter" f
diff --git a/gui.c b/gui.c
index eba1e2a59331564a40677a123d1220dc9120c059..38addd9815cc5bf2775c80278679a1e9c64e872e 100644 (file)
--- a/gui.c
+++ b/gui.c
@@ -400,11 +400,13 @@ static int draw_top_rbe(unsigned *lines)
        rbe = ringbuffer_get(bot_win_rb, fvr);
        if (!rbe)
                return -1;
-       /* first rbe might be only partially visible */
-       offset = (*lines - bot.lines) * bot.cols;
        len = strlen(rbe->msg);
-       if (offset < 0 || len < offset)
-               return -1;
+       if (*lines > bot.lines) {
+               /* first rbe is only partially visible */
+               offset = (*lines - bot.lines) * bot.cols;
+               assert(offset <= len);
+       } else
+               offset = 0;
        wattron(bot.win, COLOR_PAIR(rbe->color));
        waddstr(bot.win, rbe->msg + offset);
        *lines = NUM_LINES(len - offset);
index ef42c497062c228ddab10497c3388ffa2b8de90b..144a2690bf80da24d298ab2bb56c5403835157dc 100644 (file)
--- a/ogg_afh.c
+++ b/ogg_afh.c
@@ -21,7 +21,7 @@ struct private_vorbis_data {
 };
 
 static int vorbis_packet_callback(ogg_packet *packet, int packet_num,
-               struct afh_info *afhi, void *private_data)
+               __a_unused int serial, struct afh_info *afhi, void *private_data)
 {
        struct private_vorbis_data *pvd = private_data;
 
@@ -65,6 +65,99 @@ static int ogg_vorbis_get_file_info(char *map, size_t numbytes, __a_unused int f
        return ret;
 }
 
+struct vorbis_get_header_data {
+       ogg_stream_state os;
+       char *buf;
+       size_t len;
+};
+
+static void add_ogg_page(ogg_page *og, struct vorbis_get_header_data *vghd)
+{
+       size_t old_len = vghd->len;
+       size_t new_len = vghd->len + og->header_len + og->body_len;
+       char *buf = para_realloc(vghd->buf, new_len), *p = buf + old_len;
+
+       memcpy(p, og->header, og->header_len);
+       memcpy(p + og->header_len, og->body, og->body_len);
+       vghd->buf = buf;
+       vghd->len = new_len;
+       PARA_DEBUG_LOG("header/body/old/new: %lu/%lu/%zu/%zu\n",
+               og->header_len, og->body_len, old_len, new_len);
+}
+
+static int vorbis_get_header_callback(ogg_packet *packet, int packet_num,
+               int serial, __a_unused struct afh_info *afhi, void *private_data)
+{
+       int ret;
+       struct vorbis_get_header_data *vghd = private_data;
+       ogg_page og;
+       static unsigned char dummy_packet[] = {
+               0x03,
+               'v', 'o', 'r', 'b', 'i', 's',
+               0x06, 0x00, 0x00, 0x00,
+               'd', 'u', 'm', 'm', 'y', '\0',
+               0x00, 0x00, 0x00, 0x00, /* no comment :) */
+               0xff /* framing bit */
+       };
+
+       PARA_DEBUG_LOG("processing ogg packet #%d\n", packet_num);
+       if (packet_num > 2)
+               return 0;
+       if (packet_num == 0) {
+               ogg_stream_init(&vghd->os, serial);
+               ret = -E_OGG_PACKET_IN;
+               ret = ogg_stream_packetin(&vghd->os, packet);
+               if (ret < 0)
+                       goto out;
+               ret = -E_OGG_STREAM_FLUSH;
+               if (ogg_stream_flush(&vghd->os, &og) == 0)
+                       goto out;
+               add_ogg_page(&og, vghd);
+               return 1;
+       }
+       if (packet_num == 1) {
+               PARA_INFO_LOG("replacing metadata packet\n");
+               ogg_packet replacement = *packet;
+               replacement.packet = dummy_packet;
+               replacement.bytes = sizeof(dummy_packet);
+               ret = ogg_stream_packetin(&vghd->os, &replacement);
+               if (ret >= 0)
+                       return 1;
+               ret = -E_OGG_PACKET_IN;
+               goto out;
+       }
+       ret = -E_OGG_PACKET_IN;
+       if (ogg_stream_packetin(&vghd->os, packet) < 0)
+               goto out;
+       while (ogg_stream_flush(&vghd->os, &og))
+               add_ogg_page(&og, vghd);
+       ret = 0;
+out:
+       ogg_stream_clear(&vghd->os);
+       return ret;
+}
+
+static void vorbis_get_header(void *map, size_t mapsize, char **buf,
+               size_t *len)
+{
+       int ret;
+       struct vorbis_get_header_data vghd = {.len = 0};
+       struct ogg_afh_callback_info cb = {
+               .packet_callback = vorbis_get_header_callback,
+               .private_data = &vghd,
+       };
+
+       ret = ogg_get_file_info(map, mapsize, NULL, &cb);
+       if (ret < 0)
+               goto fail;
+       *buf = vghd.buf;
+       *len = vghd.len;
+       PARA_INFO_LOG("created %zu byte ogg vorbis header\n", *len);
+       return;
+fail:
+       PARA_ERROR_LOG("%s\n", para_strerror(-ret));
+}
+
 static const char* ogg_suffixes[] = {"ogg", NULL};
 
 /**
@@ -74,6 +167,7 @@ static const char* ogg_suffixes[] = {"ogg", NULL};
  */
 void ogg_init(struct audio_format_handler *afh)
 {
-       afh->get_file_info = ogg_vorbis_get_file_info,
+       afh->get_file_info = ogg_vorbis_get_file_info;
+       afh->get_header = vorbis_get_header;
        afh->suffixes = ogg_suffixes;
 }
index 72fab7c14db9caeb8e5459dbead0798fb2e46c67..cb59d36383a104836bbff4ef59f233f464ae4743 100644 (file)
@@ -37,13 +37,16 @@ static int process_packets_2_and_3(ogg_sync_state *oss,
                         * apparent at packetout.
                         */
                        ogg_stream_pagein(stream, &page);
+                       PARA_INFO_LOG("ogg page serial: %d\n",
+                               ogg_page_serialno(&page));
                        while (i < 2) {
                                ret = ogg_stream_packetout(stream, &packet);
                                if (ret == 0)
                                        break;
                                if (ret < 0)
                                        return -E_STREAM_PACKETOUT;
-                               ret = ci->packet_callback(&packet, i + 1, afhi,
+                               ret = ci->packet_callback(&packet, i + 1,
+                                       ogg_page_serialno(&page), afhi,
                                        ci->private_data);
                                if (ret < 0)
                                        return ret;
@@ -77,14 +80,13 @@ static int process_ogg_packets(ogg_sync_state *oss, struct afh_info *afhi,
        ret = -E_STREAM_PACKETOUT;
        if (ogg_stream_packetout(&stream, &packet) != 1)
                goto out;
-       ret = ci->packet_callback(&packet, 0, afhi, ci->private_data);
+       ret = ci->packet_callback(&packet, 0, ogg_page_serialno(&page),
+               afhi, ci->private_data);
        if (ret < 0)
                goto out;
        ret = process_packets_2_and_3(oss, &stream, afhi, ci);
        if (ret < 0)
                goto out;
-       afhi->header_offset = 0;
-       afhi->header_len = oss->returned;
        ret = 1;
 out:
        ogg_stream_clear(&stream);
@@ -109,9 +111,9 @@ static void set_chunk_tv(int frames_per_chunk, int frequency,
  * given by \a map and \a numbytes and passes each packet to the callback
  * defined by \a ci.
  *
- * If the packet callback indicates success, the chunk table is built.  Chunk
- * zero contains the first three ogg packets while all other chunks consist of
- * exactly one ogg page.
+ * If the packet callback indicates success and \a afhi is not \p NULL, the
+ * chunk table is built. Chunk zero contains the first three ogg packets while
+ * all other chunks consist of exactly one ogg page.
  *
  * \param map Audio file data.
  * \param numbytes The length of \a map.
@@ -142,6 +144,9 @@ int ogg_get_file_info(char *map, size_t numbytes, struct afh_info *afhi,
        ret = process_ogg_packets(&oss, afhi, ci);
        if (ret < 0)
                goto out;
+       if (!afhi)
+               goto out;
+       afhi->header_len = oss.returned;
        oss.returned = 0;
        oss.fill = numbytes;
        /* count ogg pages and get duration of the file */
index 01f8d6c532fb93a37231286ed66da7cf09eb5530..89c8268b1fa0335bf98675c89135a7d1531a9630 100644 (file)
@@ -24,7 +24,7 @@ struct ogg_afh_callback_info {
          * reached and no further ogg packets should be processed.
          */
        int (*packet_callback)(ogg_packet *packet, int packet_num,
-               struct afh_info *afhi, void *private_data);
+               int serial, struct afh_info *afhi, void *private_data);
        /** Vorbis/speex specific data. */
        void *private_data;
 };
diff --git a/para.h b/para.h
index c5e12fe6da3ef864bdc16bb0eaa178a8b5965cee..29c5c2b89c4ac3e0ca820c26c07cd8be4755f266 100644 (file)
--- a/para.h
+++ b/para.h
@@ -165,13 +165,38 @@ _static_inline_ long int para_random(unsigned max)
        return ((max + 0.0) * (random() / (RAND_MAX + 1.0)));
 }
 
+/** Round up x to next multiple of y. */
+#define ROUND_UP(x, y) ({ \
+       const typeof(y) _divisor = y; \
+       ((x) + _divisor - 1) / _divisor * _divisor; })
+
+/** Round down x to multiple of y. */
+#define ROUND_DOWN(x, y) ({ \
+       const typeof(y) _divisor = y; \
+       (x) / _divisor * _divisor; })
+
 /** Divide and round up to next integer. */
 #define DIV_ROUND_UP(x, y) ({ \
        typeof(y) _divisor = y; \
        ((x) + _divisor - 1) / _divisor; })
 
+/**
+ * Assert a build-time dependency, as an expression.
+ *
+ * \param cond The compile-time condition which must be true.
+ *
+ * Compilation will fail if the condition isn't true, or can't be evaluated by
+ * the compiler. This can be used in an expression: its value is "0".
+ *
+ * Taken from ccan.
+ */
+#define EXPR_BUILD_ASSERT(cond) (sizeof(char [1 - 2 * !(cond)]) - 1)
+
+/* &a[0] degrades to a pointer: a different type from an array */
+#define _array_size_chk(arr) EXPR_BUILD_ASSERT(\
+       !__builtin_types_compatible_p(typeof(arr), typeof(&(arr)[0])))
 /** Get the size of an array */
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + _array_size_chk(arr))
 
 /**
  * Wrapper for isspace.
diff --git a/score.c b/score.c
index 27fec711047f230c96215be2d90def9db3320bbe..f5fe4a833f6f6f99ca3d9afca49175113b1eac78 100644 (file)
--- a/score.c
+++ b/score.c
@@ -38,8 +38,8 @@ static int ptr_compare(const struct osl_object *obj1, const struct osl_object *o
  */
 static int score_compare(const struct osl_object *obj1, const struct osl_object *obj2)
 {
-       int d1 = *(int*)obj1->data;
-       int d2 = *(int*)obj2->data;
+       long d1 = *(long *)obj1->data;
+       long d2 = *(long *)obj2->data;
        int ret = NUM_COMPARE(d2, d1);
 
        if (ret)
@@ -141,7 +141,7 @@ int score_add(const struct osl_row *aft_row, long score)
        size = score_table_desc.column_descriptions[SCORECOL_SCORE].data_size;
        score_objs[SCORECOL_SCORE].data = para_malloc(size);
        score_objs[SCORECOL_SCORE].size = size;
-       *(int *)(score_objs[SCORECOL_SCORE].data) = score;
+       *(long *)(score_objs[SCORECOL_SCORE].data) = score;
 
 //     PARA_DEBUG_LOG("adding %p\n", *(void **) (score_objs[SCORECOL_AFT_ROW].data));
        ret = osl(osl_add_row(score_table, score_objs));
index 849b707a43043a501ab92cadbed6af66f725a139..35d6f19137b3a881482df4e65c3945d6bcdb8a78 100644 (file)
--- a/server.c
+++ b/server.c
@@ -426,6 +426,7 @@ static void init_server_command_task(int argc, char **argv)
        if (ret < 0)
                goto err;
        add_close_on_fork_list(sct->listen_fd); /* child doesn't need the listener */
+       sprintf(sct->task.status, "server command task");
        register_task(&sct->task);
        return;
 err:
index 6414f4c4ebba4fda67b7d64a32d570b50ba0436d..e693c4150e03b7dae9b991c343ec7abbfe980db0 100644 (file)
--- a/spx_afh.c
+++ b/spx_afh.c
@@ -139,7 +139,8 @@ static int spx_get_comments(unsigned char *comments, int length,
 static const char* speex_suffixes[] = {"spx", "speex", NULL};
 
 static int spx_packet_callback(ogg_packet *packet, int packet_num,
-               struct afh_info *afhi, void *private_data)
+               __a_unused int serial, struct afh_info *afhi,
+               void *private_data)
 {
        struct private_spx_data *psd = private_data;
        int ret;
diff --git a/stdin.h b/stdin.h
index 2d279a6eada30d55efe51fce50798fdaf4700239..32a4c281b8326c6705c41d5e67c44c9e09de3434 100644 (file)
--- a/stdin.h
+++ b/stdin.h
@@ -12,7 +12,7 @@ struct stdin_task {
        struct task task;
        /** Stdin is always the root of a buffer tree. */
        struct btr_node *btrn;
-       /* Use a buffer pool to minimize memcpy due to alignment problems. */
+       /** Use a buffer pool to minimize memcpy due to alignment problems. */
        struct btr_pool *btrp;
 };
 
diff --git a/vss.c b/vss.c
index 916a71d518762f63675c65c195f87b6fdce089e1..ba6f7c4c655134d11d79e6411ab92d63b4efd160 100644 (file)
--- a/vss.c
+++ b/vss.c
@@ -86,7 +86,7 @@ struct vss_task {
        /** Used by the scheduler. */
        struct task task;
        /** Pointer to the header of the mapped audio file. */
-       const char *header_buf;
+       char *header_buf;
        /** Length of the audio file header. */
        size_t header_len;
        /** Time between audio file headers are sent. */
@@ -167,6 +167,8 @@ struct fec_client {
        struct timeval next_header_time;
        /** Used for the last source pointer of an audio file. */
        unsigned char *extra_src_buf;
+       /** Needed for the last slice of the audio file header. */
+       unsigned char *extra_header_buf;
        /** Extra slices needed to store largest chunk + header. */
        int num_extra_slices;
        /** Contains the FEC-encoded data. */
@@ -211,10 +213,11 @@ static void write_fec_header(struct fec_client *fc, struct vss_task *vsst)
        write_u32(buf + 14, g->bytes);
 
        write_u8(buf + 18, fc->current_slice_num);
+       write_u8(buf + 19, 0); /* unused */
        write_u16(buf + 20, g->slice_bytes);
        write_u8(buf + 22, g->first_chunk? 0 : 1);
        write_u8(buf + 23, vsst->header_len? 1 : 0);
-       memset(buf + 24, 0, 7);
+       memset(buf + 24, 0, 8);
 }
 
 static bool need_audio_header(struct fec_client *fc, struct vss_task *vsst)
@@ -326,6 +329,7 @@ static int initialize_fec_client(struct fec_client *fc, struct vss_task *vsst)
        fc->src_data = para_realloc(fc->src_data, k * sizeof(char *));
        fc->enc_buf = para_realloc(fc->enc_buf, fc->mps);
        fc->extra_src_buf = para_realloc(fc->extra_src_buf, fc->mps);
+       fc->extra_header_buf = para_realloc(fc->extra_header_buf, fc->mps);
 
        fc->state = FEC_STATE_READY_TO_RUN;
        fc->next_header_time.tv_sec = 0;
@@ -334,6 +338,26 @@ static int initialize_fec_client(struct fec_client *fc, struct vss_task *vsst)
        return 1;
 }
 
+static void vss_get_chunk(int chunk_num, struct vss_task *vsst,
+               char **buf, size_t *sz)
+{
+       /*
+        * Chunk zero is special for header streams: It is the first portion of
+        * the audio file which consists of the audio file header. It may be
+        * arbitrary large due to embedded meta data. Audio format handlers may
+        * replace the header by a stripped one with meta data omitted which is
+        * of bounded size. We always use the stripped header for streaming
+        * rather than the unmodified header (chunk zero).
+        */
+       if (chunk_num == 0 && vsst->header_len > 0) {
+               *buf = vsst->header_buf; /* stripped header */
+               *sz = vsst->header_len;
+               return;
+       }
+       afh_get_chunk(chunk_num, &mmd->afd.afhi, vsst->map, (const char **)buf,
+               sz);
+}
+
 static void compute_group_size(struct vss_task *vsst, struct fec_group *g,
                int max_bytes)
 {
@@ -348,7 +372,7 @@ static void compute_group_size(struct vss_task *vsst, struct fec_group *g,
         * of exactly one chunk for these audio formats.
         */
        for (i = 0;; i++) {
-               const char *buf;
+               char *buf;
                size_t len;
                int chunk_num = g->first_chunk + i;
 
@@ -356,7 +380,7 @@ static void compute_group_size(struct vss_task *vsst, struct fec_group *g,
                        break;
                if (chunk_num >= mmd->afd.afhi.chunks_total) /* eof */
                        break;
-               afh_get_chunk(chunk_num, &mmd->afd.afhi, vsst->map, &buf, &len);
+               vss_get_chunk(chunk_num, vsst, &buf, &len);
                if (g->bytes + len > max_bytes)
                        break;
                /* Include this chunk */
@@ -478,7 +502,7 @@ static int setup_next_fec_group(struct fec_client *fc, struct vss_task *vsst)
 {
        int ret, i, k, n, data_slices;
        size_t len;
-       const char *buf;
+       char *buf;
        struct fec_group *g = &fc->group;
 
        if (fc->state == FEC_STATE_NONE) {
@@ -515,22 +539,36 @@ static int setup_next_fec_group(struct fec_client *fc, struct vss_task *vsst)
        fc->current_slice_num = 0;
        if (g->num == 0)
                set_group_timing(fc, vsst);
-
        /* setup header slices */
        buf = vsst->header_buf;
        for (i = 0; i < g->num_header_slices; i++) {
-               fc->src_data[i] = (const unsigned char *)buf;
-               buf += g->slice_bytes;
+               if (buf + g->slice_bytes <= vsst->header_buf + vsst->header_len) {
+                       fc->src_data[i] = (const unsigned char *)buf;
+                       buf += g->slice_bytes;
+                       continue;
+               }
+               /*
+                * Can not use vss->header_buf for this slice as it
+                * goes beyond the buffer. This slice will not be fully
+                * used.
+                */
+               uint32_t payload_size = vsst->header_buf
+                       + vsst->header_len - buf;
+               memcpy(fc->extra_header_buf, buf, payload_size);
+               if (payload_size < g->slice_bytes)
+                       memset(fc->extra_header_buf + payload_size, 0,
+                               g->slice_bytes - payload_size);
+               fc->src_data[i] = fc->extra_header_buf;
+               assert(i == g->num_header_slices - 1);
        }
 
        /* setup data slices */
-       afh_get_chunk(g->first_chunk, &mmd->afd.afhi, vsst->map, &buf, &len);
+       vss_get_chunk(g->first_chunk, vsst, &buf, &len);
        for (; i < g->num_header_slices + data_slices; i++) {
                if (buf + g->slice_bytes > vsst->map + mmd->size) {
                        /*
                         * Can not use the memory mapped audio file for this
-                        * slice as it goes beyond the map. This slice will not
-                        * be fully used.
+                        * slice as it goes beyond the map.
                         */
                        uint32_t payload_size = vsst->map + mmd->size - buf;
                        memcpy(fc->extra_src_buf, buf, payload_size);
@@ -626,6 +664,7 @@ void vss_del_fec_client(struct fec_client *fc)
        free(fc->src_data);
        free(fc->enc_buf);
        free(fc->extra_src_buf);
+       free(fc->extra_header_buf);
        fec_free(fc->parms);
        free(fc);
 }
@@ -806,6 +845,8 @@ static void vss_eof(struct vss_task *vsst)
        if (mmd->new_vss_status_flags & VSS_NOMORE)
                mmd->new_vss_status_flags = VSS_NEXT;
        set_eof_barrier(vsst);
+       afh_free_header(vsst->header_buf, mmd->afd.audio_format_id);
+       vsst->header_buf = NULL;
        para_munmap(vsst->map, mmd->size);
        vsst->map = NULL;
        mmd->chunks_sent = 0;
@@ -984,8 +1025,8 @@ static void recv_afs_result(struct vss_task *vsst, fd_set *rfds)
        mmd->events++;
        mmd->num_played++;
        mmd->new_vss_status_flags &= (~VSS_NEXT);
-       afh_get_header(&mmd->afd.afhi, vsst->map, &vsst->header_buf,
-               &vsst->header_len);
+       afh_get_header(&mmd->afd.afhi, mmd->afd.audio_format_id,
+               vsst->map, mmd->size, &vsst->header_buf, &vsst->header_len);
        return;
 err:
        free(mmd->afd.afhi.chunk_table);
@@ -1041,7 +1082,7 @@ static void vss_send(struct vss_task *vsst)
        compute_chunk_time(mmd->chunks_sent, &mmd->afd.afhi.chunk_tv,
                &mmd->stream_start, &due);
        if (tv_diff(&due, now, NULL) <= 0) {
-               const char *buf;
+               char *buf;
                size_t len;
 
                if (!mmd->chunks_sent) {
@@ -1054,8 +1095,7 @@ static void vss_send(struct vss_task *vsst)
                 * they might have still some data queued which can be sent in
                 * this case.
                 */
-               afh_get_chunk(mmd->current_chunk, &mmd->afd.afhi, vsst->map,
-                       &buf, &len);
+               vss_get_chunk(mmd->current_chunk, vsst, &buf, &len);
                for (i = 0; senders[i].name; i++) {
                        if (!senders[i].send)
                                continue;
@@ -1146,5 +1186,6 @@ void init_vss_task(int afs_socket)
                tv_add(&vsst->autoplay_barrier, &vsst->announce_tv,
                        &vsst->data_send_barrier);
        }
+       sprintf(vsst->task.status, "vss task");
        register_task(&vsst->task);
 }
index 9b7d85b3fd7d059c34476419841af8e9d3da42a1..255342dca56d4f8b8ff5a7bea199b78c76c5e55d 100644 (file)
--- a/wma_afh.c
+++ b/wma_afh.c
@@ -257,7 +257,6 @@ static int wma_get_file_info(char *map, size_t numbytes, __a_unused int fd,
        afhi->frequency = ahi.sample_rate;
        afhi->channels = ahi.channels;
        afhi->header_len = ahi.header_len;
-       afhi->header_offset = 0;
        wma_make_chunk_table(map + ahi.header_len, numbytes - ahi.header_len,
                ahi.block_align, afhi);
        read_asf_tags(map, ahi.header_len, &afhi->tags);