X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=spx_afh.c;h=e23236470a3efdafb01b1179e49817f79427f40f;hp=6414f4c4ebba4fda67b7d64a32d570b50ba0436d;hb=41d12a1e75017848620bd3670d9863aea63b62fb;hpb=a365b8263a0d7a1673699bdf454677c95b38eb95 diff --git a/spx_afh.c b/spx_afh.c index 6414f4c4..e2323647 100644 --- a/spx_afh.c +++ b/spx_afh.c @@ -1,8 +1,4 @@ -/* - * Copyright (C) 2010-2011 Andre Noll - * - * Licensed under the GPL v2. For licencing details see COPYING. - */ +/* Copyright (C) 2010 Andre Noll , see file COPYING. */ /* This file is based on speexdec.c, by Jean-Marc Valin, see below. */ @@ -38,7 +34,6 @@ */ /** \file spx_afh.c Audio format handler for ogg/speex files. */ -#include #include #include #include @@ -57,31 +52,14 @@ struct private_spx_data { struct spx_header_info shi; }; - -static char *copy_comment(const char *src, int len) -{ - char *p = para_malloc(len + 1); - - if (len > 0) - memcpy(p, src, len); - p[len] = '\0'; - PARA_DEBUG_LOG("%s\n", p); - return p; -} - static bool copy_if_tag_type(const char *tag, int taglen, const char *type, char **p) { - int len = strlen(type); - - if (taglen <= len) - return false; - if (strncasecmp(tag, type, len)) - return false; - if (tag[len] != '=') + char *q = key_value_copy(tag, taglen, type); + if (!q) return false; free(*p); - *p = copy_comment(tag + len + 1, taglen - len - 1); + *p = q; return true; } @@ -100,13 +78,13 @@ static int spx_get_comments(unsigned char *comments, int length, c += 4; if (c + len > end) return -E_SPX_COMMENT; - tags->comment = copy_comment(c, len); + tags->comment = safe_strdup(c, len); c += len; if (c + 4 > end) return -E_SPX_COMMENT; nb_fields = read_u32(c); - PARA_DEBUG_LOG("%d comment(s)\n", nb_fields); + PARA_DEBUG_LOG("%u comment(s)\n", nb_fields); c += 4; for (i = 0; i < nb_fields; i++, c += len) { char *tag; @@ -129,17 +107,16 @@ static int spx_get_comments(unsigned char *comments, int length, continue; if (copy_if_tag_type(c, len, "comment", &tags->comment)) continue; - tag = copy_comment(c, len); + tag = safe_strdup(c, len); PARA_NOTICE_LOG("unrecognized comment: %s\n", tag); free(tag); } return 1; } -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; @@ -171,15 +148,105 @@ static int spx_get_file_info(char *map, size_t numbytes, __a_unused int fd, struct afh_info *afhi) { struct private_spx_data psd; - struct ogg_afh_callback_info spx_callback_info = { + struct oac_callback_info spx_callback_info = { .packet_callback = spx_packet_callback, .private_data = &psd, }; memset(&psd, 0, sizeof(psd)); - return ogg_get_file_info(map, numbytes, afhi, &spx_callback_info); + return oac_get_file_info(map, numbytes, afhi, &spx_callback_info); } +static size_t spx_make_meta_packet(struct taginfo *tags, char **result) +{ + size_t sz; + char *buf, *p; + size_t comment_len = strlen(tags->comment), + artist_len = strlen(tags->artist), + title_len = strlen(tags->title), + album_len = strlen(tags->album), + year_len = strlen(tags->year); + uint32_t comment_sz = comment_len, + artist_sz = artist_len + strlen("artist="), + title_sz = title_len + strlen("title="), + album_sz = album_len + strlen("album="), + year_sz = year_len + strlen("year="); + uint32_t num_tags; + + sz = 4 /* comment length (always present) */ + + comment_sz + + 4; /* number of tags */ + num_tags = 0; + if (artist_len) { + num_tags++; + sz += 4 + artist_sz; + } + if (title_len) { + num_tags++; + sz += 4 + title_sz; + } + if (album_len) { + num_tags++; + sz += 4 + album_sz; + } + if (year_len) { + num_tags++; + sz += 4 + year_sz; + } + PARA_DEBUG_LOG("meta packet size: %zu bytes\n", sz); + /* terminating zero byte for the last sprintf() */ + buf = p = para_malloc(sz + 1); + write_u32(p, comment_sz); + p += 4; + strcpy(p, tags->comment); + p += comment_sz; + write_u32(p, num_tags); + p += 4; + if (artist_len) { + write_u32(p, artist_sz); + p += 4; + sprintf(p, "artist=%s", tags->artist); + p += artist_sz; + } + if (title_len) { + write_u32(p, title_sz); + p += 4; + sprintf(p, "title=%s", tags->title); + p += title_sz; + } + if (album_len) { + write_u32(p, album_sz); + p += 4; + sprintf(p, "album=%s", tags->album); + p += album_sz; + } + if (year_len) { + write_u32(p, year_sz); + p += 4; + sprintf(p, "year=%s", tags->year); + p += year_sz; + } + assert(p == buf + sz); + *result = buf; + return sz; +} + +static int spx_rewrite_tags(const char *map, size_t mapsize, + struct taginfo *tags, int output_fd, + __a_unused const char *filename) +{ + char *meta_packet; + size_t meta_sz; + int ret; + + meta_sz = spx_make_meta_packet(tags, &meta_packet); + ret = oac_rewrite_tags(map, mapsize, output_fd, meta_packet, meta_sz); + free(meta_packet); + return ret; +} + +static const char * const speex_suffixes[] = {"spx", "speex", NULL}; + /** * The init function of the ogg/speex audio format handler. * @@ -189,4 +256,5 @@ void spx_afh_init(struct audio_format_handler *afh) { afh->get_file_info = spx_get_file_info, afh->suffixes = speex_suffixes; + afh->rewrite_tags = spx_rewrite_tags; }