Hey,

seems a good simple start - needs to be more complete, like actually close()ing
pips on delete - also i agree with peter, ecore_pipe_add and ecore_pipe_del -
also i would add ecore events for pipe data - like ecore_con, and pass the
WHOLE data read (not just 1 void* size element at a time). yes - then u need to
handle decode of multiple bytes - but that's reality really).

so go the event + event struct with pipe data in it + ecore_pipe_add/del and
finish off the free stuff and i think you have a winner :)

I've attached a new version. I've renamed the functions, closed the fd's. I've also added an event that is added in the event queue when data is received.

About passing the whole data, i don't know how to do that. I send the pointer of the data, i thought it was sufficient. It's what is done in emotion, btw.

Vincent
/* structure (will be in ecore_private.h) */

struct _Ecore_Pipe
{
   int    fd_read;
   int    fd_write;
   int    event_data;
   void (*handler) (void *data);
};

/* code */

#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"

/*
 * 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) \
  send((fd), (char *)(buffer), sizeof(buffer), 0)

# define e_read(fd, buffer) \
  recv((fd), (char *)(buffer), sizeof(buffer), 0)

#else

# include <unistd.h>
# include <fcntl.h>

# define e_write(fd, buffer) \
  write((fd), (buffer), sizeof(buffer))

# define e_read(fd, buffer) \
  read((fd), (buffer), sizeof(buffer))

#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)
 * {
 *   GstBuffer  *buffer;
 *
 *   printf ("handler : %p\n", data);
 *   buffer = data;
 *   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);
 * }
 *
 * 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.
 * @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))
{
   Ecore_Pipe       *p;
   Ecore_Fd_Handler *fd_handler;
   int               fds[2];

   p = (Ecore_Pipe *)malloc(sizeof (Ecore_Pipe));
   if (!p)
     return NULL;

   if (e_pipe(fds))
     {
        free(p);
        return NULL;
     }

   p->fd_read = fds[0];
   p->fd_write = fds[1];
   p->handler = handler;
   p->event_data = ecore_event_type_new();

#ifndef _WIN32
   fcntl(p->fd_read, F_SETFL, O_NONBLOCK);
#endif /* _WIN32 */
   fd_handler = ecore_main_fd_handler_add(p->fd_read,
                                          ECORE_FD_READ,
                                          _ecore_pipe_read,
                                          p,
                                          NULL, NULL);

   return pipe;
}

/**
 * Free an Ecore_Pipe object created with ecore_pipe_new().
 *
 * @param p The Ecore_Pipe object to be freed.
 * @ingroup Ecore_Pipe_Group
 */
EAPI void
ecore_pipe_del(Ecore_Pipe *p)
{
   if (!p)
     return;

   close(p->fd_read);
   close(p->fd_write);
   free (p);
}

/**
 * Return the event that will be added to the event queue
 * when data is received.
 *
 * @param p The Ecore_Pipe object to be freed.
 * @return The event.
 * @ingroup Ecore_Pipe_Group
 */
EAPI int
ecore_pipe_event_get(Ecore_Pipe *p)
{
   if (!p)
     return 0;

   return p->event_data;
}

/**
 * Write on the file descriptor the data passed a parameter.
 *
 * @param p    The Ecore_Pipe object.
 * @param data The data to write in the pipe.
 * @ingroup Ecore_Pipe_Group
 */
EAPI void
ecore_pipe_write(Ecore_Pipe *p,
                 void       *data)
{
   void *buf[1];

   printf ("ecore_pipe_write : %p\n", data);
   buf[0] = data;
   e_write (p->fd_write, buf);
}

/* Private function */

static int
_ecore_pipe_read(void             *data,
                 Ecore_Fd_Handler *fd_handler)
{
   Ecore_Pipe *p;
   void       *buf[1];
   int         len;

   p = (Ecore_Pipe *)data;
   while ((len = e_read(p->fd_read, buf)) > 0)
     {
        if (len = sizeof (buf))
          {
             printf ("ecore_pipe_read : %p\n", buf[0]);
             p->handler(buf[0]);
          }
     }

   return 1;
}
-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Don't miss this year's exciting event. There's still time to save $100. 
Use priority code J8TL2D2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to