[MPlayer-dev-eng] [PATCH] implement the setlocale feature

Fengguang Wu fengguang.wu at gmail.com
Tue Jun 20 10:30:35 CEST 2006


On Mon, Jun 19, 2006 at 11:36:39AM +0200, Reimar Döffinger wrote:
> Hi,
> On Mon, Jun 19, 2006 at 12:55:36PM +0800, Fengguang Wu wrote:
> > Attached a patch using UTF-8 unconditionally, comments are welcome.
> 
> Much better, but still the original code is really broken.
> 1) There are already utf8->utf16 conversion functions in MPlayer, like
> libvo/sub.c, utf8_get_char so iconv is not needed.
> 2) Stuff like strlen(path)*2 to get the length of UTF-16 string will only
> work for pure ascii as well...

Thanks, updated the patch according to your comments.

I take the freedom to write a new utf8to16() function which was
originally written by Masanao Izumo <iz at onicos.co.jp>.

It can detect non-utf8 sequences. The intension is to fall back to
local charset if necessary. It's a worthy hack, IMHO.

Regards,
Wu
-------------- next part --------------
Index: libmpdemux/asf_mmst_streaming.c
===================================================================
--- libmpdemux/asf_mmst_streaming.c	(revision 18754)
+++ libmpdemux/asf_mmst_streaming.c	(working copy)
@@ -25,17 +25,6 @@
 #include <winsock2.h>
 #endif
 
-#ifndef USE_SETLOCALE
-#undef USE_ICONV
-#endif
-
-#ifdef USE_ICONV
-#include <iconv.h>
-#ifdef USE_LANGINFO
-#include <langinfo.h>
-#endif
-#endif
-
 #include "url.h"
 #include "asf.h"
 
@@ -119,40 +108,62 @@
   }
 }
 
-#ifdef USE_ICONV
-static iconv_t url_conv;
-#endif
+static char * utf8to16(char *dest, char *src, int len)
+{
+  int i;
+  unsigned char c, char2, char3;
+  long cc;
 
-static void string_utf16(char *dest, char *src, int len) {
-    int i;
-#ifdef USE_ICONV
-    size_t len1, len2;
-    char *ip, *op;
+  i = 0;
+  while(i < len) {
+    c = src[i++];
+    switch(c >> 4) {
+      case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+        // 0xxxxxxx
+        cc = c;
+        break;
+      case 12: case 13:
+        // 110x xxxx   10xx xxxx
+        char2 = src[i++];
+        if ((char2 & 0xC0) == 0x80)
+          cc = ((c & 0x1F) << 6) | (char2 & 0x3F);
+        else
+          cc = -1;
+        break;
+      case 14:
+        // 1110 xxxx  10xx xxxx  10xx xxxx
+        char2 = src[i++];
+        char3 = src[i++];
+        if ((char2 & 0xC0) == 0x80 && (char3 & 0xC0) == 0x80)
+          cc = ((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | (char3 & 0x3F);
+        else
+          cc = -1;
+        break;
+      default:
+        cc = -1;
+    }
 
-    if (url_conv != (iconv_t)(-1))
-    {
-    memset(dest, 0, 1000);
-    len1 = len; len2 = 1000;
-    ip = src; op = dest;
+    if (cc == -1)
+      return 0;
 
-    iconv(url_conv, &ip, &len1, &op, &len2);
-    }
-    else
-    {
-#endif
-	if (len > 499) len = 499;
-	for (i=0; i<len; i++) {
-	    dest[i*2] = src[i];
-	    dest[i*2+1] = 0;
-        }
-	/* trailing zeroes */
-	dest[i*2] = 0;
-	dest[i*2+1] = 0;
-#ifdef USE_ICONV
-    }
-#endif
+    *dest++ = cc;
+    *dest++ = cc >> 8;
+  }
+  return dest;
 }
 
+static int string_utf16(char *dest, char *src, int len)
+{
+  char *end = utf8to16(dest, src, len);
+
+  if (end)
+    return (end - dest) / 2;
+
+  /* TODO: try to convert from local charset */
+  /* printf("utf8to16(%s, %d) failed\n", src, len); */
+  return 0;
+}
+
 static void get_answer (int s) 
 {
   char  data[BUF_SIZE];
@@ -550,19 +561,10 @@
   * cmd 1 0x01 
   * */
 
-  /* prepare for the url encoding conversion */
-#ifdef USE_ICONV
-#ifdef USE_LANGINFO
-  url_conv = iconv_open("UTF-16LE",nl_langinfo(CODESET));
-#else
-  url_conv = iconv_open("UTF-16LE", NULL);
-#endif
-#endif
-
   snprintf (str, 1023, "\034\003NSPlayer/7.0.0.1956; {33715801-BAB3-9D85-24E9-03B90328270A}; Host: %s", url1->hostname);
-  string_utf16 (data, str, strlen(str));
+  len = string_utf16 (data, str, strlen(str));
 // send_command(s, commandno ....)
-  send_command (s, 1, 0, 0x0004000b, strlen(str)*2+2, data);
+  send_command (s, 1, 0, 0x0004000b, len*2+2, data);
 
   len = recv (s, data, BUF_SIZE, 0) ;
 
@@ -583,9 +585,9 @@
   /* This command sends file path (at server) and file name request to the server.
   * 0x5 */
 
-  string_utf16 (&data[8], path, strlen(path));
+  len = string_utf16 (&data[8], path, strlen(path));
   memset (data, 0, 8);
-  send_command (s, 5, 0, 0, strlen(path)*2+10, data);
+  send_command (s, 5, 0, 0, len*2+10, data);
   free(path);
 
   get_answer (s);
@@ -656,10 +658,5 @@
   packet_length1 = packet_length;
   mp_msg(MSGT_NETWORK,MSGL_INFO,"mmst packet_length = %d\n", packet_length);
 
-#ifdef USE_ICONV
-  if (url_conv != (iconv_t)(-1))
-    iconv_close(url_conv);
-#endif
-
   return 0;
 }


More information about the MPlayer-dev-eng mailing list