+2007-08-28 Tim-Philipp Müller <tim at centricular dot net>
+
+ * docs/libs/gst-plugins-base-libs-sections.txt:
+ * gst-libs/gst/pbutils/missing-plugins.c:
+ * gst-libs/gst/pbutils/missing-plugins.h:
+ * tests/check/libs/pbutils.c:
+ API: add gst_missing_*_installer_detail_new() convenience API so
+ that applications that know exactly what they're missing can request
+ installer detail strings for those items directly instead of having
+ to first create a dummy missing-plugin message and then get the
+ installer detail string from that. Fixes #470456.
+
2007-08-27 Jan Schmidt <thaytan@mad.scientist.com>
* gst/playback/gstdecodebin.c: (close_pad_link):
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>
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);
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;
+}
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);
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__ */
bus = gst_element_get_bus (pipeline);
/* first, test common assertion failure cases */
- ASSERT_CRITICAL (msg = gst_missing_uri_source_message_new (NULL, "http"););
+ ASSERT_CRITICAL (msg = gst_missing_uri_source_message_new (NULL, "http");
+ );
ASSERT_CRITICAL (gst_missing_uri_source_message_new (pipeline, NULL));
ASSERT_CRITICAL (gst_missing_uri_sink_message_new (NULL, "http"));
ctx = gst_install_plugins_context_new ();
- ASSERT_CRITICAL (ret = gst_install_plugins_sync (NULL, ctx);
- );
+ ASSERT_CRITICAL (ret = gst_install_plugins_sync (NULL, ctx););
ASSERT_CRITICAL (ret =
- gst_install_plugins_async (NULL, ctx, result_cb, (gpointer) & marker);
- );
+ gst_install_plugins_async (NULL, ctx, result_cb, (gpointer) & marker););
ASSERT_CRITICAL (ret =
- gst_install_plugins_async (details, ctx, NULL, (gpointer) & marker);
- );
+ gst_install_plugins_async (details, ctx, NULL, (gpointer) & marker););
/* make sure the functions return the right error code if the helper does
* not exist */
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)
{
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;
}