mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	source: add GError to get_formats
Add GError to get_formats to get more error information. Update the source possible formats when source-output is active
This commit is contained in:
		
							parent
							
								
									0378dcd4b7
								
							
						
					
					
						commit
						7cf87d902e
					
				
					 4 changed files with 109 additions and 68 deletions
				
			
		| 
						 | 
				
			
			@ -160,35 +160,61 @@ set_state (PinosSource      *source,
 | 
			
		|||
 | 
			
		||||
static GBytes *
 | 
			
		||||
get_formats (PinosSource *source,
 | 
			
		||||
             GBytes      *filter)
 | 
			
		||||
             GBytes      *filter,
 | 
			
		||||
             GError     **error)
 | 
			
		||||
{
 | 
			
		||||
  PinosGstSourcePrivate *priv = PINOS_GST_SOURCE (source)->priv;
 | 
			
		||||
  GstCaps *caps;
 | 
			
		||||
  GstCaps *caps, *cfilter;
 | 
			
		||||
  gchar *str;
 | 
			
		||||
 | 
			
		||||
  if (filter) {
 | 
			
		||||
    GstCaps *cfilter;
 | 
			
		||||
 | 
			
		||||
    cfilter = gst_caps_from_string (g_bytes_get_data (filter, NULL));
 | 
			
		||||
    if (cfilter == NULL)
 | 
			
		||||
      return NULL;
 | 
			
		||||
      goto invalid_filter;
 | 
			
		||||
 | 
			
		||||
    caps = gst_caps_intersect (priv->possible_formats, cfilter);
 | 
			
		||||
    gst_caps_unref (cfilter);
 | 
			
		||||
 | 
			
		||||
    if (caps == NULL)
 | 
			
		||||
      return NULL;
 | 
			
		||||
      goto no_formats;
 | 
			
		||||
 | 
			
		||||
  } else {
 | 
			
		||||
    caps = gst_caps_ref (priv->possible_formats);
 | 
			
		||||
  }
 | 
			
		||||
  g_object_get (priv->filter, "caps", &cfilter, NULL);
 | 
			
		||||
  if (cfilter != NULL) {
 | 
			
		||||
    GstCaps *t = caps;
 | 
			
		||||
 | 
			
		||||
    caps = gst_caps_intersect (t, cfilter);
 | 
			
		||||
    gst_caps_unref (cfilter);
 | 
			
		||||
    gst_caps_unref (t);
 | 
			
		||||
  }
 | 
			
		||||
  if (gst_caps_is_empty (caps)) {
 | 
			
		||||
    gst_caps_unref (caps);
 | 
			
		||||
    return NULL;
 | 
			
		||||
    goto no_formats;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  str = gst_caps_to_string (caps);
 | 
			
		||||
  gst_caps_unref (caps);
 | 
			
		||||
 | 
			
		||||
  return g_bytes_new_take (str, strlen (str) + 1);
 | 
			
		||||
 | 
			
		||||
invalid_filter:
 | 
			
		||||
  {
 | 
			
		||||
    if (error)
 | 
			
		||||
      *error = g_error_new (G_IO_ERROR,
 | 
			
		||||
                            G_IO_ERROR_INVALID_ARGUMENT,
 | 
			
		||||
                            "Invalid filter received");
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
no_formats:
 | 
			
		||||
  {
 | 
			
		||||
    if (error)
 | 
			
		||||
      *error = g_error_new (G_IO_ERROR,
 | 
			
		||||
                            G_IO_ERROR_NOT_FOUND,
 | 
			
		||||
                            "No compatible format found");
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
| 
						 | 
				
			
			@ -201,7 +227,8 @@ on_socket_notify (GObject    *gobject,
 | 
			
		|||
  GSocket *socket;
 | 
			
		||||
  guint num_handles;
 | 
			
		||||
  GstCaps *caps;
 | 
			
		||||
  GBytes *requested_format, *format;
 | 
			
		||||
  GBytes *requested_format, *format = NULL;
 | 
			
		||||
  gchar *str;
 | 
			
		||||
 | 
			
		||||
  g_object_get (gobject, "socket", &socket, NULL);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -220,6 +247,9 @@ on_socket_notify (GObject    *gobject,
 | 
			
		|||
  if (num_handles == 0) {
 | 
			
		||||
    pinos_source_report_idle (PINOS_SOURCE (source));
 | 
			
		||||
    g_object_set (priv->filter, "caps", NULL, NULL);
 | 
			
		||||
 | 
			
		||||
    str = gst_caps_to_string (priv->possible_formats);
 | 
			
		||||
    format = g_bytes_new_take (str, strlen (str) + 1);
 | 
			
		||||
  } else if (socket) {
 | 
			
		||||
    /* what client requested */
 | 
			
		||||
    g_object_get (gobject, "requested-format", &requested_format, NULL);
 | 
			
		||||
| 
						 | 
				
			
			@ -235,18 +265,19 @@ on_socket_notify (GObject    *gobject,
 | 
			
		|||
      g_object_set (priv->filter, "caps", caps, NULL);
 | 
			
		||||
      gst_caps_unref (caps);
 | 
			
		||||
    } else {
 | 
			
		||||
      gchar *str;
 | 
			
		||||
 | 
			
		||||
      /* we already have a client, format is whatever is configured already */
 | 
			
		||||
      g_bytes_unref (requested_format);
 | 
			
		||||
 | 
			
		||||
      g_object_get (priv->filter, "caps", &caps, NULL);
 | 
			
		||||
      str = gst_caps_to_string (caps);
 | 
			
		||||
      format = g_bytes_new (str, strlen (str) + 1);
 | 
			
		||||
      format = g_bytes_new_take (str, strlen (str) + 1);
 | 
			
		||||
      gst_caps_unref (caps);
 | 
			
		||||
    }
 | 
			
		||||
    /* this is what we use as the final format for the output */
 | 
			
		||||
    g_object_set (gobject, "format", format, NULL);
 | 
			
		||||
  }
 | 
			
		||||
  if (format) {
 | 
			
		||||
    pinos_source_update_possible_formats (PINOS_SOURCE (source), format);
 | 
			
		||||
    g_bytes_unref (format);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -260,31 +291,10 @@ create_source_output (PinosSource     *source,
 | 
			
		|||
                      GError          **error)
 | 
			
		||||
{
 | 
			
		||||
  PinosSourceOutput *output;
 | 
			
		||||
  PinosGstSourcePrivate *priv = PINOS_GST_SOURCE (source)->priv;
 | 
			
		||||
  GstCaps *caps;
 | 
			
		||||
  gchar *str;
 | 
			
		||||
 | 
			
		||||
  if (format_filter) {
 | 
			
		||||
    GstCaps *cfilter;
 | 
			
		||||
 | 
			
		||||
    str = (gchar *) g_bytes_get_data (format_filter, NULL);
 | 
			
		||||
    cfilter = gst_caps_from_string (str);
 | 
			
		||||
    if (cfilter == NULL)
 | 
			
		||||
      goto invalid_caps;
 | 
			
		||||
 | 
			
		||||
    caps = gst_caps_intersect (priv->possible_formats, cfilter);
 | 
			
		||||
    gst_caps_unref (cfilter);
 | 
			
		||||
 | 
			
		||||
    if (caps == NULL || gst_caps_is_empty (caps))
 | 
			
		||||
      goto no_format;
 | 
			
		||||
  } else {
 | 
			
		||||
    caps = gst_caps_ref (priv->possible_formats);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  str = gst_caps_to_string (caps);
 | 
			
		||||
  gst_caps_unref (caps);
 | 
			
		||||
 | 
			
		||||
  format_filter = g_bytes_new_take (str, strlen (str) + 1);
 | 
			
		||||
  format_filter = get_formats (source, format_filter, error);
 | 
			
		||||
  if (format_filter == NULL)
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  output = PINOS_SOURCE_CLASS (pinos_gst_source_parent_class)
 | 
			
		||||
                ->create_source_output (source,
 | 
			
		||||
| 
						 | 
				
			
			@ -295,32 +305,12 @@ create_source_output (PinosSource     *source,
 | 
			
		|||
                                        error);
 | 
			
		||||
  g_bytes_unref (format_filter);
 | 
			
		||||
 | 
			
		||||
  if (error == NULL)
 | 
			
		||||
  if (output == NULL)
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  g_signal_connect (output, "notify::socket", (GCallback) on_socket_notify, source);
 | 
			
		||||
 | 
			
		||||
  return output;
 | 
			
		||||
 | 
			
		||||
  /* ERRORS */
 | 
			
		||||
invalid_caps:
 | 
			
		||||
  {
 | 
			
		||||
    if (error)
 | 
			
		||||
      *error = g_error_new (G_IO_ERROR,
 | 
			
		||||
                            G_IO_ERROR_INVALID_DATA,
 | 
			
		||||
                            "Input filter data invalid");
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
no_format:
 | 
			
		||||
  {
 | 
			
		||||
    if (caps)
 | 
			
		||||
      gst_caps_unref (caps);
 | 
			
		||||
    if (error)
 | 
			
		||||
      *error = g_error_new (G_IO_ERROR,
 | 
			
		||||
                            G_IO_ERROR_NOT_FOUND,
 | 
			
		||||
                            "No format available that matches input filter");
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -199,7 +199,8 @@ client_set_state (PinosSource      *source,
 | 
			
		|||
 | 
			
		||||
static GBytes *
 | 
			
		||||
client_get_formats (PinosSource *source,
 | 
			
		||||
                    GBytes      *filter)
 | 
			
		||||
                    GBytes      *filter,
 | 
			
		||||
                    GError     **error)
 | 
			
		||||
{
 | 
			
		||||
  GstCaps *caps, *cfilter;
 | 
			
		||||
  gchar *str;
 | 
			
		||||
| 
						 | 
				
			
			@ -207,18 +208,35 @@ client_get_formats (PinosSource *source,
 | 
			
		|||
  if (filter) {
 | 
			
		||||
    cfilter = gst_caps_from_string (g_bytes_get_data (filter, NULL));
 | 
			
		||||
    if (cfilter == NULL)
 | 
			
		||||
      return NULL;
 | 
			
		||||
      goto invalid_filter;
 | 
			
		||||
  } else {
 | 
			
		||||
    cfilter = NULL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  caps = collect_caps (source, cfilter);
 | 
			
		||||
  if (caps == NULL)
 | 
			
		||||
    return NULL;
 | 
			
		||||
    goto no_format;
 | 
			
		||||
 | 
			
		||||
  str = gst_caps_to_string (caps);
 | 
			
		||||
 | 
			
		||||
  return g_bytes_new_take (str, strlen (str) + 1);
 | 
			
		||||
 | 
			
		||||
invalid_filter:
 | 
			
		||||
  {
 | 
			
		||||
    if (error)
 | 
			
		||||
      *error = g_error_new (G_IO_ERROR,
 | 
			
		||||
                            G_IO_ERROR_INVALID_ARGUMENT,
 | 
			
		||||
                            "Invalid filter received");
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
no_format:
 | 
			
		||||
  {
 | 
			
		||||
    if (error)
 | 
			
		||||
      *error = g_error_new (G_IO_ERROR,
 | 
			
		||||
                            G_IO_ERROR_NOT_FOUND,
 | 
			
		||||
                            "No compatible format found");
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -123,6 +123,11 @@ pinos_source_set_property (GObject      *_object,
 | 
			
		|||
      if (priv->properties)
 | 
			
		||||
        pinos_properties_free (priv->properties);
 | 
			
		||||
      priv->properties = g_value_dup_boxed (value);
 | 
			
		||||
      if (priv->iface)
 | 
			
		||||
        g_object_set (priv->iface,
 | 
			
		||||
            "properties", priv->properties ?
 | 
			
		||||
                      pinos_properties_to_variant (priv->properties) : NULL,
 | 
			
		||||
            NULL);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
| 
						 | 
				
			
			@ -140,7 +145,7 @@ source_register_object (PinosSource *source)
 | 
			
		|||
  GBytes *formats;
 | 
			
		||||
  GVariant *variant;
 | 
			
		||||
 | 
			
		||||
  formats = pinos_source_get_formats (source, NULL);
 | 
			
		||||
  formats = pinos_source_get_formats (source, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  skel = pinos_object_skeleton_new (PINOS_DBUS_OBJECT_SOURCE);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -245,14 +250,23 @@ default_create_source_output (PinosSource     *source,
 | 
			
		|||
{
 | 
			
		||||
  PinosSourcePrivate *priv = source->priv;
 | 
			
		||||
  PinosSourceOutput *output;
 | 
			
		||||
  GBytes *possible_formats;
 | 
			
		||||
 | 
			
		||||
  possible_formats = pinos_source_get_formats (source, format_filter, error);
 | 
			
		||||
  if (possible_formats == NULL)
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  output = g_object_new (PINOS_TYPE_SOURCE_OUTPUT, "daemon", priv->daemon,
 | 
			
		||||
                                                   "object-path", prefix,
 | 
			
		||||
                                                   "client-path", client_path,
 | 
			
		||||
                                                   "source-path", priv->object_path,
 | 
			
		||||
                                                   "possible-formats", format_filter,
 | 
			
		||||
                                                   "possible-formats", possible_formats,
 | 
			
		||||
                                                   "properties", props,
 | 
			
		||||
                                                   NULL);
 | 
			
		||||
  g_bytes_unref (possible_formats);
 | 
			
		||||
 | 
			
		||||
  if (output == NULL)
 | 
			
		||||
    goto no_output;
 | 
			
		||||
 | 
			
		||||
  g_signal_connect (output,
 | 
			
		||||
                    "remove",
 | 
			
		||||
| 
						 | 
				
			
			@ -262,6 +276,16 @@ default_create_source_output (PinosSource     *source,
 | 
			
		|||
  priv->outputs = g_list_prepend (priv->outputs, output);
 | 
			
		||||
 | 
			
		||||
  return g_object_ref (output);
 | 
			
		||||
 | 
			
		||||
  /* ERRORS */
 | 
			
		||||
no_output:
 | 
			
		||||
  {
 | 
			
		||||
    if (error)
 | 
			
		||||
      *error = g_error_new (G_IO_ERROR,
 | 
			
		||||
                            G_IO_ERROR_FAILED,
 | 
			
		||||
                            "Could not create a source output");
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
| 
						 | 
				
			
			@ -359,8 +383,9 @@ pinos_source_init (PinosSource * source)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
GBytes *
 | 
			
		||||
pinos_source_get_formats (PinosSource *source,
 | 
			
		||||
                          GBytes      *filter)
 | 
			
		||||
pinos_source_get_formats (PinosSource  *source,
 | 
			
		||||
                          GBytes       *filter,
 | 
			
		||||
                          GError      **error)
 | 
			
		||||
{
 | 
			
		||||
  PinosSourceClass *klass;
 | 
			
		||||
  GBytes *res;
 | 
			
		||||
| 
						 | 
				
			
			@ -370,10 +395,14 @@ pinos_source_get_formats (PinosSource *source,
 | 
			
		|||
  klass = PINOS_SOURCE_GET_CLASS (source);
 | 
			
		||||
 | 
			
		||||
  if (klass->get_formats)
 | 
			
		||||
    res = klass->get_formats (source, filter);
 | 
			
		||||
  else
 | 
			
		||||
    res = klass->get_formats (source, filter, error);
 | 
			
		||||
  else {
 | 
			
		||||
    res = NULL;
 | 
			
		||||
 | 
			
		||||
    if (error)
 | 
			
		||||
      *error = g_error_new (G_IO_ERROR,
 | 
			
		||||
                            G_IO_ERROR_NOT_SUPPORTED,
 | 
			
		||||
                            "Format query is not supported");
 | 
			
		||||
  }
 | 
			
		||||
  return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -64,7 +64,9 @@ struct _PinosSource {
 | 
			
		|||
struct _PinosSourceClass {
 | 
			
		||||
  GObjectClass parent_class;
 | 
			
		||||
 | 
			
		||||
  GBytes *            (*get_formats) (PinosSource *source, GBytes *filter);
 | 
			
		||||
  GBytes *            (*get_formats)  (PinosSource  *source,
 | 
			
		||||
                                       GBytes       *filter,
 | 
			
		||||
                                       GError      **error);
 | 
			
		||||
 | 
			
		||||
  gboolean            (*set_state)  (PinosSource *source, PinosSourceState);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -83,7 +85,9 @@ GType               pinos_source_get_type                (void);
 | 
			
		|||
 | 
			
		||||
const gchar *       pinos_source_get_object_path         (PinosSource *source);
 | 
			
		||||
 | 
			
		||||
GBytes *            pinos_source_get_formats             (PinosSource *source, GBytes *filter);
 | 
			
		||||
GBytes *            pinos_source_get_formats             (PinosSource *source,
 | 
			
		||||
                                                          GBytes      *filter,
 | 
			
		||||
                                                          GError     **error);
 | 
			
		||||
 | 
			
		||||
gboolean            pinos_source_set_state               (PinosSource *source, PinosSourceState state);
 | 
			
		||||
void                pinos_source_update_state            (PinosSource *source, PinosSourceState state);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue