diff --git a/docs/reference/matrix-glib/matrix-glib-sections.txt b/docs/reference/matrix-glib/matrix-glib-sections.txt index ebc812c..085a1d8 100644 --- a/docs/reference/matrix-glib/matrix-glib-sections.txt +++ b/docs/reference/matrix-glib/matrix-glib-sections.txt @@ -35,6 +35,7 @@ matrix_event_get_type MatrixClient MatrixClientInterface matrix_client_login_finished +matrix_client_incoming_event matrix_client_register_with_password matrix_client_login_with_password matrix_client_logout diff --git a/src/Makefile.am b/src/Makefile.am index 14f3f60..8a99cf4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -81,11 +81,14 @@ INST_H_SRC_FILES = \ INST_H_BUILT_FILES = \ matrix-version.h \ + matrix-marshalers.h \ $(NULL) libmatrix_glib_0_0_la_SOURCES = \ $(INST_H_BUILT_FILES) \ + matrix-marshalers.c \ $(libmatrix_glib_0_0_la_VALA_SOURCES:.vala=.c) \ + matrix-event-types.c \ matrix-version.c \ $(INST_H_SRC_FILES) \ $(NULL) @@ -119,6 +122,8 @@ dist_vapi_DATA = \ $(NULL) BUILT_SOURCES += \ + matrix-marshalers.c \ + matrix-marshalers.h \ $(NULL) test_api_client_SOURCES = test-api-client.c @@ -130,9 +135,35 @@ test_api_client_LDADD = \ CLEANFILES += $(BUILT_SOURCES) EXTRA_DIST += \ + matrix-marshalers.list \ $(INST_H_SRC_FILES) \ $(NULL) +matrix-marshalers.h: stamp-matrix-marshalers + @true + +stamp-matrix-marshalers: matrix-marshalers.list + $(AM_V_GEN) $(GLIB_GENMARSHAL) --prefix=_matrix_marshal \ + $(srcdir)/matrix-marshalers.list \ + --header \ + --valist-marshallers >> xgen-gmlh \ + && (cmp -s xgen-gmlh matrix-marshalers.h \ + || cp xgen-gmlh matrix-marshalers.h) \ + && rm -f xgen-gmlh \ + && echo timestamp > $(@F) + +matrix-marshalers.c: matrix-marshalers.h + $(AM_V_GEN) (echo "#include \"matrix-marshalers.h\""; \ + echo "#undef G_ENABLE_DEBUG"; \ + $(GLIB_GENMARSHAL) --prefix=_matrix_marshal \ + $(srcdir)/matrix-marshalers.list \ + --body \ + --valist-marshallers) >> xgen-gmlc \ + && cp xgen-gmlc matrix-marshalers.c \ + && rm -f xgen-gmlc + +CLEANFILES += stamp-matrix-marshalers + include $(INTROSPECTION_MAKEFILE) Matrix-0.0.gir: libmatrix-glib-$(MATRIX_GLIB_API_VERSION).la diff --git a/src/matrix-client.vala b/src/matrix-client.vala index 867f794..b6a9032 100644 --- a/src/matrix-client.vala +++ b/src/matrix-client.vala @@ -33,6 +33,36 @@ public interface Matrix.Client : GLib.Object { login_finished(bool success) {} + /** + * This signal is a sign of an incoming event. It gets emitted for + * every signal, regardless if it is handled by other event + * signals, before other signals. + * + * Implementations are responsible for emitting this signal when + * any kind of event arrives from the event stream or the history. + * + * @param room_id the ID of the room associated with this event + * @param raw_event the raw event as a JSON object + * @param matrix_event the event as a {@link Matrix.Event} + */ + [Signal (detailed=true)] + public virtual signal void + @event(string? room_id, Json.Node raw_event, Matrix.Event matrix_event) + {} + + /** + * Callback function delegate for the event signal. + * + * @param room_id the room the event associated with + * @param raw_event the event as a raw JSON object + * @param matrix_event the event as a Matrix.Event object + */ + public delegate void + EventCallback(Matrix.Client client, + string? room_id, + Json.Node raw_event, + Matrix.Event matrix_event); + /** * Authenticate with the Matrix.org server with a username and * password. @@ -103,4 +133,37 @@ public interface Matrix.Client : GLib.Object { { login_finished(success); } + + /** + * Emits the #MatrixClient::event signal. + * + * @param room_id the room this event is associated with + * @param raw_event the raw event + * @param matrix_event the event as a Matrix.Event + */ + public void + incoming_event(string? room_id, + Json.Node raw_event, + Matrix.Event matrix_event) + { + Quark equark = matrix_event.get_type().qname(); + + this.@event[equark.to_string()](room_id, raw_event, matrix_event); + } + + /** + * Connect a handler for events. If @param event_gtype is + * Matrix.Event, all events will be sent to the callback function, + * otherwise only events that match the specified event type. + * + * If @event_gtype is not derived from + * {@link Matrix.Event}, @param callback won’t get connected. + * + * @param event_gtype the {@link GLib.Type} of a + * {@link Matrix.Event} derivative + * @param callback the allback function to connect + */ + public extern void + connect_event(GLib.Type event_gtype, + owned EventCallback event_callback); } diff --git a/src/matrix-event-types.c b/src/matrix-event-types.c index 7e47123..727cc70 100644 --- a/src/matrix-event-types.c +++ b/src/matrix-event-types.c @@ -153,3 +153,39 @@ static void matrix_event_types_ctor(void) { } + +void +matrix_client_connect_event(MatrixClient *client, + GType event_gtype, + MatrixClientEventCallback callback, + gpointer user_data, + GDestroyNotify destroy_notify) +{ + GClosure *closure; + GQuark equark; + MatrixEventClass *event_class = MATRIX_EVENT_CLASS( + g_type_class_ref(event_gtype)); + guint event_signal_id = g_signal_lookup("event", MATRIX_TYPE_CLIENT); + + if (!MATRIX_IS_EVENT_CLASS(event_class)) { + g_warning("Trying to connect to a type that is not derived from MatrixEvent"); + g_type_class_unref(event_class); + + return; + } + + g_type_class_unref(event_class); + equark = g_type_qname(event_gtype); + + closure = g_closure_ref(g_cclosure_new(G_CALLBACK(callback), + user_data, + (GClosureNotify)destroy_notify)); + g_closure_set_marshal(closure, + _matrix_marshal_VOID__STRING_BOXED_OBJECT); + g_closure_sink(closure); + + g_signal_connect_closure_by_id(client, + event_signal_id, equark, + closure, FALSE); + +} diff --git a/src/matrix-marshalers.list b/src/matrix-marshalers.list new file mode 100644 index 0000000..1213246 --- /dev/null +++ b/src/matrix-marshalers.list @@ -0,0 +1 @@ +VOID:STRING,BOXED,OBJECT