Implement negotiation

Use generic byte blobs for formats. We currently use them to store
gstreamer caps but we could also use them to exchange serialized
GVariants if we want.

Make properties a variant dictionary
This commit is contained in:
Wim Taymans 2015-05-14 17:46:12 +02:00
parent ca7e4602f6
commit 4bc308835a
21 changed files with 620 additions and 582 deletions

View file

@ -20,7 +20,7 @@
#include <gst/gst.h>
#include <gio/gio.h>
#include "server/pv-daemon.h"
#include <server/pv-daemon.h>
#include "pv-client-source.h"
#define PV_CLIENT_SOURCE_GET_PRIVATE(obj) \
@ -102,7 +102,7 @@ collect_capabilities (PvSource * source)
query = gst_query_new_caps (NULL);
gst_element_query (priv->src, query);
gst_query_parse_caps_result (query, &res);
g_print ("%s\n", gst_caps_to_string (res));
g_print ("client source caps: %s\n", gst_caps_to_string (res));
gst_query_unref (query);
}
@ -136,8 +136,8 @@ client_set_state (PvSource *source, PvSourceState state)
return TRUE;
}
static GVariant *
client_get_capabilities (PvSource *source, GVariant *props)
static GBytes *
client_get_capabilities (PvSource *source, GBytes *filter)
{
return NULL;
}
@ -151,6 +151,7 @@ on_socket_notify (GObject *gobject,
PvClientSourcePrivate *priv = source->priv;
GSocket *socket;
guint num_handles;
GBytes *requested_format;
g_object_get (gobject, "socket", &socket, NULL);
@ -164,6 +165,13 @@ on_socket_notify (GObject *gobject,
}
priv->socket = socket;
/* force format on input */
g_object_get (priv->input, "format", &requested_format, NULL);
g_assert (requested_format != NULL);
g_print ("final format %s\n", (gchar *) g_bytes_get_data (requested_format, NULL));
g_object_set (gobject, "format", requested_format, NULL);
g_bytes_unref (requested_format);
g_object_get (priv->sink, "num-handles", &num_handles, NULL);
if (num_handles == 0) {
gst_element_set_state (priv->pipeline, GST_STATE_READY);
@ -173,55 +181,24 @@ on_socket_notify (GObject *gobject,
}
static PvSourceOutput *
client_create_source_output (PvSource *source, GVariant *props, const gchar *prefix)
client_create_source_output (PvSource *source,
const gchar *client_path,
GBytes *format_filter,
const gchar *prefix)
{
PvClientSourcePrivate *priv = PV_CLIENT_SOURCE (source)->priv;
PvSourceOutput *output;
GVariantDict dict;
GstCaps *caps;
const gchar *str;
gint32 i32;
g_variant_dict_init (&dict, props);
if (!g_variant_dict_lookup (&dict, "format.encoding", "&s", &str))
goto invalid_encoding;
/* propose format of input */
g_object_get (priv->input, "format", &format_filter, NULL);
caps = gst_caps_new_empty_simple (str);
if (g_variant_dict_lookup (&dict, "format.format", "&s", &str))
gst_caps_set_simple (caps, "format", G_TYPE_STRING, str, NULL);
if (g_variant_dict_lookup (&dict, "format.width", "i", &i32))
gst_caps_set_simple (caps, "width", G_TYPE_INT, (gint) i32, NULL);
if (g_variant_dict_lookup (&dict, "format.height", "i", &i32))
gst_caps_set_simple (caps, "height", G_TYPE_INT, (gint) i32, NULL);
if (g_variant_dict_lookup (&dict, "format.views", "i", &i32))
gst_caps_set_simple (caps, "views", G_TYPE_INT, (gint) i32, NULL);
if (g_variant_dict_lookup (&dict, "format.chroma-site", "&s", &str))
gst_caps_set_simple (caps, "chroma-site", G_TYPE_STRING, str, NULL);
if (g_variant_dict_lookup (&dict, "format.colorimetry", "&s", &str))
gst_caps_set_simple (caps, "colorimetry", G_TYPE_STRING, str, NULL);
if (g_variant_dict_lookup (&dict, "format.interlace-mode", "&s", &str))
gst_caps_set_simple (caps, "interlace-mode", G_TYPE_STRING, str, NULL);
g_print ("caps %s\n", gst_caps_to_string (caps));
g_object_set (priv->filter, "caps", caps, NULL);
gst_caps_unref (caps);
output = PV_SOURCE_CLASS (pv_client_source_parent_class)->create_source_output (source, props, prefix);
output = PV_SOURCE_CLASS (pv_client_source_parent_class)->create_source_output (source, client_path, format_filter, prefix);
gst_element_set_state (priv->pipeline, GST_STATE_READY);
g_signal_connect (output, "notify::socket", (GCallback) on_socket_notify, source);
return output;
/* ERRORS */
invalid_encoding:
{
g_variant_dict_clear (&dict);
return NULL;
}
}
static gboolean
@ -245,14 +222,31 @@ on_input_socket_notify (GObject *gobject,
PvClientSource *source = user_data;
PvClientSourcePrivate *priv = source->priv;
GSocket *socket;
GBytes *requested_format;
GstCaps *caps;
g_object_get (gobject, "socket", &socket, NULL);
g_print ("input socket %p\n", socket);
g_object_get (gobject, "requested-format", &requested_format, NULL);
g_assert (requested_format != NULL);
g_print ("final format %s\n", (gchar *) g_bytes_get_data (requested_format, NULL));
g_object_set (gobject, "format", 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_set (priv->src, "socket", socket, NULL);
}
PvSourceOutput *
pv_client_source_get_source_input (PvClientSource *source, GVariant *props, const gchar *prefix)
pv_client_source_get_source_input (PvClientSource *source,
const gchar *client_path,
GBytes *format_filter,
const gchar *prefix)
{
PvClientSourcePrivate *priv;
@ -260,7 +254,7 @@ pv_client_source_get_source_input (PvClientSource *source, GVariant *props, cons
priv = source->priv;
if (priv->input == NULL) {
priv->input = PV_SOURCE_CLASS (pv_client_source_parent_class)->create_source_output (PV_SOURCE (source), props, prefix);
priv->input = PV_SOURCE_CLASS (pv_client_source_parent_class)->create_source_output (PV_SOURCE (source), client_path, format_filter, prefix);
g_signal_connect (priv->input, "notify::socket", (GCallback) on_input_socket_notify, source);
}
return priv->input;

View file

@ -66,8 +66,9 @@ GType pv_client_source_get_type (void);
PvSource * pv_client_source_new (PvDaemon *daemon);
PvSourceOutput * pv_client_source_get_source_input (PvClientSource *source,
GVariant *props,
const gchar *prefix);
const gchar *client_path,
GBytes *format_filter,
const gchar *prefix);
G_END_DECLS

View file

@ -17,6 +17,7 @@
* Boston, MA 02110-1301, USA.
*/
#include <string.h>
#include "client/pulsevideo.h"
#include "client/pv-enumtypes.h"
@ -31,6 +32,7 @@ struct _PvClientPrivate
PvDaemon *daemon;
gchar *sender;
gchar *object_path;
GVariant *properties;
PvClient1 *client1;
};
@ -46,6 +48,7 @@ enum
PROP_DAEMON,
PROP_SENDER,
PROP_OBJECT_PATH,
PROP_PROPERTIES,
};
static void
@ -70,6 +73,10 @@ pv_client_get_property (GObject *_object,
g_value_set_string (value, priv->object_path);
break;
case PROP_PROPERTIES:
g_value_set_variant (value, priv->properties);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (client, prop_id, pspec);
break;
@ -98,6 +105,12 @@ pv_client_set_property (GObject *_object,
priv->object_path = g_value_dup_string (value);
break;
case PROP_PROPERTIES:
if (priv->properties)
g_variant_unref (priv->properties);
priv->properties = g_value_dup_variant (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (client, prop_id, pspec);
break;
@ -108,7 +121,7 @@ static gboolean
handle_create_source_output (PvClient1 *interface,
GDBusMethodInvocation *invocation,
const gchar *arg_source,
GVariant *arg_properties,
const gchar *arg_accepted_formats,
gpointer user_data)
{
PvClient *client = user_data;
@ -116,12 +129,15 @@ handle_create_source_output (PvClient1 *interface,
PvSource *source;
PvSourceOutput *output;
const gchar *object_path, *sender;
GBytes *formats;
source = pv_daemon_find_source (priv->daemon, arg_source, arg_properties);
formats = g_bytes_new (arg_accepted_formats, strlen (arg_accepted_formats) + 1);
source = pv_daemon_find_source (priv->daemon, arg_source, priv->properties, formats);
if (source == NULL)
goto no_source;
output = pv_source_create_source_output (source, arg_properties, priv->object_path);
output = pv_source_create_source_output (source, priv->object_path, formats, priv->object_path);
if (output == NULL)
goto no_output;
@ -153,7 +169,7 @@ no_output:
static gboolean
handle_create_source_input (PvClient1 *interface,
GDBusMethodInvocation *invocation,
GVariant *arg_properties,
const gchar *arg_possible_formats,
gpointer user_data)
{
PvClient *client = user_data;
@ -161,6 +177,7 @@ handle_create_source_input (PvClient1 *interface,
PvSource *source;
PvSourceOutput *input;
const gchar *source_input_path, *sender;
GBytes *formats;
source = pv_client_source_new (priv->daemon);
if (source == NULL)
@ -170,7 +187,12 @@ handle_create_source_input (PvClient1 *interface,
pv_daemon_track_object (priv->daemon, sender, G_OBJECT (source));
input = pv_client_source_get_source_input (PV_CLIENT_SOURCE (source), arg_properties, priv->object_path);
formats = g_bytes_new (arg_possible_formats, strlen (arg_possible_formats) + 1);
input = pv_client_source_get_source_input (PV_CLIENT_SOURCE (source),
priv->object_path,
formats,
priv->object_path);
if (input == NULL)
goto no_input;
@ -179,7 +201,7 @@ handle_create_source_input (PvClient1 *interface,
source_input_path = pv_source_output_get_object_path (input);
g_dbus_method_invocation_return_value (invocation,
g_variant_new ("(o)",
source_input_path));
source_input_path));
return TRUE;
@ -240,9 +262,13 @@ static void
pv_client_finalize (GObject * object)
{
PvClient *client = PV_CLIENT (object);
PvClientPrivate *priv = client->priv;
client_unregister_object (client);
if (priv->properties)
g_variant_unref (priv->properties);
G_OBJECT_CLASS (pv_client_parent_class)->finalize (object);
}
@ -298,6 +324,15 @@ pv_client_class_init (PvClientClass * klass)
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
PROP_PROPERTIES,
g_param_spec_variant ("properties",
"Properties",
"Client properties",
G_VARIANT_TYPE_DICTIONARY,
NULL,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
}
static void
@ -317,12 +352,19 @@ pv_client_init (PvClient * client)
* Returns: a new #PvClient
*/
PvClient *
pv_client_new (PvDaemon * daemon, const gchar *sender, const gchar *prefix)
pv_client_new (PvDaemon *daemon,
const gchar *sender,
const gchar *prefix,
GVariant *properties)
{
g_return_val_if_fail (PV_IS_DAEMON (daemon), NULL);
g_return_val_if_fail (g_variant_is_object_path (prefix), NULL);
return g_object_new (PV_TYPE_CLIENT, "daemon", daemon, "sender", sender, "object-path", prefix, NULL);
return g_object_new (PV_TYPE_CLIENT, "daemon", daemon,
"sender", sender,
"object-path", prefix,
"properties", properties,
NULL);
}
/**

View file

@ -62,7 +62,10 @@ struct _PvClientClass {
/* normal GObject stuff */
GType pv_client_get_type (void);
PvClient * pv_client_new (PvDaemon *daemon, const gchar *sender, const gchar *prefix);
PvClient * pv_client_new (PvDaemon *daemon,
const gchar *sender,
const gchar *prefix,
GVariant *properties);
const gchar * pv_client_get_object_path (PvClient *client);

View file

@ -150,7 +150,7 @@ handle_connect_client (PvDaemon1 *interface,
sender = g_dbus_method_invocation_get_sender (invocation);
g_print ("connect client %s\n", sender);
client = pv_client_new (daemon, sender, PV_DBUS_OBJECT_PREFIX);
client = pv_client_new (daemon, sender, PV_DBUS_OBJECT_PREFIX, arg_properties);
pv_daemon_track_object (daemon, sender, G_OBJECT (client));
@ -368,7 +368,10 @@ pv_daemon_remove_source (PvDaemon *daemon, PvSource *source)
}
PvSource *
pv_daemon_find_source (PvDaemon *daemon, const gchar *name, GVariant *props)
pv_daemon_find_source (PvDaemon *daemon,
const gchar *name,
GVariant *props,
GBytes *format_filter)
{
PvDaemonPrivate *priv;

View file

@ -75,7 +75,10 @@ void pv_daemon_track_object (PvDaemon *daemon, const gchar *sen
void pv_daemon_add_source (PvDaemon *daemon, PvSource *source);
void pv_daemon_remove_source (PvDaemon *daemon, PvSource *source);
PvSource * pv_daemon_find_source (PvDaemon *daemon, const gchar *name, GVariant *props);
PvSource * pv_daemon_find_source (PvDaemon *daemon,
const gchar *name,
GVariant *props,
GBytes *format_filter);
G_END_DECLS

View file

@ -17,6 +17,7 @@
* Boston, MA 02110-1301, USA.
*/
#include <string.h>
#include <sys/socket.h>
#include <gio/gunixfdlist.h>
@ -31,9 +32,15 @@
struct _PvSourceOutputPrivate
{
PvDaemon *daemon;
PvSourceOutput1 *iface;
gchar *object_path;
gchar *source;
gchar *client_path;
gchar *source_path;
GBytes *possible_formats;
GBytes *requested_format;
GBytes *format;
GSocket *socket;
};
@ -48,7 +55,11 @@ enum
PROP_0,
PROP_DAEMON,
PROP_OBJECT_PATH,
PROP_SOURCE,
PROP_CLIENT_PATH,
PROP_SOURCE_PATH,
PROP_POSSIBLE_FORMATS,
PROP_REQUESTED_FORMAT,
PROP_FORMAT,
PROP_SOCKET,
};
@ -70,8 +81,24 @@ pv_source_output_get_property (GObject *_object,
g_value_set_string (value, priv->object_path);
break;
case PROP_SOURCE:
g_value_set_string (value, priv->source);
case PROP_CLIENT_PATH:
g_value_set_string (value, priv->client_path);
break;
case PROP_SOURCE_PATH:
g_value_set_string (value, priv->source_path);
break;
case PROP_POSSIBLE_FORMATS:
g_value_set_boxed (value, priv->possible_formats);
break;
case PROP_REQUESTED_FORMAT:
g_value_set_boxed (value, priv->requested_format);
break;
case PROP_FORMAT:
g_value_set_boxed (value, priv->format);
break;
case PROP_SOCKET:
@ -102,8 +129,28 @@ pv_source_output_set_property (GObject *_object,
priv->object_path = g_value_dup_string (value);
break;
case PROP_SOURCE:
priv->source = g_value_dup_string (value);
case PROP_CLIENT_PATH:
priv->client_path = g_value_dup_string (value);
g_object_set (priv->iface, "client", priv->client_path, NULL);
break;
case PROP_SOURCE_PATH:
priv->source_path = g_value_dup_string (value);
g_object_set (priv->iface, "source", priv->source_path, NULL);
break;
case PROP_POSSIBLE_FORMATS:
if (priv->possible_formats)
g_bytes_unref (priv->possible_formats);
priv->possible_formats = g_value_dup_boxed (value);
g_object_set (priv->iface, "possible-formats",
g_bytes_get_data (priv->possible_formats, NULL), NULL);
break;
case PROP_FORMAT:
if (priv->format)
g_bytes_unref (priv->format);
priv->format = g_value_dup_boxed (value);
break;
default:
@ -115,32 +162,45 @@ pv_source_output_set_property (GObject *_object,
static gboolean
handle_start (PvSourceOutput1 *interface,
GDBusMethodInvocation *invocation,
GVariant *arg_properties,
const gchar *arg_requested_format,
gpointer user_data)
{
PvSourceOutput *output = user_data;
PvSourceOutputPrivate *priv = output->priv;
GUnixFDList *fdlist;
GVariantBuilder props;
gint fd[2];
priv->requested_format = g_bytes_new (arg_requested_format, strlen (arg_requested_format) + 1);
socketpair (AF_UNIX, SOCK_STREAM, 0, fd);
priv->socket = g_socket_new_from_fd (fd[0], NULL);
g_object_notify (G_OBJECT (output), "socket");
g_variant_builder_init (&props, G_VARIANT_TYPE ("a{sv}"));
g_variant_builder_add (&props, "{sv}", "name", g_variant_new_string ("hello"));
if (priv->format == NULL)
goto no_format;
fdlist = g_unix_fd_list_new ();
g_unix_fd_list_append (fdlist, fd[1], NULL);
g_dbus_method_invocation_return_value_with_unix_fd_list (invocation,
g_variant_new ("(h@a{sv})",
g_variant_new ("(hs)",
0,
g_variant_builder_end (&props)),
g_bytes_get_data (priv->format, NULL)),
fdlist);
return TRUE;
/* error */
no_format:
{
g_dbus_method_invocation_return_dbus_error (invocation,
"org.pulsevideo.Error", "No format");
close (fd[0]);
close (fd[1]);
g_clear_pointer (&priv->requested_format, g_bytes_unref);
g_clear_object (&priv->socket);
return TRUE;
}
}
static void
@ -150,6 +210,8 @@ stop_transfer (PvSourceOutput *output)
if (priv->socket) {
g_clear_object (&priv->socket);
g_clear_pointer (&priv->requested_format, g_bytes_unref);
g_clear_pointer (&priv->format, g_bytes_unref);
g_object_notify (G_OBJECT (output), "socket");
}
}
@ -193,17 +255,7 @@ output_register_object (PvSourceOutput *output, const gchar *prefix)
skel = pv_object_skeleton_new (name);
g_free (name);
{
PvSourceOutput1 *iface;
iface = pv_source_output1_skeleton_new ();
g_object_set (iface, "source", priv->source, NULL);
g_signal_connect (iface, "handle-start", (GCallback) handle_start, output);
g_signal_connect (iface, "handle-stop", (GCallback) handle_stop, output);
g_signal_connect (iface, "handle-remove", (GCallback) handle_remove, output);
pv_object_skeleton_set_source_output1 (skel, iface);
g_object_unref (iface);
}
pv_object_skeleton_set_source_output1 (skel, priv->iface);
g_free (priv->object_path);
priv->object_path = pv_daemon_export_uniquely (priv->daemon, G_DBUS_OBJECT_SKELETON (skel));
@ -228,8 +280,10 @@ pv_source_output_finalize (GObject * object)
output_unregister_object (output);
g_object_unref (priv->daemon);
g_object_unref (priv->iface);
g_free (priv->client_path);
g_free (priv->object_path);
g_free (priv->source);
g_free (priv->source_path);
G_OBJECT_CLASS (pv_source_output_parent_class)->finalize (object);
}
@ -278,15 +332,52 @@ pv_source_output_class_init (PvSourceOutputClass * klass)
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
PROP_SOURCE,
g_param_spec_string ("source",
"Source",
PROP_CLIENT_PATH,
g_param_spec_string ("client-path",
"Client Path",
"The client object path",
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
PROP_SOURCE_PATH,
g_param_spec_string ("source-path",
"Source Path",
"The source object path",
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
PROP_POSSIBLE_FORMATS,
g_param_spec_boxed ("possible-formats",
"Possible Formats",
"The possbile formats of the stream",
G_TYPE_BYTES,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
PROP_REQUESTED_FORMAT,
g_param_spec_boxed ("requested-format",
"Requested Format",
"The requested format of the stream",
G_TYPE_BYTES,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
PROP_FORMAT,
g_param_spec_boxed ("format",
"Format",
"The format of the stream",
G_TYPE_BYTES,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
PROP_SOCKET,
g_param_spec_object ("socket",
@ -300,7 +391,12 @@ pv_source_output_class_init (PvSourceOutputClass * klass)
static void
pv_source_output_init (PvSourceOutput * output)
{
output->priv = PV_SOURCE_OUTPUT_GET_PRIVATE (output);
PvSourceOutputPrivate *priv = output->priv = PV_SOURCE_OUTPUT_GET_PRIVATE (output);
priv->iface = pv_source_output1_skeleton_new ();
g_signal_connect (priv->iface, "handle-start", (GCallback) handle_start, output);
g_signal_connect (priv->iface, "handle-stop", (GCallback) handle_stop, output);
g_signal_connect (priv->iface, "handle-remove", (GCallback) handle_remove, output);
}
const gchar *

View file

@ -128,24 +128,6 @@ pv_source_set_property (GObject *_object,
}
}
static gboolean
handle_get_capabilities (PvSource1 *interface,
GDBusMethodInvocation *invocation,
GVariant *arg_properties,
gpointer user_data)
{
PvSource *source = user_data;
GVariant *out_caps;
out_caps = pv_source_get_capabilities (source, arg_properties);
g_dbus_method_invocation_return_value (invocation,
g_variant_new ("(@aa{sv})", out_caps));
return TRUE;
}
static void
source_register_object (PvSource *source)
{
@ -160,9 +142,6 @@ source_register_object (PvSource *source)
"state", priv->state,
"properties", priv->properties,
NULL);
g_signal_connect (priv->iface, "handle-get-capabilities",
(GCallback) handle_get_capabilities,
source);
pv_object_skeleton_set_source1 (skel, priv->iface);
g_free (priv->object_path);
@ -202,19 +181,26 @@ pv_source_finalize (GObject * object)
g_free (priv->object_path);
g_free (priv->name);
g_variant_unref (priv->properties);
if (priv->properties)
g_variant_unref (priv->properties);
G_OBJECT_CLASS (pv_source_parent_class)->finalize (object);
}
static PvSourceOutput *
default_create_source_output (PvSource *source, GVariant *props, const gchar *prefix)
default_create_source_output (PvSource *source,
const gchar *client_path,
GBytes *format_filter,
const gchar *prefix)
{
PvSourcePrivate *priv = source->priv;
return g_object_new (PV_TYPE_SOURCE_OUTPUT, "daemon", priv->daemon,
"object-path", prefix,
"source", priv->object_path, NULL);
"client-path", client_path,
"source-path", priv->object_path,
"possible-formats", format_filter,
NULL);
}
static gboolean
@ -281,7 +267,7 @@ pv_source_class_init (PvSourceClass * klass)
g_param_spec_variant ("properties",
"Properties",
"The properties of the source",
G_VARIANT_TYPE_VARIANT,
G_VARIANT_TYPE_DICTIONARY,
NULL,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
@ -297,18 +283,18 @@ pv_source_init (PvSource * source)
source->priv = PV_SOURCE_GET_PRIVATE (source);
}
GVariant *
pv_source_get_capabilities (PvSource *source, GVariant *props)
GBytes *
pv_source_get_capabilities (PvSource *source, GBytes *filter)
{
PvSourceClass *klass;
GVariant *res;
GBytes *res;
g_return_val_if_fail (PV_IS_SOURCE (source), NULL);
klass = PV_SOURCE_GET_CLASS (source);
if (klass->get_capabilities)
res = klass->get_capabilities (source, props);
res = klass->get_capabilities (source, filter);
else
res = NULL;
@ -365,7 +351,10 @@ pv_source_report_error (PvSource *source, GError *error)
}
PvSourceOutput *
pv_source_create_source_output (PvSource *source, GVariant *props, const gchar *prefix)
pv_source_create_source_output (PvSource *source,
const gchar *client_path,
GBytes *format_filter,
const gchar *prefix)
{
PvSourceClass *klass;
PvSourceOutput *res;
@ -375,7 +364,7 @@ pv_source_create_source_output (PvSource *source, GVariant *props, const gchar *
klass = PV_SOURCE_GET_CLASS (source);
if (klass->create_source_output)
res = klass->create_source_output (source, props, prefix);
res = klass->create_source_output (source, client_path, format_filter, prefix);
else
res = NULL;

View file

@ -64,12 +64,16 @@ struct _PvSource {
struct _PvSourceClass {
GObjectClass parent_class;
GVariant * (*get_capabilities) (PvSource *source, GVariant *props);
GBytes * (*get_capabilities) (PvSource *source, GBytes *filter);
gboolean (*set_state) (PvSource *source, PvSourceState);
PvSourceOutput * (*create_source_output) (PvSource *source, GVariant *props, const gchar *prefix);
gboolean (*release_source_output) (PvSource *source, PvSourceOutput *output);
PvSourceOutput * (*create_source_output) (PvSource *source,
const gchar *client_path,
GBytes *format_filter,
const gchar *prefix);
gboolean (*release_source_output) (PvSource *source,
PvSourceOutput *output);
};
/* normal GObject stuff */
@ -77,13 +81,16 @@ GType pv_source_get_type (void);
const gchar * pv_source_get_object_path (PvSource *source);
GVariant * pv_source_get_capabilities (PvSource *source, GVariant *props);
GBytes * pv_source_get_capabilities (PvSource *source, GBytes *filter);
gboolean pv_source_set_state (PvSource *source, PvSourceState state);
void pv_source_update_state (PvSource *source, PvSourceState state);
void pv_source_report_error (PvSource *source, GError *error);
PvSourceOutput * pv_source_create_source_output (PvSource *source, GVariant *props, const gchar *prefix);
PvSourceOutput * pv_source_create_source_output (PvSource *source,
const gchar *client_path,
GBytes *format_filter,
const gchar *prefix);
gboolean pv_source_release_source_output (PvSource *source, PvSourceOutput *output);
G_END_DECLS