Index: gst-libs/gst/pbutils/missing-plugins.c
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-base/gst-libs/gst/pbutils/missing-plugins.c,v
retrieving revision 1.8
diff -u -p -r1.8 missing-plugins.c
--- gst-libs/gst/pbutils/missing-plugins.c	26 Aug 2007 14:14:33 -0000	1.8
+++ gst-libs/gst/pbutils/missing-plugins.c	26 Aug 2007 15:03:00 -0000
@@ -415,6 +415,7 @@ gst_missing_plugin_message_get_installer
   type = gst_structure_get_string (msg->structure, "type");
   g_assert (type != NULL);      /* validity already checked above */
 
+  /* FIXME: use gst_installer_detail_new() here too */
   str = g_string_new (GST_DETAIL_STRING_MARKER "|");
   g_string_append_printf (str, "%u.%u|", GST_VERSION_MAJOR, GST_VERSION_MINOR);
 
@@ -594,3 +595,206 @@ gst_is_missing_plugin_message (GstMessag
 
   return gst_structure_has_name (msg->structure, "missing-plugin");
 }
+
+/* takes ownership of the description */
+static gchar *
+gst_installer_detail_new (gchar * description, const gchar * type,
+    const gchar * detail)
+{
+  const gchar *progname;
+  GString *s;
+
+  s = g_string_new (GST_DETAIL_STRING_MARKER "|");
+  g_string_append_printf (s, "%u.%u|", GST_VERSION_MAJOR, GST_VERSION_MINOR);
+
+  progname = (const gchar *) g_get_prgname ();
+  if (progname) {
+    g_string_append_printf (s, "%s|", progname);
+  } else {
+    g_string_append_printf (s, "pid/%lu|", (gulong) getpid ());
+  }
+
+  if (description) {
+    g_strdelimit (description, "|", '#');
+    g_string_append_printf (s, "%s|", description);
+    g_free (description);
+  } else {
+    g_string_append (s, "|");
+  }
+
+  g_string_append_printf (s, "%s-%s", type, detail);
+
+  return g_string_free (s, FALSE);
+}
+
+/**
+ * gst_missing_uri_source_installer_detail_new:
+ * @protocol: the URI protocol the missing source needs to implement,
+ *            e.g. "http" or "mms"
+ *
+ * Returns an opaque string containing all the details about the missing
+ * element to be passed to an external installer called via
+ * gst_install_plugins_async() or gst_install_plugins_sync().
+ * 
+ * This function is mainly for applications that call external plugin
+ * installation mechanisms using one of the two above-mentioned functions in
+ * the case where the application knows exactly what kind of plugin it is
+ * missing.
+ *
+ * Returns: a newly-allocated detail string, or NULL on error. Free string
+ *          with g_free() when not needed any longer.
+ *
+ * Since: 0.10.15
+ */
+gchar *
+gst_missing_uri_source_installer_detail_new (const gchar * protocol)
+{
+  gchar *desc;
+
+  g_return_val_if_fail (protocol != NULL, NULL);
+
+  desc = gst_pb_utils_get_source_description (protocol);
+  return gst_installer_detail_new (desc, "urisource", protocol);
+}
+
+/**
+ * gst_missing_uri_sink_installer_detail_new:
+ * @protocol: the URI protocol the missing source needs to implement,
+ *            e.g. "http" or "mms"
+ *
+ * Returns an opaque string containing all the details about the missing
+ * element to be passed to an external installer called via
+ * gst_install_plugins_async() or gst_install_plugins_sync().
+ * 
+ * This function is mainly for applications that call external plugin
+ * installation mechanisms using one of the two above-mentioned functions in
+ * the case where the application knows exactly what kind of plugin it is
+ * missing.
+ *
+ * Returns: a newly-allocated detail string, or NULL on error. Free string
+ *          with g_free() when not needed any longer.
+ *
+ * Since: 0.10.15
+ */
+gchar *
+gst_missing_uri_sink_installer_detail_new (const gchar * protocol)
+{
+  gchar *desc;
+
+  g_return_val_if_fail (protocol != NULL, NULL);
+
+  desc = gst_pb_utils_get_sink_description (protocol);
+  return gst_installer_detail_new (desc, "urisink", protocol);
+}
+
+/**
+ * gst_missing_element_installer_detail_new:
+ * @factory_name: the name of the missing element (element factory),
+ *            e.g. "videoscale" or "cdparanoiasrc"
+ *
+ * Returns an opaque string containing all the details about the missing
+ * element to be passed to an external installer called via
+ * gst_install_plugins_async() or gst_install_plugins_sync().
+ * 
+ * This function is mainly for applications that call external plugin
+ * installation mechanisms using one of the two above-mentioned functions in
+ * the case where the application knows exactly what kind of plugin it is
+ * missing.
+ *
+ * Returns: a newly-allocated detail string, or NULL on error. Free string
+ *          with g_free() when not needed any longer.
+ *
+ * Since: 0.10.15
+ */
+gchar *
+gst_missing_element_installer_detail_new (const gchar * factory_name)
+{
+  gchar *desc;
+
+  g_return_val_if_fail (factory_name != NULL, NULL);
+
+  desc = gst_pb_utils_get_element_description (factory_name);
+  return gst_installer_detail_new (desc, "element", factory_name);
+}
+
+/**
+ * gst_missing_decoder_installer_detail_new:
+ * @decode_caps: the (fixed) caps for which a decoder element is needed
+ *
+ * Returns an opaque string containing all the details about the missing
+ * element to be passed to an external installer called via
+ * gst_install_plugins_async() or gst_install_plugins_sync().
+ * 
+ * This function is mainly for applications that call external plugin
+ * installation mechanisms using one of the two above-mentioned functions in
+ * the case where the application knows exactly what kind of plugin it is
+ * missing.
+ *
+ * Returns: a newly-allocated detail string, or NULL on error. Free string
+ *          with g_free() when not needed any longer.
+ *
+ * Since: 0.10.15
+ */
+gchar *
+gst_missing_decoder_installer_detail_new (const GstCaps * decode_caps)
+{
+  GstCaps *caps;
+  gchar *detail_str, *caps_str, *desc;
+
+  g_return_val_if_fail (decode_caps != NULL, NULL);
+  g_return_val_if_fail (GST_IS_CAPS (decode_caps), NULL);
+  g_return_val_if_fail (!gst_caps_is_any (decode_caps), NULL);
+  g_return_val_if_fail (!gst_caps_is_empty (decode_caps), NULL);
+  g_return_val_if_fail (gst_caps_is_fixed (decode_caps), NULL);
+
+  desc = gst_pb_utils_get_decoder_description (decode_caps);
+  caps = copy_and_clean_caps (decode_caps);
+  caps_str = gst_caps_to_string (caps);
+  detail_str = gst_installer_detail_new (desc, "decoder", caps_str);
+  g_free (caps_str);
+  gst_caps_unref (caps);
+
+  return detail_str;
+}
+
+/**
+ * gst_missing_encoder_installer_detail_new:
+ * @encode_caps: the (fixed) caps for which an encoder element is needed
+ *
+ * Returns an opaque string containing all the details about the missing
+ * element to be passed to an external installer called via
+ * gst_install_plugins_async() or gst_install_plugins_sync().
+ * 
+ * This function is mainly for applications that call external plugin
+ * installation mechanisms using one of the two above-mentioned functions in
+ * the case where the application knows exactly what kind of plugin it is
+ * missing.
+ *
+ * Returns: a newly-allocated detail string, or NULL on error. Free string
+ *          with g_free() when not needed any longer.
+ *
+ * Since: 0.10.15
+ */
+gchar *
+gst_missing_encoder_installer_detail_new (const GstCaps * encode_caps)
+{
+  GstCaps *caps;
+  gchar *detail_str, *caps_str, *desc;
+
+  g_return_val_if_fail (encode_caps != NULL, NULL);
+  g_return_val_if_fail (GST_IS_CAPS (encode_caps), NULL);
+  g_return_val_if_fail (!gst_caps_is_any (encode_caps), NULL);
+  g_return_val_if_fail (!gst_caps_is_empty (encode_caps), NULL);
+  g_return_val_if_fail (gst_caps_is_fixed (encode_caps), NULL);
+
+  desc = gst_pb_utils_get_encoder_description (encode_caps);
+  caps = copy_and_clean_caps (encode_caps);
+  caps_str = gst_caps_to_string (caps);
+  detail_str = gst_installer_detail_new (desc, "encoder", caps_str);
+  g_free (caps_str);
+  gst_caps_unref (caps);
+
+  return detail_str;
+}
+
+
Index: gst-libs/gst/pbutils/missing-plugins.h
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-base/gst-libs/gst/pbutils/missing-plugins.h,v
retrieving revision 1.2
diff -u -p -r1.2 missing-plugins.h
--- gst-libs/gst/pbutils/missing-plugins.h	4 Mar 2007 23:39:49 -0000	1.2
+++ gst-libs/gst/pbutils/missing-plugins.h	26 Aug 2007 15:03:00 -0000
@@ -45,7 +45,7 @@ GstMessage * gst_missing_encoder_message
                                                  const GstCaps * encode_caps);
 
 /*
- * functions for use by the application when dealing with missing-plugin messages
+ * functions for use by applications when dealing with missing-plugin messages
  */
 
 gchar       * gst_missing_plugin_message_get_installer_detail (GstMessage * msg);
@@ -53,7 +53,24 @@ gchar       * gst_missing_plugin_message
 gchar       * gst_missing_plugin_message_get_description (GstMessage * msg);
 
 gboolean      gst_is_missing_plugin_message (GstMessage * msg);
-   
+
+
+/*
+ * functions for use by applications that know exactly what plugins they are
+ * missing and want to request them directly rather than just react to
+ * missing-plugin messages posted by elements such as playbin or decodebin
+ */
+
+gchar * gst_missing_uri_source_installer_detail_new (const gchar * protocol);
+
+gchar * gst_missing_uri_sink_installer_detail_new (const gchar * protocol);
+
+gchar * gst_missing_element_installer_detail_new (const gchar * factory_name);
+
+gchar * gst_missing_decoder_installer_detail_new (const GstCaps * decode_caps);
+
+gchar * gst_missing_encoder_installer_detail_new (const GstCaps * encode_caps);
+
 G_END_DECLS
 
 #endif /* __GST_PB_UTILS_MISSING_PLUGINS_H__ */
Index: docs/libs/gst-plugins-base-libs-sections.txt
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-base/docs/libs/gst-plugins-base-libs-sections.txt,v
retrieving revision 1.43
diff -u -p -r1.43 gst-plugins-base-libs-sections.txt
--- docs/libs/gst-plugins-base-libs-sections.txt	23 Aug 2007 10:58:41 -0000	1.43
+++ docs/libs/gst-plugins-base-libs-sections.txt	26 Aug 2007 15:03:01 -0000
@@ -1258,6 +1258,12 @@ gst_missing_encoder_message_new
 gst_missing_uri_source_message_new
 gst_missing_uri_sink_message_new
 gst_missing_element_message_new
+<SUBSECTION>
+gst_missing_uri_source_installer_detail_new
+gst_missing_uri_sink_installer_detail_new
+gst_missing_element_installer_detail_new
+gst_missing_decoder_installer_detail_new
+gst_missing_encoder_installer_detail_new
 </SECTION>
 
 <SECTION>
Index: tests/check/libs/pbutils.c
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-base/tests/check/libs/pbutils.c,v
retrieving revision 1.7
diff -u -p -r1.7 pbutils.c
--- tests/check/libs/pbutils.c	4 Mar 2007 23:39:51 -0000	1.7
+++ tests/check/libs/pbutils.c	26 Aug 2007 15:03:01 -0000
@@ -591,6 +591,96 @@ GST_START_TEST (test_pb_utils_install_pl
 
 GST_END_TEST;
 
+GST_START_TEST (test_pb_utils_installer_details)
+{
+  GstMessage *msg;
+  GstElement *el;
+  GstCaps *caps;
+  gchar *detail1, *detail2;
+
+  el = gst_pipeline_new ("dummy-element");
+
+  /* uri source */
+  detail1 = gst_missing_uri_source_installer_detail_new ("http");
+  fail_unless (detail1 != NULL);
+  fail_unless (g_str_has_prefix (detail1, "gstreamer|0.10|"));
+  fail_unless (g_str_has_suffix (detail1, "|urisource-http"));
+  msg = gst_missing_uri_source_message_new (el, "http");
+  fail_unless (msg != NULL);
+  detail2 = gst_missing_plugin_message_get_installer_detail (msg);
+  fail_unless (detail2 != NULL);
+  gst_message_unref (msg);
+  fail_unless_equals_string (detail1, detail2);
+  g_free (detail1);
+  g_free (detail2);
+
+  /* uri sink */
+  detail1 = gst_missing_uri_sink_installer_detail_new ("http");
+  fail_unless (detail1 != NULL);
+  fail_unless (g_str_has_prefix (detail1, "gstreamer|0.10|"));
+  fail_unless (g_str_has_suffix (detail1, "|urisink-http"));
+  msg = gst_missing_uri_sink_message_new (el, "http");
+  fail_unless (msg != NULL);
+  detail2 = gst_missing_plugin_message_get_installer_detail (msg);
+  fail_unless (detail2 != NULL);
+  gst_message_unref (msg);
+  fail_unless_equals_string (detail1, detail2);
+  g_free (detail1);
+  g_free (detail2);
+
+  /* element */
+  detail1 = gst_missing_element_installer_detail_new ("deinterlace");
+  fail_unless (detail1 != NULL);
+  fail_unless (g_str_has_prefix (detail1, "gstreamer|0.10|"));
+  fail_unless (g_str_has_suffix (detail1, "|element-deinterlace"));
+  msg = gst_missing_element_message_new (el, "deinterlace");
+  fail_unless (msg != NULL);
+  detail2 = gst_missing_plugin_message_get_installer_detail (msg);
+  fail_unless (detail2 != NULL);
+  gst_message_unref (msg);
+  fail_unless_equals_string (detail1, detail2);
+  g_free (detail1);
+  g_free (detail2);
+
+  /* decoder */
+  caps = gst_caps_new_simple ("audio/x-spiffy", "spiffyversion", G_TYPE_INT,
+      2, "channels", G_TYPE_INT, 6, NULL);
+  detail1 = gst_missing_decoder_installer_detail_new (caps);
+  fail_unless (detail1 != NULL);
+  fail_unless (g_str_has_prefix (detail1, "gstreamer|0.10|"));
+  fail_unless (g_str_has_suffix (detail1, "|decoder-audio/x-spiffy, spiffyversion=(int)2"));
+  msg = gst_missing_decoder_message_new (el, caps);
+  fail_unless (msg != NULL);
+  detail2 = gst_missing_plugin_message_get_installer_detail (msg);
+  fail_unless (detail2 != NULL);
+  gst_message_unref (msg);
+  gst_caps_unref (caps);
+  fail_unless_equals_string (detail1, detail2);
+  g_free (detail1);
+  g_free (detail2);
+
+  /* encoder */
+  caps = gst_caps_new_simple ("audio/x-spiffy", "spiffyversion", G_TYPE_INT,
+      2, "channels", G_TYPE_INT, 6, NULL);
+  detail1 = gst_missing_encoder_installer_detail_new (caps);
+  fail_unless (g_str_has_prefix (detail1, "gstreamer|0.10|"));
+  fail_unless (g_str_has_suffix (detail1, "|encoder-audio/x-spiffy, spiffyversion=(int)2"));
+  fail_unless (detail1 != NULL);
+  msg = gst_missing_encoder_message_new (el, caps);
+  fail_unless (msg != NULL);
+  detail2 = gst_missing_plugin_message_get_installer_detail (msg);
+  fail_unless (detail2 != NULL);
+  gst_message_unref (msg);
+  gst_caps_unref (caps);
+  fail_unless_equals_string (detail1, detail2);
+  g_free (detail1);
+  g_free (detail2);
+
+  gst_object_unref (el);
+}
+
+GST_END_TEST;
+
 static Suite *
 libgstpbutils_suite (void)
 {
@@ -603,6 +693,7 @@ libgstpbutils_suite (void)
   tcase_add_test (tc_chain, test_pb_utils_taglist_add_codec_info);
   tcase_add_test (tc_chain, test_pb_utils_get_codec_description);
   tcase_add_test (tc_chain, test_pb_utils_install_plugins);
+  tcase_add_test (tc_chain, test_pb_utils_installer_details);
   return s;
 }
 
