From f50d1548d5905cb1b43d4b358024a898b14113b8 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 21 May 2015 16:49:26 +0200 Subject: [PATCH] Add more generic gst source manager object Use device manager to add/remove all video providers dynamically, remove v4l2 specific code. Get the client proxy from subscribe instead of waiting for the subscription callback. This way we can actually make an error on failure. Clean up the objects when the server disappears. Remove subscription from the server, we don't need it. Install server objects in bus_acquired. --- src/Makefile.am | 3 +- src/client/pv-context.c | 39 ++- src/client/pv-introspect.c | 2 +- src/client/pv-subscribe.c | 23 +- src/daemon/main.c | 4 +- src/modules/gst/pv-gst-manager.c | 229 ++++++++++++++++++ src/modules/gst/pv-gst-manager.h | 60 +++++ .../pv-v4l2-source.c => gst/pv-gst-source.c} | 197 +++++++++++---- src/modules/gst/pv-gst-source.h | 61 +++++ src/modules/v4l2/pv-v4l2-source.h | 61 ----- src/server/pv-client-source.c | 6 - src/server/pv-daemon.c | 50 +--- 12 files changed, 562 insertions(+), 173 deletions(-) create mode 100644 src/modules/gst/pv-gst-manager.c create mode 100644 src/modules/gst/pv-gst-manager.h rename src/modules/{v4l2/pv-v4l2-source.c => gst/pv-gst-source.c} (55%) create mode 100644 src/modules/gst/pv-gst-source.h delete mode 100644 src/modules/v4l2/pv-v4l2-source.h diff --git a/src/Makefile.am b/src/Makefile.am index 03ff59d3b..5d6e168f3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -190,7 +190,8 @@ libpulsevideocore_@PV_MAJORMINOR@_la_SOURCES = \ server/pv-source.c server/pv-source.h \ server/pv-client-source.c server/pv-client-source.h \ server/pv-source-output.c server/pv-source-output.h \ - modules/v4l2/pv-v4l2-source.c + modules/gst/pv-gst-manager.c \ + modules/gst/pv-gst-source.c libpulsevideocore_@PV_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(SERVER_CFLAGS) libpulsevideocore_@PV_MAJORMINOR@_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version diff --git a/src/client/pv-context.c b/src/client/pv-context.c index 7467275d0..cfdb342b3 100644 --- a/src/client/pv-context.c +++ b/src/client/pv-context.c @@ -307,6 +307,33 @@ context_set_state (PvContext *context, PvContextState state) g_object_notify (G_OBJECT (context), "state"); } } +static void +on_client_proxy (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + PvContext *context = user_data; + PvContextPrivate *priv = context->priv; + GError *error = NULL; + + priv->client = pv_subscribe_get_proxy_finish (priv->subscribe, + res, + &error); + if (priv->client == NULL) + goto client_failed; + + context_set_state (context, PV_CONTEXT_STATE_READY); + + return; + +client_failed: + { + priv->error = error; + context_set_state (context, PV_STREAM_STATE_ERROR); + g_error ("failed to get client proxy: %s", error->message); + return; + } +} static void on_client_connected (GObject *source_object, @@ -330,6 +357,14 @@ on_client_connected (GObject *source_object, g_variant_get (ret, "(o)", &priv->client_path); g_variant_unref (ret); + + pv_subscribe_get_proxy (priv->subscribe, + PV_DBUS_SERVICE, + priv->client_path, + "org.pulsevideo.Client1", + NULL, + on_client_proxy, + context); } static void @@ -372,10 +407,6 @@ subscription_cb (PvSubscribe *subscribe, break; case PV_SUBSCRIPTION_FLAGS_CLIENT: - if (g_strcmp0 (g_dbus_proxy_get_object_path (object), priv->client_path) == 0) { - priv->client = object; - context_set_state (context, PV_CONTEXT_STATE_READY); - } break; case PV_SUBSCRIPTION_FLAGS_SOURCE: diff --git a/src/client/pv-introspect.c b/src/client/pv-introspect.c index b75426a9f..516249dd5 100644 --- a/src/client/pv-introspect.c +++ b/src/client/pv-introspect.c @@ -49,7 +49,7 @@ pv_context_list_source_info (PvContext *context, GDBusProxy *proxy = walk->data; PvSourceInfo info; - info.name = "v4l2"; + info.name = "gst"; cb (context, &info, user_data); } diff --git a/src/client/pv-subscribe.c b/src/client/pv-subscribe.c index d6b9c1667..7340aa2fb 100644 --- a/src/client/pv-subscribe.c +++ b/src/client/pv-subscribe.c @@ -134,17 +134,28 @@ object_data_free (PvObjectData *data) static void remove_data (PvSubscribe *subscribe, PvObjectData *data) { - PvSubscribePrivate *priv = subscribe->priv; - if (data->pending) { data->removed = TRUE; } else { - priv->objects = g_list_remove (priv->objects, data); notify_event (subscribe, data, PV_SUBSCRIPTION_EVENT_REMOVE); object_data_free (data); } } +static void +remove_all_data (PvSubscribe *subscribe) +{ + PvSubscribePrivate *priv = subscribe->priv; + GList *walk; + + for (walk = priv->objects; walk; walk = g_list_next (walk)) { + PvObjectData *data = walk->data; + remove_data (subscribe, data); + } + g_list_free (priv->objects); + priv->objects = NULL; +} + static void on_proxy_created (GObject *source_object, GAsyncResult *res, @@ -185,8 +196,10 @@ on_proxy_created (GObject *source_object, if (--priv->pending_proxies == 0) subscription_set_state (subscribe, PV_SUBSCRIPTION_STATE_READY); - if (data->removed) + if (data->removed) { + priv->objects = g_list_remove (priv->objects, data); remove_data (subscribe, data); + } } @@ -233,6 +246,7 @@ remove_interface (PvSubscribe *subscribe, if (g_strcmp0 (data->object_path, object_path) == 0 && g_strcmp0 (data->interface_name, interface_name) == 0) { + priv->objects = g_list_remove (priv->objects, data); remove_data (subscribe, data); break; } @@ -364,6 +378,7 @@ manager_proxy_appeared (PvSubscribe *subscribe) static void manager_proxy_disappeared (PvSubscribe *subscribe) { + remove_all_data (subscribe); } static void diff --git a/src/daemon/main.c b/src/daemon/main.c index a9a981903..a6a9a036b 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -22,7 +22,7 @@ #include #include -#include +#include gint main (gint argc, gchar *argv[]) @@ -36,7 +36,7 @@ main (gint argc, gchar *argv[]) daemon = pv_daemon_new (); - pv_v4l2_source_new (daemon); + pv_gst_manager_new (daemon); pv_daemon_start (daemon); g_main_loop_run (loop); diff --git a/src/modules/gst/pv-gst-manager.c b/src/modules/gst/pv-gst-manager.c new file mode 100644 index 000000000..f55d3ce3b --- /dev/null +++ b/src/modules/gst/pv-gst-manager.c @@ -0,0 +1,229 @@ +/* Pulsevideo + * Copyright (C) 2015 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include +#include + +#include "pv-gst-manager.h" +#include "pv-gst-source.h" + +#define PV_GST_MANAGER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PV_TYPE_GST_MANAGER, PvGstManagerPrivate)) + +struct _PvGstManagerPrivate +{ + PvDaemon *daemon; + + GstDeviceMonitor *monitor; +}; + +enum +{ + PROP_0, + PROP_DAEMON +}; + +G_DEFINE_TYPE (PvGstManager, pv_gst_manager, G_TYPE_OBJECT); + +static void +device_added (PvGstManager *manager, GstDevice *device) +{ + PvGstManagerPrivate *priv = manager->priv; + gchar *name; + GstElement *element; + PvSource *source; + + name = gst_device_get_display_name (device); + g_print("Device added: %s\n", name); + + element = gst_device_create_element (device, NULL); + source = pv_gst_source_new (priv->daemon, name, element); + g_object_set_data (G_OBJECT (device), "PvSource", source); + g_free (name); +} + +static void +device_removed (PvGstManager *manager, GstDevice *device) +{ + gchar *name; + PvSource *source; + + name = gst_device_get_display_name (device); + g_print("Device removed: %s\n", name); + source = g_object_steal_data (G_OBJECT (device), "PvSource"); + g_object_unref (source); + g_free (name); +} + +static gboolean +bus_handler (GstBus * bus, GstMessage * message, gpointer user_data) +{ + PvGstManager *manager = user_data; + PvGstManagerPrivate *priv = manager->priv; + GstDevice *device; + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_DEVICE_ADDED: + gst_message_parse_device_added (message, &device); + device_added (manager, device); + break; + case GST_MESSAGE_DEVICE_REMOVED: + gst_message_parse_device_removed (message, &device); + device_removed (manager, device); + break; + default: + break; + } + return TRUE; +} + +static void +start_monitor (PvGstManager *manager) +{ + PvGstManagerPrivate *priv = manager->priv; + GstBus *bus; + GList *devices; + + priv->monitor = gst_device_monitor_new (); + + bus = gst_device_monitor_get_bus (priv->monitor); + gst_bus_add_watch (bus, bus_handler, manager); + gst_object_unref (bus); + + gst_device_monitor_add_filter (priv->monitor, "Video/Source", NULL); + + gst_device_monitor_start (priv->monitor); + + devices = gst_device_monitor_get_devices (priv->monitor); + while (devices != NULL) { + GstDevice *device = devices->data; + + device_added (manager, device); + gst_object_unref (device); + devices = g_list_remove_link (devices, devices); + } +} + +static void +stop_monitor (PvGstManager *manager) +{ + PvGstManagerPrivate *priv = manager->priv; + + if (priv->monitor) { + gst_device_monitor_stop (priv->monitor); + g_object_unref (priv->monitor); + priv->monitor = NULL; + } +} + +static void +pv_gst_manager_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + PvGstManager *manager = PV_GST_MANAGER (object); + PvGstManagerPrivate *priv = manager->priv; + + switch (prop_id) { + case PROP_DAEMON: + g_value_set_object (value, priv->daemon); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +pv_gst_manager_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + PvGstManager *manager = PV_GST_MANAGER (object); + PvGstManagerPrivate *priv = manager->priv; + + switch (prop_id) { + case PROP_DAEMON: + priv->daemon = g_value_dup_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_manager_constructed (GObject * object) +{ + PvGstManager *manager = PV_GST_MANAGER (object); + + start_monitor (manager); + + G_OBJECT_CLASS (pv_gst_manager_parent_class)->constructed (object); +} + +static void +gst_manager_finalize (GObject * object) +{ + PvGstManager *manager = PV_GST_MANAGER (object); + + stop_monitor (manager); + + G_OBJECT_CLASS (pv_gst_manager_parent_class)->finalize (object); +} + +static void +pv_gst_manager_class_init (PvGstManagerClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (PvGstManagerPrivate)); + + gobject_class->constructed = gst_manager_constructed; + gobject_class->finalize = gst_manager_finalize; + gobject_class->set_property = pv_gst_manager_set_property; + gobject_class->get_property = pv_gst_manager_get_property; + + g_object_class_install_property (gobject_class, + PROP_DAEMON, + g_param_spec_object ("daemon", + "Daemon", + "The daemon", + PV_TYPE_DAEMON, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); +} + +static void +pv_gst_manager_init (PvGstManager * manager) +{ + manager->priv = PV_GST_MANAGER_GET_PRIVATE (manager); +} + +PvGstManager * +pv_gst_manager_new (PvDaemon *daemon) +{ + return g_object_new (PV_TYPE_GST_MANAGER, "daemon", daemon, NULL); +} diff --git a/src/modules/gst/pv-gst-manager.h b/src/modules/gst/pv-gst-manager.h new file mode 100644 index 000000000..2a5800dfe --- /dev/null +++ b/src/modules/gst/pv-gst-manager.h @@ -0,0 +1,60 @@ +/* Pulsevideo + * Copyright (C) 2015 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __PV_GST_MANAGER_H__ +#define __PV_GST_MANAGER_H__ + +#include + +#include +#include + +G_BEGIN_DECLS + +#define PV_TYPE_GST_MANAGER (pv_gst_manager_get_type ()) +#define PV_IS_GST_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PV_TYPE_GST_MANAGER)) +#define PV_IS_GST_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PV_TYPE_GST_MANAGER)) +#define PV_GST_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PV_TYPE_GST_MANAGER, PvGstManagerClass)) +#define PV_GST_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PV_TYPE_GST_MANAGER, PvGstManager)) +#define PV_GST_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PV_TYPE_GST_MANAGER, PvGstManagerClass)) +#define PV_GST_MANAGER_CAST(obj) ((PvGstManager*)(obj)) +#define PV_GST_MANAGER_CLASS_CAST(klass) ((PvGstManagerClass*)(klass)) + +typedef struct _PvGstManager PvGstManager; +typedef struct _PvGstManagerClass PvGstManagerClass; +typedef struct _PvGstManagerPrivate PvGstManagerPrivate; + +struct _PvGstManager { + GObject object; + + PvGstManagerPrivate *priv; +}; + +struct _PvGstManagerClass { + GObjectClass parent_class; +}; + +GType pv_gst_manager_get_type (void); + +PvGstManager * pv_gst_manager_new (PvDaemon *daemon); + +G_END_DECLS + +#endif /* __PV_GST_MANAGER_H__ */ + diff --git a/src/modules/v4l2/pv-v4l2-source.c b/src/modules/gst/pv-gst-source.c similarity index 55% rename from src/modules/v4l2/pv-v4l2-source.c rename to src/modules/gst/pv-gst-source.c index c2ac02142..1b732f9b2 100644 --- a/src/modules/v4l2/pv-v4l2-source.c +++ b/src/modules/gst/pv-gst-source.c @@ -21,28 +21,33 @@ #include #include -#include "pv-v4l2-source.h" +#include "pv-gst-source.h" -#define PV_V4L2_SOURCE_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PV_TYPE_V4L2_SOURCE, PvV4l2SourcePrivate)) +#define PV_GST_SOURCE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PV_TYPE_GST_SOURCE, PvGstSourcePrivate)) -struct _PvV4l2SourcePrivate +struct _PvGstSourcePrivate { GstElement *pipeline; - GstElement *src; + GstElement *element; GstElement *filter; GstElement *sink; GstCaps *possible_formats; }; -G_DEFINE_TYPE (PvV4l2Source, pv_v4l2_source, PV_TYPE_SOURCE); +enum { + PROP_0, + PROP_ELEMENT, +}; + +G_DEFINE_TYPE (PvGstSource, pv_gst_source, PV_TYPE_SOURCE); static gboolean bus_handler (GstBus * bus, GstMessage * message, gpointer user_data) { PvSource *source = user_data; - PvV4l2SourcePrivate *priv = PV_V4L2_SOURCE (source)->priv; + PvGstSourcePrivate *priv = PV_GST_SOURCE (source)->priv; switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_ERROR: @@ -65,26 +70,34 @@ bus_handler (GstBus * bus, GstMessage * message, gpointer user_data) } static void -setup_pipeline (PvV4l2Source *source) +setup_pipeline (PvGstSource *source) { - PvV4l2SourcePrivate *priv = source->priv; + PvGstSourcePrivate *priv = source->priv; GstBus *bus; + GstElement *elem; - priv->pipeline = gst_parse_launch ("v4l2src name=src ! " - "capsfilter name=filter ! " - "pvfdpay ! " - "multisocketsink " - "buffers-max=2 " - "buffers-soft-max=1 " - "recover-policy=latest " - "sync-method=latest " - "name=sink " - "sync=true " - "enable-last-sample=false", - NULL); - priv->filter = gst_bin_get_by_name (GST_BIN (priv->pipeline), "filter"); - priv->sink = gst_bin_get_by_name (GST_BIN (priv->pipeline), "sink"); - priv->src = gst_bin_get_by_name (GST_BIN (priv->pipeline), "src"); + priv->pipeline = gst_pipeline_new (NULL); + + gst_bin_add (GST_BIN (priv->pipeline), priv->element); + + priv->filter = gst_element_factory_make ("capsfilter", NULL); + gst_bin_add (GST_BIN (priv->pipeline), priv->filter); + gst_element_link (priv->element, priv->filter); + + elem = gst_element_factory_make ("pvfdpay", NULL); + gst_bin_add (GST_BIN (priv->pipeline), elem); + gst_element_link (priv->filter, elem); + + priv->sink = gst_element_factory_make ("multisocketsink", NULL); + g_object_set (priv->sink, "buffers-max", 2, + "buffers-soft-max", 1, + "recover-policy", 1, /* latest */ + "sync-method", 0, /* latest */ + "sync", TRUE, + "enable-last-sample", FALSE, + NULL); + gst_bin_add (GST_BIN (priv->pipeline), priv->sink); + gst_element_link (elem, priv->sink); bus = gst_pipeline_get_bus (GST_PIPELINE (priv->pipeline)); gst_bus_add_watch (bus, bus_handler, source); @@ -93,10 +106,22 @@ setup_pipeline (PvV4l2Source *source) gst_element_set_state (priv->pipeline, GST_STATE_READY); } +static void +destroy_pipeline (PvGstSource *source) +{ + PvGstSourcePrivate *priv = source->priv; + + if (priv->pipeline) { + gst_element_set_state (priv->pipeline, GST_STATE_NULL); + gst_object_unref (priv->pipeline); + priv->pipeline = NULL; + } +} + static GstCaps * collect_caps (PvSource * source, GstCaps *filter) { - PvV4l2SourcePrivate *priv = PV_V4L2_SOURCE (source)->priv; + PvGstSourcePrivate *priv = PV_GST_SOURCE (source)->priv; GstCaps *res; GstQuery *query; @@ -110,9 +135,9 @@ collect_caps (PvSource * source, GstCaps *filter) } static gboolean -v4l2_set_state (PvSource *source, PvSourceState state) +set_state (PvSource *source, PvSourceState state) { - PvV4l2SourcePrivate *priv = PV_V4L2_SOURCE (source)->priv; + PvGstSourcePrivate *priv = PV_GST_SOURCE (source)->priv; switch (state) { case PV_SOURCE_STATE_SUSPENDED: @@ -139,7 +164,7 @@ v4l2_set_state (PvSource *source, PvSourceState state) } static GBytes * -v4l2_get_formats (PvSource *source, GBytes *filter) +get_formats (PvSource *source, GBytes *filter) { GstCaps *caps, *cfilter; gchar *str; @@ -162,8 +187,8 @@ on_socket_notify (GObject *gobject, GParamSpec *pspec, gpointer user_data) { - PvV4l2Source *source = user_data; - PvV4l2SourcePrivate *priv = source->priv; + PvGstSource *source = user_data; + PvGstSourcePrivate *priv = source->priv; GSocket *socket; guint num_handles; GstCaps *caps; @@ -219,11 +244,11 @@ on_socket_notify (GObject *gobject, } static PvSourceOutput * -v4l2_create_source_output (PvSource *source, - const gchar *client_path, - GBytes *format_filter, - const gchar *prefix, - GError **error) +create_source_output (PvSource *source, + const gchar *client_path, + GBytes *format_filter, + const gchar *prefix, + GError **error) { PvSourceOutput *output; GstCaps *caps, *filtered; @@ -241,7 +266,7 @@ v4l2_create_source_output (PvSource *source, str = gst_caps_to_string (filtered); format_filter = g_bytes_new_take (str, strlen (str) + 1); - output = PV_SOURCE_CLASS (pv_v4l2_source_parent_class) + output = PV_SOURCE_CLASS (pv_gst_source_parent_class) ->create_source_output (source, client_path, format_filter, @@ -274,43 +299,109 @@ no_format: } static gboolean -v4l2_release_source_output (PvSource *source, PvSourceOutput *output) +release_source_output (PvSource *source, PvSourceOutput *output) { - return PV_SOURCE_CLASS (pv_v4l2_source_parent_class)->release_source_output (source, output); + return PV_SOURCE_CLASS (pv_gst_source_parent_class)->release_source_output (source, output); } static void -v4l2_source_finalize (GObject * object) +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) { - G_OBJECT_CLASS (pv_v4l2_source_parent_class)->finalize (object); + PvGstSource *source = PV_GST_SOURCE (object); + PvGstSourcePrivate *priv = source->priv; + + switch (prop_id) { + case PROP_ELEMENT: + g_value_set_object (value, priv->element); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } static void -pv_v4l2_source_class_init (PvV4l2SourceClass * klass) +set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + PvGstSource *source = PV_GST_SOURCE (object); + PvGstSourcePrivate *priv = source->priv; + + switch (prop_id) { + case PROP_ELEMENT: + priv->element = g_value_dup_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +source_constructed (GObject * object) +{ + PvGstSource *source = PV_GST_SOURCE (object); + + setup_pipeline (source); + + G_OBJECT_CLASS (pv_gst_source_parent_class)->constructed (object); +} + +static void +source_finalize (GObject * object) +{ + PvGstSource *source = PV_GST_SOURCE (object); + + destroy_pipeline (source); + + G_OBJECT_CLASS (pv_gst_source_parent_class)->finalize (object); +} + +static void +pv_gst_source_class_init (PvGstSourceClass * klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); PvSourceClass *source_class = PV_SOURCE_CLASS (klass); - g_type_class_add_private (klass, sizeof (PvV4l2SourcePrivate)); + g_type_class_add_private (klass, sizeof (PvGstSourcePrivate)); - gobject_class->finalize = v4l2_source_finalize; + gobject_class->constructed = source_constructed; + gobject_class->finalize = source_finalize; + gobject_class->get_property = get_property; + gobject_class->set_property = set_property; - source_class->get_formats = v4l2_get_formats; - source_class->set_state = v4l2_set_state; - source_class->create_source_output = v4l2_create_source_output; - source_class->release_source_output = v4l2_release_source_output; + g_object_class_install_property (gobject_class, + PROP_ELEMENT, + g_param_spec_object ("element", + "Element", + "The element", + GST_TYPE_ELEMENT, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + + source_class->get_formats = get_formats; + source_class->set_state = set_state; + source_class->create_source_output = create_source_output; + source_class->release_source_output = release_source_output; } static void -pv_v4l2_source_init (PvV4l2Source * source) +pv_gst_source_init (PvGstSource * source) { - source->priv = PV_V4L2_SOURCE_GET_PRIVATE (source); - - setup_pipeline (source); + source->priv = PV_GST_SOURCE_GET_PRIVATE (source); } PvSource * -pv_v4l2_source_new (PvDaemon *daemon) +pv_gst_source_new (PvDaemon *daemon, const gchar *name, GstElement *element) { - return g_object_new (PV_TYPE_V4L2_SOURCE, "daemon", daemon, "name", "v4l2", NULL); + return g_object_new (PV_TYPE_GST_SOURCE, "daemon", daemon, "name", name, "element", element, NULL); } diff --git a/src/modules/gst/pv-gst-source.h b/src/modules/gst/pv-gst-source.h new file mode 100644 index 000000000..c32579a2e --- /dev/null +++ b/src/modules/gst/pv-gst-source.h @@ -0,0 +1,61 @@ +/* Pulsevideo + * Copyright (C) 2015 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __PV_GST_SOURCE_H__ +#define __PV_GST_SOURCE_H__ + +#include + +#include +#include +#include + +G_BEGIN_DECLS + +#define PV_TYPE_GST_SOURCE (pv_gst_source_get_type ()) +#define PV_IS_GST_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PV_TYPE_GST_SOURCE)) +#define PV_IS_GST_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PV_TYPE_GST_SOURCE)) +#define PV_GST_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PV_TYPE_GST_SOURCE, PvGstSourceClass)) +#define PV_GST_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PV_TYPE_GST_SOURCE, PvGstSource)) +#define PV_GST_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PV_TYPE_GST_SOURCE, PvGstSourceClass)) +#define PV_GST_SOURCE_CAST(obj) ((PvGstSource*)(obj)) +#define PV_GST_SOURCE_CLASS_CAST(klass) ((PvGstSourceClass*)(klass)) + +typedef struct _PvGstSource PvGstSource; +typedef struct _PvGstSourceClass PvGstSourceClass; +typedef struct _PvGstSourcePrivate PvGstSourcePrivate; + +struct _PvGstSource { + PvSource object; + + PvGstSourcePrivate *priv; +}; + +struct _PvGstSourceClass { + PvSourceClass parent_class; +}; + +GType pv_gst_source_get_type (void); + +PvSource * pv_gst_source_new (PvDaemon *daemon, const gchar *name, GstElement *element); + +G_END_DECLS + +#endif /* __PV_GST_SOURCE_H__ */ + diff --git a/src/modules/v4l2/pv-v4l2-source.h b/src/modules/v4l2/pv-v4l2-source.h deleted file mode 100644 index d730dacec..000000000 --- a/src/modules/v4l2/pv-v4l2-source.h +++ /dev/null @@ -1,61 +0,0 @@ -/* Pulsevideo - * Copyright (C) 2015 Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __PV_V4L2_SOURCE_H__ -#define __PV_V4L2_SOURCE_H__ - -#include - -#include -#include -#include - -G_BEGIN_DECLS - -#define PV_TYPE_V4L2_SOURCE (pv_v4l2_source_get_type ()) -#define PV_IS_V4L2_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PV_TYPE_V4L2_SOURCE)) -#define PV_IS_V4L2_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PV_TYPE_V4L2_SOURCE)) -#define PV_V4L2_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PV_TYPE_V4L2_SOURCE, PvV4l2SourceClass)) -#define PV_V4L2_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PV_TYPE_V4L2_SOURCE, PvV4l2Source)) -#define PV_V4L2_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PV_TYPE_V4L2_SOURCE, PvV4l2SourceClass)) -#define PV_V4L2_SOURCE_CAST(obj) ((PvV4l2Source*)(obj)) -#define PV_V4L2_SOURCE_CLASS_CAST(klass) ((PvV4l2SourceClass*)(klass)) - -typedef struct _PvV4l2Source PvV4l2Source; -typedef struct _PvV4l2SourceClass PvV4l2SourceClass; -typedef struct _PvV4l2SourcePrivate PvV4l2SourcePrivate; - -struct _PvV4l2Source { - PvSource object; - - PvV4l2SourcePrivate *priv; -}; - -struct _PvV4l2SourceClass { - PvSourceClass parent_class; -}; - -GType pv_v4l2_source_get_type (void); - -PvSource * pv_v4l2_source_new (PvDaemon *daemon); - -G_END_DECLS - -#endif /* __PV_V4L2_SOURCE_H__ */ - diff --git a/src/server/pv-client-source.c b/src/server/pv-client-source.c index 93c211b63..aa591c041 100644 --- a/src/server/pv-client-source.c +++ b/src/server/pv-client-source.c @@ -169,8 +169,6 @@ on_socket_notify (GObject *gobject, g_object_get (gobject, "socket", &socket, NULL); - g_print ("source socket %p\n", socket); - if (socket == NULL) { GSocket *prev_socket = g_object_get_data (gobject, "last-socket"); if (prev_socket) { @@ -182,7 +180,6 @@ on_socket_notify (GObject *gobject, g_object_set_data (gobject, "last-socket", socket); g_object_get (priv->sink, "num-handles", &num_handles, NULL); - g_print ("num handles %d\n", num_handles); if (num_handles == 0) { gst_element_set_state (priv->pipeline, GST_STATE_READY); } else if (socket) { @@ -190,7 +187,6 @@ on_socket_notify (GObject *gobject, /* suggest what we provide */ g_object_get (priv->input, "format", &format, NULL); - g_print ("final format %s\n", (gchar *) g_bytes_get_data (format, NULL)); g_object_set (gobject, "format", format, NULL); g_bytes_unref (format); @@ -253,13 +249,11 @@ on_input_socket_notify (GObject *gobject, GstCaps *caps; g_object_get (gobject, "socket", &socket, NULL); - g_print ("input socket %p\n", socket); if (socket) { /* requested format is final format */ 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); /* and set as caps on the filter */ diff --git a/src/server/pv-daemon.c b/src/server/pv-daemon.c index 5d6ee23a4..86ef3828a 100644 --- a/src/server/pv-daemon.c +++ b/src/server/pv-daemon.c @@ -21,13 +21,13 @@ #include "config.h" +#include "client/pulsevideo.h" + #include "server/pv-daemon.h" #include "server/pv-client.h" #include "dbus/org-pulsevideo.h" -#include "modules/v4l2/pv-v4l2-source.h" - #define PV_DAEMON_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PV_TYPE_DAEMON, PvDaemonPrivate)) @@ -36,7 +36,6 @@ struct _PvDaemonPrivate guint id; GDBusConnection *connection; GDBusObjectManagerServer *server_manager; - PvSubscribe *subscribe; GList *sources; @@ -50,23 +49,6 @@ typedef struct { GList *objects; } SenderData; -static void -on_server_subscription_event (PvSubscribe *subscribe, - PvSubscriptionEvent event, - PvSubscriptionFlags flags, - GDBusProxy *object, - gpointer user_data) -{ - const gchar *name, *object_path; - - name = g_dbus_proxy_get_name (object); - object_path = g_dbus_proxy_get_object_path (object); - - switch (flags) { - default: - break; - } -} static void client_name_appeared_handler (GDBusConnection *connection, const gchar *name, @@ -176,8 +158,13 @@ bus_acquired_handler (GDBusConnection *connection, { PvDaemon *daemon = user_data; PvDaemonPrivate *priv = daemon->priv; + GDBusObjectManagerServer *manager = priv->server_manager; priv->connection = connection; + + export_server_object (daemon, manager); + + g_dbus_object_manager_server_set_connection (manager, connection); } static void @@ -185,18 +172,6 @@ name_acquired_handler (GDBusConnection *connection, const gchar *name, gpointer user_data) { - PvDaemon *daemon = user_data; - PvDaemonPrivate *priv = daemon->priv; - GDBusObjectManagerServer *manager = priv->server_manager; - - export_server_object (daemon, manager); - - g_object_set (priv->subscribe, "service", PV_DBUS_SERVICE, - "subscription-mask", PV_SUBSCRIPTION_FLAGS_ALL, - "connection", connection, - NULL); - - g_dbus_object_manager_server_set_connection (manager, connection); } static void @@ -208,10 +183,9 @@ name_lost_handler (GDBusConnection *connection, PvDaemonPrivate *priv = daemon->priv; GDBusObjectManagerServer *manager = priv->server_manager; - g_object_set (priv->subscribe, "connection", connection, NULL); - g_dbus_object_manager_server_unexport (manager, PV_DBUS_OBJECT_SERVER); g_dbus_object_manager_server_set_connection (manager, connection); + priv->connection = connection; } /** @@ -395,8 +369,8 @@ pv_daemon_finalize (GObject * object) PvDaemon *daemon = PV_DAEMON_CAST (object); PvDaemonPrivate *priv = daemon->priv; - g_clear_object (&priv->server_manager); pv_daemon_stop (daemon); + g_clear_object (&priv->server_manager); G_OBJECT_CLASS (pv_daemon_parent_class)->finalize (object); } @@ -418,11 +392,5 @@ pv_daemon_init (PvDaemon * daemon) priv->server_manager = g_dbus_object_manager_server_new (PV_DBUS_OBJECT_PREFIX); priv->senders = g_hash_table_new (g_str_hash, g_str_equal); - - priv->subscribe = pv_subscribe_new (); - g_signal_connect (priv->subscribe, - "subscription-event", - (GCallback) on_server_subscription_event, - daemon); }