# HG changeset patch # User nenolod # Date 1159847697 25200 # Node ID 722fd456ae1a3eff26914154bf739896595b0276 # Parent 096db10ce25f1e222e30e18e8f8fe4dd47ef93a0 [svn] - parse metadata on ALAC files... seems to work, but the method is inefficient diff -r 096db10ce25f -r 722fd456ae1a ChangeLog --- a/ChangeLog Mon Oct 02 19:55:45 2006 -0700 +++ b/ChangeLog Mon Oct 02 20:54:57 2006 -0700 @@ -1,3 +1,13 @@ +2006-10-03 02:55:45 +0000 William Pitcock + revision [156] + - a few concurrency fixes + + trunk/src/alac/demux.c | 30 +++++++++++++++++++++++++++++- + trunk/src/alac/demux.h | 6 +++--- + trunk/src/alac/plugin.c | 8 ++++---- + 3 files changed, 36 insertions(+), 8 deletions(-) + + 2006-10-03 01:14:15 +0000 William Pitcock revision [154] - thread safety diff -r 096db10ce25f -r 722fd456ae1a src/alac/demux.c --- a/src/alac/demux.c Mon Oct 02 19:55:45 2006 -0700 +++ b/src/alac/demux.c Mon Oct 02 20:54:57 2006 -0700 @@ -475,39 +475,92 @@ stream_skip(qtmovie->stream, size_remaining); } -/* 'udta' user data.. contains tag info */ -static void read_chunk_udta(qtmovie_t *qtmovie, size_t chunk_len) +enum +{ + UDTA_NIL = 0, + UDTA_NAM, + UDTA_ART, + UDTA_ALB, + UDTA_GEN, + UDTA_DAY +}; + +/* 'udta' user data.. contains tag info. this routine is utterly fucked because Apple's + * lovely container format is utterly fucked itself... + */ +void read_chunk_udta(qtmovie_t *qtmovie, size_t chunk_len) { /* don't need anything from here atm, skip */ size_t size_remaining = chunk_len - 8; /* FIXME WRONG */ + char *buf = g_malloc0(chunk_len); + char *bptr; + fourcc_t sub_chunk_id; /* bptr[4] << 24 | bptr[3] << 16 | bptr[2] << 8 | bptr[1] */ + int udta_tgt = UDTA_NIL; - stream_skip(qtmovie->stream, size_remaining); -#if 0 - while (size_remaining) + /* read the stream in for scanning -nenolod */ + stream_read(qtmovie->stream, size_remaining, buf); + + /* this is (bptr + 3) to account for the MAKEFOURCC() macro. -nenolod */ + for (bptr = buf; (bptr + 3) - buf < size_remaining; bptr++) { - size_t sub_chunk_len; - fourcc_t sub_chunk_id; - - sub_chunk_len = stream_read_uint32(qtmovie->stream); - if (sub_chunk_len <= 1 || sub_chunk_len > size_remaining) - return; - - sub_chunk_id = stream_read_uint32(qtmovie->stream); + sub_chunk_id = MAKEFOURCC(*bptr, *(bptr + 1), *(bptr + 2), *(bptr + 3)); switch (sub_chunk_id) { case MAKEFOURCC('m','e','t','a'): - stream_skip(qtmovie->stream, sub_chunk_len); - break; + bptr += 4; /* skip meta */ + break; + case MAKEFOURCC(0xA9,'n','a','m'): + udta_tgt = UDTA_NAM; + bptr += 4; + break; + case MAKEFOURCC(0xA9,'A','R','T'): + udta_tgt = UDTA_ART; + bptr += 4; + break; + case MAKEFOURCC(0xA9,'a','l','b'): + udta_tgt = UDTA_ALB; + bptr += 4; + break; + case MAKEFOURCC(0xA9,'g','e','n'): + udta_tgt = UDTA_GEN; + bptr += 4; + break; + case MAKEFOURCC(0xA9,'d','a','y'): + udta_tgt = UDTA_DAY; + bptr += 4; + break; + case MAKEFOURCC('d','a','t','a'): + switch(udta_tgt) + { + case UDTA_NAM: + qtmovie->res->tuple.nam = g_strdup(bptr + 12); + break; + case UDTA_ART: + qtmovie->res->tuple.art = g_strdup(bptr + 12); + break; + case UDTA_ALB: + qtmovie->res->tuple.alb = g_strdup(bptr + 12); + break; + case UDTA_DAY: + qtmovie->res->tuple.day = g_strdup(bptr + 12); + break; + case UDTA_GEN: + qtmovie->res->tuple.gen = g_strdup(bptr + 12); + break; + default: + break; + } + + bptr += 12; + bptr += strlen(bptr); + break; default: - fprintf(stderr, "read_chunk_udta(%p, %lu): unknown chunk: %c%c%c%c\n", - qtmovie, chunk_len, SPLITFOURCC(sub_chunk_id)); - return; + break; } + } - size_remaining -= sub_chunk_len; - } -#endif + g_free(buf); } /* 'moov' movie atom - contains other atoms */ diff -r 096db10ce25f -r 722fd456ae1a src/alac/demux.h --- a/src/alac/demux.h Mon Oct 02 19:55:45 2006 -0700 +++ b/src/alac/demux.h Mon Oct 02 20:54:57 2006 -0700 @@ -19,6 +19,16 @@ void *buf; struct { + char *art; + char *nam; + char *alb; + char *day; + char *cmt; + char *des; + char *gen; + } tuple; + + struct { uint32_t sample_count; uint32_t sample_duration; } *time_to_sample; diff -r 096db10ce25f -r 722fd456ae1a src/alac/plugin.c --- a/src/alac/plugin.c Mon Oct 02 19:55:45 2006 -0700 +++ b/src/alac/plugin.c Mon Oct 02 20:54:57 2006 -0700 @@ -52,6 +52,17 @@ extern void set_endian(); +static gchar * +extname(const char *filename) +{ + gchar *ext = strrchr(filename, '.'); + + if (ext != NULL) + ++ext; + + return ext; +} + static void alac_about(void) { static GtkWidget *aboutbox; @@ -106,6 +117,63 @@ return TRUE; } +TitleInput *build_tuple_from_demux(demux_res_t *demux_res, char *path) +{ + TitleInput *ti = bmp_title_input_new(); + + if (demux_res->tuple.art != NULL) + ti->performer = g_strdup(demux_res->tuple.art); + if (demux_res->tuple.nam != NULL) + ti->track_name = g_strdup(demux_res->tuple.nam); + if (demux_res->tuple.alb != NULL) + ti->album_name = g_strdup(demux_res->tuple.alb); + if (demux_res->tuple.gen != NULL) + ti->genre = g_strdup(demux_res->tuple.gen); + if (demux_res->tuple.cmt != NULL) + ti->comment = g_strdup(demux_res->tuple.cmt); + if (demux_res->tuple.day != NULL) + ti->year = atoi(demux_res->tuple.day); + + ti->file_name = g_path_get_basename(path); + ti->file_path = g_path_get_dirname(path); + ti->file_ext = extname(path); + + return ti; +} + +TitleInput *build_tuple(char *filename) +{ + demux_res_t demux_res; + VFSFile *input_file; + stream_t *input_stream; + TitleInput *ti; + + input_file = vfs_fopen(filename, "rb"); + input_stream = stream_create_file(input_file, 1); + + set_endian(); + + if (!input_stream) + { + vfs_fclose(input_file); + return NULL; + } + + /* if qtmovie_read returns successfully, the stream is up to + * the movie data, which can be used directly by the decoder */ + if (!qtmovie_read(input_stream, &demux_res)) + { + stream_destroy(input_stream); + vfs_fclose(input_file); + return NULL; + } + + stream_destroy(input_stream); + vfs_fclose(input_file); + + return build_tuple_from_demux(&demux_res, filename); +} + static void play_file(char *filename) { going = 1; @@ -156,7 +224,8 @@ NULL, NULL, NULL, /* file_info_box */ - NULL + NULL, + build_tuple }; static int get_sample_info(demux_res_t *demux_res, uint32_t samplenum, @@ -240,6 +309,8 @@ gint framesize; VFSFile *input_file; stream_t *input_stream; + TitleInput *ti; + gchar *title; memset(&demux_res, '\0', sizeof(demux_res_t)); @@ -258,6 +329,10 @@ demux_res.stream = input_stream; + /* Get the titlestring ready. */ + ti = build_tuple_from_demux(&demux_res, (char *) args); + title = xmms_get_titlestring(xmms_get_gentitle_format(), ti); + /* initialise the sound converter */ demux_res.alac = create_alac(demux_res.sample_size, demux_res.num_channels); alac_set_info(demux_res.alac, demux_res.codecdata); @@ -267,7 +342,7 @@ (float)(demux_res.sample_rate / 251)); alac_ip.output->open_audio(FMT_S16_LE, demux_res.sample_rate, demux_res.num_channels); - alac_ip.set_info((char *) args, duration, -1, demux_res.sample_rate, demux_res.num_channels); + alac_ip.set_info(title, duration, -1, demux_res.sample_rate, demux_res.num_channels); /* will convert the entire buffer */ GetBuffer(&demux_res);