From df2d739a35438561c59fd7b652cb54558fae8650 Mon Sep 17 00:00:00 2001 From: "Jonas M. Gastal" Date: Thu, 30 Jun 2011 18:10:30 +0000 Subject: [PATCH] Ecore: ecore_pipe documentation. SVN revision: 60878 --- legacy/ecore/doc/examples.dox | 65 ++++++ legacy/ecore/src/examples/Makefile.am | 7 +- .../examples/ecore_pipe_gstreamer_example.c | 180 ++++++++++++++++ .../src/examples/ecore_pipe_simple_example.c | 66 ++++++ legacy/ecore/src/lib/ecore/ecore_pipe.c | 193 +----------------- 5 files changed, 321 insertions(+), 190 deletions(-) create mode 100644 legacy/ecore/src/examples/ecore_pipe_gstreamer_example.c create mode 100644 legacy/ecore/src/examples/ecore_pipe_simple_example.c diff --git a/legacy/ecore/doc/examples.dox b/legacy/ecore/doc/examples.dox index c2980f8393..b2437d7ce8 100644 --- a/legacy/ecore/doc/examples.dox +++ b/legacy/ecore/doc/examples.dox @@ -508,3 +508,68 @@ * 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 diff --git a/legacy/ecore/src/examples/Makefile.am b/legacy/ecore/src/examples/Makefile.am index cdb4448860..bd52823e47 100644 --- a/legacy/ecore/src/examples/Makefile.am +++ b/legacy/ecore/src/examples/Makefile.am @@ -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/legacy/ecore/src/examples/ecore_pipe_gstreamer_example.c b/legacy/ecore/src/examples/ecore_pipe_gstreamer_example.c new file mode 100644 index 0000000000..590d957bfd --- /dev/null +++ b/legacy/ecore/src/examples/ecore_pipe_gstreamer_example.c @@ -0,0 +1,180 @@ +#include +#include + +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/legacy/ecore/src/examples/ecore_pipe_simple_example.c b/legacy/ecore/src/examples/ecore_pipe_simple_example.c new file mode 100644 index 0000000000..02e8bcd39a --- /dev/null +++ b/legacy/ecore/src/examples/ecore_pipe_simple_example.c @@ -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 +#include + +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; +} diff --git a/legacy/ecore/src/lib/ecore/ecore_pipe.c b/legacy/ecore/src/lib/ecore/ecore_pipe.c index 3d5923e391..ab6ce5760c 100644 --- a/legacy/ecore/src/lib/ecore/ecore_pipe.c +++ b/legacy/ecore/src/lib/ecore/ecore_pipe.c @@ -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 - * #include - * - * 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 */