Blame gst-libs/gst/pbutils/missing-plugins.c

Packit 0652a1
/* GStreamer base utils library missing plugins support
Packit 0652a1
 * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
Packit 0652a1
 *
Packit 0652a1
 * This library is free software; you can redistribute it and/or
Packit 0652a1
 * modify it under the terms of the GNU Library General Public
Packit 0652a1
 * License as published by the Free Software Foundation; either
Packit 0652a1
 * version 2 of the License, or (at your option) any later version.
Packit 0652a1
 *
Packit 0652a1
 * This library is distributed in the hope that it will be useful,
Packit 0652a1
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 0652a1
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 0652a1
 * Library General Public License for more details.
Packit 0652a1
 *
Packit 0652a1
 * You should have received a copy of the GNU Library General Public
Packit 0652a1
 * License along with this library; if not, write to the
Packit 0652a1
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Packit 0652a1
 * Boston, MA 02110-1301, USA.
Packit 0652a1
 */
Packit 0652a1
Packit 0652a1
/**
Packit 0652a1
 * SECTION:gstpbutilsmissingplugins
Packit 0652a1
 * @title: Missing plugins
Packit 0652a1
 * @short_description: Create, recognise and parse missing-plugins messages
Packit 0652a1
 *
Packit 0652a1
 * Functions to create, recognise and parse missing-plugins messages for
Packit 0652a1
 * applications and elements.
Packit 0652a1
 *
Packit 0652a1
 * Missing-plugin messages are posted on the bus by elements like decodebin
Packit 0652a1
 * or playbin if they can't find an appropriate source element or decoder
Packit 0652a1
 * element. The application can use these messages for two things:
Packit 0652a1
 *
Packit 0652a1
 *   * concise error/problem reporting to the user mentioning what exactly
Packit 0652a1
 *     is missing, see gst_missing_plugin_message_get_description()
Packit 0652a1
 *
Packit 0652a1
 *   * initiate installation of missing plugins, see
Packit 0652a1
 *     gst_missing_plugin_message_get_installer_detail() and
Packit 0652a1
 *     gst_install_plugins_async()
Packit 0652a1
 *
Packit 0652a1
 * Applications may also create missing-plugin messages themselves to install
Packit 0652a1
 * required elements that are missing, using the install mechanism mentioned
Packit 0652a1
 * above.
Packit 0652a1
 *
Packit 0652a1
 */
Packit 0652a1
Packit 0652a1
#ifdef HAVE_CONFIG_H
Packit 0652a1
# include "config.h"
Packit 0652a1
#endif
Packit 0652a1
Packit 0652a1
#ifdef HAVE_SYS_TYPES_H
Packit 0652a1
# include <sys/types.h>
Packit 0652a1
#endif
Packit 0652a1
#ifdef HAVE_UNISTD_H
Packit 0652a1
# include <unistd.h>            /* getpid on UNIX */
Packit 0652a1
#endif
Packit 0652a1
#ifdef HAVE_PROCESS_H
Packit 0652a1
# include <process.h>           /* getpid on win32 */
Packit 0652a1
#endif
Packit 0652a1
Packit 0652a1
#include "gst/gst-i18n-plugin.h"
Packit 0652a1
Packit 0652a1
#include "pbutils.h"
Packit 0652a1
#include "pbutils-private.h"
Packit 0652a1
Packit 0652a1
#include <string.h>
Packit 0652a1
Packit 0652a1
#define GST_DETAIL_STRING_MARKER "gstreamer"
Packit 0652a1
Packit 0652a1
typedef enum
Packit 0652a1
{
Packit 0652a1
  GST_MISSING_TYPE_UNKNOWN = 0,
Packit 0652a1
  GST_MISSING_TYPE_URISOURCE,
Packit 0652a1
  GST_MISSING_TYPE_URISINK,
Packit 0652a1
  GST_MISSING_TYPE_ELEMENT,
Packit 0652a1
  GST_MISSING_TYPE_DECODER,
Packit 0652a1
  GST_MISSING_TYPE_ENCODER
Packit 0652a1
} GstMissingType;
Packit 0652a1
Packit 0652a1
static const struct
Packit 0652a1
{
Packit 0652a1
  GstMissingType type;
Packit 0652a1
  const gchar type_string[12];
Packit 0652a1
} missing_type_mapping[] = {
Packit 0652a1
  {
Packit 0652a1
  GST_MISSING_TYPE_URISOURCE, "urisource"}, {
Packit 0652a1
  GST_MISSING_TYPE_URISINK, "urisink"}, {
Packit 0652a1
  GST_MISSING_TYPE_ELEMENT, "element"}, {
Packit 0652a1
  GST_MISSING_TYPE_DECODER, "decoder"}, {
Packit 0652a1
  GST_MISSING_TYPE_ENCODER, "encoder"}
Packit 0652a1
};
Packit 0652a1
Packit 0652a1
static GstMissingType
Packit 0652a1
missing_structure_get_type (const GstStructure * s)
Packit 0652a1
{
Packit 0652a1
  const gchar *type;
Packit 0652a1
  guint i;
Packit 0652a1
Packit 0652a1
  type = gst_structure_get_string (s, "type");
Packit 0652a1
  g_return_val_if_fail (type != NULL, GST_MISSING_TYPE_UNKNOWN);
Packit 0652a1
Packit 0652a1
  for (i = 0; i < G_N_ELEMENTS (missing_type_mapping); ++i) {
Packit 0652a1
    if (strcmp (missing_type_mapping[i].type_string, type) == 0)
Packit 0652a1
      return missing_type_mapping[i].type;
Packit 0652a1
  }
Packit 0652a1
Packit 0652a1
  return GST_MISSING_TYPE_UNKNOWN;
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
GstCaps *
Packit 0652a1
copy_and_clean_caps (const GstCaps * caps)
Packit 0652a1
{
Packit 0652a1
  GstStructure *s;
Packit 0652a1
  GstCaps *ret;
Packit 0652a1
Packit 0652a1
  ret = gst_caps_copy (caps);
Packit 0652a1
Packit 0652a1
  /* make caps easier to interpret, remove common fields that are likely
Packit 0652a1
   * to be irrelevant for determining the right plugin (ie. mostly fields
Packit 0652a1
   * where template caps usually have the standard MIN - MAX range as value) */
Packit 0652a1
  s = gst_caps_get_structure (ret, 0);
Packit 0652a1
  gst_structure_remove_field (s, "codec_data");
Packit 0652a1
  gst_structure_remove_field (s, "streamheader");
Packit 0652a1
  gst_structure_remove_field (s, "palette_data");
Packit 0652a1
  gst_structure_remove_field (s, "pixel-aspect-ratio");
Packit 0652a1
  gst_structure_remove_field (s, "framerate");
Packit 0652a1
  gst_structure_remove_field (s, "leaf_size");
Packit 0652a1
  gst_structure_remove_field (s, "packet_size");
Packit 0652a1
  gst_structure_remove_field (s, "block_align");
Packit 0652a1
  gst_structure_remove_field (s, "metadata-interval");  /* icy caps */
Packit 0652a1
  /* decoders/encoders almost always handle the usual width/height/channel/rate
Packit 0652a1
   * range (and if we don't remove this then the app will have a much harder
Packit 0652a1
   * time blacklisting formats it has unsuccessfully tried to install before) */
Packit 0652a1
  gst_structure_remove_field (s, "width");
Packit 0652a1
  gst_structure_remove_field (s, "depth");
Packit 0652a1
  gst_structure_remove_field (s, "height");
Packit 0652a1
  gst_structure_remove_field (s, "channels");
Packit 0652a1
  gst_structure_remove_field (s, "rate");
Packit 0652a1
  /* parsed, framed, stream-format and alignment are going to be handled by
Packit 0652a1
   * parsers and not relevant for decoders/encoders usually */
Packit 0652a1
  gst_structure_remove_field (s, "parsed");
Packit 0652a1
  gst_structure_remove_field (s, "framed");
Packit 0652a1
  gst_structure_remove_field (s, "stream-format");
Packit 0652a1
  gst_structure_remove_field (s, "alignment");
Packit 0652a1
  /* rtp fields */
Packit 0652a1
  gst_structure_remove_field (s, "config");
Packit 0652a1
  gst_structure_remove_field (s, "clock-rate");
Packit 0652a1
  gst_structure_remove_field (s, "timestamp-offset");
Packit 0652a1
  gst_structure_remove_field (s, "maxps");
Packit 0652a1
  gst_structure_remove_field (s, "seqnum-offset");
Packit 0652a1
  gst_structure_remove_field (s, "npt-start");
Packit 0652a1
  gst_structure_remove_field (s, "npt-stop");
Packit 0652a1
  gst_structure_remove_field (s, "play-speed");
Packit 0652a1
  gst_structure_remove_field (s, "play-scale");
Packit 0652a1
  gst_structure_remove_field (s, "dynamic_range");
Packit 0652a1
Packit 0652a1
  return ret;
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
/**
Packit 0652a1
 * gst_missing_uri_source_message_new:
Packit 0652a1
 * @element: the #GstElement posting the message
Packit 0652a1
 * @protocol: the URI protocol the missing source needs to implement,
Packit 0652a1
 *            e.g. "http" or "mms"
Packit 0652a1
 *
Packit 0652a1
 * Creates a missing-plugin message for @element to notify the application
Packit 0652a1
 * that a source element for a particular URI protocol is missing. This
Packit 0652a1
 * function is mainly for use in plugins.
Packit 0652a1
 *
Packit 0652a1
 * Returns: (transfer full): a new #GstMessage, or NULL on error
Packit 0652a1
 */
Packit 0652a1
GstMessage *
Packit 0652a1
gst_missing_uri_source_message_new (GstElement * element,
Packit 0652a1
    const gchar * protocol)
Packit 0652a1
{
Packit 0652a1
  GstStructure *s;
Packit 0652a1
  gchar *description;
Packit 0652a1
Packit 0652a1
  g_return_val_if_fail (element != NULL, NULL);
Packit 0652a1
  g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
Packit 0652a1
  g_return_val_if_fail (protocol != NULL, NULL);
Packit 0652a1
Packit 0652a1
  description = gst_pb_utils_get_source_description (protocol);
Packit 0652a1
Packit 0652a1
  s = gst_structure_new ("missing-plugin", "type", G_TYPE_STRING,
Packit 0652a1
      "urisource", "detail", G_TYPE_STRING, protocol, "name", G_TYPE_STRING,
Packit 0652a1
      description, NULL);
Packit 0652a1
Packit 0652a1
  g_free (description);
Packit 0652a1
  return gst_message_new_element (GST_OBJECT_CAST (element), s);
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
/**
Packit 0652a1
 * gst_missing_uri_sink_message_new:
Packit 0652a1
 * @element: the #GstElement posting the message
Packit 0652a1
 * @protocol: the URI protocol the missing sink needs to implement,
Packit 0652a1
 *            e.g. "http" or "smb"
Packit 0652a1
 *
Packit 0652a1
 * Creates a missing-plugin message for @element to notify the application
Packit 0652a1
 * that a sink element for a particular URI protocol is missing. This
Packit 0652a1
 * function is mainly for use in plugins.
Packit 0652a1
 *
Packit 0652a1
 * Returns: (transfer full): a new #GstMessage, or NULL on error
Packit 0652a1
 */
Packit 0652a1
GstMessage *
Packit 0652a1
gst_missing_uri_sink_message_new (GstElement * element, const gchar * protocol)
Packit 0652a1
{
Packit 0652a1
  GstStructure *s;
Packit 0652a1
  gchar *description;
Packit 0652a1
Packit 0652a1
  g_return_val_if_fail (element != NULL, NULL);
Packit 0652a1
  g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
Packit 0652a1
  g_return_val_if_fail (protocol != NULL, NULL);
Packit 0652a1
Packit 0652a1
  description = gst_pb_utils_get_sink_description (protocol);
Packit 0652a1
Packit 0652a1
  s = gst_structure_new ("missing-plugin", "type", G_TYPE_STRING,
Packit 0652a1
      "urisink", "detail", G_TYPE_STRING, protocol, "name", G_TYPE_STRING,
Packit 0652a1
      description, NULL);
Packit 0652a1
Packit 0652a1
  g_free (description);
Packit 0652a1
  return gst_message_new_element (GST_OBJECT_CAST (element), s);
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
/**
Packit 0652a1
 * gst_missing_element_message_new:
Packit 0652a1
 * @element: the #GstElement posting the message
Packit 0652a1
 * @factory_name: the name of the missing element (element factory),
Packit 0652a1
 *            e.g. "videoscale" or "cdparanoiasrc"
Packit 0652a1
 *
Packit 0652a1
 * Creates a missing-plugin message for @element to notify the application
Packit 0652a1
 * that a certain required element is missing. This function is mainly for
Packit 0652a1
 * use in plugins.
Packit 0652a1
 *
Packit 0652a1
 * Returns: (transfer full): a new #GstMessage, or NULL on error
Packit 0652a1
 */
Packit 0652a1
GstMessage *
Packit 0652a1
gst_missing_element_message_new (GstElement * element,
Packit 0652a1
    const gchar * factory_name)
Packit 0652a1
{
Packit 0652a1
  GstStructure *s;
Packit 0652a1
  gchar *description;
Packit 0652a1
Packit 0652a1
  g_return_val_if_fail (element != NULL, NULL);
Packit 0652a1
  g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
Packit 0652a1
  g_return_val_if_fail (factory_name != NULL, NULL);
Packit 0652a1
Packit 0652a1
  description = gst_pb_utils_get_element_description (factory_name);
Packit 0652a1
Packit 0652a1
  s = gst_structure_new ("missing-plugin", "type", G_TYPE_STRING,
Packit 0652a1
      "element", "detail", G_TYPE_STRING, factory_name, "name", G_TYPE_STRING,
Packit 0652a1
      description, NULL);
Packit 0652a1
Packit 0652a1
  g_free (description);
Packit 0652a1
  return gst_message_new_element (GST_OBJECT_CAST (element), s);
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
/**
Packit 0652a1
 * gst_missing_decoder_message_new:
Packit 0652a1
 * @element: the #GstElement posting the message
Packit 0652a1
 * @decode_caps: the (fixed) caps for which a decoder element is needed
Packit 0652a1
 *
Packit 0652a1
 * Creates a missing-plugin message for @element to notify the application
Packit 0652a1
 * that a decoder element for a particular set of (fixed) caps is missing.
Packit 0652a1
 * This function is mainly for use in plugins.
Packit 0652a1
 *
Packit 0652a1
 * Returns: (transfer full): a new #GstMessage, or NULL on error
Packit 0652a1
 */
Packit 0652a1
GstMessage *
Packit 0652a1
gst_missing_decoder_message_new (GstElement * element,
Packit 0652a1
    const GstCaps * decode_caps)
Packit 0652a1
{
Packit 0652a1
  GstStructure *s;
Packit 0652a1
  GstCaps *caps;
Packit 0652a1
  gchar *description;
Packit 0652a1
Packit 0652a1
  g_return_val_if_fail (element != NULL, NULL);
Packit 0652a1
  g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
Packit 0652a1
  g_return_val_if_fail (decode_caps != NULL, NULL);
Packit 0652a1
  g_return_val_if_fail (GST_IS_CAPS (decode_caps), NULL);
Packit 0652a1
  g_return_val_if_fail (!gst_caps_is_any (decode_caps), NULL);
Packit 0652a1
  g_return_val_if_fail (!gst_caps_is_empty (decode_caps), NULL);
Packit 0652a1
  g_return_val_if_fail (gst_caps_is_fixed (decode_caps), NULL);
Packit 0652a1
Packit 0652a1
  description = gst_pb_utils_get_decoder_description (decode_caps);
Packit 0652a1
  caps = copy_and_clean_caps (decode_caps);
Packit 0652a1
Packit 0652a1
  s = gst_structure_new ("missing-plugin", "type", G_TYPE_STRING,
Packit 0652a1
      "decoder", "detail", GST_TYPE_CAPS, caps, "name", G_TYPE_STRING,
Packit 0652a1
      description, NULL);
Packit 0652a1
Packit 0652a1
  gst_caps_unref (caps);
Packit 0652a1
  g_free (description);
Packit 0652a1
Packit 0652a1
  return gst_message_new_element (GST_OBJECT_CAST (element), s);
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
/**
Packit 0652a1
 * gst_missing_encoder_message_new:
Packit 0652a1
 * @element: the #GstElement posting the message
Packit 0652a1
 * @encode_caps: the (fixed) caps for which an encoder element is needed
Packit 0652a1
 *
Packit 0652a1
 * Creates a missing-plugin message for @element to notify the application
Packit 0652a1
 * that an encoder element for a particular set of (fixed) caps is missing.
Packit 0652a1
 * This function is mainly for use in plugins.
Packit 0652a1
 *
Packit 0652a1
 * Returns: (transfer full): a new #GstMessage, or NULL on error
Packit 0652a1
 */
Packit 0652a1
GstMessage *
Packit 0652a1
gst_missing_encoder_message_new (GstElement * element,
Packit 0652a1
    const GstCaps * encode_caps)
Packit 0652a1
{
Packit 0652a1
  GstStructure *s;
Packit 0652a1
  GstCaps *caps;
Packit 0652a1
  gchar *description;
Packit 0652a1
Packit 0652a1
  g_return_val_if_fail (element != NULL, NULL);
Packit 0652a1
  g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
Packit 0652a1
  g_return_val_if_fail (encode_caps != NULL, NULL);
Packit 0652a1
  g_return_val_if_fail (GST_IS_CAPS (encode_caps), NULL);
Packit 0652a1
  g_return_val_if_fail (!gst_caps_is_any (encode_caps), NULL);
Packit 0652a1
  g_return_val_if_fail (!gst_caps_is_empty (encode_caps), NULL);
Packit 0652a1
  g_return_val_if_fail (gst_caps_is_fixed (encode_caps), NULL);
Packit 0652a1
Packit 0652a1
  description = gst_pb_utils_get_encoder_description (encode_caps);
Packit 0652a1
  caps = copy_and_clean_caps (encode_caps);
Packit 0652a1
Packit 0652a1
  s = gst_structure_new ("missing-plugin", "type", G_TYPE_STRING,
Packit 0652a1
      "encoder", "detail", GST_TYPE_CAPS, caps, "name", G_TYPE_STRING,
Packit 0652a1
      description, NULL);
Packit 0652a1
Packit 0652a1
  gst_caps_unref (caps);
Packit 0652a1
  g_free (description);
Packit 0652a1
Packit 0652a1
  return gst_message_new_element (GST_OBJECT_CAST (element), s);
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
static gboolean
Packit 0652a1
missing_structure_get_string_detail (const GstStructure * s, gchar ** p_detail)
Packit 0652a1
{
Packit 0652a1
  const gchar *detail;
Packit 0652a1
  GType detail_type;
Packit 0652a1
Packit 0652a1
  *p_detail = NULL;
Packit 0652a1
Packit 0652a1
  detail_type = gst_structure_get_field_type (s, "detail");
Packit 0652a1
  if (!g_type_is_a (detail_type, G_TYPE_STRING)) {
Packit 0652a1
    GST_WARNING ("expected 'detail' field to be of G_TYPE_STRING");
Packit 0652a1
    return FALSE;
Packit 0652a1
  }
Packit 0652a1
Packit 0652a1
  detail = gst_structure_get_string (s, "detail");
Packit 0652a1
  if (detail == NULL || *detail == '\0') {
Packit 0652a1
    GST_WARNING ("empty 'detail' field");
Packit 0652a1
    return FALSE;
Packit 0652a1
  }
Packit 0652a1
  *p_detail = g_strdup (detail);
Packit 0652a1
  return TRUE;
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
static gboolean
Packit 0652a1
missing_structure_get_caps_detail (const GstStructure * s, GstCaps ** p_caps)
Packit 0652a1
{
Packit 0652a1
  const GstCaps *caps;
Packit 0652a1
  const GValue *val;
Packit 0652a1
  GType detail_type;
Packit 0652a1
Packit 0652a1
  *p_caps = NULL;
Packit 0652a1
Packit 0652a1
  detail_type = gst_structure_get_field_type (s, "detail");
Packit 0652a1
  if (!g_type_is_a (detail_type, GST_TYPE_CAPS)) {
Packit 0652a1
    GST_WARNING ("expected 'detail' field to be of GST_TYPE_CAPS");
Packit 0652a1
    return FALSE;
Packit 0652a1
  }
Packit 0652a1
Packit 0652a1
  val = gst_structure_get_value (s, "detail");
Packit 0652a1
  caps = gst_value_get_caps (val);
Packit 0652a1
  if (gst_caps_is_empty (caps) || gst_caps_is_any (caps)) {
Packit 0652a1
    GST_WARNING ("EMPTY or ANY caps not allowed");
Packit 0652a1
    return FALSE;
Packit 0652a1
  }
Packit 0652a1
Packit 0652a1
  *p_caps = gst_caps_copy (caps);
Packit 0652a1
  return TRUE;
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
/**
Packit 0652a1
 * gst_missing_plugin_message_get_installer_detail:
Packit 0652a1
 * @msg: a missing-plugin #GstMessage of type #GST_MESSAGE_ELEMENT
Packit 0652a1
 *
Packit 0652a1
 * Returns an opaque string containing all the details about the missing
Packit 0652a1
 * element to be passed to an external installer called via
Packit 0652a1
 * gst_install_plugins_async() or gst_install_plugins_sync().
Packit 0652a1
 *
Packit 0652a1
 * This function is mainly for applications that call external plugin
Packit 0652a1
 * installation mechanisms using one of the two above-mentioned functions.
Packit 0652a1
 *
Packit 0652a1
 * Returns: a newly-allocated detail string, or NULL on error. Free string
Packit 0652a1
 *          with g_free() when not needed any longer.
Packit 0652a1
 */
Packit 0652a1
gchar *
Packit 0652a1
gst_missing_plugin_message_get_installer_detail (GstMessage * msg)
Packit 0652a1
{
Packit 0652a1
  GstMissingType missing_type;
Packit 0652a1
  const gchar *progname;
Packit 0652a1
  const gchar *type;
Packit 0652a1
  GString *str = NULL;
Packit 0652a1
  gchar *detail = NULL;
Packit 0652a1
  gchar *desc;
Packit 0652a1
  const GstStructure *structure;
Packit 0652a1
Packit 0652a1
  g_return_val_if_fail (gst_is_missing_plugin_message (msg), NULL);
Packit 0652a1
Packit 0652a1
  structure = gst_message_get_structure (msg);
Packit 0652a1
  GST_LOG ("Parsing missing-plugin message: %" GST_PTR_FORMAT, structure);
Packit 0652a1
Packit 0652a1
  missing_type = missing_structure_get_type (structure);
Packit 0652a1
  if (missing_type == GST_MISSING_TYPE_UNKNOWN) {
Packit 0652a1
    GST_WARNING ("couldn't parse 'type' field");
Packit 0652a1
    goto error;
Packit 0652a1
  }
Packit 0652a1
Packit 0652a1
  type = gst_structure_get_string (structure, "type");
Packit 0652a1
  g_assert (type != NULL);      /* validity already checked above */
Packit 0652a1
Packit 0652a1
  /* FIXME: use gst_installer_detail_new() here too */
Packit 0652a1
  str = g_string_new (GST_DETAIL_STRING_MARKER "|");
Packit 0652a1
  g_string_append_printf (str, "%s|", GST_API_VERSION);
Packit 0652a1
Packit 0652a1
  progname = (const gchar *) g_get_prgname ();
Packit 0652a1
  if (progname) {
Packit 0652a1
    g_string_append_printf (str, "%s|", progname);
Packit 0652a1
  } else {
Packit 0652a1
    g_string_append_printf (str, "pid/%lu|", (gulong) getpid ());
Packit 0652a1
  }
Packit 0652a1
Packit 0652a1
  desc = gst_missing_plugin_message_get_description (msg);
Packit 0652a1
  if (desc) {
Packit 0652a1
    g_strdelimit (desc, "|", '#');
Packit 0652a1
    g_string_append_printf (str, "%s|", desc);
Packit 0652a1
    g_free (desc);
Packit 0652a1
  } else {
Packit 0652a1
    g_string_append (str, "|");
Packit 0652a1
  }
Packit 0652a1
Packit 0652a1
  switch (missing_type) {
Packit 0652a1
    case GST_MISSING_TYPE_URISOURCE:
Packit 0652a1
    case GST_MISSING_TYPE_URISINK:
Packit 0652a1
    case GST_MISSING_TYPE_ELEMENT:
Packit 0652a1
      if (!missing_structure_get_string_detail (structure, &detail))
Packit 0652a1
        goto error;
Packit 0652a1
      break;
Packit 0652a1
    case GST_MISSING_TYPE_DECODER:
Packit 0652a1
    case GST_MISSING_TYPE_ENCODER:{
Packit 0652a1
      GstCaps *caps = NULL;
Packit 0652a1
Packit 0652a1
      if (!missing_structure_get_caps_detail (structure, &caps))
Packit 0652a1
        goto error;
Packit 0652a1
Packit 0652a1
      detail = gst_caps_to_string (caps);
Packit 0652a1
      gst_caps_unref (caps);
Packit 0652a1
      break;
Packit 0652a1
    }
Packit 0652a1
    default:
Packit 0652a1
      g_return_val_if_reached (NULL);
Packit 0652a1
  }
Packit 0652a1
Packit 0652a1
  g_string_append_printf (str, "%s-%s", type, detail);
Packit 0652a1
  g_free (detail);
Packit 0652a1
Packit 0652a1
  return g_string_free (str, FALSE);
Packit 0652a1
Packit 0652a1
/* ERRORS */
Packit 0652a1
error:
Packit 0652a1
  {
Packit 0652a1
    GST_WARNING ("Failed to parse missing-plugin msg: %" GST_PTR_FORMAT, msg);
Packit 0652a1
    if (str)
Packit 0652a1
      g_string_free (str, TRUE);
Packit 0652a1
    return NULL;
Packit 0652a1
  }
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
/**
Packit 0652a1
 * gst_missing_plugin_message_get_description:
Packit 0652a1
 * @msg: a missing-plugin #GstMessage of type #GST_MESSAGE_ELEMENT
Packit 0652a1
 *
Packit 0652a1
 * Returns a localised string describing the missing feature, for use in
Packit 0652a1
 * error dialogs and the like. Should never return NULL unless @msg is not
Packit 0652a1
 * a valid missing-plugin message.
Packit 0652a1
 *
Packit 0652a1
 * This function is mainly for applications that need a human-readable string
Packit 0652a1
 * describing a missing plugin, given a previously collected missing-plugin
Packit 0652a1
 * message
Packit 0652a1
 *
Packit 0652a1
 * Returns: a newly-allocated description string, or NULL on error. Free
Packit 0652a1
 *          string with g_free() when not needed any longer.
Packit 0652a1
 */
Packit 0652a1
gchar *
Packit 0652a1
gst_missing_plugin_message_get_description (GstMessage * msg)
Packit 0652a1
{
Packit 0652a1
  GstMissingType missing_type;
Packit 0652a1
  const gchar *desc;
Packit 0652a1
  gchar *ret = NULL;
Packit 0652a1
  const GstStructure *structure;
Packit 0652a1
Packit 0652a1
  g_return_val_if_fail (gst_is_missing_plugin_message (msg), NULL);
Packit 0652a1
Packit 0652a1
  structure = gst_message_get_structure (msg);
Packit 0652a1
  GST_LOG ("Parsing missing-plugin message: %" GST_PTR_FORMAT, structure);
Packit 0652a1
Packit 0652a1
  desc = gst_structure_get_string (structure, "name");
Packit 0652a1
  if (desc != NULL && *desc != '\0') {
Packit 0652a1
    ret = g_strdup (desc);
Packit 0652a1
    goto done;
Packit 0652a1
  }
Packit 0652a1
Packit 0652a1
  /* fallback #1 */
Packit 0652a1
  missing_type = missing_structure_get_type (structure);
Packit 0652a1
Packit 0652a1
  switch (missing_type) {
Packit 0652a1
    case GST_MISSING_TYPE_URISOURCE:
Packit 0652a1
    case GST_MISSING_TYPE_URISINK:
Packit 0652a1
    case GST_MISSING_TYPE_ELEMENT:{
Packit 0652a1
      gchar *detail = NULL;
Packit 0652a1
Packit 0652a1
      if (missing_structure_get_string_detail (structure, &detail)) {
Packit 0652a1
        if (missing_type == GST_MISSING_TYPE_URISOURCE)
Packit 0652a1
          ret = gst_pb_utils_get_source_description (detail);
Packit 0652a1
        else if (missing_type == GST_MISSING_TYPE_URISINK)
Packit 0652a1
          ret = gst_pb_utils_get_sink_description (detail);
Packit 0652a1
        else
Packit 0652a1
          ret = gst_pb_utils_get_element_description (detail);
Packit 0652a1
        g_free (detail);
Packit 0652a1
      }
Packit 0652a1
      break;
Packit 0652a1
    }
Packit 0652a1
    case GST_MISSING_TYPE_DECODER:
Packit 0652a1
    case GST_MISSING_TYPE_ENCODER:{
Packit 0652a1
      GstCaps *caps = NULL;
Packit 0652a1
Packit 0652a1
      if (missing_structure_get_caps_detail (structure, &caps)) {
Packit 0652a1
        if (missing_type == GST_MISSING_TYPE_DECODER)
Packit 0652a1
          ret = gst_pb_utils_get_decoder_description (caps);
Packit 0652a1
        else
Packit 0652a1
          ret = gst_pb_utils_get_encoder_description (caps);
Packit 0652a1
        gst_caps_unref (caps);
Packit 0652a1
      }
Packit 0652a1
      break;
Packit 0652a1
    }
Packit 0652a1
    default:
Packit 0652a1
      break;
Packit 0652a1
  }
Packit 0652a1
Packit 0652a1
  if (ret)
Packit 0652a1
    goto done;
Packit 0652a1
Packit 0652a1
  /* fallback #2 */
Packit 0652a1
  switch (missing_type) {
Packit 0652a1
    case GST_MISSING_TYPE_URISOURCE:
Packit 0652a1
      desc = _("Unknown source element");
Packit 0652a1
      break;
Packit 0652a1
    case GST_MISSING_TYPE_URISINK:
Packit 0652a1
      desc = _("Unknown sink element");
Packit 0652a1
      break;
Packit 0652a1
    case GST_MISSING_TYPE_ELEMENT:
Packit 0652a1
      desc = _("Unknown element");
Packit 0652a1
      break;
Packit 0652a1
    case GST_MISSING_TYPE_DECODER:
Packit 0652a1
      desc = _("Unknown decoder element");
Packit 0652a1
      break;
Packit 0652a1
    case GST_MISSING_TYPE_ENCODER:
Packit 0652a1
      desc = _("Unknown encoder element");
Packit 0652a1
      break;
Packit 0652a1
    default:
Packit 0652a1
      /* we should really never get here, but we better still return
Packit 0652a1
       * something if we do */
Packit 0652a1
      desc = _("Plugin or element of unknown type");
Packit 0652a1
      break;
Packit 0652a1
  }
Packit 0652a1
  ret = g_strdup (desc);
Packit 0652a1
Packit 0652a1
done:
Packit 0652a1
Packit 0652a1
  GST_LOG ("returning '%s'", ret);
Packit 0652a1
  return ret;
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
/**
Packit 0652a1
 * gst_is_missing_plugin_message:
Packit 0652a1
 * @msg: a #GstMessage
Packit 0652a1
 *
Packit 0652a1
 * Checks whether @msg is a missing plugins message.
Packit 0652a1
 *
Packit 0652a1
 * Returns: %TRUE if @msg is a missing-plugins message, otherwise %FALSE.
Packit 0652a1
 */
Packit 0652a1
gboolean
Packit 0652a1
gst_is_missing_plugin_message (GstMessage * msg)
Packit 0652a1
{
Packit 0652a1
  const GstStructure *structure;
Packit 0652a1
Packit 0652a1
  g_return_val_if_fail (msg != NULL, FALSE);
Packit 0652a1
  g_return_val_if_fail (GST_IS_MESSAGE (msg), FALSE);
Packit 0652a1
Packit 0652a1
  structure = gst_message_get_structure (msg);
Packit 0652a1
  if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ELEMENT || structure == NULL)
Packit 0652a1
    return FALSE;
Packit 0652a1
Packit 0652a1
  return gst_structure_has_name (structure, "missing-plugin");
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
/* takes ownership of the description */
Packit 0652a1
static gchar *
Packit 0652a1
gst_installer_detail_new (gchar * description, const gchar * type,
Packit 0652a1
    const gchar * detail)
Packit 0652a1
{
Packit 0652a1
  const gchar *progname;
Packit 0652a1
  GString *s;
Packit 0652a1
Packit 0652a1
  s = g_string_new (GST_DETAIL_STRING_MARKER "|");
Packit 0652a1
  g_string_append_printf (s, "%s|", GST_API_VERSION);
Packit 0652a1
Packit 0652a1
  progname = (const gchar *) g_get_prgname ();
Packit 0652a1
  if (progname) {
Packit 0652a1
    g_string_append_printf (s, "%s|", progname);
Packit 0652a1
  } else {
Packit 0652a1
    g_string_append_printf (s, "pid/%lu|", (gulong) getpid ());
Packit 0652a1
  }
Packit 0652a1
Packit 0652a1
  if (description) {
Packit 0652a1
    g_strdelimit (description, "|", '#');
Packit 0652a1
    g_string_append_printf (s, "%s|", description);
Packit 0652a1
    g_free (description);
Packit 0652a1
  } else {
Packit 0652a1
    g_string_append (s, "|");
Packit 0652a1
  }
Packit 0652a1
Packit 0652a1
  g_string_append_printf (s, "%s-%s", type, detail);
Packit 0652a1
Packit 0652a1
  return g_string_free (s, FALSE);
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
/**
Packit 0652a1
 * gst_missing_uri_source_installer_detail_new:
Packit 0652a1
 * @protocol: the URI protocol the missing source needs to implement,
Packit 0652a1
 *            e.g. "http" or "mms"
Packit 0652a1
 *
Packit 0652a1
 * Returns an opaque string containing all the details about the missing
Packit 0652a1
 * element to be passed to an external installer called via
Packit 0652a1
 * gst_install_plugins_async() or gst_install_plugins_sync().
Packit 0652a1
 *
Packit 0652a1
 * This function is mainly for applications that call external plugin
Packit 0652a1
 * installation mechanisms using one of the two above-mentioned functions in
Packit 0652a1
 * the case where the application knows exactly what kind of plugin it is
Packit 0652a1
 * missing.
Packit 0652a1
 *
Packit 0652a1
 * Returns: a newly-allocated detail string, or NULL on error. Free string
Packit 0652a1
 *          with g_free() when not needed any longer.
Packit 0652a1
 */
Packit 0652a1
gchar *
Packit 0652a1
gst_missing_uri_source_installer_detail_new (const gchar * protocol)
Packit 0652a1
{
Packit 0652a1
  gchar *desc;
Packit 0652a1
Packit 0652a1
  g_return_val_if_fail (protocol != NULL, NULL);
Packit 0652a1
Packit 0652a1
  desc = gst_pb_utils_get_source_description (protocol);
Packit 0652a1
  return gst_installer_detail_new (desc, "urisource", protocol);
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
/**
Packit 0652a1
 * gst_missing_uri_sink_installer_detail_new:
Packit 0652a1
 * @protocol: the URI protocol the missing source needs to implement,
Packit 0652a1
 *            e.g. "http" or "mms"
Packit 0652a1
 *
Packit 0652a1
 * Returns an opaque string containing all the details about the missing
Packit 0652a1
 * element to be passed to an external installer called via
Packit 0652a1
 * gst_install_plugins_async() or gst_install_plugins_sync().
Packit 0652a1
 *
Packit 0652a1
 * This function is mainly for applications that call external plugin
Packit 0652a1
 * installation mechanisms using one of the two above-mentioned functions in
Packit 0652a1
 * the case where the application knows exactly what kind of plugin it is
Packit 0652a1
 * missing.
Packit 0652a1
 *
Packit 0652a1
 * Returns: a newly-allocated detail string, or NULL on error. Free string
Packit 0652a1
 *          with g_free() when not needed any longer.
Packit 0652a1
 */
Packit 0652a1
gchar *
Packit 0652a1
gst_missing_uri_sink_installer_detail_new (const gchar * protocol)
Packit 0652a1
{
Packit 0652a1
  gchar *desc;
Packit 0652a1
Packit 0652a1
  g_return_val_if_fail (protocol != NULL, NULL);
Packit 0652a1
Packit 0652a1
  desc = gst_pb_utils_get_sink_description (protocol);
Packit 0652a1
  return gst_installer_detail_new (desc, "urisink", protocol);
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
/**
Packit 0652a1
 * gst_missing_element_installer_detail_new:
Packit 0652a1
 * @factory_name: the name of the missing element (element factory),
Packit 0652a1
 *            e.g. "videoscale" or "cdparanoiasrc"
Packit 0652a1
 *
Packit 0652a1
 * Returns an opaque string containing all the details about the missing
Packit 0652a1
 * element to be passed to an external installer called via
Packit 0652a1
 * gst_install_plugins_async() or gst_install_plugins_sync().
Packit 0652a1
 *
Packit 0652a1
 * This function is mainly for applications that call external plugin
Packit 0652a1
 * installation mechanisms using one of the two above-mentioned functions in
Packit 0652a1
 * the case where the application knows exactly what kind of plugin it is
Packit 0652a1
 * missing.
Packit 0652a1
 *
Packit 0652a1
 * Returns: a newly-allocated detail string, or NULL on error. Free string
Packit 0652a1
 *          with g_free() when not needed any longer.
Packit 0652a1
 */
Packit 0652a1
gchar *
Packit 0652a1
gst_missing_element_installer_detail_new (const gchar * factory_name)
Packit 0652a1
{
Packit 0652a1
  gchar *desc;
Packit 0652a1
Packit 0652a1
  g_return_val_if_fail (factory_name != NULL, NULL);
Packit 0652a1
Packit 0652a1
  desc = gst_pb_utils_get_element_description (factory_name);
Packit 0652a1
  return gst_installer_detail_new (desc, "element", factory_name);
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
/**
Packit 0652a1
 * gst_missing_decoder_installer_detail_new:
Packit 0652a1
 * @decode_caps: the (fixed) caps for which a decoder element is needed
Packit 0652a1
 *
Packit 0652a1
 * Returns an opaque string containing all the details about the missing
Packit 0652a1
 * element to be passed to an external installer called via
Packit 0652a1
 * gst_install_plugins_async() or gst_install_plugins_sync().
Packit 0652a1
 *
Packit 0652a1
 * This function is mainly for applications that call external plugin
Packit 0652a1
 * installation mechanisms using one of the two above-mentioned functions in
Packit 0652a1
 * the case where the application knows exactly what kind of plugin it is
Packit 0652a1
 * missing.
Packit 0652a1
 *
Packit 0652a1
 * Returns: a newly-allocated detail string, or NULL on error. Free string
Packit 0652a1
 *          with g_free() when not needed any longer.
Packit 0652a1
 */
Packit 0652a1
gchar *
Packit 0652a1
gst_missing_decoder_installer_detail_new (const GstCaps * decode_caps)
Packit 0652a1
{
Packit 0652a1
  GstCaps *caps;
Packit 0652a1
  gchar *detail_str, *caps_str, *desc;
Packit 0652a1
Packit 0652a1
  g_return_val_if_fail (decode_caps != NULL, NULL);
Packit 0652a1
  g_return_val_if_fail (GST_IS_CAPS (decode_caps), NULL);
Packit 0652a1
  g_return_val_if_fail (!gst_caps_is_any (decode_caps), NULL);
Packit 0652a1
  g_return_val_if_fail (!gst_caps_is_empty (decode_caps), NULL);
Packit 0652a1
  g_return_val_if_fail (gst_caps_is_fixed (decode_caps), NULL);
Packit 0652a1
Packit 0652a1
  desc = gst_pb_utils_get_decoder_description (decode_caps);
Packit 0652a1
  caps = copy_and_clean_caps (decode_caps);
Packit 0652a1
  caps_str = gst_caps_to_string (caps);
Packit 0652a1
  detail_str = gst_installer_detail_new (desc, "decoder", caps_str);
Packit 0652a1
  g_free (caps_str);
Packit 0652a1
  gst_caps_unref (caps);
Packit 0652a1
Packit 0652a1
  return detail_str;
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
/**
Packit 0652a1
 * gst_missing_encoder_installer_detail_new:
Packit 0652a1
 * @encode_caps: the (fixed) caps for which an encoder element is needed
Packit 0652a1
 *
Packit 0652a1
 * Returns an opaque string containing all the details about the missing
Packit 0652a1
 * element to be passed to an external installer called via
Packit 0652a1
 * gst_install_plugins_async() or gst_install_plugins_sync().
Packit 0652a1
 *
Packit 0652a1
 * This function is mainly for applications that call external plugin
Packit 0652a1
 * installation mechanisms using one of the two above-mentioned functions in
Packit 0652a1
 * the case where the application knows exactly what kind of plugin it is
Packit 0652a1
 * missing.
Packit 0652a1
 *
Packit 0652a1
 * Returns: a newly-allocated detail string, or NULL on error. Free string
Packit 0652a1
 *          with g_free() when not needed any longer.
Packit 0652a1
 */
Packit 0652a1
gchar *
Packit 0652a1
gst_missing_encoder_installer_detail_new (const GstCaps * encode_caps)
Packit 0652a1
{
Packit 0652a1
  GstCaps *caps;
Packit 0652a1
  gchar *detail_str, *caps_str, *desc;
Packit 0652a1
Packit 0652a1
  g_return_val_if_fail (encode_caps != NULL, NULL);
Packit 0652a1
  g_return_val_if_fail (GST_IS_CAPS (encode_caps), NULL);
Packit 0652a1
  g_return_val_if_fail (!gst_caps_is_any (encode_caps), NULL);
Packit 0652a1
  g_return_val_if_fail (!gst_caps_is_empty (encode_caps), NULL);
Packit 0652a1
  g_return_val_if_fail (gst_caps_is_fixed (encode_caps), NULL);
Packit 0652a1
Packit 0652a1
  desc = gst_pb_utils_get_encoder_description (encode_caps);
Packit 0652a1
  caps = copy_and_clean_caps (encode_caps);
Packit 0652a1
  caps_str = gst_caps_to_string (caps);
Packit 0652a1
  detail_str = gst_installer_detail_new (desc, "encoder", caps_str);
Packit 0652a1
  g_free (caps_str);
Packit 0652a1
  gst_caps_unref (caps);
Packit 0652a1
Packit 0652a1
  return detail_str;
Packit 0652a1
}