diff --git a/src/modules/gst/gst-source.c b/src/modules/gst/gst-source.c index 731b9d771..8523e233b 100644 --- a/src/modules/gst/gst-source.c +++ b/src/modules/gst/gst-source.c @@ -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 diff --git a/src/server/client-source.c b/src/server/client-source.c index 9de6369fb..d6d21b255 100644 --- a/src/server/client-source.c +++ b/src/server/client-source.c @@ -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 diff --git a/src/server/source.c b/src/server/source.c index 497ff5688..7b5df7482 100644 --- a/src/server/source.c +++ b/src/server/source.c @@ -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; } diff --git a/src/server/source.h b/src/server/source.h index e9285bea5..912f66780 100644 --- a/src/server/source.h +++ b/src/server/source.h @@ -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);