gst_plugins_base/gst-libs/gst/pbutils/missing-plugins.c
changeset 0 0e761a78d257
child 8 4a7fac7dd34a
equal deleted inserted replaced
-1:000000000000 0:0e761a78d257
       
     1 /* GStreamer base utils library missing plugins support
       
     2  * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
       
     3  *
       
     4  * This library is free software; you can redistribute it and/or
       
     5  * modify it under the terms of the GNU Library General Public
       
     6  * License as published by the Free Software Foundation; either
       
     7  * version 2 of the License, or (at your option) any later version.
       
     8  *
       
     9  * This library is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    12  * Library General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU Library General Public
       
    15  * License along with this library; if not, write to the
       
    16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    17  * Boston, MA 02111-1307, USA.
       
    18  */
       
    19 
       
    20 /**
       
    21  * SECTION:gstpbutilsmissingplugins
       
    22  * @short_description: Create, recognise and parse missing-plugins messages
       
    23  *
       
    24  * <refsect2>
       
    25  * <para>
       
    26  * Functions to create, recognise and parse missing-plugins messages for
       
    27  * applications and elements.
       
    28  * </para>
       
    29  * <para>
       
    30  * Missing-plugin messages are posted on the bus by elements like decodebin
       
    31  * or playbin if they can't find an appropriate source element or decoder
       
    32  * element. The application can use these messages for two things:
       
    33  * <itemizedlist>
       
    34  *   <listitem><para>
       
    35  *     concise error/problem reporting to the user mentioning what exactly
       
    36  *     is missing, see gst_missing_plugin_message_get_description()
       
    37  *   </para></listitem>
       
    38  *   <listitem><para>
       
    39  *     initiate installation of missing plugins, see
       
    40  *     gst_missing_plugin_message_get_installer_detail() and
       
    41  *     gst_install_plugins_async()
       
    42  *   </para></listitem>
       
    43  * </itemizedlist>
       
    44  * </para>
       
    45  * <para>
       
    46  * Applications may also create missing-plugin messages themselves to install
       
    47  * required elements that are missing, using the install mechanism mentioned
       
    48  * above.
       
    49  * </para>
       
    50  * </refsect2>
       
    51  */
       
    52 
       
    53 #ifdef HAVE_CONFIG_H
       
    54 # include "config.h"
       
    55 #endif
       
    56 
       
    57 #ifdef HAVE_SYS_TYPES_H
       
    58 # include <sys/types.h>
       
    59 #endif
       
    60 #ifdef HAVE_UNISTD_H
       
    61 # include <unistd.h>            /* getpid on UNIX */
       
    62 #endif
       
    63 #ifdef HAVE_PROCESS_H
       
    64 # include <process.h>           /* getpid on win32 */
       
    65 #endif
       
    66 
       
    67 #ifdef __SYMBIAN32__
       
    68 #include <gst_global.h>
       
    69 #endif
       
    70 
       
    71 #include "gst/gst-i18n-plugin.h"
       
    72 
       
    73 #include "pbutils.h"
       
    74 
       
    75 #include <string.h>
       
    76 
       
    77 #define GST_DETAIL_STRING_MARKER "gstreamer"
       
    78 
       
    79 typedef enum
       
    80 {
       
    81   GST_MISSING_TYPE_UNKNOWN = 0,
       
    82   GST_MISSING_TYPE_URISOURCE,
       
    83   GST_MISSING_TYPE_URISINK,
       
    84   GST_MISSING_TYPE_ELEMENT,
       
    85   GST_MISSING_TYPE_DECODER,
       
    86   GST_MISSING_TYPE_ENCODER
       
    87 } GstMissingType;
       
    88 
       
    89 static const struct
       
    90 {
       
    91   GstMissingType type;
       
    92   const gchar type_string[12];
       
    93 } missing_type_mapping[] = {
       
    94   {
       
    95   GST_MISSING_TYPE_URISOURCE, "urisource"}, {
       
    96   GST_MISSING_TYPE_URISINK, "urisink"}, {
       
    97   GST_MISSING_TYPE_ELEMENT, "element"}, {
       
    98   GST_MISSING_TYPE_DECODER, "decoder"}, {
       
    99   GST_MISSING_TYPE_ENCODER, "encoder"}
       
   100 };
       
   101 
       
   102 static GstMissingType
       
   103 missing_structure_get_type (const GstStructure * s)
       
   104 {
       
   105   const gchar *type;
       
   106   guint i;
       
   107 
       
   108   type = gst_structure_get_string (s, "type");
       
   109   g_return_val_if_fail (type != NULL, GST_MISSING_TYPE_UNKNOWN);
       
   110 
       
   111   for (i = 0; i < G_N_ELEMENTS (missing_type_mapping); ++i) {
       
   112     if (strcmp (missing_type_mapping[i].type_string, type) == 0)
       
   113       return missing_type_mapping[i].type;
       
   114   }
       
   115 
       
   116   return GST_MISSING_TYPE_UNKNOWN;
       
   117 }
       
   118 
       
   119 static GstCaps *
       
   120 copy_and_clean_caps (const GstCaps * caps)
       
   121 {
       
   122   GstStructure *s;
       
   123   GstCaps *ret;
       
   124 
       
   125   ret = gst_caps_copy (caps);
       
   126 
       
   127   /* make caps easier to interpret, remove common fields that are likely
       
   128    * to be irrelevant for determining the right plugin (ie. mostly fields
       
   129    * where template caps usually have the standard MIN - MAX range as value) */
       
   130   s = gst_caps_get_structure (ret, 0);
       
   131   gst_structure_remove_field (s, "codec_data");
       
   132   gst_structure_remove_field (s, "palette_data");
       
   133   gst_structure_remove_field (s, "pixel-aspect-ratio");
       
   134   gst_structure_remove_field (s, "framerate");
       
   135   gst_structure_remove_field (s, "leaf_size");
       
   136   gst_structure_remove_field (s, "packet_size");
       
   137   /* decoders/encoders almost always handle the usual width/height/channel/rate
       
   138    * range (and if we don't remove this then the app will have a much harder
       
   139    * time blacklisting formats it has unsuccessfully tried to install before) */
       
   140   gst_structure_remove_field (s, "width");
       
   141   gst_structure_remove_field (s, "height");
       
   142   gst_structure_remove_field (s, "channels");
       
   143   gst_structure_remove_field (s, "rate");
       
   144   /* rtp fields */
       
   145   gst_structure_remove_field (s, "config");
       
   146   gst_structure_remove_field (s, "clock-rate");
       
   147   gst_structure_remove_field (s, "clock-base");
       
   148   gst_structure_remove_field (s, "maxps");
       
   149   gst_structure_remove_field (s, "seqnum-base");
       
   150   gst_structure_remove_field (s, "npt-start");
       
   151   gst_structure_remove_field (s, "npt-stop");
       
   152   gst_structure_remove_field (s, "play-speed");
       
   153   gst_structure_remove_field (s, "play-scale");
       
   154 
       
   155   return ret;
       
   156 }
       
   157 
       
   158 /**
       
   159  * gst_missing_uri_source_message_new:
       
   160  * @element: the #GstElement posting the message
       
   161  * @protocol: the URI protocol the missing source needs to implement,
       
   162  *            e.g. "http" or "mms"
       
   163  *
       
   164  * Creates a missing-plugin message for @element to notify the application
       
   165  * that a source element for a particular URI protocol is missing. This
       
   166  * function is mainly for use in plugins.
       
   167  *
       
   168  * Returns: a new #GstMessage, or NULL on error
       
   169  */
       
   170 #ifdef __SYMBIAN32__
       
   171 EXPORT_C
       
   172 #endif
       
   173 
       
   174 GstMessage *
       
   175 gst_missing_uri_source_message_new (GstElement * element,
       
   176     const gchar * protocol)
       
   177 {
       
   178   GstStructure *s;
       
   179   gchar *description;
       
   180 
       
   181   g_return_val_if_fail (element != NULL, NULL);
       
   182   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
       
   183   g_return_val_if_fail (protocol != NULL, NULL);
       
   184 
       
   185   description = gst_pb_utils_get_source_description (protocol);
       
   186 
       
   187   s = gst_structure_new ("missing-plugin", "type", G_TYPE_STRING,
       
   188       "urisource", "detail", G_TYPE_STRING, protocol, "name", G_TYPE_STRING,
       
   189       description, NULL);
       
   190 
       
   191   g_free (description);
       
   192   return gst_message_new_element (GST_OBJECT_CAST (element), s);
       
   193 }
       
   194 
       
   195 /**
       
   196  * gst_missing_uri_sink_message_new:
       
   197  * @element: the #GstElement posting the message
       
   198  * @protocol: the URI protocol the missing sink needs to implement,
       
   199  *            e.g. "http" or "smb"
       
   200  *
       
   201  * Creates a missing-plugin message for @element to notify the application
       
   202  * that a sink element for a particular URI protocol is missing. This
       
   203  * function is mainly for use in plugins.
       
   204  *
       
   205  * Returns: a new #GstMessage, or NULL on error
       
   206  */
       
   207 #ifdef __SYMBIAN32__
       
   208 EXPORT_C
       
   209 #endif
       
   210 
       
   211 GstMessage *
       
   212 gst_missing_uri_sink_message_new (GstElement * element, const gchar * protocol)
       
   213 {
       
   214   GstStructure *s;
       
   215   gchar *description;
       
   216 
       
   217   g_return_val_if_fail (element != NULL, NULL);
       
   218   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
       
   219   g_return_val_if_fail (protocol != NULL, NULL);
       
   220 
       
   221   description = gst_pb_utils_get_sink_description (protocol);
       
   222 
       
   223   s = gst_structure_new ("missing-plugin", "type", G_TYPE_STRING,
       
   224       "urisink", "detail", G_TYPE_STRING, protocol, "name", G_TYPE_STRING,
       
   225       description, NULL);
       
   226 
       
   227   g_free (description);
       
   228   return gst_message_new_element (GST_OBJECT_CAST (element), s);
       
   229 }
       
   230 
       
   231 /**
       
   232  * gst_missing_element_message_new:
       
   233  * @element: the #GstElement posting the message
       
   234  * @factory_name: the name of the missing element (element factory),
       
   235  *            e.g. "videoscale" or "cdparanoiasrc"
       
   236  *
       
   237  * Creates a missing-plugin message for @element to notify the application
       
   238  * that a certain required element is missing. This function is mainly for
       
   239  * use in plugins.
       
   240  *
       
   241  * Returns: a new #GstMessage, or NULL on error
       
   242  */
       
   243 #ifdef __SYMBIAN32__
       
   244 EXPORT_C
       
   245 #endif
       
   246 
       
   247 GstMessage *
       
   248 gst_missing_element_message_new (GstElement * element,
       
   249     const gchar * factory_name)
       
   250 {
       
   251   GstStructure *s;
       
   252   gchar *description;
       
   253 
       
   254   g_return_val_if_fail (element != NULL, NULL);
       
   255   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
       
   256   g_return_val_if_fail (factory_name != NULL, NULL);
       
   257 
       
   258   description = gst_pb_utils_get_element_description (factory_name);
       
   259 
       
   260   s = gst_structure_new ("missing-plugin", "type", G_TYPE_STRING,
       
   261       "element", "detail", G_TYPE_STRING, factory_name, "name", G_TYPE_STRING,
       
   262       description, NULL);
       
   263 
       
   264   g_free (description);
       
   265   return gst_message_new_element (GST_OBJECT_CAST (element), s);
       
   266 }
       
   267 
       
   268 /**
       
   269  * gst_missing_decoder_message_new:
       
   270  * @element: the #GstElement posting the message
       
   271  * @decode_caps: the (fixed) caps for which a decoder element is needed
       
   272  *
       
   273  * Creates a missing-plugin message for @element to notify the application
       
   274  * that a decoder element for a particular set of (fixed) caps is missing.
       
   275  * This function is mainly for use in plugins.
       
   276  *
       
   277  * Returns: a new #GstMessage, or NULL on error
       
   278  */
       
   279 #ifdef __SYMBIAN32__
       
   280 EXPORT_C
       
   281 #endif
       
   282 
       
   283 GstMessage *
       
   284 gst_missing_decoder_message_new (GstElement * element,
       
   285     const GstCaps * decode_caps)
       
   286 {
       
   287   GstStructure *s;
       
   288   GstCaps *caps;
       
   289   gchar *description;
       
   290 
       
   291   g_return_val_if_fail (element != NULL, NULL);
       
   292   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
       
   293   g_return_val_if_fail (decode_caps != NULL, NULL);
       
   294   g_return_val_if_fail (GST_IS_CAPS (decode_caps), NULL);
       
   295   g_return_val_if_fail (!gst_caps_is_any (decode_caps), NULL);
       
   296   g_return_val_if_fail (!gst_caps_is_empty (decode_caps), NULL);
       
   297   g_return_val_if_fail (gst_caps_is_fixed (decode_caps), NULL);
       
   298 
       
   299   description = gst_pb_utils_get_decoder_description (decode_caps);
       
   300   caps = copy_and_clean_caps (decode_caps);
       
   301 
       
   302   s = gst_structure_new ("missing-plugin", "type", G_TYPE_STRING,
       
   303       "decoder", "detail", GST_TYPE_CAPS, caps, "name", G_TYPE_STRING,
       
   304       description, NULL);
       
   305 
       
   306   gst_caps_unref (caps);
       
   307   g_free (description);
       
   308 
       
   309   return gst_message_new_element (GST_OBJECT_CAST (element), s);
       
   310 }
       
   311 
       
   312 /**
       
   313  * gst_missing_encoder_message_new:
       
   314  * @element: the #GstElement posting the message
       
   315  * @encode_caps: the (fixed) caps for which an encoder element is needed
       
   316  *
       
   317  * Creates a missing-plugin message for @element to notify the application
       
   318  * that an encoder element for a particular set of (fixed) caps is missing.
       
   319  * This function is mainly for use in plugins.
       
   320  *
       
   321  * Returns: a new #GstMessage, or NULL on error
       
   322  */
       
   323 #ifdef __SYMBIAN32__
       
   324 EXPORT_C
       
   325 #endif
       
   326 
       
   327 GstMessage *
       
   328 gst_missing_encoder_message_new (GstElement * element,
       
   329     const GstCaps * encode_caps)
       
   330 {
       
   331   GstStructure *s;
       
   332   GstCaps *caps;
       
   333   gchar *description;
       
   334 
       
   335   g_return_val_if_fail (element != NULL, NULL);
       
   336   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
       
   337   g_return_val_if_fail (encode_caps != NULL, NULL);
       
   338   g_return_val_if_fail (GST_IS_CAPS (encode_caps), NULL);
       
   339   g_return_val_if_fail (!gst_caps_is_any (encode_caps), NULL);
       
   340   g_return_val_if_fail (!gst_caps_is_empty (encode_caps), NULL);
       
   341   g_return_val_if_fail (gst_caps_is_fixed (encode_caps), NULL);
       
   342 
       
   343   description = gst_pb_utils_get_encoder_description (encode_caps);
       
   344   caps = copy_and_clean_caps (encode_caps);
       
   345 
       
   346   s = gst_structure_new ("missing-plugin", "type", G_TYPE_STRING,
       
   347       "encoder", "detail", GST_TYPE_CAPS, caps, "name", G_TYPE_STRING,
       
   348       description, NULL);
       
   349 
       
   350   gst_caps_unref (caps);
       
   351   g_free (description);
       
   352 
       
   353   return gst_message_new_element (GST_OBJECT_CAST (element), s);
       
   354 }
       
   355 
       
   356 static gboolean
       
   357 missing_structure_get_string_detail (const GstStructure * s, gchar ** p_detail)
       
   358 {
       
   359   const gchar *detail;
       
   360   GType detail_type;
       
   361 
       
   362   *p_detail = NULL;
       
   363 
       
   364   detail_type = gst_structure_get_field_type (s, "detail");
       
   365   if (!g_type_is_a (detail_type, G_TYPE_STRING)) {
       
   366     GST_WARNING ("expected 'detail' field to be of G_TYPE_STRING");
       
   367     return FALSE;
       
   368   }
       
   369 
       
   370   detail = gst_structure_get_string (s, "detail");
       
   371   if (detail == NULL || *detail == '\0') {
       
   372     GST_WARNING ("empty 'detail' field");
       
   373     return FALSE;
       
   374   }
       
   375   *p_detail = g_strdup (detail);
       
   376   return TRUE;
       
   377 }
       
   378 
       
   379 static gboolean
       
   380 missing_structure_get_caps_detail (const GstStructure * s, GstCaps ** p_caps)
       
   381 {
       
   382   const GstCaps *caps;
       
   383   const GValue *val;
       
   384   GType detail_type;
       
   385 
       
   386   *p_caps = NULL;
       
   387 
       
   388   detail_type = gst_structure_get_field_type (s, "detail");
       
   389   if (!g_type_is_a (detail_type, GST_TYPE_CAPS)) {
       
   390     GST_WARNING ("expected 'detail' field to be of GST_TYPE_CAPS");
       
   391     return FALSE;
       
   392   }
       
   393 
       
   394   val = gst_structure_get_value (s, "detail");
       
   395   caps = gst_value_get_caps (val);
       
   396   if (gst_caps_is_empty (caps) || gst_caps_is_any (caps)) {
       
   397     GST_WARNING ("EMPTY or ANY caps not allowed");
       
   398     return FALSE;
       
   399   }
       
   400 
       
   401   *p_caps = gst_caps_copy (caps);
       
   402   return TRUE;
       
   403 }
       
   404 
       
   405 /**
       
   406  * gst_missing_plugin_message_get_installer_detail:
       
   407  * @msg: a missing-plugin #GstMessage of type #GST_MESSAGE_ELEMENT
       
   408  *
       
   409  * Returns an opaque string containing all the details about the missing
       
   410  * element to be passed to an external installer called via
       
   411  * gst_install_plugins_async() or gst_install_plugins_sync().
       
   412  * 
       
   413  * This function is mainly for applications that call external plugin
       
   414  * installation mechanisms using one of the two above-mentioned functions.
       
   415  *
       
   416  * Returns: a newly-allocated detail string, or NULL on error. Free string
       
   417  *          with g_free() when not needed any longer.
       
   418  */
       
   419 #ifdef __SYMBIAN32__
       
   420 EXPORT_C
       
   421 #endif
       
   422 
       
   423 gchar *
       
   424 gst_missing_plugin_message_get_installer_detail (GstMessage * msg)
       
   425 {
       
   426   GstMissingType missing_type;
       
   427   const gchar *progname;
       
   428   const gchar *type;
       
   429   GString *str = NULL;
       
   430   gchar *detail = NULL;
       
   431   gchar *desc;
       
   432 
       
   433   g_return_val_if_fail (gst_is_missing_plugin_message (msg), NULL);
       
   434 
       
   435   GST_LOG ("Parsing missing-plugin message: %" GST_PTR_FORMAT, msg->structure);
       
   436 
       
   437   missing_type = missing_structure_get_type (msg->structure);
       
   438   if (missing_type == GST_MISSING_TYPE_UNKNOWN) {
       
   439     GST_WARNING ("couldn't parse 'type' field");
       
   440     goto error;
       
   441   }
       
   442 
       
   443   type = gst_structure_get_string (msg->structure, "type");
       
   444   g_assert (type != NULL);      /* validity already checked above */
       
   445 
       
   446   /* FIXME: use gst_installer_detail_new() here too */
       
   447   str = g_string_new (GST_DETAIL_STRING_MARKER "|");
       
   448   g_string_append_printf (str, "%u.%u|", GST_VERSION_MAJOR, GST_VERSION_MINOR);
       
   449 
       
   450   progname = (const gchar *) g_get_prgname ();
       
   451   if (progname) {
       
   452     g_string_append_printf (str, "%s|", progname);
       
   453   } else {
       
   454     g_string_append_printf (str, "pid/%lu|", (gulong) getpid ());
       
   455   }
       
   456 
       
   457   desc = gst_missing_plugin_message_get_description (msg);
       
   458   if (desc) {
       
   459     g_strdelimit (desc, "|", '#');
       
   460     g_string_append_printf (str, "%s|", desc);
       
   461     g_free (desc);
       
   462   } else {
       
   463     g_string_append (str, "|");
       
   464   }
       
   465 
       
   466   switch (missing_type) {
       
   467     case GST_MISSING_TYPE_URISOURCE:
       
   468     case GST_MISSING_TYPE_URISINK:
       
   469     case GST_MISSING_TYPE_ELEMENT:
       
   470       if (!missing_structure_get_string_detail (msg->structure, &detail))
       
   471         goto error;
       
   472       break;
       
   473     case GST_MISSING_TYPE_DECODER:
       
   474     case GST_MISSING_TYPE_ENCODER:{
       
   475       GstCaps *caps = NULL;
       
   476 
       
   477       if (!missing_structure_get_caps_detail (msg->structure, &caps))
       
   478         goto error;
       
   479 
       
   480       detail = gst_caps_to_string (caps);
       
   481       gst_caps_unref (caps);
       
   482       break;
       
   483     }
       
   484     default:
       
   485       g_return_val_if_reached (NULL);
       
   486   }
       
   487 
       
   488   g_string_append_printf (str, "%s-%s", type, detail);
       
   489   g_free (detail);
       
   490 
       
   491   return g_string_free (str, FALSE);
       
   492 
       
   493 /* ERRORS */
       
   494 error:
       
   495   {
       
   496     GST_WARNING ("Failed to parse missing-plugin msg: %" GST_PTR_FORMAT, msg);
       
   497     if (str)
       
   498       g_string_free (str, TRUE);
       
   499     return NULL;
       
   500   }
       
   501 }
       
   502 
       
   503 /**
       
   504  * gst_missing_plugin_message_get_description:
       
   505  * @msg: a missing-plugin #GstMessage of type #GST_MESSAGE_ELEMENT
       
   506  *
       
   507  * Returns a localised string describing the missing feature, for use in
       
   508  * error dialogs and the like. Should never return NULL unless @msg is not
       
   509  * a valid missing-plugin message.
       
   510  *
       
   511  * This function is mainly for applications that need a human-readable string
       
   512  * describing a missing plugin, given a previously collected missing-plugin
       
   513  * message
       
   514  *
       
   515  * Returns: a newly-allocated description string, or NULL on error. Free
       
   516  *          string with g_free() when not needed any longer.
       
   517  */
       
   518 #ifdef __SYMBIAN32__
       
   519 EXPORT_C
       
   520 #endif
       
   521 gchar *
       
   522 gst_missing_plugin_message_get_description (GstMessage * msg)
       
   523 {
       
   524   GstMissingType missing_type;
       
   525   const gchar *desc;
       
   526   gchar *ret = NULL;
       
   527 
       
   528   g_return_val_if_fail (gst_is_missing_plugin_message (msg), NULL);
       
   529 
       
   530   GST_LOG ("Parsing missing-plugin message: %" GST_PTR_FORMAT, msg->structure);
       
   531 
       
   532   desc = gst_structure_get_string (msg->structure, "name");
       
   533   if (desc != NULL && *desc != '\0') {
       
   534     ret = g_strdup (desc);
       
   535     goto done;
       
   536   }
       
   537 
       
   538   /* fallback #1 */
       
   539   missing_type = missing_structure_get_type (msg->structure);
       
   540 
       
   541   switch (missing_type) {
       
   542     case GST_MISSING_TYPE_URISOURCE:
       
   543     case GST_MISSING_TYPE_URISINK:
       
   544     case GST_MISSING_TYPE_ELEMENT:{
       
   545       gchar *detail = NULL;
       
   546 
       
   547       if (missing_structure_get_string_detail (msg->structure, &detail)) {
       
   548         if (missing_type == GST_MISSING_TYPE_URISOURCE)
       
   549           ret = gst_pb_utils_get_source_description (detail);
       
   550         else if (missing_type == GST_MISSING_TYPE_URISINK)
       
   551           ret = gst_pb_utils_get_sink_description (detail);
       
   552         else
       
   553           ret = gst_pb_utils_get_sink_description (detail);
       
   554         g_free (detail);
       
   555       }
       
   556       break;
       
   557     }
       
   558     case GST_MISSING_TYPE_DECODER:
       
   559     case GST_MISSING_TYPE_ENCODER:{
       
   560       GstCaps *caps = NULL;
       
   561 
       
   562       if (missing_structure_get_caps_detail (msg->structure, &caps)) {
       
   563         if (missing_type == GST_MISSING_TYPE_DECODER)
       
   564           ret = gst_pb_utils_get_decoder_description (caps);
       
   565         else
       
   566           ret = gst_pb_utils_get_encoder_description (caps);
       
   567         gst_caps_unref (caps);
       
   568       }
       
   569       break;
       
   570     }
       
   571     default:
       
   572       break;
       
   573   }
       
   574 
       
   575   if (ret)
       
   576     goto done;
       
   577 
       
   578   /* fallback #2 */
       
   579   switch (missing_type) {
       
   580     case GST_MISSING_TYPE_URISOURCE:
       
   581       desc = _("Unknown source element");
       
   582       break;
       
   583     case GST_MISSING_TYPE_URISINK:
       
   584       desc = _("Unknown sink element");
       
   585       break;
       
   586     case GST_MISSING_TYPE_ELEMENT:
       
   587       desc = _("Unknown element");
       
   588       break;
       
   589     case GST_MISSING_TYPE_DECODER:
       
   590       desc = _("Unknown decoder element");
       
   591       break;
       
   592     case GST_MISSING_TYPE_ENCODER:
       
   593       desc = _("Unknown encoder element");
       
   594       break;
       
   595     default:
       
   596       /* we should really never get here, but we better still return
       
   597        * something if we do */
       
   598       desc = _("Plugin or element of unknown type");
       
   599       break;
       
   600   }
       
   601   ret = g_strdup (desc);
       
   602 
       
   603 done:
       
   604 
       
   605   GST_LOG ("returning '%s'", ret);
       
   606   return ret;
       
   607 }
       
   608 
       
   609 /**
       
   610  * gst_is_missing_plugin_message:
       
   611  * @msg: a #GstMessage
       
   612  *
       
   613  * Checks whether @msg is a missing plugins message.
       
   614  *
       
   615  * Returns: %TRUE if @msg is a missing-plugins message, otherwise %FALSE.
       
   616  */
       
   617 #ifdef __SYMBIAN32__
       
   618 EXPORT_C
       
   619 #endif
       
   620 
       
   621 gboolean
       
   622 gst_is_missing_plugin_message (GstMessage * msg)
       
   623 {
       
   624   g_return_val_if_fail (msg != NULL, FALSE);
       
   625   g_return_val_if_fail (GST_IS_MESSAGE (msg), FALSE);
       
   626 
       
   627   if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ELEMENT || msg->structure == NULL)
       
   628     return FALSE;
       
   629 
       
   630   return gst_structure_has_name (msg->structure, "missing-plugin");
       
   631 }
       
   632 
       
   633 /* takes ownership of the description */
       
   634 static gchar *
       
   635 gst_installer_detail_new (gchar * description, const gchar * type,
       
   636     const gchar * detail)
       
   637 {
       
   638   const gchar *progname;
       
   639   GString *s;
       
   640 
       
   641   s = g_string_new (GST_DETAIL_STRING_MARKER "|");
       
   642   g_string_append_printf (s, "%u.%u|", GST_VERSION_MAJOR, GST_VERSION_MINOR);
       
   643 
       
   644   progname = (const gchar *) g_get_prgname ();
       
   645   if (progname) {
       
   646     g_string_append_printf (s, "%s|", progname);
       
   647   } else {
       
   648     g_string_append_printf (s, "pid/%lu|", (gulong) getpid ());
       
   649   }
       
   650 
       
   651   if (description) {
       
   652     g_strdelimit (description, "|", '#');
       
   653     g_string_append_printf (s, "%s|", description);
       
   654     g_free (description);
       
   655   } else {
       
   656     g_string_append (s, "|");
       
   657   }
       
   658 
       
   659   g_string_append_printf (s, "%s-%s", type, detail);
       
   660 
       
   661   return g_string_free (s, FALSE);
       
   662 }
       
   663 
       
   664 /**
       
   665  * gst_missing_uri_source_installer_detail_new:
       
   666  * @protocol: the URI protocol the missing source needs to implement,
       
   667  *            e.g. "http" or "mms"
       
   668  *
       
   669  * Returns an opaque string containing all the details about the missing
       
   670  * element to be passed to an external installer called via
       
   671  * gst_install_plugins_async() or gst_install_plugins_sync().
       
   672  * 
       
   673  * This function is mainly for applications that call external plugin
       
   674  * installation mechanisms using one of the two above-mentioned functions in
       
   675  * the case where the application knows exactly what kind of plugin it is
       
   676  * missing.
       
   677  *
       
   678  * Returns: a newly-allocated detail string, or NULL on error. Free string
       
   679  *          with g_free() when not needed any longer.
       
   680  *
       
   681  * Since: 0.10.15
       
   682  */
       
   683 #ifdef __SYMBIAN32__
       
   684 EXPORT_C
       
   685 #endif
       
   686 
       
   687 gchar *
       
   688 gst_missing_uri_source_installer_detail_new (const gchar * protocol)
       
   689 {
       
   690   gchar *desc;
       
   691 
       
   692   g_return_val_if_fail (protocol != NULL, NULL);
       
   693 
       
   694   desc = gst_pb_utils_get_source_description (protocol);
       
   695   return gst_installer_detail_new (desc, "urisource", protocol);
       
   696 }
       
   697 
       
   698 /**
       
   699  * gst_missing_uri_sink_installer_detail_new:
       
   700  * @protocol: the URI protocol the missing source needs to implement,
       
   701  *            e.g. "http" or "mms"
       
   702  *
       
   703  * Returns an opaque string containing all the details about the missing
       
   704  * element to be passed to an external installer called via
       
   705  * gst_install_plugins_async() or gst_install_plugins_sync().
       
   706  * 
       
   707  * This function is mainly for applications that call external plugin
       
   708  * installation mechanisms using one of the two above-mentioned functions in
       
   709  * the case where the application knows exactly what kind of plugin it is
       
   710  * missing.
       
   711  *
       
   712  * Returns: a newly-allocated detail string, or NULL on error. Free string
       
   713  *          with g_free() when not needed any longer.
       
   714  *
       
   715  * Since: 0.10.15
       
   716  */
       
   717 #ifdef __SYMBIAN32__
       
   718 EXPORT_C
       
   719 #endif
       
   720 
       
   721 gchar *
       
   722 gst_missing_uri_sink_installer_detail_new (const gchar * protocol)
       
   723 {
       
   724   gchar *desc;
       
   725 
       
   726   g_return_val_if_fail (protocol != NULL, NULL);
       
   727 
       
   728   desc = gst_pb_utils_get_sink_description (protocol);
       
   729   return gst_installer_detail_new (desc, "urisink", protocol);
       
   730 }
       
   731 
       
   732 /**
       
   733  * gst_missing_element_installer_detail_new:
       
   734  * @factory_name: the name of the missing element (element factory),
       
   735  *            e.g. "videoscale" or "cdparanoiasrc"
       
   736  *
       
   737  * Returns an opaque string containing all the details about the missing
       
   738  * element to be passed to an external installer called via
       
   739  * gst_install_plugins_async() or gst_install_plugins_sync().
       
   740  * 
       
   741  * This function is mainly for applications that call external plugin
       
   742  * installation mechanisms using one of the two above-mentioned functions in
       
   743  * the case where the application knows exactly what kind of plugin it is
       
   744  * missing.
       
   745  *
       
   746  * Returns: a newly-allocated detail string, or NULL on error. Free string
       
   747  *          with g_free() when not needed any longer.
       
   748  *
       
   749  * Since: 0.10.15
       
   750  */
       
   751 #ifdef __SYMBIAN32__
       
   752 EXPORT_C
       
   753 #endif
       
   754 
       
   755 gchar *
       
   756 gst_missing_element_installer_detail_new (const gchar * factory_name)
       
   757 {
       
   758   gchar *desc;
       
   759 
       
   760   g_return_val_if_fail (factory_name != NULL, NULL);
       
   761 
       
   762   desc = gst_pb_utils_get_element_description (factory_name);
       
   763   return gst_installer_detail_new (desc, "element", factory_name);
       
   764 }
       
   765 
       
   766 /**
       
   767  * gst_missing_decoder_installer_detail_new:
       
   768  * @decode_caps: the (fixed) caps for which a decoder element is needed
       
   769  *
       
   770  * Returns an opaque string containing all the details about the missing
       
   771  * element to be passed to an external installer called via
       
   772  * gst_install_plugins_async() or gst_install_plugins_sync().
       
   773  * 
       
   774  * This function is mainly for applications that call external plugin
       
   775  * installation mechanisms using one of the two above-mentioned functions in
       
   776  * the case where the application knows exactly what kind of plugin it is
       
   777  * missing.
       
   778  *
       
   779  * Returns: a newly-allocated detail string, or NULL on error. Free string
       
   780  *          with g_free() when not needed any longer.
       
   781  *
       
   782  * Since: 0.10.15
       
   783  */
       
   784 #ifdef __SYMBIAN32__
       
   785 EXPORT_C
       
   786 #endif
       
   787 
       
   788 gchar *
       
   789 gst_missing_decoder_installer_detail_new (const GstCaps * decode_caps)
       
   790 {
       
   791   GstCaps *caps;
       
   792   gchar *detail_str, *caps_str, *desc;
       
   793 
       
   794   g_return_val_if_fail (decode_caps != NULL, NULL);
       
   795   g_return_val_if_fail (GST_IS_CAPS (decode_caps), NULL);
       
   796   g_return_val_if_fail (!gst_caps_is_any (decode_caps), NULL);
       
   797   g_return_val_if_fail (!gst_caps_is_empty (decode_caps), NULL);
       
   798   g_return_val_if_fail (gst_caps_is_fixed (decode_caps), NULL);
       
   799 
       
   800   desc = gst_pb_utils_get_decoder_description (decode_caps);
       
   801   caps = copy_and_clean_caps (decode_caps);
       
   802   caps_str = gst_caps_to_string (caps);
       
   803   detail_str = gst_installer_detail_new (desc, "decoder", caps_str);
       
   804   g_free (caps_str);
       
   805   gst_caps_unref (caps);
       
   806 
       
   807   return detail_str;
       
   808 }
       
   809 
       
   810 /**
       
   811  * gst_missing_encoder_installer_detail_new:
       
   812  * @encode_caps: the (fixed) caps for which an encoder element is needed
       
   813  *
       
   814  * Returns an opaque string containing all the details about the missing
       
   815  * element to be passed to an external installer called via
       
   816  * gst_install_plugins_async() or gst_install_plugins_sync().
       
   817  * 
       
   818  * This function is mainly for applications that call external plugin
       
   819  * installation mechanisms using one of the two above-mentioned functions in
       
   820  * the case where the application knows exactly what kind of plugin it is
       
   821  * missing.
       
   822  *
       
   823  * Returns: a newly-allocated detail string, or NULL on error. Free string
       
   824  *          with g_free() when not needed any longer.
       
   825  *
       
   826  * Since: 0.10.15
       
   827  */
       
   828 #ifdef __SYMBIAN32__
       
   829 EXPORT_C
       
   830 #endif
       
   831 
       
   832 gchar *
       
   833 gst_missing_encoder_installer_detail_new (const GstCaps * encode_caps)
       
   834 {
       
   835   GstCaps *caps;
       
   836   gchar *detail_str, *caps_str, *desc;
       
   837 
       
   838   g_return_val_if_fail (encode_caps != NULL, NULL);
       
   839   g_return_val_if_fail (GST_IS_CAPS (encode_caps), NULL);
       
   840   g_return_val_if_fail (!gst_caps_is_any (encode_caps), NULL);
       
   841   g_return_val_if_fail (!gst_caps_is_empty (encode_caps), NULL);
       
   842   g_return_val_if_fail (gst_caps_is_fixed (encode_caps), NULL);
       
   843 
       
   844   desc = gst_pb_utils_get_encoder_description (encode_caps);
       
   845   caps = copy_and_clean_caps (encode_caps);
       
   846   caps_str = gst_caps_to_string (caps);
       
   847   detail_str = gst_installer_detail_new (desc, "encoder", caps_str);
       
   848   g_free (caps_str);
       
   849   gst_caps_unref (caps);
       
   850 
       
   851   return detail_str;
       
   852 }