2011-03-14 07:38:06 -04:00
|
|
|
#include "shell-tp-client.h"
|
|
|
|
|
2011-03-28 03:08:13 -04:00
|
|
|
#include <string.h>
|
|
|
|
|
2011-03-14 07:38:06 -04:00
|
|
|
#include <telepathy-glib/telepathy-glib.h>
|
|
|
|
|
|
|
|
G_DEFINE_TYPE(ShellTpClient, shell_tp_client, TP_TYPE_BASE_CLIENT)
|
|
|
|
|
|
|
|
struct _ShellTpClientPrivate
|
|
|
|
{
|
|
|
|
ShellTpClientObserveChannelsImpl observe_impl;
|
|
|
|
gpointer user_data_obs;
|
|
|
|
GDestroyNotify destroy_obs;
|
2011-04-05 07:28:11 -04:00
|
|
|
|
|
|
|
ShellTpClientApproveChannelsImpl approve_channels_impl;
|
|
|
|
gpointer user_data_approve_channels;
|
|
|
|
GDestroyNotify destroy_approve_channels;
|
|
|
|
|
|
|
|
ShellTpClientHandleChannelsImpl handle_channels_impl;
|
|
|
|
gpointer user_data_handle_channels;
|
|
|
|
GDestroyNotify destroy_handle_channels;
|
2011-03-14 07:38:06 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ShellTpClientObserveChannelsImpl:
|
|
|
|
* @client: a #ShellTpClient instance
|
|
|
|
* @account: a #TpAccount having %TP_ACCOUNT_FEATURE_CORE prepared if possible
|
|
|
|
* @connection: a #TpConnection having %TP_CONNECTION_FEATURE_CORE prepared
|
|
|
|
* if possible
|
|
|
|
* @channels: (element-type TelepathyGLib.Channel): a #GList of #TpChannel,
|
|
|
|
* all having %TP_CHANNEL_FEATURE_CORE prepared if possible
|
|
|
|
* @dispatch_operation: (allow-none): a #TpChannelDispatchOperation or %NULL;
|
|
|
|
* the dispatch_operation is not guaranteed to be prepared
|
|
|
|
* @requests: (element-type TelepathyGLib.ChannelRequest): a #GList of
|
|
|
|
* #TpChannelRequest, all having their object-path defined but are not
|
|
|
|
* guaranteed to be prepared.
|
|
|
|
* @context: a #TpObserveChannelsContext representing the context of this
|
|
|
|
* D-Bus call
|
|
|
|
*
|
|
|
|
* Signature of the implementation of the ObserveChannels method.
|
|
|
|
*/
|
|
|
|
|
2011-04-05 07:28:11 -04:00
|
|
|
/**
|
|
|
|
* ShellTpClientApproveChannelsImpl:
|
|
|
|
* @client: a #ShellTpClient instance
|
|
|
|
* @account: a #TpAccount having %TP_ACCOUNT_FEATURE_CORE prepared if possible
|
|
|
|
* @connection: a #TpConnection having %TP_CONNECTION_FEATURE_CORE prepared
|
|
|
|
* if possible
|
|
|
|
* @channels: (element-type TelepathyGLib.Channel): a #GList of #TpChannel,
|
|
|
|
* all having %TP_CHANNEL_FEATURE_CORE prepared if possible
|
|
|
|
* @dispatch_operation: (allow-none): a #TpChannelDispatchOperation or %NULL;
|
|
|
|
* the dispatch_operation is not guaranteed to be prepared
|
|
|
|
* @context: a #TpAddDispatchOperationContext representing the context of this
|
|
|
|
* D-Bus call
|
|
|
|
*
|
|
|
|
* Signature of the implementation of the AddDispatchOperation method.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ShellTpClientHandleChannelsImpl:
|
|
|
|
* @client: a #ShellTpClient instance
|
|
|
|
* @account: a #TpAccount having %TP_ACCOUNT_FEATURE_CORE prepared if possible
|
|
|
|
* @connection: a #TpConnection having %TP_CONNECTION_FEATURE_CORE prepared
|
|
|
|
* if possible
|
|
|
|
* @channels: (element-type TelepathyGLib.Channel): a #GList of #TpChannel,
|
|
|
|
* all having %TP_CHANNEL_FEATURE_CORE prepared if possible
|
|
|
|
* @requests_satisfied: (element-type TelepathyGLib.ChannelRequest): a #GList of
|
|
|
|
* #TpChannelRequest having their object-path defined but are not guaranteed
|
|
|
|
* to be prepared.
|
|
|
|
* @user_action_time: the time at which user action occurred, or one of the
|
|
|
|
* special values %TP_USER_ACTION_TIME_NOT_USER_ACTION or
|
|
|
|
* %TP_USER_ACTION_TIME_CURRENT_TIME
|
|
|
|
* (see #TpAccountChannelRequest:user-action-time for details)
|
|
|
|
* @context: a #TpHandleChannelsContext representing the context of this
|
|
|
|
* D-Bus call
|
|
|
|
*
|
|
|
|
* Signature of the implementation of the HandleChannels method.
|
|
|
|
*/
|
|
|
|
|
2011-03-14 07:38:06 -04:00
|
|
|
static void
|
|
|
|
shell_tp_client_init (ShellTpClient *self)
|
|
|
|
{
|
2011-04-05 07:28:11 -04:00
|
|
|
GHashTable *filter;
|
|
|
|
|
2011-03-14 07:38:06 -04:00
|
|
|
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, SHELL_TYPE_TP_CLIENT,
|
|
|
|
ShellTpClientPrivate);
|
|
|
|
|
2011-04-05 07:28:11 -04:00
|
|
|
/* We only care about single-user text-based chats */
|
|
|
|
filter = tp_asv_new (
|
|
|
|
TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
|
|
|
|
TP_IFACE_CHANNEL_TYPE_TEXT,
|
|
|
|
TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT,
|
|
|
|
TP_HANDLE_TYPE_CONTACT,
|
|
|
|
NULL);
|
|
|
|
|
2011-03-14 07:38:06 -04:00
|
|
|
/* Observer */
|
2011-05-07 03:01:24 -04:00
|
|
|
tp_base_client_set_observer_recover (TP_BASE_CLIENT (self), TRUE);
|
2011-03-14 07:38:06 -04:00
|
|
|
|
2011-04-05 07:28:11 -04:00
|
|
|
tp_base_client_add_observer_filter (TP_BASE_CLIENT (self), filter);
|
|
|
|
|
|
|
|
/* Approver */
|
|
|
|
tp_base_client_add_approver_filter (TP_BASE_CLIENT (self), filter);
|
|
|
|
|
|
|
|
/* Handler */
|
|
|
|
tp_base_client_add_handler_filter (TP_BASE_CLIENT (self), filter);
|
|
|
|
|
|
|
|
g_hash_table_unref (filter);
|
2011-03-14 07:38:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
observe_channels (TpBaseClient *client,
|
|
|
|
TpAccount *account,
|
|
|
|
TpConnection *connection,
|
|
|
|
GList *channels,
|
|
|
|
TpChannelDispatchOperation *dispatch_operation,
|
|
|
|
GList *requests,
|
|
|
|
TpObserveChannelsContext *context)
|
|
|
|
{
|
|
|
|
ShellTpClient *self = (ShellTpClient *) client;
|
|
|
|
|
|
|
|
g_assert (self->priv->observe_impl != NULL);
|
|
|
|
|
|
|
|
self->priv->observe_impl (self, account, connection, channels,
|
|
|
|
dispatch_operation, requests, context, self->priv->user_data_obs);
|
|
|
|
}
|
|
|
|
|
2011-04-05 07:28:11 -04:00
|
|
|
static void
|
|
|
|
add_dispatch_operation (TpBaseClient *client,
|
|
|
|
TpAccount *account,
|
|
|
|
TpConnection *connection,
|
|
|
|
GList *channels,
|
|
|
|
TpChannelDispatchOperation *dispatch_operation,
|
|
|
|
TpAddDispatchOperationContext *context)
|
|
|
|
{
|
|
|
|
ShellTpClient *self = (ShellTpClient *) client;
|
|
|
|
|
|
|
|
g_assert (self->priv->approve_channels_impl != NULL);
|
|
|
|
|
|
|
|
self->priv->approve_channels_impl (self, account, connection, channels,
|
|
|
|
dispatch_operation, context, self->priv->user_data_approve_channels);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
handle_channels (TpBaseClient *client,
|
|
|
|
TpAccount *account,
|
|
|
|
TpConnection *connection,
|
|
|
|
GList *channels,
|
|
|
|
GList *requests_satisfied,
|
|
|
|
gint64 user_action_time,
|
|
|
|
TpHandleChannelsContext *context)
|
|
|
|
{
|
|
|
|
ShellTpClient *self = (ShellTpClient *) client;
|
|
|
|
|
|
|
|
g_assert (self->priv->handle_channels_impl != NULL);
|
|
|
|
|
|
|
|
self->priv->handle_channels_impl (self, account, connection, channels,
|
|
|
|
requests_satisfied, user_action_time, context,
|
|
|
|
self->priv->user_data_handle_channels);
|
|
|
|
}
|
|
|
|
|
2011-03-14 07:38:06 -04:00
|
|
|
static void
|
|
|
|
shell_tp_client_dispose (GObject *object)
|
|
|
|
{
|
|
|
|
ShellTpClient *self = SHELL_TP_CLIENT (object);
|
|
|
|
void (*dispose) (GObject *) =
|
|
|
|
G_OBJECT_CLASS (shell_tp_client_parent_class)->dispose;
|
|
|
|
|
|
|
|
if (self->priv->destroy_obs != NULL)
|
|
|
|
{
|
|
|
|
self->priv->destroy_obs (self->priv->user_data_obs);
|
|
|
|
self->priv->destroy_obs = NULL;
|
2011-04-05 07:28:11 -04:00
|
|
|
self->priv->user_data_obs = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (self->priv->destroy_approve_channels != NULL)
|
|
|
|
{
|
|
|
|
self->priv->destroy_approve_channels (self->priv->user_data_approve_channels);
|
|
|
|
self->priv->destroy_approve_channels = NULL;
|
|
|
|
self->priv->user_data_approve_channels = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (self->priv->destroy_handle_channels != NULL)
|
|
|
|
{
|
|
|
|
self->priv->destroy_handle_channels (self->priv->user_data_handle_channels);
|
|
|
|
self->priv->destroy_handle_channels = NULL;
|
|
|
|
self->priv->user_data_handle_channels = NULL;
|
2011-03-14 07:38:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (dispose != NULL)
|
|
|
|
dispose (object);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_tp_client_class_init (ShellTpClientClass *cls)
|
|
|
|
{
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (cls);
|
|
|
|
TpBaseClientClass *base_clt_cls = TP_BASE_CLIENT_CLASS (cls);
|
|
|
|
|
|
|
|
g_type_class_add_private (cls, sizeof (ShellTpClientPrivate));
|
|
|
|
|
|
|
|
object_class->dispose = shell_tp_client_dispose;
|
|
|
|
|
|
|
|
base_clt_cls->observe_channels = observe_channels;
|
2011-04-05 07:28:11 -04:00
|
|
|
base_clt_cls->add_dispatch_operation = add_dispatch_operation;
|
|
|
|
base_clt_cls->handle_channels = handle_channels;
|
2011-03-14 07:38:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
shell_tp_client_set_observe_channels_func (ShellTpClient *self,
|
|
|
|
ShellTpClientObserveChannelsImpl observe_impl,
|
|
|
|
gpointer user_data,
|
|
|
|
GDestroyNotify destroy)
|
|
|
|
{
|
|
|
|
g_assert (self->priv->observe_impl == NULL);
|
|
|
|
|
|
|
|
self->priv->observe_impl = observe_impl;
|
|
|
|
self->priv->user_data_obs = user_data;
|
|
|
|
self->priv->destroy_obs = destroy;
|
|
|
|
}
|
2011-03-28 03:08:13 -04:00
|
|
|
|
2011-04-05 07:28:11 -04:00
|
|
|
void
|
|
|
|
shell_tp_client_set_approve_channels_func (ShellTpClient *self,
|
|
|
|
ShellTpClientApproveChannelsImpl approve_channels_impl,
|
|
|
|
gpointer user_data,
|
|
|
|
GDestroyNotify destroy)
|
|
|
|
{
|
|
|
|
g_assert (self->priv->approve_channels_impl == NULL);
|
|
|
|
|
|
|
|
self->priv->approve_channels_impl = approve_channels_impl;
|
|
|
|
self->priv->user_data_approve_channels = user_data;
|
|
|
|
self->priv->destroy_approve_channels = destroy;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
shell_tp_client_set_handle_channels_func (ShellTpClient *self,
|
|
|
|
ShellTpClientHandleChannelsImpl handle_channels_impl,
|
|
|
|
gpointer user_data,
|
|
|
|
GDestroyNotify destroy)
|
|
|
|
{
|
|
|
|
g_assert (self->priv->handle_channels_impl == NULL);
|
|
|
|
|
|
|
|
self->priv->handle_channels_impl = handle_channels_impl;
|
|
|
|
self->priv->user_data_handle_channels = user_data;
|
|
|
|
self->priv->destroy_handle_channels = destroy;
|
|
|
|
}
|
|
|
|
|
2011-03-28 03:08:13 -04:00
|
|
|
/* Telepathy utility functions */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ShellGetTpContactCb:
|
|
|
|
* @connection: The connection
|
|
|
|
* @contacts: (element-type TelepathyGLib.Contact): List of contacts
|
|
|
|
* @failed: Array of failed contacts
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_global_get_tp_contacts_cb (TpConnection *self,
|
|
|
|
guint n_contacts,
|
|
|
|
TpContact * const *contacts,
|
|
|
|
guint n_failed,
|
|
|
|
const TpHandle *failed,
|
|
|
|
const GError *error,
|
|
|
|
gpointer user_data,
|
|
|
|
GObject *weak_object)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
GList *contact_list = NULL;
|
|
|
|
for (i = 0; i < n_contacts; i++) {
|
|
|
|
contact_list = g_list_append(contact_list, contacts[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
TpHandle *failed_list = g_new0 (TpHandle, n_failed + 1);
|
|
|
|
memcpy(failed_list, failed, n_failed);
|
|
|
|
|
|
|
|
((ShellGetTpContactCb)user_data)(self, contact_list, failed_list);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_get_tp_contacts:
|
|
|
|
* @self: A connection, which must be ready
|
|
|
|
* @n_handles: Number of handles in handles
|
|
|
|
* @handles: (array length=n_handles) (element-type uint): Array of handles
|
|
|
|
* @n_features: Number of features in features
|
|
|
|
* @features: (array length=n_features) (allow-none) (element-type uint):
|
|
|
|
* Array of features
|
|
|
|
* @callback: (scope async): User callback to run when the contacts are ready
|
|
|
|
*
|
|
|
|
* Wrap tp_connection_get_contacts_by_handle so we can transform the array
|
|
|
|
* into a null-terminated one, which gjs can handle.
|
|
|
|
* We send the original callback to tp_connection_get_contacts_by_handle as
|
|
|
|
* user_data, and we have our own function as callback, which does the
|
|
|
|
* transforming.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
shell_get_tp_contacts (TpConnection *self,
|
|
|
|
guint n_handles,
|
|
|
|
const TpHandle *handles,
|
|
|
|
guint n_features,
|
|
|
|
const TpContactFeature *features,
|
|
|
|
ShellGetTpContactCb callback)
|
|
|
|
{
|
|
|
|
tp_connection_get_contacts_by_handle(self, n_handles, handles,
|
|
|
|
n_features, features,
|
|
|
|
shell_global_get_tp_contacts_cb,
|
|
|
|
callback, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_global_get_self_contact_features_cb (TpConnection *connection,
|
|
|
|
guint n_contacts,
|
|
|
|
TpContact * const *contacts,
|
|
|
|
const GError *error,
|
|
|
|
gpointer user_data,
|
|
|
|
GObject *weak_object)
|
|
|
|
{
|
|
|
|
if (error != NULL) {
|
|
|
|
g_print ("Failed to upgrade self contact: %s", error->message);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
((ShellGetSelfContactFeaturesCb)user_data)(connection, *contacts);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_get_self_contact_features:
|
|
|
|
* @self: A connection, which must be ready
|
|
|
|
* @n_features: Number of features in features
|
|
|
|
* @features: (array length=n_features) (allow-none) (element-type uint):
|
|
|
|
* Array of features
|
|
|
|
* @callback: (scope async): User callback to run when the contact is ready
|
|
|
|
*
|
|
|
|
* Wrap tp_connection_upgrade_contacts due to the lack of support for
|
|
|
|
* proper arrays arguments in GJS.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
shell_get_self_contact_features (TpConnection *self,
|
|
|
|
guint n_features,
|
|
|
|
const TpContactFeature *features,
|
|
|
|
ShellGetSelfContactFeaturesCb callback)
|
|
|
|
{
|
|
|
|
TpContact *self_contact = tp_connection_get_self_contact (self);
|
|
|
|
|
|
|
|
tp_connection_upgrade_contacts (self, 1, &self_contact,
|
|
|
|
n_features, features,
|
|
|
|
shell_global_get_self_contact_features_cb,
|
|
|
|
callback, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_get_contact_events:
|
|
|
|
* @log_manager: A #TplLogManager
|
|
|
|
* @account: A #TpAccount
|
|
|
|
* @entity: A #TplEntity
|
|
|
|
* @num_events: The number of events to retrieve
|
|
|
|
* @callback: (scope async): User callback to run when the contact is ready
|
|
|
|
*
|
|
|
|
* Wrap tpl_log_manager_get_filtered_events_async because gjs cannot support
|
|
|
|
* multiple callbacks in the same function call.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
shell_get_contact_events (TplLogManager *log_manager,
|
|
|
|
TpAccount *account,
|
|
|
|
TplEntity *entity,
|
|
|
|
guint num_events,
|
|
|
|
GAsyncReadyCallback callback)
|
|
|
|
{
|
|
|
|
tpl_log_manager_get_filtered_events_async (log_manager,
|
|
|
|
account,
|
|
|
|
entity,
|
|
|
|
TPL_EVENT_MASK_TEXT,
|
|
|
|
num_events,
|
|
|
|
NULL, NULL,
|
|
|
|
callback, NULL);
|
|
|
|
}
|