Ecore: ecore_pipe documentation.
authorgastal <gastal@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 30 Jun 2011 18:10:30 +0000 (18:10 +0000)
committergastal <gastal@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 30 Jun 2011 18:10:30 +0000 (18:10 +0000)
git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/ecore@60878 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

doc/examples.dox
src/examples/Makefile.am
src/examples/ecore_pipe_gstreamer_example.c [new file with mode: 0644]
src/examples/ecore_pipe_simple_example.c [new file with mode: 0644]
src/lib/ecore/ecore_pipe.c

index c2980f8..b2437d7 100644 (file)
  * Shows how to use fd handlers.
 */
 
+/**
+ * @page tutorial_ecore_pipe_gstreamer_example
+ *
+ * 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.
+ *
+ * @include ecore_pipe_gstreamer_example.c
+ * @example ecore_pipe_gstreamer_example.c
+ */
+
+/**
+ * @page tutorial_ecore_pipe_simple_example
+ * @dontinclude ecore_pipe_simple_example.c
+ *
+ * This example shows some simple usage of ecore_pipe. We are going to create a
+ * pipe, fork our process, and then the child is going to comunicate to the
+ * parent the result of its processing through the pipe.
+ *
+ * As always we start with our includes, nothing especial:
+ * @skip #include
+ * @until Ecore.h
+ *
+ * The first thing we are going to define in our example is the function we are
+ * going to run on the child process, which, as mentioned, will do some
+ * processing and then will write the result to the pipe:
+ * @until }
+ * @until }
+ * @note The sleep was added so the parent process would think the child process
+ * was doing something interesting...
+ *
+ * Next up is our function for handling data arriving in the pipe. It copies the
+ * data to another buffer, adds a terminating NULL and prints it. Also if it
+ * receives a certain string it stops the main loop(efectvely ending the
+ * program):
+ * @until }
+ * @until }
+ *
+ * And now on to our main function, we start by declaring some variables and
+ * initializing ecore:
+ * @until ecore_init
+ *
+ * And since we are talking about pipes let's create one:
+ * @until pipe_add
+ *
+ * Now we are going to fork:
+ * @until fork
+ * @note duh...
+ *
+ * The child process is going to do the our fancy processing:
+ * @until }
+ * @note It's very important to call ecore_pipe_read_close() here so that the
+ * child process won't read what it is writing to the pipe itself.
+ *
+ * And the parent is going to run ecore's main loop waiting for some data:
+ * @until }
+ * @note Calling ecore_pipe_write_close() here isn't important but since we
+ * aren't going to write in the pipe it is good practice.
+ *
+ * And finally when done processing(the child) or done receiving(the parent) we
+ * delete the pipe and shutdown ecore:
+ * @until }
+ *
+ * @example ecore_pipe_simple_example.c
+ */
\ No newline at end of file
index cdb4448..bd52823 100644 (file)
@@ -24,7 +24,9 @@ SRCS = \
        ecore_con_client_example.c \
        ecore_con_server_example.c \
        ecore_fd_handler_gnutls_example.c \
-       ecore_file_download_example.c
+       ecore_file_download_example.c \
+       ecore_pipe_simple_example.c \
+       ecore_pipe_gstreamer_example.c
 
 EXTRA_DIST = $(SRCS)
 
@@ -43,6 +45,7 @@ pkglib_PROGRAMS += \
        ecore_idler_example \
        ecore_job_example \
        ecore_timer_example \
-       ecore_time_functions_example
+       ecore_time_functions_example \
+       ecore_pipe_simple_example
 endif
 
diff --git a/src/examples/ecore_pipe_gstreamer_example.c b/src/examples/ecore_pipe_gstreamer_example.c
new file mode 100644 (file)
index 0000000..590d957
--- /dev/null
@@ -0,0 +1,180 @@
+#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_del (pipe);
+    ecore_shutdown ();
+    gst_deinit ();
+    return -1;
+  }
+
+  gst_element_set_state (pipeline, GST_STATE_PLAYING);
+
+  ecore_main_loop_begin();
+
+  ecore_pipe_del (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", EINA_TRUE, NULL);
+  g_object_set (G_OBJECT (sink), "signal-handoffs", EINA_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;
+}
diff --git a/src/examples/ecore_pipe_simple_example.c b/src/examples/ecore_pipe_simple_example.c
new file mode 100644 (file)
index 0000000..02e8bcd
--- /dev/null
@@ -0,0 +1,66 @@
+//Compile with:
+//gcc -g -Wall `pkg-config --cflags --libs ecore` -o ecore_pipe_simple_example ecore_pipe_simple_example.c
+
+#include <unistd.h>
+#include <Ecore.h>
+
+static void
+do_lengthy_task(Ecore_Pipe *pipe)
+{
+   int i, j;
+   char *buffer;
+   for (i = 0; i < 20; i++)
+     {
+        sleep(1);
+        buffer = malloc(sizeof(char) * i);
+        for (j = 0; j < i; j++)
+           buffer[j] = 'a' + j;
+        ecore_pipe_write(pipe, buffer, i);
+        free(buffer);
+     }
+   ecore_pipe_write(pipe, "close", 5);
+}
+
+static void
+handler(void *data, void *buf, unsigned int len)
+{
+   char *str = malloc(sizeof(char) * len + 1);
+   memcpy(str, buf, len);
+   str[len] = '\0';
+   printf("received %d bytes\n", len);
+   printf("content: %s\n", (const char*)str);
+   free(str);
+   if (len && !strncmp(buf, "close", len < 5 ? len : 5))
+     {
+        printf("close requested\n");
+        ecore_main_loop_quit();
+     }
+}
+
+int
+main (int argc, char *argv[])
+{
+   Ecore_Pipe *pipe;
+   pid_t child_pid;
+
+   ecore_init();
+
+   pipe = ecore_pipe_add(handler, NULL);
+
+   child_pid = fork();
+   if(!child_pid)
+     {
+        ecore_pipe_read_close(pipe);
+        do_lengthy_task(pipe);
+     }
+   else
+     {
+        ecore_pipe_write_close(pipe);
+        ecore_main_loop_begin();
+     }
+
+   ecore_pipe_del(pipe);
+   ecore_shutdown();
+
+   return 0;
+}
index 3d5923e..ab6ce57 100644 (file)
@@ -98,9 +98,8 @@ static Eina_Bool _ecore_pipe_read(void *data, Ecore_Fd_Handler *fd_handler);
 /**
  * @addtogroup 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.
+ * These functions wrap the pipe / write / read functions to easily integrate
+ * its use into ecore's 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
@@ -108,191 +107,9 @@ static Eina_Bool _ecore_pipe_read(void *data, Ecore_Fd_Handler *fd_handler);
  * 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_del (pipe);
- *     ecore_shutdown ();
- *     gst_deinit ();
- *     return -1;
- *   }
- *
- *   gst_element_set_state (pipeline, GST_STATE_PLAYING);
- *
- *   ecore_main_loop_begin();
- *
- *   ecore_pipe_del (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", EINA_TRUE, NULL);
- *   g_object_set (G_OBJECT (sink), "signal-handoffs", EINA_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
+ * For examples see here:
+ * @li @ref tutorial_ecore_pipe_gstreamer_example
+ * @li @ref tutorial_ecore_pipe_simple_example
  */