encoding-target: Add API for list all categories and targets
authorEdward Hervey <edward.hervey@collabora.co.uk>
Mon, 3 Jan 2011 12:20:19 +0000 (13:20 +0100)
committerEdward Hervey <bilboed@bilboed.com>
Wed, 5 Jan 2011 19:54:21 +0000 (20:54 +0100)
API: gst_encoding_list_available_categories
API: gst_encoding_list_all_targets

docs/libs/gst-plugins-base-libs-sections.txt
gst-libs/gst/pbutils/encoding-target.c
gst-libs/gst/pbutils/encoding-target.h
tests/check/libs/profile.c
win32/common/libgstpbutils.def

index e42c956..29969fe 100644 (file)
@@ -1964,6 +1964,8 @@ gst_encoding_target_save
 gst_encoding_target_save_to
 gst_encoding_target_load
 gst_encoding_target_load_from
+gst_encoding_list_all_targets
+gst_encoding_list_available_categories
 <SUBSECTION Standard>
 GST_ENCODING_PROFILE
 GST_IS_ENCODING_PROFILE
index 6565bd9..faee8c3 100644 (file)
@@ -950,3 +950,184 @@ gst_encoding_target_save (GstEncodingTarget * target, GError ** error)
 
   return TRUE;
 }
+
+static GList *
+get_categories (gchar * path)
+{
+  GList *res = NULL;
+  GDir *topdir;
+  const gchar *subdirname;
+
+  topdir = g_dir_open (path, 0, NULL);
+  if (G_UNLIKELY (topdir == NULL))
+    return NULL;
+
+  while ((subdirname = g_dir_read_name (topdir))) {
+    gchar *ltmp = g_build_filename (path, subdirname, NULL);
+
+    if (g_file_test (ltmp, G_FILE_TEST_IS_DIR)) {
+      res = g_list_append (res, (gpointer) g_strdup (subdirname));
+    }
+    g_free (ltmp);
+  }
+
+  g_dir_close (topdir);
+
+  return res;
+}
+
+/**
+ * gst_encoding_list_available_categories:
+ *
+ * Lists all #GstEncodingTarget categories present on disk.
+ *
+ * Returns: (transfer full) (element-type gchar*): A list
+ * of #GstEncodingTarget categories.
+*/
+GList *
+gst_encoding_list_available_categories (void)
+{
+  GList *res = NULL;
+  GList *tmp1, *tmp2;
+  gchar *topdir;
+
+  /* First try user-local categories */
+  topdir = g_build_filename (g_get_home_dir (), ".gstreamer-0.10",
+      "encoding-profile", NULL);
+  res = get_categories (topdir);
+  g_free (topdir);
+
+  /* Extend with system-wide categories */
+  topdir = g_build_filename (GST_DATADIR, "gstreamer-" GST_MAJORMINOR,
+      "encoding-profile", NULL);
+  tmp1 = get_categories (topdir);
+  g_free (topdir);
+
+  for (tmp2 = tmp1; tmp2; tmp2 = tmp2->next) {
+    gchar *name = (gchar *) tmp2->data;
+    if (!g_list_find_custom (res, name, (GCompareFunc) g_strcmp0))
+      res = g_list_append (res, (gpointer) name);
+    else
+      g_free (name);
+  }
+  g_free (tmp1);
+
+  return res;
+}
+
+static inline GList *
+sub_get_all_targets (gchar * subdir)
+{
+  GList *res = NULL;
+  const gchar *filename;
+  GDir *dir;
+  GstEncodingTarget *target;
+
+  dir = g_dir_open (subdir, 0, NULL);
+  if (G_UNLIKELY (dir == NULL))
+    return NULL;
+
+  while ((filename = g_dir_read_name (dir))) {
+    gchar *fullname;
+
+    /* Only try files ending with .gstprofile */
+    if (!g_str_has_suffix (filename, ".gstprofile"))
+      continue;
+
+    fullname = g_build_filename (subdir, filename, NULL);
+    target = gst_encoding_target_load_from (fullname, NULL);
+    if (target) {
+      res = g_list_append (res, target);
+    } else
+      GST_WARNING ("Failed to get a target from %s", fullname);
+    g_free (fullname);
+  }
+  g_dir_close (dir);
+
+  return res;
+}
+
+static inline GList *
+get_all_targets (gchar * topdir, const gchar * categoryname)
+{
+  GList *res = NULL;
+
+  if (categoryname) {
+    gchar *subdir = g_build_filename (topdir, categoryname, NULL);
+    /* Try to open the directory */
+    res = sub_get_all_targets (subdir);
+    g_free (subdir);
+  } else {
+    const gchar *subdirname;
+    GDir *dir = g_dir_open (topdir, 0, NULL);
+
+    if (G_UNLIKELY (dir == NULL))
+      return NULL;
+
+    while ((subdirname = g_dir_read_name (dir))) {
+      gchar *ltmp = g_build_filename (topdir, subdirname, NULL);
+
+      if (g_file_test (ltmp, G_FILE_TEST_IS_DIR)) {
+        res = g_list_concat (res, sub_get_all_targets (ltmp));
+      }
+      g_free (ltmp);
+    }
+    g_dir_close (dir);
+  }
+
+  return res;
+}
+
+static guint
+compare_targets (const GstEncodingTarget * ta, const GstEncodingTarget * tb)
+{
+  if (!g_strcmp0 (ta->name, tb->name)
+      && !g_strcmp0 (ta->category, tb->category))
+    return -1;
+
+  return 0;
+}
+
+/**
+ * gst_encoding_list_all_targets:
+ * @categoryname: (allow-none): The category, for ex: #GST_ENCODING_CATEGORY_DEVICE.
+ * Can be NULL.
+ *
+ * List all available #GstEncodingTarget for the specified category, or all categories
+ * if @categoryname is NULL.
+ *
+ * Returns: (transfer full) (element-type GstEncodingTarget): The list of #GstEncodingTarget
+ */
+GList *
+gst_encoding_list_all_targets (const gchar * categoryname)
+{
+  GList *res;
+  GList *tmp1, *tmp2;
+  gchar *topdir;
+
+  /* Get user-locals */
+  topdir = g_build_filename (g_get_home_dir (), ".gstreamer-0.10",
+      "encoding-profile", NULL);
+  res = get_all_targets (topdir, categoryname);
+  g_free (topdir);
+
+  /* Get system-wide */
+  topdir = g_build_filename (GST_DATADIR, "gstreamer-" GST_MAJORMINOR,
+      "encoding-profile", NULL);
+  tmp1 = get_all_targets (topdir, categoryname);
+  g_free (topdir);
+
+  /* Merge system-wide targets */
+  /* FIXME : We should merge the system-wide profiles into the user-locals
+   * instead of stopping at identical target names */
+  for (tmp2 = tmp1; tmp2; tmp2 = tmp2->next) {
+    GstEncodingTarget *target = (GstEncodingTarget *) tmp2->data;
+    if (g_list_find_custom (res, target, (GCompareFunc) compare_targets))
+      gst_encoding_target_unref (target);
+    else
+      res = g_list_append (res, target);
+  }
+  g_list_free (tmp1);
+
+  return res;
+}
index fb73654..bb5b409 100644 (file)
@@ -102,6 +102,9 @@ GstEncodingTarget *gst_encoding_target_load (const gchar *name,
 GstEncodingTarget *gst_encoding_target_load_from (const gchar *path,
                                                  GError **error);
 
+GList *gst_encoding_list_available_categories (void);
+GList *gst_encoding_list_all_targets (const gchar * categoryname);
+
 G_END_DECLS
 
 #endif /* __GST_PROFILE_REGISTRY_H__ */
index adedbba..deed294 100644 (file)
@@ -464,6 +464,52 @@ GST_START_TEST (test_loading_profile)
 
 GST_END_TEST;
 
+GST_START_TEST (test_target_list)
+{
+  GList *categories;
+  GList *targets;
+  GList *tmp;
+
+  /* Make sure we get our test category in the available categories */
+  categories = gst_encoding_list_available_categories ();
+  fail_if (categories == NULL);
+  fail_if (g_list_find_custom (categories, "herding",
+          (GCompareFunc) g_strcmp0) == NULL);
+  g_list_foreach (categories, (GFunc) g_free, NULL);
+  g_list_free (categories);
+
+  /* Try getting all available targets with a specified category */
+  targets = gst_encoding_list_all_targets ("herding");
+  fail_if (targets == NULL);
+  for (tmp = targets; tmp; tmp = tmp->next) {
+    GstEncodingTarget *target = (GstEncodingTarget *) tmp->data;
+    if (!g_strcmp0 (gst_encoding_target_get_name (target), "myponytarget"))
+      break;
+  }
+  /* If tmp is NULL, it means we iterated the whole list without finding
+   * our target */
+  fail_if (tmp == NULL);
+  g_list_foreach (targets, (GFunc) gst_mini_object_unref, NULL);
+  g_list_free (targets);
+
+  /* Try getting all available targets without a specified category */
+  targets = gst_encoding_list_all_targets (NULL);
+  fail_if (targets == NULL);
+  for (tmp = targets; tmp; tmp = tmp->next) {
+    GstEncodingTarget *target = (GstEncodingTarget *) tmp->data;
+    if (!g_strcmp0 (gst_encoding_target_get_name (target), "myponytarget"))
+      break;
+  }
+  /* If tmp is NULL, it means we iterated the whole list without finding
+   * our target */
+  fail_if (tmp == NULL);
+  g_list_foreach (targets, (GFunc) gst_mini_object_unref, NULL);
+  g_list_free (targets);
+}
+
+GST_END_TEST;
+
+
 static const gchar *profile_string = "\
 [_gstencodingtarget_]\n\
 name=myponytarget\n\
@@ -564,6 +610,7 @@ profile_suite (void)
   if (can_write) {
     tcase_add_test (tc_chain, test_loading_profile);
     tcase_add_test (tc_chain, test_saving_profile);
+    tcase_add_test (tc_chain, test_target_list);
   }
 
   tcase_add_unchecked_fixture (tc_chain, test_setup, test_teardown);
index 333bc68..63c125d 100644 (file)
@@ -65,6 +65,8 @@ EXPORTS
        gst_encoding_container_profile_get_profiles
        gst_encoding_container_profile_get_type
        gst_encoding_container_profile_new
+       gst_encoding_list_all_targets
+       gst_encoding_list_available_categories
        gst_encoding_profile_find
        gst_encoding_profile_get_description
        gst_encoding_profile_get_format