mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-01 22:58:50 -04:00
Improve error reporting
Pass GError around for things that can fail and report the errors back to the client. Improve shutdown of pipeline when no clients are consuming. Make GStreamer elements handle all kinds of data and not just video because we can.
This commit is contained in:
parent
4bc308835a
commit
cbe7b52a70
13 changed files with 145 additions and 61 deletions
|
|
@ -61,7 +61,7 @@ static GstStaticPadTemplate gst_pulsevideo_sink_template =
|
||||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
GST_PAD_SINK,
|
GST_PAD_SINK,
|
||||||
GST_PAD_ALWAYS,
|
GST_PAD_ALWAYS,
|
||||||
GST_STATIC_CAPS (PVS_VIDEO_CAPS)
|
GST_STATIC_CAPS_ANY
|
||||||
);
|
);
|
||||||
|
|
||||||
#define gst_pulsevideo_sink_parent_class parent_class
|
#define gst_pulsevideo_sink_parent_class parent_class
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,6 @@
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/base/gstbasesink.h>
|
#include <gst/base/gstbasesink.h>
|
||||||
|
|
||||||
#include <gst/video/video.h>
|
|
||||||
|
|
||||||
#include <client/pv-context.h>
|
#include <client/pv-context.h>
|
||||||
#include <client/pv-stream.h>
|
#include <client/pv-stream.h>
|
||||||
#include <client/pv-introspect.h>
|
#include <client/pv-introspect.h>
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ static GstStaticPadTemplate gst_pulsevideo_src_template =
|
||||||
GST_STATIC_PAD_TEMPLATE ("src",
|
GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
GST_PAD_SRC,
|
GST_PAD_SRC,
|
||||||
GST_PAD_ALWAYS,
|
GST_PAD_ALWAYS,
|
||||||
GST_STATIC_CAPS (PVS_VIDEO_CAPS)
|
GST_STATIC_CAPS_ANY
|
||||||
);
|
);
|
||||||
|
|
||||||
#define gst_pulsevideo_src_parent_class parent_class
|
#define gst_pulsevideo_src_parent_class parent_class
|
||||||
|
|
@ -238,7 +238,7 @@ gst_pulsevideo_src_negotiate (GstBaseSrc * basesrc)
|
||||||
thiscaps = gst_pad_query_caps (GST_BASE_SRC_PAD (basesrc), NULL);
|
thiscaps = gst_pad_query_caps (GST_BASE_SRC_PAD (basesrc), NULL);
|
||||||
GST_DEBUG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
|
GST_DEBUG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
|
||||||
/* nothing or anything is allowed, we're done */
|
/* nothing or anything is allowed, we're done */
|
||||||
if (thiscaps == NULL || gst_caps_is_any (thiscaps))
|
if (thiscaps == NULL)
|
||||||
goto no_nego_needed;
|
goto no_nego_needed;
|
||||||
|
|
||||||
if (G_UNLIKELY (gst_caps_is_empty (thiscaps)))
|
if (G_UNLIKELY (gst_caps_is_empty (thiscaps)))
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,6 @@
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/base/gstpushsrc.h>
|
#include <gst/base/gstpushsrc.h>
|
||||||
|
|
||||||
#include <gst/video/video.h>
|
|
||||||
|
|
||||||
#include <client/pv-context.h>
|
#include <client/pv-context.h>
|
||||||
#include <client/pv-stream.h>
|
#include <client/pv-stream.h>
|
||||||
#include <client/pv-introspect.h>
|
#include <client/pv-introspect.h>
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,6 @@ struct _PvV4l2SourcePrivate
|
||||||
GstElement *sink;
|
GstElement *sink;
|
||||||
|
|
||||||
GstCaps *possible_formats;
|
GstCaps *possible_formats;
|
||||||
|
|
||||||
GSocket *socket;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (PvV4l2Source, pv_v4l2_source, PV_TYPE_SOURCE);
|
G_DEFINE_TYPE (PvV4l2Source, pv_v4l2_source, PV_TYPE_SOURCE);
|
||||||
|
|
@ -91,6 +89,8 @@ setup_pipeline (PvV4l2Source *source)
|
||||||
bus = gst_pipeline_get_bus (GST_PIPELINE (priv->pipeline));
|
bus = gst_pipeline_get_bus (GST_PIPELINE (priv->pipeline));
|
||||||
gst_bus_add_watch (bus, bus_handler, source);
|
gst_bus_add_watch (bus, bus_handler, source);
|
||||||
gst_object_unref (bus);
|
gst_object_unref (bus);
|
||||||
|
|
||||||
|
gst_element_set_state (priv->pipeline, GST_STATE_READY);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstCaps *
|
static GstCaps *
|
||||||
|
|
@ -101,7 +101,7 @@ collect_caps (PvSource * source, GstCaps *filter)
|
||||||
GstQuery *query;
|
GstQuery *query;
|
||||||
|
|
||||||
query = gst_query_new_caps (filter);
|
query = gst_query_new_caps (filter);
|
||||||
gst_element_query (priv->src, query);
|
gst_element_query (priv->filter, query);
|
||||||
gst_query_parse_caps_result (query, &res);
|
gst_query_parse_caps_result (query, &res);
|
||||||
gst_caps_ref (res);
|
gst_caps_ref (res);
|
||||||
gst_query_unref (query);
|
gst_query_unref (query);
|
||||||
|
|
@ -154,36 +154,57 @@ on_socket_notify (GObject *gobject,
|
||||||
GSocket *socket;
|
GSocket *socket;
|
||||||
guint num_handles;
|
guint num_handles;
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
GBytes *requested_format;
|
GBytes *requested_format, *format;
|
||||||
|
|
||||||
g_object_get (gobject, "socket", &socket, NULL);
|
g_object_get (gobject, "socket", &socket, NULL);
|
||||||
|
|
||||||
g_print ("source socket %p\n", socket);
|
g_print ("source socket %p\n", socket);
|
||||||
|
|
||||||
if (socket == NULL) {
|
if (socket == NULL) {
|
||||||
if (priv->socket)
|
GSocket *prev_socket = g_object_get_data (gobject, "last-socket");
|
||||||
g_signal_emit_by_name (priv->sink, "remove", priv->socket);
|
if (prev_socket) {
|
||||||
|
g_signal_emit_by_name (priv->sink, "remove", prev_socket);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
g_signal_emit_by_name (priv->sink, "add", socket);
|
g_signal_emit_by_name (priv->sink, "add", socket);
|
||||||
}
|
}
|
||||||
priv->socket = socket;
|
g_object_set_data (gobject, "last-socket", socket);
|
||||||
|
|
||||||
g_object_get (gobject, "requested-format", &requested_format, NULL);
|
|
||||||
g_assert (requested_format != NULL);
|
|
||||||
g_object_set (gobject, "format", requested_format, NULL);
|
|
||||||
|
|
||||||
g_print ("final format %s\n", g_bytes_get_data (requested_format, NULL));
|
|
||||||
|
|
||||||
caps = gst_caps_from_string (g_bytes_get_data (requested_format, NULL));
|
|
||||||
g_assert (caps != NULL);
|
|
||||||
g_object_set (priv->filter, "caps", caps, NULL);
|
|
||||||
gst_caps_unref (caps);
|
|
||||||
g_bytes_unref (requested_format);
|
|
||||||
|
|
||||||
g_object_get (priv->sink, "num-handles", &num_handles, NULL);
|
g_object_get (priv->sink, "num-handles", &num_handles, NULL);
|
||||||
|
g_print ("num handles %d\n", num_handles);
|
||||||
if (num_handles == 0) {
|
if (num_handles == 0) {
|
||||||
gst_element_set_state (priv->pipeline, GST_STATE_READY);
|
gst_element_set_state (priv->pipeline, GST_STATE_READY);
|
||||||
} else {
|
g_object_set (priv->filter, "caps", NULL, NULL);
|
||||||
|
} else if (socket) {
|
||||||
|
/* what client requested */
|
||||||
|
g_object_get (gobject, "requested-format", &requested_format, NULL);
|
||||||
|
g_assert (requested_format != NULL);
|
||||||
|
|
||||||
|
if (num_handles == 1) {
|
||||||
|
/* first client, we set the requested format as the format */
|
||||||
|
format = requested_format;
|
||||||
|
|
||||||
|
/* set on the filter */
|
||||||
|
caps = gst_caps_from_string (g_bytes_get_data (format, NULL));
|
||||||
|
g_assert (caps != NULL);
|
||||||
|
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);
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
}
|
||||||
|
/* this is what we use as the final format for the output */
|
||||||
|
g_print ("final format %s\n", (gchar *) g_bytes_get_data (format, NULL));
|
||||||
|
g_object_set (gobject, "format", format, NULL);
|
||||||
|
g_bytes_unref (format);
|
||||||
|
|
||||||
gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
|
gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -192,9 +213,9 @@ static PvSourceOutput *
|
||||||
v4l2_create_source_output (PvSource *source,
|
v4l2_create_source_output (PvSource *source,
|
||||||
const gchar *client_path,
|
const gchar *client_path,
|
||||||
GBytes *format_filter,
|
GBytes *format_filter,
|
||||||
const gchar *prefix)
|
const gchar *prefix,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
PvV4l2SourcePrivate *priv = PV_V4L2_SOURCE (source)->priv;
|
|
||||||
PvSourceOutput *output;
|
PvSourceOutput *output;
|
||||||
GstCaps *caps, *filtered;
|
GstCaps *caps, *filtered;
|
||||||
gchar *str;
|
gchar *str;
|
||||||
|
|
@ -205,8 +226,6 @@ v4l2_create_source_output (PvSource *source,
|
||||||
if (caps == NULL)
|
if (caps == NULL)
|
||||||
goto invalid_caps;
|
goto invalid_caps;
|
||||||
|
|
||||||
gst_element_set_state (priv->pipeline, GST_STATE_READY);
|
|
||||||
|
|
||||||
filtered = collect_caps (source, caps);
|
filtered = collect_caps (source, caps);
|
||||||
if (filtered == NULL || gst_caps_is_empty (filtered))
|
if (filtered == NULL || gst_caps_is_empty (filtered))
|
||||||
goto no_format;
|
goto no_format;
|
||||||
|
|
@ -215,7 +234,14 @@ v4l2_create_source_output (PvSource *source,
|
||||||
g_print ("output filter %s\n", str);
|
g_print ("output filter %s\n", str);
|
||||||
format_filter = g_bytes_new_take (str, strlen (str) + 1);
|
format_filter = g_bytes_new_take (str, strlen (str) + 1);
|
||||||
|
|
||||||
output = PV_SOURCE_CLASS (pv_v4l2_source_parent_class)->create_source_output (source, client_path, format_filter, prefix);
|
output = PV_SOURCE_CLASS (pv_v4l2_source_parent_class)
|
||||||
|
->create_source_output (source,
|
||||||
|
client_path,
|
||||||
|
format_filter,
|
||||||
|
prefix,
|
||||||
|
error);
|
||||||
|
if (error == 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);
|
||||||
|
|
||||||
|
|
@ -224,10 +250,18 @@ v4l2_create_source_output (PvSource *source,
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
invalid_caps:
|
invalid_caps:
|
||||||
{
|
{
|
||||||
|
if (error)
|
||||||
|
*error = g_error_new (G_IO_ERROR,
|
||||||
|
G_IO_ERROR_INVALID_DATA,
|
||||||
|
"Input filter data invalid");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
no_format:
|
no_format:
|
||||||
{
|
{
|
||||||
|
if (error)
|
||||||
|
*error = g_error_new (G_IO_ERROR,
|
||||||
|
G_IO_ERROR_NOT_FOUND,
|
||||||
|
"No format available that matches input filter");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -184,7 +184,8 @@ static PvSourceOutput *
|
||||||
client_create_source_output (PvSource *source,
|
client_create_source_output (PvSource *source,
|
||||||
const gchar *client_path,
|
const gchar *client_path,
|
||||||
GBytes *format_filter,
|
GBytes *format_filter,
|
||||||
const gchar *prefix)
|
const gchar *prefix,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
PvClientSourcePrivate *priv = PV_CLIENT_SOURCE (source)->priv;
|
PvClientSourcePrivate *priv = PV_CLIENT_SOURCE (source)->priv;
|
||||||
PvSourceOutput *output;
|
PvSourceOutput *output;
|
||||||
|
|
@ -192,7 +193,15 @@ client_create_source_output (PvSource *source,
|
||||||
/* propose format of input */
|
/* propose format of input */
|
||||||
g_object_get (priv->input, "format", &format_filter, NULL);
|
g_object_get (priv->input, "format", &format_filter, NULL);
|
||||||
|
|
||||||
output = PV_SOURCE_CLASS (pv_client_source_parent_class)->create_source_output (source, client_path, format_filter, prefix);
|
output = PV_SOURCE_CLASS (pv_client_source_parent_class)
|
||||||
|
->create_source_output (source,
|
||||||
|
client_path,
|
||||||
|
format_filter,
|
||||||
|
prefix,
|
||||||
|
error);
|
||||||
|
|
||||||
|
if (output == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
gst_element_set_state (priv->pipeline, GST_STATE_READY);
|
gst_element_set_state (priv->pipeline, GST_STATE_READY);
|
||||||
|
|
||||||
|
|
@ -246,7 +255,8 @@ PvSourceOutput *
|
||||||
pv_client_source_get_source_input (PvClientSource *source,
|
pv_client_source_get_source_input (PvClientSource *source,
|
||||||
const gchar *client_path,
|
const gchar *client_path,
|
||||||
GBytes *format_filter,
|
GBytes *format_filter,
|
||||||
const gchar *prefix)
|
const gchar *prefix,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
PvClientSourcePrivate *priv;
|
PvClientSourcePrivate *priv;
|
||||||
|
|
||||||
|
|
@ -254,7 +264,15 @@ pv_client_source_get_source_input (PvClientSource *source,
|
||||||
priv = source->priv;
|
priv = source->priv;
|
||||||
|
|
||||||
if (priv->input == NULL) {
|
if (priv->input == NULL) {
|
||||||
priv->input = PV_SOURCE_CLASS (pv_client_source_parent_class)->create_source_output (PV_SOURCE (source), client_path, format_filter, prefix);
|
priv->input = PV_SOURCE_CLASS (pv_client_source_parent_class)
|
||||||
|
->create_source_output (PV_SOURCE (source),
|
||||||
|
client_path,
|
||||||
|
format_filter,
|
||||||
|
prefix,
|
||||||
|
error);
|
||||||
|
if (priv->input == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
g_signal_connect (priv->input, "notify::socket", (GCallback) on_input_socket_notify, source);
|
g_signal_connect (priv->input, "notify::socket", (GCallback) on_input_socket_notify, source);
|
||||||
}
|
}
|
||||||
return priv->input;
|
return priv->input;
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,8 @@ PvSource * pv_client_source_new (PvDaemon *daemon);
|
||||||
PvSourceOutput * pv_client_source_get_source_input (PvClientSource *source,
|
PvSourceOutput * pv_client_source_get_source_input (PvClientSource *source,
|
||||||
const gchar *client_path,
|
const gchar *client_path,
|
||||||
GBytes *format_filter,
|
GBytes *format_filter,
|
||||||
const gchar *prefix);
|
const gchar *prefix,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -130,14 +130,23 @@ handle_create_source_output (PvClient1 *interface,
|
||||||
PvSourceOutput *output;
|
PvSourceOutput *output;
|
||||||
const gchar *object_path, *sender;
|
const gchar *object_path, *sender;
|
||||||
GBytes *formats;
|
GBytes *formats;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
formats = g_bytes_new (arg_accepted_formats, strlen (arg_accepted_formats) + 1);
|
formats = g_bytes_new (arg_accepted_formats, strlen (arg_accepted_formats) + 1);
|
||||||
|
|
||||||
source = pv_daemon_find_source (priv->daemon, arg_source, priv->properties, formats);
|
source = pv_daemon_find_source (priv->daemon,
|
||||||
|
arg_source,
|
||||||
|
priv->properties,
|
||||||
|
formats,
|
||||||
|
&error);
|
||||||
if (source == NULL)
|
if (source == NULL)
|
||||||
goto no_source;
|
goto no_source;
|
||||||
|
|
||||||
output = pv_source_create_source_output (source, priv->object_path, formats, priv->object_path);
|
output = pv_source_create_source_output (source,
|
||||||
|
priv->object_path,
|
||||||
|
formats,
|
||||||
|
priv->object_path,
|
||||||
|
&error);
|
||||||
if (output == NULL)
|
if (output == NULL)
|
||||||
goto no_output;
|
goto no_output;
|
||||||
|
|
||||||
|
|
@ -154,14 +163,16 @@ handle_create_source_output (PvClient1 *interface,
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
no_source:
|
no_source:
|
||||||
{
|
{
|
||||||
g_dbus_method_invocation_return_dbus_error (invocation,
|
g_dbus_method_invocation_return_gerror (invocation, error);
|
||||||
"org.pulsevideo.Error", "Can't create source");
|
g_clear_error (&error);
|
||||||
|
g_bytes_unref (formats);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
no_output:
|
no_output:
|
||||||
{
|
{
|
||||||
g_dbus_method_invocation_return_dbus_error (invocation,
|
g_dbus_method_invocation_return_gerror (invocation, error);
|
||||||
"org.pulsevideo.Error", "Can't create output");
|
g_clear_error (&error);
|
||||||
|
g_bytes_unref (formats);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -178,6 +189,7 @@ handle_create_source_input (PvClient1 *interface,
|
||||||
PvSourceOutput *input;
|
PvSourceOutput *input;
|
||||||
const gchar *source_input_path, *sender;
|
const gchar *source_input_path, *sender;
|
||||||
GBytes *formats;
|
GBytes *formats;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
source = pv_client_source_new (priv->daemon);
|
source = pv_client_source_new (priv->daemon);
|
||||||
if (source == NULL)
|
if (source == NULL)
|
||||||
|
|
@ -192,7 +204,8 @@ handle_create_source_input (PvClient1 *interface,
|
||||||
input = pv_client_source_get_source_input (PV_CLIENT_SOURCE (source),
|
input = pv_client_source_get_source_input (PV_CLIENT_SOURCE (source),
|
||||||
priv->object_path,
|
priv->object_path,
|
||||||
formats,
|
formats,
|
||||||
priv->object_path);
|
priv->object_path,
|
||||||
|
&error);
|
||||||
if (input == NULL)
|
if (input == NULL)
|
||||||
goto no_input;
|
goto no_input;
|
||||||
|
|
||||||
|
|
@ -214,8 +227,9 @@ no_source:
|
||||||
}
|
}
|
||||||
no_input:
|
no_input:
|
||||||
{
|
{
|
||||||
g_dbus_method_invocation_return_dbus_error (invocation,
|
g_dbus_method_invocation_return_gerror (invocation, error);
|
||||||
"org.pulsevideo.Error", "Can't create input");
|
g_clear_error (&error);
|
||||||
|
g_bytes_unref (formats);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,8 +78,6 @@ client_name_appeared_handler (GDBusConnection *connection,
|
||||||
SenderData *data = user_data;
|
SenderData *data = user_data;
|
||||||
PvDaemonPrivate *priv = data->daemon->priv;
|
PvDaemonPrivate *priv = data->daemon->priv;
|
||||||
|
|
||||||
g_print ("client name appeared def: %p\n", g_main_context_get_thread_default ());
|
|
||||||
|
|
||||||
g_hash_table_insert (priv->senders, data->sender, data);
|
g_hash_table_insert (priv->senders, data->sender, data);
|
||||||
|
|
||||||
if (!g_strcmp0 (name, g_dbus_connection_get_unique_name (connection)))
|
if (!g_strcmp0 (name, g_dbus_connection_get_unique_name (connection)))
|
||||||
|
|
@ -121,7 +119,6 @@ sender_data_new (PvDaemon *daemon, const gchar *sender)
|
||||||
data->daemon = daemon;
|
data->daemon = daemon;
|
||||||
data->sender = g_strdup (sender);
|
data->sender = g_strdup (sender);
|
||||||
|
|
||||||
g_print ("watch name def: %p\n", g_main_context_get_thread_default ());
|
|
||||||
g_print ("watch name %s %p\n", sender, data);
|
g_print ("watch name %s %p\n", sender, data);
|
||||||
|
|
||||||
data->id = g_bus_watch_name_on_connection (priv->connection,
|
data->id = g_bus_watch_name_on_connection (priv->connection,
|
||||||
|
|
@ -371,15 +368,21 @@ PvSource *
|
||||||
pv_daemon_find_source (PvDaemon *daemon,
|
pv_daemon_find_source (PvDaemon *daemon,
|
||||||
const gchar *name,
|
const gchar *name,
|
||||||
GVariant *props,
|
GVariant *props,
|
||||||
GBytes *format_filter)
|
GBytes *format_filter,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
PvDaemonPrivate *priv;
|
PvDaemonPrivate *priv;
|
||||||
|
|
||||||
g_return_val_if_fail (PV_IS_DAEMON (daemon), NULL);
|
g_return_val_if_fail (PV_IS_DAEMON (daemon), NULL);
|
||||||
priv = daemon->priv;
|
priv = daemon->priv;
|
||||||
|
|
||||||
if (priv->sources == NULL)
|
if (priv->sources == NULL) {
|
||||||
|
if (error)
|
||||||
|
*error = g_error_new (G_IO_ERROR,
|
||||||
|
G_IO_ERROR_NOT_FOUND,
|
||||||
|
"No sources registered");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return priv->sources->data;
|
return priv->sources->data;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,8 @@ void pv_daemon_remove_source (PvDaemon *daemon, PvSource *source
|
||||||
PvSource * pv_daemon_find_source (PvDaemon *daemon,
|
PvSource * pv_daemon_find_source (PvDaemon *daemon,
|
||||||
const gchar *name,
|
const gchar *name,
|
||||||
GVariant *props,
|
GVariant *props,
|
||||||
GBytes *format_filter);
|
GBytes *format_filter,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -271,14 +271,22 @@ output_unregister_object (PvSourceOutput *output)
|
||||||
pv_daemon_unexport (priv->daemon, priv->object_path);
|
pv_daemon_unexport (priv->daemon, priv->object_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pv_source_output_dispose (GObject * object)
|
||||||
|
{
|
||||||
|
PvSourceOutput *output = PV_SOURCE_OUTPUT (object);
|
||||||
|
|
||||||
|
output_unregister_object (output);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (pv_source_output_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pv_source_output_finalize (GObject * object)
|
pv_source_output_finalize (GObject * object)
|
||||||
{
|
{
|
||||||
PvSourceOutput *output = PV_SOURCE_OUTPUT (object);
|
PvSourceOutput *output = PV_SOURCE_OUTPUT (object);
|
||||||
PvSourceOutputPrivate *priv = output->priv;
|
PvSourceOutputPrivate *priv = output->priv;
|
||||||
|
|
||||||
output_unregister_object (output);
|
|
||||||
|
|
||||||
g_object_unref (priv->daemon);
|
g_object_unref (priv->daemon);
|
||||||
g_object_unref (priv->iface);
|
g_object_unref (priv->iface);
|
||||||
g_free (priv->client_path);
|
g_free (priv->client_path);
|
||||||
|
|
@ -306,6 +314,7 @@ pv_source_output_class_init (PvSourceOutputClass * klass)
|
||||||
|
|
||||||
g_type_class_add_private (klass, sizeof (PvSourceOutputPrivate));
|
g_type_class_add_private (klass, sizeof (PvSourceOutputPrivate));
|
||||||
|
|
||||||
|
gobject_class->dispose = pv_source_output_dispose;
|
||||||
gobject_class->finalize = pv_source_output_finalize;
|
gobject_class->finalize = pv_source_output_finalize;
|
||||||
gobject_class->set_property = pv_source_output_set_property;
|
gobject_class->set_property = pv_source_output_set_property;
|
||||||
gobject_class->get_property = pv_source_output_get_property;
|
gobject_class->get_property = pv_source_output_get_property;
|
||||||
|
|
|
||||||
|
|
@ -210,7 +210,6 @@ default_release_source_output (PvSource *source, PvSourceOutput *output)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pv_source_class_init (PvSourceClass * klass)
|
pv_source_class_init (PvSourceClass * klass)
|
||||||
{
|
{
|
||||||
|
|
@ -354,7 +353,8 @@ PvSourceOutput *
|
||||||
pv_source_create_source_output (PvSource *source,
|
pv_source_create_source_output (PvSource *source,
|
||||||
const gchar *client_path,
|
const gchar *client_path,
|
||||||
GBytes *format_filter,
|
GBytes *format_filter,
|
||||||
const gchar *prefix)
|
const gchar *prefix,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
PvSourceClass *klass;
|
PvSourceClass *klass;
|
||||||
PvSourceOutput *res;
|
PvSourceOutput *res;
|
||||||
|
|
@ -363,10 +363,16 @@ pv_source_create_source_output (PvSource *source,
|
||||||
|
|
||||||
klass = PV_SOURCE_GET_CLASS (source);
|
klass = PV_SOURCE_GET_CLASS (source);
|
||||||
|
|
||||||
if (klass->create_source_output)
|
if (klass->create_source_output) {
|
||||||
res = klass->create_source_output (source, client_path, format_filter, prefix);
|
res = klass->create_source_output (source, client_path, format_filter, prefix, error);
|
||||||
else
|
} else {
|
||||||
|
if (error) {
|
||||||
|
*error = g_error_new (G_IO_ERROR,
|
||||||
|
G_IO_ERROR_NOT_SUPPORTED,
|
||||||
|
"Create SourceOutput not implemented");
|
||||||
|
}
|
||||||
res = NULL;
|
res = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,8 @@ struct _PvSourceClass {
|
||||||
PvSourceOutput * (*create_source_output) (PvSource *source,
|
PvSourceOutput * (*create_source_output) (PvSource *source,
|
||||||
const gchar *client_path,
|
const gchar *client_path,
|
||||||
GBytes *format_filter,
|
GBytes *format_filter,
|
||||||
const gchar *prefix);
|
const gchar *prefix,
|
||||||
|
GError **error);
|
||||||
gboolean (*release_source_output) (PvSource *source,
|
gboolean (*release_source_output) (PvSource *source,
|
||||||
PvSourceOutput *output);
|
PvSourceOutput *output);
|
||||||
};
|
};
|
||||||
|
|
@ -90,7 +91,8 @@ void pv_source_report_error (PvSource *source, GError *err
|
||||||
PvSourceOutput * pv_source_create_source_output (PvSource *source,
|
PvSourceOutput * pv_source_create_source_output (PvSource *source,
|
||||||
const gchar *client_path,
|
const gchar *client_path,
|
||||||
GBytes *format_filter,
|
GBytes *format_filter,
|
||||||
const gchar *prefix);
|
const gchar *prefix,
|
||||||
|
GError **error);
|
||||||
gboolean pv_source_release_source_output (PvSource *source, PvSourceOutput *output);
|
gboolean pv_source_release_source_output (PvSource *source, PvSourceOutput *output);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue