diff --git a/ChangeLog b/ChangeLog index 94b846fa49..12f5957b22 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2007-08-28 Tim-Philipp Müller + + * 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 * gst/playback/gstdecodebin.c: (close_pad_link): diff --git a/docs/libs/gst-plugins-base-libs-sections.txt b/docs/libs/gst-plugins-base-libs-sections.txt index e9b8d31b90..ad39354413 100644 --- a/docs/libs/gst-plugins-base-libs-sections.txt +++ b/docs/libs/gst-plugins-base-libs-sections.txt @@ -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 + +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
diff --git a/gst-libs/gst/pbutils/missing-plugins.c b/gst-libs/gst/pbutils/missing-plugins.c index c139907c8b..f78cfc8fe4 100644 --- a/gst-libs/gst/pbutils/missing-plugins.c +++ b/gst-libs/gst/pbutils/missing-plugins.c @@ -415,6 +415,7 @@ gst_missing_plugin_message_get_installer_detail (GstMessage * msg) 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,204 @@ gst_is_missing_plugin_message (GstMessage * msg) 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; +} diff --git a/gst-libs/gst/pbutils/missing-plugins.h b/gst-libs/gst/pbutils/missing-plugins.h index e875b32db8..508304e461 100644 --- a/gst-libs/gst/pbutils/missing-plugins.h +++ b/gst-libs/gst/pbutils/missing-plugins.h @@ -45,7 +45,7 @@ GstMessage * gst_missing_encoder_message_new (GstElement * element, 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_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__ */ diff --git a/tests/check/libs/pbutils.c b/tests/check/libs/pbutils.c index 3ae6270d12..368bf336e7 100644 --- a/tests/check/libs/pbutils.c +++ b/tests/check/libs/pbutils.c @@ -72,7 +72,8 @@ GST_START_TEST (test_pb_utils_post_missing_messages) 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")); @@ -540,14 +541,11 @@ GST_START_TEST (test_pb_utils_install_plugins) 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 */ @@ -591,6 +589,98 @@ GST_START_TEST (test_pb_utils_install_plugins) 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; }