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.
This commit is contained in:
Wim Taymans 2015-05-21 16:49:26 +02:00
parent e24398fe8c
commit f50d1548d5
12 changed files with 562 additions and 173 deletions

View file

@ -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

View file

@ -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:

View file

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

View file

@ -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

View file

@ -22,7 +22,7 @@
#include <client/pulsevideo.h>
#include <server/pv-daemon.h>
#include <modules/v4l2/pv-v4l2-source.h>
#include <modules/gst/pv-gst-manager.h>
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);

View file

@ -0,0 +1,229 @@
/* Pulsevideo
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
*
* 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 <string.h>
#include <gst/gst.h>
#include <gio/gio.h>
#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);
}

View file

@ -0,0 +1,60 @@
/* Pulsevideo
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
*
* 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 <glib-object.h>
#include <client/pulsevideo.h>
#include <server/pv-daemon.h>
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__ */

View file

@ -21,28 +21,33 @@
#include <gst/gst.h>
#include <gio/gio.h>
#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);
}

View file

@ -0,0 +1,61 @@
/* Pulsevideo
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
*
* 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 <glib-object.h>
#include <client/pulsevideo.h>
#include <server/pv-daemon.h>
#include <server/pv-source.h>
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__ */

View file

@ -1,61 +0,0 @@
/* Pulsevideo
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
*
* 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 <glib-object.h>
#include <client/pulsevideo.h>
#include <server/pv-daemon.h>
#include <server/pv-source.h>
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__ */

View file

@ -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 */

View file

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