tizen 2.3 release
[framework/multimedia/gst-plugins-base0.10.git] / gst / subparse / samiparse.c
similarity index 81%
rename from wearable/gst/subparse/samiparse.c
rename to gst/subparse/samiparse.c
index 892ee7e..8220a82 100755 (executable)
@@ -40,6 +40,7 @@ struct _LanguageStruct
     gchar *language_code;
     gchar *language_key;
 };
+#define MAX_LANGUAGE 10
 #endif
 struct _GstSamiContext
 {
@@ -63,10 +64,10 @@ struct _GstSamiContext
 #ifdef SUBPARSE_MODIFICATION
   guint64 time3;                /* To store the last current time when language is changed */
   GList *lang_list;             /* Language list for an external subtitle file */
-  gboolean time_set;            /* If language is set already by user */
   gchar *current_language;      /* Current language parsed */
   gchar *desired_language;      /* Language set by user */
   gboolean language_changed;    /* language changed signal */
+  gboolean end_body;            /* </BODY> reached */
 #endif
 };
 
@@ -512,7 +513,23 @@ html_context_handle_element (HtmlContext * ctxt,
   for (i = 0; i < count; i += 2) {
     gchar *attr_name = NULL, *attr_value = NULL;
     gsize length;
+
+#ifdef SUBPARSE_MODIFICATION
+    /* sometimes count can unnecessarily be high value, because of unrequired "=" in subtitle file.
+     * In that case it should not crash */
+    if (!next)
+      break;
+#endif
+
     next = string_token (next + 1, "=", &attr_name);
+
+#ifdef SUBPARSE_MODIFICATION
+    /* sometimes count can unnecessarily be high value, because of unrequired "=" in subtitle file.
+     * In that case it should not crash */
+    if (!next)
+      break;
+#endif
+
     next = string_token (next + 1, " ", &attr_value);
 
     /* strip " or ' from attribute value */
@@ -836,7 +853,8 @@ handle_p (GstSamiContext * sctx, const gchar ** atts)
       key = atts[i];
       value = atts[i + 1];
 
-      if (sctx->current_language && value && strcmp(sctx->current_language, value))
+      if (sctx->current_language && value && strcmp(sctx->current_language, value)
+          && (sctx->time1 == sctx->time2))
         sctx->language_changed = TRUE;
 
       else if (!sctx->current_language)
@@ -844,12 +862,16 @@ handle_p (GstSamiContext * sctx, const gchar ** atts)
 
       if (key && !g_ascii_strcasecmp ("class", key) && value) {
         strcpy (sctx->current_language, value);
+        if (sctx->desired_language == NULL && key) {
+          sctx->desired_language = (gchar*) malloc (strlen(value) + 1);
+          strcpy(sctx->desired_language, value);
+          GST_LOG("no language list was found and desired lang was set to %s",sctx->desired_language);
+        }
       }
       if (sctx->language_changed)
       {
-         sctx->time1 = sctx->time3;
-         sctx->time2 = sctx->time1;
-         sctx->time_set = FALSE;
+         sctx->time1 = 0;
+         sctx->time2 = sctx->time3;
          sctx->language_changed = FALSE;
       }
       if (!value)
@@ -867,6 +889,10 @@ handle_start_language_list (GstSamiContext * sctx, const gchar ** atts)
   GstLangStruct *temp = NULL;
 
   if (atts != NULL) {
+    if (g_list_length (sctx->lang_list)) {
+      GST_LOG ("We already got the language list");
+      return;
+    }
     for (i = 0; (atts[attrIndex] != NULL); i++) {
       const gchar *key, *value;
 
@@ -957,6 +983,11 @@ handle_end_element (HtmlContext * ctx, const char *name, gpointer user_data)
       (!g_ascii_strcasecmp ("sami", name))) {
     /* We will usually have one buffer left when the body is closed
      * as we need the next sync to actually send it */
+
+#ifdef SUBPARSE_MODIFICATION
+    sctx->end_body = TRUE;
+#endif
+
     if (sctx->buf->len != 0) {
       /* Only set a new start time if we don't have text pending */
       if (sctx->resultbuf->len == 0)
@@ -1026,9 +1057,9 @@ sami_context_init (ParserState * state)
 #ifdef SUBPARSE_MODIFICATION
   context->current_language = NULL;
   context->desired_language = NULL;
-  context->time_set = FALSE;
   context->lang_list = NULL;
   context->language_changed = FALSE;
+  context->end_body = FALSE;
 #endif
   state->user_data = context;
 }
@@ -1099,16 +1130,186 @@ sami_context_change_language (ParserState * state)
   GstSamiContext *context = (GstSamiContext *) state->user_data;
   GST_LOG ("**********desired language was %s**************", context->desired_language);
   free (context->desired_language);
-  context->desired_language = state->current_language;
-  context->time_set = TRUE;
+  if(state->current_language) {
+    context->desired_language = state->current_language;
+  } else {
+    context->desired_language = state->msl_language;
+  }
   GST_LOG ("desired language changed to %s", context->desired_language);
 }
+
+gchar *
+sami_convert_to_utf8 (const gchar * str, gsize len, const gchar * encoding,
+    gsize * consumed, GError ** err, GstSubParse * self)
+{
+  gchar *ret = NULL;
+
+  /* The char cast is necessary in glib < 2.24 */
+  ret =
+      g_convert_with_fallback (str, len, "UTF-8", encoding, (char *) "*",
+      consumed, NULL, err);
+
+  if (ret == NULL)
+  {
+    GST_DEBUG_OBJECT (self, "g_convert_with_fallback returns NULL");
+    return ret;
+  }
+
+  /* + 3 to skip UTF-8 BOM if it was added */
+  len = strlen (ret);
+  if (len >= 3 && (guint8) ret[0] == 0xEF && (guint8) ret[1] == 0xBB
+      && (guint8) ret[2] == 0xBF)
+    g_memmove (ret, ret + 3, len + 1 - 3);
+
+  return ret;
+}
+
+gboolean
+sami_validate_langlist_body(GList * lang_list, GstSubParse * self){
+  gchar * file_path_type = NULL;
+  gchar * file_path = NULL;
+  gchar   line[1024];
+  FILE  * fp = NULL;
+  guint i = 0, found_count = 0;
+  const guint list_len = g_list_length(lang_list);
+  gboolean counter[MAX_LANGUAGE];
+  struct LangStruct
+  {
+      gchar *language_code;
+      gchar *language_key;
+  } * lang;
+
+  GstQuery *cquery;
+  GstStructure *structure;
+  const GValue *value;
+  structure = gst_structure_new ("FileSrcURI",
+                                 "file-uri", G_TYPE_STRING, NULL, NULL);
+
+  cquery = gst_query_new_application (GST_QUERY_CUSTOM, structure);
+
+  if (!gst_pad_peer_query (self->sinkpad, cquery))
+  {
+    GST_DEBUG_OBJECT (self, "failed to query SMI file path");
+    gst_query_unref (cquery);
+    return FALSE;
+  }
+  structure = gst_query_get_structure (cquery);
+  value = gst_structure_get_value (structure, "file-uri");
+  file_path = g_strdup (g_value_get_string (value));
+
+  if (file_path == NULL){
+    GST_DEBUG_OBJECT (self, "could not parse the SMI file path");
+    gst_query_unref (cquery);
+    return FALSE;
+  }
+  gst_query_unref (cquery);
+
+  GST_INFO_OBJECT (self, "file path comes as %s", file_path);
+
+  file_path_type = g_strndup ((gchar *) file_path, 4);
+  GST_INFO_OBJECT (self, "received file path by query = %s,%s", file_path,file_path_type);
+  if (!g_strcmp0(file_path_type, "file")){
+    file_path += 7;
+    GST_INFO_OBJECT (self, "file path comes as %s", file_path);
+
+    fp = fopen (file_path, "r");
+    if (!fp){
+      GST_DEBUG_OBJECT (self, "failed to open file");
+      return FALSE;
+    }
+
+    for(i=0;i<list_len;i++){
+      counter[i] = FALSE;
+    }
+
+    while(!feof(fp) && found_count < list_len){
+      GError *err = NULL;
+      gsize * consumed = NULL;
+      gint gap = 0;
+      guint charCount = 0;
+      gchar* result = NULL;
+      gchar* temp = NULL;
+      gchar* temp_lang = NULL;
+      gchar * temp1 = NULL;
+      gchar *con_temp_lang = NULL;
+      gchar *con_temp = NULL;
+      gboolean conversion = TRUE;
+      charCount = fread (line, sizeof(char), 1024, fp);
+      if (!charCount) {
+        GST_WARNING_OBJECT (self, "fread returned zero bytes");
+        continue;
+      }
+      GST_DEBUG("value of detected encoding is %s and self encoding is %s",self->detected_encoding,self->encoding);
+      if (self->detected_encoding && strcmp (self->detected_encoding, "UTF-8") && conversion){
+        result = sami_convert_to_utf8 (line, charCount, self->detected_encoding, consumed, &err, self);
+      }
+      if(result == NULL) {
+         result = line;
+         conversion =  FALSE;
+      }
+      con_temp = g_utf8_strdown (result,strlen(result));
+      temp = con_temp;
+      while(con_temp) {
+        con_temp = g_strstr_len(con_temp, strlen(con_temp),"class=");
+        if(con_temp) {
+          temp1 = g_strstr_len(con_temp+1, strlen(con_temp),"class=");
+        }
+        if(temp1 && con_temp){
+          gap = strlen(con_temp)-strlen(temp1);
+        }else if(con_temp) {
+          gap = strlen(con_temp);
+        } else {
+          continue;
+        }
+        if(con_temp){
+          for(i=0;i<list_len;i++){
+            if(counter[i]==TRUE){
+              con_temp=con_temp+1;
+              continue;
+            }
+            lang = (struct LangStruct *) g_list_nth_data(lang_list,i);
+            if(lang) {
+              temp_lang = (gchar*)g_malloc(strlen(lang->language_key)+1);
+              strcpy(temp_lang,lang->language_key);
+              con_temp_lang = g_utf8_strdown (temp_lang,strlen(temp_lang));
+              if(g_strstr_len(con_temp,gap,con_temp_lang)){
+                found_count++;
+                counter[i]=TRUE;
+                GST_INFO_OBJECT (self, " valid Language in list : [%s]", lang->language_key);
+                con_temp=con_temp+1;
+              }
+              g_free(temp_lang);
+              g_free(con_temp_lang);
+            }
+          }
+        }
+      }
+      if(conversion)
+       g_free (result);
+      if(temp)
+       g_free(temp);
+
+    }
+
+    if(found_count < list_len){
+      for(i=0;i<list_len;i++){
+        if(counter[i]==FALSE)
+          lang_list = g_list_delete_link(lang_list,g_list_nth(lang_list,i));
+      }
+    }
+  }
+  return TRUE;
+}
 #endif
 
 gchar *
 parse_sami (ParserState * state, const gchar * line)
 {
   gchar *ret = NULL;
+#ifdef SUBPARSE_MODIFICATION
+  gint64 clip_start = 0, clip_stop = 0;
+  gboolean in_seg = FALSE;
+#endif
   GstSamiContext *context = (GstSamiContext *) state->user_data;
 
   gchar *unescaped = unescape_string (line);
@@ -1124,7 +1325,7 @@ parse_sami (ParserState * state, const gchar * line)
   g_free (unescaped);
 #ifdef SUBPARSE_MODIFICATION
   if (context->desired_language && context->current_language) {
-    if (!strcmp(context->current_language, context->desired_language)) {
+    if ((!strcmp(context->current_language, context->desired_language)) || context->end_body) {
 #endif
       if (context->has_result) {
         if (context->rubybuf->len) {
@@ -1140,8 +1341,21 @@ parse_sami (ParserState * state, const gchar * line)
         context->has_result = FALSE;
       }
 #ifdef SUBPARSE_MODIFICATION
+      context->end_body = FALSE;
     }
   }
+  /* Check our segment start/stop */
+  in_seg = gst_segment_clip (state->segment, GST_FORMAT_TIME,
+             state->start_time, state->start_time + state->duration, &clip_start,
+             &clip_stop);
+
+  /* No need to send that text if it's out of segment */
+  if (in_seg) {
+    state->start_time = clip_start;
+    state->duration = clip_stop - clip_start;
+  } else {
+    return NULL;
+  }
 #endif
   return ret;
 }