tools: gst-inspect: prettify type names for strings
[platform/upstream/gstreamer.git] / subprojects / gstreamer / tools / gst-inspect.c
index 7056f8e..328809a 100644 (file)
 #include <io.h>
 #endif
 
+#ifdef __APPLE__
+#include <TargetConditionals.h>
+#endif
+
 /* "R" : support color
  * "X" : do not clear the screen when leaving the pager
  * "F" : skip the pager if content fit into the screen
@@ -118,6 +122,14 @@ GMainLoop *loop = NULL;
 #define FEATURE_RANK_COLOR    (colored_output? CYAN : "")
 #define FEATURE_PROTO_COLOR   (colored_output? BRYELLOW : "")
 
+#define GST_DOC_BASE_URL "https://gstreamer.freedesktop.org/documentation"
+
+static const gchar *gstreamer_modules[] = {
+  "gstreamer", "gst-plugins-base", "gst-plugins-good", "gst-plugins-ugly",
+  "gst-plugins-bad", "gst-editing-services", "gst-libav", "gst-rtsp-server",
+  "gstreamer-vaapi", NULL
+};
+
 static char *_name = NULL;
 static int indent = 0;
 
@@ -243,9 +255,10 @@ get_rank_name (char *s, gint rank)
 }
 
 static void
-print_factory_details_info (GstElementFactory * factory)
+print_factory_details_info (GstElementFactory * factory, GstPlugin * plugin)
 {
   gchar **keys, **k;
+  gboolean seen_doc_uri = FALSE;
   GstRank rank;
   char s[40];
 
@@ -266,9 +279,42 @@ print_factory_details_info (GstElementFactory * factory)
       key[0] = g_ascii_toupper (key[0]);
       n_print ("%s%-25s%s%s%s\n", PROP_NAME_COLOR, key, PROP_VALUE_COLOR, val,
           RESET_COLOR);
+      seen_doc_uri =
+          seen_doc_uri || g_str_equal (key, GST_ELEMENT_METADATA_DOC_URI);
     }
     g_strfreev (keys);
   }
+
+  if (!seen_doc_uri && plugin != NULL &&
+      !gst_element_factory_get_skip_documentation (factory)) {
+    const gchar *module = gst_plugin_get_source (plugin);
+    const gchar *origin = gst_plugin_get_origin (plugin);
+
+    /* gst-plugins-rs has per-plugin module names so need to check origin there */
+    if (g_strv_contains (gstreamer_modules, module)
+        || (origin != NULL && g_str_has_suffix (origin, "/gst-plugins-rs"))) {
+      GList *features;
+
+      features =
+          gst_registry_get_feature_list_by_plugin (gst_registry_get (),
+          gst_plugin_get_name (plugin));
+
+      /* if the plugin only has a single feature, plugin page == feature page */
+      if (features != NULL && features->next == NULL) {
+        n_print ("%s%-25s%s%s%s/%s/#%s-page%s\n", PROP_NAME_COLOR,
+            "Documentation", RESET_COLOR, PROP_VALUE_COLOR, GST_DOC_BASE_URL,
+            gst_plugin_get_name (plugin), GST_OBJECT_NAME (factory),
+            RESET_COLOR);
+      } else {
+        n_print ("%s%-25s%s%s%s/%s/%s.html%s\n", PROP_NAME_COLOR,
+            "Documentation", RESET_COLOR, PROP_VALUE_COLOR, GST_DOC_BASE_URL,
+            gst_plugin_get_name (plugin), GST_OBJECT_NAME (factory),
+            RESET_COLOR);
+      }
+      gst_plugin_feature_list_free (features);
+    }
+  }
+
   pop_indent ();
   n_print ("\n");
 }
@@ -363,7 +409,7 @@ flags_to_string (GFlagsValue * vals, guint flags)
   G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_DEPRECATED | \
   GST_PARAM_CONTROLLABLE | GST_PARAM_MUTABLE_PLAYING | \
   GST_PARAM_MUTABLE_PAUSED | GST_PARAM_MUTABLE_READY | \
-  GST_PARAM_CONDITIONALLY_AVAILABLE)
+  GST_PARAM_CONDITIONALLY_AVAILABLE | GST_PARAM_DOC_SHOW_DEFAULT)
 
 static int
 sort_gparamspecs (GParamSpec ** a, GParamSpec ** b)
@@ -386,6 +432,7 @@ print_object_properties_info (GObject * obj, GObjectClass * obj_class,
       (GCompareDataFunc) sort_gparamspecs, NULL);
 
   n_print ("%s%s%s:\n", HEADING_COLOR, desc, RESET_COLOR);
+  n_print ("\n");
 
   push_indent ();
 
@@ -702,6 +749,15 @@ print_object_properties_info (GObject * obj, GObjectClass * obj_class,
         } else if (param->value_type == GST_TYPE_ARRAY) {
           GstParamSpecArray *parray = GST_PARAM_SPEC_ARRAY_LIST (param);
 
+          if (GST_VALUE_HOLDS_ARRAY (&value)) {
+            gchar *def = gst_value_serialize (&value);
+
+            n_print ("%sDefault%s: \"%s\"\n", PROP_ATTR_VALUE_COLOR,
+                RESET_COLOR, def);
+
+            g_free (def);
+          }
+
           if (parray->element_spec) {
             n_print ("%sGstValueArray of GValues of type%s %s\"%s\"%s",
                 PROP_VALUE_COLOR, RESET_COLOR, DATATYPE_COLOR,
@@ -725,6 +781,8 @@ print_object_properties_info (GObject * obj, GObjectClass * obj_class,
     pop_indent_n (11);
 
     g_value_reset (&value);
+
+    n_print ("\n");
   }
   if (num_properties == 0)
     n_print ("%snone%s\n", PROP_VALUE_COLOR, RESET_COLOR);
@@ -757,7 +815,7 @@ gst_static_pad_compare_func (gconstpointer p1, gconstpointer p2)
 static void
 print_pad_templates_info (GstElement * element, GstElementFactory * factory)
 {
-  GList *pads;
+  GList *pads, *tmp;
   GstStaticPadTemplate *padtemplate;
   GstPadTemplate *tmpl;
 
@@ -773,9 +831,9 @@ print_pad_templates_info (GstElement * element, GstElementFactory * factory)
   pads = g_list_copy ((GList *)
       gst_element_factory_get_static_pad_templates (factory));
   pads = g_list_sort (pads, gst_static_pad_compare_func);
-  while (pads) {
-    padtemplate = (GstStaticPadTemplate *) (pads->data);
-    pads = g_list_next (pads);
+
+  for (tmp = pads; tmp; tmp = tmp->next) {
+    padtemplate = (GstStaticPadTemplate *) (tmp->data);
 
     if (padtemplate->direction == GST_PAD_SRC)
       n_print ("%sSRC template%s: %s'%s'%s\n", PROP_NAME_COLOR, RESET_COLOR,
@@ -832,7 +890,7 @@ print_pad_templates_info (GstElement * element, GstElementFactory * factory)
 
     pop_indent ();
 
-    if (pads != NULL)
+    if (tmp->next)
       n_print ("\n");
   }
   g_list_free (pads);
@@ -1010,6 +1068,21 @@ gtype_needs_ptr_marker (GType type)
   return FALSE;
 }
 
+static const gchar *
+pretty_type_name (GType type, const gchar ** p_pmark)
+{
+  if (type == G_TYPE_STRING) {
+    *p_pmark = " * ";
+    return "gchar";
+  } else if (type == G_TYPE_STRV) {
+    *p_pmark = " ** ";
+    return "gchar";
+  } else {
+    *p_pmark = gtype_needs_ptr_marker (type) ? " * " : " ";
+    return g_type_name (type);
+  }
+}
+
 static void
 print_signal_info (GstElement * element)
 {
@@ -1067,6 +1140,7 @@ print_signal_info (GstElement * element)
         n_print ("%sElement Signals%s:\n", HEADING_COLOR, RESET_COLOR);
       else
         n_print ("%sElement Actions%s:\n", HEADING_COLOR, RESET_COLOR);
+      n_print ("\n");
     } else {
       continue;
     }
@@ -1074,37 +1148,39 @@ print_signal_info (GstElement * element)
     for (l = found_signals; l; l = l->next) {
       gchar *indent;
       const gchar *pmark;
+      const gchar *retval_type_name;
       int indent_len;
 
       query = (GSignalQuery *) l->data;
-      indent_len = strlen (query->signal_name) +
-          strlen (g_type_name (query->return_type)) + 24;
-
-      if (gtype_needs_ptr_marker (query->return_type)) {
-        pmark = "* ";
-        indent_len += 2;
-      } else {
-        pmark = " ";
-      }
+      retval_type_name = pretty_type_name (query->return_type, &pmark);
+      indent_len =
+          strlen (query->signal_name) + strlen (retval_type_name) + 24 +
+          strlen (pmark) - 1;
 
       indent = g_new0 (gchar, indent_len + 1);
       memset (indent, ' ', indent_len);
 
-      n_print ("  %s\"%s\"%s :  %s%s%s%suser_function%s (%s%s%s* object%s",
+      n_print ("  %s\"%s\"%s :  %s%s%s%suser_function%s (%s%s%s * object%s",
           PROP_NAME_COLOR, query->signal_name, RESET_COLOR,
-          DATATYPE_COLOR, g_type_name (query->return_type), PROP_VALUE_COLOR,
+          DATATYPE_COLOR, retval_type_name, PROP_VALUE_COLOR,
           pmark, RESET_COLOR, DATATYPE_COLOR, g_type_name (type),
           PROP_VALUE_COLOR, RESET_COLOR);
 
       for (j = 0; j < query->n_params; j++) {
-        const gchar *type_name, *asterisk;
+        const gchar *type_name, *asterisk, *const_prefix;
 
-        type_name = g_type_name (query->param_types[j]);
-        asterisk = gtype_needs_ptr_marker (query->param_types[j]) ? "*" : "";
+        type_name = pretty_type_name (query->param_types[j], &asterisk);
+
+        /* Add const prefix for string and string array arguments */
+        if (g_str_equal (type_name, "gchar") && strchr (asterisk, '*')) {
+          const_prefix = "const ";
+        } else {
+          const_prefix = "";
+        }
 
         g_print (",\n");
-        n_print ("%s%s%s%s%s arg%d%s", indent, DATATYPE_COLOR, type_name,
-            PROP_VALUE_COLOR, asterisk, j, RESET_COLOR);
+        n_print ("%s%s%s%s%s%sarg%d%s", indent, DATATYPE_COLOR, const_prefix,
+            type_name, PROP_VALUE_COLOR, asterisk, j, RESET_COLOR);
       }
 
       if (k == 0) {
@@ -1115,6 +1191,7 @@ print_signal_info (GstElement * element)
         g_print (");\n");
 
       g_free (indent);
+      g_print ("\n");
     }
 
     if (found_signals) {
@@ -1443,15 +1520,18 @@ print_all_uri_handlers (void)
 static void
 print_plugin_info (GstPlugin * plugin)
 {
+  const gchar *plugin_name = gst_plugin_get_name (plugin);
   const gchar *release_date = gst_plugin_get_release_date_string (plugin);
   const gchar *filename = gst_plugin_get_filename (plugin);
+  const gchar *module = gst_plugin_get_source (plugin);
+  const gchar *origin = gst_plugin_get_origin (plugin);
 
   n_print ("%sPlugin Details%s:\n", HEADING_COLOR, RESET_COLOR);
 
   push_indent ();
 
   n_print ("%s%-25s%s%s%s%s\n", PROP_NAME_COLOR, "Name", RESET_COLOR,
-      PROP_VALUE_COLOR, gst_plugin_get_name (plugin), RESET_COLOR);
+      PROP_VALUE_COLOR, plugin_name, RESET_COLOR);
   n_print ("%s%-25s%s%s%s%s\n", PROP_NAME_COLOR, "Description", RESET_COLOR,
       PROP_VALUE_COLOR, gst_plugin_get_description (plugin), RESET_COLOR);
   n_print ("%s%-25s%s%s%s%s\n", PROP_NAME_COLOR, "Filename", RESET_COLOR,
@@ -1461,7 +1541,15 @@ print_plugin_info (GstPlugin * plugin)
   n_print ("%s%-25s%s%s%s%s\n", PROP_NAME_COLOR, "License", RESET_COLOR,
       PROP_VALUE_COLOR, gst_plugin_get_license (plugin), RESET_COLOR);
   n_print ("%s%-25s%s%s%s%s\n", PROP_NAME_COLOR, "Source module", RESET_COLOR,
-      PROP_VALUE_COLOR, gst_plugin_get_source (plugin), RESET_COLOR);
+      PROP_VALUE_COLOR, module, RESET_COLOR);
+
+  /* gst-plugins-rs has per-plugin module names so need to check origin there */
+  if (g_strv_contains (gstreamer_modules, module)
+      || (origin != NULL && g_str_has_suffix (origin, "/gst-plugins-rs"))) {
+    n_print ("%s%-25s%s%s%s/%s/%s\n", PROP_NAME_COLOR, "Documentation",
+        RESET_COLOR, PROP_VALUE_COLOR, GST_DOC_BASE_URL, plugin_name,
+        RESET_COLOR);
+  }
 
   if (release_date != NULL) {
     const gchar *tz = "(UTC)";
@@ -1649,9 +1737,10 @@ print_element_info (GstPluginFeature * feature, gboolean print_names)
   else
     _name = NULL;
 
-  print_factory_details_info (factory);
-
   plugin = gst_plugin_feature_get_plugin (GST_PLUGIN_FEATURE (factory));
+
+  print_factory_details_info (factory, plugin);
+
   if (plugin) {
     print_plugin_info (plugin);
     gst_object_unref (plugin);
@@ -2024,8 +2113,8 @@ _parse_sort_type (const gchar * option_name, const gchar * optarg,
   return FALSE;
 }
 
-int
-main (int argc, char *argv[])
+static int
+real_main (int argc, char *argv[])
 {
   gboolean print_all = FALSE;
   gboolean do_print_blacklist = FALSE;
@@ -2104,7 +2193,12 @@ main (int argc, char *argv[])
   ctx = g_option_context_new ("[ELEMENT-NAME | PLUGIN-NAME]");
   g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE);
   g_option_context_add_group (ctx, gst_init_get_option_group ());
-  if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
+#if defined(G_OS_WIN32) && !defined(GST_CHECK_MAIN)
+  if (!g_option_context_parse_strv (ctx, &argv, &err))
+#else
+  if (!g_option_context_parse (ctx, &argc, &argv, &err))
+#endif
+  {
     g_printerr ("Error initializing: %s\n", err->message);
     g_clear_error (&err);
     g_option_context_free (ctx);
@@ -2115,6 +2209,10 @@ main (int argc, char *argv[])
   gst_init (&argc, &argv);
 #endif
 
+#if defined(G_OS_WIN32) && !defined(GST_CHECK_MAIN)
+  argc = g_strv_length (argv);
+#endif
+
   gst_tools_print_version ();
 
   if (print_all && argc > 1) {
@@ -2267,3 +2365,26 @@ done:
 
   return exit_code;
 }
+
+int
+main (int argc, char *argv[])
+{
+  int ret;
+
+  /* gstinspect.c calls this function */
+#if defined(G_OS_WIN32) && !defined(GST_CHECK_MAIN)
+  argv = g_win32_get_command_line ();
+#endif
+
+#if defined(__APPLE__) && TARGET_OS_MAC && !TARGET_OS_IPHONE
+  ret = gst_macos_main ((GstMainFunc) real_main, argc, argv, NULL);
+#else
+  ret = real_main (argc, argv);
+#endif
+
+#if defined(G_OS_WIN32) && !defined(GST_CHECK_MAIN)
+  g_strfreev (argv);
+#endif
+
+  return ret;
+}