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