Ecore_Avahi: initial commit.

TODO:
- Add tests, how ?
- Integrate with Eo, needed ?
This commit is contained in:
Cedric BAIL 2013-11-10 08:51:42 +01:00 committed by Cedric BAIL
parent 99e3ce489a
commit 0a1cc79a91
13 changed files with 671 additions and 0 deletions

View File

@ -131,6 +131,7 @@ pc/ecore-input-evas.pc \
pc/ecore-imf.pc \
pc/ecore-imf-evas.pc \
pc/ecore-evas.pc \
pc/ecore-avahi.pc \
pc/embryo.pc \
pc/eio.pc \
pc/eldbus.pc \

View File

@ -2568,6 +2568,62 @@ AC_SUBST([ECORE_WIN32_LIBS])
EFL_LIB_END_OPTIONAL([Ecore_Win32])
#### End of Ecore_Win32
#### Ecore_Avahi
EFL_LIB_START([Ecore_Avahi])
### Default values
### Additional options to configure
want_avahi="yes"
AC_ARG_ENABLE([avahi],
[AC_HELP_STRING([--disable-avahi],
[disable avahi support. @<:@default=enabled@:>@])],
[
if test "x${enableval}" = "xyes" ; then
want_avahi="yes"
else
want_avahi="no"
fi
], [
want_avahi="yes"
])
### Checks for programs
### Checks for libraries
EFL_INTERNAL_DEPEND_PKG([ECORE_AVAHI], [ecore])
EFL_INTERNAL_DEPEND_PKG([ECORE_AVAHI], [eina])
EFL_INTERNAL_DEPEND_PKG([ECORE_AVAHI], [eo])
EFL_OPTIONAL_DEPEND_PKG([ECORE_AVAHI], [${want_avahi}], [AVAHI], [avahi-client])
EFL_ADD_FEATURE([ECORE_AVAHI], [avahi-client], [${have_avahi}])
# Needed bu example as they use avahi directly in that case
if test "x${have_avahi}" = "xyes"; then
PKG_CHECK_MODULES([AVAHI_CLIENT], [avahi-client])
fi
EFL_EVAL_PKGS([Ecore_Avahi])
### Checks for header files
### Checks for types
### Checks for structures
### Checks for compiler characteristics
### Checks for linker characteristics
### Checks for library functions
EFL_LIB_END([Ecore_Avahi])
#### End of Ecore_Avahi
#### Ecore_WinCE
EFL_LIB_START_OPTIONAL([Ecore_WinCE], [test "${have_wince}" = "yes"])
@ -3748,6 +3804,7 @@ src/examples/eet/Makefile
src/examples/eo/Makefile
src/examples/evas/Makefile
src/examples/ecore/Makefile
src/examples/ecore_avahi/Makefile
src/examples/eio/Makefile
src/examples/eldbus/Makefile
src/examples/ephysics/Makefile
@ -3795,6 +3852,7 @@ pc/ecore-evas.pc
pc/ecore-imf.pc
pc/ecore-imf-evas.pc
pc/ecore-audio.pc
pc/ecore-avahi.pc
pc/embryo.pc
pc/eio.pc
pc/eldbus.pc
@ -3914,6 +3972,7 @@ echo "Ecore_Win32.....: $have_win32"
echo "Ecore_WinCE.....: $have_wince"
fi
echo "Ecore_Audio.....: ${efl_lib_optional_ecore_audio} (${features_ecore_audio})"
echo "Ecore_Avahi.....: yes (${features_ecore_avahi})"
echo "Ecore_Evas......: yes (${features_ecore_evas})"
echo "Eeze............: ${efl_lib_optional_eeze} (${features_eeze})"
echo "EPhysics........: ${efl_lib_optional_ephysics}"

1
pc/.gitignore vendored
View File

@ -1,3 +1,4 @@
/ecore-avahi.pc
/ecore-audio.pc
/ecore-cocoa.pc
/ecore-con.pc

12
pc/ecore-avahi.pc.in Normal file
View File

@ -0,0 +1,12 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: ecore-avahi
Description: E core library, avahi integration
Requires.private: @requirements_pc_ecore_avahi@
Version: @VERSION@
Libs: -L${libdir} -lecore_avahi
Libs.private: @requirements_libs_ecore_avahi@
Cflags: -I${includedir}/efl-@VMAJ@ -I${includedir}/efl-@VMAJ@ -I${includedir}/ecore-avahi-@VMAJ@

View File

@ -44,6 +44,7 @@ include Makefile_Ecore_IMF.am
include Makefile_Ecore_IMF_Evas.am
include Makefile_Ecore_Evas.am
include Makefile_Ecore_Audio.am
include Makefile_Ecore_Avahi.am
include Makefile_Embryo.am
include Makefile_Eio.am
include Makefile_Eldbus.am
@ -74,6 +75,7 @@ examples/eo \
examples/eet \
examples/evas \
examples/ecore \
examples/ecore_avahi \
examples/eio \
examples/eldbus \
examples/ephysics \

View File

@ -0,0 +1,16 @@
### Library
lib_LTLIBRARIES += lib/ecore_avahi/libecore_avahi.la
installed_ecoreavahimainheadersdir = $(includedir)/ecore-avahi-@VMAJ@
dist_installed_ecoreavahimainheaders_DATA = \
lib/ecore_avahi/Ecore_Avahi.h
lib_ecore_avahi_libecore_avahi_la_SOURCES = \
lib/ecore_avahi/ecore_avahi.c
lib_ecore_avahi_libecore_avahi_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @ECORE_AVAHI_CFLAGS@
lib_ecore_avahi_libecore_avahi_la_LIBADD = @ECORE_AVAHI_LIBS@
lib_ecore_avahi_libecore_avahi_la_DEPENDENCIES = @ECORE_AVAHI_INTERNAL_LIBS@
lib_ecore_avahi_libecore_avahi_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@

1
src/examples/ecore_avahi/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
ecore_avahi_example

View File

@ -0,0 +1,35 @@
MAINTAINERCLEANFILES = Makefile.in
AM_CPPFLAGS = \
-I$(top_builddir)/src/lib/efl \
-I$(top_srcdir)/src/lib/eina \
-I$(top_srcdir)/src/lib/eo \
-I$(top_srcdir)/src/lib/ecore \
-I$(top_srcdir)/src/lib/ecore_avahi\
-I$(top_builddir)/src/lib/eina \
-I$(top_builddir)/src/lib/eo \
-I$(top_builddir)/src/lib/ecore \
-I$(top_builddir)/src/lib/ecore_avahi \
@AVAHI_CLIENT_CFLAGS@
EXTRA_PROGRAMS = \
ecore_avahi_example
ecore_avahi_example_SOURCES = ecore_avahi_example.c
ecore_avahi_example_LDADD = $(top_builddir)/src/lib/ecore/libecore.la \
$(top_builddir)/src/lib/ecore_avahi/libecore_avahi.la \
$(top_builddir)/src/lib/eo/libeo.la \
$(top_builddir)/src/lib/eina/libeina.la \
@AVAHI_CLIENT_LIBS@
examples: $(EXTRA_PROGRAMS)
clean-local:
rm -f $(EXTRA_PROGRAMS)
install-examples:
mkdir -p $(datadir)/ecore_avahi/examples
$(install_sh_DATA) -c ecore_avahi_example.c $(datadir)/ecore_avahi/examples
uninstall-local:
rm -f $(datadir)/ecore_avahi/examples/ecore_avahi_example.c

View File

@ -0,0 +1,187 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#ifdef HAVE_AVAHI
#include <avahi-client/client.h>
#include <avahi-client/lookup.h>
#include <avahi-client/publish.h>
#include <avahi-common/simple-watch.h>
#include <avahi-common/malloc.h>
#include <avahi-common/error.h>
#include <avahi-common/alternative.h>
#include <avahi-common/timeval.h>
#include <Ecore.h>
#include <Ecore_Avahi.h>
typedef struct _Ecore_Avahi_Example Ecore_Avahi_Example;
struct _Ecore_Avahi_Example
{
AvahiClient *client;
AvahiEntryGroup *group;
const char *server;
int port;
};
static void
_ecore_avahi_group_cb(AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata)
{
Ecore_Avahi_Example *example = userdata;
switch (state)
{
case AVAHI_ENTRY_GROUP_ESTABLISHED :
/* The entry group has been established successfully */
fprintf(stderr, "Service '%s' successfully established.\n", example->server);
break;
case AVAHI_ENTRY_GROUP_COLLISION :
fprintf(stderr, "Service name collision.\n");
ecore_main_loop_quit();
break;
case AVAHI_ENTRY_GROUP_FAILURE :
fprintf(stderr, "Entry group failure: %s\n", avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g))));
/* Some kind of failure happened while we were registering our services */
ecore_main_loop_quit();
break;
case AVAHI_ENTRY_GROUP_UNCOMMITED:
case AVAHI_ENTRY_GROUP_REGISTERING:
;
}
}
static void
_ecore_avahi_service_create(AvahiClient *c, Ecore_Avahi_Example *example)
{
int error;
example->group = avahi_entry_group_new(c, _ecore_avahi_group_cb, example);
if (!example->group)
{
fprintf(stderr, "avahi_entry_group_new() failed: %s\n", avahi_strerror(avahi_client_errno(c)));
goto fail;
}
/* If the group is empty (either because it was just created, or
* because it was reset previously, add our entries. */
if (!avahi_entry_group_is_empty(example->group)) return ;
error = avahi_entry_group_add_service(example->group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0,
example->server, "_ipp._tcp", NULL, NULL, example->port, "name=ThisIsATest", NULL);
if (error < 0)
{
fprintf(stderr, "Failed to add _ipp._tcp service with error: %s.\n", avahi_strerror(error));
goto fail;
}
error = avahi_entry_group_commit(example->group);
if (error < 0)
{
fprintf(stderr, "Failed to commit entry group with error: %s\n", avahi_strerror(error));
goto fail;
}
return ;
fail:
ecore_main_loop_quit();
}
static void
_ecore_avahi_client_cb(AvahiClient *c, AvahiClientState state, void * userdata)
{
Ecore_Avahi_Example *example = userdata;
switch (state)
{
case AVAHI_CLIENT_S_RUNNING:
/* The server has started successfully and registered its host
* name on the network, so it's time to create our services */
_ecore_avahi_service_create(c, example);
break;
case AVAHI_CLIENT_FAILURE:
fprintf(stderr, "Avahi client failure: %s\n", avahi_strerror(avahi_client_errno(c)));
break;
case AVAHI_CLIENT_S_COLLISION:
/* Let's drop our registered services. When the server is back
* in AVAHI_SERVER_RUNNING state we will register them
* again with the new host name. */
case AVAHI_CLIENT_S_REGISTERING:
/* The server records are now being established. This
* might be caused by a host name change. We need to wait
* for our own records to register until the host name is
* properly esatblished. */
if (example->group) avahi_entry_group_reset(example->group);
break;
case AVAHI_CLIENT_CONNECTING:
;
}
}
int
main(int argc, char **argv)
{
Ecore_Avahi_Example example = { 0 };
Ecore_Avahi *handler;
const AvahiPoll *poll_api;
int exit_code = 0;
int error = 0;
if (argc < 3)
{
fprintf(stderr, "Usage : %s name port\n", argv[0]);
return -1;
}
eina_init();
ecore_init();
handler = ecore_avahi_add();
poll_api = ecore_avahi_poll_get(handler);
if (!poll_api)
{
fprintf(stderr, "Build EFL with Avahi support.\n");
exit_code = -1;
goto fail;
}
example.server = eina_stringshare_add(argv[1]);
example.port = atoi(argv[2]);
example.client = avahi_client_new(poll_api, AVAHI_CLIENT_NO_FAIL, _ecore_avahi_client_cb, &example, &error);
if (!example.client)
{
fprintf(stderr, "Failed to create avahi client: %s.\n", avahi_strerror(error));
exit_code = -1;
goto fail;
}
ecore_main_loop_begin();
avahi_client_free(example.client);
fail:
eina_stringshare_del(example.server);
ecore_shutdown();
eina_shutdown();
return exit_code;
}
#else
int
main(int argc, char **argv)
{
fprintf(stderr, "This example require Avahi to be build !\n");
}
#endif

View File

@ -179,6 +179,7 @@ EAPI void *ecore_timer_del(Ecore_Timer *timer);
EAPI void ecore_timer_interval_set(Ecore_Timer *timer, double in);
EAPI double ecore_timer_interval_get(Ecore_Timer *timer);
EAPI void ecore_timer_freeze(Ecore_Timer *timer);
EAPI Eina_Bool ecore_timer_freeze_get(Ecore_Timer *timer);
EAPI void ecore_timer_thaw(Ecore_Timer *timer);
EAPI void ecore_timer_delay(Ecore_Timer *timer, double add);
EAPI void ecore_timer_reset(Ecore_Timer *timer);

View File

@ -485,6 +485,26 @@ unlock:
_ecore_unlock();
}
EAPI Eina_Bool
ecore_timer_freeze_get(Ecore_Timer *timer)
{
int r = 0;
eo_do(timer, eo_event_freeze_get(&r));
return !!r;
}
static void
_timer_freeze_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
{
EINA_MAIN_LOOP_CHECK_RETURN;
Ecore_Timer_Private_Data *timer = _pd;
int *r = va_arg(*list, int*);
if (r) *r = timer->frozen;
}
/**
* Resumes a frozen (paused) timer.
*
@ -989,6 +1009,7 @@ _class_constructor(Eo_Class *klass)
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_EVENT_FREEZE), _timer_freeze),
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_EVENT_THAW), _timer_thaw),
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_EVENT_FREEZE_GET), _timer_freeze_get),
EO_OP_FUNC(ECORE_TIMER_ID(ECORE_TIMER_SUB_ID_DELAY), _timer_delay),
EO_OP_FUNC(ECORE_TIMER_ID(ECORE_TIMER_SUB_ID_RESET), _timer_reset),

View File

@ -0,0 +1,88 @@
/**
@brief Ecore Avahi integration Library Public API Calls
These routines are used for integrating Avahi with Ecore main loop
*/
#ifndef _ECORE_AVAHI_H
# define _ECORE_AVAHI_H
#ifdef EAPI
# undef EAPI
#endif
#ifdef _WIN32
# ifdef EFL_ECORE_BUILD
# ifdef DLL_EXPORT
# define EAPI __declspec(dllexport)
# else
# define EAPI
# endif /* ! DLL_EXPORT */
# else
# define EAPI __declspec(dllimport)
# endif /* ! EFL_ECORE_BUILD */
#else
# ifdef __GNUC__
# if __GNUC__ >= 4
# define EAPI __attribute__ ((visibility("default")))
# else
# define EAPI
# endif
# else
# define EAPI
# endif
#endif /* ! _WIN32 */
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup Ecore_Avahi Ecore main loop integration function.
* @ingroup Ecore
*
* @{
*/
/**
* @since 1.9
*/
typedef struct _Ecore_Avahi Ecore_Avahi; /**< A handle for an Avahi instance. */
/**
* @brief Create an AvahiPoll context and integrate it within Ecore main loop.
*
* @return A handler that reference the AvahiPoll context
* @since 1.9
*/
EAPI Ecore_Avahi *ecore_avahi_add(void);
/**
* @brief Delete the specified handler of an AvahiPoll.
*
* @param handler The actual handler to destroy.
* @since 1.9
*
* Be aware there should not be any reference still using that handler before
* destroying it.
*/
EAPI void ecore_avahi_del(Ecore_Avahi *handler);
/**
* @brief Get the AvahiPoll structure to integrate with Ecore main loop.
*
* @param handler The handler to get the AvahiPoll structure from.
* @return return the actual AvahiPoll structure to use with Avahi.
* @since 1.9
*/
EAPI const void *ecore_avahi_poll_get(Ecore_Avahi *handler); // return AvahiPoll
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,247 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <Eina.h>
#include <Ecore.h>
#include "Ecore_Avahi.h"
#ifdef HAVE_AVAHI
#include <avahi-common/watch.h>
typedef struct _Ecore_Avahi_Watch Ecore_Avahi_Watch;
typedef struct _Ecore_Avahi_Timeout Ecore_Avahi_Timeout;
struct _Ecore_Avahi_Watch
{
Ecore_Fd_Handler *handler;
Ecore_Avahi *parent;
AvahiWatchCallback callback;
void *callback_data;
};
struct _Ecore_Avahi_Timeout
{
Ecore_Timer *timer;
Ecore_Avahi *parent;
AvahiTimeoutCallback callback;
void *callback_data;
};
struct _Ecore_Avahi
{
AvahiPoll api;
Eina_List *watches;
Eina_List *timeouts;
};
static Ecore_Fd_Handler_Flags
_ecore_avahi_events2ecore(AvahiWatchEvent events)
{
return (events & AVAHI_WATCH_IN ? ECORE_FD_READ : 0) |
(events & AVAHI_WATCH_OUT ? ECORE_FD_WRITE : 0) |
(events & AVAHI_WATCH_ERR ? ECORE_FD_ERROR : 0);
}
static Eina_Bool
_ecore_avahi_watch_cb(void *data, Ecore_Fd_Handler *fd_handler)
{
Ecore_Avahi_Watch *watch = data;
AvahiWatchEvent flags = 0;
flags = ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ) ? AVAHI_WATCH_IN : 0;
flags |= ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE) ? AVAHI_WATCH_OUT : 0;
flags |= ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR) ? AVAHI_WATCH_ERR : 0;
watch->callback((AvahiWatch*) watch, ecore_main_fd_handler_fd_get(fd_handler), flags, watch->callback_data);
return ECORE_CALLBACK_RENEW;
}
static AvahiWatch *
_ecore_avahi_watch_new(const AvahiPoll *api,
int fd, AvahiWatchEvent events,
AvahiWatchCallback callback, void *userdata)
{
Ecore_Avahi_Watch *watch;
Ecore_Avahi *ea;
ea = api->userdata;
watch = calloc(1, sizeof (Ecore_Avahi_Watch));
if (!watch) return NULL;
watch->handler = ecore_main_fd_handler_add(fd, _ecore_avahi_events2ecore(events),
_ecore_avahi_watch_cb, watch, NULL, NULL);
watch->callback = callback;
watch->callback_data = userdata;
watch->parent = ea;
ea->watches = eina_list_append(ea->watches, watch);
return (AvahiWatch*) watch;
}
static void
_ecore_avahi_watch_update(AvahiWatch *w, AvahiWatchEvent events)
{
Ecore_Avahi_Watch *watch = (Ecore_Avahi_Watch *) w;
ecore_main_fd_handler_active_set(watch->handler, _ecore_avahi_events2ecore(events));
}
static void
_ecore_avahi_watch_free(AvahiWatch *w)
{
Ecore_Avahi_Watch *watch = (Ecore_Avahi_Watch *) w;
ecore_main_fd_handler_del(watch->handler);
watch->parent->watches = eina_list_remove(watch->parent->watches, watch);
free(watch);
}
static AvahiWatchEvent
_ecore_avahi_watch_get_events(AvahiWatch *w)
{
Ecore_Avahi_Watch *watch = (Ecore_Avahi_Watch *) w;
AvahiWatchEvent flags = 0;
flags = ecore_main_fd_handler_active_get(watch->handler, ECORE_FD_READ) ? AVAHI_WATCH_IN : 0;
flags |= ecore_main_fd_handler_active_get(watch->handler, ECORE_FD_WRITE) ? AVAHI_WATCH_OUT : 0;
flags |= ecore_main_fd_handler_active_get(watch->handler, ECORE_FD_ERROR) ? AVAHI_WATCH_ERR : 0;
return flags;
}
static double
_ecore_avahi_timeval2double(const struct timeval *tv)
{
if (!tv) return 3600;
return tv->tv_sec + (double) tv->tv_usec / 1000000;
}
static Eina_Bool
_ecore_avahi_timeout_cb(void *data)
{
Ecore_Avahi_Timeout *timeout = data;
ecore_timer_freeze(timeout->timer);
timeout->callback((AvahiTimeout*) timeout, timeout->callback_data);
return ECORE_CALLBACK_RENEW;
}
static AvahiTimeout *
_ecore_avahi_timeout_new(const AvahiPoll *api, const struct timeval *tv,
AvahiTimeoutCallback callback, void *userdata)
{
Ecore_Avahi_Timeout *timeout;
Ecore_Avahi *ea;
ea = api->userdata;
timeout = calloc(1, sizeof (Ecore_Avahi_Timeout));
if (!timeout) return NULL;
timeout->timer = ecore_timer_add(_ecore_avahi_timeval2double(tv), _ecore_avahi_timeout_cb, timeout);
if (!tv) ecore_timer_freeze(timeout->timer);
timeout->callback = callback;
timeout->callback_data = userdata;
timeout->parent = ea;
ea->timeouts = eina_list_append(ea->timeouts, timeout);
return (AvahiTimeout*) timeout;
}
static void
_ecore_avahi_timeout_update(AvahiTimeout *t, const struct timeval *tv)
{
Ecore_Avahi_Timeout *timeout = (Ecore_Avahi_Timeout *) t;
if (tv)
{
ecore_timer_interval_set(timeout->timer, _ecore_avahi_timeval2double(tv));
if (ecore_timer_freeze_get(timeout->timer))
ecore_timer_thaw(timeout->timer);
}
else
{
ecore_timer_freeze(timeout->timer);
}
}
static void
_ecore_avahi_timeout_free(AvahiTimeout *t)
{
Ecore_Avahi_Timeout *timeout = (Ecore_Avahi_Timeout *) t;
ecore_timer_del(timeout->timer);
timeout->parent->timeouts = eina_list_remove(timeout->parent->timeouts, timeout);
free(timeout);
}
#endif
EAPI Ecore_Avahi *
ecore_avahi_add(void)
{
#ifdef HAVE_AVAHI
Ecore_Avahi *handler;
handler = calloc(1, sizeof (Ecore_Avahi));
if (!handler) return NULL;
handler->api.userdata = handler;
handler->api.watch_new = _ecore_avahi_watch_new;
handler->api.watch_free = _ecore_avahi_watch_free;
handler->api.watch_update = _ecore_avahi_watch_update;
handler->api.watch_get_events = _ecore_avahi_watch_get_events;
handler->api.timeout_new = _ecore_avahi_timeout_new;
handler->api.timeout_free = _ecore_avahi_timeout_free;
handler->api.timeout_update = _ecore_avahi_timeout_update;
return handler;
#else
return NULL;
#endif
}
EAPI void
ecore_avahi_del(Ecore_Avahi *handler)
{
#ifdef HAVE_AVAHI
Ecore_Avahi_Timeout *timeout;
Ecore_Avahi_Watch *watch;
EINA_LIST_FREE(handler->watches, watch)
{
ecore_main_fd_handler_del(watch->handler);
free(watch);
}
EINA_LIST_FREE(handler->timeouts, timeout)
{
ecore_timer_del(timeout->timer);
free(timeout);
}
free(handler);
#else
(void) handler;
#endif
}
EAPI const void *
ecore_avahi_poll_get(Ecore_Avahi *handler)
{
#ifdef HAVE_AVAHI
if (!handler) return NULL;
return &handler->api;
#else
return NULL;
#endif
}