--- gst-plugins-0.8.11/gst/subparse/gstsubparse.h~	2005-09-23 01:13:34.011522000 +0900
+++ gst-plugins-0.8.11/gst/subparse/gstsubparse.h	2005-09-23 02:01:47.093165750 +0900
@@ -69,6 +69,11 @@
       GString *buf;
       guint64 time;
     } mpsub;
+    struct {
+      int state;
+      GString *inbuf, *outbuf;
+      guint64 time1, time2;
+    } sami;
   } state;
 
   /* seek */
--- gst-plugins-0.8.11/gst/subparse/gstsubparse.c~	2005-09-23 01:13:38.127779250 +0900
+++ gst-plugins-0.8.11/gst/subparse/gstsubparse.c	2005-09-23 02:38:35.689128500 +0900
@@ -38,7 +38,8 @@
   GST_SUB_PARSE_FORMAT_UNKNOWN = 0,
   GST_SUB_PARSE_FORMAT_MDVDSUB = 1,
   GST_SUB_PARSE_FORMAT_SUBRIP = 2,
-  GST_SUB_PARSE_FORMAT_MPSUB = 3
+  GST_SUB_PARSE_FORMAT_MPSUB = 3,
+  GST_SUB_PARSE_FORMAT_SAMI = 4
 } GstSubParseFormat;
 
 static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
@@ -229,7 +230,7 @@
 convert_encoding (GstSubparse * self, const gchar * str, gsize len)
 {
   gsize bytes_read, bytes_written;
-  gchar *rv;
+  gchar *rv, *enc;
   GString *converted;
 
   converted = g_string_new (NULL);
@@ -241,7 +242,11 @@
     g_free (dbg);
 #endif
 
-    rv = g_locale_to_utf8 (str, len, &bytes_read, &bytes_written, NULL);
+     if((enc = getenv("GST_SUBTITLE_ENCODING"))) {
+       rv = g_convert_with_fallback(str, len, "UTF-8", enc, "?", &bytes_read, &bytes_written, NULL);
+     }else {
+       rv = g_locale_to_utf8 (str, len, &bytes_read, &bytes_written, NULL);
+     }
     if (rv) {
       g_string_append_len (converted, rv, bytes_written);
       g_free (rv);
@@ -545,6 +550,131 @@
   self->parser.parse = parse_mpsub;
 }
 
+static GString * 
+escape_amp (GString * ostr)
+{
+  int i;
+  gchar * c = ostr->str;
+  GString * str = g_string_new(NULL);
+  for( i = 0; i < ostr->len ; i++, c++) {
+    if(*c == '&') {
+      if(!strncasecmp(c+1, "nbsp;", 5)) {
+        str = g_string_append_c(str, ' '); /* convert to space */
+        c += 5;
+        i += 5;
+      }else if(!strncasecmp(c+1, "lt;", 3)) {
+        str = g_string_append(str, "&lt;");
+        c += 3;
+        i += 3;
+      }else if(!strncasecmp(c+1, "gt;", 3)) {
+        str = g_string_append(str, "&gt;");
+        c += 3;
+        i += 3;
+      }else if(!strncasecmp(c+1, "quot;", 5)) {
+        str = g_string_append(str, "&quot;");
+        c += 5;
+        i += 5;
+      }else if(!strncasecmp(c+1, "amp;", 4)) {
+        str = g_string_append(str, "&amp;");
+        c += 4;
+        i += 4;
+      }else if(!strncasecmp(c+1, "apos;", 5)) {
+        str = g_string_append(str, "&apos;");
+        c += 5;
+        i += 5;
+      }else {
+        str = g_string_append(str, "&amp;"); /* convert to amp */
+      }
+    } else {
+      str = g_string_append_c(str, *c);
+    }
+  }
+  return str;
+}
+
+static gchar *
+parse_sami (GstSubparse * self, guint64 * out_start_time,
+	    guint64 * out_end_time, gboolean after_seek)
+{
+  gchar *line;
+  GString *inbuf = self->state.sami.inbuf;
+  GString *outbuf = self->state.sami.outbuf;
+
+  line = get_next_line (self);
+  inbuf = g_string_append (inbuf, line);
+  g_free (line);
+
+  while (1) {
+    line = strchr (inbuf->str, '<');
+    if (line) {
+      if (self->state.sami.state != 0)
+	outbuf = g_string_append_len (outbuf, inbuf->str, line - inbuf->str);
+      inbuf = g_string_erase (inbuf, 0, line - inbuf->str);
+    } else {
+      if (self->state.sami.state != 0) {
+	outbuf = g_string_append (outbuf, inbuf->str);
+      }
+      g_string_truncate (inbuf, 0);
+      break;
+    }
+
+    if (!strncasecmp (inbuf->str, "<sync", 5)) {
+      inbuf = g_string_erase (inbuf, 0, 5);	/* strip <sync */
+      line = strchr (inbuf->str, '=') + 1;
+      inbuf = g_string_erase (inbuf, 0, line - inbuf->str);	/* strip start= */
+      self->state.sami.time1 = self->state.sami.time2;
+      self->state.sami.time2 = atoi (inbuf->str) * GST_MSECOND;
+
+      line = strchr (inbuf->str, '>') + 1;
+      inbuf = g_string_erase (inbuf, 0, line - inbuf->str);
+
+      gchar *retval = NULL;
+
+      GString * escaped = escape_amp(outbuf);
+      retval = g_strdup(escaped->str);
+      g_string_free(escaped, TRUE);
+      *out_start_time = self->state.sami.time1;
+      *out_end_time = self->state.sami.time2;
+      g_string_truncate (outbuf, 0);
+
+      self->state.sami.outbuf = outbuf;
+      self->state.sami.inbuf = inbuf;
+      //printf ("time : %lld - %lld \"%s\"\n", *out_start_time, *out_end_time, retval);
+      return retval;
+    } else if (!strncasecmp (inbuf->str, "<font", 5)) {
+
+    } else if (!strncasecmp (inbuf->str, "<body", 5)) {
+      self->state.sami.state = 1;
+    } else if (!strncasecmp (inbuf->str, "<br", 3)) {
+      g_string_append_c (self->state.subrip.buf, '\n');
+      inbuf = g_string_erase (inbuf, 0, 3);
+    }
+    line = strchr (inbuf->str, '>') + 1;
+    inbuf = g_string_erase (inbuf, 0, line - inbuf->str);
+  }
+  self->state.sami.inbuf = inbuf;
+  self->state.sami.outbuf = outbuf;;
+  return NULL;
+}
+
+static void
+parse_sami_deinit (GstSubparse * self)
+{
+  g_string_free (self->state.sami.outbuf, TRUE);
+  g_string_free (self->state.sami.inbuf, TRUE);
+}
+
+static void
+parse_sami_init (GstSubparse * self)
+{
+  self->state.sami.state = 0;
+  self->state.sami.inbuf = g_string_new (NULL);
+  self->state.sami.outbuf = g_string_new (NULL);
+  self->parser.deinit = parse_sami_deinit;
+  self->parser.parse = parse_sami;
+}
+
+
 /*
  * FIXME: maybe we should pass along a second argument, the preceding
  * text buffer, because that is how this originally worked, even though
@@ -597,6 +727,11 @@
     g_free (match_str);
     return GST_SUB_PARSE_FORMAT_MPSUB;
   }
+  if (strstr (match_str, "<SAMI>")) {
+    GST_LOG ("subparse: SAMI (time based) format detected");
+    g_free (match_str);
+    return GST_SUB_PARSE_FORMAT_SAMI;
+  }
 
   GST_WARNING ("subparse: subtitle format autodetection failed!");
   g_free (match_str);
@@ -646,6 +781,12 @@
       res = gst_pad_set_explicit_caps (self->srcpad,
           gst_caps_new_simple ("text/plain", NULL));
       break;
+    case GST_SUB_PARSE_FORMAT_SAMI:
+      GST_DEBUG ("SAMI format detected");
+      parse_sami_init (self);
+      res = gst_pad_set_explicit_caps (self->srcpad,
+          gst_caps_new_simple ("text/plain", NULL));
+      break;
     case GST_SUB_PARSE_FORMAT_UNKNOWN:
     default:
       GST_DEBUG ("no subtitle format detected");
@@ -783,6 +924,9 @@
     case GST_SUB_PARSE_FORMAT_MPSUB:
       GST_DEBUG ("SubRip format detected");
       break;
+    case GST_SUB_PARSE_FORMAT_SAMI:
+      GST_DEBUG ("SAMI format detected");
+      break;
     case GST_SUB_PARSE_FORMAT_UNKNOWN:
       GST_DEBUG ("no subtitle format detected");
       return;
@@ -795,7 +939,7 @@
 static gboolean
 plugin_init (GstPlugin * plugin)
 {
-  static gchar *sub_exts[] = { "srt", "sub", "mpsub", "mdvd", NULL };
+  static gchar *sub_exts[] = { "srt", "sub", "mpsub", "mdvd", "smi", NULL };
 
   GST_DEBUG_CATEGORY_INIT (subparse_debug, "subparse", 0, ".sub parser");
 
