multifdsink, multisocketsink: fix broken action signal setup

We can't just make a vfunc that takes a union of int
and pointer as argument, and then set up subclass-specific
action signals and signals that take int (in multifdsink's
case) or a GSocket * (in multisocketsink's case), and then
expect everything to Just Work. This blows up spectacularly
on PPC G4 for some reason.

Fixes multifdsink unit test on PPC, and fixes aborts in
multisocketunit test (now hangs in gst_pad_push - progress).
This commit is contained in:
Tim-Philipp Müller 2012-09-09 01:20:38 +01:00
parent 175bd55a66
commit 84a3add409
6 changed files with 283 additions and 85 deletions

View file

@ -140,6 +140,9 @@ enum
SIGNAL_GET_STATS, SIGNAL_GET_STATS,
/* signals */ /* signals */
SIGNAL_CLIENT_ADDED,
SIGNAL_CLIENT_REMOVED,
SIGNAL_CLIENT_HANDLE_REMOVED,
LAST_SIGNAL LAST_SIGNAL
}; };
@ -159,8 +162,24 @@ static void gst_multi_fd_sink_stop_post (GstMultiHandleSink * mhsink);
static gboolean gst_multi_fd_sink_start_pre (GstMultiHandleSink * mhsink); static gboolean gst_multi_fd_sink_start_pre (GstMultiHandleSink * mhsink);
static gpointer gst_multi_fd_sink_thread (GstMultiHandleSink * mhsink); static gpointer gst_multi_fd_sink_thread (GstMultiHandleSink * mhsink);
static void gst_multi_fd_sink_add (GstMultiFdSink * sink, int fd);
static void gst_multi_fd_sink_add_full (GstMultiFdSink * sink, int fd,
GstSyncMethod sync, GstFormat min_format, guint64 min_value,
GstFormat max_format, guint64 max_value);
static void gst_multi_fd_sink_remove (GstMultiFdSink * sink, int fd);
static void gst_multi_fd_sink_remove_flush (GstMultiFdSink * sink, int fd);
static GstStructure *gst_multi_fd_sink_get_stats (GstMultiFdSink * sink,
int fd);
static void gst_multi_fd_sink_emit_client_added (GstMultiHandleSink * mhsink,
GstMultiSinkHandle handle);
static void gst_multi_fd_sink_emit_client_removed (GstMultiHandleSink * mhsink,
GstMultiSinkHandle handle, GstClientStatus status);
static GstMultiHandleClient *gst_multi_fd_sink_new_client (GstMultiHandleSink * static GstMultiHandleClient *gst_multi_fd_sink_new_client (GstMultiHandleSink *
mhsink, GstMultiSinkHandle handle, GstSyncMethod sync_method); mhsink, GstMultiSinkHandle handle, GstSyncMethod sync_method);
static void gst_multi_fd_sink_client_free (GstMultiHandleSink * m,
GstMultiHandleClient * client);
static int gst_multi_fd_sink_client_get_fd (GstMultiHandleClient * client); static int gst_multi_fd_sink_client_get_fd (GstMultiHandleClient * client);
static void gst_multi_fd_sink_handle_debug (GstMultiSinkHandle handle, static void gst_multi_fd_sink_handle_debug (GstMultiSinkHandle handle,
gchar debug[30]); gchar debug[30]);
@ -218,7 +237,7 @@ gst_multi_fd_sink_class_init (GstMultiFdSinkClass * klass)
gst_multi_fd_sink_signals[SIGNAL_ADD] = gst_multi_fd_sink_signals[SIGNAL_ADD] =
g_signal_new ("add", G_TYPE_FROM_CLASS (klass), g_signal_new ("add", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GstMultiHandleSinkClass, add), NULL, NULL, G_STRUCT_OFFSET (GstMultiFdSinkClass, add), NULL, NULL,
g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
/** /**
* GstMultiFdSink::add-full: * GstMultiFdSink::add-full:
@ -238,7 +257,7 @@ gst_multi_fd_sink_class_init (GstMultiFdSinkClass * klass)
gst_multi_fd_sink_signals[SIGNAL_ADD_BURST] = gst_multi_fd_sink_signals[SIGNAL_ADD_BURST] =
g_signal_new ("add-full", G_TYPE_FROM_CLASS (klass), g_signal_new ("add-full", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GstMultiHandleSinkClass, add_full), NULL, NULL, G_STRUCT_OFFSET (GstMultiFdSinkClass, add_full), NULL, NULL,
gst_tcp_marshal_VOID__INT_ENUM_INT_UINT64_INT_UINT64, G_TYPE_NONE, 6, gst_tcp_marshal_VOID__INT_ENUM_INT_UINT64_INT_UINT64, G_TYPE_NONE, 6,
G_TYPE_INT, GST_TYPE_SYNC_METHOD, GST_TYPE_FORMAT, G_TYPE_UINT64, G_TYPE_INT, GST_TYPE_SYNC_METHOD, GST_TYPE_FORMAT, G_TYPE_UINT64,
GST_TYPE_FORMAT, G_TYPE_UINT64); GST_TYPE_FORMAT, G_TYPE_UINT64);
@ -252,7 +271,7 @@ gst_multi_fd_sink_class_init (GstMultiFdSinkClass * klass)
gst_multi_fd_sink_signals[SIGNAL_REMOVE] = gst_multi_fd_sink_signals[SIGNAL_REMOVE] =
g_signal_new ("remove", G_TYPE_FROM_CLASS (klass), g_signal_new ("remove", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GstMultiHandleSinkClass, remove), NULL, NULL, G_STRUCT_OFFSET (GstMultiFdSinkClass, remove), NULL, NULL,
gst_tcp_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); gst_tcp_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
/** /**
* GstMultiFdSink::remove-flush: * GstMultiFdSink::remove-flush:
@ -265,7 +284,7 @@ gst_multi_fd_sink_class_init (GstMultiFdSinkClass * klass)
gst_multi_fd_sink_signals[SIGNAL_REMOVE_FLUSH] = gst_multi_fd_sink_signals[SIGNAL_REMOVE_FLUSH] =
g_signal_new ("remove-flush", G_TYPE_FROM_CLASS (klass), g_signal_new ("remove-flush", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GstMultiHandleSinkClass, remove_flush), NULL, NULL, G_STRUCT_OFFSET (GstMultiFdSinkClass, remove_flush), NULL, NULL,
gst_tcp_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); gst_tcp_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
/** /**
@ -287,7 +306,7 @@ gst_multi_fd_sink_class_init (GstMultiFdSinkClass * klass)
gst_multi_fd_sink_signals[SIGNAL_GET_STATS] = gst_multi_fd_sink_signals[SIGNAL_GET_STATS] =
g_signal_new ("get-stats", G_TYPE_FROM_CLASS (klass), g_signal_new ("get-stats", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GstMultiHandleSinkClass, get_stats), NULL, NULL, G_STRUCT_OFFSET (GstMultiFdSinkClass, get_stats), NULL, NULL,
gst_tcp_marshal_BOXED__INT, GST_TYPE_STRUCTURE, 1, G_TYPE_INT); gst_tcp_marshal_BOXED__INT, GST_TYPE_STRUCTURE, 1, G_TYPE_INT);
/** /**
@ -299,11 +318,10 @@ gst_multi_fd_sink_class_init (GstMultiFdSinkClass * klass)
* be emitted from the streaming thread so application should be prepared * be emitted from the streaming thread so application should be prepared
* for that. * for that.
*/ */
gstmultihandlesink_class->signals[GST_MULTI_HANDLE_SIGNAL_CLIENT_ADDED] = gst_multi_fd_sink_signals[SIGNAL_CLIENT_ADDED] =
g_signal_new ("client-added", G_TYPE_FROM_CLASS (klass), g_signal_new ("client-added", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstMultiHandleSinkClass, G_SIGNAL_RUN_LAST, 0, NULL, NULL, gst_tcp_marshal_VOID__INT, G_TYPE_NONE,
client_added), NULL, NULL, gst_tcp_marshal_VOID__INT, G_TYPE_NONE, 1, 1, G_TYPE_INT);
G_TYPE_INT);
/** /**
* GstMultiFdSink::client-removed: * GstMultiFdSink::client-removed:
* @gstmultifdsink: the multifdsink element that emitted this signal * @gstmultifdsink: the multifdsink element that emitted this signal
@ -318,11 +336,9 @@ gst_multi_fd_sink_class_init (GstMultiFdSinkClass * klass)
* the get-stats signal from this callback. For the same reason it is * the get-stats signal from this callback. For the same reason it is
* not safe to close() and reuse @fd in this callback. * not safe to close() and reuse @fd in this callback.
*/ */
gstmultihandlesink_class->signals[GST_MULTI_HANDLE_SIGNAL_CLIENT_REMOVED] gst_multi_fd_sink_signals[SIGNAL_CLIENT_REMOVED] =
=
g_signal_new ("client-removed", G_TYPE_FROM_CLASS (klass), g_signal_new ("client-removed", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstMultiHandleSinkClass, G_SIGNAL_RUN_LAST, 0, NULL, NULL, gst_tcp_marshal_VOID__INT_ENUM,
client_removed), NULL, NULL, gst_tcp_marshal_VOID__INT_ENUM,
G_TYPE_NONE, 2, G_TYPE_INT, GST_TYPE_CLIENT_STATUS); G_TYPE_NONE, 2, G_TYPE_INT, GST_TYPE_CLIENT_STATUS);
/** /**
* GstMultiFdSink::client-fd-removed: * GstMultiFdSink::client-fd-removed:
@ -339,11 +355,10 @@ gst_multi_fd_sink_class_init (GstMultiFdSinkClass * klass)
* *
* Since: 0.10.7 * Since: 0.10.7
*/ */
gstmultihandlesink_class->signals /* FIXME: rename to client-fd-removed */
[GST_MULTI_HANDLE_SIGNAL_CLIENT_HANDLE_REMOVED] = gst_multi_fd_sink_signals[SIGNAL_CLIENT_HANDLE_REMOVED] =
g_signal_new ("client-handle-removed", G_TYPE_FROM_CLASS (klass), g_signal_new ("client-handle-removed", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstMultiHandleSinkClass, G_SIGNAL_RUN_LAST, 0, NULL, NULL, gst_tcp_marshal_VOID__INT,
client_handle_removed), NULL, NULL, gst_tcp_marshal_VOID__INT,
G_TYPE_NONE, 1, G_TYPE_INT); G_TYPE_NONE, 1, G_TYPE_INT);
gst_element_class_set_static_metadata (gstelement_class, gst_element_class_set_static_metadata (gstelement_class,
@ -352,6 +367,17 @@ gst_multi_fd_sink_class_init (GstMultiFdSinkClass * klass)
"Thomas Vander Stichele <thomas at apestaart dot org>, " "Thomas Vander Stichele <thomas at apestaart dot org>, "
"Wim Taymans <wim@fluendo.com>"); "Wim Taymans <wim@fluendo.com>");
klass->add = GST_DEBUG_FUNCPTR (gst_multi_fd_sink_add);
klass->add_full = GST_DEBUG_FUNCPTR (gst_multi_fd_sink_add_full);
klass->remove = GST_DEBUG_FUNCPTR (gst_multi_fd_sink_remove);
klass->remove_flush = GST_DEBUG_FUNCPTR (gst_multi_fd_sink_remove_flush);
klass->get_stats = GST_DEBUG_FUNCPTR (gst_multi_fd_sink_get_stats);
gstmultihandlesink_class->emit_client_added =
gst_multi_fd_sink_emit_client_added;
gstmultihandlesink_class->emit_client_removed =
gst_multi_fd_sink_emit_client_removed;
gstmultihandlesink_class->stop_pre = gstmultihandlesink_class->stop_pre =
GST_DEBUG_FUNCPTR (gst_multi_fd_sink_stop_pre); GST_DEBUG_FUNCPTR (gst_multi_fd_sink_stop_pre);
gstmultihandlesink_class->stop_post = gstmultihandlesink_class->stop_post =
@ -362,6 +388,7 @@ gst_multi_fd_sink_class_init (GstMultiFdSinkClass * klass)
GST_DEBUG_FUNCPTR (gst_multi_fd_sink_thread); GST_DEBUG_FUNCPTR (gst_multi_fd_sink_thread);
gstmultihandlesink_class->new_client = gstmultihandlesink_class->new_client =
GST_DEBUG_FUNCPTR (gst_multi_fd_sink_new_client); GST_DEBUG_FUNCPTR (gst_multi_fd_sink_new_client);
gstmultihandlesink_class->client_free = gst_multi_fd_sink_client_free;
gstmultihandlesink_class->client_get_fd = gstmultihandlesink_class->client_get_fd =
GST_DEBUG_FUNCPTR (gst_multi_fd_sink_client_get_fd); GST_DEBUG_FUNCPTR (gst_multi_fd_sink_client_get_fd);
gstmultihandlesink_class->handle_debug = gstmultihandlesink_class->handle_debug =
@ -388,6 +415,87 @@ gst_multi_fd_sink_init (GstMultiFdSink * this)
this->handle_read = DEFAULT_HANDLE_READ; this->handle_read = DEFAULT_HANDLE_READ;
} }
/* methods to emit signals */
static void
gst_multi_fd_sink_emit_client_added (GstMultiHandleSink * mhsink,
GstMultiSinkHandle handle)
{
g_signal_emit (mhsink, gst_multi_fd_sink_signals[SIGNAL_CLIENT_ADDED], 0,
handle.fd);
}
static void
gst_multi_fd_sink_emit_client_removed (GstMultiHandleSink * mhsink,
GstMultiSinkHandle handle, GstClientStatus status)
{
g_signal_emit (mhsink, gst_multi_fd_sink_signals[SIGNAL_CLIENT_REMOVED], 0,
handle.fd, status);
}
static void
gst_multi_fd_sink_client_free (GstMultiHandleSink * mhsink,
GstMultiHandleClient * client)
{
g_signal_emit (mhsink,
gst_multi_fd_sink_signals[SIGNAL_CLIENT_HANDLE_REMOVED], 0,
client->handle.fd);
}
/* action signals */
static void
gst_multi_fd_sink_add (GstMultiFdSink * sink, int fd)
{
GstMultiSinkHandle handle;
handle.fd = fd;
gst_multi_handle_sink_add (GST_MULTI_HANDLE_SINK_CAST (sink), handle);
}
static void
gst_multi_fd_sink_add_full (GstMultiFdSink * sink, int fd,
GstSyncMethod sync, GstFormat min_format, guint64 min_value,
GstFormat max_format, guint64 max_value)
{
GstMultiSinkHandle handle;
handle.fd = fd;
gst_multi_handle_sink_add_full (GST_MULTI_HANDLE_SINK_CAST (sink), handle,
sync, min_format, min_value, max_format, max_value);
}
static void
gst_multi_fd_sink_remove (GstMultiFdSink * sink, int fd)
{
GstMultiSinkHandle handle;
handle.fd = fd;
gst_multi_handle_sink_remove (GST_MULTI_HANDLE_SINK_CAST (sink), handle);
}
static void
gst_multi_fd_sink_remove_flush (GstMultiFdSink * sink, int fd)
{
GstMultiSinkHandle handle;
handle.fd = fd;
gst_multi_handle_sink_remove_flush (GST_MULTI_HANDLE_SINK_CAST (sink),
handle);
}
static GstStructure *
gst_multi_fd_sink_get_stats (GstMultiFdSink * sink, int fd)
{
GstMultiSinkHandle handle;
handle.fd = fd;
return gst_multi_handle_sink_get_stats (GST_MULTI_HANDLE_SINK_CAST (sink),
handle);
}
/* vfuncs */
static GstMultiHandleClient * static GstMultiHandleClient *
gst_multi_fd_sink_new_client (GstMultiHandleSink * mhsink, gst_multi_fd_sink_new_client (GstMultiHandleSink * mhsink,
GstMultiSinkHandle handle, GstSyncMethod sync_method) GstMultiSinkHandle handle, GstSyncMethod sync_method)

View file

@ -75,6 +75,13 @@ struct _GstMultiFdSinkClass {
GstMultiHandleSinkClass parent_class; GstMultiHandleSinkClass parent_class;
/* element methods */ /* element methods */
void (*add) (GstMultiFdSink *sink, int fd);
void (*add_full) (GstMultiFdSink *sink, int fd, GstSyncMethod sync,
GstFormat format, guint64 value,
GstFormat max_format, guint64 max_value);
void (*remove) (GstMultiFdSink *sink, int fd);
void (*remove_flush) (GstMultiFdSink *sink, int fd);
GstStructure* (*get_stats) (GstMultiFdSink *sink, int fd);
/* vtable */ /* vtable */
gboolean (*wait) (GstMultiFdSink *sink, GstPoll *set); gboolean (*wait) (GstMultiFdSink *sink, GstPoll *set);

View file

@ -474,12 +474,14 @@ gst_multi_handle_sink_class_init (GstMultiHandleSinkClass * klass)
klass->client_queue_buffer = klass->client_queue_buffer =
GST_DEBUG_FUNCPTR (gst_multi_handle_sink_client_queue_buffer); GST_DEBUG_FUNCPTR (gst_multi_handle_sink_client_queue_buffer);
#if 0
klass->add = GST_DEBUG_FUNCPTR (gst_multi_handle_sink_add); klass->add = GST_DEBUG_FUNCPTR (gst_multi_handle_sink_add);
klass->add_full = GST_DEBUG_FUNCPTR (gst_multi_handle_sink_add_full); klass->add_full = GST_DEBUG_FUNCPTR (gst_multi_handle_sink_add_full);
klass->remove = GST_DEBUG_FUNCPTR (gst_multi_handle_sink_remove); klass->remove = GST_DEBUG_FUNCPTR (gst_multi_handle_sink_remove);
klass->remove_flush = GST_DEBUG_FUNCPTR (gst_multi_handle_sink_remove_flush); klass->remove_flush = GST_DEBUG_FUNCPTR (gst_multi_handle_sink_remove_flush);
#endif
klass->clear = GST_DEBUG_FUNCPTR (gst_multi_handle_sink_clear); klass->clear = GST_DEBUG_FUNCPTR (gst_multi_handle_sink_clear);
klass->get_stats = GST_DEBUG_FUNCPTR (gst_multi_handle_sink_get_stats);
GST_DEBUG_CATEGORY_INIT (multihandlesink_debug, "multihandlesink", 0, GST_DEBUG_CATEGORY_INIT (multihandlesink_debug, "multihandlesink", 0,
"Multi socket sink"); "Multi socket sink");
@ -689,8 +691,7 @@ gst_multi_handle_sink_add_full (GstMultiHandleSink * sink,
CLIENTS_UNLOCK (sink); CLIENTS_UNLOCK (sink);
g_signal_emit (G_OBJECT (sink), mhsinkclass->emit_client_added (mhsink, handle);
mhsinkclass->signals[GST_MULTI_HANDLE_SIGNAL_CLIENT_ADDED], 0, handle);
return; return;
@ -707,9 +708,8 @@ duplicate:
{ {
CLIENTS_UNLOCK (sink); CLIENTS_UNLOCK (sink);
GST_WARNING_OBJECT (sink, "%s duplicate client found, refusing", debug); GST_WARNING_OBJECT (sink, "%s duplicate client found, refusing", debug);
g_signal_emit (G_OBJECT (sink), mhsinkclass->emit_client_removed (mhsink, handle,
mhsinkclass->signals[GST_MULTI_HANDLE_SIGNAL_CLIENT_REMOVED], 0, GST_CLIENT_STATUS_DUPLICATE);
handle, GST_CLIENT_STATUS_DUPLICATE);
return; return;
} }
} }
@ -977,9 +977,7 @@ gst_multi_handle_sink_remove_client_link (GstMultiHandleSink * sink,
* might query some properties */ * might query some properties */
CLIENTS_UNLOCK (sink); CLIENTS_UNLOCK (sink);
g_signal_emit (G_OBJECT (sink), mhsinkclass->emit_client_removed (sink, mhclient->handle, mhclient->status);
mhsinkclass->signals[GST_MULTI_HANDLE_SIGNAL_CLIENT_REMOVED], 0,
mhclient->handle, mhclient->status);
/* lock again before we remove the client completely */ /* lock again before we remove the client completely */
CLIENTS_LOCK (sink); CLIENTS_LOCK (sink);
@ -1004,13 +1002,12 @@ gst_multi_handle_sink_remove_client_link (GstMultiHandleSink * sink,
CLIENTS_UNLOCK (sink); CLIENTS_UNLOCK (sink);
/* and the handle is really gone now */ /* sub-class must implement this to emit the client-$handle-removed signal */
g_signal_emit (G_OBJECT (sink), g_assert (mhsinkclass->client_free != NULL);
mhsinkclass->signals[GST_MULTI_HANDLE_SIGNAL_CLIENT_HANDLE_REMOVED],
0, mhclient->handle); /* and the handle is really gone now */
mhsinkclass->client_free (sink, mhclient);
if (mhsinkclass->client_free)
mhsinkclass->client_free (mhclient);
g_free (mhclient); g_free (mhclient);
CLIENTS_LOCK (sink); CLIENTS_LOCK (sink);

View file

@ -34,6 +34,7 @@ G_BEGIN_DECLS
(gst_multi_handle_sink_get_type()) (gst_multi_handle_sink_get_type())
#define GST_MULTI_HANDLE_SINK(obj) \ #define GST_MULTI_HANDLE_SINK(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MULTI_HANDLE_SINK,GstMultiHandleSink)) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MULTI_HANDLE_SINK,GstMultiHandleSink))
#define GST_MULTI_HANDLE_SINK_CAST(obj) ((GstMultiHandleSink *)(obj))
#define GST_MULTI_HANDLE_SINK_CLASS(klass) \ #define GST_MULTI_HANDLE_SINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MULTI_HANDLE_SINK,GstMultiHandleSinkClass)) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MULTI_HANDLE_SINK,GstMultiHandleSinkClass))
#define GST_IS_MULTI_HANDLE_SINK(obj) \ #define GST_IS_MULTI_HANDLE_SINK(obj) \
@ -238,31 +239,10 @@ struct _GstMultiHandleSink {
gint time_queued; /* number of queued time */ gint time_queued; /* number of queued time */
}; };
/* MultiHandleSink signals implemented in base class and declared
* in subclass
*/
enum
{
/* signals */
GST_MULTI_HANDLE_SIGNAL_CLIENT_ADDED,
GST_MULTI_HANDLE_SIGNAL_CLIENT_REMOVED,
GST_MULTI_HANDLE_SIGNAL_CLIENT_HANDLE_REMOVED,
GST_MULTI_HANDLE_LAST_SIGNAL
};
struct _GstMultiHandleSinkClass { struct _GstMultiHandleSinkClass {
GstBaseSinkClass parent_class; GstBaseSinkClass parent_class;
/* element methods */ /* methods */
void (*add) (GstMultiHandleSink *sink, GstMultiSinkHandle handle);
void (*add_full) (GstMultiHandleSink *sink, GstMultiSinkHandle handle, GstSyncMethod sync,
GstFormat format, guint64 value,
GstFormat max_format, guint64 max_value);
void (*remove) (GstMultiHandleSink *sink, GstMultiSinkHandle handle);
void (*remove_flush) (GstMultiHandleSink *sink, GstMultiSinkHandle handle);
void (*clear) (GstMultiHandleSink *sink); void (*clear) (GstMultiHandleSink *sink);
void (*stop_pre) (GstMultiHandleSink *sink); void (*stop_pre) (GstMultiHandleSink *sink);
void (*stop_post) (GstMultiHandleSink *sink); void (*stop_post) (GstMultiHandleSink *sink);
@ -275,8 +255,8 @@ struct _GstMultiHandleSinkClass {
GstBuffer *buffer); GstBuffer *buffer);
int (*client_get_fd) int (*client_get_fd)
(GstMultiHandleClient *client); (GstMultiHandleClient *client);
void (*client_free) void (*client_free) (GstMultiHandleSink *mhsink,
(GstMultiHandleClient *client); GstMultiHandleClient *client);
void (*handle_debug) (GstMultiSinkHandle handle, gchar debug[30]); void (*handle_debug) (GstMultiSinkHandle handle, gchar debug[30]);
gpointer (*handle_hash_key) (GstMultiSinkHandle handle); gpointer (*handle_hash_key) (GstMultiSinkHandle handle);
/* called when the client hash/list has been changed */ /* called when the client hash/list has been changed */
@ -286,26 +266,20 @@ struct _GstMultiHandleSinkClass {
GstMultiHandleClient* (*new_client) (GstMultiHandleSink *mhsink, GstMultiSinkHandle handle, GstSyncMethod sync_method); GstMultiHandleClient* (*new_client) (GstMultiHandleSink *mhsink, GstMultiSinkHandle handle, GstSyncMethod sync_method);
GstStructure* (*get_stats) (GstMultiHandleSink *sink, GstMultiSinkHandle handle);
/* vtable */ /* vtable */
gboolean (*init) (GstMultiHandleSink *sink); gboolean (*init) (GstMultiHandleSink *sink);
gboolean (*close) (GstMultiHandleSink *sink); gboolean (*close) (GstMultiHandleSink *sink);
void (*removed) (GstMultiHandleSink *sink, GstMultiSinkHandle handle); void (*removed) (GstMultiHandleSink *sink, GstMultiSinkHandle handle);
/* signals */ /* subclass needs to emit these because actual argument size (int/pointer) differs */
void (*client_added) (GstElement *element, GstMultiSinkHandle handle); void (*emit_client_added) (GstMultiHandleSink *mhsink, GstMultiSinkHandle handle);
void (*client_removed) (GstElement *element, GstMultiSinkHandle handle, GstClientStatus status); void (*emit_client_removed) (GstMultiHandleSink *mhsink, GstMultiSinkHandle handle, GstClientStatus status);
void (*client_handle_removed) (GstElement *element, GstMultiSinkHandle handle);
guint signals[GST_MULTI_HANDLE_LAST_SIGNAL];
}; };
GType gst_multi_handle_sink_get_type (void); GType gst_multi_handle_sink_get_type (void);
void gst_multi_handle_sink_add (GstMultiHandleSink *sink, GstMultiSinkHandle); void gst_multi_handle_sink_add (GstMultiHandleSink *sink, GstMultiSinkHandle handle);
void gst_multi_handle_sink_add_full (GstMultiHandleSink *sink, GstMultiSinkHandle, GstSyncMethod sync, void gst_multi_handle_sink_add_full (GstMultiHandleSink *sink, GstMultiSinkHandle handle, GstSyncMethod sync,
GstFormat min_format, guint64 min_value, GstFormat min_format, guint64 min_value,
GstFormat max_format, guint64 max_value); GstFormat max_format, guint64 max_value);
void gst_multi_handle_sink_remove (GstMultiHandleSink *sink, GstMultiSinkHandle handle); void gst_multi_handle_sink_remove (GstMultiHandleSink *sink, GstMultiSinkHandle handle);

View file

@ -131,6 +131,9 @@ enum
SIGNAL_GET_STATS, SIGNAL_GET_STATS,
/* signals */ /* signals */
SIGNAL_CLIENT_ADDED,
SIGNAL_CLIENT_REMOVED,
SIGNAL_CLIENT_HANDLE_REMOVED,
LAST_SIGNAL LAST_SIGNAL
}; };
@ -144,6 +147,23 @@ enum
static void gst_multi_socket_sink_finalize (GObject * object); static void gst_multi_socket_sink_finalize (GObject * object);
static void gst_multi_socket_sink_add (GstMultiSocketSink * sink,
GSocket * socket);
static void gst_multi_socket_sink_add_full (GstMultiSocketSink * sink,
GSocket * socket, GstSyncMethod sync, GstFormat min_format,
guint64 min_value, GstFormat max_format, guint64 max_value);
static void gst_multi_socket_sink_remove (GstMultiSocketSink * sink,
GSocket * socket);
static void gst_multi_socket_sink_remove_flush (GstMultiSocketSink * sink,
GSocket * socket);
static GstStructure *gst_multi_socket_sink_get_stats (GstMultiSocketSink * sink,
GSocket * socket);
static void gst_multi_socket_sink_emit_client_added (GstMultiHandleSink * mhs,
GstMultiSinkHandle handle);
static void gst_multi_socket_sink_emit_client_removed (GstMultiHandleSink * mhs,
GstMultiSinkHandle handle, GstClientStatus status);
static void gst_multi_socket_sink_stop_pre (GstMultiHandleSink * mhsink); static void gst_multi_socket_sink_stop_pre (GstMultiHandleSink * mhsink);
static void gst_multi_socket_sink_stop_post (GstMultiHandleSink * mhsink); static void gst_multi_socket_sink_stop_post (GstMultiHandleSink * mhsink);
static gboolean gst_multi_socket_sink_start_pre (GstMultiHandleSink * mhsink); static gboolean gst_multi_socket_sink_start_pre (GstMultiHandleSink * mhsink);
@ -152,7 +172,8 @@ static GstMultiHandleClient
* gst_multi_socket_sink_new_client (GstMultiHandleSink * mhsink, * gst_multi_socket_sink_new_client (GstMultiHandleSink * mhsink,
GstMultiSinkHandle handle, GstSyncMethod sync_method); GstMultiSinkHandle handle, GstSyncMethod sync_method);
static int gst_multi_socket_sink_client_get_fd (GstMultiHandleClient * client); static int gst_multi_socket_sink_client_get_fd (GstMultiHandleClient * client);
static void gst_multi_socket_sink_client_free (GstMultiHandleClient * client); static void gst_multi_socket_sink_client_free (GstMultiHandleSink * mhsink,
GstMultiHandleClient * client);
static void gst_multi_socket_sink_handle_debug (GstMultiSinkHandle handle, static void gst_multi_socket_sink_handle_debug (GstMultiSinkHandle handle,
gchar debug[30]); gchar debug[30]);
@ -207,7 +228,7 @@ gst_multi_socket_sink_class_init (GstMultiSocketSinkClass * klass)
gst_multi_socket_sink_signals[SIGNAL_ADD] = gst_multi_socket_sink_signals[SIGNAL_ADD] =
g_signal_new ("add", G_TYPE_FROM_CLASS (klass), g_signal_new ("add", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GstMultiHandleSinkClass, add), NULL, NULL, G_STRUCT_OFFSET (GstMultiSocketSinkClass, add), NULL, NULL,
g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_SOCKET); g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_SOCKET);
/** /**
* GstMultiSocketSink::add-full: * GstMultiSocketSink::add-full:
@ -227,7 +248,7 @@ gst_multi_socket_sink_class_init (GstMultiSocketSinkClass * klass)
gst_multi_socket_sink_signals[SIGNAL_ADD_BURST] = gst_multi_socket_sink_signals[SIGNAL_ADD_BURST] =
g_signal_new ("add-full", G_TYPE_FROM_CLASS (klass), g_signal_new ("add-full", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GstMultiHandleSinkClass, add_full), NULL, NULL, G_STRUCT_OFFSET (GstMultiSocketSinkClass, add_full), NULL, NULL,
gst_tcp_marshal_VOID__OBJECT_ENUM_ENUM_UINT64_ENUM_UINT64, G_TYPE_NONE, 6, gst_tcp_marshal_VOID__OBJECT_ENUM_ENUM_UINT64_ENUM_UINT64, G_TYPE_NONE, 6,
G_TYPE_SOCKET, GST_TYPE_SYNC_METHOD, GST_TYPE_FORMAT, G_TYPE_UINT64, G_TYPE_SOCKET, GST_TYPE_SYNC_METHOD, GST_TYPE_FORMAT, G_TYPE_UINT64,
GST_TYPE_FORMAT, G_TYPE_UINT64); GST_TYPE_FORMAT, G_TYPE_UINT64);
@ -241,7 +262,7 @@ gst_multi_socket_sink_class_init (GstMultiSocketSinkClass * klass)
gst_multi_socket_sink_signals[SIGNAL_REMOVE] = gst_multi_socket_sink_signals[SIGNAL_REMOVE] =
g_signal_new ("remove", G_TYPE_FROM_CLASS (klass), g_signal_new ("remove", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GstMultiHandleSinkClass, remove), NULL, NULL, G_STRUCT_OFFSET (GstMultiSocketSinkClass, remove), NULL, NULL,
g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_SOCKET); g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_SOCKET);
/** /**
* GstMultiSocketSink::remove-flush: * GstMultiSocketSink::remove-flush:
@ -254,7 +275,7 @@ gst_multi_socket_sink_class_init (GstMultiSocketSinkClass * klass)
gst_multi_socket_sink_signals[SIGNAL_REMOVE_FLUSH] = gst_multi_socket_sink_signals[SIGNAL_REMOVE_FLUSH] =
g_signal_new ("remove-flush", G_TYPE_FROM_CLASS (klass), g_signal_new ("remove-flush", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GstMultiHandleSinkClass, remove_flush), NULL, NULL, G_STRUCT_OFFSET (GstMultiSocketSinkClass, remove_flush), NULL, NULL,
g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_SOCKET); g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_SOCKET);
/** /**
@ -274,7 +295,7 @@ gst_multi_socket_sink_class_init (GstMultiSocketSinkClass * klass)
gst_multi_socket_sink_signals[SIGNAL_GET_STATS] = gst_multi_socket_sink_signals[SIGNAL_GET_STATS] =
g_signal_new ("get-stats", G_TYPE_FROM_CLASS (klass), g_signal_new ("get-stats", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (GstMultiHandleSinkClass, get_stats), NULL, NULL, G_STRUCT_OFFSET (GstMultiSocketSinkClass, get_stats), NULL, NULL,
gst_tcp_marshal_BOXED__OBJECT, GST_TYPE_STRUCTURE, 1, G_TYPE_SOCKET); gst_tcp_marshal_BOXED__OBJECT, GST_TYPE_STRUCTURE, 1, G_TYPE_SOCKET);
/** /**
@ -286,10 +307,9 @@ gst_multi_socket_sink_class_init (GstMultiSocketSinkClass * klass)
* be emitted from the streaming thread so application should be prepared * be emitted from the streaming thread so application should be prepared
* for that. * for that.
*/ */
gstmultihandlesink_class->signals[GST_MULTI_HANDLE_SIGNAL_CLIENT_ADDED] = gst_multi_socket_sink_signals[SIGNAL_CLIENT_ADDED] =
g_signal_new ("client-added", G_TYPE_FROM_CLASS (klass), g_signal_new ("client-added", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstMultiHandleSinkClass, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
client_added), NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, G_TYPE_OBJECT); G_TYPE_NONE, 1, G_TYPE_OBJECT);
/** /**
* GstMultiSocketSink::client-removed: * GstMultiSocketSink::client-removed:
@ -305,11 +325,9 @@ gst_multi_socket_sink_class_init (GstMultiSocketSinkClass * klass)
* the get-stats signal from this callback. For the same reason it is * the get-stats signal from this callback. For the same reason it is
* not safe to close() and reuse @socket in this callback. * not safe to close() and reuse @socket in this callback.
*/ */
gstmultihandlesink_class->signals[GST_MULTI_HANDLE_SIGNAL_CLIENT_REMOVED] gst_multi_socket_sink_signals[SIGNAL_CLIENT_REMOVED] =
=
g_signal_new ("client-removed", G_TYPE_FROM_CLASS (klass), g_signal_new ("client-removed", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstMultiHandleSinkClass, G_SIGNAL_RUN_LAST, 0, NULL, NULL, gst_tcp_marshal_VOID__OBJECT_ENUM,
client_removed), NULL, NULL, gst_tcp_marshal_VOID__OBJECT_ENUM,
G_TYPE_NONE, 2, G_TYPE_INT, GST_TYPE_CLIENT_STATUS); G_TYPE_NONE, 2, G_TYPE_INT, GST_TYPE_CLIENT_STATUS);
/** /**
* GstMultiSocketSink::client-socket-removed: * GstMultiSocketSink::client-socket-removed:
@ -326,11 +344,10 @@ gst_multi_socket_sink_class_init (GstMultiSocketSinkClass * klass)
* *
* Since: 0.10.7 * Since: 0.10.7
*/ */
gstmultihandlesink_class->signals /* FIXME: rename to client-socket-removed */
[GST_MULTI_HANDLE_SIGNAL_CLIENT_HANDLE_REMOVED] = gst_multi_socket_sink_signals[SIGNAL_CLIENT_HANDLE_REMOVED] =
g_signal_new ("client-handle-removed", G_TYPE_FROM_CLASS (klass), g_signal_new ("client-handle-removed", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstMultiHandleSinkClass, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
client_handle_removed), NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, G_TYPE_SOCKET); G_TYPE_NONE, 1, G_TYPE_SOCKET);
gst_element_class_set_static_metadata (gstelement_class, gst_element_class_set_static_metadata (gstelement_class,
@ -344,6 +361,17 @@ gst_multi_socket_sink_class_init (GstMultiSocketSinkClass * klass)
gstbasesink_class->unlock_stop = gstbasesink_class->unlock_stop =
GST_DEBUG_FUNCPTR (gst_multi_socket_sink_unlock_stop); GST_DEBUG_FUNCPTR (gst_multi_socket_sink_unlock_stop);
klass->add = GST_DEBUG_FUNCPTR (gst_multi_socket_sink_add);
klass->add_full = GST_DEBUG_FUNCPTR (gst_multi_socket_sink_add_full);
klass->remove = GST_DEBUG_FUNCPTR (gst_multi_socket_sink_remove);
klass->remove_flush = GST_DEBUG_FUNCPTR (gst_multi_socket_sink_remove_flush);
klass->get_stats = GST_DEBUG_FUNCPTR (gst_multi_socket_sink_get_stats);
gstmultihandlesink_class->emit_client_added =
gst_multi_socket_sink_emit_client_added;
gstmultihandlesink_class->emit_client_removed =
gst_multi_socket_sink_emit_client_removed;
gstmultihandlesink_class->stop_pre = gstmultihandlesink_class->stop_pre =
GST_DEBUG_FUNCPTR (gst_multi_socket_sink_stop_pre); GST_DEBUG_FUNCPTR (gst_multi_socket_sink_stop_pre);
gstmultihandlesink_class->stop_post = gstmultihandlesink_class->stop_post =
@ -394,6 +422,76 @@ gst_multi_socket_sink_finalize (GObject * object)
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (parent_class)->finalize (object);
} }
/* methods to emit signals */
static void
gst_multi_socket_sink_emit_client_added (GstMultiHandleSink * mhsink,
GstMultiSinkHandle handle)
{
g_signal_emit (mhsink, gst_multi_socket_sink_signals[SIGNAL_CLIENT_ADDED], 0,
handle.socket);
}
static void
gst_multi_socket_sink_emit_client_removed (GstMultiHandleSink * mhsink,
GstMultiSinkHandle handle, GstClientStatus status)
{
g_signal_emit (mhsink, gst_multi_socket_sink_signals[SIGNAL_CLIENT_REMOVED],
0, handle.socket, status);
}
/* action signals */
static void
gst_multi_socket_sink_add (GstMultiSocketSink * sink, GSocket * socket)
{
GstMultiSinkHandle handle;
handle.socket = socket;
gst_multi_handle_sink_add (GST_MULTI_HANDLE_SINK_CAST (sink), handle);
}
static void
gst_multi_socket_sink_add_full (GstMultiSocketSink * sink, GSocket * socket,
GstSyncMethod sync, GstFormat min_format, guint64 min_value,
GstFormat max_format, guint64 max_value)
{
GstMultiSinkHandle handle;
handle.socket = socket;
gst_multi_handle_sink_add_full (GST_MULTI_HANDLE_SINK_CAST (sink), handle,
sync, min_format, min_value, max_format, max_value);
}
static void
gst_multi_socket_sink_remove (GstMultiSocketSink * sink, GSocket * socket)
{
GstMultiSinkHandle handle;
handle.socket = socket;
gst_multi_handle_sink_remove (GST_MULTI_HANDLE_SINK_CAST (sink), handle);
}
static void
gst_multi_socket_sink_remove_flush (GstMultiSocketSink * sink, GSocket * socket)
{
GstMultiSinkHandle handle;
handle.socket = socket;
gst_multi_handle_sink_remove_flush (GST_MULTI_HANDLE_SINK_CAST (sink),
handle);
}
static GstStructure *
gst_multi_socket_sink_get_stats (GstMultiSocketSink * sink, GSocket * socket)
{
GstMultiSinkHandle handle;
handle.socket = socket;
return gst_multi_handle_sink_get_stats (GST_MULTI_HANDLE_SINK_CAST (sink),
handle);
}
static GstMultiHandleClient * static GstMultiHandleClient *
gst_multi_socket_sink_new_client (GstMultiHandleSink * mhsink, gst_multi_socket_sink_new_client (GstMultiHandleSink * mhsink,
GstMultiSinkHandle handle, GstSyncMethod sync_method) GstMultiSinkHandle handle, GstSyncMethod sync_method)
@ -431,9 +529,15 @@ gst_multi_socket_sink_client_get_fd (GstMultiHandleClient * client)
} }
static void static void
gst_multi_socket_sink_client_free (GstMultiHandleClient * client) gst_multi_socket_sink_client_free (GstMultiHandleSink * mhsink,
GstMultiHandleClient * client)
{ {
g_assert (G_IS_SOCKET (client->handle.socket)); g_assert (G_IS_SOCKET (client->handle.socket));
g_signal_emit (mhsink,
gst_multi_socket_sink_signals[SIGNAL_CLIENT_HANDLE_REMOVED], 0,
client->handle.socket);
g_object_unref (client->handle.socket); g_object_unref (client->handle.socket);
} }

View file

@ -75,6 +75,14 @@ struct _GstMultiSocketSinkClass {
GstMultiHandleSinkClass parent_class; GstMultiHandleSinkClass parent_class;
/* element methods */ /* element methods */
void (*add) (GstMultiSocketSink *sink, GSocket *socket);
void (*add_full) (GstMultiSocketSink *sink, GSocket *socket,
GstSyncMethod sync,
GstFormat format, guint64 value,
GstFormat max_format, guint64 max_value);
void (*remove) (GstMultiSocketSink *sink, GSocket *socket);
void (*remove_flush) (GstMultiSocketSink *sink, GSocket *socket);
GstStructure* (*get_stats) (GstMultiSocketSink *sink, GSocket *socket);
/* signals */ /* signals */
}; };