diff --git a/.gitignore b/.gitignore
index bbada99..07f3b7e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -47,7 +47,6 @@ Makefile.in
/src/vala-temp
/src/vala-stamp
/src/matrix-glib.h
-/src/matrix-client.c
/src/matrix-http-client.c
/src/namespace-info.vala
/src/namespace-info.c
diff --git a/autogen.sh b/autogen.sh
index a568815..46c3815 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -8,7 +8,7 @@ DIE=0
PKG_NAME="matrix-glib"
(test -f "$srcdir/configure.ac" \
- && test -f "$srcdir/src/matrix-client.vala") || {
+ && test -f "$srcdir/src/matrix-client.c") || {
echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
echo " top-level $PKG_NAME directory"
diff --git a/src/Makefile.am b/src/Makefile.am
index 8f59e26..49eaa6e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -17,7 +17,6 @@ lib_LTLIBRARIES = libmatrix-glib-0.0.la
# Vala source files
libmatrix_glib_0_0_la_VALA_SOURCES = \
namespace-info.vala \
- matrix-client.vala \
matrix-http-client.vala \
$(NULL)
@@ -76,6 +75,7 @@ INST_H_SRC_FILES = \
matrix-compacts.h \
matrix-api.h \
matrix-http-api.h \
+ matrix-client.h \
matrix-event-base.h \
matrix-event-call-base.h \
matrix-event-call-answer.h \
@@ -135,6 +135,7 @@ libmatrix_glib_0_0_la_SOURCES = \
matrix-version.c \
matrix-api.c \
matrix-http-api.c \
+ matrix-client.c \
matrix-types.c \
matrix-compacts.c \
matrix-event-base.c \
diff --git a/src/matrix-client.c b/src/matrix-client.c
new file mode 100644
index 0000000..883dd50
--- /dev/null
+++ b/src/matrix-client.c
@@ -0,0 +1,496 @@
+/*
+ * This file is part of matrix-glib-sdk
+ *
+ * matrix-glib-sdk is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * matrix-glib-sdk is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with matrix-glib-sdk. If not, see
+ * .
+ */
+
+#include "matrix-client.h"
+#include "matrix-marshalers.h"
+
+/**
+ * SECTION:matrix-client
+ * @short_description: Interface for Matrix client implementations
+ * @title: Interface for Matrix client implementations
+ */
+
+enum {
+ SIGNAL_LOGIN_FINISHED,
+ SIGNAL_EVENT,
+ SIGNAL_POLLING_STARTED,
+ SIGNAL_POLLING_STOPPED,
+ NUM_SIGNALS
+};
+static guint matrix_client_signals[NUM_SIGNALS] = {0};
+
+/**
+ * MatrixClientInterface:
+ * @login_with_password: the virtual function pointer for matrix_client_login_with_password()
+ * @register_with_password: the virtual function pointer for matrix_client_register_with_password()
+ * @logout: the virtual function pointer for matrix_client_logout()
+ * @begin_polling: the virtual function pointer for matrix_client_begin_polling()
+ * @stop_polling: the virtual function pointer for matrix_client_stop_polling()
+ * @get_user_profile: the virtual function pointer for matrix_client_get_user_profile()
+ * @get_user_presence: the virtual function pointer for matrix_client_get_user_presence()
+ * @get_room_by_id: the virtual function pointer for matrix_client_get_room_by_id()
+ * @get_room_by_alias: the virtual function pointer for matrix_client_get_room_by_alias()
+ * @send: the virtual function pointer for matrix_client_send()
+ * @save_state: the virtual function pointer for matrix_client_save_state()
+ * @load_state: the virtual function pointer for matrix_client_load_state()
+ * @login_finished: the class closure for the #MatrixClient::login-finished signal
+ * @event: the class closure for the #MatrixClient::event signal
+ *
+ * Base interface for client communication with a Matrix.org homeserver
+ */
+G_DEFINE_INTERFACE(MatrixClient, matrix_client, G_TYPE_OBJECT);
+
+/**
+ * MatrixClientSendCallback:
+ * @client: the #MatrixClient that initiated the request
+ * @event_id: the event ID of the event just sent
+ * @error: (nullable): a #GError holding errors that happened during sending, if any
+ * @user_data: (nullable): user data set when event sending was initiated
+ *
+ * Callback function type for matrix_client_send().
+ */
+
+/**
+ * MatrixClientEventCallback:
+ * @client: the #MatrixClient that sent the signal
+ * @room_id: the room ID from which the event originated
+ * @raw_event: the raw event
+ * @matrix_event: (nullable): a #MatrixMessageBase derived object
+ * @user_data: (nullable): user data set when the signal was connected
+ *
+ * Callback function type for matrix_client_connect_event().
+ *
+ * @matrix_event may be unset if there was no message handler registered for the message type
+ * (using matrix_message_register_type()), or if the message couldn’t be deserialised by the
+ * message handler.
+ */
+
+/**
+ * matrix_client_login_with_password:
+ * @client: a #MatrixClient
+ * @username: the username to login with
+ * @password: the password to use
+ * @error: a #GError, or %NULL to ignore errors
+ *
+ * Authenticate with the Matrix.org server with a username and password.
+ */
+void
+matrix_client_login_with_password(MatrixClient *matrix_client, const gchar *username, const gchar *password, GError **error)
+{
+ g_return_if_fail(matrix_client != NULL);
+
+ MATRIX_CLIENT_GET_IFACE(matrix_client)->login_with_password(matrix_client, username, password, error);
+}
+
+/**
+ * matrix_client_register_with_password:
+ * @client: a #MatrixClient
+ * @username: the username to register. If omitted, the server will generate one
+ * @password: the password to use with the registration
+ * @error: a #GError, or %NULL to ignore errors
+ *
+ * Register @username with the homeserver as a normal user. Upon success, the user is registered
+ * and authenticated.
+ *
+ * Implementations must emit the #MatrixClient::login-finished signal when a response arrives.
+ *
+ * This method registers a normal user account. If you want to register a different kind of user,
+ * use matrix_api_register_account().
+ */
+void
+matrix_client_register_with_password(MatrixClient *matrix_client, const gchar *username, const gchar *password, GError **error)
+{
+ g_return_if_fail(matrix_client != NULL);
+
+ MATRIX_CLIENT_GET_IFACE(matrix_client)->register_with_password(matrix_client, username, password, error);
+}
+
+/**
+ * matrix_client_logout:
+ * @client: an object implementing the #MatrixClient interface
+ * @error: a #GError, or %NULL to ignore errors
+ *
+ * Logout from the homeserver. As Matrix.org doesn’t have such a concept, this cancels all ongoing
+ * requests and clears the authentication data (e.g. tokens).
+ */
+void
+matrix_client_logout(MatrixClient *matrix_client, GError **error)
+{
+ g_return_if_fail(matrix_client != NULL);
+
+ MATRIX_CLIENT_GET_IFACE(matrix_client)->logout(matrix_client, error);
+}
+
+/**
+ * matrix_client_begin_polling:
+ * @client: an object implementing the #MatrixClient interface
+ * @error: a #GError, or %NULL to ignore errors
+ *
+ * Begin polling the event stream.
+ */
+void
+matrix_client_begin_polling(MatrixClient *matrix_client, GError **error)
+{
+ g_return_if_fail(matrix_client != NULL);
+
+ MATRIX_CLIENT_GET_IFACE(matrix_client)->begin_polling(matrix_client, error);
+}
+
+/**
+ * matrix_client_stop_polling:
+ * @client: a #MatrixClient
+ * @cancel_ongoing: if %TRUE, ongoing requests will be cancelled, too
+ * @error: a #GError, or %NULL to ignore errors
+ *
+ * Stop polling the event stream. If @cancel_ongoing is %TRUE, ongoing requests will be cancelled,
+ * too.
+ */
+void
+matrix_client_stop_polling(MatrixClient *matrix_client, gboolean cancel_ongoing, GError **error)
+{
+ g_return_if_fail(matrix_client != NULL);
+
+ MATRIX_CLIENT_GET_IFACE(matrix_client)->stop_polling(matrix_client, cancel_ongoing, error);
+}
+
+/**
+ * matrix_client_emit_login_finished:
+ * @client: a #MatrixClient
+ * @success: set to %TRUE if login was successful
+ *
+ * Convenience function to emit the #MatrixClient::login-finished signal.
+ */
+void
+matrix_client_emit_login_finished(MatrixClient *matrix_client, gboolean success)
+{
+ g_signal_emit(matrix_client, matrix_client_signals[SIGNAL_LOGIN_FINISHED], 0, success);
+}
+
+/**
+ * matrix_client_incoming_event:
+ * @client: an object implementing the #MatrixClient interface
+ * @room_id: the room the event is associated with
+ * @raw_event: the raw event
+ * @matrix_event: the event as a Matrix.Event
+ *
+ * Emits the #MatrixClient::event signal.
+ */
+void
+matrix_client_incoming_event(MatrixClient *matrix_client, const gchar *room_id, JsonNode *raw_event, MatrixEventBase *matrix_event)
+{
+ GQuark equark;
+
+ g_return_if_fail(raw_event != NULL);
+
+ if (matrix_event == NULL) {
+ equark = g_type_qname(MATRIX_EVENT_TYPE_BASE);
+ } else {
+ equark = g_type_qname(G_TYPE_FROM_INSTANCE((GObject*)matrix_event));
+ }
+
+ g_signal_emit(matrix_client, matrix_client_signals[SIGNAL_EVENT], equark, room_id, raw_event, matrix_event);
+}
+
+/**
+ * matrix_client_get_user_profile:
+ * @client: an object implementing the #MatrixClient interface
+ * @user_id: (not nullable): the user ID to get the profile for
+ * @room_id: (nullable): the room ID to get the profile from, or %NULL to get the global profile
+ * @error: (nullable): a #GError, or %NULL to ignore errors
+ *
+ * Get the profile of a user specified by @user_id. If @room_id is not %NULL, return the
+ * room-specific profile. If the user’s profile is not cached yet, @error is set to
+ * #MATRIX_ERROR_UNAVAILABLE.
+ *
+ * Returns: (nullable): a #MatrixProfile object
+ */
+MatrixProfile *
+matrix_client_get_user_profile(MatrixClient *matrix_client, const gchar *user_id, const gchar *room_id, GError **error)
+{
+ g_return_val_if_fail(matrix_client != NULL, NULL);
+
+ return MATRIX_CLIENT_GET_IFACE(matrix_client)->get_user_profile(matrix_client, user_id, room_id, error);
+}
+
+/**
+ * matrix_client_get_user_presence:
+ * @client: an object implementing the #MatrixClient interface
+ * @user_id: (not nullable): the user ID to get presence info for
+ * @room_id: (nullable): the room ID to get the presence info from, or %NULL to get the global
+ * presence info
+ * @error: (nullable): a #GError, or %NULL to ignore errors
+ *
+ * Get the presence state of a user specified by @user_id. If @room_id is %NULL, return the room
+ * specific presence state. If the user's presence state is not cached yet, @error is set to
+ * #MATRIX_ERROR_UNAVAILABLE.
+ *
+ * Returns: the presence of @user_id
+ */
+MatrixPresence
+matrix_client_get_user_presence(MatrixClient *matrix_client, const gchar *user_id, const gchar *room_id, GError **error)
+{
+ g_return_val_if_fail(matrix_client != NULL, 0);
+
+ return MATRIX_CLIENT_GET_IFACE(matrix_client)->get_user_presence(matrix_client, user_id, room_id, error);
+}
+
+/**
+ * matrix_client_get_room_by_id:
+ * @client: an object implementing the #MatrixClient interface
+ * @room_id: (not nullable): the room ID to get the room information for
+ * @error: (nullable): a #GError, or %NULL to ignore errors
+ *
+ * Get a room object by the room ID specified in @room_id. If room data is not cached yet, error
+ * is set to #MATRIX_ERROR_UNAVAILABLE and %NULL is returned.
+ *
+ * Returns: (nullable): a #MatrixRoom object corresponding to @room_id
+ */
+MatrixRoom *
+matrix_client_get_room_by_id(MatrixClient *matrix_client, const gchar *room_id, GError **error)
+{
+ g_return_val_if_fail(matrix_client != NULL, NULL);
+
+ return MATRIX_CLIENT_GET_IFACE(matrix_client)->get_room_by_id(matrix_client, room_id, error);
+}
+
+/**
+ * matrix_client_get_room_by_alias:
+ * @client: an object implementing the #MatrixClient interface
+ * @room_alias: (not nullable): a room alias
+ * @error: (nullable): a #GError, or %NULL to ignore errors
+ *
+ * Get a room object by the room alias specified in @room_alias. If room data is not cached yet,
+ * @error is set to #MATRIX_ERROR_UNAVAILABLE and %NULL is returned.
+ *
+ * Please note that this may be a lengthy operation, especially if there are many rooms with many
+ * aliases.
+ *
+ * Returns: (nullable): a #MatrixRoom object with @room_alias
+ */
+MatrixRoom *
+matrix_client_get_room_by_alias(MatrixClient *matrix_client, const gchar *room_alias, GError **error)
+{
+ g_return_val_if_fail(matrix_client != NULL, NULL);
+
+ return MATRIX_CLIENT_GET_IFACE(matrix_client)->get_room_by_alias(matrix_client, room_alias, error);
+}
+
+/**
+ * matrix_client_send:
+ * @client: a #MatrixClient
+ * @room_id: the room to send the event to
+ * @evt: the event to send
+ * @callback: the callback function to call when the request is finished
+ * @user_data: user data to pass to the callback function
+ * @txn_id: the transaction ID to be used during this request. In case of a state event, it will be
+ * untouched
+ * @error: (nullable): a #GError, or %NULL to ignore errors
+ *
+ * Send an event to the given room. This should use the correct endpoint (e.g. the
+ * `/room/{roomId}/send` or the `/room/{roomId}/state` API in case of a HTTP connection) depending
+ * on the event: if the event has a state key (there is a state_key key in the generated JSON),
+ * even if an empty one, it will use the latter.
+ */
+void
+matrix_client_send(MatrixClient *matrix_client,
+ const gchar *room_id,
+ MatrixEventBase *evt,
+ gulong txn_id,
+ MatrixClientSendCallback cb,
+ gpointer user_data,
+ GError **error)
+{
+ g_return_if_fail(matrix_client != NULL);
+
+ MATRIX_CLIENT_GET_IFACE(matrix_client)->send(matrix_client, room_id, evt, cb, user_data, txn_id, error);
+}
+
+/**
+ * matrix_client_save_state:
+ * @client: an object implementing the #MatrixClient interface
+ * @filename: the filename to save state info to
+ * @error: a #GError, or %NULL to ignore errors
+ *
+ * Save the client state to a file. This may include server addresses and credentials, too, so a
+ * secure storage is highly recommended.
+ */
+void
+matrix_client_save_state(MatrixClient *matrix_client, const gchar *filename, GError **error)
+{
+ g_return_if_fail(matrix_client != NULL);
+
+ MATRIX_CLIENT_GET_IFACE(matrix_client)->save_state(matrix_client, filename, error);
+}
+
+/**
+ * matrix_client_load_state:
+ * @client: an object implementing the #MatrixClient interface
+ * @filename: the name of the file to load state from
+ * @error: (nullable): a #GError, or %NULL to ignore errors
+ *
+ * Load the state of the client, as saved by matrix_client_save_state().
+ */
+void
+matrix_client_load_state(MatrixClient *matrix_client, const gchar *filename, GError **error)
+{
+ g_return_if_fail(matrix_client != NULL);
+
+ MATRIX_CLIENT_GET_IFACE(matrix_client)->load_state(matrix_client, filename, error);
+}
+
+static void
+matrix_client_real_login_finished(MatrixClient *matrix_client, gboolean success)
+{}
+
+static void
+matrix_client_real_event(MatrixClient *matrix_client, const gchar *room_id, JsonNode *raw_event, MatrixEventBase *matrix_event)
+{
+ g_return_if_fail(raw_event != NULL);
+}
+
+static void
+matrix_client_default_init(MatrixClientInterface *iface)
+{
+ static gboolean initialized = FALSE;
+ if (!initialized) {
+ initialized = TRUE;
+ iface->login_finished = matrix_client_real_login_finished;
+ iface->event = matrix_client_real_event;
+ /**
+ * MatrixClient::login-finished:
+ * @client: the #MatrixClient that emitted the signal
+ * @success: if %TRUE, login was successful
+ *
+ * This signal is a sign for a finished login request.
+ *
+ * Implementations are responsible for emitting this signal when they get a response for a
+ * login request.
+ */
+ matrix_client_signals[SIGNAL_LOGIN_FINISHED] = g_signal_new(
+ "login-finished",
+ MATRIX_TYPE_CLIENT,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(MatrixClientInterface, login_finished),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+
+ /**
+ * MatrixClient::event:
+ * @client: the #MatrixClient that emitted the signal
+ * @room_id: the ID of the room associated with this event
+ * @raw_event: the raw event as a JSON object
+ * @matrix_event: the event as a #MatrixEventBase derived object
+ *
+ * This signal is a sign of an incoming event.
+ *
+ * It gets emitted for every event, 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.
+ */
+ matrix_client_signals[SIGNAL_EVENT] = g_signal_new(
+ "event",
+ MATRIX_TYPE_CLIENT,
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ G_STRUCT_OFFSET(MatrixClientInterface, event),
+ NULL, NULL,
+ _matrix_marshal_VOID__STRING_BOXED_OBJECT,
+ G_TYPE_NONE, 3, G_TYPE_STRING, JSON_TYPE_NODE, MATRIX_EVENT_TYPE_BASE);
+
+ /**
+ * MatrixClient::polling-started:
+ * @client: the #MatrixClient that emitted the signal
+ *
+ * This signal is emitted when polling is started.
+ */
+ matrix_client_signals[SIGNAL_POLLING_STARTED] = g_signal_new(
+ "polling-started",
+ MATRIX_TYPE_CLIENT,
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ /**
+ * MatrixClient::polling-stopped:
+ * @client: the object that sent the signal
+ * @error: gets set to an actual error if polling is stopped due to one
+ *
+ * This signal gets invoked when polling is stopped due to any reason.
+ */
+ matrix_client_signals[SIGNAL_POLLING_STOPPED] = g_signal_new(
+ "polling-stopped",
+ MATRIX_TYPE_CLIENT,
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOXED,
+ G_TYPE_NONE, 1, G_TYPE_ERROR);
+ }
+}
+
+/**
+ * matrix_client_connect_event:
+ * @client: a #MatrixClient
+ * @event_gtype: the #GType of a #MatrixEventBase derived type
+ * @event_callback: the callback function to connect
+ * @user_data: user data passed to the callback function
+ * @destroy_notify: function to call on @user_data when it can be destroyed
+ *
+ * Connect a handler for events. If @event_gtype is #MATRIX_EVENT_TYPE_BASE, 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 #MatrixEventBase, @callback won’t get connected.
+ */
+void
+matrix_client_connect_event(MatrixClient *client,
+ GType event_gtype,
+ MatrixClientEventCallback callback,
+ gpointer user_data,
+ GDestroyNotify destroy_notify)
+{
+ GClosure *closure;
+ GQuark equark;
+ MatrixEventBaseClass *event_class = MATRIX_EVENT_BASE_CLASS(
+ g_type_class_ref(event_gtype));
+ guint event_signal_id = g_signal_lookup("event", MATRIX_TYPE_CLIENT);
+
+ if (!MATRIX_EVENT_IS_BASE_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-client.h b/src/matrix-client.h
new file mode 100644
index 0000000..4ce806e
--- /dev/null
+++ b/src/matrix-client.h
@@ -0,0 +1,133 @@
+/*
+ * This file is part of matrix-glib-sdk
+ *
+ * matrix-glib-sdk is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * matrix-glib-sdk is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with matrix-glib-sdk. If not, see
+ * .
+ */
+
+#ifndef __MATRIX_GLIB_SDK_CLIENT_H__
+# define __MATRIX_GLIB_SDK_CLIENT_H__
+
+# include
+# include "matrix-enumtypes.h"
+# include "matrix-profile.h"
+# include "matrix-room.h"
+# include "matrix-event-base.h"
+
+G_BEGIN_DECLS
+
+# define MATRIX_TYPE_CLIENT matrix_client_get_type()
+G_DECLARE_INTERFACE(MatrixClient, matrix_client, MATRIX, CLIENT, GObject);
+
+typedef void (*MatrixClientSendCallback)(MatrixClient *client, const gchar *event_id, GError *error, void *user_data);
+typedef void (*MatrixClientEventCallback)(MatrixClient *client, const gchar *room_id, JsonNode *raw_event, MatrixEventBase *matrix_event, void *user_data);
+
+struct _MatrixClientInterface {
+ GTypeInterface parent_iface;
+ void (*login_with_password)(MatrixClient *client,
+ const gchar *username,
+ const gchar *password,
+ GError **error);
+ void (*register_with_password)(MatrixClient *client,
+ const gchar *username,
+ const gchar *password,
+ GError **error);
+ void (*logout)(MatrixClient *client, GError **error);
+ void (*begin_polling)(MatrixClient *client, GError **error);
+ void (*stop_polling)(MatrixClient *client, gboolean cancel_ongoing, GError **error);
+ MatrixProfile *(*get_user_profile)(MatrixClient *client,
+ const gchar *user_id,
+ const gchar *room_id,
+ GError **error);
+ MatrixPresence (*get_user_presence)(MatrixClient *client,
+ const gchar *user_id,
+ const gchar *room_id,
+ GError **error);
+ MatrixRoom *(*get_room_by_id)(MatrixClient *client, const gchar *room_id, GError **error);
+ MatrixRoom *(*get_room_by_alias)(MatrixClient *client,
+ const gchar *room_alias,
+ GError **error);
+ void (*send)(MatrixClient *client,
+ const gchar *room_id,
+ MatrixEventBase *evt,
+ MatrixClientSendCallback cb, void *cb_target,
+ gulong txn_id,
+ GError **error);
+ void (*save_state)(MatrixClient *client,
+ const gchar *filename,
+ GError **error);
+ void (*load_state)(MatrixClient *client,
+ const gchar *filename,
+ GError **error);
+ void (*login_finished)(MatrixClient *client, gboolean success);
+ void (*event)(MatrixClient *client,
+ const gchar *room_id,
+ JsonNode *raw_event,
+ MatrixEventBase *matrix_event);
+};
+
+GType matrix_client_get_type(void) G_GNUC_CONST;
+void matrix_client_login_with_password(MatrixClient *client,
+ const gchar *username,
+ const gchar *password,
+ GError **error);
+void matrix_client_register_with_password(MatrixClient *client,
+ const gchar *username,
+ const gchar *password,
+ GError **error);
+void matrix_client_logout(MatrixClient *client, GError **error);
+void matrix_client_begin_polling(MatrixClient *client, GError **error);
+void matrix_client_stop_polling(MatrixClient *client, gboolean cancel_ongoing, GError **error);
+void matrix_client_emit_login_finished(MatrixClient *client, gboolean success);
+void matrix_client_incoming_event(MatrixClient *client,
+ const gchar *room_id,
+ JsonNode *raw_event,
+ MatrixEventBase *matrix_event);
+void matrix_client_connect_event(MatrixClient *client,
+ GType event_gtype,
+ MatrixClientEventCallback event_callback,
+ gpointer user_data,
+ GDestroyNotify destroy_notify);
+MatrixProfile *matrix_client_get_user_profile(MatrixClient *client,
+ const gchar *user_id,
+ const gchar *room_id,
+ GError **error);
+MatrixPresence matrix_client_get_user_presence(MatrixClient *client,
+ const gchar *user_id,
+ const gchar *room_id,
+ GError **error);
+MatrixRoom *matrix_client_get_room_by_id(MatrixClient *client,
+ const gchar *room_id,
+ GError **error);
+MatrixRoom *matrix_client_get_room_by_alias(MatrixClient *client,
+ const gchar *room_alias,
+ GError **error);
+void matrix_client_send(MatrixClient *client,
+ const gchar *room_id,
+ MatrixEventBase *evt,
+ gulong txn_id,
+ MatrixClientSendCallback callback,
+ gpointer user_data,
+ GError **error);
+void matrix_client_save_state(MatrixClient *client, const gchar *filename, GError **error);
+void matrix_client_load_state(MatrixClient *client, const gchar *filename, GError **error);
+void matrix_client_connect_event(MatrixClient *client,
+ GType event_gtype,
+ MatrixClientEventCallback callback,
+ gpointer user_data,
+ GDestroyNotify destroy_notify);
+
+G_END_DECLS
+
+#endif /*__MATRIX_GLIB_SDK_CLIENT_H__ */
diff --git a/src/matrix-client.vala b/src/matrix-client.vala
deleted file mode 100644
index 56fc26d..0000000
--- a/src/matrix-client.vala
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * This file is part of matrix-glib-sdk
- *
- * matrix-glib-sdk is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * matrix-glib-sdk is distributed in the hope that it will be
- * useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with matrix-glib-sdk. If not, see
- * .
- */
-
-/**
- * Base interface for client communication with a Matrix.org
- * homeserver
- */
-public interface Matrix.Client : GLib.Object {
- /**
- * This signal is a sign for a finished login request.
- *
- * Implementations are responsible for emitting this signal when
- * they get a response for a login request.
- *
- * @param success if %TRUE, login was successful
- */
- public virtual signal void
- 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.Base? matrix_event)
- {}
-
- /**
- * This signal is emitted when polling is started.
- */
- public signal void
- polling_started();
-
- /**
- * This signal gets invoked when polling is stopped due to any
- * reason.
- *
- * @param error gets set to an actual error if polling is stopped
- * due to one
- */
- public signal void
- polling_stopped(GLib.Error? error);
-
- /**
- * 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.Base? matrix_event);
-
- /**
- * Authenticate with the Matrix.org server with a username and
- * password.
- *
- * @param username the username to login with
- * @param password the password to use
- */
- public abstract void
- login_with_password(string username,
- string password)
- throws Matrix.Error;
-
- /**
- * Register @username with the homeserver as a normal user.
- *
- * Upon success, the user is registered and authenticated.
- *
- * Implementations must emit the login-finished signal when a
- * response arrives.
- *
- * This method registers a normal user account. If you want to
- * register a different kind of user, use
- * matrix_api_register_account().
- *
- * @param username the username to register. If omitted, the
- * server will generate one
- * @param password the password to use with the registration
- */
- public abstract void
- register_with_password(string? username,
- string password)
- throws Matrix.Error;
-
- /**
- * Logout from the homeserver. As Matrix.org doesn’t have such a
- * concept, this cancels all ongoing requests and clears the
- * authentication data (e.g. tokens).
- */
- public abstract void
- logout()
- throws Matrix.Error;
-
- /**
- * Begin polling the event stream.
- */
- public abstract void
- begin_polling()
- throws Matrix.Error;
-
- /**
- * Stop polling the event stream. If @param cancel_ongoing is
- * {{{true}}}, ongoing requests will be cancelled, too.
- *
- * @param cancel_ongoing if {{{true}}}, ongoing requests will be
- * cancelled, too
- */
- public abstract void
- stop_polling(bool cancel_ongoing)
- throws Matrix.Error;
-
- /**
- * Convenience function to emits the login-finished signal.
- *
- * @param success set to {{{true}}} if login was successful
- */
- public void
- emit_login_finished(bool success)
- {
- 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.Base? matrix_event)
- {
- Quark equark;
-
- if (matrix_event == null) {
- equark = typeof(Matrix.Event.Base).qname();
- } else {
- 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 event_callback the allback function to connect
- */
- public extern void
- connect_event(GLib.Type event_gtype,
- owned EventCallback event_callback);
-
- /**
- * Get the profile of a user specified by @param user_id.
- * If @param room_id is not null, return the room-specific
- * profile. If the user's profile is not cached yet,
- * Matrix.Error.UNAVAILABLE is thrown.
- */
- public abstract Profile?
- get_user_profile(string user_id, string? room_id = null)
- throws Matrix.Error;
-
- /**
- * Get the presence state of a user specified
- * by @param user_id. If @param room_id is null, return
- * the room specific presence state. If the user's presence
- * state is not cached yet, Matrix.Error.UNAVAILABLE is
- * thrown.
- */
- public abstract Presence
- get_user_presence(string user_id, string? room_id = null)
- throws Matrix.Error;
-
- /**
- * Get a room object by the room ID specified in @param room_id.
- * If room data is not cached yet, Matrix.Error.UNAVAILABLE is
- * thrown.
- *
- * @param room_id the ID of a room
- * @return a Matrix.Room object
- */
- public abstract Room
- get_room_by_id(string room_id)
- throws Matrix.Error;
-
- /**
- * Get a room object by the room alias specified
- * in @param room_alias. If room data is not cached yet,
- * {@link Matrix.Error.UNAVAILABLE} is thrown.
- *
- * @param room_alias a room alias
- * @return a Matrix.Room object
- */
- public abstract Room
- get_room_by_alias(string room_alias)
- throws Matrix.Error;
-
- /**
- * Callback type for {@link Matrix.Client.send}.
- *
- * @param event_id the event_id returned by the server
- * @param err an error raised during event sending, if any
- */
- public delegate void
- SendCallback(string? event_id, GLib.Error? err);
-
- /**
- * Send an event to the given room. This will use the
- * /room/{roomId}/send or /room/{roomId}/state API depending on
- * the event: if the event has a state key (there is a state_key
- * key in the generated JSON), even if an empty one, it will use
- * the latter.
- *
- * @param room_id the room to send the event to
- * @param evt the event to send
- * @param cb the callback function to call when the request is
- * finished
- * @param txn_id the transaction ID used by this request. In case
- * of a state event, it will be untouched
- */
- public abstract void
- send(string room_id,
- Matrix.Event.Base evt,
- SendCallback? cb,
- out ulong txn_id)
- throws Matrix.Error;
-
- /*
- * Save the state of the client. Implementors can choose what they
- * actually save, and in what format.
- *
- * @param filename the name of the file to save state to
- */
- public abstract void
- save_state(string filename)
- throws Matrix.Error, GLib.Error;
-
- /**
- * Load the state of the client, as saved by save_state().
- *
- * @param filename the name of the file to load state from
- */
- public abstract void
- load_state(string filename)
- throws Matrix.Error, GLib.Error;
-}
diff --git a/src/matrix-event-types.c b/src/matrix-event-types.c
index 828db56..d0adaf8 100644
--- a/src/matrix-event-types.c
+++ b/src/matrix-event-types.c
@@ -279,38 +279,3 @@ matrix_event_types_ctor(void)
MATRIX_MESSAGE_TYPE_LOCATION,
NULL);
}
-
-void
-matrix_client_connect_event(MatrixClient *client,
- GType event_gtype,
- MatrixClientEventCallback callback,
- gpointer user_data,
- GDestroyNotify destroy_notify)
-{
- GClosure *closure;
- GQuark equark;
- MatrixEventBaseClass *event_class = MATRIX_EVENT_BASE_CLASS(
- g_type_class_ref(event_gtype));
- guint event_signal_id = g_signal_lookup("event", MATRIX_TYPE_CLIENT);
-
- if (!MATRIX_EVENT_IS_BASE_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/vapi/c-api.vapi b/vapi/c-api.vapi
index 7fc386e..145d0a5 100644
--- a/vapi/c-api.vapi
+++ b/vapi/c-api.vapi
@@ -948,6 +948,76 @@ namespace Matrix {
public void abort_pending();
}
+ [CCode (cheader_filename = "matrix-client.h", type_cname = "MatrixClientInterface")]
+ public interface Client : GLib.Object {
+ public virtual signal void login_finished(bool success);
+
+ [Signal (detailed=true)]
+ public virtual signal void @event(string? room_id, Json.Node raw_event, Matrix.Event.Base? matrix_event);
+
+ public signal void polling_started();
+
+ public signal void polling_stopped(GLib.Error? error);
+
+ public delegate void EventCallback(Matrix.Client client, string? room_id, Json.Node raw_event, Matrix.Event.Base? matrix_event);
+
+ public abstract void login_with_password(string username, string password)
+ throws Matrix.Error;
+
+ public abstract void register_with_password(string? username, string password)
+ throws Matrix.Error;
+
+ public abstract void logout()
+ throws Matrix.Error;
+
+ public abstract void begin_polling()
+ throws Matrix.Error;
+
+ public abstract void stop_polling(bool cancel_ongoing)
+ throws Matrix.Error;
+
+ public void emit_login_finished(bool success);
+
+ public void incoming_event(string? room_id, Json.Node raw_event, Matrix.Event.Base? matrix_event);
+
+ public void
+ connect_event(GLib.Type event_gtype, owned EventCallback event_callback);
+
+ public abstract Profile?
+ get_user_profile(string user_id, string? room_id = null)
+ throws Matrix.Error;
+
+ public abstract Presence
+ get_user_presence(string user_id, string? room_id = null)
+ throws Matrix.Error;
+
+ public abstract Room
+ get_room_by_id(string room_id)
+ throws Matrix.Error;
+
+ public abstract Room
+ get_room_by_alias(string room_alias)
+ throws Matrix.Error;
+
+ public delegate void
+ SendCallback(string? event_id, GLib.Error? err);
+
+ public abstract void
+ send(string room_id,
+ Matrix.Event.Base evt,
+ SendCallback? cb,
+ out ulong txn_id)
+ throws Matrix.Error;
+
+ public abstract void
+ save_state(string filename)
+ throws Matrix.Error, GLib.Error;
+
+ public abstract void
+ load_state(string filename)
+ throws Matrix.Error, GLib.Error;
+ }
+
/**
* The major version number of the Matrix.org GLib SDK.
*/