These functions wrap the pipe / write / read functions to easily integrate a loop that is in its own thread to the ecore main loop. More...

Functions

EAPI Ecore_Pipeecore_pipe_add (Ecore_Pipe_Cb handler, const void *data)
 Create two file descriptors (sockets on Windows).
EAPI void * ecore_pipe_del (Ecore_Pipe *p)
 Free an Ecore_Pipe object created with ecore_pipe_add().
EAPI Eina_Bool ecore_pipe_write (Ecore_Pipe *p, const void *buffer, unsigned int nbytes)
 Write on the file descriptor the data passed as parameter.
EAPI void ecore_pipe_write_close (Ecore_Pipe *p)
 Close the write end of an Ecore_Pipe object created with ecore_pipe_add().
EAPI void ecore_pipe_read_close (Ecore_Pipe *p)
 Close the read end of an Ecore_Pipe object created with ecore_pipe_add().

Detailed Description

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.

 #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;
 }

Function Documentation

EAPI Ecore_Pipe* ecore_pipe_add ( Ecore_Pipe_Cb  handler,
const void *  data 
)

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.

Parameters:
handlerThe handler called when data is received.
dataData to pass to handler when it is called.
Returns:
A newly created Ecore_Pipe object if successful. NULL otherwise.

References ECORE_FD_READ, and ecore_main_fd_handler_add().

Referenced by ecore_thread_feedback_run().

EAPI void* ecore_pipe_del ( Ecore_Pipe p)

Free an Ecore_Pipe object created with ecore_pipe_add().

Parameters:
pThe Ecore_Pipe object to be freed.
Returns:
The pointer to the private data

References ecore_main_fd_handler_del().

Referenced by ecore_thread_feedback_run().

EAPI void ecore_pipe_read_close ( Ecore_Pipe p)

Close the read end of an Ecore_Pipe object created with ecore_pipe_add().

Parameters:
pThe Ecore_Pipe object.

References ecore_main_fd_handler_del().

EAPI Eina_Bool ecore_pipe_write ( Ecore_Pipe p,
const void *  buffer,
unsigned int  nbytes 
)

Write on the file descriptor the data passed as parameter.

Parameters:
pThe Ecore_Pipe object.
bufferThe data to write into the pipe.
nbytesThe size of the buffer in bytes
Returns:
Returns EINA_TRUE on a successful write, EINA_FALSE on an error

Referenced by ecore_thread_feedback().

EAPI void ecore_pipe_write_close ( Ecore_Pipe p)

Close the write end of an Ecore_Pipe object created with ecore_pipe_add().

Parameters:
pThe Ecore_Pipe object.