Added qmafw-gst-subtitles-renderer-0.0.55 for Meego Harmattan 1.2
[mafwsubrenderer] / qmafw-gst-subtitles-renderer / src / mafw-gst-renderer-utils.c
diff --git a/qmafw-gst-subtitles-renderer/src/mafw-gst-renderer-utils.c b/qmafw-gst-subtitles-renderer/src/mafw-gst-renderer-utils.c
new file mode 100644 (file)
index 0000000..49364fd
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * This file is a part of MAFW
+ *
+ * Copyright (C) 2007, 2008, 2009 Nokia Corporation, all rights reserved.
+ *
+ * Contact: Visa Smolander <visa.smolander@nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+
+#include <string.h>
+#include <gio/gio.h>
+
+#include <gst/gst.h>
+
+#include "mafw-gst-renderer-utils.h"
+
+#undef  G_LOG_DOMAIN
+#define G_LOG_DOMAIN "mafw-gst-renderer-utils"
+
+/**
+ * convert_utf8:
+ * @src: string.
+ * @dst: location for utf8 version of @src.
+ *
+ * Tries to convert @src into UTF-8, placing it into @dst.
+ *
+ * Returns: TRUE on success.
+ */
+gboolean convert_utf8(const gchar *src, gchar **dst)
+{
+    GError *error;
+
+    if (!src || !dst)
+        return FALSE;
+    if (g_utf8_validate(src, -1, NULL)) {
+        *dst = g_strdup(src);
+        return TRUE;
+    }
+    error = NULL;
+    *dst = g_locale_to_utf8(src, -1, NULL, NULL, &error);
+    if (error) {
+        g_warning("utf8 conversion failed '%s' (%d: %s)",
+              src, error->code, error->message);
+        g_error_free(error);
+        return FALSE;
+    }
+    return TRUE;
+}
+
+/**
+ * uri_is_stream:
+ * @uri: the URI to be checked.
+ *
+ * Check if given URI is a stream (not a local resource).  To not depend on
+ * gnomevfs for this, we assume everything that doesn't start with "file://" is
+ * a stream.
+ *
+ * Returns: TRUE if the URI is not local.
+ */
+gboolean uri_is_stream(const gchar *uri)
+{
+    if (uri == NULL) {
+        return FALSE;
+    } else {
+        return !g_str_has_prefix(uri, "file://");
+    }
+}
+
+/** remap_gst_error_code:
+ *
+ * @error: pointer to error
+ * 
+ * Maps a Gst error to worker errror code,
+ * mapping follows roughly the one from FMAFW gst-renderer.
+ *
+ * Returns: possibly remapped ecode if the domain was certain Gst domain.
+*/
+gint remap_gst_error_code(const GError *error)
+{
+
+    gint new_err_code;
+
+    if (error->domain == GST_RESOURCE_ERROR)
+    {
+        /* handle RESOURCE errors */
+        switch (error->code)
+        {
+            case GST_RESOURCE_ERROR_READ:
+                new_err_code = WORKER_ERROR_STREAM_DISCONNECTED;
+                break;
+            case GST_RESOURCE_ERROR_NOT_FOUND:
+            case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
+            case GST_RESOURCE_ERROR_OPEN_READ:
+                new_err_code = WORKER_ERROR_MEDIA_NOT_FOUND;
+                break;
+            case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
+                new_err_code = WORKER_ERROR_UNABLE_TO_PERFORM;
+                break;
+            case GST_RESOURCE_ERROR_WRITE:
+                /* DSP renderers send ERROR_WRITE when they find
+                   corrupted data */
+                new_err_code = WORKER_ERROR_CORRUPTED_FILE;
+                break;
+            case GST_RESOURCE_ERROR_SEEK:
+                new_err_code = WORKER_ERROR_CANNOT_SET_POSITION;
+                break;
+            default:
+                /* Unknown RESOURCE error */
+                new_err_code = WORKER_ERROR_UNABLE_TO_PERFORM;
+                break;
+        }
+    }
+    else if (error->domain == GST_STREAM_ERROR)
+    {
+        /* handle STREAM errors */
+        switch (error->code) {
+            case GST_STREAM_ERROR_TYPE_NOT_FOUND:
+                new_err_code = WORKER_ERROR_TYPE_NOT_AVAILABLE;
+                break;
+            case GST_STREAM_ERROR_FORMAT:
+            case GST_STREAM_ERROR_WRONG_TYPE:
+            case GST_STREAM_ERROR_FAILED:
+                new_err_code = WORKER_ERROR_UNSUPPORTED_TYPE;
+                break;
+            case GST_STREAM_ERROR_DECODE:
+            case GST_STREAM_ERROR_DEMUX:
+                new_err_code = WORKER_ERROR_CORRUPTED_FILE;
+                break;
+            case GST_STREAM_ERROR_CODEC_NOT_FOUND:
+                new_err_code = WORKER_ERROR_CODEC_NOT_FOUND;
+                break;
+            case GST_STREAM_ERROR_DECRYPT:
+            case GST_STREAM_ERROR_DECRYPT_NOKEY:
+                new_err_code = WORKER_ERROR_DRM_NOT_ALLOWED;
+                break;
+            case WORKER_ERROR_POSSIBLY_PLAYLIST_TYPE:
+                new_err_code = WORKER_ERROR_POSSIBLY_PLAYLIST_TYPE;
+                break;
+            default:
+                /* Unknown STREAM error */
+                new_err_code = WORKER_ERROR_UNABLE_TO_PERFORM;
+                break;
+        }
+    }
+    else if( error->domain == GST_CORE_ERROR )
+    {
+        switch( error->code ) {
+            case GST_CORE_ERROR_MISSING_PLUGIN:
+                new_err_code = WORKER_ERROR_UNSUPPORTED_TYPE;
+                break;
+            default:
+                new_err_code = error->code;
+        }
+    }
+    else
+    {
+        /* by default return the original code */
+        new_err_code = error->code;
+    }
+
+    return new_err_code;
+
+}
+
+/*
+ * Imported from totem-uri.c
+ * Copyright (C) 2004 Bastien Nocera
+ */
+
+/* List from xine-lib's demux_sputext.c */
+static const char subtitle_ext[][4] = {
+    "sub",
+    "srt",
+    "smi",
+    "ssa",
+    "ass",
+    "asc"
+};
+
+static inline gboolean
+uri_exists (const char *uri)
+{
+    GFile *file = g_file_new_for_uri (uri);
+    if (file != NULL) {
+        if (g_file_query_exists (file, NULL)) {
+            g_object_unref (file);
+                return TRUE;
+        }
+        g_object_unref (file);
+    }
+    return FALSE;
+}
+
+static char *
+uri_get_subtitle_for_uri (const char *uri)
+{
+    char *subtitle;
+    guint len, i;
+    gint suffix;
+
+    /* Find the filename suffix delimiter */
+    len = strlen (uri);
+    for (suffix = len - 1; suffix > 0; suffix--) {
+        if (uri[suffix] == G_DIR_SEPARATOR ||
+            (uri[suffix] == '/')) {
+                /* This filename has no extension; we'll need to 
+                 * add one */
+                suffix = len;
+                break;
+        }
+        if (uri[suffix] == '.') {
+            /* Found our extension marker */
+            break;
+        }
+    }
+    if (suffix < 0)
+        return NULL;
+
+    /* Generate a subtitle string with room at the end to store the
+     * 3 character extensions for which we want to search */
+    subtitle = g_malloc0 (suffix + 4 + 1);
+    g_return_val_if_fail (subtitle != NULL, NULL);
+    g_strlcpy (subtitle, uri, suffix + 4 + 1);
+    g_strlcpy (subtitle + suffix, ".???", 5);
+
+    /* Search for any files with one of our known subtitle extensions */
+    for (i = 0; i < G_N_ELEMENTS (subtitle_ext) ; i++) {
+        char *subtitle_ext_upper;
+        memcpy (subtitle + suffix + 1, subtitle_ext[i], 3);
+
+        if (uri_exists (subtitle))
+            return subtitle;
+
+        /* Check with upper-cased extension */
+        subtitle_ext_upper = g_ascii_strup (subtitle_ext[i], -1);
+        memcpy (subtitle + suffix + 1, subtitle_ext_upper, 3);
+        g_free (subtitle_ext_upper);
+
+        if (uri_exists (subtitle))
+            return subtitle;
+    }
+    g_free (subtitle);
+    return NULL;
+}
+
+static char *
+uri_get_subtitle_in_subdir (GFile *file, const char *subdir)
+{
+    char *filename, *subtitle, *full_path_str;
+    GFile *parent, *full_path, *directory;
+
+    /* Get the sibling directory @subdir of the file @file */
+    parent = g_file_get_parent (file);
+    directory = g_file_get_child (parent, subdir);
+    g_object_unref (parent);
+
+    /* Get the file of the same name as @file in the @subdir directory */
+    filename = g_file_get_basename (file);
+    full_path = g_file_get_child (directory, filename);
+    g_object_unref (directory);
+    g_free (filename);
+
+    /* Get the subtitles from that URI */
+    full_path_str = g_file_get_uri (full_path);
+    g_object_unref (full_path);
+    subtitle = uri_get_subtitle_for_uri (full_path_str);
+    g_free (full_path_str);
+
+    return subtitle;
+}
+
+char *
+uri_get_subtitle_uri (const char *uri)
+{
+    GFile *file;
+    char *subtitle;
+
+    if (g_str_has_prefix (uri, "http") != FALSE)
+        return NULL;
+
+    /* Has the user specified a subtitle file manually? */
+    if (strstr (uri, "#subtitle:") != NULL)
+        return NULL;
+
+    /* Does the file exist? */
+    file = g_file_new_for_uri (uri);
+    if (g_file_query_exists (file, NULL) != TRUE) {
+        g_object_unref (file);
+        return NULL;
+    }
+
+    /* Try in the current directory */
+    subtitle = uri_get_subtitle_for_uri (uri);
+    if (subtitle != NULL) {
+        g_object_unref (file);
+        return subtitle;
+    }
+
+    subtitle = uri_get_subtitle_in_subdir (file, "subtitles");
+    g_object_unref (file);
+
+    return subtitle;
+}