From c9fcb00489fe3546dd6c67ad142ee8396202a471 Mon Sep 17 00:00:00 2001 From: Cosimo Alfarano Date: Wed, 9 Dec 2009 16:46:46 -0200 Subject: Text interface 1-1 chat and chatrooms loggin * refactored main objects (TplTextChannel, TplChannel, TplContact, TplLogEntryText) * using a deferred task chain style procedures in TplTextChannel, to allow a easier-to-read CB's cascading (hopefully) * renamed all modules using dashes instead of underscores (tpl_foo.c -> tpl-foo.c) * using tpl-log-manager from Empathy to manage LogStores * enabled TplLogManager into TplTextChannel received/sent signals * enabled 1-1 sent/received logging * enabled chatroom logging --- src/Makefile.am | 43 ++-- src/compile.sh | 10 +- src/test.c | 2 +- src/tpl-channel.c | 115 +++++++++ src/tpl-contact.c | 72 ++++++ src/tpl-headless-logger-init.c | 37 +++ src/tpl-log-entry-text.c | 161 ++++++++++++ src/tpl-log-manager.c | 69 +---- src/tpl-log-store-empathy.c | 196 +++++++++++--- src/tpl-log-store.c | 5 +- src/tpl-observer.c | 261 +++++++++++++++++++ src/tpl-text-channel-context.c | 569 +++++++++++++++++++++++++++++++++++++++++ src/tpl-utils.c | 13 + src/tpl_channel_data.c | 116 --------- src/tpl_contact.c | 44 ---- src/tpl_headless_logger_init.c | 38 --- src/tpl_log_entry_text.c | 124 --------- src/tpl_observer.c | 269 ------------------- src/tpl_text_channel_data.c | 370 --------------------------- src/tpl_utils.c | 13 - 20 files changed, 1415 insertions(+), 1112 deletions(-) create mode 100644 src/tpl-channel.c create mode 100644 src/tpl-contact.c create mode 100644 src/tpl-headless-logger-init.c create mode 100644 src/tpl-log-entry-text.c create mode 100644 src/tpl-observer.c create mode 100644 src/tpl-text-channel-context.c create mode 100644 src/tpl-utils.c delete mode 100644 src/tpl_channel_data.c delete mode 100644 src/tpl_contact.c delete mode 100644 src/tpl_headless_logger_init.c delete mode 100644 src/tpl_log_entry_text.c delete mode 100644 src/tpl_observer.c delete mode 100644 src/tpl_text_channel_data.c delete mode 100644 src/tpl_utils.c (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 6564061..a3a5fbf 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,42 +5,33 @@ AM_CPPFLAGS = \ $(ERROR_CFLAGS) \ -I$(top_srcdir) \ -I$(top_srcdir)/include \ - -DG_LOG_DOMAIN=\"tpl\" \ + -DG_LOG_DOMAIN=\"TPLogger\" \ $(TPL_CFLAGS) \ $(LIBTPL_CFLAGS) \ $(DISABLE_DEPRECATED) \ $(WARN_CFLAGS) -LDADD = \ - $(TPL_LIBS) \ +LDADD = $(TPL_LIBS) \ $(LIBTPL_LIBS) -# $(top_builddir)/libempathy-gtk/libempathy-gtk.la \ -# $(top_builddir)/libempathy/libempathy.la \ -# $(top_builddir)/extensions/libemp-extensions.la \ -# $(LIBNOTIFY_LIBS) \ -# $(LIBCHAMPLAIN_LIBS) \ -# $(WEBKIT_LIBS) -bin_PROGRAMS = \ - telepathy-logger +bin_PROGRAMS = telepathy-logger -BUILT_SOURCES= -# empathy-tube-dispatch-enumtypes.h \ -# empathy-tube-dispatch-enumtypes.c +#BUILT_SOURCES= telepathy_logger_handwritten_source = \ - test.c \ - tpl_channel_data.c \ - tpl_contact.c \ - tpl_headless_logger_init.c \ - tpl_log_entry_text.c \ - tpl_observer.c \ - tpl_text_channel_data.c \ - tpl-time.c \ - tpl_utils.c \ - tpl-log-manager.c \ - tpl-log-store.c \ - tpl-log-store-empathy.c + test.c \ + tpl-observer.c \ + tpl-headless-logger-init.c \ + tpl-channel.c \ + tpl-text-channel-context.c \ + tpl-log-entry-text.c \ + tpl-contact.c \ + tpl-log-manager.c \ + tpl-log-store.c \ + tpl-log-store-empathy.c \ + tpl-utils.c \ + tpl-time.c + telepathy_logger_SOURCES = \ $(telepathy_logger_handwritten_source) diff --git a/src/compile.sh b/src/compile.sh index 27548cb..b20a496 100755 --- a/src/compile.sh +++ b/src/compile.sh @@ -4,15 +4,15 @@ PACKAGE_NAME="TpLogger" CC=${CC:-gcc} CCOPTS="-D__USE_POSIX -DPACKAGE_NAME=\"${PACKAGE_NAME}\" --std=c99 -g -I../include -Wall -Werror" # -pedantic" PKGS="telepathy-glib libxml-2.0" -MODULES="tpl_observer.c tpl_headless_logger_init.c - tpl_channel_data.c tpl_text_channel_data.c - tpl_contact.c - tpl_utils.c +MODULES="tpl-observer.c tpl-headless-logger-init.c + tpl-channel-data.c tpl-text-channel-data.c + tpl-contact.c + tpl-utils.c tpl-time.c tpl-log-manager.c tpl-log-store.c tpl-log-store-empathy.c - tpl_log_entry_text.c + tpl-log-entry-text.c test.c" EXECUTABLE="telepathy-logger" diff --git a/src/test.c b/src/test.c index df8c167..196c5a1 100644 --- a/src/test.c +++ b/src/test.c @@ -1,6 +1,6 @@ #include -#include +#include static GMainLoop *loop = NULL; diff --git a/src/tpl-channel.c b/src/tpl-channel.c new file mode 100644 index 0000000..4d97b55 --- /dev/null +++ b/src/tpl-channel.c @@ -0,0 +1,115 @@ +#include +#include + +G_DEFINE_TYPE (TplChannel, tpl_channel, G_TYPE_OBJECT) + +static void tpl_channel_class_init(TplChannelClass* klass) { + //GObjectClass* gobject_class = G_OBJECT_CLASS (klass); +} + + +static void tpl_channel_init(TplChannel* self) { + /* Init TplChannel's members to zero/NULL */ +#define TPL_SET_NULL(x) tpl_channel_set_##x(self, NULL) + TPL_SET_NULL(channel); + TPL_SET_NULL(channel_path); + TPL_SET_NULL(channel_type); + TPL_SET_NULL(channel_properties); + TPL_SET_NULL(account); + TPL_SET_NULL(account_path); + TPL_SET_NULL(connection); + TPL_SET_NULL(connection_path); + TPL_SET_NULL(observer); +#undef TPL_SET_NULL +} + +TplChannel* tpl_channel_new(TpSvcClientObserver* observer) { + TplChannel *ret = g_object_new(TPL_TYPE_CHANNEL,NULL); + tpl_channel_set_observer(ret, observer); + return ret; +} + +void tpl_channel_free(TplChannel* tpl_text) { + /* TODO free and unref other members */ + g_free(tpl_text); +} + + +TpSvcClientObserver* tpl_channel_get_observer(TplChannel *self) { + return self->observer; +} +TpAccount *tpl_channel_get_account(TplChannel *self) { + return self->account; +} +const gchar *tpl_channel_get_account_path(TplChannel *self) { + return self->account_path; +} +TpConnection *tpl_channel_get_connection(TplChannel *self) { + return self->connection; +} +const gchar *tpl_channel_get_connection_path(TplChannel *self) { + return self->connection_path; +} +TpChannel *tpl_channel_get_channel(TplChannel *self) { + return self->channel; +} +const gchar *tpl_channel_get_channel_path(TplChannel *self) { + return self->channel_path; +} +const gchar *tpl_channel_get_channel_type(TplChannel *self) { + return self->channel_type; +} +GHashTable *tpl_channel_get_channel_properties(TplChannel *self) { + return self->channel_properties; +} + + + +void tpl_channel_set_observer(TplChannel *self, + TpSvcClientObserver *data) { + //g_debug("SET observer\n"); + _unref_object_if_not_null(&(self->observer)); + self->observer = data; + _ref_object_if_not_null(data); +} +void tpl_channel_set_account(TplChannel *self, TpAccount *data) { + //g_debug("SET account\n"); + _unref_object_if_not_null(&(self->account)); + if (self->account!=NULL) + g_object_unref(self->account); + self->account = data; + _ref_object_if_not_null(data); +} +void tpl_channel_set_account_path(TplChannel *self, const gchar *data) { + //g_debug("SET path\n"); + if (self->account!=NULL) + self->account_path = data; +} +void tpl_channel_set_connection(TplChannel *self, TpConnection *data) { + //g_debug("SET connection\n"); + _unref_object_if_not_null(&(self->connection)); + self->connection = data; + _ref_object_if_not_null(data); +} +void tpl_channel_set_connection_path(TplChannel *self, const gchar *data) { + //g_debug("SET connectin path\n"); + self->connection_path = data; +} +void tpl_channel_set_channel(TplChannel *self, TpChannel *data) { + //g_debug("SET channel\n"); + _unref_object_if_not_null(&(self->channel)); + self->channel = data; + _ref_object_if_not_null(data); +} +void tpl_channel_set_channel_path(TplChannel *self, const gchar *data) { + //g_debug("SET channel path\n"); + self->channel_path = data; +} +void tpl_channel_set_channel_type(TplChannel *self, const gchar *data) { + //g_debug("SET channel type\n"); + self->channel_type = data; +} +void tpl_channel_set_channel_properties(TplChannel *self, GHashTable *data) { + //g_debug("SET channel prop\n"); + self->channel_properties = data; +} diff --git a/src/tpl-contact.c b/src/tpl-contact.c new file mode 100644 index 0000000..f3b00fb --- /dev/null +++ b/src/tpl-contact.c @@ -0,0 +1,72 @@ +#include +#include + +G_DEFINE_TYPE (TplContact, tpl_contact, G_TYPE_OBJECT) + +static void tpl_contact_class_init(TplContactClass* klass) { + //GObjectClass* gobject_class = G_OBJECT_CLASS (klass); +} + +static void tpl_contact_init(TplContact* self) { +} + +/* retrieved contact and set TplContact ready */ + +TplContact *tpl_contact_from_tp_contact(TpContact *contact) +{ + TplContact *ret; + const gchar *id, *alias; + const gchar *pres_msg, *pres_status; + + ret = tpl_contact_new(); + id = tp_contact_get_identifier(contact); + alias = tp_contact_get_alias(contact); + pres_status = tp_contact_get_presence_status(contact); + pres_msg = tp_contact_get_presence_message (contact); + +#define CONTACT_ENTRY_SET(x,y) tpl_contact_set_##x(ret,y) + CONTACT_ENTRY_SET(contact, contact); + CONTACT_ENTRY_SET(alias, alias); + CONTACT_ENTRY_SET(identifier, id); + CONTACT_ENTRY_SET(presence_status, pres_status); + CONTACT_ENTRY_SET(presence_message, pres_msg ); +#undef CONTACT_ENTRY_SET + + return ret; +} + +TplContact *tpl_contact_new() { + return g_object_new(TPL_TYPE_CONTACT, NULL); +} + +#define ADD_GET(x,y) y tpl_contact_get_##x(TplContact *self) { \ + return self->x; } + ADD_GET(contact, TpContact *); + ADD_GET(alias, const gchar *); + ADD_GET(identifier, const gchar *); + ADD_GET(presence_status, const gchar *); + ADD_GET(presence_message, const gchar *); + ADD_GET(contact_type, TplContactType); + ADD_GET(account, TpAccount *); +#undef ADD_GET + +#define ADD_SET_PTR(member,y) void tpl_contact_set_##member(TplContact *self, y data) { \ + _unref_object_if_not_null(&(self->member)) ; \ + self->member = data; \ + _ref_object_if_not_null(data); } + ADD_SET_PTR(contact, TpContact *); + ADD_SET_PTR(account, TpAccount *); +#undef ADD_SET_PTR +#define ADD_SET_STR(member, Type) \ + void tpl_contact_set_##member(TplContact *self, Type data) \ + { g_free( (gchar*) self->member); self->member = g_strdup (data); } + ADD_SET_STR(alias, const gchar *); + ADD_SET_STR(identifier, const gchar *); + ADD_SET_STR(presence_status, const gchar *); + ADD_SET_STR(presence_message, const gchar *); +#undef ADD_SET_STR + +void tpl_contact_set_contact_type(TplContact *self, TplContactType data) +{ + self->contact_type = data; +} diff --git a/src/tpl-headless-logger-init.c b/src/tpl-headless-logger-init.c new file mode 100644 index 0000000..82705d7 --- /dev/null +++ b/src/tpl-headless-logger-init.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include + +#include +#include + +/* + * Initialization of TPL (TelePathy Logger), it futurely set all the + * inernal structs. tpl_headless_logger_deinit will free/unref them + */ +void tpl_headless_logger_init(void) +{ + TplObserver *observer; + DBusGConnection *bus; + TpDBusDaemon *tp_bus; + GError *error = NULL; + + bus = tp_get_bus(); + tp_bus = tp_dbus_daemon_new(bus); + + if ( tp_dbus_daemon_request_name (tp_bus, TPL_OBSERVER_WELL_KNOWN_BUS_NAME, + TRUE, &error) ) { + g_print("Well Known name requested successfully!\n"); + } else { + g_print("Well Known name request error: %s\n", error->message); + g_clear_error(&error); + g_error_free(error); + } + + + observer = tpl_observer_new (); + dbus_g_connection_register_g_object (bus, + TPL_OBSERVER_OBJECT_PATH, + G_OBJECT(observer)); +} diff --git a/src/tpl-log-entry-text.c b/src/tpl-log-entry-text.c new file mode 100644 index 0000000..932befa --- /dev/null +++ b/src/tpl-log-entry-text.c @@ -0,0 +1,161 @@ +#include +#include +#include +#include + +G_DEFINE_TYPE (TplLogEntryText, tpl_log_entry_text, G_TYPE_OBJECT) + +static void tpl_log_entry_text_class_init(TplLogEntryTextClass* klass) +{ + //GObjectClass* gobject_class = G_OBJECT_CLASS (klass); +} + +static void tpl_log_entry_text_init(TplLogEntryText* self) +{ +#define TPL_SET_NULL(x) tpl_log_entry_text_set_##x(self, NULL) + TPL_SET_NULL(tpl_text_channel); +#undef TPL_SET_NULL +} + +TplLogEntryText *tpl_log_entry_text_new(void) +{ + TplLogEntryText *ret = g_object_new(TPL_TYPE_LOG_ENTRY_TEXT, NULL); + return ret; +} + + + +TpChannelTextMessageType +tpl_log_entry_text_message_type_from_str (const gchar *type_str) +{ + if (g_strcmp0 (type_str, "normal") == 0) { + return TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL; + } + else if (g_strcmp0 (type_str, "action") == 0) { + return TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION; + } + else if (g_strcmp0 (type_str, "notice") == 0) { + return TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE; + } + else if (g_strcmp0 (type_str, "auto-reply") == 0) { + return TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY; + } + + return TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL; +} + + +const gchar *tpl_log_entry_text_message_type_to_str (TpChannelTextMessageType msg_type) +{ + switch (msg_type) + { + case TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION: + return "action"; + case TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE: + return "notice"; + case TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY: + return "auto-reply"; + default: + return "normal"; + } +} + + +TplChannel * +tpl_log_entry_text_get_tpl_channel (TplLogEntryText *self) +{ + return tpl_text_channel_get_tpl_channel ( + tpl_log_entry_text_get_tpl_text_channel (self)); +} + +TplTextChannel * +tpl_log_entry_text_get_tpl_text_channel(TplLogEntryText *self) +{ + return self->tpl_text; +} + +TplContact *tpl_log_entry_text_get_sender (TplLogEntryText *self) +{ + return self->sender; +} +TplContact *tpl_log_entry_text_get_receiver (TplLogEntryText *self) +{ + return self->receiver; +} +const gchar *tpl_log_entry_text_get_message (TplLogEntryText *self) +{ + return self->message; +} +TpChannelTextMessageType +tpl_log_entry_text_get_message_type (TplLogEntryText *self) +{ + return self->message_type; +} +TplLogEntryTextSignalType +tpl_log_entry_text_get_signal_type (TplLogEntryText *self) +{ + return self->signal_type; +} +TplLogEntryTextDirection tpl_log_entry_text_get_direction (TplLogEntryText *self) +{ + return self->direction; +} +time_t tpl_log_entry_text_get_timestamp (TplLogEntryText *self) +{ + return self->timestamp; +} +guint tpl_log_entry_text_get_message_id (TplLogEntryText *self) +{ + return self->message_id; +} +const gchar *tpl_log_entry_text_get_chat_id (TplLogEntryText *self) +{ + return self->chat_id; +} + + +void tpl_log_entry_text_set_tpl_text_channel(TplLogEntryText *self, TplTextChannel *data) +{ + _unref_object_if_not_null(self->tpl_text); + self->tpl_text = data; + _ref_object_if_not_null(data); +} + +void tpl_log_entry_text_set_sender (TplLogEntryText *self, TplContact *data) +{ + self->sender = data; +} +void tpl_log_entry_text_set_receiver (TplLogEntryText *self, TplContact *data) +{ + self->receiver = data; +} +void tpl_log_entry_text_set_message (TplLogEntryText *self, const gchar *data) +{ + self->message = g_strdup (data); +} +void tpl_log_entry_text_set_message_type (TplLogEntryText *self, TpChannelTextMessageType data) +{ + self->message_type = data; +} +void tpl_log_entry_text_set_signal_type (TplLogEntryText *self, TplLogEntryTextSignalType data) +{ + self->signal_type = data; +} +void tpl_log_entry_text_set_direction (TplLogEntryText *self, TplLogEntryTextDirection data) +{ + self->direction = data; +} + +void tpl_log_entry_text_set_timestamp (TplLogEntryText *self, time_t data) +{ + self->timestamp = data; +} + +void tpl_log_entry_text_set_message_id (TplLogEntryText *self, guint data) +{ + self->message_id = data; +} +void tpl_log_entry_text_set_chat_id (TplLogEntryText *self, const gchar *data) +{ + self->chat_id = g_strdup (data); +} diff --git a/src/tpl-log-manager.c b/src/tpl-log-manager.c index 642733a..d4f946f 100644 --- a/src/tpl-log-manager.c +++ b/src/tpl-log-manager.c @@ -19,10 +19,9 @@ * Boston, MA 02110-1301 USA * * Authors: Xavier Claessens + * Cosimo Alfarano */ -//#include - #include #include #include @@ -34,9 +33,8 @@ #include #include #include -#include +#include #include -//#include //#define DEBUG_FLAG EMPATHY_DEBUG_OTHER //#include @@ -64,6 +62,10 @@ log_manager_finalize (GObject *object) g_list_free (priv->stores); } +/* + * - Singleton LogManager constructor - + * Initialises LogStores with LogStoreEmpathy instance + */ static GObject * log_manager_constructor (GType type, guint n_props, @@ -401,62 +403,3 @@ tpl_log_manager_get_date_readable (const gchar *date) return tpl_time_to_string_local (t, "%a %d %b %Y"); } - -/* TPL: useless TODO remove -static void -log_manager_chat_received_message_cb (EmpathyTpChat *tp_chat, - TplLogEntryText *message, - TplLogManager *log_manager) -{ - GError *error = NULL; - TpHandleType handle_type; - TpChannel *channel; - - channel = empathy_tp_chat_get_channel (tp_chat); - tp_channel_get_handle (channel, &handle_type); - - if (!tpl_log_manager_add_message (log_manager, - tp_channel_get_identifier (channel), - handle_type == TP_HANDLE_TYPE_ROOM, - message, &error)) - { - DEBUG ("Failed to write message: %s", - error ? error->message : "No error message"); - - if (error != NULL) - g_error_free (error); - } -} -*/ - -/* TPL: useless TODO remove -static void -log_manager_dispatcher_observe_cb (EmpathyDispatcher *dispatcher, - EmpathyDispatchOperation *operation, - TplLogManager *log_manager) -{ - GQuark channel_type; - - channel_type = empathy_dispatch_operation_get_channel_type_id (operation); - - if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_TEXT) - { - EmpathyTpChat *tp_chat; - - tp_chat = EMPATHY_TP_CHAT ( - empathy_dispatch_operation_get_channel_wrapper (operation)); - - g_signal_connect (tp_chat, "message-received", - G_CALLBACK (log_manager_chat_received_message_cb), log_manager); - } -} -*/ -/* -void -tpl_log_manager_observe (TplLogManager *log_manager, - EmpathyDispatcher *dispatcher) -{ - g_signal_connect (dispatcher, "observe", - G_CALLBACK (log_manager_dispatcher_observe_cb), log_manager); -} -*/ diff --git a/src/tpl-log-store-empathy.c b/src/tpl-log-store-empathy.c index 4fde4ff..9d739c9 100644 --- a/src/tpl-log-store-empathy.c +++ b/src/tpl-log-store-empathy.c @@ -44,8 +44,8 @@ #include #include -#include -#include +#include +#include //#define DEBUG_FLAG EMPATHY_DEBUG_OTHER //#include @@ -205,32 +205,131 @@ log_store_empathy_get_filename (TplLogStore *self, return filename; } +static gboolean _log_store_empathy_write_to_store ( TplLogStore *self, + TpAccount *account, + const gchar *chat_id, + gboolean chatroom, + const gchar *entry, + GError **error) +{ + FILE *file; + gchar *filename; + gchar *basedir; + + filename = log_store_empathy_get_filename (self, account, chat_id, chatroom); + basedir = g_path_get_dirname (filename); + if (!g_file_test (basedir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) + { + DEBUG ("Creating directory:'%s'", basedir); + g_mkdir_with_parents (basedir, LOG_DIR_CREATE_MODE); + } + g_free (basedir); + + DEBUG ("Adding log to file: '%s'", filename); + + if (!g_file_test (filename, G_FILE_TEST_EXISTS)) + { + file = g_fopen (filename, "w+"); + if (file != NULL) + g_fprintf (file, LOG_HEADER); + + g_chmod (filename, LOG_FILE_CREATE_MODE); + } + else + { + file = g_fopen (filename, "r+"); + if (file != NULL) + fseek (file, - strlen (LOG_FOOTER), SEEK_END); + } + + g_fprintf(file, entry); + + fclose (file); + g_free (filename); + return TRUE; +} + +static gboolean _log_store_empathy_add_message_status_changed ( + TplLogStore *self, + const gchar *chat_id, + gboolean chatroom, + TplLogEntryText *message, + GError **error) + +{ + TpAccount *account; + TplContact *sender; + const gchar *str; + gchar *timestamp; + gchar *contact_name; + gchar *contact_id; + gchar *contact_status; + gchar *contact_presence; + gchar *entry; + gboolean ret = FALSE; + + sender = tpl_log_entry_text_get_sender (message); + account = tpl_channel_get_account ( + tpl_log_entry_text_get_tpl_channel (message) ); + + timestamp = log_store_empathy_get_timestamp_from_message (message); + + str = tpl_contact_get_alias (sender); + contact_name = g_markup_escape_text (str, -1); + + str = tpl_contact_get_identifier (sender); + contact_id = g_markup_escape_text (str, -1); + + str = tpl_contact_get_presence_status (sender); + contact_presence = g_markup_escape_text (str, -1); + + str = tpl_contact_get_presence_message (sender); + contact_status = g_markup_escape_text (str, -1); + + entry = g_strdup_printf( + "\n" LOG_FOOTER, + timestamp, contact_id, contact_name, + tpl_contact_get_contact_type (sender) == + TPL_CONTACT_USER ? "true" : "false", + contact_presence, contact_status); + + + ret = _log_store_empathy_write_to_store(self, + account, chat_id, chatroom, entry, error); + + g_free (contact_id); + g_free (contact_name); + g_free (contact_presence); + g_free (contact_status); + g_free (timestamp); + g_free(entry); + + return ret; +} + + static gboolean -log_store_empathy_add_message (TplLogStore *self, +_log_store_empathy_add_message_chat (TplLogStore *self, const gchar *chat_id, gboolean chatroom, TplLogEntryText *message, GError **error) { - FILE *file; + gboolean ret; TpAccount *account; TplContact *sender; const gchar *body_str; const gchar *str; //EmpathyAvatar *avatar; //gchar *avatar_token = NULL; - gchar *filename; - gchar *basedir; gchar *body; gchar *timestamp; gchar *contact_name; gchar *contact_id; + gchar *entry; TpChannelTextMessageType msg_type; - g_return_val_if_fail (TPL_IS_LOG_STORE (self), FALSE); - g_return_val_if_fail (chat_id != NULL, FALSE); - g_return_val_if_fail (TPL_IS_LOG_ENTRY_TEXT (message), FALSE); - sender = tpl_log_entry_text_get_sender (message); account = tpl_channel_get_account ( tpl_log_entry_text_get_tpl_channel (message) ); @@ -240,32 +339,6 @@ log_store_empathy_add_message (TplLogStore *self, if (TPL_STR_EMPTY (body_str)) return FALSE; - filename = log_store_empathy_get_filename (self, account, chat_id, chatroom); - basedir = g_path_get_dirname (filename); - if (!g_file_test (basedir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) - { - DEBUG ("Creating directory:'%s'", basedir); - g_mkdir_with_parents (basedir, LOG_DIR_CREATE_MODE); - } - g_free (basedir); - - DEBUG ("Adding message: '%s' to file: '%s'", body_str, filename); - - if (!g_file_test (filename, G_FILE_TEST_EXISTS)) - { - file = g_fopen (filename, "w+"); - if (file != NULL) - g_fprintf (file, LOG_HEADER); - - g_chmod (filename, LOG_FILE_CREATE_MODE); - } - else - { - file = g_fopen (filename, "r+"); - if (file != NULL) - fseek (file, - strlen (LOG_FOOTER), SEEK_END); - } - body = g_markup_escape_text (body_str, -1); timestamp = log_store_empathy_get_timestamp_from_message (message); @@ -279,10 +352,11 @@ log_store_empathy_add_message (TplLogStore *self, if (avatar != NULL) avatar_token = g_markup_escape_text (avatar->token, -1); */ - g_fprintf (file, - "" + entry = g_strdup_printf ( + "" "%s\n" LOG_FOOTER, timestamp, - tpl_log_entry_text_get_id (message), + tpl_log_entry_text_get_message_id (message), contact_id, contact_name, //avatar_token ? avatar_token : "", // instead force to "" as //follow @@ -290,17 +364,55 @@ log_store_empathy_add_message (TplLogStore *self, tpl_contact_get_contact_type (sender) == TPL_CONTACT_USER ? "true" : "false", tpl_log_entry_text_message_type_to_str (msg_type), body); - fclose (file); - g_free (filename); + ret = _log_store_empathy_write_to_store(self, + account, chat_id, chatroom, entry, error); + g_free (contact_id); g_free (contact_name); g_free (timestamp); g_free (body); + g_free (entry); //g_free (avatar_token); + return TRUE; } + +static gboolean +log_store_empathy_add_message (TplLogStore *self, + const gchar *chat_id, + gboolean chatroom, + TplLogEntryText *message, + GError **error) +{ + TplLogEntryTextSignalType signal_type; + + g_return_val_if_fail (TPL_IS_LOG_STORE (self), FALSE); + g_return_val_if_fail (chat_id != NULL, FALSE); + g_return_val_if_fail (TPL_IS_LOG_ENTRY_TEXT (message), FALSE); + + + signal_type = tpl_log_entry_text_get_signal_type (message); + + switch (signal_type) { + case TPL_LOG_ENTRY_TEXT_SIGNAL_SENT: + case TPL_LOG_ENTRY_TEXT_SIGNAL_RECEIVED: + return _log_store_empathy_add_message_chat(self, + chat_id, chatroom, message, error); + break; + case TPL_LOG_ENTRY_TEXT_SIGNAL_CHAT_STATUS_CHANGED: + return _log_store_empathy_add_message_status_changed(self, + chat_id, chatroom, message, error); + break; + case TPL_LOG_ENTRY_TEXT_SIGNAL_SEND_ERROR: + case TPL_LOG_ENTRY_TEXT_SIGNAL_LOST_MESSAGE: + default: + g_warning("received an not handled signal type/signal type unknown"); + return FALSE; + } +} + static gboolean log_store_empathy_exists (TplLogStore *self, TpAccount *account, @@ -556,7 +668,7 @@ log_store_empathy_get_messages_for_file (TplLogStore *self, //tpl_log_entry_text_set_is_backlog (message, TRUE); if (cm_id_str) - tpl_log_entry_text_set_id (message, cm_id); + tpl_log_entry_text_set_message_id (message, cm_id); messages = g_list_append (messages, message); diff --git a/src/tpl-log-store.c b/src/tpl-log-store.c index d9d62cc..228db0e 100644 --- a/src/tpl-log-store.c +++ b/src/tpl-log-store.c @@ -76,7 +76,10 @@ tpl_log_store_add_message (TplLogStore *self, GError **error) { if (!TPL_LOG_STORE_GET_INTERFACE (self)->add_message) - return FALSE; + { + g_warning("LogStore: add_message not implemented"); + return FALSE; + } return TPL_LOG_STORE_GET_INTERFACE (self)->add_message ( self, chat_id, chatroom, message, error); diff --git a/src/tpl-observer.c b/src/tpl-observer.c new file mode 100644 index 0000000..480e680 --- /dev/null +++ b/src/tpl-observer.c @@ -0,0 +1,261 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static void observer_iface_init (gpointer, gpointer); + +G_DEFINE_TYPE_WITH_CODE (TplObserver, tpl_observer, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, + tp_dbus_properties_mixin_iface_init); + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CLIENT, + NULL); + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CLIENT_OBSERVER, + observer_iface_init); +); + +static const char *client_interfaces[] = { + TP_IFACE_CLIENT_OBSERVER, + NULL +}; + +enum +{ + PROP_0, + PROP_INTERFACES, + PROP_CHANNEL_FILTER +}; + +static void _observe_channel_when_ready_cb(TpChannel *channel, + const GError *error, + gpointer user_data) +{ + TplChannel *tpl_chan = TPL_CHANNEL(user_data); + gpointer tpl_channel_instance; + // TODO add a GHashTable mapping + // channelpath:tpl_channel_instance to record observed channels + // and a way to access (get/set) them + + if(error!=NULL) { + g_error("channel error: %s", error->message); + g_error("giving up observing channel '%s'", + tpl_chan->channel_path); + // TODO free tpl_chan + //tpl_channel_data_free(tpl_chan); + return; + } + + tpl_channel_set_channel_type(tpl_chan, + tp_channel_get_channel_type(tpl_chan->channel) ); + + /* Instantiate and delegate channel handling to the right object */ + if(0==g_strcmp0(TP_IFACE_CHAN_TEXT, tpl_chan->channel_type)) { + tpl_channel_instance = tpl_text_channel_new(tpl_chan); + // TODO add to hash + } else { + g_warning("%s: channel not handled by TPL", tpl_chan->channel_type); + } +} + + +static void _tp_connection_called_when_ready_cb(TpConnection *connection, + const GError *error, + gpointer user_data) +{ + TplChannel *tpl_chan = TPL_CHANNEL(user_data); + + tp_channel_call_when_ready (tpl_channel_get_channel(tpl_chan), + _observe_channel_when_ready_cb, tpl_chan); +} + + +static void +tpl_observer_observe_channels (TpSvcClientObserver *self, + const char *account, + const char *connection, + const GPtrArray *channels, + const char *dispatch_op, + const GPtrArray *requests_satisfied, + GHashTable *observer_info, + DBusGMethodInvocation *context) +{ + TpAccount *tp_acc; + TpConnection *tp_conn; + TpDBusDaemon *tp_bus_daemon; + GError *error = NULL; + + g_debug (" > tpl_observer_observe_channels\n"); + g_debug (" account = %s\n", account); + g_debug (" connection = %s\n", connection); + g_debug (" dispatchop = %s\n", dispatch_op); + + tp_bus_daemon = tp_dbus_daemon_dup(&error); + if(tp_bus_daemon == NULL) { + g_error("%s\n", error->message); + g_clear_error(&error); + g_error_free(error); + } + + tp_acc = tp_account_new(tp_bus_daemon, account, &error); + if(tp_acc == NULL) { + g_error("%s\n", error->message); + g_clear_error(&error); + g_error_free(error); + error=NULL; + } + + + tp_conn = tp_connection_new (tp_bus_daemon, NULL, connection, &error); + if(tp_conn == NULL) { + g_error("%s\n", error->message); + g_clear_error(&error); + g_error_free(error); + error=NULL; + } + + /* channels is of type a(oa{sv}) */ + for (guint i = 0; i < channels->len; i++) + { + GValueArray *channel = g_ptr_array_index (channels, i); + TpChannel *tp_chan = NULL; + TplChannel* tpl_chan = tpl_channel_new(self); + + char *path = g_value_get_boxed (g_value_array_get_nth (channel, 0)); + // propertyNameStr/value hash + GHashTable *map = g_value_get_boxed (g_value_array_get_nth (channel, 1)); + + g_debug (" channel = %s\n", path); + tp_chan = tp_channel_new (tp_conn, path, NULL, TP_UNKNOWN_HANDLE_TYPE, 0, + &error); + + tpl_channel_set_account(tpl_chan, tp_acc); + tpl_channel_set_account_path(tpl_chan, account); + tpl_channel_set_connection(tpl_chan, tp_conn); + tpl_channel_set_connection_path(tpl_chan, connection); + tpl_channel_set_channel(tpl_chan, tp_chan); + tpl_channel_set_channel_path(tpl_chan, path); + tpl_channel_set_channel_properties(tpl_chan, map); + + tp_connection_call_when_ready(tp_conn, + _tp_connection_called_when_ready_cb, tpl_chan); + } + + + + tp_svc_client_observer_return_from_observe_channels (context); +} + +static void +tpl_observer_get_property (GObject *self, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + g_print(" :: get_property\n"); + switch (property_id) + { + GPtrArray *array; + GHashTable *map; + case PROP_INTERFACES: + g_print (" :: interfaces\n"); + g_value_set_boxed (value, client_interfaces); + break; + + case PROP_CHANNEL_FILTER: + g_print (" :: channel-filter\n"); + + /* create an empty filter - which means all channels */ + array = g_ptr_array_new (); + map = g_hash_table_new (NULL, NULL); + + g_ptr_array_add (array, map); + g_value_set_boxed (value, array); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (self, property_id, pspec); + break; + } +} + +static void +tpl_observer_class_init (TplObserverClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + /* D-Bus properties are exposed as GObject properties through the + * TpDBusPropertiesMixin */ + /* properties on the Client interface */ + static TpDBusPropertiesMixinPropImpl client_props[] = { + { "Interfaces", "interfaces", NULL }, + { NULL } + }; + + /* properties on the Client.Observer interface */ + static TpDBusPropertiesMixinPropImpl client_observer_props[] = { + { "ObserverChannelFilter", "channel-filter", NULL }, + { NULL } + }; + + /* complete list of interfaces with properties */ + static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { + { TP_IFACE_CLIENT, + tp_dbus_properties_mixin_getter_gobject_properties, + NULL, + client_props + }, + { TP_IFACE_CLIENT_OBSERVER, + tp_dbus_properties_mixin_getter_gobject_properties, + NULL, + client_observer_props + }, + { NULL } + }; + object_class->get_property = tpl_observer_get_property; + + g_object_class_install_property (object_class, PROP_INTERFACES, + g_param_spec_boxed ("interfaces", + "Interfaces", + "Available D-Bus Interfaces", + G_TYPE_STRV, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_CHANNEL_FILTER, + g_param_spec_boxed ("channel-filter", + "Channel Filter", + "Filter for channels we observe", + TP_ARRAY_TYPE_CHANNEL_CLASS_LIST, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /* call our mixin class init */ + klass->dbus_props_class.interfaces = prop_interfaces; + tp_dbus_properties_mixin_class_init (object_class, + G_STRUCT_OFFSET (TplObserverClass, dbus_props_class)); +} + +static void +tpl_observer_init (TplObserver *self) +{ +} + +static void +observer_iface_init (gpointer g_iface, gpointer iface_data) +{ + TpSvcClientObserverClass *klass = (TpSvcClientObserverClass *) g_iface; + +#define IMPLEMENT(x) tp_svc_client_observer_implement_##x (klass, \ + tpl_observer_##x) + IMPLEMENT (observe_channels); +#undef IMPLEMENT +} + +TplObserver *tpl_observer_new (void) +{ + return g_object_new (TYPE_TPL_OBSERVER, NULL); +} diff --git a/src/tpl-text-channel-context.c b/src/tpl-text-channel-context.c new file mode 100644 index 0000000..125f520 --- /dev/null +++ b/src/tpl-text-channel-context.c @@ -0,0 +1,569 @@ +/* + * This object acts as a Text Channel context, handling a automaton to + * set up all the needed information before connect to Text iface + * signals. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#define TP_CONTACT_FEATURES_LEN 2 +#define TP_CONTACT_MYSELF 0 +#define TP_CONTACT_REMOTE 1 + +typedef void (*TplPendingProc) (TplTextChannel *self); + +static TpContactFeature features[TP_CONTACT_FEATURES_LEN] = { + TP_CONTACT_FEATURE_ALIAS, + TP_CONTACT_FEATURE_PRESENCE +}; + + + +/* Signal's Callbacks */ + +static void +_channel_on_lost_message_cb (TpChannel *proxy, + gpointer user_data, + GObject *weak_object) +{ + g_debug("LOST MESSAGE"); + // log that the system lost a message +} + +static void +_channel_on_send_error_cb (TpChannel *proxy, + guint arg_Error, + guint arg_Timestamp, + guint arg_Type, + const gchar *arg_Text, + gpointer user_data, + GObject *weak_object) +{ + g_error("unable to send the message: %s", arg_Text); + // log that the system was unable to send the message +} + + +static void +_channel_on_sent_signal_cb (TpChannel *proxy, + guint arg_Timestamp, + guint arg_Type, + const gchar *arg_Text, + gpointer user_data, + GObject *weak_object) +{ + GError *error=NULL; + TplTextChannel *tpl_text = TPL_TEXT_CHANNEL(user_data); + TpContact *remote,*me; + TplContact *tpl_contact_sender; + TplContact *tpl_contact_receiver; + TplLogEntryText *log; + TplLogManager *logmanager; + const gchar *chat_id; + + /* Initialize data for TplContact */ + me = tpl_text_channel_get_my_contact(tpl_text); + remote = tpl_text_channel_get_remote_contact(tpl_text); + + tpl_contact_sender = tpl_contact_from_tp_contact(me); + tpl_contact_set_contact_type(tpl_contact_sender, + TPL_CONTACT_USER); + tpl_contact_receiver = tpl_contact_from_tp_contact(remote); + tpl_contact_set_contact_type(tpl_contact_receiver, + TPL_CONTACT_USER); + + g_message("%s (%s): %s\n", + tpl_contact_get_identifier(tpl_contact_sender), + tpl_contact_get_alias(tpl_contact_sender), + arg_Text); + + /* Initialize TplLogEntryText */ + log = tpl_log_entry_text_new(); + tpl_log_entry_text_set_tpl_text_channel(log, tpl_text); + tpl_log_entry_text_set_sender(log, tpl_contact_sender); + tpl_log_entry_text_set_receiver(log, tpl_contact_receiver); + tpl_log_entry_text_set_message(log, arg_Text); + tpl_log_entry_text_set_message_type(log, arg_Type); + tpl_log_entry_text_set_signal_type(log, + TPL_LOG_ENTRY_TEXT_SIGNAL_SENT); + tpl_log_entry_text_set_timestamp(log, (time_t) arg_Timestamp); + tpl_log_entry_text_set_message_id(log, 123); + + /* Initialized LogStore and send the message */ + + // TODO use the log-manager + if (!tpl_text_channel_is_chatroom(tpl_text)) + chat_id = g_strdup (tpl_contact_get_identifier( + tpl_contact_receiver)); + else + chat_id = g_strdup (tpl_text_channel_get_chatroom_id( + tpl_text)); + + g_message("CHATID(%d):%s\n", + tpl_text_channel_is_chatroom(tpl_text), chat_id); + + logmanager = tpl_log_manager_dup_singleton(); + tpl_log_manager_add_message(logmanager, + chat_id, + tpl_text_channel_is_chatroom(tpl_text), + log, &error); + if(error!=NULL) + { + g_error("LogStore: %s", error->message); + g_clear_error(&error); + g_error_free(error); + } + +} + + + +static void +_channel_on_received_signal_with_contact_cb(TpConnection *connection, + guint n_contacts, + TpContact * const *contacts, + guint n_failed, + const TpHandle *failed, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + TplLogEntryText *log = TPL_LOG_ENTRY_TEXT(user_data); + GError *e = NULL; + TplLogManager *logmanager; + TplTextChannel *tpl_text; + TpContact *remote; + TplContact *tpl_contact_sender; + const gchar *chat_id; + + if(error!=NULL) + { + g_error("LogStore: %s", error->message); + // TODO cleanup + return; + } + + tpl_text = tpl_log_entry_text_get_tpl_text_channel(log); + remote = tpl_text_channel_get_remote_contact(tpl_text); + tpl_contact_sender = tpl_contact_from_tp_contact(remote); + + tpl_contact_set_contact_type(tpl_contact_sender, + TPL_CONTACT_USER); + tpl_log_entry_text_set_sender(log, tpl_contact_sender); + + g_message("%s (%s): %s\n", + tpl_contact_get_identifier(tpl_contact_sender), + tpl_contact_get_alias(tpl_contact_sender), + tpl_log_entry_text_get_message(log)); + + /* Initialize LogStore and store the message */ + // TODO use the log-manager + + if (!tpl_text_channel_is_chatroom(tpl_text)) + chat_id = g_strdup (tpl_contact_get_identifier( + tpl_contact_sender)); + else + chat_id = g_strdup (tpl_text_channel_get_chatroom_id( + tpl_text)); + + g_message("RECV: CHATID(%d):%s = %s\n", + tpl_text_channel_is_chatroom(tpl_text), chat_id, + tpl_contact_get_identifier(tpl_contact_sender)); + + logmanager = tpl_log_manager_dup_singleton(); + tpl_log_manager_add_message(logmanager, + chat_id, + tpl_text_channel_is_chatroom (tpl_text), + log, &e); + if(e!=NULL) + { + g_error("LogStore: %s", e->message); + g_clear_error(&e); + g_error_free(e); + } +} + +static void +_channel_on_received_signal_cb (TpChannel *proxy, + guint arg_ID, + guint arg_Timestamp, + guint arg_Sender, + guint arg_Type, + guint arg_Flags, + const gchar *arg_Text, + gpointer user_data, + GObject *weak_object) +{ + TplTextChannel *tpl_text = TPL_TEXT_CHANNEL(user_data); + TplChannel *tpl_chan = + tpl_text_channel_get_tpl_channel(tpl_text); + TpContact *me; + TplContact *tpl_contact_receiver; + TplLogEntryText *log; + + /* Initialize TplLogEntryText (part 1) */ + log = tpl_log_entry_text_new(); + tpl_log_entry_text_set_tpl_text_channel(log, tpl_text); + tpl_log_entry_text_set_message(log, arg_Text); + tpl_log_entry_text_set_message_type(log, arg_Type); + tpl_log_entry_text_set_signal_type(log, + TPL_LOG_ENTRY_TEXT_SIGNAL_RECEIVED); + tpl_log_entry_text_set_timestamp(log, (time_t) arg_Timestamp); + tpl_log_entry_text_set_message_id(log, 123); //TODO set a real Id + + me = tpl_text_channel_get_my_contact(tpl_text); + tpl_contact_receiver = tpl_contact_from_tp_contact(me); + tpl_contact_set_contact_type(tpl_contact_receiver, + TPL_CONTACT_USER); + tpl_log_entry_text_set_receiver(log, tpl_contact_receiver); + + tp_connection_get_contacts_by_handle( + tpl_channel_get_connection(tpl_chan), + 1, &arg_Sender, + TP_CONTACT_FEATURES_LEN, features, + _channel_on_received_signal_with_contact_cb, + log, NULL, NULL); +} + +/* End of Signal's Callbacks */ + + +/* Context related operations */ + +static void +context_continue(TplTextChannel *ctx) +{ + if (g_queue_is_empty(ctx->chain)) { + // TODO do some sanity checks + } else { + TplPendingProc next = g_queue_pop_head(ctx->chain); + next(ctx); + } +} + +/* Context TplPendingProc and related CB */ + +/* Connect signals to TplTextChannel instance */ +static void +_tpl_text_channel_pendingproc_connect_signals(TplTextChannel* self) +{ + GError *error=NULL; + TpChannel *channel = NULL; + + channel = tpl_channel_get_channel( + tpl_text_channel_get_tpl_channel (self) ); + + //TODO handle data destruction + tp_cli_channel_type_text_connect_to_received(self->tpl_channel->channel, + _channel_on_received_signal_cb, self, NULL, NULL, &error); + if (error!=NULL) { + g_error("received signal connect: %s\n", error->message); + g_clear_error(&error); + g_error_free(error); + } + + //TODO handle data destruction + tp_cli_channel_type_text_connect_to_sent(self->tpl_channel->channel, + _channel_on_sent_signal_cb, self, NULL, NULL, &error); + if (error!=NULL) { + g_error("sent signal connect: %s\n", error->message); + g_clear_error(&error); + g_error_free(error); + } + + //TODO handle data destruction + tp_cli_channel_type_text_connect_to_send_error( + self->tpl_channel->channel, + _channel_on_send_error_cb, self, NULL, NULL, &error); + if (error!=NULL) { + g_error("send error signal connect: %s\n", error->message); + g_clear_error(&error); + g_error_free(error); + } + + //TODO handle data destruction + tp_cli_channel_type_text_connect_to_lost_message( + self->tpl_channel->channel, + _channel_on_lost_message_cb, self, NULL, NULL, &error); + if (error!=NULL) { + g_error("lost message signal connect: %s\n", error->message); + g_clear_error(&error); + g_error_free(error); + } + + // TODO connect to TpContacts' notify::presence-type + + context_continue(self); + + g_debug("CONNECT!\n"); +} + +static void +_tpl_text_channel_get_chatroom_cb (TpConnection *proxy, + const gchar **out_Identifiers, + const GError *error, + gpointer user_data, GObject *weak_object) +{ + TplTextChannel *tpl_text = TPL_TEXT_CHANNEL(user_data); + + if(error!=NULL) { + g_error("retrieving chatroom identifier: %s\n", + error->message); + } + + g_debug("SETTING CHATROOM ID: %s\n", *out_Identifiers); + tpl_text_channel_set_chatroom_id(tpl_text, *out_Identifiers); + + context_continue(tpl_text); +} + +static void +_tpl_text_channel_pendingproc_get_chatroom_id(TplTextChannel *ctx) +{ + TplChannel *tpl_chan = tpl_text_channel_get_tpl_channel(ctx); + TpConnection *connection = tpl_channel_get_connection(tpl_chan); + TpHandle room_handle; + GArray *handles; + + handles = g_array_new(FALSE, FALSE, sizeof(TpHandle)); + room_handle = tp_channel_get_handle( + tpl_channel_get_channel (tpl_chan), + NULL); + g_array_append_val(handles, room_handle); + + + g_debug("HANDLE ROOM: %d\n", + g_array_index(handles, TpHandle, 0)); + + tpl_text_channel_set_chatroom(ctx, TRUE); + //TODO unref tpl_text + tp_cli_connection_call_inspect_handles(connection, + -1, TP_HANDLE_TYPE_ROOM, handles, + _tpl_text_channel_get_chatroom_cb, + ctx, NULL, NULL); +} + + +/* retrieve contacts (me and remote buddy/chatroom) and set TplTextChannel + * members */ + + +// used by _get_my_contact and _get_remote_contact +static void +_tpl_text_channel_get_contact_cb(TpConnection *connection, + guint n_contacts, + TpContact * const *contacts, + guint n_failed, + const TpHandle *failed, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + TplTextChannel *tpl_text = TPL_TEXT_CHANNEL(user_data); + + g_assert_cmpuint(n_failed, ==, 0); + g_assert_cmpuint(n_contacts, ==, 1); + g_assert_cmpuint(tpl_text->selector, <=, TP_CONTACT_REMOTE); + + if (n_failed > 0) { + g_error("error resolving self handle for connection %s\n", + tpl_channel_get_connection_path( + tpl_text_channel_get_tpl_channel(tpl_text)) + ); + context_continue(tpl_text); + return; + } + + switch(tpl_text->selector) + { + case TP_CONTACT_MYSELF: + tpl_text_channel_set_my_contact(tpl_text, *contacts); + break; + case TP_CONTACT_REMOTE: + tpl_text_channel_set_remote_contact(tpl_text, + *contacts); + break; + default: + g_error("retrieving TpContacts: passing invalid value for selector: %d", tpl_text->selector); + context_continue(tpl_text); + return; + } + + context_continue(tpl_text); +} + + +static void +_tpl_text_channel_pendingproc_get_remote_contact(TplTextChannel *ctx) +{ + TpHandleType remote_handle_type; + TpHandle remote_handle; + TplChannel *tpl_chan = tpl_text_channel_get_tpl_channel(ctx); + + remote_handle = tp_channel_get_handle( + tpl_channel_get_channel (tpl_chan), + &remote_handle_type); + + ctx->selector = TP_CONTACT_REMOTE; + tp_connection_get_contacts_by_handle( + tpl_channel_get_connection(tpl_chan), + 1, &remote_handle, + TP_CONTACT_FEATURES_LEN, features, + _tpl_text_channel_get_contact_cb, + ctx, NULL, NULL); +} + +static void +_tpl_text_channel_pendingproc_get_my_contact(TplTextChannel *ctx) +{ + TplChannel *tpl_chan = tpl_text_channel_get_tpl_channel(ctx); + TpHandle my_handle = tp_connection_get_self_handle( + tpl_channel_get_connection(tpl_chan)); + + ctx->selector = TP_CONTACT_MYSELF; + tp_connection_get_contacts_by_handle( + tpl_channel_get_connection(tpl_chan), + 1, &my_handle, + TP_CONTACT_FEATURES_LEN, features, + _tpl_text_channel_get_contact_cb, + ctx, NULL, NULL); +} +/* end of async Callbacks */ + + +G_DEFINE_TYPE (TplTextChannel, tpl_text_channel, G_TYPE_OBJECT) + + +static void tpl_text_channel_class_init(TplTextChannelClass* klass) { + //GObjectClass* gobject_class = G_OBJECT_CLASS (klass); +} + + +static void tpl_text_channel_init(TplTextChannel* self) { + /* Init TplTextChannel's members to zero/NULL */ +#define TPL_SET_NULL(x) tpl_text_channel_set_##x(self, NULL) + TPL_SET_NULL(tpl_channel); + TPL_SET_NULL(my_contact); + TPL_SET_NULL(remote_contact); + TPL_SET_NULL(chatroom_id); +#undef TPL_SET_NULL + tpl_text_channel_set_chatroom(self, FALSE); +} + +TplTextChannel* tpl_text_channel_new(TplChannel* tpl_channel) +{ + TplTextChannel *ret = g_object_new(TPL_TYPE_TEXT_CHANNEL,NULL); + tpl_text_channel_set_tpl_channel(ret, tpl_channel); + + // here some post instance-initialization, the object needs + // to set some type's members and probably access (futurely) some + // props + TpHandleType remote_handle_type; + tp_channel_get_handle( + tpl_channel_get_channel(tpl_channel), + &remote_handle_type); + + ret->chain = g_queue_new(); + g_queue_push_tail(ret->chain, + _tpl_text_channel_pendingproc_get_my_contact); + + switch (remote_handle_type) + { + case TP_HANDLE_TYPE_CONTACT: + g_queue_push_tail(ret->chain, + _tpl_text_channel_pendingproc_get_remote_contact); + break; + case TP_HANDLE_TYPE_ROOM: + g_queue_push_tail(ret->chain, + _tpl_text_channel_pendingproc_get_chatroom_id); + break; + + /* follows unhandled TpHandleType */ + case TP_HANDLE_TYPE_NONE: + g_debug("remote handle: TP_HANDLE_TYPE_NONE: un-handled\n"); + break; + case TP_HANDLE_TYPE_LIST: + g_debug("remote handle: TP_HANDLE_TYPE_LIST: un-handled\n"); + break; + case TP_HANDLE_TYPE_GROUP: + g_debug("remote handle: TP_HANDLE_TYPE_GROUP: un-handled\n"); + break; + default: + g_error("remote handle unknown\n"); + break; + } + + g_queue_push_tail(ret->chain, + _tpl_text_channel_pendingproc_connect_signals); + + // start the chain consuming + context_continue(ret); + return ret; +} + +void tpl_text_channel_free(TplTextChannel* tpl_text) { + /* TODO free and unref other members */ + g_free(tpl_text); +} + + +TplChannel *tpl_text_channel_get_tpl_channel(TplTextChannel *self) +{ + return self->tpl_channel; +} + +TpContact *tpl_text_channel_get_remote_contact(TplTextChannel *self) +{ + return self->remote_contact; +} +TpContact *tpl_text_channel_get_my_contact(TplTextChannel *self) +{ + return self->my_contact; +} +gboolean tpl_text_channel_is_chatroom(TplTextChannel *self) +{ + return self->chatroom; +} +const gchar *tpl_text_channel_get_chatroom_id(TplTextChannel *self) +{ + return self->chatroom_id; +} + +void tpl_text_channel_set_tpl_channel(TplTextChannel *self, TplChannel *data) { + //g_debug("SET TPL CHANNEL\n"); + _unref_object_if_not_null(&(self->tpl_channel)); + self->tpl_channel = data; + _ref_object_if_not_null(data); +} + +void tpl_text_channel_set_remote_contact(TplTextChannel *self, TpContact *data) +{ + //g_debug("SET remote contact\n"); + _unref_object_if_not_null(&(self->remote_contact)); + self->remote_contact = data; + _ref_object_if_not_null(data); +} +void tpl_text_channel_set_my_contact(TplTextChannel *self, TpContact *data) +{ + //g_debug("SET my contact\n"); + _unref_object_if_not_null(&(self->my_contact)); + self->my_contact = data; + _ref_object_if_not_null(data); +} +void tpl_text_channel_set_chatroom(TplTextChannel *self, gboolean data) +{ + self->chatroom = data; +} +void tpl_text_channel_set_chatroom_id(TplTextChannel *self, const gchar *data) +{ + g_free ((gchar*)self->chatroom_id); + self->chatroom_id = g_strdup (data); +} diff --git a/src/tpl-utils.c b/src/tpl-utils.c new file mode 100644 index 0000000..2f65476 --- /dev/null +++ b/src/tpl-utils.c @@ -0,0 +1,13 @@ +#include + +void _unref_object_if_not_null(void* data) { + if (data && G_IS_OBJECT(data)) { + g_object_unref(data); + } +} + +void _ref_object_if_not_null(void* data) { + if (data && G_IS_OBJECT(data)) { + g_object_ref(data); + } +} diff --git a/src/tpl_channel_data.c b/src/tpl_channel_data.c deleted file mode 100644 index f2928ad..0000000 --- a/src/tpl_channel_data.c +++ /dev/null @@ -1,116 +0,0 @@ -#include -#include - - -G_DEFINE_TYPE (TplChannel, tpl_channel, G_TYPE_OBJECT) - -static void tpl_channel_class_init(TplChannelClass* klass) { - //GObjectClass* gobject_class = G_OBJECT_CLASS (klass); -} - - -static void tpl_channel_init(TplChannel* self) { - /* Init TplChannel's members to zero/NULL */ -#define TPL_SET_NULL(x) tpl_channel_set_##x(self, NULL) - TPL_SET_NULL(channel); - TPL_SET_NULL(channel_path); - TPL_SET_NULL(channel_type); - TPL_SET_NULL(channel_properties); - TPL_SET_NULL(account); - TPL_SET_NULL(account_path); - TPL_SET_NULL(connection); - TPL_SET_NULL(connection_path); - TPL_SET_NULL(observer); -#undef TPL_SET_NULL -} - -TplChannel* tpl_channel_new(TpSvcClientObserver* observer) { - TplChannel *ret = g_object_new(TPL_TYPE_CHANNEL,NULL); - tpl_channel_set_observer(ret, observer); - return ret; -} - -void tpl_channel_free(TplChannel* tpl_text) { - /* TODO free and unref other members */ - g_free(tpl_text); -} - - -TpSvcClientObserver* tpl_channel_get_observer(TplChannel *self) { - return self->observer; -} -TpAccount *tpl_channel_get_account(TplChannel *self) { - return self->account; -} -const gchar *tpl_channel_get_account_path(TplChannel *self) { - return self->account_path; -} -TpConnection *tpl_channel_get_connection(TplChannel *self) { - return self->connection; -} -const gchar *tpl_channel_get_connection_path(TplChannel *self) { - return self->connection_path; -} -TpChannel *tpl_channel_get_channel(TplChannel *self) { - return self->channel; -} -const gchar *tpl_channel_get_channel_path(TplChannel *self) { - return self->channel_path; -} -const gchar *tpl_channel_get_channel_type(TplChannel *self) { - return self->channel_type; -} -GHashTable *tpl_channel_get_channel_properties(TplChannel *self) { - return self->channel_properties; -} - - - -void tpl_channel_set_observer(TplChannel *self, - TpSvcClientObserver *data) { - //g_debug("SET observer\n"); - _unref_object_if_not_null(&(self->observer)); - self->observer = data; - _ref_object_if_not_null(data); -} -void tpl_channel_set_account(TplChannel *self, TpAccount *data) { - //g_debug("SET account\n"); - _unref_object_if_not_null(&(self->account)); - if (self->account!=NULL) - g_object_unref(self->account); - self->account = data; - _ref_object_if_not_null(data); -} -void tpl_channel_set_account_path(TplChannel *self, const gchar *data) { - //g_debug("SET path\n"); - if (self->account!=NULL) - self->account_path = data; -} -void tpl_channel_set_connection(TplChannel *self, TpConnection *data) { - //g_debug("SET connection\n"); - _unref_object_if_not_null(&(self->connection)); - self->connection = data; - _ref_object_if_not_null(data); -} -void tpl_channel_set_connection_path(TplChannel *self, const gchar *data) { - //g_debug("SET connectin path\n"); - self->connection_path = data; -} -void tpl_channel_set_channel(TplChannel *self, TpChannel *data) { - //g_debug("SET channel\n"); - _unref_object_if_not_null(&(self->channel)); - self->channel = data; - _ref_object_if_not_null(data); -} -void tpl_channel_set_channel_path(TplChannel *self, const gchar *data) { - //g_debug("SET channel path\n"); - self->channel_path = data; -} -void tpl_channel_set_channel_type(TplChannel *self, const gchar *data) { - //g_debug("SET channel type\n"); - self->channel_type = data; -} -void tpl_channel_set_channel_properties(TplChannel *self, GHashTable *data) { - //g_debug("SET channel prop\n"); - self->channel_properties = data; -} diff --git a/src/tpl_contact.c b/src/tpl_contact.c deleted file mode 100644 index ec1ebea..0000000 --- a/src/tpl_contact.c +++ /dev/null @@ -1,44 +0,0 @@ -#include -#include - -G_DEFINE_TYPE (TplContact, tpl_contact, G_TYPE_OBJECT) - -static void tpl_contact_class_init(TplContactClass* klass) { - //GObjectClass* gobject_class = G_OBJECT_CLASS (klass); -} - -static void tpl_contact_init(TplContact* self) { -} - -/* retrieved contat and set TplContact ready */ - -TplContact *tpl_contact_new() { - return g_object_new(TPL_TYPE_CONTACT,NULL); -} - -#define ADD_GET(x,y) y tpl_contact_get_##x(TplContact *self) { \ - return self->x; } - ADD_GET(contact, TpContact *); - ADD_GET(alias, const gchar *); - ADD_GET(identifier, const gchar *); - ADD_GET(presence_status, const gchar *); - ADD_GET(presence_message, const gchar *); - ADD_GET(contact_type, TplContactType); - ADD_GET(account, TpAccount *); -#undef ADD_GET - -#define ADD_SET(member,y) void tpl_contact_set_##member(TplContact *self, y data) { \ - _unref_object_if_not_null(&(self->member)) ; \ - self->member = data; \ - _ref_object_if_not_null(data); } - ADD_SET(contact, TpContact *); - ADD_SET(account, TpAccount *); -#undef ADD_SET -#define ADD_SET_SIMPLE(member,y) void tpl_contact_set_##member(TplContact *self, y data) { \ - self->member = data;} - ADD_SET_SIMPLE(alias, const gchar *); - ADD_SET_SIMPLE(identifier, const gchar *); - ADD_SET_SIMPLE(presence_status, const gchar *); - ADD_SET_SIMPLE(presence_message, const gchar *); - ADD_SET_SIMPLE(contact_type, TplContactType); -#undef ADD_SET_SIMPLE diff --git a/src/tpl_headless_logger_init.c b/src/tpl_headless_logger_init.c deleted file mode 100644 index 1f9061d..0000000 --- a/src/tpl_headless_logger_init.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include -#include -#include - -#include - -#include - -/* - * Initialization of TPL (TelePathy Logger), it futurely set all the - * inernal structs. tpl_headless_logger_deinit will free/unref them - */ -void tpl_headless_logger_init(void) -{ - TplObserver *observer; - DBusGConnection *bus; - TpDBusDaemon *tp_bus; - GError *error = NULL; - - bus = tp_get_bus(); - tp_bus = tp_dbus_daemon_new(bus); - - if ( tp_dbus_daemon_request_name (tp_bus, TPL_OBSERVER_WELL_KNOWN_BUS_NAME, - TRUE, &error) ) { - g_print("Well Known name requested successfully!\n"); - } else { - g_print("Well Known name request error: %s\n", error->message); - g_clear_error(&error); - g_error_free(error); - } - - - observer = tpl_observer_new (); - dbus_g_connection_register_g_object (bus, - TPL_OBSERVER_OBJECT_PATH, - G_OBJECT(observer)); -} diff --git a/src/tpl_log_entry_text.c b/src/tpl_log_entry_text.c deleted file mode 100644 index 66bd071..0000000 --- a/src/tpl_log_entry_text.c +++ /dev/null @@ -1,124 +0,0 @@ -#include -#include -#include -#include - -G_DEFINE_TYPE (TplLogEntryText, tpl_log_entry_text, G_TYPE_OBJECT) - -static void tpl_log_entry_text_class_init(TplLogEntryTextClass* klass) { - //GObjectClass* gobject_class = G_OBJECT_CLASS (klass); -} - -static void tpl_log_entry_text_init(TplLogEntryText* self) { -#define TPL_SET_NULL(x) tpl_log_entry_text_set_##x(self, NULL) - TPL_SET_NULL(tpl_channel); -#undef TPL_SET_NULL -} - -TplLogEntryText *tpl_log_entry_text_new(void) { - TplLogEntryText *ret = g_object_new(TPL_TYPE_LOG_ENTRY_TEXT, NULL); - return ret; -} - - - -TpChannelTextMessageType -tpl_log_entry_text_message_type_from_str (const gchar *type_str) -{ - if (g_strcmp0 (type_str, "normal") == 0) { - return TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL; - } - if (g_strcmp0 (type_str, "action") == 0) { - return TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION; - } - else if (g_strcmp0 (type_str, "notice") == 0) { - return TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE; - } - else if (g_strcmp0 (type_str, "auto-reply") == 0) { - return TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY; - } - - return TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL; -} - - -const gchar *tpl_log_entry_text_message_type_to_str (TpChannelTextMessageType msg_type) -{ - switch (msg_type) { - case TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION: - return "action"; - case TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE: - return "notice"; - case TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY: - return "auto-reply"; - default: - return "normal"; - } -} - - -TplChannel *tpl_log_entry_text_get_tpl_channel(TplLogEntryText *self) { - return self->tpl_channel; -} -TplContact *tpl_log_entry_text_get_sender (TplLogEntryText *self) { - return self->sender; -} -TplContact *tpl_log_entry_text_get_receiver (TplLogEntryText *self) { - return self->receiver; -} -const gchar *tpl_log_entry_text_get_message (TplLogEntryText *self) { - return self->message; -} -TpChannelTextMessageType tpl_log_entry_text_get_message_type (TplLogEntryText *self) { - return self->message_type; -} -TplLogEntryTextSignalType tpl_log_entry_text_get_signal_type (TplLogEntryText *self) { - return self->signal_type; -} -TplLogEntryTextDirection tpl_log_entry_text_get_direction (TplLogEntryText *self) { - return self->direction; -} -time_t tpl_log_entry_text_get_timestamp (TplLogEntryText *self) -{ - return self->timestamp; -} -guint tpl_log_entry_text_get_id (TplLogEntryText *self) -{ - return self->id; -} - - -void tpl_log_entry_text_set_tpl_channel(TplLogEntryText *self, TplChannel *data) { - _unref_object_if_not_null(self->tpl_channel); - self->tpl_channel = data; - _ref_object_if_not_null(data); -} - -void tpl_log_entry_text_set_sender (TplLogEntryText *self, TplContact *data) { - self->sender = data; -} -void tpl_log_entry_text_set_receiver (TplLogEntryText *self, TplContact *data) { - self->receiver = data; -} -void tpl_log_entry_text_set_message (TplLogEntryText *self, const gchar *data) { - self->message = data; -} -void tpl_log_entry_text_set_message_type (TplLogEntryText *self, TpChannelTextMessageType data) { - self->message_type = data; -} -void tpl_log_entry_text_set_signal_type (TplLogEntryText *self, TplLogEntryTextSignalType data) { - self->signal_type = data; -} -void tpl_log_entry_text_set_direction (TplLogEntryText *self, TplLogEntryTextDirection data) { - self->direction = data; -} - -void tpl_log_entry_text_set_timestamp (TplLogEntryText *self, time_t data) -{ - self->timestamp = data; -} - -void tpl_log_entry_text_set_id (TplLogEntryText *self, guint data) -{ - self->id = data; -} diff --git a/src/tpl_observer.c b/src/tpl_observer.c deleted file mode 100644 index 49ce80a..0000000 --- a/src/tpl_observer.c +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -static void observer_iface_init (gpointer, gpointer); - -G_DEFINE_TYPE_WITH_CODE (TplObserver, tpl_observer, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, - tp_dbus_properties_mixin_iface_init); - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CLIENT, - NULL); - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CLIENT_OBSERVER, - observer_iface_init); -); - -static const char *client_interfaces[] = { - TP_IFACE_CLIENT_OBSERVER, - NULL -}; - -enum -{ - PROP_0, - PROP_INTERFACES, - PROP_CHANNEL_FILTER -}; - -void _observe_channel_when_ready_cb(TpChannel *channel, - const GError *error, - gpointer user_data); -void _tp_connection_called_when_ready_cb(TpConnection *connection, - const GError *error, - gpointer user_data); - - -void _observe_channel_when_ready_cb(TpChannel *channel, - const GError *error, - gpointer user_data) -{ - TplChannel *tpl_chan = TPL_CHANNEL(user_data); - gpointer tpl_channel_instance; - // TODO add a GHashTable mapping - // channelpath:tpl_channel_instance to record observed channels - // and a way to access (get/set) them - - if(error!=NULL) { - g_error("channel error: %s", error->message); - g_error("giving up observing channel '%s'", - tpl_chan->channel_path); - // TODO free tpl_chan - //tpl_channel_data_free(tpl_chan); - return; - } - - tpl_channel_set_channel_type(tpl_chan, - tp_channel_get_channel_type(tpl_chan->channel) ); - - /* Instantiate and delegate channel handling to the right object */ - if(0==g_strcmp0(TP_IFACE_CHAN_TEXT, tpl_chan->channel_type)) { - tpl_channel_instance = tpl_text_channel_new(tpl_chan); - // TODO add to hash - } else { - g_warning("%s: channel not handled by TPL", tpl_chan->channel_type); - } -} - - -void _tp_connection_called_when_ready_cb(TpConnection *connection, - const GError *error, - gpointer user_data) -{ - TplChannel *tpl_chan = TPL_CHANNEL(user_data); - - tp_channel_call_when_ready (tpl_channel_get_channel(tpl_chan), - _observe_channel_when_ready_cb, tpl_chan); -} - - -static void -tpl_observer_observe_channels (TpSvcClientObserver *self, - const char *account, - const char *connection, - const GPtrArray *channels, - const char *dispatch_op, - const GPtrArray *requests_satisfied, - GHashTable *observer_info, - DBusGMethodInvocation *context) -{ - TpAccount *tp_acc; - TpConnection *tp_conn; - TpDBusDaemon *tp_bus_daemon; - GError *error = NULL; - - g_debug (" > tpl_observer_observe_channels\n"); - g_debug (" account = %s\n", account); - g_debug (" connection = %s\n", connection); - g_debug (" dispatchop = %s\n", dispatch_op); - - tp_bus_daemon = tp_dbus_daemon_dup(&error); - if(tp_bus_daemon == NULL) { - g_error("%s\n", error->message); - g_clear_error(&error); - g_error_free(error); - } - - tp_acc = tp_account_new(tp_bus_daemon, account, &error); - if(tp_acc == NULL) { - g_error("%s\n", error->message); - g_clear_error(&error); - g_error_free(error); - error=NULL; - } - - - tp_conn = tp_connection_new (tp_bus_daemon, NULL, connection, &error); - if(tp_conn == NULL) { - g_error("%s\n", error->message); - g_clear_error(&error); - g_error_free(error); - error=NULL; - } - - /* channels is of type a(oa{sv}) */ - for (guint i = 0; i < channels->len; i++) - { - GValueArray *channel = g_ptr_array_index (channels, i); - TpChannel *tp_chan = NULL; - TplChannel* tpl_chan = tpl_channel_new(self); - - char *path = g_value_get_boxed (g_value_array_get_nth (channel, 0)); - // propertyNameStr/value hash - GHashTable *map = g_value_get_boxed (g_value_array_get_nth (channel, 1)); - - g_debug (" channel = %s\n", path); - tp_chan = tp_channel_new (tp_conn, path, NULL, TP_UNKNOWN_HANDLE_TYPE, 0, - &error); - - tpl_channel_set_account(tpl_chan, tp_acc); - tpl_channel_set_account_path(tpl_chan, account); - tpl_channel_set_connection(tpl_chan, tp_conn); - tpl_channel_set_connection_path(tpl_chan, connection); - tpl_channel_set_channel(tpl_chan, tp_chan); - tpl_channel_set_channel_path(tpl_chan, path); - tpl_channel_set_channel_properties(tpl_chan, map); - - tp_connection_call_when_ready(tp_conn, - _tp_connection_called_when_ready_cb, tpl_chan); - } - - - - tp_svc_client_observer_return_from_observe_channels (context); -} - -static void -tpl_observer_get_property (GObject *self, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - g_print(" :: get_property\n"); - switch (property_id) - { - GPtrArray *array; - GHashTable *map; - case PROP_INTERFACES: - g_print (" :: interfaces\n"); - g_value_set_boxed (value, client_interfaces); - break; - - case PROP_CHANNEL_FILTER: - g_print (" :: channel-filter\n"); - - /* create an empty filter - which means all channels */ - array = g_ptr_array_new (); - map = g_hash_table_new (NULL, NULL); - - g_ptr_array_add (array, map); - g_value_set_boxed (value, array); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (self, property_id, pspec); - break; - } -} - -static void -tpl_observer_class_init (TplObserverClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - /* D-Bus properties are exposed as GObject properties through the - * TpDBusPropertiesMixin */ - /* properties on the Client interface */ - static TpDBusPropertiesMixinPropImpl client_props[] = { - { "Interfaces", "interfaces", NULL }, - { NULL } - }; - - /* properties on the Client.Observer interface */ - static TpDBusPropertiesMixinPropImpl client_observer_props[] = { - { "ObserverChannelFilter", "channel-filter", NULL }, - { NULL } - }; - - /* complete list of interfaces with properties */ - static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { - { TP_IFACE_CLIENT, - tp_dbus_properties_mixin_getter_gobject_properties, - NULL, - client_props - }, - { TP_IFACE_CLIENT_OBSERVER, - tp_dbus_properties_mixin_getter_gobject_properties, - NULL, - client_observer_props - }, - { NULL } - }; - object_class->get_property = tpl_observer_get_property; - - g_object_class_install_property (object_class, PROP_INTERFACES, - g_param_spec_boxed ("interfaces", - "Interfaces", - "Available D-Bus Interfaces", - G_TYPE_STRV, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (object_class, PROP_CHANNEL_FILTER, - g_param_spec_boxed ("channel-filter", - "Channel Filter", - "Filter for channels we observe", - TP_ARRAY_TYPE_CHANNEL_CLASS_LIST, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - /* call our mixin class init */ - klass->dbus_props_class.interfaces = prop_interfaces; - tp_dbus_properties_mixin_class_init (object_class, - G_STRUCT_OFFSET (TplObserverClass, dbus_props_class)); -} - -static void -tpl_observer_init (TplObserver *self) -{ -} - -static void -observer_iface_init (gpointer g_iface, gpointer iface_data) -{ - TpSvcClientObserverClass *klass = (TpSvcClientObserverClass *) g_iface; - -#define IMPLEMENT(x) tp_svc_client_observer_implement_##x (klass, \ - tpl_observer_##x) - IMPLEMENT (observe_channels); -#undef IMPLEMENT -} - -TplObserver *tpl_observer_new (void) -{ - return g_object_new (TYPE_TPL_OBSERVER, NULL); -} diff --git a/src/tpl_text_channel_data.c b/src/tpl_text_channel_data.c deleted file mode 100644 index da8a51e..0000000 --- a/src/tpl_text_channel_data.c +++ /dev/null @@ -1,370 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include -#include - -#define TP_CONTACT_FEATURES_LEN 2 -#define TP_CONTACT_CONTACTS_LEN 2 -#define TP_CONTACT_MYSELF 0 -#define TP_CONTACT_REMOTE 1 - -static TpContactFeature features[TP_CONTACT_FEATURES_LEN] = { - TP_CONTACT_FEATURE_ALIAS, - TP_CONTACT_FEATURE_PRESENCE -}; - - -/* definitions */ - -void _channel_on_sent_signal_cb (TpChannel *proxy, - guint arg_Timestamp, - guint arg_Type, - const gchar *arg_Text, - gpointer user_data, - GObject *weak_object); -void _channel_on_sent_signal_cb (TpChannel *proxy, - guint arg_Timestamp, - guint arg_Type, - const gchar *arg_Text, - gpointer user_data, - GObject *weak_object); -void _channel_on_received_signal_cb (TpChannel *proxy, - guint arg_ID, - guint arg_Timestamp, - guint arg_Sender, - guint arg_Type, - guint arg_Flags, - const gchar *arg_Text, - gpointer user_data, - GObject *weak_object); -void _tpl_text_channel_connect_signals(TplTextChannel* self); -void _tpl_text_channel_set_ready_cb(TpConnection *connection, - guint n_contacts, - TpContact * const *contacts, - guint n_failed, - const TpHandle *failed, - const GError *error, - gpointer user_data, - GObject *weak_object); -/* end of definitions */ - - - - -/* Callbacks */ - -void _channel_on_sent_signal_cb (TpChannel *proxy, - guint arg_Timestamp, - guint arg_Type, - const gchar *arg_Text, - gpointer user_data, - GObject *weak_object) -{ - GError *error=NULL; - TplTextChannel *tpl_text = TPL_TEXT_CHANNEL(user_data); - TpContact *remote,*me; - const gchar *my_id, *my_alias, *remote_id, *remote_alias; - const gchar *my_pres_msg, *my_pres_status; - const gchar *remote_pres_msg, *remote_pres_status; - TplContact *tpl_contact_sender; - TplContact *tpl_contact_receiver; - TplLogEntryText *log; - TplLogStoreEmpathy *logstore; - - /* Initialize data for TplContact */ - me = tpl_text_channel_get_my_contact(tpl_text); - remote = tpl_text_channel_get_remote_contact(tpl_text); - - my_id = tp_contact_get_identifier(me); - remote_id = tp_contact_get_identifier(remote); - - my_alias = tp_contact_get_alias(me); - remote_alias = tp_contact_get_alias(remote); - - my_pres_status = tp_contact_get_presence_status(me); - remote_pres_status = tp_contact_get_presence_status(remote); - - my_pres_msg = tp_contact_get_presence_message (me); - remote_pres_msg = tp_contact_get_presence_message (remote); - - tpl_contact_sender = tpl_contact_new(); - tpl_contact_receiver = tpl_contact_new(); -#define CONTACT_ENTRY_SET(x,y) tpl_contact_set_##x(tpl_contact_sender,y) - CONTACT_ENTRY_SET(contact, me); - CONTACT_ENTRY_SET(alias, my_alias); - CONTACT_ENTRY_SET(identifier, my_id); - CONTACT_ENTRY_SET(presence_status, my_pres_status); - CONTACT_ENTRY_SET(presence_message, my_pres_msg ); - CONTACT_ENTRY_SET(contact_type, TPL_CONTACT_USER); -#undef CONTACT_ENTRY_SET -#define CONTACT_ENTRY_SET(x,y) tpl_contact_set_##x(tpl_contact_receiver,y) - CONTACT_ENTRY_SET(contact, remote); - CONTACT_ENTRY_SET(alias, remote_alias); - CONTACT_ENTRY_SET(identifier, remote_id); - CONTACT_ENTRY_SET(presence_status, remote_pres_status ); - CONTACT_ENTRY_SET(presence_message, remote_pres_msg); - CONTACT_ENTRY_SET(contact_type, TPL_CONTACT_USER); -#undef CONTACT_ENTRY_SET - - g_message("%s (%s): %s\n", - tpl_contact_get_identifier(tpl_contact_sender), - tpl_contact_get_alias(tpl_contact_sender), - arg_Text); - - - /* Initialize TplLogEntryText */ - - log = tpl_log_entry_text_new(); - tpl_log_entry_text_set_tpl_channel(log, - tpl_text_channel_get_tpl_channel(tpl_text)); - tpl_log_entry_text_set_sender(log, tpl_contact_sender); - tpl_log_entry_text_set_receiver(log, tpl_contact_receiver); - tpl_log_entry_text_set_message(log, arg_Text); - tpl_log_entry_text_set_message_type(log, arg_Type); - tpl_log_entry_text_set_signal_type(log, - TPL_LOG_ENTRY_TEXT_CHANNEL_MESSAGE); - tpl_log_entry_text_set_timestamp(log, (time_t) arg_Timestamp); - tpl_log_entry_text_set_id(log, 123); - - /* Initialized LogStore and send the message */ - - logstore = g_object_new(TPL_TYPE_LOG_STORE_EMPATHY, NULL); - if (!TPL_LOG_STORE_GET_INTERFACE(logstore)->add_message) { - g_warning("LOGSTORE IFACE: add message not implemented\n"); - return; - } - - tpl_log_store_add_message( TPL_LOG_STORE(logstore), - tpl_contact_get_identifier(tpl_contact_sender), - FALSE, - log, - &error); - if(error!=NULL) { - g_error("LOGSTORE: %s", error->message); - g_clear_error(&error); - g_error_free(error); - } - -} - -void _channel_on_received_signal_cb (TpChannel *proxy, - guint arg_ID, - guint arg_Timestamp, - guint arg_Sender, - guint arg_Type, - guint arg_Flags, - const gchar *arg_Text, - gpointer user_data, - GObject *weak_object) -{ - TplTextChannel *tpl_text = TPL_TEXT_CHANNEL(user_data); - TpContact *remote,*me; - const gchar *my_id, *my_alias, *remote_id, *remote_alias; - const gchar *my_pres_msg, *my_pres_status; - const gchar *remote_pres_msg, *remote_pres_status; - TplContact *tpl_contact_sender; - TplContact *tpl_contact_receiver; - TplLogEntryText *log; - - me = tpl_text_channel_get_my_contact(tpl_text); - remote = tpl_text_channel_get_remote_contact(tpl_text); - - my_id = tp_contact_get_identifier(me); - remote_id = tp_contact_get_identifier(remote); - - my_alias = tp_contact_get_alias(me); - remote_alias = tp_contact_get_alias(remote); - - my_pres_status = tp_contact_get_presence_status(me); - remote_pres_status = tp_contact_get_presence_status(remote); - - my_pres_msg = tp_contact_get_presence_message (me); - remote_pres_msg = tp_contact_get_presence_message (remote); - - tpl_contact_sender = tpl_contact_new(); - tpl_contact_receiver = tpl_contact_new(); -#define CONTACT_ENTRY_SET(x,y) tpl_contact_set_##x(tpl_contact_sender,y) - CONTACT_ENTRY_SET(contact, remote); - CONTACT_ENTRY_SET(alias, remote_alias); - CONTACT_ENTRY_SET(identifier, remote_id); - CONTACT_ENTRY_SET(presence_status, remote_pres_status); - CONTACT_ENTRY_SET(presence_message, remote_pres_msg ); -#undef CONTACT_ENTRY_SET -#define CONTACT_ENTRY_SET(x,y) tpl_contact_set_##x(tpl_contact_receiver,y) - CONTACT_ENTRY_SET(contact, me); - CONTACT_ENTRY_SET(alias, my_alias); - CONTACT_ENTRY_SET(identifier, my_id); - CONTACT_ENTRY_SET(presence_status, my_pres_status ); - CONTACT_ENTRY_SET(presence_message, my_pres_msg); -#undef CONTACT_ENTRY_SET - - g_message("%s (%s): %s\n", - tpl_contact_get_identifier(tpl_contact_sender), - tpl_contact_get_alias(tpl_contact_sender), - arg_Text); - - - log = tpl_log_entry_text_new(); - tpl_log_entry_text_set_tpl_channel(log, - tpl_text_channel_get_tpl_channel(tpl_text)); - tpl_log_entry_text_set_sender(log, tpl_contact_sender); - tpl_log_entry_text_set_receiver(log, tpl_contact_receiver); - tpl_log_entry_text_set_message(log, arg_Text); - tpl_log_entry_text_set_message_type(log, arg_Type); - tpl_log_entry_text_set_signal_type(log, TPL_LOG_ENTRY_TEXT_CHANNEL_MESSAGE); -} - -/* connect signals to TplTextChannel instance */ - -void _tpl_text_channel_connect_signals(TplTextChannel* self) -{ - GError *error=NULL; -// Signals for Text channels -// "lost-message" : Run Last / Has Details -// "received" : Run Last / Has Details -// "send-error" : Run Last / Has Details -// "sent" : Run Last / Has Details -// "chat-state-changed" : Run Last / Has Details -// "password-flags-changed" : Run Last / Has Details - //TODO handle data destruction - tp_cli_channel_type_text_connect_to_received(self->tpl_channel->channel, - _channel_on_received_signal_cb, self, NULL, NULL, &error); - if (error!=NULL) { - g_error("received signal connect: %s\n", error->message); - g_clear_error(&error); - g_error_free(error); - } - - //TODO handle data destruction - tp_cli_channel_type_text_connect_to_sent(self->tpl_channel->channel, - _channel_on_sent_signal_cb, self, NULL, NULL, &error); - if (error!=NULL) { - g_error("sent signal connect: %s\n", error->message); - g_clear_error(&error); - g_error_free(error); - } -} - - -/* retrieve contacts (me and remove buddy) and set TplTextChannel - * members */ - -void _tpl_text_channel_set_ready_cb(TpConnection *connection, - guint n_contacts, - TpContact * const *contacts, - guint n_failed, - const TpHandle *failed, - const GError *error, - gpointer user_data, - GObject *weak_object) -{ - TplTextChannel *tpl_text = (TplTextChannel*) user_data; - - tpl_text_channel_set_my_contact(tpl_text, contacts[TP_CONTACT_MYSELF]); - tpl_text_channel_set_remote_contact(tpl_text, contacts[TP_CONTACT_REMOTE]); - - //g_debug("MY ALIAS: %s\n", tp_contact_get_alias( - // tpl_text_channel_get_my_contact(tpl_text))); - //g_debug("REMOTE ID: %s\n", tp_contact_get_identifier( - // tpl_text_channel_get_remote_contact(tpl_text))); - - - _tpl_text_channel_connect_signals(tpl_text); -} - - - - - -/* end of async Callbacks */ - - - -G_DEFINE_TYPE (TplTextChannel, tpl_text_channel, G_TYPE_OBJECT) - - -static void tpl_text_channel_class_init(TplTextChannelClass* klass) { - //GObjectClass* gobject_class = G_OBJECT_CLASS (klass); -} - - -static void tpl_text_channel_init(TplTextChannel* self) { - /* Init TplTextChannel's members to zero/NULL */ -#define TPL_SET_NULL(x) tpl_text_channel_set_##x(self, NULL) - TPL_SET_NULL(tpl_channel); - TPL_SET_NULL(my_contact); - TPL_SET_NULL(remote_contact); -#undef TPL_SET_NULL -} - -TplTextChannel* tpl_text_channel_new(TplChannel* tpl_channel) -{ - TplTextChannel *ret = g_object_new(TPL_TYPE_TEXT_CHANNEL,NULL); - ret->tpl_channel = tpl_channel; - tpl_text_channel_set_tpl_channel(ret, tpl_channel); - - // here some post instance-initialization, the object needs - // to set some type's members and probably access (futurely) some - // props - TpHandle contacts[TP_CONTACT_CONTACTS_LEN] = {0,0}; - TpHandleType remote_handle_type; - - contacts[TP_CONTACT_REMOTE] = tp_channel_get_handle( - ret->tpl_channel->channel, &remote_handle_type); - contacts[TP_CONTACT_MYSELF] = tp_connection_get_self_handle( - ret->tpl_channel->connection); - tp_connection_get_contacts_by_handle( - ret->tpl_channel->connection, - TP_CONTACT_CONTACTS_LEN, contacts, - TP_CONTACT_FEATURES_LEN, features, - _tpl_text_channel_set_ready_cb, - ret, NULL, NULL); - return ret; -} - -void tpl_text_channel_free(TplTextChannel* tpl_text) { - /* TODO free and unref other members */ - g_free(tpl_text); -} - - -TplChannel *tpl_text_channel_get_tpl_channel(TplTextChannel *self) -{ - return self->tpl_channel; -} - -TpContact *tpl_text_channel_get_remote_contact(TplTextChannel *self) -{ - return self->remote_contact; -} -TpContact *tpl_text_channel_get_my_contact(TplTextChannel *self) -{ - return self->my_contact; -} - -void tpl_text_channel_set_tpl_channel(TplTextChannel *self, TplChannel *data) { - //g_debug("SET TPL CHANNEL\n"); - _unref_object_if_not_null(&(self->tpl_channel)); - self->tpl_channel = data; - _ref_object_if_not_null(data); -} - -void tpl_text_channel_set_remote_contact(TplTextChannel *self, TpContact *data) -{ - //g_debug("SET remote contact\n"); - _unref_object_if_not_null(&(self->remote_contact)); - self->remote_contact = data; - _ref_object_if_not_null(data); -} -void tpl_text_channel_set_my_contact(TplTextChannel *self, TpContact *data) -{ - //g_debug("SET my contact\n"); - _unref_object_if_not_null(&(self->my_contact)); - self->my_contact = data; - _ref_object_if_not_null(data); -} diff --git a/src/tpl_utils.c b/src/tpl_utils.c deleted file mode 100644 index 04fda19..0000000 --- a/src/tpl_utils.c +++ /dev/null @@ -1,13 +0,0 @@ -#include - -void _unref_object_if_not_null(void* data) { - if (data && G_IS_OBJECT(data)) { - g_object_unref(data); - } -} - -void _ref_object_if_not_null(void* data) { - if (data && G_IS_OBJECT(data)) { - g_object_ref(data); - } -} -- cgit v1.2.1