fix compilation on windows, minor formatting, use unix end of line
authorcaro <caro@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 12 Nov 2008 07:54:25 +0000 (07:54 +0000)
committercaro <caro@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 12 Nov 2008 07:54:25 +0000 (07:54 +0000)
git-svn-id: http://svn.enlightenment.org/svn/e/trunk/ecore@37597 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/lib/ecore/ecore_pipe.c

index cec7fc7..cd3d6bc 100644 (file)
-/*\r
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2\r
- */\r
-#include <stdlib.h>\r
-#ifdef HAVE_CONFIG_H\r
-# include <config.h>\r
-#endif\r
-#ifdef HAVE_EVIL\r
-# include <Evil.h>\r
-#endif\r
-#include "ecore_private.h"\r
-#include "Ecore.h"\r
-\r
-struct _Ecore_Pipe\r
-{\r
-   ECORE_MAGIC;\r
-   int               fd_read;\r
-   int               fd_write;\r
-   Ecore_Fd_Handler *fd_handler;\r
-   const void       *data;\r
-   void (*handler) (void *data, void *buffer, unsigned int nbyte);\r
-   unsigned int      len;\r
-   size_t            already_read;\r
-   void             *passed_data;\r
-};\r
-\r
-/* How of then we should retry to write to the pipe */\r
-#define ECORE_PIPE_WRITE_RETRY 6\r
-\r
-/*\r
- * On Windows, pipe() is implemented with sockets.\r
- * Contrary to Linux, Windows uses different functions\r
- * for sockets and fd's: write() is for fd's and send\r
- * is for sockets. So I need to put some win32 code\r
- * here. I can't think of a solution where the win32\r
- * code is in Evil and not here.\r
- */\r
-\r
-#ifdef _WIN32\r
-\r
-# include <winsock2.h>\r
-\r
-# define pipe_write(fd, buffer, size) send((fd), (char *)(buffer), size, 0)\r
-# define pipe_read(fd, buffer, size)  recv((fd), (char *)(buffer), size, 0)\r
-\r
-#else\r
-\r
-# include <unistd.h>\r
-# include <fcntl.h>\r
-# include <errno.h>\r
-\r
-# define pipe_write(fd, buffer, size) write((fd), buffer, size)\r
-# define pipe_read(fd, buffer, size)  read((fd), buffer, size)\r
-\r
-#endif /* _WIN32 */\r
-\r
-\r
-static int _ecore_pipe_read(void             *data,\r
-                            Ecore_Fd_Handler *fd_handler);\r
-\r
-/**\r
- * @defgroup Ecore_Pipe_Group Pipe wrapper\r
- *\r
- * These functions wrap the pipe / write / read functions to\r
- * easily integrate a loop that is in its own thread to the ecore\r
- * main loop.\r
- *\r
- * The ecore_pipe_add() function creates file descriptors (sockets on\r
- * Windows) and attach an handle to the ecore main loop. That handle is\r
- * called when data is read in the pipe. To write data in the pipe,\r
- * just call ecore_pipe_write(). When you are done, just call\r
- * ecore_pipe_del().\r
- *\r
- * Here is an example that uses the pipe wrapper with a Gstreamer\r
- * pipeline. For each decoded frame in the Gstreamer thread, a handle\r
- * is called in the ecore thread.\r
- *\r
- * @code#include <gst/gst.h>\r
- * #include <Ecore.h>\r
- *\r
- * static int nbr = 0;\r
- *\r
- * static GstElement *_buid_pipeline (gchar *filename, Ecore_Pipe *pipe);\r
- *\r
- * static void new_decoded_pad_cb (GstElement *demuxer,\r
- *                                 GstPad     *new_pad,\r
- *                                 gpointer    user_data);\r
- *\r
- * static void handler(void *data, void *buf, unsigned int len)\r
- * {\r
- *   GstBuffer  *buffer = *((GstBuffer **)buf);\r
- *\r
- *   printf ("handler : %p\n", buffer);\r
- *   printf ("frame  : %d %p %lld %p\n", nbr++, data, (long long)GST_BUFFER_DURATION(buffer), buffer);\r
- *   gst_buffer_unref (buffer);\r
- * }\r
- *\r
- *\r
- * static void handoff (GstElement* object,\r
- *                      GstBuffer* arg0,\r
- *                      GstPad* arg1,\r
- *                      gpointer user_data)\r
- * {\r
- *   Ecore_Pipe *pipe;\r
- *\r
- *   pipe = (Ecore_Pipe *)user_data;\r
- *   printf ("handoff : %p\n", arg0);\r
- *   gst_buffer_ref (arg0);\r
- *   ecore_pipe_write(pipe, &arg0, sizeof(arg0));\r
- * }\r
- *\r
- * int\r
- * main (int argc, char *argv[])\r
- * {\r
- *   GstElement *pipeline;\r
- *   char *filename;\r
- *   Ecore_Pipe *pipe;\r
- *\r
- *   gst_init (&argc, &argv);\r
- *\r
- *   if (!ecore_init ())\r
- *     {\r
- *       gst_deinit ();\r
- *       return 0;\r
- *     }\r
- *\r
- *   pipe = ecore_pipe_add (handler);\r
- *   if (!pipe)\r
- *     {\r
- *       ecore_shutdown ();\r
- *       gst_deinit ();\r
- *       return 0;\r
- *     }\r
- *\r
- *   if (argc < 2) {\r
- *     g_print ("usage: %s file.avi\n", argv[0]);\r
- *     ecore_pipe_del (pipe);\r
- *     ecore_shutdown ();\r
- *     gst_deinit ();\r
- *     return 0;\r
- *   }\r
- *   filename = argv[1];\r
- *\r
- *   pipeline = _buid_pipeline (filename, pipe);\r
- *   if (!pipeline) {\r
- *     g_print ("Error during the pipeline building\n");\r
- *     ecore_pipe_free (pipe);\r
- *     ecore_shutdown ();\r
- *     gst_deinit ();\r
- *     return -1;\r
- *   }\r
- *\r
- *   gst_element_set_state (pipeline, GST_STATE_PLAYING);\r
- *\r
- *   ecore_main_loop_begin();\r
- *\r
- *   ecore_pipe_free (pipe);\r
- *   ecore_shutdown ();\r
- *   gst_deinit ();\r
- *\r
- *   return 0;\r
- * }\r
- *\r
- * static void\r
- * new_decoded_pad_cb (GstElement *demuxer,\r
- *                     GstPad     *new_pad,\r
- *                     gpointer    user_data)\r
- * {\r
- *   GstElement *decoder;\r
- *   GstPad *pad;\r
- *   GstCaps *caps;\r
- *   gchar *str;\r
- *\r
- *   caps = gst_pad_get_caps (new_pad);\r
- *   str = gst_caps_to_string (caps);\r
- *\r
- *   if (g_str_has_prefix (str, "video/")) {\r
- *     decoder = GST_ELEMENT (user_data);\r
- *\r
- *     pad = gst_element_get_pad (decoder, "sink");\r
- *     if (GST_PAD_LINK_FAILED (gst_pad_link (new_pad, pad))) {\r
- *       g_warning ("Failed to link %s:%s to %s:%s", GST_DEBUG_PAD_NAME (new_pad),\r
- *                  GST_DEBUG_PAD_NAME (pad));\r
- *     }\r
- *   }\r
- *   g_free (str);\r
- *   gst_caps_unref (caps);\r
- * }\r
- *\r
- * static GstElement *\r
- * _buid_pipeline (gchar *filename, Ecore_Pipe *pipe)\r
- * {\r
- *   GstElement          *pipeline;\r
- *   GstElement          *filesrc;\r
- *   GstElement          *demuxer;\r
- *   GstElement          *decoder;\r
- *   GstElement          *sink;\r
-  GstStateChangeReturn res;\r
- *\r
- *   pipeline = gst_pipeline_new ("pipeline");\r
- *   if (!pipeline)\r
- *     return NULL;\r
- *\r
- *   filesrc = gst_element_factory_make ("filesrc", "filesrc");\r
- *   if (!filesrc) {\r
- *     printf ("no filesrc");\r
- *     goto failure;\r
- *   }\r
- *   g_object_set (G_OBJECT (filesrc), "location", filename, NULL);\r
- *\r
- *   demuxer = gst_element_factory_make ("oggdemux", "demuxer");\r
- *   if (!demuxer) {\r
- *     printf ("no demux");\r
- *     goto failure;\r
- *   }\r
- *\r
- *   decoder = gst_element_factory_make ("theoradec", "decoder");\r
- *   if (!decoder) {\r
- *     printf ("no dec");\r
- *     goto failure;\r
- *   }\r
- *\r
- *   g_signal_connect (demuxer, "pad-added",\r
- *                     G_CALLBACK (new_decoded_pad_cb), decoder);\r
- *\r
- *   sink = gst_element_factory_make ("fakesink", "sink");\r
- *   if (!sink) {\r
- *     printf ("no sink");\r
- *     goto failure;\r
- *   }\r
- *   g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);\r
- *   g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL);\r
- *   g_signal_connect (sink, "handoff",\r
- *                     G_CALLBACK (handoff), pipe);\r
- *\r
- *   gst_bin_add_many (GST_BIN (pipeline),\r
- *                     filesrc, demuxer, decoder, sink, NULL);\r
- *\r
- *   if (!gst_element_link (filesrc, demuxer))\r
- *     goto failure;\r
- *   if (!gst_element_link (decoder, sink))\r
- *     goto failure;\r
- *\r
- *   res = gst_element_set_state (pipeline, GST_STATE_PAUSED);\r
- *   if (res == GST_STATE_CHANGE_FAILURE)\r
- *     goto failure;\r
- *\r
- *   res = gst_element_get_state( pipeline, NULL, NULL, GST_CLOCK_TIME_NONE );\r
- *   if (res != GST_STATE_CHANGE_SUCCESS)\r
- *     goto failure;\r
- *\r
- *   return pipeline;\r
- *\r
- *  failure:\r
- *   gst_object_unref (GST_OBJECT (pipeline));\r
- *   return NULL;\r
- * }\r
- * @endcode\r
- */\r
-\r
-\r
-/**\r
- * Create two file descriptors (sockets on Windows). Add\r
- * a callback that will be called when the file descriptor that\r
- * is listened receives data. An event is also put in the event\r
- * queue when data is received.\r
- *\r
- * @param handler The handler called when data is received.\r
- * @param data    Data to pass to @p handler when it is called.\r
- * @return        A newly created Ecore_Pipe object if successful.\r
- *                @c NULL otherwise.\r
- * @ingroup Ecore_Pipe_Group\r
- */\r
-EAPI Ecore_Pipe *\r
-ecore_pipe_add(void (*handler) (void *data, void *buffer, unsigned int nbyte),\r
-               const void *data)\r
-{\r
-   Ecore_Pipe       *p;\r
-   int               fds[2];\r
-\r
-   if(!handler)\r
-     return NULL;\r
-   p = (Ecore_Pipe *)calloc(1, sizeof(Ecore_Pipe));\r
-   if (!p)\r
-     return NULL;\r
-\r
-   if (pipe(fds))\r
-     {\r
-        free(p);\r
-        return NULL;\r
-     }\r
-\r
-   ECORE_MAGIC_SET(p, ECORE_MAGIC_PIPE);\r
-   p->fd_read = fds[0];\r
-   p->fd_write = fds[1];\r
-   p->handler = handler;\r
-   p->data = data;\r
-\r
-#ifndef _WIN32\r
-   fcntl(p->fd_read, F_SETFL, O_NONBLOCK);\r
-#endif /* _WIN32 */\r
-   p->fd_handler = ecore_main_fd_handler_add(p->fd_read,\r
-                                          ECORE_FD_READ,\r
-                                          _ecore_pipe_read,\r
-                                          p,\r
-                                          NULL, NULL);\r
-\r
-   return p;\r
-}\r
-\r
-/**\r
- * Free an Ecore_Pipe object created with ecore_pipe_add().\r
- *\r
- * @param p The Ecore_Pipe object to be freed.\r
- * @return The pointer to the private data\r
- * @ingroup Ecore_Pipe_Group\r
- */\r
-EAPI void *\r
-ecore_pipe_del(Ecore_Pipe *p)\r
-{\r
-   void *data;\r
-\r
-   if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE))\r
-     {\r
-       ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE,\r
-             "ecore_pipe_del");\r
-       return NULL;\r
-     }\r
-   ecore_main_fd_handler_del(p->fd_handler);\r
-   close(p->fd_read);\r
-   close(p->fd_write);\r
-   data = (void *)p->data;\r
-   free (p);\r
-   return data;\r
-}\r
-\r
-/**\r
- * Write on the file descriptor the data passed as parameter.\r
- *\r
- * @param p      The Ecore_Pipe object.\r
- * @param buffer The data to write into the pipe.\r
- * @param nbytes The size of the @p buffer in bytes\r
- * @ingroup Ecore_Pipe_Group\r
- */\r
-EAPI int\r
-ecore_pipe_write(Ecore_Pipe *p, const void *buffer, unsigned int nbytes)\r
-{\r
-   ssize_t ret;\r
-   size_t already_written = 0;\r
-   int retry = ECORE_PIPE_WRITE_RETRY;\r
-\r
-   if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE))\r
-     {\r
-       ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE,\r
-             "ecore_pipe_write");\r
-       return 0;\r
-     }\r
-   /* first write the len into the pipe */\r
-   do\r
-     {\r
-       ret = pipe_write(p->fd_write, &nbytes, sizeof(nbytes));\r
-       if (ret == sizeof(nbytes))\r
-         {\r
-            retry = ECORE_PIPE_WRITE_RETRY;\r
-            break;\r
-         }\r
-       else if (ret > 0)\r
-         {\r
-            /* XXX What should we do here? */\r
-            fprintf(stderr, "The length of the data was not written complete"\r
-                 " to the pipe\n");\r
-            return 0;\r
-         }\r
-       else if (ret == -1 && errno == EINTR)\r
-         /* try it again */\r
-         ;\r
-       else\r
-         {\r
-            fprintf(stderr, "An unhandled error (ret: %d errno: %d)"\r
-                  "occured while writing to the pipe the length\n",\r
-                  ret, errno);\r
-         }\r
-     } \r
-   while (retry--);\r
-\r
-   if (retry != ECORE_PIPE_WRITE_RETRY)\r
-     return 0;\r
-\r
-   /* and now pass the data to the pipe */\r
-   do\r
-     {\r
-       ret = pipe_write(p->fd_write, \r
-             ((unsigned char *)buffer) + already_written,\r
-             nbytes - already_written);\r
-\r
-       if (ret == (ssize_t)(nbytes - already_written))\r
-         return 1;\r
-       else if (ret >= 0)\r
-         {\r
-            already_written -= ret;\r
-            continue;\r
-         }\r
-       else if (ret == -1 && errno == EINTR)\r
-         /* try it again */\r
-         ;\r
-       else\r
-         {\r
-            fprintf(stderr, "An unhandled error (ret: %d errno: %d)"\r
-                  "occured while writing to the pipe the length\n",\r
-                  ret, errno);\r
-         }\r
-     } \r
-   while (retry--);\r
-\r
-   return 0;\r
-}\r
-\r
-/* Private function */\r
-\r
-static int\r
-_ecore_pipe_read(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__)\r
-{\r
-   Ecore_Pipe  *p;\r
-   double       start_time;\r
-\r
-   p = (Ecore_Pipe *)data;\r
-   start_time = ecore_time_get();\r
-\r
-   do \r
-     {\r
-       ssize_t       ret;\r
-\r
-       /* if we already have read some data we don't need to read the len\r
-        * but to finish the already started job\r
-        */\r
-       if (p->len == 0)\r
-         {\r
-            /* read the len of the passed data */\r
-            ret = pipe_read(p->fd_read, &p->len, sizeof(p->len));\r
-\r
-            /* catch the non error case first */\r
-            if (ret == sizeof(p->len))\r
-              ;\r
-            else if (ret > 0)\r
-              {\r
-                 /* XXX What should we do here? */\r
-                 fprintf(stderr, "Only read %d bytes from the pipe, although"\r
-                       " we need to read %d bytes.\n", ret, sizeof(p->len));\r
-              }\r
-            else if (ret == 0 \r
-                  || (ret == -1 && (errno == EINTR || errno == EAGAIN)))\r
-              return ECORE_CALLBACK_RENEW;\r
-            else\r
-              {\r
-                 fprintf(stderr, "An unhandled error (ret: %d errno: %d)"\r
-                       "occured while reading from the pipe the length\n",\r
-                       ret, errno);\r
-                 return ECORE_CALLBACK_RENEW;\r
-              }\r
-         }\r
-\r
-       if (!p->passed_data)\r
-         p->passed_data = malloc(p->len);\r
-\r
-       /* and read the passed data */\r
-       ret = pipe_read(p->fd_read, \r
-             ((unsigned char *)p->passed_data) + p->already_read,\r
-             p->len - p->already_read);\r
-\r
-       /* catch the non error case first */\r
-       if (ret == (ssize_t)(p->len - p->already_read))\r
-         {\r
-            p->handler((void *)p->data, p->passed_data, p->len);\r
-            free(p->passed_data);\r
-            /* reset all values to 0 */\r
-            p->passed_data = NULL;\r
-            p->already_read = 0;\r
-            p->len = 0;\r
-         }\r
-       else if (ret >= 0)\r
-         {\r
-            p->already_read += ret;\r
-            return ECORE_CALLBACK_RENEW;\r
-         }\r
-       else if (ret == -1 && (errno == EINTR || errno == EAGAIN))\r
-         return ECORE_CALLBACK_RENEW;\r
-       else\r
-         {\r
-            fprintf(stderr, "An unhandled error (ret: %d errno: %d)"\r
-                  "occured while reading from the pipe the data\n",\r
-                  ret, errno);\r
-            return ECORE_CALLBACK_RENEW;\r
-         }\r
-     }\r
-   while (ecore_time_get() - start_time < ecore_animator_frametime_get());\r
-\r
-   return ECORE_CALLBACK_RENEW;\r
-}\r
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <errno.h>
+
+#ifdef HAVE_EVIL
+# include <Evil.h>
+#endif
+
+#include "ecore_private.h"
+#include "Ecore.h"
+
+/* How of then we should retry to write to the pipe */
+#define ECORE_PIPE_WRITE_RETRY 6
+
+/*
+ * On Windows, pipe() is implemented with sockets.
+ * Contrary to Linux, Windows uses different functions
+ * for sockets and fd's: write() is for fd's and send
+ * is for sockets. So I need to put some win32 code
+ * here. I can't think of a solution where the win32
+ * code is in Evil and not here.
+ */
+
+#ifdef _WIN32
+
+# include <winsock2.h>
+
+# define pipe_write(fd, buffer, size) send((fd), (char *)(buffer), size, 0)
+# define pipe_read(fd, buffer, size)  recv((fd), (char *)(buffer), size, 0)
+
+#else
+
+# include <unistd.h>
+# include <fcntl.h>
+
+# define pipe_write(fd, buffer, size) write((fd), buffer, size)
+# define pipe_read(fd, buffer, size)  read((fd), buffer, size)
+
+#endif /* ! _WIN32 */
+
+struct _Ecore_Pipe
+{
+   ECORE_MAGIC;
+   int               fd_read;
+   int               fd_write;
+   Ecore_Fd_Handler *fd_handler;
+   const void       *data;
+   void (*handler)  (void *data, void *buffer, unsigned int nbyte);
+   unsigned int      len;
+   size_t            already_read;
+   void             *passed_data;
+};
+
+
+static int _ecore_pipe_read(void             *data,
+                            Ecore_Fd_Handler *fd_handler);
+
+/**
+ * @defgroup Ecore_Pipe_Group Pipe wrapper
+ *
+ * These functions wrap the pipe / write / read functions to
+ * easily integrate a loop that is in its own thread to the ecore
+ * main loop.
+ *
+ * The ecore_pipe_add() function creates file descriptors (sockets on
+ * Windows) and attach an handle to the ecore main loop. That handle is
+ * called when data is read in the pipe. To write data in the pipe,
+ * just call ecore_pipe_write(). When you are done, just call
+ * ecore_pipe_del().
+ *
+ * Here is an example that uses the pipe wrapper with a Gstreamer
+ * pipeline. For each decoded frame in the Gstreamer thread, a handle
+ * is called in the ecore thread.
+ *
+ * @code#include <gst/gst.h>
+ * #include <Ecore.h>
+ *
+ * static int nbr = 0;
+ *
+ * static GstElement *_buid_pipeline (gchar *filename, Ecore_Pipe *pipe);
+ *
+ * static void new_decoded_pad_cb (GstElement *demuxer,
+ *                                 GstPad     *new_pad,
+ *                                 gpointer    user_data);
+ *
+ * static void handler(void *data, void *buf, unsigned int len)
+ * {
+ *   GstBuffer  *buffer = *((GstBuffer **)buf);
+ *
+ *   printf ("handler : %p\n", buffer);
+ *   printf ("frame  : %d %p %lld %p\n", nbr++, data, (long long)GST_BUFFER_DURATION(buffer), buffer);
+ *   gst_buffer_unref (buffer);
+ * }
+ *
+ *
+ * static void handoff (GstElement* object,
+ *                      GstBuffer* arg0,
+ *                      GstPad* arg1,
+ *                      gpointer user_data)
+ * {
+ *   Ecore_Pipe *pipe;
+ *
+ *   pipe = (Ecore_Pipe *)user_data;
+ *   printf ("handoff : %p\n", arg0);
+ *   gst_buffer_ref (arg0);
+ *   ecore_pipe_write(pipe, &arg0, sizeof(arg0));
+ * }
+ *
+ * int
+ * main (int argc, char *argv[])
+ * {
+ *   GstElement *pipeline;
+ *   char *filename;
+ *   Ecore_Pipe *pipe;
+ *
+ *   gst_init (&argc, &argv);
+ *
+ *   if (!ecore_init ())
+ *     {
+ *       gst_deinit ();
+ *       return 0;
+ *     }
+ *
+ *   pipe = ecore_pipe_add (handler);
+ *   if (!pipe)
+ *     {
+ *       ecore_shutdown ();
+ *       gst_deinit ();
+ *       return 0;
+ *     }
+ *
+ *   if (argc < 2) {
+ *     g_print ("usage: %s file.avi\n", argv[0]);
+ *     ecore_pipe_del (pipe);
+ *     ecore_shutdown ();
+ *     gst_deinit ();
+ *     return 0;
+ *   }
+ *   filename = argv[1];
+ *
+ *   pipeline = _buid_pipeline (filename, pipe);
+ *   if (!pipeline) {
+ *     g_print ("Error during the pipeline building\n");
+ *     ecore_pipe_free (pipe);
+ *     ecore_shutdown ();
+ *     gst_deinit ();
+ *     return -1;
+ *   }
+ *
+ *   gst_element_set_state (pipeline, GST_STATE_PLAYING);
+ *
+ *   ecore_main_loop_begin();
+ *
+ *   ecore_pipe_free (pipe);
+ *   ecore_shutdown ();
+ *   gst_deinit ();
+ *
+ *   return 0;
+ * }
+ *
+ * static void
+ * new_decoded_pad_cb (GstElement *demuxer,
+ *                     GstPad     *new_pad,
+ *                     gpointer    user_data)
+ * {
+ *   GstElement *decoder;
+ *   GstPad *pad;
+ *   GstCaps *caps;
+ *   gchar *str;
+ *
+ *   caps = gst_pad_get_caps (new_pad);
+ *   str = gst_caps_to_string (caps);
+ *
+ *   if (g_str_has_prefix (str, "video/")) {
+ *     decoder = GST_ELEMENT (user_data);
+ *
+ *     pad = gst_element_get_pad (decoder, "sink");
+ *     if (GST_PAD_LINK_FAILED (gst_pad_link (new_pad, pad))) {
+ *       g_warning ("Failed to link %s:%s to %s:%s", GST_DEBUG_PAD_NAME (new_pad),
+ *                  GST_DEBUG_PAD_NAME (pad));
+ *     }
+ *   }
+ *   g_free (str);
+ *   gst_caps_unref (caps);
+ * }
+ *
+ * static GstElement *
+ * _buid_pipeline (gchar *filename, Ecore_Pipe *pipe)
+ * {
+ *   GstElement          *pipeline;
+ *   GstElement          *filesrc;
+ *   GstElement          *demuxer;
+ *   GstElement          *decoder;
+ *   GstElement          *sink;
+  GstStateChangeReturn res;
+ *
+ *   pipeline = gst_pipeline_new ("pipeline");
+ *   if (!pipeline)
+ *     return NULL;
+ *
+ *   filesrc = gst_element_factory_make ("filesrc", "filesrc");
+ *   if (!filesrc) {
+ *     printf ("no filesrc");
+ *     goto failure;
+ *   }
+ *   g_object_set (G_OBJECT (filesrc), "location", filename, NULL);
+ *
+ *   demuxer = gst_element_factory_make ("oggdemux", "demuxer");
+ *   if (!demuxer) {
+ *     printf ("no demux");
+ *     goto failure;
+ *   }
+ *
+ *   decoder = gst_element_factory_make ("theoradec", "decoder");
+ *   if (!decoder) {
+ *     printf ("no dec");
+ *     goto failure;
+ *   }
+ *
+ *   g_signal_connect (demuxer, "pad-added",
+ *                     G_CALLBACK (new_decoded_pad_cb), decoder);
+ *
+ *   sink = gst_element_factory_make ("fakesink", "sink");
+ *   if (!sink) {
+ *     printf ("no sink");
+ *     goto failure;
+ *   }
+ *   g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
+ *   g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL);
+ *   g_signal_connect (sink, "handoff",
+ *                     G_CALLBACK (handoff), pipe);
+ *
+ *   gst_bin_add_many (GST_BIN (pipeline),
+ *                     filesrc, demuxer, decoder, sink, NULL);
+ *
+ *   if (!gst_element_link (filesrc, demuxer))
+ *     goto failure;
+ *   if (!gst_element_link (decoder, sink))
+ *     goto failure;
+ *
+ *   res = gst_element_set_state (pipeline, GST_STATE_PAUSED);
+ *   if (res == GST_STATE_CHANGE_FAILURE)
+ *     goto failure;
+ *
+ *   res = gst_element_get_state( pipeline, NULL, NULL, GST_CLOCK_TIME_NONE );
+ *   if (res != GST_STATE_CHANGE_SUCCESS)
+ *     goto failure;
+ *
+ *   return pipeline;
+ *
+ *  failure:
+ *   gst_object_unref (GST_OBJECT (pipeline));
+ *   return NULL;
+ * }
+ * @endcode
+ */
+
+
+/**
+ * Create two file descriptors (sockets on Windows). Add
+ * a callback that will be called when the file descriptor that
+ * is listened receives data. An event is also put in the event
+ * queue when data is received.
+ *
+ * @param handler The handler called when data is received.
+ * @param data    Data to pass to @p handler when it is called.
+ * @return        A newly created Ecore_Pipe object if successful.
+ *                @c NULL otherwise.
+ * @ingroup Ecore_Pipe_Group
+ */
+EAPI Ecore_Pipe *
+ecore_pipe_add(void (*handler) (void *data, void *buffer, unsigned int nbyte),
+               const void *data)
+{
+   Ecore_Pipe *p;
+   int         fds[2];
+
+   if(!handler)
+     return NULL;
+
+   p = (Ecore_Pipe *)calloc(1, sizeof(Ecore_Pipe));
+   if (!p)
+     return NULL;
+
+   if (pipe(fds))
+     {
+        free(p);
+        return NULL;
+     }
+
+   ECORE_MAGIC_SET(p, ECORE_MAGIC_PIPE);
+   p->fd_read = fds[0];
+   p->fd_write = fds[1];
+   p->handler = handler;
+   p->data = data;
+
+#ifndef _WIN32
+   fcntl(p->fd_read, F_SETFL, O_NONBLOCK);
+#endif /* _WIN32 */
+   p->fd_handler = ecore_main_fd_handler_add(p->fd_read,
+                                          ECORE_FD_READ,
+                                          _ecore_pipe_read,
+                                          p,
+                                          NULL, NULL);
+
+   return p;
+}
+
+/**
+ * Free an Ecore_Pipe object created with ecore_pipe_add().
+ *
+ * @param p The Ecore_Pipe object to be freed.
+ * @return The pointer to the private data
+ * @ingroup Ecore_Pipe_Group
+ */
+EAPI void *
+ecore_pipe_del(Ecore_Pipe *p)
+{
+   void *data;
+
+   if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE))
+     {
+       ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE,
+             "ecore_pipe_del");
+       return NULL;
+     }
+   ecore_main_fd_handler_del(p->fd_handler);
+   close(p->fd_read);
+   close(p->fd_write);
+   data = (void *)p->data;
+   free (p);
+   return data;
+}
+
+/**
+ * Write on the file descriptor the data passed as parameter.
+ *
+ * @param p      The Ecore_Pipe object.
+ * @param buffer The data to write into the pipe.
+ * @param nbytes The size of the @p buffer in bytes
+ * @ingroup Ecore_Pipe_Group
+ */
+EAPI int
+ecore_pipe_write(Ecore_Pipe *p, const void *buffer, unsigned int nbytes)
+{
+   ssize_t ret;
+   size_t  already_written = 0;
+   int     retry = ECORE_PIPE_WRITE_RETRY;
+
+   if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE))
+     {
+       ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE,
+             "ecore_pipe_write");
+       return 0;
+     }
+   /* first write the len into the pipe */
+   do
+     {
+       ret = pipe_write(p->fd_write, &nbytes, sizeof(nbytes));
+       if (ret == sizeof(nbytes))
+         {
+            retry = ECORE_PIPE_WRITE_RETRY;
+            break;
+         }
+       else if (ret > 0)
+         {
+            /* XXX What should we do here? */
+            fprintf(stderr, "The length of the data was not written complete"
+                 " to the pipe\n");
+            return 0;
+         }
+       else if (ret == -1 && errno == EINTR)
+         /* try it again */
+         ;
+       else
+         {
+            fprintf(stderr, "An unhandled error (ret: %d errno: %d)"
+                  "occured while writing to the pipe the length\n",
+                  ret, errno);
+         }
+     }
+   while (retry--);
+
+   if (retry != ECORE_PIPE_WRITE_RETRY)
+     return 0;
+
+   /* and now pass the data to the pipe */
+   do
+     {
+       ret = pipe_write(p->fd_write,
+             ((unsigned char *)buffer) + already_written,
+             nbytes - already_written);
+
+       if (ret == (ssize_t)(nbytes - already_written))
+         return 1;
+       else if (ret >= 0)
+         {
+            already_written -= ret;
+            continue;
+         }
+       else if (ret == -1 && errno == EINTR)
+         /* try it again */
+         ;
+       else
+         {
+            fprintf(stderr, "An unhandled error (ret: %d errno: %d)"
+                  "occured while writing to the pipe the length\n",
+                  ret, errno);
+         }
+     }
+   while (retry--);
+
+   return 0;
+}
+
+/* Private function */
+
+static int
+_ecore_pipe_read(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__)
+{
+   Ecore_Pipe  *p;
+   double       start_time;
+
+   p = (Ecore_Pipe *)data;
+   start_time = ecore_time_get();
+
+   do
+     {
+       ssize_t       ret;
+
+       /* if we already have read some data we don't need to read the len
+        * but to finish the already started job
+        */
+       if (p->len == 0)
+         {
+            /* read the len of the passed data */
+            ret = pipe_read(p->fd_read, &p->len, sizeof(p->len));
+
+            /* catch the non error case first */
+            if (ret == sizeof(p->len))
+              ;
+            else if (ret > 0)
+              {
+                 /* XXX What should we do here? */
+                 fprintf(stderr, "Only read %d bytes from the pipe, although"
+                       " we need to read %d bytes.\n", ret, sizeof(p->len));
+              }
+            else if ((ret == 0) ||
+                      ((ret == -1) && ((errno == EINTR) || (errno == EAGAIN))))
+              return ECORE_CALLBACK_RENEW;
+            else
+              {
+                 fprintf(stderr, "An unhandled error (ret: %d errno: %d)"
+                       "occured while reading from the pipe the length\n",
+                       ret, errno);
+                 return ECORE_CALLBACK_RENEW;
+              }
+         }
+
+       if (!p->passed_data)
+         p->passed_data = malloc(p->len);
+
+       /* and read the passed data */
+       ret = pipe_read(p->fd_read,
+             ((unsigned char *)p->passed_data) + p->already_read,
+             p->len - p->already_read);
+
+       /* catch the non error case first */
+       if (ret == (ssize_t)(p->len - p->already_read))
+         {
+            p->handler((void *)p->data, p->passed_data, p->len);
+            free(p->passed_data);
+            /* reset all values to 0 */
+            p->passed_data = NULL;
+            p->already_read = 0;
+            p->len = 0;
+         }
+       else if (ret >= 0)
+         {
+            p->already_read += ret;
+            return ECORE_CALLBACK_RENEW;
+         }
+       else if (ret == -1 && (errno == EINTR || errno == EAGAIN))
+         return ECORE_CALLBACK_RENEW;
+       else
+         {
+            fprintf(stderr, "An unhandled error (ret: %d errno: %d)"
+                  "occured while reading from the pipe the data\n",
+                  ret, errno);
+            return ECORE_CALLBACK_RENEW;
+         }
+     }
+   while (ecore_time_get() - start_time < ecore_animator_frametime_get());
+
+   return ECORE_CALLBACK_RENEW;
+}