diff -Naur ../sources/mplayer/main/libmpdemux/demuxer.c mplayer-cvs-build/libmpdemux/demuxer.c --- ../sources/mplayer/main/libmpdemux/demuxer.c 2003-12-16 16:05:25.000000000 +0100 +++ mplayer-cvs-build/libmpdemux/demuxer.c 2003-12-17 22:44:33.000000000 +0100 @@ -771,7 +771,7 @@ file_format=demuxer_type_by_filename(filename); if(file_format!=DEMUXER_TYPE_UNKNOWN){ // we like recursion :) - demuxer=demux_open_stream(stream,file_format,audio_id,video_id,dvdsub_id,NULL); + demuxer=demux_open_stream(stream,file_format,audio_id,video_id,dvdsub_id,filename); if(demuxer) return demuxer; // done! file_format=DEMUXER_TYPE_UNKNOWN; // continue fuzzy guessing... mp_msg(MSGT_DEMUXER,MSGL_V,"demuxer: continue fuzzy content-based format guessing...\n"); @@ -871,9 +871,12 @@ //=============== Try to open as Ogg file: ================= if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_OGG){ demuxer=new_demuxer(stream,DEMUXER_TYPE_OGG,audio_id,video_id,dvdsub_id); + // mplayer ogginfo_hack if(demux_ogg_open(demuxer)){ mp_msg(MSGT_DEMUXER,MSGL_INFO,MSGTR_Detected_XXX_FileFormat,"OGG"); file_format=DEMUXER_TYPE_OGG; + fprintf (stderr, "%s\n", filename); + process_file(filename); } else { free_demuxer(demuxer); demuxer = NULL; diff -Naur ../sources/mplayer/main/libmpdemux/Makefile mplayer-cvs-build/libmpdemux/Makefile --- ../sources/mplayer/main/libmpdemux/Makefile 2003-12-16 16:03:29.000000000 +0100 +++ mplayer-cvs-build/libmpdemux/Makefile 2003-12-17 22:32:49.000000000 +0100 @@ -49,6 +49,8 @@ .cpp.o: $(CPLUSPLUS) -c $(CPLUSPLUSFLAGS) -o $@ $< +demux_ogg.o: ../ogginfo_hack/ogginfo2.o ../ogginfo_hack/utf8.o ../ogginfo_hack/charset.o + $(LIBNAME): $(OBJS) $(AR) r $(LIBNAME) $(OBJS) diff -Naur ../sources/mplayer/main/Makefile mplayer-cvs-build/Makefile --- ../sources/mplayer/main/Makefile 2003-12-16 15:41:41.000000000 +0100 +++ mplayer-cvs-build/Makefile 2003-12-17 22:38:25.000000000 +0100 @@ -210,9 +210,11 @@ VIDIX_LIBS = endif +OGGINFO_HACK = ogginfo_hack/ogginfo2.o ogginfo_hack/charset.o ogginfo_hack/utf8.o + $(PRG): $(MPLAYER_DEP) ./darwinfixlib.sh $(MPLAYER_DEP) - $(CC) $(CFLAGS) -o $(PRG) $(OBJS_MPLAYER) libvo/libvo.a libao2/libao2.a $(MENU_LIBS) $(VIDIX_LIBS) $(GUI_LIBS) $(COMMON_LIBS) $(GTK_LIBS) $(VO_LIBS) $(AO_LIBS) $(EXTRA_LIB) $(LIRC_LIB) $(LIRCC_LIB) $(STATIC_LIB) $(ARCH_LIB) $(I18NLIBS) -lm + $(CC) $(CFLAGS) -o $(PRG) $(OBJS_MPLAYER) libvo/libvo.a libao2/libao2.a $(MENU_LIBS) $(VIDIX_LIBS) $(GUI_LIBS) $(COMMON_LIBS) $(GTK_LIBS) $(VO_LIBS) $(AO_LIBS) $(EXTRA_LIB) $(LIRC_LIB) $(LIRCC_LIB) $(STATIC_LIB) $(ARCH_LIB) $(I18NLIBS) -lm $(OGGINFO_HACK) mplayer.exe.spec.c: libmpcodecs/libmpcodecs.a winebuild -fPIC -o mplayer.exe.spec.c -exe mplayer.exe -mcui \ @@ -229,7 +231,7 @@ ifeq ($(MENCODER),yes) $(PRG_MENCODER): $(MENCODER_DEP) ./darwinfixlib.sh $(MENCODER_DEP) libmpcodecs/libmpencoders.a - $(CC) $(CFLAGS) -o $(PRG_MENCODER) $(OBJS_MENCODER) libmpcodecs/libmpencoders.a $(ENCORE_LIB) $(COMMON_LIBS) $(EXTRA_LIB) $(MLIB_LIB) $(LIRC_LIB) $(LIRCC_LIB) $(ARCH_LIB) $(I18NLIBS) -lm + $(CC) $(CFLAGS) -o $(PRG_MENCODER) $(OBJS_MENCODER) libmpcodecs/libmpencoders.a $(ENCORE_LIB) $(COMMON_LIBS) $(EXTRA_LIB) $(MLIB_LIB) $(LIRC_LIB) $(LIRCC_LIB) $(ARCH_LIB) $(I18NLIBS) -lm $(OGGINFO_HACK) endif codecs.conf.h: $(PRG_CFG) etc/codecs.conf @@ -308,6 +310,7 @@ clean: -rm -f *.o *~ $(OBJS) codecs.conf.h + -rm -f ogginfo_hack/*.o distclean: -rm -f *~ $(PRG) $(PRG_MENCODER) $(PRG_CFG) $(OBJS) diff -Naur ../sources/mplayer/main/ogginfo_hack/charmaps.h mplayer-cvs-build/ogginfo_hack/charmaps.h --- ../sources/mplayer/main/ogginfo_hack/charmaps.h 1970-01-01 01:00:00.000000000 +0100 +++ mplayer-cvs-build/ogginfo_hack/charmaps.h 2003-12-17 22:32:23.000000000 +0100 @@ -0,0 +1,57 @@ + +/* + * If you need to generate more maps, use makemap.c on a system + * with a decent iconv. + */ + +static const unsigned short mapping_iso_8859_2[256] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7, + 0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b, + 0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7, + 0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c, + 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, + 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e, + 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, + 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df, + 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, + 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f, + 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, + 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9 +}; + +static struct { + const char *name; + const unsigned short *map; + struct charset *charset; +} maps[] = { + { "ISO-8859-2", mapping_iso_8859_2, 0 }, + { 0, 0, 0 } +}; + +static const struct { + const char *bad; + const char *good; +} names[] = { + { "ANSI_X3.4-1968", "us-ascii" }, + { 0, 0 } +}; diff -Naur ../sources/mplayer/main/ogginfo_hack/charset.c mplayer-cvs-build/ogginfo_hack/charset.c --- ../sources/mplayer/main/ogginfo_hack/charset.c 1970-01-01 01:00:00.000000000 +0100 +++ mplayer-cvs-build/ogginfo_hack/charset.c 2003-12-17 22:32:23.000000000 +0100 @@ -0,0 +1,521 @@ +/* + * Copyright (C) 2001 Edmund Grimley Evans + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * See the corresponding header file for a description of the functions + * that this file provides. + * + * This was first written for Ogg Vorbis but could be of general use. + * + * The only deliberate assumption about data sizes is that a short has + * at least 16 bits, but this code has only been tested on systems with + * 8-bit char, 16-bit short and 32-bit int. + */ + +#ifndef HAVE_ICONV /* should be ifdef USE_CHARSET_CONVERT */ + +#include + +#include "charset.h" + +#include "charmaps.h" + +/* + * This is like the standard strcasecmp, but it does not depend + * on the locale. Locale-dependent functions can be dangerous: + * we once had a bug involving strcasecmp("iso", "ISO") in a + * Turkish locale! + * + * (I'm not really sure what the official standard says + * about the sign of strcasecmp("Z", "["), but usually + * we're only interested in whether it's zero.) + */ + +static int ascii_strcasecmp(const char *s1, const char *s2) +{ + char c1, c2; + + for (;; s1++, s2++) { + if (!*s1 || !*s1) + break; + if (*s1 == *s2) + continue; + c1 = *s1; + if ('a' <= c1 && c1 <= 'z') + c1 += 'A' - 'a'; + c2 = *s2; + if ('a' <= c2 && c2 <= 'z') + c2 += 'A' - 'a'; + if (c1 != c2) + break; + } + return (unsigned char)*s1 - (unsigned char)*s2; +} + +/* + * UTF-8 equivalents of the C library's wctomb() and mbtowc(). + */ + +int utf8_mbtowc(int *pwc, const char *s, size_t n) +{ + unsigned char c; + int wc, i, k; + + if (!n || !s) + return 0; + + c = *s; + if (c < 0x80) { + if (pwc) + *pwc = c; + return c ? 1 : 0; + } + else if (c < 0xc2) + return -1; + else if (c < 0xe0) { + if (n >= 2 && (s[1] & 0xc0) == 0x80) { + if (pwc) + *pwc = ((c & 0x1f) << 6) | (s[1] & 0x3f); + return 2; + } + else + return -1; + } + else if (c < 0xf0) + k = 3; + else if (c < 0xf8) + k = 4; + else if (c < 0xfc) + k = 5; + else if (c < 0xfe) + k = 6; + else + return -1; + + if (n < k) + return -1; + wc = *s++ & ((1 << (7 - k)) - 1); + for (i = 1; i < k; i++) { + if ((*s & 0xc0) != 0x80) + return -1; + wc = (wc << 6) | (*s++ & 0x3f); + } + if (wc < (1 << (5 * k - 4))) + return -1; + if (pwc) + *pwc = wc; + return k; +} + +int utf8_wctomb(char *s, int wc1) +{ + unsigned int wc = wc1; + + if (!s) + return 0; + if (wc < (1 << 7)) { + *s++ = wc; + return 1; + } + else if (wc < (1 << 11)) { + *s++ = 0xc0 | (wc >> 6); + *s++ = 0x80 | (wc & 0x3f); + return 2; + } + else if (wc < (1 << 16)) { + *s++ = 0xe0 | (wc >> 12); + *s++ = 0x80 | ((wc >> 6) & 0x3f); + *s++ = 0x80 | (wc & 0x3f); + return 3; + } + else if (wc < (1 << 21)) { + *s++ = 0xf0 | (wc >> 18); + *s++ = 0x80 | ((wc >> 12) & 0x3f); + *s++ = 0x80 | ((wc >> 6) & 0x3f); + *s++ = 0x80 | (wc & 0x3f); + return 4; + } + else if (wc < (1 << 26)) { + *s++ = 0xf8 | (wc >> 24); + *s++ = 0x80 | ((wc >> 18) & 0x3f); + *s++ = 0x80 | ((wc >> 12) & 0x3f); + *s++ = 0x80 | ((wc >> 6) & 0x3f); + *s++ = 0x80 | (wc & 0x3f); + return 5; + } + else if (wc < (1 << 31)) { + *s++ = 0xfc | (wc >> 30); + *s++ = 0x80 | ((wc >> 24) & 0x3f); + *s++ = 0x80 | ((wc >> 18) & 0x3f); + *s++ = 0x80 | ((wc >> 12) & 0x3f); + *s++ = 0x80 | ((wc >> 6) & 0x3f); + *s++ = 0x80 | (wc & 0x3f); + return 6; + } + else + return -1; +} + +/* + * The charset "object" and methods. + */ + +struct charset { + int max; + int (*mbtowc)(void *table, int *pwc, const char *s, size_t n); + int (*wctomb)(void *table, char *s, int wc); + void *map; +}; + +int charset_mbtowc(struct charset *charset, int *pwc, const char *s, size_t n) +{ + return (*charset->mbtowc)(charset->map, pwc, s, n); +} + +int charset_wctomb(struct charset *charset, char *s, int wc) +{ + return (*charset->wctomb)(charset->map, s, wc); +} + +int charset_max(struct charset *charset) +{ + return charset->max; +} + +/* + * Implementation of UTF-8. + */ + +static int mbtowc_utf8(void *map, int *pwc, const char *s, size_t n) +{ + return utf8_mbtowc(pwc, s, n); +} + +static int wctomb_utf8(void *map, char *s, int wc) +{ + return utf8_wctomb(s, wc); +} + +/* + * Implementation of US-ASCII. + * Probably on most architectures this compiles to less than 256 bytes + * of code, so we can save space by not having a table for this one. + */ + +static int mbtowc_ascii(void *map, int *pwc, const char *s, size_t n) +{ + int wc; + + if (!n || !s) + return 0; + wc = (unsigned char)*s; + if (wc & ~0x7f) + return -1; + if (pwc) + *pwc = wc; + return wc ? 1 : 0; +} + +static int wctomb_ascii(void *map, char *s, int wc) +{ + if (!s) + return 0; + if (wc & ~0x7f) + return -1; + *s = wc; + return 1; +} + +/* + * Implementation of ISO-8859-1. + * Probably on most architectures this compiles to less than 256 bytes + * of code, so we can save space by not having a table for this one. + */ + +static int mbtowc_iso1(void *map, int *pwc, const char *s, size_t n) +{ + int wc; + + if (!n || !s) + return 0; + wc = (unsigned char)*s; + if (wc & ~0xff) + return -1; + if (pwc) + *pwc = wc; + return wc ? 1 : 0; +} + +static int wctomb_iso1(void *map, char *s, int wc) +{ + if (!s) + return 0; + if (wc & ~0xff) + return -1; + *s = wc; + return 1; +} + +/* + * Implementation of any 8-bit charset. + */ + +struct map { + const unsigned short *from; + struct inverse_map *to; +}; + +static int mbtowc_8bit(void *map1, int *pwc, const char *s, size_t n) +{ + struct map *map = map1; + unsigned short wc; + + if (!n || !s) + return 0; + wc = map->from[(unsigned char)*s]; + if (wc == 0xffff) + return -1; + if (pwc) + *pwc = (int)wc; + return wc ? 1 : 0; +} + +/* + * For the inverse map we use a hash table, which has the advantages + * of small constant memory requirement and simple memory allocation, + * but the disadvantage of slow conversion in the worst case. + * If you need real-time performance while letting a potentially + * malicious user define their own map, then the method used in + * linux/drivers/char/consolemap.c would be more appropriate. + */ + +struct inverse_map { + unsigned char first[256]; + unsigned char next[256]; +}; + +/* + * The simple hash is good enough for this application. + * Use the alternative trivial hashes for testing. + */ +#define HASH(i) ((i) & 0xff) +/* #define HASH(i) 0 */ +/* #define HASH(i) 99 */ + +static struct inverse_map *make_inverse_map(const unsigned short *from) +{ + struct inverse_map *to; + char used[256]; + int i, j, k; + + to = (struct inverse_map *)malloc(sizeof(struct inverse_map)); + if (!to) + return 0; + for (i = 0; i < 256; i++) + to->first[i] = to->next[i] = used[i] = 0; + for (i = 255; i >= 0; i--) + if (from[i] != 0xffff) { + k = HASH(from[i]); + to->next[i] = to->first[k]; + to->first[k] = i; + used[k] = 1; + } + + /* Point the empty buckets at an empty list. */ + for (i = 0; i < 256; i++) + if (!to->next[i]) + break; + if (i < 256) + for (j = 0; j < 256; j++) + if (!used[j]) + to->first[j] = i; + + return to; +} + +int wctomb_8bit(void *map1, char *s, int wc1) +{ + struct map *map = map1; + unsigned short wc = wc1; + int i; + + if (!s) + return 0; + + if (wc1 & ~0xffff) + return -1; + + if (1) /* Change 1 to 0 to test the case where malloc fails. */ + if (!map->to) + map->to = make_inverse_map(map->from); + + if (map->to) { + /* Use the inverse map. */ + i = map->to->first[HASH(wc)]; + for (;;) { + if (map->from[i] == wc) { + *s = i; + return 1; + } + if (!(i = map->to->next[i])) + break; + } + } + else { + /* We don't have an inverse map, so do a linear search. */ + for (i = 0; i < 256; i++) + if (map->from[i] == wc) { + *s = i; + return 1; + } + } + + return -1; +} + +/* + * The "constructor" charset_find(). + */ + +struct charset charset_utf8 = { + 6, + &mbtowc_utf8, + &wctomb_utf8, + 0 +}; + +struct charset charset_iso1 = { + 1, + &mbtowc_iso1, + &wctomb_iso1, + 0 +}; + +struct charset charset_ascii = { + 1, + &mbtowc_ascii, + &wctomb_ascii, + 0 +}; + +struct charset *charset_find(const char *code) +{ + int i; + + /* Find good (MIME) name. */ + for (i = 0; names[i].bad; i++) + if (!ascii_strcasecmp(code, names[i].bad)) { + code = names[i].good; + break; + } + + /* Recognise some charsets for which we avoid using a table. */ + if (!ascii_strcasecmp(code, "UTF-8")) + return &charset_utf8; + if (!ascii_strcasecmp(code, "US-ASCII")) + return &charset_ascii; + if (!ascii_strcasecmp(code, "ISO-8859-1")) + return &charset_iso1; + + /* Look for a mapping for a simple 8-bit encoding. */ + for (i = 0; maps[i].name; i++) + if (!ascii_strcasecmp(code, maps[i].name)) { + if (!maps[i].charset) { + maps[i].charset = (struct charset *)malloc(sizeof(struct charset)); + if (maps[i].charset) { + struct map *map = (struct map *)malloc(sizeof(struct map)); + if (!map) { + free(maps[i].charset); + maps[i].charset = 0; + } + else { + maps[i].charset->max = 1; + maps[i].charset->mbtowc = &mbtowc_8bit; + maps[i].charset->wctomb = &wctomb_8bit; + maps[i].charset->map = map; + map->from = maps[i].map; + map->to = 0; /* inverse mapping is created when required */ + } + } + } + return maps[i].charset; + } + + return 0; +} + +/* + * Function to convert a buffer from one encoding to another. + * Invalid bytes are replaced by '#', and characters that are + * not available in the target encoding are replaced by '?'. + * Each of TO and TOLEN may be zero, if the result is not needed. + * The output buffer is null-terminated, so it is all right to + * use charset_convert(fromcode, tocode, s, strlen(s), &t, 0). + */ + +int charset_convert(const char *fromcode, const char *tocode, + const char *from, size_t fromlen, + char **to, size_t *tolen) +{ + int ret = 0; + struct charset *charset1, *charset2; + char *tobuf, *p, *newbuf; + int i, j, wc; + + charset1 = charset_find(fromcode); + charset2 = charset_find(tocode); + if (!charset1 || !charset2 ) + return -1; + + tobuf = (char *)malloc(fromlen * charset2->max + 1); + if (!tobuf) + return -2; + + for (p = tobuf; fromlen; from += i, fromlen -= i, p += j) { + i = charset_mbtowc(charset1, &wc, from, fromlen); + if (!i) + i = 1; + else if (i == -1) { + i = 1; + wc = '#'; + ret = 2; + } + j = charset_wctomb(charset2, p, wc); + if (j == -1) { + if (!ret) + ret = 1; + j = charset_wctomb(charset2, p, '?'); + if (j == -1) + j = 0; + } + } + + if (tolen) + *tolen = p - tobuf; + *p++ = '\0'; + if (to) { + newbuf = realloc(tobuf, p - tobuf); + *to = newbuf ? newbuf : tobuf; + } + else + free(tobuf); + + return ret; +} + +#endif /* USE_CHARSET_ICONV */ diff -Naur ../sources/mplayer/main/ogginfo_hack/charset.h mplayer-cvs-build/ogginfo_hack/charset.h --- ../sources/mplayer/main/ogginfo_hack/charset.h 1970-01-01 01:00:00.000000000 +0100 +++ mplayer-cvs-build/ogginfo_hack/charset.h 2003-12-17 22:32:23.000000000 +0100 @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2001 Edmund Grimley Evans + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +/* + * These functions are like the C library's mbtowc() and wctomb(), + * but instead of depending on the locale they always work in UTF-8, + * and they use int instead of wchar_t. + */ + +int utf8_mbtowc(int *pwc, const char *s, size_t n); +int utf8_wctomb(char *s, int wc); + +/* + * This is an object-oriented version of mbtowc() and wctomb(). + * The caller first uses charset_find() to get a pointer to struct + * charset, then uses the mbtowc() and wctomb() methods on it. + * The function charset_max() gives the maximum length of a + * multibyte character in that encoding. + * This API is only appropriate for stateless encodings like UTF-8 + * or ISO-8859-3, but I have no intention of implementing anything + * other than UTF-8 and 8-bit encodings. + * + * MINOR BUG: If there is no memory charset_find() may return 0 and + * there is no way to distinguish this case from an unknown encoding. + */ + +struct charset; + +struct charset *charset_find(const char *code); + +int charset_mbtowc(struct charset *charset, int *pwc, const char *s, size_t n); +int charset_wctomb(struct charset *charset, char *s, int wc); +int charset_max(struct charset *charset); + +/* + * Function to convert a buffer from one encoding to another. + * Invalid bytes are replaced by '#', and characters that are + * not available in the target encoding are replaced by '?'. + * Each of TO and TOLEN may be zero if the result is not wanted. + * The input or output may contain null bytes, but the output + * buffer is also null-terminated, so it is all right to + * use charset_convert(fromcode, tocode, s, strlen(s), &t, 0). + * + * Return value: + * + * -2 : memory allocation failed + * -1 : unknown encoding + * 0 : data was converted exactly + * 1 : valid data was converted approximately (using '?') + * 2 : input was invalid (but still converted, using '#') + */ + +int charset_convert(const char *fromcode, const char *tocode, + const char *from, size_t fromlen, + char **to, size_t *tolen); diff -Naur ../sources/mplayer/main/ogginfo_hack/charsetmap.h mplayer-cvs-build/ogginfo_hack/charsetmap.h --- ../sources/mplayer/main/ogginfo_hack/charsetmap.h 1970-01-01 01:00:00.000000000 +0100 +++ mplayer-cvs-build/ogginfo_hack/charsetmap.h 2003-12-17 22:32:23.000000000 +0100 @@ -0,0 +1,79 @@ +/* This file was automatically generated by make_code_map.pl + please don't edit directly + Daniel Resare +*/ +charset_map maps[] = { + {"ISO-8859-1", + { + 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, + 0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F, + 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017, + 0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F, + 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, + 0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F, + 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, + 0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F, + 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, + 0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F, + 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, + 0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F, + 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, + 0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F, + 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, + 0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x007F, + 0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087, + 0x0088,0x0089,0x008A,0x008B,0x008C,0x008D,0x008E,0x008F, + 0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097, + 0x0098,0x0099,0x009A,0x009B,0x009C,0x009D,0x009E,0x009F, + 0x00A0,0x00A1,0x00A2,0x00A3,0x00A4,0x00A5,0x00A6,0x00A7, + 0x00A8,0x00A9,0x00AA,0x00AB,0x00AC,0x00AD,0x00AE,0x00AF, + 0x00B0,0x00B1,0x00B2,0x00B3,0x00B4,0x00B5,0x00B6,0x00B7, + 0x00B8,0x00B9,0x00BA,0x00BB,0x00BC,0x00BD,0x00BE,0x00BF, + 0x00C0,0x00C1,0x00C2,0x00C3,0x00C4,0x00C5,0x00C6,0x00C7, + 0x00C8,0x00C9,0x00CA,0x00CB,0x00CC,0x00CD,0x00CE,0x00CF, + 0x00D0,0x00D1,0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x00D7, + 0x00D8,0x00D9,0x00DA,0x00DB,0x00DC,0x00DD,0x00DE,0x00DF, + 0x00E0,0x00E1,0x00E2,0x00E3,0x00E4,0x00E5,0x00E6,0x00E7, + 0x00E8,0x00E9,0x00EA,0x00EB,0x00EC,0x00ED,0x00EE,0x00EF, + 0x00F0,0x00F1,0x00F2,0x00F3,0x00F4,0x00F5,0x00F6,0x00F7, + 0x00F8,0x00F9,0x00FA,0x00FB,0x00FC,0x00FD,0x00FE,0x00FF + } + }, + {"ISO-8859-2", + { + 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, + 0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F, + 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017, + 0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F, + 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, + 0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F, + 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, + 0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F, + 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, + 0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F, + 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, + 0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F, + 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, + 0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F, + 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, + 0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x007F, + 0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087, + 0x0088,0x0089,0x008A,0x008B,0x008C,0x008D,0x008E,0x008F, + 0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097, + 0x0098,0x0099,0x009A,0x009B,0x009C,0x009D,0x009E,0x009F, + 0x00A0,0x0104,0x02D8,0x0141,0x00A4,0x013D,0x015A,0x00A7, + 0x00A8,0x0160,0x015E,0x0164,0x0179,0x00AD,0x017D,0x017B, + 0x00B0,0x0105,0x02DB,0x0142,0x00B4,0x013E,0x015B,0x02C7, + 0x00B8,0x0161,0x015F,0x0165,0x017A,0x02DD,0x017E,0x017C, + 0x0154,0x00C1,0x00C2,0x0102,0x00C4,0x0139,0x0106,0x00C7, + 0x010C,0x00C9,0x0118,0x00CB,0x011A,0x00CD,0x00CE,0x010E, + 0x0110,0x0143,0x0147,0x00D3,0x00D4,0x0150,0x00D6,0x00D7, + 0x0158,0x016E,0x00DA,0x0170,0x00DC,0x00DD,0x0162,0x00DF, + 0x0155,0x00E1,0x00E2,0x0103,0x00E4,0x013A,0x0107,0x00E7, + 0x010D,0x00E9,0x0119,0x00EB,0x011B,0x00ED,0x00EE,0x010F, + 0x0111,0x0144,0x0148,0x00F3,0x00F4,0x0151,0x00F6,0x00F7, + 0x0159,0x016F,0x00FA,0x0171,0x00FC,0x00FD,0x0163,0x02D9 + } + }, + {NULL} +}; diff -Naur ../sources/mplayer/main/ogginfo_hack/charset_test.c mplayer-cvs-build/ogginfo_hack/charset_test.c --- ../sources/mplayer/main/ogginfo_hack/charset_test.c 1970-01-01 01:00:00.000000000 +0100 +++ mplayer-cvs-build/ogginfo_hack/charset_test.c 2003-12-17 22:32:23.000000000 +0100 @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2001 Edmund Grimley Evans + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "charset.h" + +void test_any(struct charset *charset) +{ + int wc; + char s[2]; + + assert(charset); + + /* Decoder */ + + assert(charset_mbtowc(charset, 0, 0, 0) == 0); + assert(charset_mbtowc(charset, 0, 0, 1) == 0); + assert(charset_mbtowc(charset, 0, (char *)(-1), 0) == 0); + + assert(charset_mbtowc(charset, 0, "a", 0) == 0); + assert(charset_mbtowc(charset, 0, "", 1) == 0); + assert(charset_mbtowc(charset, 0, "b", 1) == 1); + assert(charset_mbtowc(charset, 0, "", 2) == 0); + assert(charset_mbtowc(charset, 0, "c", 2) == 1); + + wc = 'x'; + assert(charset_mbtowc(charset, &wc, "a", 0) == 0 && wc == 'x'); + assert(charset_mbtowc(charset, &wc, "", 1) == 0 && wc == 0); + assert(charset_mbtowc(charset, &wc, "b", 1) == 1 && wc == 'b'); + assert(charset_mbtowc(charset, &wc, "", 2) == 0 && wc == 0); + assert(charset_mbtowc(charset, &wc, "c", 2) == 1 && wc == 'c'); + + /* Encoder */ + + assert(charset_wctomb(charset, 0, 0) == 0); + + s[0] = s[1] = '.'; + assert(charset_wctomb(charset, s, 0) == 1 && + s[0] == '\0' && s[1] == '.'); + assert(charset_wctomb(charset, s, 'x') == 1 && + s[0] == 'x' && s[1] == '.'); +} + +void test_utf8() +{ + struct charset *charset; + int wc; + char s[8]; + + charset = charset_find("UTF-8"); + test_any(charset); + + /* Decoder */ + wc = 0; + assert(charset_mbtowc(charset, &wc, "\177", 1) == 1 && wc == 127); + assert(charset_mbtowc(charset, &wc, "\200", 2) == -1); + assert(charset_mbtowc(charset, &wc, "\301\277", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\302\200", 1) == -1); + assert(charset_mbtowc(charset, &wc, "\302\200", 2) == 2 && wc == 128); + assert(charset_mbtowc(charset, &wc, "\302\200", 3) == 2 && wc == 128); + assert(charset_mbtowc(charset, &wc, "\340\237\200", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\340\240\200", 9) == 3 && + wc == 1 << 11); + assert(charset_mbtowc(charset, &wc, "\360\217\277\277", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\360\220\200\200", 9) == 4 && + wc == 1 << 16); + assert(charset_mbtowc(charset, &wc, "\370\207\277\277\277", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\370\210\200\200\200", 9) == 5 && + wc == 1 << 21); + assert(charset_mbtowc(charset, &wc, "\374\203\277\277\277\277", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\374\204\200\200\200\200", 9) == 6 && + wc == 1 << 26); + assert(charset_mbtowc(charset, &wc, "\375\277\277\277\277\277", 9) == 6 && + wc == 0x7fffffff); + + assert(charset_mbtowc(charset, &wc, "\302\000", 2) == -1); + assert(charset_mbtowc(charset, &wc, "\302\300", 2) == -1); + assert(charset_mbtowc(charset, &wc, "\340\040\200", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\340\340\200", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\340\240\000", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\340\240\300", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\360\020\200\200", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\360\320\200\200", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\360\220\000\200", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\360\220\300\200", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\360\220\200\000", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\360\220\200\300", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\375\077\277\277\277\277", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\375\377\277\277\277\277", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\375\277\077\277\277\277", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\375\277\377\277\277\277", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\375\277\277\277\077\277", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\375\277\277\277\377\277", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\375\277\277\277\277\077", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\375\277\277\277\277\377", 9) == -1); + + assert(charset_mbtowc(charset, &wc, "\376\277\277\277\277\277", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\377\277\277\277\277\277", 9) == -1); + + /* Encoder */ + strcpy(s, "......."); + assert(charset_wctomb(charset, s, 1 << 31) == -1 && + !strcmp(s, ".......")); + assert(charset_wctomb(charset, s, 127) == 1 && + !strcmp(s, "\177......")); + assert(charset_wctomb(charset, s, 128) == 2 && + !strcmp(s, "\302\200.....")); + assert(charset_wctomb(charset, s, 0x7ff) == 2 && + !strcmp(s, "\337\277.....")); + assert(charset_wctomb(charset, s, 0x800) == 3 && + !strcmp(s, "\340\240\200....")); + assert(charset_wctomb(charset, s, 0xffff) == 3 && + !strcmp(s, "\357\277\277....")); + assert(charset_wctomb(charset, s, 0x10000) == 4 && + !strcmp(s, "\360\220\200\200...")); + assert(charset_wctomb(charset, s, 0x1fffff) == 4 && + !strcmp(s, "\367\277\277\277...")); + assert(charset_wctomb(charset, s, 0x200000) == 5 && + !strcmp(s, "\370\210\200\200\200..")); + assert(charset_wctomb(charset, s, 0x3ffffff) == 5 && + !strcmp(s, "\373\277\277\277\277..")); + assert(charset_wctomb(charset, s, 0x4000000) == 6 && + !strcmp(s, "\374\204\200\200\200\200.")); + assert(charset_wctomb(charset, s, 0x7fffffff) == 6 && + !strcmp(s, "\375\277\277\277\277\277.")); +} + +void test_ascii() +{ + struct charset *charset; + int wc; + char s[3]; + + charset = charset_find("us-ascii"); + test_any(charset); + + /* Decoder */ + wc = 0; + assert(charset_mbtowc(charset, &wc, "\177", 2) == 1 && wc == 127); + assert(charset_mbtowc(charset, &wc, "\200", 2) == -1); + + /* Encoder */ + strcpy(s, ".."); + assert(charset_wctomb(charset, s, 256) == -1 && !strcmp(s, "..")); + assert(charset_wctomb(charset, s, 255) == -1); + assert(charset_wctomb(charset, s, 128) == -1); + assert(charset_wctomb(charset, s, 127) == 1 && !strcmp(s, "\177.")); +} + +void test_iso1() +{ + struct charset *charset; + int wc; + char s[3]; + + charset = charset_find("iso-8859-1"); + test_any(charset); + + /* Decoder */ + wc = 0; + assert(charset_mbtowc(charset, &wc, "\302\200", 9) == 1 && wc == 0xc2); + + /* Encoder */ + strcpy(s, ".."); + assert(charset_wctomb(charset, s, 256) == -1 && !strcmp(s, "..")); + assert(charset_wctomb(charset, s, 255) == 1 && !strcmp(s, "\377.")); + assert(charset_wctomb(charset, s, 128) == 1 && !strcmp(s, "\200.")); +} + +void test_iso2() +{ + struct charset *charset; + int wc; + char s[3]; + + charset = charset_find("iso-8859-2"); + test_any(charset); + + /* Decoder */ + wc = 0; + assert(charset_mbtowc(charset, &wc, "\302\200", 9) == 1 && wc == 0xc2); + assert(charset_mbtowc(charset, &wc, "\377", 2) == 1 && wc == 0x2d9); + + /* Encoder */ + strcpy(s, ".."); + assert(charset_wctomb(charset, s, 256) == -1 && !strcmp(s, "..")); + assert(charset_wctomb(charset, s, 255) == -1 && !strcmp(s, "..")); + assert(charset_wctomb(charset, s, 258) == 1 && !strcmp(s, "\303.")); + assert(charset_wctomb(charset, s, 128) == 1 && !strcmp(s, "\200.")); +} + +void test_convert() +{ + const char *p; + char *q, *r; + char s[256]; + size_t n, n2; + int i; + + p = "\000x\302\200\375\277\277\277\277\277"; + assert(charset_convert("UTF-8", "UTF-8", p, 10, &q, &n) == 0 && + n == 10 && !strcmp(p, q)); + assert(charset_convert("UTF-8", "UTF-8", "x\301\277y", 4, &q, &n) == 2 && + n == 4 && !strcmp(q, "x##y")); + assert(charset_convert("UTF-8", "UTF-8", "x\301\277y", 4, 0, &n) == 2 && + n == 4); + assert(charset_convert("UTF-8", "UTF-8", "x\301\277y", 4, &q, 0) == 2 && + !strcmp(q, "x##y")); + assert(charset_convert("UTF-8", "iso-8859-1", + "\302\200\304\200x", 5, &q, &n) == 1 && + n == 3 && !strcmp(q, "\200?x")); + assert(charset_convert("iso-8859-1", "UTF-8", + "\000\200\377", 3, &q, &n) == 0 && + n == 5 && !memcmp(q, "\000\302\200\303\277", 5)); + assert(charset_convert("iso-8859-1", "iso-8859-1", + "\000\200\377", 3, &q, &n) == 0 && + n == 3 && !memcmp(q, "\000\200\377", 3)); + + assert(charset_convert("iso-8859-2", "utf-8", "\300", 1, &q, &n) == 0 && + n == 2 && !strcmp(q, "\305\224")); + assert(charset_convert("utf-8", "iso-8859-2", "\305\224", 2, &q, &n) == 0 && + n == 1 && !strcmp(q, "\300")); + + for (i = 0; i < 256; i++) + s[i] = i; + + assert(charset_convert("iso-8859-2", "utf-8", s, 256, &q, &n) == 0); + assert(charset_convert("utf-8", "iso-8859-2", q, n, &r, &n2) == 0); + assert(n2 == 256 && !memcmp(r, s, n2)); +} + +int main() +{ + test_utf8(); + test_ascii(); + test_iso1(); + test_iso2(); + + test_convert(); + + return 0; +} diff -Naur ../sources/mplayer/main/ogginfo_hack/i18n.h mplayer-cvs-build/ogginfo_hack/i18n.h --- ../sources/mplayer/main/ogginfo_hack/i18n.h 1970-01-01 01:00:00.000000000 +0100 +++ mplayer-cvs-build/ogginfo_hack/i18n.h 2003-12-17 22:13:02.000000000 +0100 @@ -0,0 +1,18 @@ +#ifndef VORBIS_TOOLS_I18N_H +#define VORBIS_TOOLS_I18N_H + +#ifdef ENABLE_NLS +#include +#define _(X) gettext(X) +#else +#define _(X) (X) +#define textdomain(X) +#define bindtextdomain(X, Y) +#endif +#ifdef gettext_noop +#define N_(X) gettext_noop(X) +#else +#define N_(X) (X) +#endif + +#endif diff -Naur ../sources/mplayer/main/ogginfo_hack/ogginfo2.c mplayer-cvs-build/ogginfo_hack/ogginfo2.c --- ../sources/mplayer/main/ogginfo_hack/ogginfo2.c 1970-01-01 01:00:00.000000000 +0100 +++ mplayer-cvs-build/ogginfo_hack/ogginfo2.c 2003-12-17 22:26:42.000000000 +0100 @@ -0,0 +1,735 @@ +/* Code adapted for mplayer ogginfo hack + Copyright 2003 Boris Buegling +*/ + +/* Ogginfo + * + * A tool to describe ogg file contents and metadata. + * + * Copyright 2002 Michael Smith + * Licensed under the GNU GPL, distributed with this program. + */ + + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include "utf8.h" +#include "i18n.h" + +#define CHUNK 4500 + +/* Different implementations have different format strings for 64 bit ints. */ +#ifdef _WIN32 +#define INT64FORMAT "%I64d" +#else +#define INT64FORMAT "%Ld" +#endif + +struct vorbis_release { + char *vendor_string; + char *desc; +} releases[] = { + {"Xiphophorus libVorbis I 20000508", "1.0 beta 1 or beta 2"}, + {"Xiphophorus libVorbis I 20001031", "1.0 beta 3"}, + {"Xiphophorus libVorbis I 20010225", "1.0 beta 4"}, + {"Xiphophorus libVorbis I 20010615", "1.0 rc1"}, + {"Xiphophorus libVorbis I 20010813", "1.0 rc2"}, + {"Xiphophorus libVorbis I 20011217", "1.0 rc3"}, + {"Xiphophorus libVorbis I 20011231", "1.0 rc3"}, + {"Xiph.Org libVorbis I 20020717", "1.0"}, + {NULL, NULL}, + }; + + +/* TODO: + * + * - detect decreasing granulepos + * - detect violations of muxing constraints + * - better EOS detection (when EOS not explicitly set) + * - detect granulepos 'gaps' (possibly vorbis-specific). + * - check for serial number == (unsigned)-1 (will break some tools?) + * - more options (e.g. less or more verbose) + */ + +typedef struct _stream_processor { + void (*process_page)(struct _stream_processor *, ogg_page *); + void (*process_end)(struct _stream_processor *); + int isillegal; + int shownillegal; + int isnew; + long seqno; + int lostseq; + + int start; + int end; + + int num; + char *type; + + ogg_uint32_t serial; /* must be 32 bit unsigned */ + ogg_stream_state os; + void *data; +} stream_processor; + +typedef struct { + stream_processor *streams; + int allocated; + int used; + + int in_headers; +} stream_set; + +typedef struct { + vorbis_info vi; + vorbis_comment vc; + + long bytes; + ogg_int64_t lastgranulepos; + + int doneheaders; +} misc_vorbis_info; + +static int printinfo = 1; +static int printwarn = 1; +static int verbose = 1; + +static stream_set *create_stream_set(void) { + stream_set *set = calloc(1, sizeof(stream_set)); + + set->streams = calloc(5, sizeof(stream_processor)); + set->allocated = 5; + set->used = 0; + + return set; +} + +static void info(char *format, ...) +{ + va_list ap; + + if(!printinfo) + return; + + va_start(ap, format); + vfprintf(stdout, format, ap); + va_end(ap); +} + +static void warn(char *format, ...) +{ + va_list ap; + + if(!printwarn) + return; + + va_start(ap, format); + vfprintf(stdout, format, ap); + va_end(ap); +} + +static void error(char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vfprintf(stdout, format, ap); + va_end(ap); +} + +static void vorbis_process(stream_processor *stream, ogg_page *page ) +{ + ogg_packet packet; + misc_vorbis_info *inf = stream->data; + int i, header=0; + int k; + + ogg_stream_pagein(&stream->os, page); + + while(ogg_stream_packetout(&stream->os, &packet) > 0) { + if(inf->doneheaders < 3) { + if(vorbis_synthesis_headerin(&inf->vi, &inf->vc, &packet) < 0) { + warn(_("Warning: Could not decode vorbis header " + "packet - invalid vorbis stream (%d)\n"), stream->num); + continue; + } + header = 1; + inf->doneheaders++; + if(inf->doneheaders == 3) { + if(ogg_page_granulepos(page) != 0 || ogg_stream_packetpeek(&stream->os, NULL) == 1) + warn(_("Warning: Vorbis stream %d does not have headers " + "correctly framed. Terminal header page contains " + "additional packets or has non-zero granulepos\n"), + stream->num); + info(_("Vorbis headers parsed for stream %d, " + "information follows...\n"), stream->num); + + info(_("Version: %d\n"), inf->vi.version); + k = 0; + while(releases[k].vendor_string) { + if(!strcmp(inf->vc.vendor, releases[k].vendor_string)) { + info(_("Vendor: %s (%s)\n"), inf->vc.vendor, + releases[k].desc); + break; + } + k++; + } + if(!releases[k].vendor_string) + info(_("Vendor: %s\n"), inf->vc.vendor); + info(_("Channels: %d\n"), inf->vi.channels); + info(_("Rate: %ld\n\n"), inf->vi.rate); + + if(inf->vi.bitrate_nominal > 0) + info(_("Nominal bitrate: %f kb/s\n"), + (double)inf->vi.bitrate_nominal / 1000.0); + else + info(_("Nominal bitrate not set\n")); + + if(inf->vi.bitrate_upper > 0) + info(_("Upper bitrate: %f kb/s\n"), + (double)inf->vi.bitrate_upper / 1000.0); + else + info(_("Upper bitrate not set\n")); + + if(inf->vi.bitrate_lower > 0) + info(_("Lower bitrate: %f kb/s\n"), + (double)inf->vi.bitrate_lower / 1000.0); + else + info(_("Lower bitrate not set\n")); + + if(inf->vc.comments > 0) + info(_("User comments section follows...\n")); + + for(i=0; i < inf->vc.comments; i++) { + char *sep = strchr(inf->vc.user_comments[i], '='); + char *decoded; + int j; + int broken = 0; + unsigned char *val; + int bytes; + int remaining; + + if(sep == NULL) { + warn(_("Warning: Comment %d in stream %d is invalidly " + "formatted, does not contain '=': \"%s\"\n"), + i, stream->num, inf->vc.user_comments[i]); + continue; + } + + for(j=0; j < sep-inf->vc.user_comments[i]; j++) { + if(inf->vc.user_comments[i][j] < 0x20 || + inf->vc.user_comments[i][j] > 0x7D) { + warn(_("Warning: Invalid comment fieldname in " + "comment %d (stream %d): \"%s\"\n"), + i, stream->num, inf->vc.user_comments[i]); + broken = 1; + break; + } + } + + if(broken) + continue; + + val = inf->vc.user_comments[i]; + + j = sep-inf->vc.user_comments[i]+1; + while(j < inf->vc.comment_lengths[i]) + { + remaining = inf->vc.comment_lengths[i] - j; + if((val[j] & 0x80) == 0) + bytes = 1; + else if((val[j] & 0x40) == 0x40) { + if((val[j] & 0x20) == 0) + bytes = 2; + else if((val[j] & 0x10) == 0) + bytes = 3; + else if((val[j] & 0x08) == 0) + bytes = 4; + else if((val[j] & 0x04) == 0) + bytes = 5; + else if((val[j] & 0x02) == 0) + bytes = 6; + else { + warn(_("Warning: Illegal UTF-8 sequence in " + "comment %d (stream %d): length " + "marker wrong\n"), + i, stream->num); + broken = 1; + break; + } + } + else { + warn(_("Warning: Illegal UTF-8 sequence in comment " + "%d (stream %d): length marker wrong\n"), + i, stream->num); + broken = 1; + break; + } + + if(bytes > remaining) { + warn(_("Warning: Illegal UTF-8 sequence in comment " + "%d (stream %d): too few bytes\n"), + i, stream->num); + broken = 1; + break; + } + + switch(bytes) { + case 1: + /* No more checks needed */ + break; + case 2: + if((val[j+1] & 0xC0) != 0x80) + broken = 1; + if((val[j] & 0xFE) == 0xC0) + broken = 1; + break; + case 3: + if(!((val[j] == 0xE0 && val[j+1] >= 0xA0 && + val[j+1] <= 0xBF && + (val[j+2] & 0xC0) == 0x80) || + (val[j] >= 0xE1 && val[j] <= 0xEC && + (val[j+1] & 0xC0) == 0x80 && + (val[j+2] & 0xC0) == 0x80) || + (val[j] == 0xED && val[j+1] >= 0x80 && + val[j+1] <= 0x9F && + (val[j+2] & 0xC0) == 0x80) || + (val[j] >= 0xEE && val[j] <= 0xEF && + (val[j+1] & 0xC0) == 0x80 && + (val[j+2] & 0xC0) == 0x80))) + broken = 1; + if(val[j] == 0xE0 && (val[j+1] & 0xE0) == 0x80) + broken = 1; + break; + case 4: + if(!((val[j] == 0xF0 && val[j+1] >= 0x90 && + val[j+1] <= 0xBF && + (val[j+2] & 0xC0) == 0x80 && + (val[j+3] & 0xC0) == 0x80) || + (val[j] >= 0xF1 && val[j] <= 0xF3 && + (val[j+1] & 0xC0) == 0x80 && + (val[j+2] & 0xC0) == 0x80 && + (val[j+3] & 0xC0) == 0x80) || + (val[j] == 0xF4 && val[j+1] >= 0x80 && + val[j+1] <= 0x8F && + (val[j+2] & 0xC0) == 0x80 && + (val[j+3] & 0xC0) == 0x80))) + broken = 1; + if(val[j] == 0xF0 && (val[j+1] & 0xF0) == 0x80) + broken = 1; + break; + /* 5 and 6 aren't actually allowed at this point*/ + case 5: + broken = 1; + break; + case 6: + broken = 1; + break; + } + + if(broken) { + warn(_("Warning: Illegal UTF-8 sequence in comment " + "%d (stream %d): invalid sequence\n"), + i, stream->num); + broken = 1; + break; + } + + j += bytes; + } + + if(!broken) { + if(utf8_decode(sep+1, &decoded) < 0) { + warn(_("Warning: Failure in utf8 decoder. This " + "should be impossible\n")); + continue; + } + *sep = 0; + info("\t%s=%s\n", inf->vc.user_comments[i], decoded); + free(decoded); + } + } + } + } + } + + if(!header) { + ogg_int64_t gp = ogg_page_granulepos(page); + if(gp > 0) { + if(gp < inf->lastgranulepos) + warn(_("Warning: granulepos in stream %d decreases from " + INT64FORMAT " to " INT64FORMAT "\n"), stream->num, + inf->lastgranulepos, gp); + inf->lastgranulepos = gp; + } + inf->bytes += page->header_len + page->body_len; + } +} + +static void vorbis_end(stream_processor *stream) +{ + misc_vorbis_info *inf = stream->data; + long minutes, seconds; + double bitrate, time; + + time = (double)inf->lastgranulepos / inf->vi.rate; + minutes = (long)time / 60; + seconds = (long)time - minutes*60; + bitrate = inf->bytes*8 / time / 1000.0; + + info(_("Vorbis stream %d:\n" + "\tTotal data length: %ld bytes\n" + "\tPlayback length: %ldm:%02lds\n" + "\tAverage bitrate: %f kbps\n"), + stream->num,inf->bytes, minutes, seconds, bitrate); + + vorbis_comment_clear(&inf->vc); + vorbis_info_clear(&inf->vi); + + free(stream->data); +} + +static void process_null(stream_processor *stream, ogg_page *page) +{ + /* This is for invalid streams. */ +} + +static void process_other(stream_processor *stream, ogg_page *page ) +{ + ogg_packet packet; + + ogg_stream_pagein(&stream->os, page); + + while(ogg_stream_packetout(&stream->os, &packet) > 0) { + /* Should we do anything here? Currently, we don't */ + } +} + + +static void free_stream_set(stream_set *set) +{ + int i; + for(i=0; i < set->used; i++) { + if(!set->streams[i].end) { + warn(_("Warning: EOS not set on stream %d\n"), + set->streams[i].num); + if(set->streams[i].process_end) + set->streams[i].process_end(&set->streams[i]); + } + ogg_stream_clear(&set->streams[i].os); + } + + free(set->streams); + free(set); +} + +static int streams_open(stream_set *set) +{ + int i; + int res=0; + for(i=0; i < set->used; i++) { + if(!set->streams[i].end) + res++; + } + + return res; +} + +static void null_start(stream_processor *stream) +{ + stream->process_end = NULL; + stream->type = "invalid"; + stream->process_page = process_null; +} + +static void other_start(stream_processor *stream, char *type) +{ + if(type) + stream->type = type; + else + stream->type = "unknown"; + stream->process_page = process_other; + stream->process_end = NULL; +} + +static void vorbis_start(stream_processor *stream) +{ + misc_vorbis_info *info; + + stream->type = "vorbis"; + stream->process_page = vorbis_process; + stream->process_end = vorbis_end; + + stream->data = calloc(1, sizeof(misc_vorbis_info)); + + info = stream->data; + + vorbis_comment_init(&info->vc); + vorbis_info_init(&info->vi); + +} + +static stream_processor *find_stream_processor(stream_set *set, ogg_page *page) +{ + ogg_uint32_t serial = ogg_page_serialno(page); + int i, found = 0; + int invalid = 0; + stream_processor *stream; + + for(i=0; i < set->used; i++) { + if(serial == set->streams[i].serial) { + /* We have a match! */ + found = 1; + stream = &(set->streams[i]); + + set->in_headers = 0; + /* if we have detected EOS, then this can't occur here. */ + if(stream->end) { + stream->isillegal = 1; + return stream; + } + + stream->isnew = 0; + stream->start = ogg_page_bos(page); + stream->end = ogg_page_eos(page); + stream->serial = serial; + return stream; + } + } + + /* If there are streams open, and we've reached the end of the + * headers, then we can't be starting a new stream. + * XXX: might this sometimes catch ok streams if EOS flag is missing, + * but the stream is otherwise ok? + */ + if(streams_open(set) && !set->in_headers) + invalid = 1; + + set->in_headers = 1; + + if(set->allocated < set->used) + stream = &set->streams[set->used]; + else { + set->allocated += 5; + set->streams = realloc(set->streams, sizeof(stream_processor)* + set->allocated); + stream = &set->streams[set->used]; + } + set->used++; + stream->num = set->used; /* We count from 1 */ + + stream->isnew = 1; + stream->isillegal = invalid; + + { + int res; + ogg_packet packet; + + /* We end up processing the header page twice, but that's ok. */ + ogg_stream_init(&stream->os, serial); + ogg_stream_pagein(&stream->os, page); + res = ogg_stream_packetout(&stream->os, &packet); + if(res <= 0) { + warn(_("Warning: Invalid header page, no packet found\n")); + null_start(stream); + } + else if(packet.bytes >= 7 && memcmp(packet.packet, "\001vorbis", 7)==0) + vorbis_start(stream); + else if(packet.bytes >= 8 && memcmp(packet.packet, "OggMIDI\0", 8)==0) + other_start(stream, "MIDI"); + else + other_start(stream, NULL); + + res = ogg_stream_packetout(&stream->os, &packet); + if(res > 0) { + warn(_("Warning: Invalid header page in stream %d, " + "contains multiple packets\n"), stream->num); + } + + /* re-init, ready for processing */ + ogg_stream_clear(&stream->os); + ogg_stream_init(&stream->os, serial); + } + + stream->start = ogg_page_bos(page); + stream->end = ogg_page_eos(page); + stream->serial = serial; + + return stream; +} + +static int get_next_page(FILE *f, ogg_sync_state *sync, ogg_page *page, + ogg_int64_t *written) +{ + int ret; + char *buffer; + int bytes; + + while((ret = ogg_sync_pageout(sync, page)) <= 0) { + if(ret < 0) + warn(_("Warning: Hole in data found at approximate offset " + INT64FORMAT " bytes. Corrupted ogg.\n"), *written); + + buffer = ogg_sync_buffer(sync, CHUNK); + bytes = fread(buffer, 1, CHUNK, f); + if(bytes <= 0) { + ogg_sync_wrote(sync, 0); + return 0; + } + ogg_sync_wrote(sync, bytes); + *written += bytes; + } + + return 1; +} + +void process_file(char *filename) { + FILE *file = fopen(filename, "rb"); + ogg_sync_state sync; + ogg_page page; + stream_set *processors = create_stream_set(); + int gotpage = 0; + ogg_int64_t written = 0; + + if(!file) { + error(_("Error opening input file \"%s\": %s\n"), filename, + strerror(errno)); + return; + } + + printf(_("Processing file \"%s\"...\n\n"), filename); + + ogg_sync_init(&sync); + + while(get_next_page(file, &sync, &page, &written)) { + stream_processor *p = find_stream_processor(processors, &page); + gotpage = 1; + + if(!p) { + error(_("Could not find a processor for stream, bailing\n")); + return; + } + + if(p->isillegal && !p->shownillegal) { + warn(_("Warning: illegally placed page(s) for logical stream %d\n" + "This indicates a corrupt ogg file.\n"), p->num); + p->shownillegal = 1; + continue; + } + + if(p->isnew) { + info(_("New logical stream (#%d, serial: %08x): type %s\n"), + p->num, p->serial, p->type); + if(!p->start) + warn(_("Warning: stream start flag not set on stream %d\n"), + p->num); + } + else if(p->start) + warn(_("Warning: stream start flag found in mid-stream " + "on stream %d\n"), p->num); + + if(p->seqno++ != ogg_page_pageno(&page)) { + if(!p->lostseq) + warn(_("Warning: sequence number gap in stream %d. Got page " + "%ld when expecting page %ld. Indicates missing data.\n" + ), p->num, ogg_page_pageno(&page), p->seqno - 1); + p->seqno = ogg_page_pageno(&page); + p->lostseq = 1; + } + else + p->lostseq = 0; + + if(!p->isillegal) { + p->process_page(p, &page); + + if(p->end) { + if(p->process_end) + p->process_end(p); + info(_("Logical stream %d ended\n"), p->num); + p->isillegal = 1; + } + } + } + + if(!gotpage) + error(_("Error: No ogg data found in file \"%s\".\n" + "Input probably not ogg.\n"), filename); + + free_stream_set(processors); + + ogg_sync_clear(&sync); + + fclose(file); +} + +static void usage(void) { + printf(_("ogginfo 1.0\n" + "(c) 2002 Michael Smith \n" + "\n" + "Usage: ogginfo [flags] files1.ogg [file2.ogg ... fileN.ogg]\n" + "Flags supported:\n" + "\t-h Show this help message\n" + "\t-q Make less verbose. Once will remove detailed informative\n" + "\t messages, two will remove warnings\n" + "\t-v Make more verbose. This may enable more detailed checks\n" + "\t for some stream types.\n\n")); +} + +#if 0 +int main(int argc, char **argv) { + int f, ret; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + if(argc < 2) { + fprintf(stderr, + _("Usage: ogginfo [flags] file1.ogg [file2.ogg ... fileN.ogg]\n" + "\n" + "Ogginfo is a tool for printing information about ogg files\n" + "and for diagnosing problems with them.\n" + "Full help shown with \"ogginfo -h\".\n")); + exit(1); + } + + while((ret = getopt(argc, argv, "hvq")) >= 0) { + switch(ret) { + case 'h': + usage(); + return 0; + case 'v': + verbose++; + break; + case 'q': + verbose--; + break; + } + } + + if(verbose < 1) + printinfo = 0; + if(verbose < 0) + printwarn = 0; + + if(optind >= argc) { + fprintf(stderr, + _("No input files specified. \"ogginfo -h\" for help\n")); + return 1; + } + + for(f=optind; f < argc; f++) { + process_file(argv[f]); + } + + return 0; +} +#endif diff -Naur ../sources/mplayer/main/ogginfo_hack/utf8.c mplayer-cvs-build/ogginfo_hack/utf8.c --- ../sources/mplayer/main/ogginfo_hack/utf8.c 1970-01-01 01:00:00.000000000 +0100 +++ mplayer-cvs-build/ogginfo_hack/utf8.c 2003-12-17 22:27:39.000000000 +0100 @@ -0,0 +1,320 @@ +/* + * Copyright (C) 2001 Peter Harris + * Copyright (C) 2001 Edmund Grimley Evans + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Convert a string between UTF-8 and the locale's charset. + */ + +#include +#include + +#include "utf8.h" + + +#ifdef _WIN32 + + /* Thanks to Peter Harris for this win32 + * code. + */ + +#include +#include + +static unsigned char *make_utf8_string(const wchar_t *unicode) +{ + int size = 0, index = 0, out_index = 0; + unsigned char *out; + unsigned short c; + + /* first calculate the size of the target string */ + c = unicode[index++]; + while(c) { + if(c < 0x0080) { + size += 1; + } else if(c < 0x0800) { + size += 2; + } else { + size += 3; + } + c = unicode[index++]; + } + + out = malloc(size + 1); + if (out == NULL) + return NULL; + index = 0; + + c = unicode[index++]; + while(c) + { + if(c < 0x080) { + out[out_index++] = (unsigned char)c; + } else if(c < 0x800) { + out[out_index++] = 0xc0 | (c >> 6); + out[out_index++] = 0x80 | (c & 0x3f); + } else { + out[out_index++] = 0xe0 | (c >> 12); + out[out_index++] = 0x80 | ((c >> 6) & 0x3f); + out[out_index++] = 0x80 | (c & 0x3f); + } + c = unicode[index++]; + } + out[out_index] = 0x00; + + return out; +} + +static wchar_t *make_unicode_string(const unsigned char *utf8) +{ + int size = 0, index = 0, out_index = 0; + wchar_t *out; + unsigned char c; + + /* first calculate the size of the target string */ + c = utf8[index++]; + while(c) { + if((c & 0x80) == 0) { + index += 0; + } else if((c & 0xe0) == 0xe0) { + index += 2; + } else { + index += 1; + } + size += 1; + c = utf8[index++]; + } + + out = malloc((size + 1) * sizeof(wchar_t)); + if (out == NULL) + return NULL; + index = 0; + + c = utf8[index++]; + while(c) + { + if((c & 0x80) == 0) { + out[out_index++] = c; + } else if((c & 0xe0) == 0xe0) { + out[out_index] = (c & 0x1F) << 12; + c = utf8[index++]; + out[out_index] |= (c & 0x3F) << 6; + c = utf8[index++]; + out[out_index++] |= (c & 0x3F); + } else { + out[out_index] = (c & 0x3F) << 6; + c = utf8[index++]; + out[out_index++] |= (c & 0x3F); + } + c = utf8[index++]; + } + out[out_index] = 0; + + return out; +} + +int utf8_encode(const char *from, char **to) +{ + wchar_t *unicode; + int wchars, err; + + wchars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from, + strlen(from), NULL, 0); + + if(wchars == 0) + { + fprintf(stderr, "Unicode translation error %d\n", GetLastError()); + return -1; + } + + unicode = calloc(wchars + 1, sizeof(unsigned short)); + if(unicode == NULL) + { + fprintf(stderr, "Out of memory processing string to UTF8\n"); + return -1; + } + + err = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from, + strlen(from), unicode, wchars); + if(err != wchars) + { + free(unicode); + fprintf(stderr, "Unicode translation error %d\n", GetLastError()); + return -1; + } + + /* On NT-based windows systems, we could use WideCharToMultiByte(), but + * MS doesn't actually have a consistent API across win32. + */ + *to = make_utf8_string(unicode); + + free(unicode); + return 0; +} + +int utf8_decode(const char *from, char **to) +{ + wchar_t *unicode; + int chars, err; + + /* On NT-based windows systems, we could use MultiByteToWideChar(CP_UTF8), but + * MS doesn't actually have a consistent API across win32. + */ + unicode = make_unicode_string(from); + if(unicode == NULL) + { + fprintf(stderr, "Out of memory processing string from UTF8 to UNICODE16\n"); + return -1; + } + + chars = WideCharToMultiByte(GetConsoleCP(), WC_COMPOSITECHECK, unicode, + -1, NULL, 0, NULL, NULL); + + if(chars == 0) + { + fprintf(stderr, "Unicode translation error %d\n", GetLastError()); + free(unicode); + return -1; + } + + *to = calloc(chars + 1, sizeof(unsigned char)); + if(*to == NULL) + { + fprintf(stderr, "Out of memory processing string to local charset\n"); + free(unicode); + return -1; + } + + err = WideCharToMultiByte(GetConsoleCP(), WC_COMPOSITECHECK, unicode, + -1, *to, chars, NULL, NULL); + if(err != chars) + { + fprintf(stderr, "Unicode translation error %d\n", GetLastError()); + free(unicode); + free(*to); + *to = NULL; + return -1; + } + + free(unicode); + return 0; +} + +#else /* End win32. Rest is for real operating systems */ + + +#ifdef HAVE_LANGINFO_CODESET +#include +#endif + +int iconvert(const char *fromcode, const char *tocode, + const char *from, size_t fromlen, + char **to, size_t *tolen); + +static char *current_charset = 0; /* means "US-ASCII" */ + +void convert_set_charset(const char *charset) +{ + + if (!charset) + charset = getenv("CHARSET"); + +#ifdef HAVE_LANGINFO_CODESET + if (!charset) + charset = nl_langinfo(CODESET); +#endif + + free(current_charset); + current_charset = 0; + if (charset && *charset) + current_charset = strdup(charset); +} + +static int convert_buffer(const char *fromcode, const char *tocode, + const char *from, size_t fromlen, + char **to, size_t *tolen) +{ + int ret = -1; + +#ifdef HAVE_ICONV + ret = iconvert(fromcode, tocode, from, fromlen, to, tolen); + if (ret != -1) + return ret; +#endif + +#ifndef HAVE_ICONV /* should be ifdef USE_CHARSET_CONVERT */ + ret = charset_convert(fromcode, tocode, from, fromlen, to, tolen); + if (ret != -1) + return ret; +#endif + + return ret; +} + +static int convert_string(const char *fromcode, const char *tocode, + const char *from, char **to, char replace) +{ + int ret; + size_t fromlen; + char *s; + + fromlen = strlen(from); + ret = convert_buffer(fromcode, tocode, from, fromlen, to, 0); + if (ret == -2) + return -1; + if (ret != -1) + return ret; + + s = malloc(fromlen + 1); + if (!s) + return -1; + strcpy(s, from); + *to = s; + for (; *s; s++) + if (*s & ~0x7f) + *s = replace; + return 3; +} + +int utf8_encode(const char *from, char **to) +{ + char *charset; + + if (!current_charset) + convert_set_charset(0); + charset = current_charset ? current_charset : "US-ASCII"; + return convert_string(charset, "UTF-8", from, to, '#'); +} + +int utf8_decode(const char *from, char **to) +{ + char *charset; + + if(*from == 0) { + *to = malloc(1); + **to = 0; + return 1; + } + + if (!current_charset) + convert_set_charset(0); + charset = current_charset ? current_charset : "US-ASCII"; + return convert_string("UTF-8", charset, from, to, '?'); +} + +#endif diff -Naur ../sources/mplayer/main/ogginfo_hack/utf8.h mplayer-cvs-build/ogginfo_hack/utf8.h --- ../sources/mplayer/main/ogginfo_hack/utf8.h 1970-01-01 01:00:00.000000000 +0100 +++ mplayer-cvs-build/ogginfo_hack/utf8.h 2003-12-17 22:12:55.000000000 +0100 @@ -0,0 +1,36 @@ + +/* + * Convert a string between UTF-8 and the locale's charset. + * Invalid bytes are replaced by '#', and characters that are + * not available in the target encoding are replaced by '?'. + * + * If the locale's charset is not set explicitly then it is + * obtained using nl_langinfo(CODESET), where available, the + * environment variable CHARSET, or assumed to be US-ASCII. + * + * Return value of conversion functions: + * + * -1 : memory allocation failed + * 0 : data was converted exactly + * 1 : valid data was converted approximately (using '?') + * 2 : input was invalid (but still converted, using '#') + * 3 : unknown encoding (but still converted, using '?') + */ + +#ifndef __UTF8_H +#define __UTF8_H + +#ifdef __cplusplus +extern "C" { +#endif + +void convert_set_charset(const char *charset); + +int utf8_encode(const char *from, char **to); +int utf8_decode(const char *from, char **to); + +#ifdef __cplusplus +} +#endif + +#endif /* __UTF8_H */