mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -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 *
|
static GBytes *
|
||||||
get_formats (PinosSource *source,
|
get_formats (PinosSource *source,
|
||||||
GBytes *filter)
|
GBytes *filter,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
PinosGstSourcePrivate *priv = PINOS_GST_SOURCE (source)->priv;
|
PinosGstSourcePrivate *priv = PINOS_GST_SOURCE (source)->priv;
|
||||||
GstCaps *caps;
|
GstCaps *caps, *cfilter;
|
||||||
gchar *str;
|
gchar *str;
|
||||||
|
|
||||||
if (filter) {
|
if (filter) {
|
||||||
GstCaps *cfilter;
|
|
||||||
|
|
||||||
cfilter = gst_caps_from_string (g_bytes_get_data (filter, NULL));
|
cfilter = gst_caps_from_string (g_bytes_get_data (filter, NULL));
|
||||||
if (cfilter == NULL)
|
if (cfilter == NULL)
|
||||||
return NULL;
|
goto invalid_filter;
|
||||||
|
|
||||||
caps = gst_caps_intersect (priv->possible_formats, cfilter);
|
caps = gst_caps_intersect (priv->possible_formats, cfilter);
|
||||||
gst_caps_unref (cfilter);
|
gst_caps_unref (cfilter);
|
||||||
|
|
||||||
if (caps == NULL)
|
if (caps == NULL)
|
||||||
return NULL;
|
goto no_formats;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
caps = gst_caps_ref (priv->possible_formats);
|
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)) {
|
if (gst_caps_is_empty (caps)) {
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
return NULL;
|
goto no_formats;
|
||||||
}
|
}
|
||||||
|
|
||||||
str = gst_caps_to_string (caps);
|
str = gst_caps_to_string (caps);
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
|
|
||||||
return g_bytes_new_take (str, strlen (str) + 1);
|
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
|
static void
|
||||||
|
|
@ -201,7 +227,8 @@ on_socket_notify (GObject *gobject,
|
||||||
GSocket *socket;
|
GSocket *socket;
|
||||||
guint num_handles;
|
guint num_handles;
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
GBytes *requested_format, *format;
|
GBytes *requested_format, *format = NULL;
|
||||||
|
gchar *str;
|
||||||
|
|
||||||
g_object_get (gobject, "socket", &socket, NULL);
|
g_object_get (gobject, "socket", &socket, NULL);
|
||||||
|
|
||||||
|
|
@ -220,6 +247,9 @@ on_socket_notify (GObject *gobject,
|
||||||
if (num_handles == 0) {
|
if (num_handles == 0) {
|
||||||
pinos_source_report_idle (PINOS_SOURCE (source));
|
pinos_source_report_idle (PINOS_SOURCE (source));
|
||||||
g_object_set (priv->filter, "caps", NULL, NULL);
|
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) {
|
} else if (socket) {
|
||||||
/* what client requested */
|
/* what client requested */
|
||||||
g_object_get (gobject, "requested-format", &requested_format, NULL);
|
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);
|
g_object_set (priv->filter, "caps", caps, NULL);
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
} else {
|
} else {
|
||||||
gchar *str;
|
|
||||||
|
|
||||||
/* we already have a client, format is whatever is configured already */
|
/* we already have a client, format is whatever is configured already */
|
||||||
g_bytes_unref (requested_format);
|
g_bytes_unref (requested_format);
|
||||||
|
|
||||||
g_object_get (priv->filter, "caps", &caps, NULL);
|
g_object_get (priv->filter, "caps", &caps, NULL);
|
||||||
str = gst_caps_to_string (caps);
|
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);
|
gst_caps_unref (caps);
|
||||||
}
|
}
|
||||||
/* this is what we use as the final format for the output */
|
/* this is what we use as the final format for the output */
|
||||||
g_object_set (gobject, "format", format, NULL);
|
g_object_set (gobject, "format", format, NULL);
|
||||||
|
}
|
||||||
|
if (format) {
|
||||||
|
pinos_source_update_possible_formats (PINOS_SOURCE (source), format);
|
||||||
g_bytes_unref (format);
|
g_bytes_unref (format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -260,31 +291,10 @@ create_source_output (PinosSource *source,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
PinosSourceOutput *output;
|
PinosSourceOutput *output;
|
||||||
PinosGstSourcePrivate *priv = PINOS_GST_SOURCE (source)->priv;
|
|
||||||
GstCaps *caps;
|
|
||||||
gchar *str;
|
|
||||||
|
|
||||||
if (format_filter) {
|
format_filter = get_formats (source, format_filter, error);
|
||||||
GstCaps *cfilter;
|
if (format_filter == NULL)
|
||||||
|
return NULL;
|
||||||
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);
|
|
||||||
|
|
||||||
output = PINOS_SOURCE_CLASS (pinos_gst_source_parent_class)
|
output = PINOS_SOURCE_CLASS (pinos_gst_source_parent_class)
|
||||||
->create_source_output (source,
|
->create_source_output (source,
|
||||||
|
|
@ -295,32 +305,12 @@ create_source_output (PinosSource *source,
|
||||||
error);
|
error);
|
||||||
g_bytes_unref (format_filter);
|
g_bytes_unref (format_filter);
|
||||||
|
|
||||||
if (error == NULL)
|
if (output == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
g_signal_connect (output, "notify::socket", (GCallback) on_socket_notify, source);
|
g_signal_connect (output, "notify::socket", (GCallback) on_socket_notify, source);
|
||||||
|
|
||||||
return output;
|
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
|
static gboolean
|
||||||
|
|
|
||||||
|
|
@ -199,7 +199,8 @@ client_set_state (PinosSource *source,
|
||||||
|
|
||||||
static GBytes *
|
static GBytes *
|
||||||
client_get_formats (PinosSource *source,
|
client_get_formats (PinosSource *source,
|
||||||
GBytes *filter)
|
GBytes *filter,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
GstCaps *caps, *cfilter;
|
GstCaps *caps, *cfilter;
|
||||||
gchar *str;
|
gchar *str;
|
||||||
|
|
@ -207,18 +208,35 @@ client_get_formats (PinosSource *source,
|
||||||
if (filter) {
|
if (filter) {
|
||||||
cfilter = gst_caps_from_string (g_bytes_get_data (filter, NULL));
|
cfilter = gst_caps_from_string (g_bytes_get_data (filter, NULL));
|
||||||
if (cfilter == NULL)
|
if (cfilter == NULL)
|
||||||
return NULL;
|
goto invalid_filter;
|
||||||
} else {
|
} else {
|
||||||
cfilter = NULL;
|
cfilter = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
caps = collect_caps (source, cfilter);
|
caps = collect_caps (source, cfilter);
|
||||||
if (caps == NULL)
|
if (caps == NULL)
|
||||||
return NULL;
|
goto no_format;
|
||||||
|
|
||||||
str = gst_caps_to_string (caps);
|
str = gst_caps_to_string (caps);
|
||||||
|
|
||||||
return g_bytes_new_take (str, strlen (str) + 1);
|
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
|
static void
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,11 @@ pinos_source_set_property (GObject *_object,
|
||||||
if (priv->properties)
|
if (priv->properties)
|
||||||
pinos_properties_free (priv->properties);
|
pinos_properties_free (priv->properties);
|
||||||
priv->properties = g_value_dup_boxed (value);
|
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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -140,7 +145,7 @@ source_register_object (PinosSource *source)
|
||||||
GBytes *formats;
|
GBytes *formats;
|
||||||
GVariant *variant;
|
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);
|
skel = pinos_object_skeleton_new (PINOS_DBUS_OBJECT_SOURCE);
|
||||||
|
|
||||||
|
|
@ -245,14 +250,23 @@ default_create_source_output (PinosSource *source,
|
||||||
{
|
{
|
||||||
PinosSourcePrivate *priv = source->priv;
|
PinosSourcePrivate *priv = source->priv;
|
||||||
PinosSourceOutput *output;
|
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,
|
output = g_object_new (PINOS_TYPE_SOURCE_OUTPUT, "daemon", priv->daemon,
|
||||||
"object-path", prefix,
|
"object-path", prefix,
|
||||||
"client-path", client_path,
|
"client-path", client_path,
|
||||||
"source-path", priv->object_path,
|
"source-path", priv->object_path,
|
||||||
"possible-formats", format_filter,
|
"possible-formats", possible_formats,
|
||||||
"properties", props,
|
"properties", props,
|
||||||
NULL);
|
NULL);
|
||||||
|
g_bytes_unref (possible_formats);
|
||||||
|
|
||||||
|
if (output == NULL)
|
||||||
|
goto no_output;
|
||||||
|
|
||||||
g_signal_connect (output,
|
g_signal_connect (output,
|
||||||
"remove",
|
"remove",
|
||||||
|
|
@ -262,6 +276,16 @@ default_create_source_output (PinosSource *source,
|
||||||
priv->outputs = g_list_prepend (priv->outputs, output);
|
priv->outputs = g_list_prepend (priv->outputs, output);
|
||||||
|
|
||||||
return g_object_ref (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
|
static gboolean
|
||||||
|
|
@ -359,8 +383,9 @@ pinos_source_init (PinosSource * source)
|
||||||
}
|
}
|
||||||
|
|
||||||
GBytes *
|
GBytes *
|
||||||
pinos_source_get_formats (PinosSource *source,
|
pinos_source_get_formats (PinosSource *source,
|
||||||
GBytes *filter)
|
GBytes *filter,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
PinosSourceClass *klass;
|
PinosSourceClass *klass;
|
||||||
GBytes *res;
|
GBytes *res;
|
||||||
|
|
@ -370,10 +395,14 @@ pinos_source_get_formats (PinosSource *source,
|
||||||
klass = PINOS_SOURCE_GET_CLASS (source);
|
klass = PINOS_SOURCE_GET_CLASS (source);
|
||||||
|
|
||||||
if (klass->get_formats)
|
if (klass->get_formats)
|
||||||
res = klass->get_formats (source, filter);
|
res = klass->get_formats (source, filter, error);
|
||||||
else
|
else {
|
||||||
res = NULL;
|
res = NULL;
|
||||||
|
if (error)
|
||||||
|
*error = g_error_new (G_IO_ERROR,
|
||||||
|
G_IO_ERROR_NOT_SUPPORTED,
|
||||||
|
"Format query is not supported");
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,9 @@ struct _PinosSource {
|
||||||
struct _PinosSourceClass {
|
struct _PinosSourceClass {
|
||||||
GObjectClass parent_class;
|
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);
|
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);
|
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);
|
gboolean pinos_source_set_state (PinosSource *source, PinosSourceState state);
|
||||||
void pinos_source_update_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