diff options
author | Laurent Ghigonis <laurent@p1sec.com> | 2013-02-27 19:51:09 +0100 |
---|---|---|
committer | Laurent Ghigonis <laurent@p1sec.com> | 2013-02-27 19:51:09 +0100 |
commit | 69334f06424f8defa980421c5e632eb23ec8015c (patch) | |
tree | ca81fdd7dd91b46a905eb81f66b4e95791125a16 /gg_elife | |
parent | Merge egraph repository in glouglou repository (diff) | |
parent | if gg_packet type is not about packets, do not inject pattern (diff) | |
download | glouglou-69334f06424f8defa980421c5e632eb23ec8015c.tar.xz glouglou-69334f06424f8defa980421c5e632eb23ec8015c.zip |
Merge elife repository in glouglou repository in gg_elife/
Diffstat (limited to 'gg_elife')
-rw-r--r-- | gg_elife/.gitignore | 68 | ||||
-rw-r--r-- | gg_elife/AUTHORS | 1 | ||||
-rw-r--r-- | gg_elife/COPYING | 1 | ||||
-rw-r--r-- | gg_elife/ChangeLog | 1 | ||||
-rw-r--r-- | gg_elife/Makefile.am | 6 | ||||
-rw-r--r-- | gg_elife/NEWS | 6 | ||||
-rw-r--r-- | gg_elife/README | 79 | ||||
-rwxr-xr-x | gg_elife/autogen.sh | 17 | ||||
-rw-r--r-- | gg_elife/configure.ac | 64 | ||||
-rw-r--r-- | gg_elife/data/Makefile.am | 18 | ||||
-rw-r--r-- | gg_elife/data/elife.edc | 48 | ||||
-rw-r--r-- | gg_elife/m4/efl_binary.m4 | 71 | ||||
-rw-r--r-- | gg_elife/src/Makefile.am | 37 | ||||
-rw-r--r-- | gg_elife/src/elife.c | 106 | ||||
-rw-r--r-- | gg_elife/src/elife_edje_external.c | 192 | ||||
-rw-r--r-- | gg_elife/src/elife_evas_smart.c | 558 | ||||
-rw-r--r-- | gg_elife/src/elife_evas_smart.h | 8 |
17 files changed, 1281 insertions, 0 deletions
diff --git a/gg_elife/.gitignore b/gg_elife/.gitignore new file mode 100644 index 0000000..a8e7ece --- /dev/null +++ b/gg_elife/.gitignore @@ -0,0 +1,68 @@ +/INSTALL +/Makefile +/Makefile.in +/aclocal.m4 +/autom4te.cache/ +/config.guess +/config.h +/config.h.in +/config.log +/config.status +/config.sub +/configure +/depcomp +/install-sh +/libtool +/ltmain.sh +/m4/libtool.m4 +/m4/ltoptions.m4 +/m4/ltsugar.m4 +/m4/ltversion.m4 +/m4/lt~obsolete.m4 +/missing +/src/.deps/ +/src/.libs/ +/src/Makefile +/src/Makefile.in +/src/elife +/src/*.lo +/src/*.o +/src/module.la +/stamp-h1 +/compile +/data/Makefile +/data/Makefile.in +/data/elife.edj +/intl +/ABOUT-NLS +/config.rpath +/m4/codeset.m4 +/m4/gettext.m4 +/m4/glibc2.m4 +/m4/glibc21.m4 +/m4/iconv.m4 +/m4/intdiv0.m4 +/m4/intl.m4 +/m4/intldir.m4 +/m4/intlmacosx.m4 +/m4/intmax.m4 +/m4/inttypes-pri.m4 +/m4/inttypes_h.m4 +/m4/lcmessage.m4 +/m4/lib-ld.m4 +/m4/lib-link.m4 +/m4/lib-prefix.m4 +/m4/lock.m4 +/m4/longlong.m4 +/m4/nls.m4 +/m4/po.m4 +/m4/printf-posix.m4 +/m4/progtest.m4 +/m4/size_max.m4 +/m4/stdint_h.m4 +/m4/uintmax_t.m4 +/m4/visibility.m4 +/m4/wchar_t.m4 +/m4/wint_t.m4 +/m4/xsize.m4 +/po/ diff --git a/gg_elife/AUTHORS b/gg_elife/AUTHORS new file mode 100644 index 0000000..4e42cdc --- /dev/null +++ b/gg_elife/AUTHORS @@ -0,0 +1 @@ +Laurent Ghigonis <laurent@p1sec.com> diff --git a/gg_elife/COPYING b/gg_elife/COPYING new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/gg_elife/COPYING @@ -0,0 +1 @@ + diff --git a/gg_elife/ChangeLog b/gg_elife/ChangeLog new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/gg_elife/ChangeLog @@ -0,0 +1 @@ + diff --git a/gg_elife/Makefile.am b/gg_elife/Makefile.am new file mode 100644 index 0000000..215bf9f --- /dev/null +++ b/gg_elife/Makefile.am @@ -0,0 +1,6 @@ +AUTOMAKE_OPTIONS = 1.4 foreign +MAINTAINERCLEANFILES = Makefile.in + +SUBDIRS = src data + +ACLOCAL_AMFLAGS = -I m4 diff --git a/gg_elife/NEWS b/gg_elife/NEWS new file mode 100644 index 0000000..5c5261f --- /dev/null +++ b/gg_elife/NEWS @@ -0,0 +1,6 @@ +bal$ git log --reverse --tags --simplify-by-decoration --pretty="format:%ai %d" +2012-10-14 16:35:56 +0200 +2012-11-04 18:59:46 +0100 (v1.0) +2012-11-04 19:14:50 +0100 (v1.1) +2012-11-05 04:09:01 +0100 (origin/master, origin/manual_draw, manual_draw) +2012-11-05 04:12:52 +0100 (HEAD, v1.2, master) diff --git a/gg_elife/README b/gg_elife/README new file mode 100644 index 0000000..1906131 --- /dev/null +++ b/gg_elife/README @@ -0,0 +1,79 @@ +elife - Game of life / Living graphic +v1.2 + +Packaging and general structure from EEnvader.fractal by Boris Faure <billiob@gmail.com> +Many thanks to you Boris ! + +Dependencies +============ + +Enlightenment 0.16.999 (aka e17) + +Install +======= + +./autogen.sh +make +sudo make install + +"elife" will then appear in the "System" category of e17 wallpapers configuration panel. +A binary called "elife" is also created and installed to run elife in standalone. + +Glouglou support +================ + +To enable glouglou support, pass --enable-glouglou to automake scripts : +./autogen.sh --enable-glouglou +OR +./configure --enable-glouglou + +You will need libglouglou and glougloud + +Elife slows down my e17 ! +========================= + +elife is running in the same process as e17 therefore it can slow down the +whole window manager, depending on your machine CPU. + +To improve this, you can: + +* Use OpenGL rendering in e17 by using the Composite module, and set the engine +to OpenGL in Composite > Rendering pannel + +* Reduce the size of the elife grid by modifying the source code, in +src/elife_evas_smart.c at the definitions of NCELL_X and NCELL_Y + +TODO +==== + +* make install without sudo rights +* make a gadget + +Code organisation +================= + +The core code is in src/elife_evas_smart.c +All the other files are here to build standalone binary and edje file. + +src/elife_evas_smart.c + At each life cycle, grid_evolution() gets called + +Ideas +===== + +freenode #e +20:08 < loran> for the moment each cell is an evas_object. having the whole grid as one evas object and filling polygons manually (i'll take a look at seed + algorithm) might be faster, not sure +20:10 < loran> but if i can have opengl rendering for the background with composite module for example, then i will improve other parts of elife, like having cell + created on external events like new processes, packets blocked by firewall, ... +20:10 < loran> :p +20:15 < drohan> it sounds interesting, but for future reference, you need a way to gain trust from the users, a background that uses cpu is not trusted, if you + change it as a widget or something else or try to comment all the code so the users can see what you are doing with it +20:16 < loran> haha good point :p +20:17 < drohan> and even then you will have a little problem with trust, change everything so you don't have to install it system wide, just local .e dir +20:17 < loran> i think you can run make install without system rights +20:17 < loran> without sudo + +Optimisation ideas: +* one evas_object_rectangle, manualy write memory inside it (DONE) + diff --git a/gg_elife/autogen.sh b/gg_elife/autogen.sh new file mode 100755 index 0000000..ae01364 --- /dev/null +++ b/gg_elife/autogen.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +rm -rf autom4te.cache +rm -f aclocal.m4 ltmain.sh + +touch README + +echo "Running autopoint..." ; autopoint -f || : +echo "Running aclocal..." ; aclocal -I m4 $ACLOCAL_FLAGS || exit 1 +echo "Running autoheader..." ; autoheader || exit 1 +echo "Running autoconf..." ; autoconf || exit 1 +echo "Running libtoolize..." ; (libtoolize --copy --automake || glibtoolize --automake) || exit 1 +echo "Running automake..." ; automake --add-missing --copy --gnu || exit 1 + +if [ -z "$NOCONFIGURE" ]; then + ./configure "$@" +fi diff --git a/gg_elife/configure.ac b/gg_elife/configure.ac new file mode 100644 index 0000000..60d1703 --- /dev/null +++ b/gg_elife/configure.ac @@ -0,0 +1,64 @@ +dnl Process this file with autoconf to produce a configure script. + +# get rid of that stupid cache mechanism +rm -f config.cache + +AC_INIT(elife, 0.1, laurent@p1sec.com) +AC_PREREQ(2.52) +AC_CONFIG_SRCDIR(configure.ac) +AC_CANONICAL_BUILD +AC_CANONICAL_HOST +AC_ISC_POSIX + +AM_INIT_AUTOMAKE(1.6) +AM_CONFIG_HEADER(config.h) +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +AC_PROG_CC_C99 +AC_HEADER_STDC +AC_C_CONST +AM_PROG_CC_C_O + +define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])dnl +define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl +AC_PROG_LIBTOOL + +m4_ifdef([AM_GNU_GETTEXT_VERSION], [ +AM_GNU_GETTEXT_VERSION([0.17]) +]) + +PKG_PROG_PKG_CONFIG +PKG_CHECK_MODULES([ELIFE], [edje ecore-evas ecore evas eina]) +datadir_edj=$($PKG_CONFIG --variable=prefix enlightenment)/share/enlightenment/data/backgrounds + +EFL_WITH_BIN([edje], [edje-cc], [edje_cc]) +vmaj=$($PKG_CONFIG --variable=vmaj edje) +MODULE_ARCH="$host_os-$host_cpu-$vmaj.0.0" +AC_SUBST(MODULE_ARCH) +AC_DEFINE_UNQUOTED(MODULE_ARCH, "$MODULE_ARCH", "Module architecture") + +datadir=$(pkg-config --variable=modules edje)/${PACKAGE} +AC_ARG_ENABLE(homedir-install, + AS_HELP_STRING([--enable-homedir-install], [Install module in homedir]), + [ + datadir="${HOME}/.edje/modules/${PACKAGE}"; + datadir_edj="${HOME}/.e/e/backgrounds" + ] +) +AC_SUBST(datadir_edj) + +AC_ARG_ENABLE(glouglou, +[ --enable-glouglou Enable glouglou support], +[case "${enableval}" in + yes) glouglou=true ;; + no) glouglou=false ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-glouglou) ;; +esac],[glouglou=false]) +AM_CONDITIONAL(HAVE_GLOUGLOU, test x$glouglou = xtrue) + +AC_OUTPUT([ +Makefile +data/Makefile +src/Makefile +], [ +]) diff --git a/gg_elife/data/Makefile.am b/gg_elife/data/Makefile.am new file mode 100644 index 0000000..8664660 --- /dev/null +++ b/gg_elife/data/Makefile.am @@ -0,0 +1,18 @@ +AUTOMAKE_OPTIONS = 1.4 foreign +MAINTAINERCLEANFILES = Makefile.in + +EDJE_FLAGS = -v + +filesdir = @datadir_edj@ +files_DATA = elife.edj + +EXTRA_DIST = elife.edc + +elife.edj: elife.edc + $(edje_cc) $(EDJE_FLAGS) $< $@ + +clean-local: + rm -rf elife.edj *~ + +uninstall: + rm -rf $(DESTDIR)@datadir_edj@/elife.edj diff --git a/gg_elife/data/elife.edc b/gg_elife/data/elife.edc new file mode 100644 index 0000000..69df75c --- /dev/null +++ b/gg_elife/data/elife.edc @@ -0,0 +1,48 @@ +externals { + external: "elife"; +} + +collections { + group { + name: "e/desktop/background"; + + script { + public clock_cb(unused) { + emit("elife:refresh", "☃"); + timer(0.5, "clock_cb", 1); + } + } + + parts { + part { + name: "bg"; + type: RECT; + description { + state: "default" 0.0; + color: 0 0 0 255; + } + } + part { + name: "elife"; + type: EXTERNAL; + source: "elife"; + + description { + state: "default" 0.0; + } + } + } + + // Get everything started at load + programs { + program { + name: "init"; + signal: "load"; + source: ""; + script { + clock_cb(0); + } + } + } + } +} diff --git a/gg_elife/m4/efl_binary.m4 b/gg_elife/m4/efl_binary.m4 new file mode 100644 index 0000000..c774688 --- /dev/null +++ b/gg_elife/m4/efl_binary.m4 @@ -0,0 +1,71 @@ +dnl Copyright (C) 2010 Vincent Torri <vtorri at univ-evry dot fr> +dnl That code is public domain and can be freely used or copied. + +dnl Macro that check if a binary is built or not + +dnl Usage: EFL_ENABLE_BIN(binary) +dnl Call AC_SUBST(BINARY_PRG) (BINARY is the uppercase of binary, - being transformed into _) +dnl Define have_binary (- is transformed into _) +dnl Define conditional BUILD_BINARY (BINARY is the uppercase of binary, - being transformed into _) + +AC_DEFUN([EFL_ENABLE_BIN], +[ + +m4_pushdef([UP], m4_translit([[$1]], [-a-z], [_A-Z]))dnl +m4_pushdef([DOWN], m4_translit([[$1]], [-A-Z], [_a-z]))dnl + +have_[]m4_defn([DOWN])="yes" + +dnl configure option + +AC_ARG_ENABLE([$1], + [AC_HELP_STRING([--disable-$1], [disable building of ]DOWN)], + [ + if test "x${enableval}" = "xyes" ; then + have_[]m4_defn([DOWN])="yes" + else + have_[]m4_defn([DOWN])="no" + fi + ]) + +AC_MSG_CHECKING([whether to build ]DOWN[ binary]) +AC_MSG_RESULT([$have_[]m4_defn([DOWN])]) + +if test "x$have_[]m4_defn([DOWN])" = "xyes"; then + UP[]_PRG=DOWN[${EXEEXT}] +fi + +AC_SUBST(UP[]_PRG) + +AM_CONDITIONAL(BUILD_[]UP, test "x$have_[]m4_defn([DOWN])" = "xyes") + +AS_IF([test "x$have_[]m4_defn([DOWN])" = "xyes"], [$2], [$3]) + +]) + + +dnl Macro that check if a binary is built or not + +dnl Usage: EFL_WITH_BIN(package, binary, default_value) +dnl Call AC_SUBST(_binary) (_binary is the lowercase of binary, - being transformed into _ by default, or the value set by the user) + +AC_DEFUN([EFL_WITH_BIN], +[ + +m4_pushdef([DOWN], m4_translit([[$2]], [-A-Z], [_a-z]))dnl + +dnl configure option + +AC_ARG_WITH([$2], + [AC_HELP_STRING([--with-$2=PATH], [specify a specific path to ]DOWN[ @<:@default=$3@:>@])], + [_efl_with_binary=${withval}], + [_efl_with_binary=$(pkg-config --variable=prefix $1)/bin/$3]) + +DOWN=${_efl_with_binary} +AC_MSG_NOTICE(DOWN[ set to ${_efl_with_binary}]) + +with_binary_[]m4_defn([DOWN])=${_efl_with_binary} + +AC_SUBST(DOWN) + +]) diff --git a/gg_elife/src/Makefile.am b/gg_elife/src/Makefile.am new file mode 100644 index 0000000..f8135a0 --- /dev/null +++ b/gg_elife/src/Makefile.am @@ -0,0 +1,37 @@ +MAINTAINERCLEANFILES = Makefile.in +INCLUDES = -I. \ + -I$(top_srcdir) \ + -I$(includedir) \ + @ELIFE_CFLAGS@ + + +pkgdir = $(datadir)/$(MODULE_ARCH) +pkg_LTLIBRARIES = module.la +module_la_SOURCES = \ + elife_evas_smart.c \ + elife_edje_external.c + +module_la_LIBADD = @ELIFE_LIBS@ +module_la_DEPENDENCIES = $(top_builddir)/config.h + +bin_PROGRAMS = elife +elife_SOURCES = \ + elife_evas_smart.c \ + elife.c +elife_CPPFLAGS = \ + @ELIFE_CFLAGS@ + +if HAVE_GLOUGLOU +module_la_LDFLAGS = -module -avoid-version -lglouglou -levent +module_la_CFLAGS = -DHAVE_GLOUGLOU +elife_LDADD = \ + @ELIFE_LIBS@ -lglouglou -levent +elife_CFLAGS = -DHAVE_GLOUGLOU +else +module_la_LDFLAGS = -module -avoid-version +elife_LDADD = \ + @ELIFE_LIBS@ +endif + +clean-local: + rm -rf *~ diff --git a/gg_elife/src/elife.c b/gg_elife/src/elife.c new file mode 100644 index 0000000..8b97cb8 --- /dev/null +++ b/gg_elife/src/elife.c @@ -0,0 +1,106 @@ +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <Evas.h> +#include <Ecore.h> +#include <Ecore_Evas.h> + +#include "elife_evas_smart.h" + +#define BG 0xff002b36 +#define FG 0xff839496 + +#define MIN(a,b) (((a)<(b))?(a):(b)) + +static struct { + Ecore_Evas *ee; + Evas *evas; + Evas_Coord w, h; + Evas_Object *bg; + Evas_Object *elife; +} elife_g; +#define _G elife_g + +static void +resize_cb(Ecore_Evas *ee) +{ + int w, h; + + ecore_evas_geometry_get(ee, NULL, NULL, &w, &h); + evas_object_resize(_G.bg, w, h); + evas_object_resize(_G.elife, w, h); +} + +static Eina_Bool +timer_cb(void *data) +{ + Evas_Object *o = (Evas_Object *)data; + + evas_object_smart_callback_call(o, "refresh", NULL); + + return EINA_TRUE; +} + +int +main(void) +{ + unsigned int seedval; + int fd; + + if (!ecore_evas_init()) + return -1; + + _G.w = 600; + _G.h = 350; + + + /*open file */ + if ((fd = open("/dev/urandom", O_RDONLY)) < 0) { + perror(NULL); + exit(1); + } + if (read(fd, &seedval, sizeof(seedval)) != sizeof(seedval)) { + perror(NULL); + close(fd); + exit(1); + } + close(fd); + srand(seedval); + + _G.ee = ecore_evas_software_x11_new( + NULL, /* const char * disp_name */ + 0, /* Ecore_X_Window parent */ + 0, 0, _G.w, _G.h); + + ecore_evas_title_set(_G.ee, "elife"); + ecore_evas_borderless_set(_G.ee, 0); + ecore_evas_show(_G.ee); + _G.evas = ecore_evas_get(_G.ee); + + _G.bg = evas_object_rectangle_add(_G.evas); + evas_object_color_set(_G.bg, + (BG >> 16) & 0xff, + (BG >> 8) & 0xff, + BG & 0xff, + BG >> 24); + evas_object_move(_G.bg, 0, 0); + evas_object_resize(_G.bg, _G.w, _G.h); + evas_object_show(_G.bg); + + _G.elife = elife_smart_new(_G.evas); + evas_object_resize(_G.elife, _G.w, _G.h); + evas_object_show(_G.elife); + + ecore_timer_add(0.1, timer_cb, _G.elife); + + ecore_evas_callback_resize_set(_G.ee, &resize_cb); + + ecore_main_loop_begin(); + + ecore_evas_shutdown(); + ecore_shutdown(); + + return 0; +} diff --git a/gg_elife/src/elife_edje_external.c b/gg_elife/src/elife_edje_external.c new file mode 100644 index 0000000..14035d2 --- /dev/null +++ b/gg_elife/src/elife_edje_external.c @@ -0,0 +1,192 @@ +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <Evas.h> +#include <Ecore.h> +#include <Ecore_Evas.h> +#include <Edje.h> + +#include "elife_evas_smart.h" + +/* Prototypes -{{{-*/ + +static Evas_Object * +elife_ext_add(void *data, Evas *evas, Evas_Object *parent, + const Eina_List *params, const char *part_name); +static void +elife_ext_state_set(void *data, Evas_Object *obj, + const void *from_params, + const void *to_params, float pos); +static void +elife_ext_signal_emit(void *data, Evas_Object *obj, + const char *emission, const char *source); +static Eina_Bool +elife_ext_param_set(void *data, Evas_Object *obj, + const Edje_External_Param *param); +static Eina_Bool +elife_ext_param_get(void *data, const Evas_Object *obj, + Edje_External_Param *param); +static Evas_Object * +elife_ext_content_get(void *data, const Evas_Object *obj, + const char *content); +static void* +elife_ext_params_parse(void *data, Evas_Object *obj, + const Eina_List *params); +static void +elife_ext_params_free(void *params); +static const char* +elife_ext_label_get(void *data); +static const char* +elife_ext_description_get(void *data); +static Evas_Object * +elife_ext_icon_add(void *data, Evas *e); +static Evas_Object * +elife_ext_preview_add(void *data, Evas *e); +static const char* +elife_ext_translate(void *data, const char *orig); + +/* }}} */ +/* Globals -{{{-*/ + +static struct { + Edje_External_Type ext_type; +} elife_g = { + .ext_type = { + .abi_version = EDJE_EXTERNAL_TYPE_ABI_VERSION, + .module = "elife", + .module_name = "elife", + .add = elife_ext_add, + .state_set = elife_ext_state_set, + .signal_emit = elife_ext_signal_emit, + .param_set = elife_ext_param_set, + .param_get = elife_ext_param_get, + .content_get = elife_ext_content_get, + .params_parse = elife_ext_params_parse, + .params_free = elife_ext_params_free, + .label_get = elife_ext_label_get, + .description_get = elife_ext_description_get, + .icon_add = elife_ext_icon_add, + .preview_add = elife_ext_preview_add, + .translate = elife_ext_translate, + }, +}; +#define _G elife_g + +/* }}} */ +/* Edje External -{{{-*/ + +static Evas_Object * +elife_ext_add(void *data, Evas *evas, Evas_Object *parent, + const Eina_List *params, const char *part_name) +{ + return elife_smart_new(evas); +} + +static void +elife_ext_state_set(void *data, Evas_Object *obj, + const void *from_params, + const void *to_params, float pos) +{ +} + +static void +elife_ext_signal_emit(void *data, Evas_Object *obj, + const char *emission, const char *source) +{ + evas_object_smart_callback_call(obj, emission, NULL); +} + +static Eina_Bool +elife_ext_param_set(void *data, Evas_Object *obj, + const Edje_External_Param *param) +{ + return EINA_TRUE; +} + +static Eina_Bool +elife_ext_param_get(void *data, const Evas_Object *obj, + Edje_External_Param *param) +{ + return EINA_TRUE; +} + +static Evas_Object * +elife_ext_content_get(void *data, const Evas_Object *obj, + const char *content) +{ + return NULL; +} + +static void* +elife_ext_params_parse(void *data, Evas_Object *obj, + const Eina_List *params) +{ + return NULL; +} + +static void +elife_ext_params_free(void *params) +{ +} + +static const char* +elife_ext_label_get(void *data) +{ + return NULL; +} + +static const char* +elife_ext_description_get(void *data) +{ + return NULL; +} + +static Evas_Object * +elife_ext_icon_add(void *data, Evas *e) +{ + return NULL; +} + +static Evas_Object * +elife_ext_preview_add(void *data, Evas *e) +{ + return NULL; +} + +static const char* +elife_ext_translate(void *data, const char *orig) +{ + return NULL; +} +/* }}} */ +/* Init/Shutdown -{{{-*/ + +Eina_Bool +elife_init(void) +{ + unsigned int seedval = time(NULL); + int fd; + + if ((fd = open("/dev/random", O_RDONLY)) >= 0) { + read(fd, &seedval, sizeof(seedval)); + close(fd); + } + srand(seedval); + + edje_external_type_register("elife", &_G.ext_type); + + return EINA_TRUE; +} + +void +elife_shutdown(void) +{ + edje_external_type_unregister("elife"); +} + +EINA_MODULE_INIT(elife_init); +EINA_MODULE_SHUTDOWN(elife_shutdown); + +/* }}} */ diff --git a/gg_elife/src/elife_evas_smart.c b/gg_elife/src/elife_evas_smart.c new file mode 100644 index 0000000..acbd9a2 --- /dev/null +++ b/gg_elife/src/elife_evas_smart.c @@ -0,0 +1,558 @@ +/* + * elife - Game of life / Living graphic + */ + +/* + * Copyright (c) 2012 Laurent Ghigonis <laurent@p1sec.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdlib.h> +#include <err.h> + +#include "elife_evas_smart.h" + +#ifdef HAVE_GLOUGLOU +#include <libglouglou.h> +#endif + +#define NCELL_X 100 +#define NCELL_Y 100 +#define INJECT_PROBA 40 +#define INITCELL_PROBA 7 +#define CONWAY_GROW_DIE 600 +#define DEBUG 0 + +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define CELL_GET(grid, x, y) &(grid->cells[(y*grid->w) + x]) + +typedef struct lifepattern_s { + const int w; + const int h; + const char *pat; +} lifepattern_s; + +enum lifepattern_t { + ELIFE_PAT_BEEHIVE = 0, + ELIFE_PAT_BOAT = 1, + ELIFE_PAT_SHIP = 2, + ELIFE_PAT_LOAF = 3, + ELIFE_PAT_QUEENBEE = 4, + ELIFE_PAT_GLIDER = 5, + ELIFE_PAT_LWSS = 6, +}; +#define PATTERN_COUNT 7 + +lifepattern_s lifepatterns[] = { + [ELIFE_PAT_BEEHIVE] = {3, 4, "010101101010"}, + [ELIFE_PAT_BOAT] = {3, 3, "010101011"}, + [ELIFE_PAT_SHIP] = {3, 3, "110101011"}, + [ELIFE_PAT_LOAF] = {4, 4, "0110100101010010"}, + [ELIFE_PAT_QUEENBEE] = {4, 7, "1100001000010001000100101100"}, + [ELIFE_PAT_GLIDER] = {3, 3, "010011101"}, + [ELIFE_PAT_LWSS] = {5, 4, "10010000011000101111"}, +}; + +enum lifemode { + ELIFE_MODE_CONWAY, + ELIFE_MODE_CONWAY_GROW, + ELIFE_MODE_LORAN_CIVILISATION, +}; + +struct cell { + int age, newage; + u_int32_t forced_color; + int x, y; + int r, g, b; +}; + +struct grid { + Evas_Object *container; + struct cell *cells; + Evas_Object *image; + int *mem; + int w, h; + int pix_w, pix_h; + int cell_pix_w, cell_pix_h; + int age; + enum lifemode mode; +#ifdef HAVE_GLOUGLOU + struct gg_client *ggcli; + struct event_base *ev_base; +#endif +}; + +static struct grid *grid_new(Evas_Object *container, + int w, int h, enum lifemode mode); +static void grid_del(struct grid *grid); +static int grid_evolution(struct grid *grid); +static void grid_inject_pattern(struct grid *grid, u_int32_t color); +static int grid_redraw(struct grid *grid, int w, int h); +static int cell_neighbours_count(struct cell *cell, struct grid *grid); +static void cell_redraw(struct cell *c, struct grid *g); +static void grid_mouse_down(void *data, Evas *evas, Evas_Object *child, + void *event_info); + +Evas_Object *elife_smart_new(Evas *e); +static void elife_on_refresh(void *data, Evas_Object *o, + void *event_info); +static Evas_Object *elife_object_new(Evas *evas); +static Evas_Smart *_elife_object_smart_get(void); +static void _elife_object_del(Evas_Object *o); +static void _elife_object_move(Evas_Object *o, + Evas_Coord x, Evas_Coord y); +static void _elife_object_resize(Evas_Object *o, + Evas_Coord w, Evas_Coord h); +/* Not implemented +static void _elife_object_show(Evas_Object *o); +static void _elife_object_hide(Evas_Object *o); +static void _elife_object_color_set(Evas_Object *o, int r, int g, int b, int a); +static void _elife_object_clip_set(Evas_Object *o, Evas_Object *clip); +static void _elife_object_clip_unset(Evas_Object *o); +*/ +void *xmalloc(size_t size); + +static struct { + Evas_Smart_Class klass; +} elife_evas_smart_g = { + .klass = { + .name = "elife_object", + .version = EVAS_SMART_CLASS_VERSION, + .add = NULL, + .del = _elife_object_del, + .move = _elife_object_move, + .resize = _elife_object_resize, + .show = NULL, + .hide = NULL, + .color_set = NULL, + .clip_set = NULL, + .clip_unset = NULL, + .calculate = NULL, + .member_add = NULL, + .member_del = NULL, + .parent = NULL, + .callbacks = NULL, + .interfaces = NULL, + .data = NULL, + }, +#define _G elife_evas_smart_g +}; + +#ifdef HAVE_GLOUGLOU +int +gg_packet(struct gg_client *cli, struct gg_packet *pkt) +{ + struct grid *grid; + u_int32_t color; + + grid = cli->usrdata; + switch(pkt->type) { + case PACKET_FORK: color=0xff0000; break; + case PACKET_EXEC: color=0x00ff00; break; + case PACKET_EXIT: color=0x0000ff; break; + default: return 0; + } + grid_inject_pattern(grid, color); + + return 0; +} +#endif + +static struct grid * +grid_new(Evas_Object *container, int w, int h, enum lifemode mode) +{ + struct grid *g; + struct cell *cell; + Evas_Object *o; + int i, j; + + g = xmalloc(sizeof(struct grid)); + g->container = container; + o = evas_object_image_filled_add(evas_object_evas_get(container)); + if (!o) + err(1, "Cannot create image for grid"); + evas_object_image_alpha_set(o, EINA_FALSE); + evas_object_image_smooth_scale_set(o, EINA_FALSE); + evas_object_data_set(o, "grid", g); + evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, + grid_mouse_down, g); + evas_object_smart_member_add(o, container); + evas_object_show(o); + g->image = o; + g->mem = NULL; + g->w = w; + g->h = h; + g->age = 0; + g->mode = mode; + g->cells = xmalloc(sizeof(struct cell) * w * h); + for (j=0; j<h; j++) { + for (i=0; i<w; i++) { + cell = CELL_GET(g, i, j); + cell->x = i; + cell->y = j; + cell->r = 0; + cell->g = 0; + cell->b = 0; + cell->forced_color = 0x000000; + cell->age = !(rand() % INITCELL_PROBA); + } + } + +#ifdef HAVE_GLOUGLOU + g->ev_base = event_base_new(); + g->ggcli = gg_client_connect(g->ev_base, "127.0.0.1", GLOUGLOU_ANALY_DEFAULT_PORT, + NULL, gg_packet, g); +#endif + + return g; +} + +static void +grid_del(struct grid *grid) +{ +#ifdef HAVE_GLOUGLOU + gg_client_disconnect(grid->ggcli); +#endif + free(grid->cells); + free(grid->mem); + free(grid); +} + +static int +grid_evolution(struct grid *grid) +{ + struct cell *cell; + int i, j; + int neighbours; + + for (j=0; j<grid->h; j++) { + for (i=0; i<grid->w; i++) { + cell = CELL_GET(grid, i, j); + neighbours = cell_neighbours_count(cell, grid); + switch (grid->mode) { + case ELIFE_MODE_CONWAY: + if (cell->age == 0 && neighbours == 3) + cell->newage = 1; + else if (cell->age > 0 && (neighbours == 2 || neighbours == 3)) + cell->newage = cell->age; + else + cell->newage = 0; + break; + case ELIFE_MODE_CONWAY_GROW: + if (cell->age == 0 && neighbours == 3) + cell->newage = 1; + else if (cell->age > 0 && (neighbours == 2 || neighbours == 3)) + if (cell->age > CONWAY_GROW_DIE) + cell->newage = 0; + else + cell->newage = cell->age + 1; + else + cell->newage = 0; + break; + case ELIFE_MODE_LORAN_CIVILISATION: + if (neighbours == 4 || neighbours < 2) + cell->newage = 0; + else if (neighbours > 2 && neighbours != 5) + cell->newage = cell->age + 1; + else if (neighbours == 2 && cell->age > 1) + cell->newage = 0; + else + cell->newage = cell->age; + if (cell->age > 100) + cell->newage = 0; + break; + } + if (cell->newage == 0 && cell->forced_color) + cell->forced_color = 0; + if (DEBUG) + printf("evolution: %d %d n %d age %d newage %d\n", i, j, + neighbours, cell->age, cell->newage); + } + } + +#ifdef HAVE_GLOUGLOU + event_base_loop(grid->ev_base, EVLOOP_NONBLOCK); +#else + if (rand() % INJECT_PROBA == 0) + grid_inject_pattern(grid, 0); +#endif + + for (j=0; j<grid->h; j++) { + for (i=0; i<grid->w; i++) { + cell = CELL_GET(grid, i, j); + cell->age = cell->newage; + cell_redraw(cell, grid); + } + } + evas_object_image_pixels_dirty_set(grid->image, EINA_TRUE); + + grid->age++; +} + +static void +grid_inject_pattern(struct grid *grid, u_int32_t color) +{ + struct cell *cell; + enum lifepattern_t npat; + lifepattern_s *pat; + int x, y, cx, cy; + int i, j; + int age; + + npat = rand() % PATTERN_COUNT; + if (DEBUG) + printf("grid_inject_pattern: %d\n", npat); + pat = &lifepatterns[npat]; + x = rand() % (grid->w - pat->w); + y = rand() % (grid->h - pat->h); + for (j=0; j<pat->h; j++) { + for (i=0; i<pat->w; i++) { + cx = x + i; + cy = y + j; + if (cx >= grid->w || cy >= grid->h) + continue; + cell = CELL_GET(grid, cx, cy); + age = (pat->pat[pat->w*j + i] - '0') * 27; + if (age != 0) + cell->newage = age; + cell->forced_color = color; + cell->age = cell->newage; + // cell_redraw(cell, grid); + } + } +} + +static int +grid_redraw(struct grid *grid, int w, int h) +{ + struct cell *cell; + int i,j; + Evas_Object *o; + + grid->cell_pix_w = w / grid->w; + grid->cell_pix_h = h / grid->h; + grid->pix_w = (w / grid->w) * grid->w; + grid->pix_h = (h / grid->h) * grid->h; + if (DEBUG) + printf("redraw: container %d %d cell %d %d\n", w, h, grid->cell_pix_w, grid->cell_pix_h); + + evas_object_image_fill_set(grid->image, 0, 0, grid->pix_w, grid->pix_h); + evas_object_image_size_set (grid->image, grid->pix_w, grid->pix_h); + evas_object_resize(grid->image, w, h); + /* XXX could be optimized to avoid flickering on resize */ + if (grid->mem) + free(grid->mem); + grid->mem = calloc(w * h, sizeof(int)); + if (!grid->mem) + err(1, "could not calloc grid->mem"); + evas_object_image_data_set(grid->image, (void *) grid->mem); + for (j=0; j<grid->h; j++) { + for (i=0; i<grid->w; i++) { + cell = CELL_GET(grid, i, j); + cell_redraw(cell, grid); + } + } +} + +static int +cell_neighbours_count(struct cell *cell, struct grid *grid) +{ + struct cell *ncell; + int m, n, cx, cy; + int count; + + count = 0; + for (n=-1; n<=1; n++) { + for (m=-1; m<=1; m++) { + if (m == 0 && n == 0) + continue; + cx = cell->x + m; + cy = cell->y + n; + if (cx < 0 || cx >= grid->w || cy < 0 || cy >= grid->h) + continue; + ncell = CELL_GET(grid, cx, cy); + if (ncell->age > 0) + count++; + } + } + + return count; +} + +static void +cell_redraw(struct cell *c, struct grid *grid) +{ + u_int8_t r, g, b, a; + int x, y, w, h; + int i, j; + int color; + + if (c->forced_color && c->age > 0) { + r = (c->forced_color & 0xff0000) >> 16; + g = (c->forced_color & 0xff00) >> 8; + b = (c->forced_color & 0xff); + } else if (c->age < 100) { + r = (c->age > 0) ? 128 : 0; + g = (c->age > 0) ? (33 + c->age * 7) : 0; + b = 0; + } else if (c->age < CONWAY_GROW_DIE - 50) { + r = 128 - c->age; + g = 255 - c->age; + b = (c->age - 100) * 2; + } else { + r = 255; + g = (c->age % 2) * 255; + b = 255; + } + a = 255; + if (r == c->r && g == c->g && b == c->b) + return; + c->r = r; + c->g = g; + c->b = b; + + x = c->x * grid->cell_pix_w; + y = c->y * grid->cell_pix_h; + w = grid->cell_pix_w; + h = grid->cell_pix_h; + for (j=y; j<y+h; j++) { + for (i=x; i<x+w; i++) { + color = 0xff000000 + (r << 16) + (g << 8) + (b); + grid->mem[j*grid->pix_w + i] = color; + } + } +} + +static void +grid_mouse_down(void *data, + Evas *evas, + Evas_Object *child, + void *event_info) +{ + Evas_Coord x, y, w, h; + Evas_Event_Mouse_Up *evt = event_info; + struct grid *grid; + + grid = data; + grid_inject_pattern(grid, 0); +} + +Evas_Object * +elife_smart_new(Evas *e) +{ + return elife_object_new(e); +} + +static void +elife_on_refresh(void *data, Evas_Object *o, void *event_info) +{ + Evas_Coord x, y, w, h; + Evas_Object *child; + struct grid *grid; + + grid = evas_object_data_get(o, "grid"); + + grid_evolution(grid); +} + +static Evas_Object * +elife_object_new(Evas *evas) +{ + Evas_Object *elife_object; + struct grid *grid; + + elife_object = evas_object_smart_add(evas, + _elife_object_smart_get()); + grid = grid_new(elife_object, NCELL_X, NCELL_Y, ELIFE_MODE_CONWAY_GROW); + evas_object_data_set(elife_object, "grid", grid); + evas_object_smart_callback_add(elife_object, + "refresh", + elife_on_refresh, + NULL); + + return elife_object; +} + +static Evas_Smart * +_elife_object_smart_get(void) +{ + static Evas_Smart *smart = NULL; + + if (smart) + return smart; + + smart = evas_smart_class_new(&_G.klass); + return smart; +} + +static void +_elife_object_del(Evas_Object *o) +{ + Evas_Object *child; + struct grid *grid; + Eina_List *list; + + list = evas_object_smart_members_get(o); + EINA_LIST_FREE(list, child) { + evas_object_smart_member_del(child); + evas_object_del(child); + } + grid = evas_object_data_del(o, "grid"); + grid_del(grid); +} + +static void +_elife_object_move(Evas_Object *o, Evas_Coord x, Evas_Coord y) +{ + Evas_Coord orig_x, orig_y, dx, dy; + Eina_List *lst; + Evas_Object *child; + void *data; + + if (DEBUG) + printf("oject_move: %d %d\n", x, y); + evas_object_geometry_get(o, &orig_x, &orig_y, NULL, NULL); + dx = x - orig_x; + dy = y - orig_y; + + lst = evas_object_smart_members_get(o); + EINA_LIST_FREE(lst, data) { + child = data; + evas_object_geometry_get(child, &orig_x, &orig_y, NULL, NULL); + evas_object_move(child, orig_x + dx, orig_y + dy); + } +} + +static void +_elife_object_resize(Evas_Object *o, Evas_Coord w, Evas_Coord h) +{ + struct grid *grid; + + if (DEBUG) + printf("oject_resize: %d %d\n", w, h); + grid = evas_object_data_get(o, "grid"); + grid_redraw(grid, w, h); +} + +void * +xmalloc(size_t size) +{ + void *x; + + x = malloc(size); + if (!x) + err(1, "Error: failed to allocate %d", size); + return x; +} + diff --git a/gg_elife/src/elife_evas_smart.h b/gg_elife/src/elife_evas_smart.h new file mode 100644 index 0000000..b5a5b85 --- /dev/null +++ b/gg_elife/src/elife_evas_smart.h @@ -0,0 +1,8 @@ +#ifndef ELIFE_SMART_H +#define ELIFE_SMART_H +#include <Evas.h> + +Evas_Object *elife_smart_new(Evas *e); + +#endif + |