-/*
- * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
- */
-#include <stdlib.h>
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#ifdef HAVE_EVIL
-# include <Evil.h>
-#endif
-#include "ecore_private.h"
-#include "Ecore.h"
-
-struct _Ecore_Pipe
-{
- ECORE_MAGIC;
- int fd_read;
- int fd_write;
- Ecore_Fd_Handler *fd_handler;
- void (*handler) (void *data, void *buffer, int nbyte);
- const void *data;
-};
-
-/*
- * 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' think of a solution where the win32
- * code is in Evil and not here.
- */
-
-#ifdef _WIN32
-
-# include <winsock2.h>
-
-# define e_write(fd, buffer, size) send((fd), (char *)(buffer), size, 0)
-# define e_read(fd, buffer, size) recv((fd), (char *)(buffer), size, 0)
-
-#else
-
-# include <unistd.h>
-# include <fcntl.h>
-
-# define e_write(fd, buffer, size) write((fd), buffer, size)
-# define e_read(fd, buffer, size) read((fd), buffer, size)
-# define e_pipe(mod) pipe(mod)
-
-#endif /* _WIN32 */
-
-
-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 *buffer, int nbyte)
- * {
- * GstBuffer *gbuffer;
- *
- * printf ("handler : %p\n", data);
- * gbuffer = buffer;
- * printf ("frame : %d %p %lld %p\n", nbr++, data, (long long)GST_BUFFER_DURATION(gbuffer), gbuffer);
- * gst_buffer_unref (gbuffer);
- * }
- *
- *
- * 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);
- * }
- *
- * 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, int nbyte),
- const void *data)
-{
- Ecore_Pipe *p;
- Ecore_Fd_Handler *fd_handler;
- int fds[2];
-
- if (!handler)
- return NULL;
- p = (Ecore_Pipe *)malloc(sizeof (Ecore_Pipe));
- if (!p)
- return NULL;
-
- if (e_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.
- * @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 data The data to write into the pipe.
- * @param nbytes The size of the @p data in bytes
- * @ingroup Ecore_Pipe_Group
- */
-EAPI void
-ecore_pipe_write(Ecore_Pipe *p, const void *buffer, int nbytes)
-{
- if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE))
- {
- ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE,
- "ecore_pipe_write");
- return;
- }
- /* first write the len into the pipe */
- e_write(p->fd_write, &nbytes, sizeof(nbytes));
-
- /* and now pass the data to the pipe */
- e_write(p->fd_write, buffer, nbytes);
-}
-
-/* Private function */
-
-static int
-_ecore_pipe_read(void *data, Ecore_Fd_Handler *fd_handler)
-{
- Ecore_Pipe *p;
- unsigned int len;
- void *passed_data;
-
- p = (Ecore_Pipe *)data;
-
- /* read the len of the passed data */
- e_read(p->fd_read, &len, sizeof(len));
-
- /* and read the passed data */
- passed_data = malloc(len);
- e_read(p->fd_read, passed_data, len);
-
- p->handler(p->data, passed_data, len);
- free(passed_data);
-
- return ECORE_CALLBACK_RENEW;
-}
+/*\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