multifdsink, multisocketsink: fix broken action signal setup
authorTim-Philipp Müller <tim@centricular.net>
Sun, 9 Sep 2012 00:20:38 +0000 (01:20 +0100)
committerTim-Philipp Müller <tim@centricular.net>
Sun, 9 Sep 2012 00:57:59 +0000 (01:57 +0100)
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).

gst/tcp/gstmultifdsink.c
gst/tcp/gstmultifdsink.h
gst/tcp/gstmultihandlesink.c
gst/tcp/gstmultihandlesink.h
gst/tcp/gstmultisocketsink.c
gst/tcp/gstmultisocketsink.h

index ffecee1..43aed79 100644 (file)
@@ -140,6 +140,9 @@ enum
   SIGNAL_GET_STATS,
 
   /* signals */
+  SIGNAL_CLIENT_ADDED,
+  SIGNAL_CLIENT_REMOVED,
+  SIGNAL_CLIENT_HANDLE_REMOVED,
 
   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 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 *
     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 void gst_multi_fd_sink_handle_debug (GstMultiSinkHandle handle,
     gchar debug[30]);
@@ -218,7 +237,7 @@ gst_multi_fd_sink_class_init (GstMultiFdSinkClass * klass)
   gst_multi_fd_sink_signals[SIGNAL_ADD] =
       g_signal_new ("add", G_TYPE_FROM_CLASS (klass),
       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);
   /**
    * GstMultiFdSink::add-full:
@@ -238,7 +257,7 @@ gst_multi_fd_sink_class_init (GstMultiFdSinkClass * klass)
   gst_multi_fd_sink_signals[SIGNAL_ADD_BURST] =
       g_signal_new ("add-full", G_TYPE_FROM_CLASS (klass),
       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,
       G_TYPE_INT, GST_TYPE_SYNC_METHOD, 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] =
       g_signal_new ("remove", G_TYPE_FROM_CLASS (klass),
       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);
   /**
    * GstMultiFdSink::remove-flush:
@@ -265,7 +284,7 @@ gst_multi_fd_sink_class_init (GstMultiFdSinkClass * klass)
   gst_multi_fd_sink_signals[SIGNAL_REMOVE_FLUSH] =
       g_signal_new ("remove-flush", G_TYPE_FROM_CLASS (klass),
       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);
 
   /**
@@ -287,7 +306,7 @@ gst_multi_fd_sink_class_init (GstMultiFdSinkClass * klass)
   gst_multi_fd_sink_signals[SIGNAL_GET_STATS] =
       g_signal_new ("get-stats", G_TYPE_FROM_CLASS (klass),
       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);
 
   /**
@@ -299,11 +318,10 @@ gst_multi_fd_sink_class_init (GstMultiFdSinkClass * klass)
    * be emitted from the streaming thread so application should be prepared
    * 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_RUN_LAST, G_STRUCT_OFFSET (GstMultiHandleSinkClass,
-          client_added), NULL, NULL, gst_tcp_marshal_VOID__INT, G_TYPE_NONE, 1,
-      G_TYPE_INT);
+      G_SIGNAL_RUN_LAST, 0, NULL, NULL, gst_tcp_marshal_VOID__INT, G_TYPE_NONE,
+      1, G_TYPE_INT);
   /**
    * GstMultiFdSink::client-removed:
    * @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
    * 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_RUN_LAST, G_STRUCT_OFFSET (GstMultiHandleSinkClass,
-          client_removed), NULL, NULL, gst_tcp_marshal_VOID__INT_ENUM,
+      G_SIGNAL_RUN_LAST, 0, NULL, NULL, gst_tcp_marshal_VOID__INT_ENUM,
       G_TYPE_NONE, 2, G_TYPE_INT, GST_TYPE_CLIENT_STATUS);
   /**
    * GstMultiFdSink::client-fd-removed:
@@ -339,11 +355,10 @@ gst_multi_fd_sink_class_init (GstMultiFdSinkClass * klass)
    *
    * Since: 0.10.7
    */
-  gstmultihandlesink_class->signals
-      [GST_MULTI_HANDLE_SIGNAL_CLIENT_HANDLE_REMOVED] =
+  /* FIXME: rename to client-fd-removed */
+  gst_multi_fd_sink_signals[SIGNAL_CLIENT_HANDLE_REMOVED] =
       g_signal_new ("client-handle-removed", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstMultiHandleSinkClass,
-          client_handle_removed), NULL, NULL, gst_tcp_marshal_VOID__INT,
+      G_SIGNAL_RUN_LAST, 0, NULL, NULL, gst_tcp_marshal_VOID__INT,
       G_TYPE_NONE, 1, G_TYPE_INT);
 
   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>, "
       "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 =
       GST_DEBUG_FUNCPTR (gst_multi_fd_sink_stop_pre);
   gstmultihandlesink_class->stop_post =
@@ -362,6 +388,7 @@ gst_multi_fd_sink_class_init (GstMultiFdSinkClass * klass)
       GST_DEBUG_FUNCPTR (gst_multi_fd_sink_thread);
   gstmultihandlesink_class->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 =
       GST_DEBUG_FUNCPTR (gst_multi_fd_sink_client_get_fd);
   gstmultihandlesink_class->handle_debug =
@@ -388,6 +415,87 @@ gst_multi_fd_sink_init (GstMultiFdSink * this)
   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 *
 gst_multi_fd_sink_new_client (GstMultiHandleSink * mhsink,
     GstMultiSinkHandle handle, GstSyncMethod sync_method)
index f479652..88b8486 100644 (file)
@@ -75,6 +75,13 @@ struct _GstMultiFdSinkClass {
   GstMultiHandleSinkClass parent_class;
 
   /* 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 */
   gboolean (*wait)   (GstMultiFdSink *sink, GstPoll *set);
index b9e1097..973729b 100644 (file)
@@ -474,12 +474,14 @@ gst_multi_handle_sink_class_init (GstMultiHandleSinkClass * klass)
   klass->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_full = GST_DEBUG_FUNCPTR (gst_multi_handle_sink_add_full);
   klass->remove = GST_DEBUG_FUNCPTR (gst_multi_handle_sink_remove);
   klass->remove_flush = GST_DEBUG_FUNCPTR (gst_multi_handle_sink_remove_flush);
+#endif
+
   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,
       "Multi socket sink");
@@ -689,8 +691,7 @@ gst_multi_handle_sink_add_full (GstMultiHandleSink * sink,
 
   CLIENTS_UNLOCK (sink);
 
-  g_signal_emit (G_OBJECT (sink),
-      mhsinkclass->signals[GST_MULTI_HANDLE_SIGNAL_CLIENT_ADDED], 0, handle);
+  mhsinkclass->emit_client_added (mhsink, handle);
 
   return;
 
@@ -707,9 +708,8 @@ duplicate:
   {
     CLIENTS_UNLOCK (sink);
     GST_WARNING_OBJECT (sink, "%s duplicate client found, refusing", debug);
-    g_signal_emit (G_OBJECT (sink),
-        mhsinkclass->signals[GST_MULTI_HANDLE_SIGNAL_CLIENT_REMOVED], 0,
-        handle, GST_CLIENT_STATUS_DUPLICATE);
+    mhsinkclass->emit_client_removed (mhsink, handle,
+        GST_CLIENT_STATUS_DUPLICATE);
     return;
   }
 }
@@ -977,9 +977,7 @@ gst_multi_handle_sink_remove_client_link (GstMultiHandleSink * sink,
    * might query some properties */
   CLIENTS_UNLOCK (sink);
 
-  g_signal_emit (G_OBJECT (sink),
-      mhsinkclass->signals[GST_MULTI_HANDLE_SIGNAL_CLIENT_REMOVED], 0,
-      mhclient->handle, mhclient->status);
+  mhsinkclass->emit_client_removed (sink, mhclient->handle, mhclient->status);
 
   /* lock again before we remove the client completely */
   CLIENTS_LOCK (sink);
@@ -1004,13 +1002,12 @@ gst_multi_handle_sink_remove_client_link (GstMultiHandleSink * sink,
 
   CLIENTS_UNLOCK (sink);
 
+  /* sub-class must implement this to emit the client-$handle-removed signal */
+  g_assert (mhsinkclass->client_free != NULL);
+
   /* and the handle is really gone now */
-  g_signal_emit (G_OBJECT (sink),
-      mhsinkclass->signals[GST_MULTI_HANDLE_SIGNAL_CLIENT_HANDLE_REMOVED],
-      0, mhclient->handle);
+  mhsinkclass->client_free (sink, mhclient);
 
-  if (mhsinkclass->client_free)
-    mhsinkclass->client_free (mhclient);
   g_free (mhclient);
 
   CLIENTS_LOCK (sink);
index 7c2bac1..56c6798 100644 (file)
@@ -34,6 +34,7 @@ G_BEGIN_DECLS
   (gst_multi_handle_sink_get_type())
 #define GST_MULTI_HANDLE_SINK(obj) \
   (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) \
   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MULTI_HANDLE_SINK,GstMultiHandleSinkClass))
 #define GST_IS_MULTI_HANDLE_SINK(obj) \
@@ -238,31 +239,10 @@ struct _GstMultiHandleSink {
   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 {
   GstBaseSinkClass parent_class;
 
-  /* element 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);
-
+  /* methods */
   void          (*clear)        (GstMultiHandleSink *sink);
   void          (*stop_pre)     (GstMultiHandleSink *sink);
   void          (*stop_post)    (GstMultiHandleSink *sink);
@@ -275,8 +255,8 @@ struct _GstMultiHandleSinkClass {
                                  GstBuffer *buffer);
   int           (*client_get_fd)
                                 (GstMultiHandleClient *client);
-  void          (*client_free)
-                                (GstMultiHandleClient *client);
+  void          (*client_free)  (GstMultiHandleSink   *mhsink,
+                                 GstMultiHandleClient *client);
   void          (*handle_debug) (GstMultiSinkHandle handle, gchar debug[30]);
   gpointer      (*handle_hash_key)  (GstMultiSinkHandle handle);
   /* 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);
 
 
-  GstStructure* (*get_stats)    (GstMultiHandleSink *sink, GstMultiSinkHandle handle);
-
-
   /* vtable */
   gboolean (*init)   (GstMultiHandleSink *sink);
   gboolean (*close)  (GstMultiHandleSink *sink);
   void (*removed) (GstMultiHandleSink *sink, GstMultiSinkHandle handle);
 
-  /* signals */
-  void (*client_added) (GstElement *element, GstMultiSinkHandle handle);
-  void (*client_removed) (GstElement *element, GstMultiSinkHandle handle, GstClientStatus status);
-  void (*client_handle_removed) (GstElement *element, GstMultiSinkHandle handle);
-
-  guint signals[GST_MULTI_HANDLE_LAST_SIGNAL];
+  /* subclass needs to emit these because actual argument size (int/pointer) differs */
+  void (*emit_client_added)          (GstMultiHandleSink *mhsink, GstMultiSinkHandle handle);
+  void (*emit_client_removed)        (GstMultiHandleSink *mhsink, GstMultiSinkHandle handle, GstClientStatus status);
 };
 
 GType gst_multi_handle_sink_get_type (void);
 
-void          gst_multi_handle_sink_add          (GstMultiHandleSink *sink, GstMultiSinkHandle);
-void          gst_multi_handle_sink_add_full     (GstMultiHandleSink *sink, GstMultiSinkHandle, GstSyncMethod sync, 
+void          gst_multi_handle_sink_add          (GstMultiHandleSink *sink, GstMultiSinkHandle handle);
+void          gst_multi_handle_sink_add_full     (GstMultiHandleSink *sink, GstMultiSinkHandle handle, GstSyncMethod sync,
                                               GstFormat min_format, guint64 min_value,
                                               GstFormat max_format, guint64 max_value);
 void          gst_multi_handle_sink_remove       (GstMultiHandleSink *sink, GstMultiSinkHandle handle);
index 2aac825..e395501 100644 (file)
@@ -131,6 +131,9 @@ enum
   SIGNAL_GET_STATS,
 
   /* signals */
+  SIGNAL_CLIENT_ADDED,
+  SIGNAL_CLIENT_REMOVED,
+  SIGNAL_CLIENT_HANDLE_REMOVED,
 
   LAST_SIGNAL
 };
@@ -144,6 +147,23 @@ enum
 
 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_post (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,
     GstMultiSinkHandle handle, GstSyncMethod sync_method);
 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,
     gchar debug[30]);
 
@@ -207,7 +228,7 @@ gst_multi_socket_sink_class_init (GstMultiSocketSinkClass * klass)
   gst_multi_socket_sink_signals[SIGNAL_ADD] =
       g_signal_new ("add", G_TYPE_FROM_CLASS (klass),
       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);
   /**
    * GstMultiSocketSink::add-full:
@@ -227,7 +248,7 @@ gst_multi_socket_sink_class_init (GstMultiSocketSinkClass * klass)
   gst_multi_socket_sink_signals[SIGNAL_ADD_BURST] =
       g_signal_new ("add-full", G_TYPE_FROM_CLASS (klass),
       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,
       G_TYPE_SOCKET, GST_TYPE_SYNC_METHOD, 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] =
       g_signal_new ("remove", G_TYPE_FROM_CLASS (klass),
       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);
   /**
    * GstMultiSocketSink::remove-flush:
@@ -254,7 +275,7 @@ gst_multi_socket_sink_class_init (GstMultiSocketSinkClass * klass)
   gst_multi_socket_sink_signals[SIGNAL_REMOVE_FLUSH] =
       g_signal_new ("remove-flush", G_TYPE_FROM_CLASS (klass),
       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);
 
   /**
@@ -274,7 +295,7 @@ gst_multi_socket_sink_class_init (GstMultiSocketSinkClass * klass)
   gst_multi_socket_sink_signals[SIGNAL_GET_STATS] =
       g_signal_new ("get-stats", G_TYPE_FROM_CLASS (klass),
       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);
 
   /**
@@ -286,10 +307,9 @@ gst_multi_socket_sink_class_init (GstMultiSocketSinkClass * klass)
    * be emitted from the streaming thread so application should be prepared
    * 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_RUN_LAST, G_STRUCT_OFFSET (GstMultiHandleSinkClass,
-          client_added), NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
+      G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
       G_TYPE_NONE, 1, G_TYPE_OBJECT);
   /**
    * 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
    * 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_RUN_LAST, G_STRUCT_OFFSET (GstMultiHandleSinkClass,
-          client_removed), NULL, NULL, gst_tcp_marshal_VOID__OBJECT_ENUM,
+      G_SIGNAL_RUN_LAST, 0, NULL, NULL, gst_tcp_marshal_VOID__OBJECT_ENUM,
       G_TYPE_NONE, 2, G_TYPE_INT, GST_TYPE_CLIENT_STATUS);
   /**
    * GstMultiSocketSink::client-socket-removed:
@@ -326,11 +344,10 @@ gst_multi_socket_sink_class_init (GstMultiSocketSinkClass * klass)
    *
    * Since: 0.10.7
    */
-  gstmultihandlesink_class->signals
-      [GST_MULTI_HANDLE_SIGNAL_CLIENT_HANDLE_REMOVED] =
+  /* FIXME: rename to client-socket-removed */
+  gst_multi_socket_sink_signals[SIGNAL_CLIENT_HANDLE_REMOVED] =
       g_signal_new ("client-handle-removed", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstMultiHandleSinkClass,
-          client_handle_removed), NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
+      G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
       G_TYPE_NONE, 1, G_TYPE_SOCKET);
 
   gst_element_class_set_static_metadata (gstelement_class,
@@ -344,6 +361,17 @@ gst_multi_socket_sink_class_init (GstMultiSocketSinkClass * klass)
   gstbasesink_class->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 =
       GST_DEBUG_FUNCPTR (gst_multi_socket_sink_stop_pre);
   gstmultihandlesink_class->stop_post =
@@ -394,6 +422,76 @@ gst_multi_socket_sink_finalize (GObject * 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 *
 gst_multi_socket_sink_new_client (GstMultiHandleSink * mhsink,
     GstMultiSinkHandle handle, GstSyncMethod sync_method)
@@ -431,9 +529,15 @@ gst_multi_socket_sink_client_get_fd (GstMultiHandleClient * client)
 }
 
 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_signal_emit (mhsink,
+      gst_multi_socket_sink_signals[SIGNAL_CLIENT_HANDLE_REMOVED], 0,
+      client->handle.socket);
+
   g_object_unref (client->handle.socket);
 }
 
index d9f9fc0..2f6432e 100644 (file)
@@ -75,6 +75,14 @@ struct _GstMultiSocketSinkClass {
   GstMultiHandleSinkClass parent_class;
 
   /* 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 */
 };