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); }