diff --git a/aqhome/0BUILD b/aqhome/0BUILD
index 2516366..5208aa9 100644
--- a/aqhome/0BUILD
+++ b/aqhome/0BUILD
@@ -70,6 +70,7 @@
hexfile
data
events
+ events2
client
@@ -82,6 +83,7 @@
aqhhexfile
aqhdata
aqhevents
+ aqhevents2
aqhclient
diff --git a/aqhome/events2/0BUILD b/aqhome/events2/0BUILD
new file mode 100644
index 0000000..3968dc1
--- /dev/null
+++ b/aqhome/events2/0BUILD
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+ $(gwenhywfar_cflags)
+ $(aqdatabase_cflags)
+ -I$(topsrcdir)
+ -I$(topbuilddir)
+
+
+
+ --include=$(builddir)
+ --include=$(srcdir)
+ --include=$(aqdatabase_AQDATABASE_TYPEMAKERDIR)/c
+
+
+
+
+
+ $(visibility_cflags)
+
+
+
+ --api=AQHOME_API
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(local/built_headers_pub)
+
+
+
+
+ eventloop.h
+ object.h
+ fdobject.h
+
+
+
+
+ eventloop_p.h
+ object_p.h
+ fdobject_p.h
+
+
+
+
+ $(local/typefiles)
+
+ eventloop.c
+ eventloop_select.c
+ object.c
+ fdobject.c
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aqhome/events2/eventloop.c b/aqhome/events2/eventloop.c
new file mode 100644
index 0000000..a37bc0d
--- /dev/null
+++ b/aqhome/events2/eventloop.c
@@ -0,0 +1,79 @@
+/****************************************************************************
+ * This file is part of the project AqHome.
+ * AqHome (c) by 2025 Martin Preuss, all rights reserved.
+ *
+ * The license for this file can be found in the file COPYING which you
+ * should have received along with this file.
+ ****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include "./eventloop_p.h"
+
+#include
+
+
+
+
+AQH_EVENT_LOOP *AQH_EventLoop_new()
+{
+ AQH_EVENT_LOOP *eventLoop;
+
+ GWEN_NEW_OBJECT(AQH_EVENT_LOOP, eventLoop);
+ eventLoop->fdObjectList=AQH_Object_List2_new();
+ eventLoop->timerObjectList=AQH_Object_List2_new();
+
+ return eventLoop;
+}
+
+
+
+void AQH_EventLoop_free(AQH_EVENT_LOOP *eventLoop)
+{
+ if (eventLoop) {
+ AQH_Object_List2_free(eventLoop->timerObjectList);
+ AQH_Object_List2_free(eventLoop->fdObjectList);
+ }
+}
+
+
+
+void AQH_EventLoop_AddFdObject(AQH_EVENT_LOOP *eventLoop, AQH_OBJECT *o)
+{
+ if (eventLoop && o && NULL==AQH_Object_List2_Contains(eventLoop->fdObjectList, o)) {
+ AQH_Object_List2_PushBack(eventLoop->fdObjectList, o);
+ }
+}
+
+
+
+void AQH_EventLoop_DelFdObject(AQH_EVENT_LOOP *eventLoop, AQH_OBJECT *o)
+{
+ if (eventLoop && o)
+ AQH_Object_List2_Remove(eventLoop->fdObjectList, o);
+}
+
+
+
+void AQH_EventLoop_AddTimerObject(AQH_EVENT_LOOP *eventLoop, AQH_OBJECT *o)
+{
+ if (eventLoop && o && NULL==AQH_Object_List2_Contains(eventLoop->timerObjectList, o)) {
+ AQH_Object_List2_PushBack(eventLoop->timerObjectList, o);
+ }
+}
+
+
+
+void AQH_EventLoop_DelTimerObject(AQH_EVENT_LOOP *eventLoop, AQH_OBJECT *o)
+{
+ if (eventLoop && o)
+ AQH_Object_List2_Remove(eventLoop->timerObjectList, o);
+}
+
+
+
+
+
+
diff --git a/aqhome/events2/eventloop.h b/aqhome/events2/eventloop.h
new file mode 100644
index 0000000..9d95bcd
--- /dev/null
+++ b/aqhome/events2/eventloop.h
@@ -0,0 +1,32 @@
+/****************************************************************************
+ * This file is part of the project AqHome.
+ * AqHome (c) by 2025 Martin Preuss, all rights reserved.
+ *
+ * The license for this file can be found in the file COPYING which you
+ * should have received along with this file.
+ ****************************************************************************/
+
+#ifndef AQH_EVENTLOOP_H
+#define AQH_EVENTLOOP_H
+
+typedef struct AQH_EVENT_LOOP AQH_EVENT_LOOP;
+
+
+#include
+
+
+
+AQHOME_API AQH_EVENT_LOOP *AQH_EventLoop_new();
+AQHOME_API void AQH_EventLoop_free(AQH_EVENT_LOOP *eventLoop);
+
+AQHOME_API void AQH_EventLoop_Run(AQH_EVENT_LOOP *eventLoop);
+
+AQHOME_API void AQH_EventLoop_AddFdObject(AQH_EVENT_LOOP *eventLoop, AQH_OBJECT *o);
+AQHOME_API void AQH_EventLoop_DelFdObject(AQH_EVENT_LOOP *eventLoop, AQH_OBJECT *o);
+
+AQHOME_API void AQH_EventLoop_AddTimerObject(AQH_EVENT_LOOP *eventLoop, AQH_OBJECT *o);
+AQHOME_API void AQH_EventLoop_DelTimerObject(AQH_EVENT_LOOP *eventLoop, AQH_OBJECT *o);
+
+
+
+#endif
diff --git a/aqhome/events2/eventloop_p.h b/aqhome/events2/eventloop_p.h
new file mode 100644
index 0000000..e813766
--- /dev/null
+++ b/aqhome/events2/eventloop_p.h
@@ -0,0 +1,25 @@
+/****************************************************************************
+ * This file is part of the project AqHome.
+ * AqHome (c) by 2025 Martin Preuss, all rights reserved.
+ *
+ * The license for this file can be found in the file COPYING which you
+ * should have received along with this file.
+ ****************************************************************************/
+
+#ifndef AQH_EVENTLOOP_P_H
+#define AQH_EVENTLOOP_P_H
+
+#include "./eventloop.h"
+
+
+
+struct AQH_EVENT_LOOP
+{
+ AQH_OBJECT_LIST2 *fdObjectList;
+ AQH_OBJECT_LIST2 *timerObjectList;
+};
+
+
+
+
+#endif
diff --git a/aqhome/events2/eventloop_select.c b/aqhome/events2/eventloop_select.c
new file mode 100644
index 0000000..fa4381f
--- /dev/null
+++ b/aqhome/events2/eventloop_select.c
@@ -0,0 +1,173 @@
+/****************************************************************************
+ * This file is part of the project AqHome.
+ * AqHome (c) by 2025 Martin Preuss, all rights reserved.
+ *
+ * The license for this file can be found in the file COPYING which you
+ * should have received along with this file.
+ ****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include "./eventloop_p.h"
+#include "./fdobject.h"
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+
+
+/* ------------------------------------------------------------------------------------------------
+ * forward declarations
+ * ------------------------------------------------------------------------------------------------
+ */
+
+static int _sampleFdsIntoSet(AQH_OBJECT_LIST2 *ol, fd_set *fds, int mode);
+static void _markReadyFdObjects(AQH_OBJECT_LIST2 *ol, fd_set *fds, int mode);
+static void _signalReadyFdObjects(AQH_OBJECT_LIST2 *ol);
+
+
+
+/* ------------------------------------------------------------------------------------------------
+ * code
+ * ------------------------------------------------------------------------------------------------
+ */
+
+void AQH_EventLoop_Run(AQH_EVENT_LOOP *eventLoop)
+{
+ fd_set fdRead;
+ fd_set fdWrite;
+ int highestFd=-1;
+ int rv;
+
+ FD_ZERO(&fdRead);
+ FD_ZERO(&fdWrite);
+
+ highestFd=_sampleFdsIntoSet(eventLoop->fdObjectList, &fdRead, AQH_FDOBJECT_FDMODE_READ);
+ rv=_sampleFdsIntoSet(eventLoop->fdObjectList, &fdWrite, AQH_FDOBJECT_FDMODE_WRITE);
+ highestFd=(rv>highestFd)?rv:highestFd;
+
+ if (highestFd>-1) {
+ struct timeval tv;
+
+ tv.tv_sec=0;
+ tv.tv_usec=200000;
+ rv=select(highestFd+1, &fdRead, &fdWrite, NULL, &tv);
+ if (rv>0) {
+ /* some fds became active */
+ _markReadyFdObjects(eventLoop->fdObjectList, &fdRead, AQH_FDOBJECT_FDMODE_READ);
+ _markReadyFdObjects(eventLoop->fdObjectList, &fdWrite, AQH_FDOBJECT_FDMODE_WRITE);
+ _signalReadyFdObjects(eventLoop->fdObjectList);
+ }
+ else if (rv<0) {
+ if (errno!=EINTR) {
+ /* error */
+ DBG_ERROR(AQH_LOGDOMAIN, "Error on SELECT: %d (%s)", errno, strerror(errno));
+ }
+ }
+ else {
+ /* no fd became active (TODO: maybe signal deep idle objects?) */
+ }
+ }
+}
+
+
+
+int _sampleFdsIntoSet(AQH_OBJECT_LIST2 *ol, fd_set *fds, int mode)
+{
+ AQH_OBJECT_LIST2_ITERATOR *it;
+ int highestFd=-1;
+
+ it=AQH_Object_List2_First(ol);
+ if (it) {
+ AQH_OBJECT *o;
+
+ o=AQH_Object_List2Iterator_Data(it);
+ while(o) {
+ int m;
+
+ m=AQH_FdObject_GetFdMode(o);
+ if (m==mode) {
+ int fd;
+
+ fd=AQH_FdObject_GetFd(o);
+ if (fd>-1) {
+ highestFd=(fd>highestFd)?fd:highestFd;
+ FD_SET(fd, fds);
+ }
+ }
+ o=AQH_Object_List2Iterator_Next(it);
+ }
+ AQH_Object_List2Iterator_free(it);
+ }
+
+ return highestFd;
+}
+
+
+
+void _markReadyFdObjects(AQH_OBJECT_LIST2 *ol, fd_set *fds, int mode)
+{
+ AQH_OBJECT_LIST2_ITERATOR *it;
+
+ it=AQH_Object_List2_First(ol);
+ if (it) {
+ AQH_OBJECT *o;
+
+ o=AQH_Object_List2Iterator_Data(it);
+ while(o) {
+ int m;
+
+ m=AQH_FdObject_GetFdMode(o);
+ if (m==mode) {
+ int fd;
+
+ fd=AQH_FdObject_GetFd(o);
+ if (FD_ISSET(fd, fds))
+ AQH_Object_AddFlags(o, AQH_OBJECT_FLAGS_FIRE);
+ }
+ o=AQH_Object_List2Iterator_Next(it);
+ }
+
+ AQH_Object_List2Iterator_free(it);
+ }
+}
+
+
+
+void _signalReadyFdObjects(AQH_OBJECT_LIST2 *ol)
+{
+ AQH_OBJECT_LIST2_ITERATOR *it;
+
+ it=AQH_Object_List2_First(ol);
+ if (it) {
+ AQH_OBJECT *o;
+
+ o=AQH_Object_List2Iterator_Data(it);
+ while(o) {
+ if (AQH_Object_GetFlags(o) & AQH_OBJECT_FLAGS_FIRE) {
+ AQH_Object_SubFlags(o, AQH_OBJECT_FLAGS_FIRE);
+ AQH_Object_EmitSignal(o, AQH_FDOBJECT_SIGNAL_ISREADY, 0, NULL);
+ }
+ o=AQH_Object_List2Iterator_Next(it);
+ }
+
+ AQH_Object_List2Iterator_free(it);
+ }
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/aqhome/events2/fdobject.c b/aqhome/events2/fdobject.c
new file mode 100644
index 0000000..6d1cc56
--- /dev/null
+++ b/aqhome/events2/fdobject.c
@@ -0,0 +1,140 @@
+/****************************************************************************
+ * This file is part of the project Gwenhywfar.
+ * Gwenhywfar (c) by 2023 Martin Preuss, all rights reserved.
+ *
+ * The license for this file can be found in the file COPYING which you
+ * should have received along with this file.
+ ****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include "./fdobject_p.h"
+
+#include
+
+
+
+GWEN_INHERIT(AQH_OBJECT, AQH_FDOBJECT)
+
+
+
+/* ------------------------------------------------------------------------------------------------
+ * forward declarations
+ * ------------------------------------------------------------------------------------------------
+ */
+
+static void GWENHYWFAR_CB _freeData(void *bp, void *p);
+static void _cbEnable(AQH_OBJECT *o);
+static void _cbDisable(AQH_OBJECT *o);
+
+
+
+
+/* ------------------------------------------------------------------------------------------------
+ * implementations
+ * ------------------------------------------------------------------------------------------------
+ */
+
+AQH_OBJECT *AQH_FdObject_new(AQH_EVENT_LOOP *eventLoop, int fd, int mode)
+{
+ AQH_OBJECT *o;
+ AQH_FDOBJECT *xo;
+
+ o=AQH_Object_new(eventLoop);
+ GWEN_NEW_OBJECT(AQH_FDOBJECT, xo);
+ GWEN_INHERIT_SETDATA(AQH_OBJECT, AQH_FDOBJECT, o, xo, _freeData);
+ xo->fd=fd;
+ xo->fdMode=mode;
+
+ AQH_Object_SetEnableFn(o, _cbEnable);
+ AQH_Object_SetDisableFn(o, _cbDisable);
+
+ return o;
+}
+
+
+
+void GWENHYWFAR_CB _freeData(GWEN_UNUSED void *bp, void *p)
+{
+ AQH_FDOBJECT *xo;
+
+ xo=(AQH_FDOBJECT*)p;
+ GWEN_FREE_OBJECT(xo);
+}
+
+
+
+int AQH_FdObject_GetFdMode(const AQH_OBJECT *o)
+{
+ if (o) {
+ AQH_FDOBJECT *xo;
+
+ xo=GWEN_INHERIT_GETDATA(AQH_OBJECT, AQH_FDOBJECT, o);
+ if (xo)
+ return xo->fdMode;
+ }
+
+ return 0;
+}
+
+
+
+void AQH_FdObject_SetFdMode(AQH_OBJECT *o, int i)
+{
+ if (o) {
+ AQH_FDOBJECT *xo;
+
+ xo=GWEN_INHERIT_GETDATA(AQH_OBJECT, AQH_FDOBJECT, o);
+ if (xo)
+ xo->fdMode=i;
+ }
+}
+
+
+
+int AQH_FdObject_GetFd(const AQH_OBJECT *o)
+{
+ if (o) {
+ AQH_FDOBJECT *xo;
+
+ xo=GWEN_INHERIT_GETDATA(AQH_OBJECT, AQH_FDOBJECT, o);
+ if (xo)
+ return xo->fd;
+ }
+
+ return -1;
+}
+
+
+
+void _cbEnable(AQH_OBJECT *o)
+{
+ if (o) {
+ AQH_EVENT_LOOP *eventLoop;
+
+ eventLoop=AQH_Object_GetEventLoop(o);
+ if (eventLoop)
+ AQH_EventLoop_AddFdObject(eventLoop, o);
+ }
+}
+
+
+
+void _cbDisable(AQH_OBJECT *o)
+{
+ if (o) {
+ AQH_EVENT_LOOP *eventLoop;
+
+ eventLoop=AQH_Object_GetEventLoop(o);
+ if (eventLoop)
+ AQH_EventLoop_DelFdObject(eventLoop, o);
+ }
+}
+
+
+
+
+
+
diff --git a/aqhome/events2/fdobject.h b/aqhome/events2/fdobject.h
new file mode 100644
index 0000000..09a8678
--- /dev/null
+++ b/aqhome/events2/fdobject.h
@@ -0,0 +1,36 @@
+/****************************************************************************
+ * This file is part of the project Gwenhywfar.
+ * Gwenhywfar (c) by 2023 Martin Preuss, all rights reserved.
+ *
+ * The license for this file can be found in the file COPYING which you
+ * should have received along with this file.
+ ****************************************************************************/
+
+#ifndef AQH_FDOBJECT_H
+#define AQH_FDOBJECT_H
+
+
+#include
+
+
+enum {
+ AQH_FDOBJECT_FDMODE_READ=1,
+ AQH_FDOBJECT_FDMODE_WRITE
+};
+
+
+enum {
+ AQH_FDOBJECT_SIGNAL_ISREADY=AQH_OBJECT_SIGNAL_LAST
+};
+
+
+
+AQHOME_API AQH_OBJECT *AQH_FdObject_new(AQH_EVENT_LOOP *eventLoop, int fd, int mode);
+
+AQHOME_API int AQH_FdObject_GetFdMode(const AQH_OBJECT *o);
+AQHOME_API void AQH_FdObject_SetFdMode(AQH_OBJECT *o, int i);
+
+AQHOME_API int AQH_FdObject_GetFd(const AQH_OBJECT *o);
+
+
+#endif
diff --git a/aqhome/events2/fdobject_p.h b/aqhome/events2/fdobject_p.h
new file mode 100644
index 0000000..c3793b3
--- /dev/null
+++ b/aqhome/events2/fdobject_p.h
@@ -0,0 +1,23 @@
+/****************************************************************************
+ * This file is part of the project Gwenhywfar.
+ * Gwenhywfar (c) by 2023 Martin Preuss, all rights reserved.
+ *
+ * The license for this file can be found in the file COPYING which you
+ * should have received along with this file.
+ ****************************************************************************/
+
+#ifndef AQH_FDOBJECT_P_H
+#define AQH_FDOBJECT_P_H
+
+
+#include "./fdobject.h"
+
+
+typedef struct AQH_FDOBJECT AQH_FDOBJECT;
+struct AQH_FDOBJECT {
+ int fdMode;
+ int fd;
+};
+
+
+#endif
diff --git a/aqhome/events2/object.c b/aqhome/events2/object.c
new file mode 100644
index 0000000..61a3a24
--- /dev/null
+++ b/aqhome/events2/object.c
@@ -0,0 +1,276 @@
+/****************************************************************************
+ * This file is part of the project AqHome.
+ * AqHome (c) by 2025 Martin Preuss, all rights reserved.
+ *
+ * The license for this file can be found in the file COPYING which you
+ * should have received along with this file.
+ ****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include "./object_p.h"
+
+
+
+/* ------------------------------------------------------------------------------------------------
+ * forward declarations
+ * ------------------------------------------------------------------------------------------------
+ */
+
+AQH_LINK *AQH_Link_new();
+void AQH_Link_free(AQH_LINK *ln);
+
+AQH_LINK *_findLink(AQH_OBJECT *o, uint32_t signalId, uint32_t slotId, AQH_OBJECT *targetObject);
+
+
+
+/* ------------------------------------------------------------------------------------------------
+ * list, inherit
+ * ------------------------------------------------------------------------------------------------
+ */
+
+GWEN_LIST_FUNCTIONS(AQH_LINK, AQH_Link)
+
+GWEN_INHERIT_FUNCTIONS(AQH_OBJECT)
+GWEN_LIST_FUNCTIONS(AQH_OBJECT, AQH_Object)
+GWEN_LIST2_FUNCTIONS(AQH_OBJECT, AQH_Object)
+
+
+
+/* ------------------------------------------------------------------------------------------------
+ * code
+ * ------------------------------------------------------------------------------------------------
+ */
+
+AQH_OBJECT *AQH_Object_new(AQH_EVENT_LOOP *eventLoop)
+{
+ AQH_OBJECT *o;
+
+ GWEN_NEW_OBJECT(AQH_OBJECT, o);
+ GWEN_INHERIT_INIT(AQH_OBJECT, o);
+ GWEN_LIST_INIT(AQH_OBJECT, o);
+ o->eventLoop=eventLoop;
+ o->linkList=AQH_Link_List_new();
+
+ return 0;
+}
+
+
+
+void AQH_Object_free(AQH_OBJECT *o)
+{
+ if (o) {
+ GWEN_INHERIT_FINI(AQH_OBJECT, o);
+ GWEN_LIST_FINI(AQH_OBJECT, o);
+
+ AQH_Link_List_free(o->linkList);
+
+ GWEN_FREE_OBJECT(o);
+ }
+}
+
+
+
+uint32_t AQH_Object_GetFlags(const AQH_OBJECT *o)
+{
+ return o?o->flags:0;
+}
+
+
+
+void AQH_Object_SetFlags(AQH_OBJECT *o, uint32_t i)
+{
+ if (o)
+ o->flags=i;
+}
+
+
+
+void AQH_Object_AddFlags(AQH_OBJECT *o, uint32_t i)
+{
+ if (o)
+ o->flags|=i;
+}
+
+
+
+void AQH_Object_SubFlags(AQH_OBJECT *o, uint32_t i)
+{
+ if (o)
+ o->flags&=~i;
+}
+
+
+
+AQH_EVENT_LOOP *AQH_Object_GetEventLoop(const AQH_OBJECT *o)
+{
+ return o?o->eventLoop:NULL;
+}
+
+
+
+AQH_LINK *_findLink(AQH_OBJECT *o, uint32_t signalId, uint32_t slotId, AQH_OBJECT *targetObject)
+{
+ if (o) {
+ AQH_LINK *ln;
+
+ ln=AQH_Link_List_First(o->linkList);
+ while(ln) {
+ if (ln->signalIdForSender==signalId &&
+ ln->signalIdForTarget==slotId &&
+ ln->targetObject==targetObject)
+ return ln;
+ ln=AQH_Link_List_Next(ln);
+ }
+ }
+ return NULL;
+}
+
+
+
+void AQH_Object_AddLink(AQH_OBJECT *o, uint32_t signalId, uint32_t slotId, AQH_OBJECT *targetObject)
+{
+ AQH_LINK *ln;
+
+ ln=_findLink(o, signalId, slotId, targetObject);
+ if (ln==NULL) {
+ ln=AQH_Link_new();
+ ln->signalIdForSender=signalId;
+ ln->signalIdForTarget=slotId;
+ ln->targetObject=targetObject;
+ AQH_Link_List_Add(ln, o->linkList);
+ }
+}
+
+
+
+void AQH_Object_DelLink(AQH_OBJECT *o, uint32_t signalId, uint32_t slotId, AQH_OBJECT *targetObject)
+{
+ AQH_LINK *ln;
+
+ ln=_findLink(o, signalId, slotId, targetObject);
+ if (ln) {
+ AQH_Link_List_Del(ln);
+ AQH_Link_free(ln);
+ }
+}
+
+
+
+int AQH_Object_EmitSignal(AQH_OBJECT *o, uint32_t signalId, int param1, void *param2)
+{
+ int signalWasHandled=0;
+
+ if (o) {
+ AQH_LINK *ln;
+
+ ln=AQH_Link_List_First(o->linkList);
+ while(ln) {
+ if (ln->signalIdForSender==signalId && ln->targetObject) {
+ if (AQH_Object_HandleSignal(ln->targetObject, ln->signalIdForTarget, o, param1, param2))
+ signalWasHandled=1;
+ }
+ ln=AQH_Link_List_Next(ln);
+ }
+ }
+ return signalWasHandled;
+}
+
+
+
+int AQH_Object_HandleSignal(AQH_OBJECT *o, uint32_t slotId, AQH_OBJECT *senderObject, int param1, void *param2)
+{
+ if (o && o->signalHandlerFn)
+ return o->signalHandlerFn(o, slotId, senderObject, param1, param2);
+ return 0;
+}
+
+
+
+void AQH_Object_Enable(AQH_OBJECT *o)
+{
+ if (o && o->enableFn)
+ o->enableFn(o);
+}
+
+
+
+void AQH_Object_Disable(AQH_OBJECT *o)
+{
+ if (o && o->disableFn)
+ o->disableFn(o);
+}
+
+
+
+AQH_OBJECT_SIGNALHANDLER_FN AQH_Object_SetSignalHandlerFn(AQH_OBJECT *o, AQH_OBJECT_SIGNALHANDLER_FN f)
+{
+ if (o) {
+ AQH_OBJECT_SIGNALHANDLER_FN oldFn;
+
+ oldFn=o->signalHandlerFn;
+ o->signalHandlerFn=f;
+ return oldFn;
+ }
+ return NULL;
+}
+
+
+
+AQH_OBJECT_ENABLE_FN AQH_Object_SetEnableFn(AQH_OBJECT *o, AQH_OBJECT_ENABLE_FN f)
+{
+ if (o) {
+ AQH_OBJECT_ENABLE_FN oldFn;
+
+ oldFn=o->enableFn;
+ o->enableFn=f;
+ return oldFn;
+ }
+ return NULL;
+}
+
+
+
+AQH_OBJECT_DISABLE_FN AQH_Object_SetDisableFn(AQH_OBJECT *o, AQH_OBJECT_DISABLE_FN f)
+{
+ if (o) {
+ AQH_OBJECT_DISABLE_FN oldFn;
+
+ oldFn=o->disableFn;
+ o->disableFn=f;
+ return oldFn;
+ }
+ return NULL;
+}
+
+
+
+
+
+
+AQH_LINK *AQH_Link_new()
+{
+ AQH_LINK *ln;
+
+ GWEN_NEW_OBJECT(AQH_LINK, ln);
+ GWEN_LIST_INIT(AQH_LINK, ln);
+
+ return ln;
+}
+
+
+
+void AQH_Link_free(AQH_LINK *ln)
+{
+ if (ln) {
+ GWEN_LIST_FINI(AQH_LINK, ln);
+ GWEN_FREE_OBJECT(ln);
+ }
+}
+
+
+
+
+
diff --git a/aqhome/events2/object.h b/aqhome/events2/object.h
new file mode 100644
index 0000000..e801c9c
--- /dev/null
+++ b/aqhome/events2/object.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+ * This file is part of the project AqHome.
+ * AqHome (c) by 2025 Martin Preuss, all rights reserved.
+ *
+ * The license for this file can be found in the file COPYING which you
+ * should have received along with this file.
+ ****************************************************************************/
+
+#ifndef AQH_OBJECT_H
+#define AQH_OBJECT_H
+
+#include "aqhome/api.h"
+
+#include
+#include
+#include
+
+#include
+
+
+
+#define AQH_OBJECT_FLAGS_FIRE 0x80000000L
+
+
+enum {
+ AQH_OBJECT_SIGNAL_LAST=10 /* reserve signal ids 0-9 */
+};
+
+
+
+/* ------------------------------------------------------------------------------------------------
+ * @name Type Definition
+ */
+/*@{*/
+typedef struct AQH_OBJECT AQH_OBJECT;
+GWEN_INHERIT_FUNCTION_LIB_DEFS(AQH_OBJECT, AQHOME_API)
+GWEN_LIST_FUNCTION_LIB_DEFS(AQH_OBJECT, AQH_Object, AQHOME_API)
+GWEN_LIST2_FUNCTION_LIB_DEFS(AQH_OBJECT, AQH_Object, AQHOME_API)
+/*@}*/
+
+
+#include
+
+
+
+/* ------------------------------------------------------------------------------------------------
+ * @name Virtual Function Declarations
+ */
+/*@{*/
+typedef int (*AQH_OBJECT_SIGNALHANDLER_FN)(AQH_OBJECT *o, uint32_t slotId, AQH_OBJECT *senderObject, int param1, void *param2);
+typedef void (*AQH_OBJECT_ENABLE_FN)(AQH_OBJECT *o);
+typedef void (*AQH_OBJECT_DISABLE_FN)(AQH_OBJECT *o);
+/*@}*/
+
+
+
+/* ------------------------------------------------------------------------------------------------
+ * @name Construction, Destruction
+ */
+/*@{*/
+AQHOME_API AQH_OBJECT *AQH_Object_new(AQH_EVENT_LOOP *eventLoop);
+AQHOME_API void AQH_Object_free(AQH_OBJECT *o);
+/*@}*/
+
+
+
+/* ------------------------------------------------------------------------------------------------
+ * @name Manipulate Flags
+ */
+/*@{*/
+AQHOME_API uint32_t AQH_Object_GetFlags(const AQH_OBJECT *o);
+AQHOME_API void AQH_Object_SetFlags(AQH_OBJECT *o, uint32_t i);
+AQHOME_API void AQH_Object_AddFlags(AQH_OBJECT *o, uint32_t i);
+AQHOME_API void AQH_Object_SubFlags(AQH_OBJECT *o, uint32_t i);
+/*@}*/
+
+
+
+/* ------------------------------------------------------------------------------------------------
+ * @name Getters, Setters
+ */
+/*@{*/
+AQHOME_API AQH_EVENT_LOOP *AQH_Object_GetEventLoop(const AQH_OBJECT *o);
+/*@}*/
+
+
+
+/* ------------------------------------------------------------------------------------------------
+ * @name Link Handling
+ */
+/*@{*/
+AQHOME_API void AQH_Object_AddLink(AQH_OBJECT *o, uint32_t signalId, uint32_t slotId, AQH_OBJECT *targetObject);
+AQHOME_API void AQH_Object_DelLink(AQH_OBJECT *o, uint32_t signalId, uint32_t slotId, AQH_OBJECT *targetObject);
+/*@}*/
+
+
+
+/* ------------------------------------------------------------------------------------------------
+ * @name Virtual Function Declarations
+ */
+/*@{*/
+AQHOME_API int AQH_Object_EmitSignal(AQH_OBJECT *o, uint32_t signalId, int param1, void *param2);
+AQHOME_API int AQH_Object_HandleSignal(AQH_OBJECT *o, uint32_t slotId, AQH_OBJECT *senderObject, int param1, void *param2);
+AQHOME_API void AQH_Object_Enable(AQH_OBJECT *o);
+AQHOME_API void AQH_Object_Disable(AQH_OBJECT *o);
+/*@}*/
+
+
+
+/* ------------------------------------------------------------------------------------------------
+ * @name Setter for Virtual Functions
+ */
+/*@{*/
+AQHOME_API AQH_OBJECT_SIGNALHANDLER_FN AQH_Object_SetSignalHandlerFn(AQH_OBJECT *o, AQH_OBJECT_SIGNALHANDLER_FN f);
+AQHOME_API AQH_OBJECT_ENABLE_FN AQH_Object_SetEnableFn(AQH_OBJECT *o, AQH_OBJECT_ENABLE_FN f);
+AQHOME_API AQH_OBJECT_DISABLE_FN AQH_Object_SetDisableFn(AQH_OBJECT *o, AQH_OBJECT_DISABLE_FN f);
+/*@}*/
+
+
+
+#endif
diff --git a/aqhome/events2/object_p.h b/aqhome/events2/object_p.h
new file mode 100644
index 0000000..b5f5c6e
--- /dev/null
+++ b/aqhome/events2/object_p.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+ * This file is part of the project Gwenhywfar.
+ * Gwenhywfar (c) by 2023 Martin Preuss, all rights reserved.
+ *
+ * The license for this file can be found in the file COPYING which you
+ * should have received along with this file.
+ ****************************************************************************/
+
+#ifndef AQH_OBJECT_P_H
+#define AQH_OBJECT_P_H
+
+
+#include "./object.h"
+
+
+typedef struct AQH_LINK AQH_LINK;
+GWEN_LIST_FUNCTION_DEFS(AQH_LINK, AQH_Link)
+
+
+
+struct AQH_LINK {
+ GWEN_LIST_ELEMENT(AQH_LINK)
+
+ uint32_t signalIdForSender;
+ uint32_t signalIdForTarget;
+ AQH_OBJECT *targetObject;
+};
+
+
+
+struct AQH_OBJECT {
+ GWEN_INHERIT_ELEMENT(AQH_OBJECT)
+ GWEN_LIST_ELEMENT(AQH_OBJECT)
+
+ uint32_t flags;
+ AQH_EVENT_LOOP *eventLoop;
+
+ AQH_LINK_LIST *linkList;
+
+ AQH_OBJECT_SIGNALHANDLER_FN signalHandlerFn;
+ AQH_OBJECT_ENABLE_FN enableFn;
+ AQH_OBJECT_DISABLE_FN disableFn;
+};
+
+
+#endif