Adding a new plugin: switch.
authorJulien Moutte <julien@moutte.net>
Mon, 8 Dec 2003 20:01:01 +0000 (20:01 +0000)
committerJulien Moutte <julien@moutte.net>
Mon, 8 Dec 2003 20:01:01 +0000 (20:01 +0000)
Original commit message from CVS:
Adding a new plugin: switch.

It takes N input and only has 1 output. You can "switch" the forwarded input through properties ("nb_sources", "active_source") and i will probably add tuner interface support soon.

It should be able to handle any kind of data passing through it.

It is still a work in progress don't consider it usable for production yet.

configure.ac
gst/switch/Makefile.am [new file with mode: 0644]
gst/switch/gstswitch.c [new file with mode: 0644]
gst/switch/gstswitch.h [new file with mode: 0644]

index 7f6ea84..68734b8 100644 (file)
@@ -334,6 +334,7 @@ GST_PLUGINS_ALL="\
        spectrum \
        speed \
        stereo \
+       switch \
        synaesthesia \
        tags \
        tcp \
@@ -1395,6 +1396,7 @@ gst/smpte/Makefile
 gst/spectrum/Makefile
 gst/speed/Makefile
 gst/stereo/Makefile
+gst/switch/Makefile
 gst/synaesthesia/Makefile
 gst/tags/Makefile
 gst/tcp/Makefile
diff --git a/gst/switch/Makefile.am b/gst/switch/Makefile.am
new file mode 100644 (file)
index 0000000..fcac882
--- /dev/null
@@ -0,0 +1,9 @@
+
+plugin_LTLIBRARIES = libgstswitch.la
+
+libgstswitch_la_SOURCES = gstswitch.c
+libgstswitch_la_CFLAGS = $(GST_CFLAGS)
+libgstswitch_la_LIBADD =
+libgstswitch_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+
+noinst_HEADERS = gstswitch.h
diff --git a/gst/switch/gstswitch.c b/gst/switch/gstswitch.c
new file mode 100644 (file)
index 0000000..09da3cd
--- /dev/null
@@ -0,0 +1,336 @@
+/* GStreamer
+ * Copyright (C) 2003 Julien Moutte <julien@moutte.net>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* Object header */
+#include "gstswitch.h"
+
+enum {
+  ARG_0,
+  ARG_NB_SOURCES,
+  ARG_ACTIVE_SOURCE
+};
+
+/* ElementFactory information */
+static GstElementDetails gst_switch_details = GST_ELEMENT_DETAILS (
+  "Switch",
+  "Generic",
+  "N-to-1 input switching",
+  "Julien Moutte <julien@moutte.net>"
+);
+
+GST_PAD_TEMPLATE_FACTORY (gst_switch_sink_factory,
+  "sink%d",
+  GST_PAD_SINK,
+  GST_PAD_REQUEST,
+  GST_CAPS_ANY
+);
+
+static GstElementClass *parent_class = NULL;
+
+/* ============================================================= */
+/*                                                               */
+/*                       Private Methods                         */
+/*                                                               */
+/* ============================================================= */
+
+static GstPad*
+gst_switch_request_new_pad (GstElement *element,
+                            GstPadTemplate *templ,
+                            const gchar *unused) 
+{
+  char *name = NULL;
+  GstPad *sinkpad = NULL;
+  GstSwitch *gstswitch = NULL;
+  GstSwitchPad *switchpad = NULL;
+  
+  g_return_val_if_fail (GST_IS_SWITCH (element), NULL);
+  
+  if (templ->direction != GST_PAD_SINK) {
+    g_warning ("gstswitch: requested a non sink pad\n");
+    return NULL;
+  }
+  
+  gstswitch = GST_SWITCH (element);
+  
+  name = g_strdup_printf ("sink%d", gstswitch->nb_sinkpads);
+  
+  sinkpad = gst_pad_new_from_template (templ, name);
+  
+  if (name)
+    g_free (name);
+  
+  gst_element_add_pad (GST_ELEMENT (gstswitch), sinkpad);
+  
+  switchpad = g_new0 (GstSwitchPad, 1);
+  if (!switchpad)
+    return NULL;
+  
+  switchpad->sinkpad = sinkpad;
+  switchpad->data = NULL;
+  switchpad->forwarded = FALSE;
+  
+  gstswitch->sinkpads = g_list_insert (gstswitch->sinkpads, switchpad,
+                                       gstswitch->nb_sinkpads);
+  gstswitch->nb_sinkpads++;
+  
+  return sinkpad;
+}
+
+static gboolean
+gst_switch_poll_sinkpads (GstSwitch *gstswitch)
+{
+  GList *pads;
+  
+  g_return_val_if_fail (gstswitch != NULL, FALSE);
+  g_return_val_if_fail (GST_IS_SWITCH (gstswitch), FALSE);
+  
+  pads = gstswitch->sinkpads;
+  
+  while (pads) {
+    GstSwitchPad *switchpad = pads->data;
+    GstData *data = gst_pad_pull (switchpad->sinkpad);
+    if (GST_IS_EVENT (data) &&
+        (GST_EVENT_TYPE (GST_EVENT (data)) == GST_EVENT_EOS)) {
+      /* If that data was not forwarded we unref it */
+      if (!switchpad->forwarded && switchpad->data) {
+        gst_data_unref (switchpad->data);
+        switchpad->data = NULL;
+      }
+      gst_event_unref (GST_EVENT (data));
+    }
+    else  {
+      /* If that data was not forwarded we unref it */
+      if (!switchpad->forwarded && switchpad->data) {
+        gst_data_unref (switchpad->data);
+        switchpad->data = NULL;
+      }
+      switchpad->data = data;
+      switchpad->forwarded = FALSE;
+    }
+    pads = g_list_next (pads);
+  }
+    
+  return TRUE;
+}
+
+static void 
+gst_switch_loop (GstElement *element) 
+{
+  GstSwitch *gstswitch = NULL;
+  GstSwitchPad *switchpad = NULL;
+  
+  g_return_if_fail (element != NULL);
+  g_return_if_fail (GST_IS_SWITCH (element));
+  
+  gstswitch = GST_SWITCH (element);
+  
+  /* We poll all our sinkpads */
+  gst_switch_poll_sinkpads (gstswitch);
+  
+  /* We get the active sinkpad */
+  switchpad = g_list_nth_data (gstswitch->sinkpads, gstswitch->active_sinkpad);
+  
+  if (switchpad) {
+    /* Pushing active sinkpad data to srcpad */
+    gst_pad_push (gstswitch->srcpad, switchpad->data);
+    /* Mark this data as forwarded so that it won't get unrefed on next poll */
+    switchpad->forwarded = TRUE;
+  }
+}
+
+/* =========================================== */
+/*                                             */
+/*                 Properties                  */
+/*                                             */
+/* =========================================== */
+
+static void
+gst_switch_set_property (GObject *object, guint prop_id,
+                         const GValue *value, GParamSpec *pspec)
+{
+  GstSwitch *gstswitch = NULL;
+  
+  g_return_if_fail (GST_IS_SWITCH (object));
+  
+  gstswitch = GST_SWITCH (object);
+  
+  switch (prop_id) {
+    case ARG_ACTIVE_SOURCE:
+      gstswitch->active_sinkpad = g_value_get_int (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_switch_get_property (GObject *object, guint prop_id,
+                         GValue *value, GParamSpec *pspec)
+{
+  GstSwitch *gstswitch = NULL;
+  
+  g_return_if_fail (GST_IS_SWITCH (object));
+  
+  gstswitch = GST_SWITCH (object);
+  
+  switch (prop_id) {
+    case ARG_ACTIVE_SOURCE:
+      g_value_set_int (value, gstswitch->active_sinkpad);
+      break;
+    case ARG_NB_SOURCES:
+      g_value_set_int (value, gstswitch->nb_sinkpads);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+/* =========================================== */
+/*                                             */
+/*              Init & Class init              */
+/*                                             */
+/* =========================================== */
+
+static void
+gst_switch_dispose (GObject *object)
+{
+  GstSwitch *gstswitch = NULL;
+  
+  gstswitch = GST_SWITCH (object);
+
+  if (gstswitch->sinkpads) {  
+    g_list_free (gstswitch->sinkpads);
+    gstswitch->sinkpads = NULL;
+  }
+  
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gst_switch_init (GstSwitch *gstswitch)
+{
+  gstswitch->srcpad = gst_pad_new ("src", GST_PAD_SRC);
+  gst_element_add_pad (GST_ELEMENT (gstswitch), gstswitch->srcpad);
+  
+  gst_element_set_loop_function (GST_ELEMENT (gstswitch), gst_switch_loop);
+  
+  gstswitch->sinkpads = NULL;
+  gstswitch->active_sinkpad = 0;
+  gstswitch->nb_sinkpads = 0;
+}
+
+static void
+gst_switch_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+  
+  gst_element_class_set_details (element_class, &gst_switch_details);
+
+  gst_element_class_add_pad_template (element_class, 
+    GST_PAD_TEMPLATE_GET (gst_switch_sink_factory));
+}
+
+static void
+gst_switch_class_init (GstSwitchClass *klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+
+  parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
+  
+  g_object_class_install_property (gobject_class,
+                                   ARG_NB_SOURCES,
+                                   g_param_spec_int ("nb_sources",
+                                                     "number of sources",
+                                                     "number of sources",
+                                                     G_MININT, G_MAXINT, 0,
+                                                     G_PARAM_READABLE));
+  g_object_class_install_property (gobject_class,
+                                   ARG_ACTIVE_SOURCE,
+                                   g_param_spec_int ("active_source",
+                                                     "active source",
+                                                     "active source",
+                                                     G_MININT, G_MAXINT, 0,
+                                                     G_PARAM_READWRITE));
+                                                     
+  gobject_class->dispose = gst_switch_dispose;
+  gobject_class->set_property = gst_switch_set_property;
+  gobject_class->get_property = gst_switch_get_property;
+  
+  gstelement_class->request_new_pad = gst_switch_request_new_pad;
+}
+
+/* ============================================================= */
+/*                                                               */
+/*                       Public Methods                          */
+/*                                                               */
+/* ============================================================= */
+
+GType
+gst_switch_get_type (void)
+{
+  static GType switch_type = 0;
+
+  if (!switch_type) {
+      static const GTypeInfo switch_info = {
+        sizeof(GstSwitchClass),
+        gst_switch_base_init,
+        NULL,
+        (GClassInitFunc) gst_switch_class_init,
+        NULL,
+        NULL,
+        sizeof(GstSwitch),
+        0,
+        (GInstanceInitFunc) gst_switch_init,
+      };
+      
+      switch_type = g_type_register_static (GST_TYPE_ELEMENT,
+                                            "GstSwitch", &switch_info, 0);
+  }
+    
+  return switch_type;
+}
+
+static gboolean
+plugin_init (GstPlugin *plugin)
+{
+  return gst_element_register (plugin, "switch", GST_RANK_NONE,
+                               GST_TYPE_SWITCH);
+}
+
+GST_PLUGIN_DEFINE (
+  GST_VERSION_MAJOR,
+  GST_VERSION_MINOR,
+  "switch",
+  "N-to-1 input switching",
+  plugin_init,
+  VERSION,
+  GST_LICENSE,
+  GST_PACKAGE,
+  GST_ORIGIN
+)
diff --git a/gst/switch/gstswitch.h b/gst/switch/gstswitch.h
new file mode 100644 (file)
index 0000000..2025650
--- /dev/null
@@ -0,0 +1,67 @@
+/* GStreamer
+ * Copyright (C) 2003 Julien Moutte <julien@moutte.net>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GST_SWITCH_H__
+#define __GST_SWITCH_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_SWITCH \
+  (gst_switch_get_type())
+#define GST_SWITCH(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_SWITCH, GstSwitch))
+#define GST_SWITCH_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_SWITCH, GstSwitch))
+#define GST_IS_SWITCH(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_SWITCH))
+#define GST_IS_SWITCH_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_SWITCH))
+
+typedef struct _GstSwitchPad GstSwitchPad;
+
+typedef struct _GstSwitch GstSwitch;
+typedef struct _GstSwitchClass GstSwitchClass;
+
+struct _GstSwitchPad {
+  GstPad *sinkpad;
+  GstData *data;
+  gboolean forwarded;
+};
+
+struct _GstSwitch {
+  GstElement element;
+  
+  GList *sinkpads;
+  GstPad *srcpad;
+  
+  guint nb_sinkpads;
+  guint active_sinkpad;
+};
+
+struct _GstSwitchClass {
+  GstElementClass parent_class;
+};
+
+GType gst_switch_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_SWITCH_H__ */