* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Authors: Xavier Claessens <xclaesse@gmail.com>
*/
#include <telepathy-glib/channel.h>
#include <telepathy-glib/dbus.h>
-
-#include <libmissioncontrol/mission-control.h>
+#include <telepathy-glib/util.h>
+#include <telepathy-glib/interfaces.h>
#include "empathy-tp-roomlist.h"
#include "empathy-chatroom.h"
#include "empathy-utils.h"
-#include "empathy-debug.h"
#define DEBUG_FLAG EMPATHY_DEBUG_TP
#include "empathy-debug.h"
-#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
- EMPATHY_TYPE_TP_ROOMLIST, EmpathyTpRoomlistPriv))
-
-struct _EmpathyTpRoomlistPriv {
+#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyTpRoomlist)
+typedef struct {
TpConnection *connection;
TpChannel *channel;
- McAccount *account;
+ TpAccount *account;
gboolean is_listing;
-};
-
-static void empathy_tp_roomlist_class_init (EmpathyTpRoomlistClass *klass);
-static void empathy_tp_roomlist_init (EmpathyTpRoomlist *chat);
+ gboolean start_requested;
+} EmpathyTpRoomlistPriv;
enum {
NEW_ROOM,
DESTROY,
+ ERROR,
LAST_SIGNAL
};
enum {
PROP_0,
- PROP_CONNECTION,
+ PROP_ACCOUNT,
PROP_IS_LISTING,
};
g_object_notify (list, "is-listing");
}
+static void
+tp_roomlist_chatrooms_free (gpointer data)
+{
+ GSList *chatrooms = data;
+
+ g_slist_foreach (chatrooms, (GFunc) g_object_unref, NULL);
+ g_slist_free (chatrooms);
+}
+
+static void
+tp_roomlist_inspect_handles_cb (TpConnection *connection,
+ const gchar **names,
+ const GError *error,
+ gpointer user_data,
+ GObject *list)
+{
+ GSList *chatrooms = user_data;
+
+ if (error != NULL) {
+ DEBUG ("Error: %s", error->message);
+ return;
+ }
+
+ while (*names != NULL) {
+ EmpathyChatroom *chatroom = chatrooms->data;
+
+ empathy_chatroom_set_room (chatroom, *names);
+ g_signal_emit (list, signals[NEW_ROOM], 0, chatroom);
+
+ names++;
+ chatrooms = chatrooms->next;
+ }
+}
+
static void
tp_roomlist_got_rooms_cb (TpChannel *channel,
const GPtrArray *rooms,
GObject *list)
{
EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
+ EmpathyChatroom *chatroom;
guint i;
- const gchar **names;
- gchar **room_ids;
- GArray *handles;
+ GArray *handles = NULL;
+ GSList *chatrooms = NULL;
- names = g_new0 (const gchar*, rooms->len + 1);
- handles = g_array_sized_new (FALSE, FALSE, sizeof (guint), rooms->len);
for (i = 0; i < rooms->len; i++) {
const GValue *room_name_value;
+ const GValue *handle_name_value;
+ const GValue *room_members_value;
+ const GValue *room_subject_value;
+ const GValue *room_invite_value;
+ const GValue *room_password_value;
GValueArray *room_struct;
guint handle;
+ const gchar *channel_type;
GHashTable *info;
/* Get information */
room_struct = g_ptr_array_index (rooms, i);
handle = g_value_get_uint (g_value_array_get_nth (room_struct, 0));
+ channel_type = g_value_get_string (g_value_array_get_nth (room_struct, 1));
info = g_value_get_boxed (g_value_array_get_nth (room_struct, 2));
room_name_value = g_hash_table_lookup (info, "name");
-
- names[i] = g_value_get_string (room_name_value);
- g_array_append_val (handles, handle);
- }
-
- tp_cli_connection_run_inspect_handles (priv->connection, -1,
- TP_HANDLE_TYPE_ROOM,
- handles,
- &room_ids,
- NULL, NULL);
- for (i = 0; i < handles->len; i++) {
- EmpathyChatroom *chatroom;
-
- chatroom = empathy_chatroom_new_full (priv->account,
- room_ids[i],
- names[i],
- FALSE);
- g_signal_emit (list, signals[NEW_ROOM], 0, chatroom);
- g_object_unref (chatroom);
- g_free (room_ids[i]);
+ handle_name_value = g_hash_table_lookup (info, "handle-name");
+ room_subject_value = g_hash_table_lookup (info, "subject");
+ room_members_value = g_hash_table_lookup (info, "members");
+ room_invite_value = g_hash_table_lookup (info, "invite-only");
+ room_password_value = g_hash_table_lookup (info, "password");
+
+ if (tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TEXT)) {
+ continue;
+ }
+
+ chatroom = empathy_chatroom_new (priv->account);
+
+ if (room_name_value != NULL) {
+ empathy_chatroom_set_name (chatroom,
+ g_value_get_string (room_name_value));
+ }
+
+ if (room_members_value != NULL) {
+ empathy_chatroom_set_members_count (chatroom,
+ g_value_get_uint (room_members_value));
+ }
+
+ if (room_subject_value != NULL) {
+ empathy_chatroom_set_subject (chatroom,
+ g_value_get_string (room_subject_value));
+ }
+
+ if (room_invite_value != NULL) {
+ empathy_chatroom_set_invite_only (chatroom,
+ g_value_get_boolean (room_invite_value));
+ }
+
+ if (room_password_value != NULL) {
+ empathy_chatroom_set_need_password (chatroom,
+ g_value_get_boolean (room_password_value));
+ }
+
+ if (handle_name_value != NULL) {
+ empathy_chatroom_set_room (chatroom,
+ g_value_get_string (handle_name_value));
+
+ /* We have the room ID, we can directly emit it */
+ g_signal_emit (list, signals[NEW_ROOM], 0, chatroom);
+ g_object_unref (chatroom);
+ } else {
+ /* We don't have the room ID, we'll inspect all handles
+ * at once and then emit rooms */
+ if (handles == NULL) {
+ handles = g_array_new (FALSE, FALSE, sizeof (guint));
+ }
+
+ g_array_append_val (handles, handle);
+ chatrooms = g_slist_prepend (chatrooms, chatroom);
+ }
}
- g_free (names);
- g_free (room_ids);
- g_array_free (handles, TRUE);
+ if (handles != NULL) {
+ chatrooms = g_slist_reverse (chatrooms);
+ tp_cli_connection_call_inspect_handles (priv->connection, -1,
+ TP_HANDLE_TYPE_ROOM,
+ handles,
+ tp_roomlist_inspect_handles_cb,
+ chatrooms,
+ tp_roomlist_chatrooms_free,
+ list);
+ g_array_unref (handles);
+ }
}
static void
}
static void
-tp_roomlist_request_channel_cb (TpConnection *connection,
- const gchar *object_path,
- const GError *error,
- gpointer user_data,
- GObject *list)
+call_list_rooms_cb (TpChannel *proxy,
+ const GError *error,
+ gpointer list,
+ GObject *weak_object)
{
- EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
+ if (error != NULL) {
+ DEBUG ("Error listing rooms: %s", error->message);
+ g_signal_emit_by_name (list, "error::start", error);
+ }
+}
- if (error) {
- DEBUG ("Error requesting channel: %s", error->message);
- return;
+static void
+stop_listing_cb (TpChannel *proxy,
+ const GError *error,
+ gpointer list,
+ GObject *weak_object)
+{
+ if (error != NULL) {
+ DEBUG ("Error on stop listing: %s", error->message);
+ g_signal_emit_by_name (list, "error::stop", error);
}
+}
+
+static void
+tp_roomlist_create_channel_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ EmpathyTpRoomlist *self = user_data;
+ EmpathyTpRoomlistPriv *priv = GET_PRIV (self);
+ GError *error = NULL;
- priv->channel = tp_channel_new (priv->connection, object_path,
- TP_IFACE_CHANNEL_TYPE_ROOM_LIST,
- TP_HANDLE_TYPE_NONE,
- 0, NULL);
- tp_channel_run_until_ready (priv->channel, NULL, NULL);
+ priv->channel = tp_account_channel_request_create_and_handle_channel_finish (
+ TP_ACCOUNT_CHANNEL_REQUEST (source), result, NULL, &error);
+
+ if (priv->channel == NULL) {
+ DEBUG ("Error creating channel: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
g_signal_connect (priv->channel, "invalidated",
- G_CALLBACK (tp_roomlist_invalidated_cb),
- list);
+ G_CALLBACK (tp_roomlist_invalidated_cb), self);
tp_cli_channel_type_room_list_connect_to_listing_rooms (priv->channel,
tp_roomlist_listing_cb,
NULL, NULL,
- G_OBJECT (list),
+ G_OBJECT (self),
NULL);
tp_cli_channel_type_room_list_connect_to_got_rooms (priv->channel,
tp_roomlist_got_rooms_cb,
NULL, NULL,
- G_OBJECT (list),
+ G_OBJECT (self),
NULL);
tp_cli_channel_type_room_list_call_get_listing_rooms (priv->channel, -1,
tp_roomlist_get_listing_rooms_cb,
NULL, NULL,
- G_OBJECT (list));
+ G_OBJECT (self));
+
+ if (priv->start_requested == TRUE) {
+ tp_cli_channel_type_room_list_call_list_rooms (priv->channel, -1,
+ call_list_rooms_cb, self, NULL, G_OBJECT (self));
+ priv->start_requested = FALSE;
+ }
+
+out:
+ g_object_unref (self);
}
static void
tp_roomlist_constructed (GObject *list)
{
EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
- MissionControl *mc;
-
- mc = empathy_mission_control_new ();
- priv->account = mission_control_get_account_for_tpconnection (mc,
- priv->connection,
- NULL);
- g_object_unref (mc);
-
- tp_cli_connection_call_request_channel (priv->connection, -1,
- TP_IFACE_CHANNEL_TYPE_ROOM_LIST,
- TP_HANDLE_TYPE_NONE,
- 0,
- TRUE,
- tp_roomlist_request_channel_cb,
- NULL, NULL,
- list);
+ GHashTable *request;
+ TpAccountChannelRequest *req;
+
+ request = tp_asv_new (
+ TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
+ TP_IFACE_CHANNEL_TYPE_ROOM_LIST,
+ TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_NONE,
+ NULL);
+
+ priv->connection = tp_account_get_connection (priv->account);
+ g_object_ref (priv->connection);
+
+ req = tp_account_channel_request_new (priv->account, request,
+ TP_USER_ACTION_TIME_CURRENT_TIME);
+
+ /* Ensure we stay alive during the async call */
+ g_object_ref (list);
+
+ tp_account_channel_request_create_and_handle_channel_async (req, NULL,
+ tp_roomlist_create_channel_cb, list);
+
+ g_hash_table_unref (request);
+ g_object_unref (req);
}
static void
EmpathyTpRoomlistPriv *priv = GET_PRIV (object);
switch (param_id) {
- case PROP_CONNECTION:
- g_value_set_object (value, priv->connection);
+ case PROP_ACCOUNT:
+ g_value_set_object (value, priv->account);
break;
case PROP_IS_LISTING:
g_value_set_boolean (value, priv->is_listing);
EmpathyTpRoomlistPriv *priv = GET_PRIV (object);
switch (param_id) {
- case PROP_CONNECTION:
- priv->connection = g_object_ref (g_value_get_object (value));
+ case PROP_ACCOUNT:
+ priv->account = g_value_dup_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
object_class->set_property = tp_roomlist_set_property;
g_object_class_install_property (object_class,
- PROP_CONNECTION,
- g_param_spec_object ("connection",
- "The Connection",
- "The connection on which it lists rooms",
- TP_TYPE_CONNECTION,
+ PROP_ACCOUNT,
+ g_param_spec_object ("account",
+ "The Account",
+ "The account on which it lists rooms",
+ TP_TYPE_ACCOUNT,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
+ g_cclosure_marshal_generic,
G_TYPE_NONE,
1, EMPATHY_TYPE_CHATROOM);
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
+ g_cclosure_marshal_generic,
G_TYPE_NONE,
0);
+ signals[ERROR] =
+ g_signal_new ("error",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_NONE,
+ 1, G_TYPE_POINTER);
+
g_type_class_add_private (object_class, sizeof (EmpathyTpRoomlistPriv));
}
static void
empathy_tp_roomlist_init (EmpathyTpRoomlist *list)
{
+ EmpathyTpRoomlistPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (list,
+ EMPATHY_TYPE_TP_ROOMLIST, EmpathyTpRoomlistPriv);
+
+ list->priv = priv;
+ priv->start_requested = FALSE;
+ priv->is_listing = FALSE;
}
EmpathyTpRoomlist *
-empathy_tp_roomlist_new (McAccount *account)
+empathy_tp_roomlist_new (TpAccount *account)
{
EmpathyTpRoomlist *list;
- MissionControl *mc;
- TpConnection *connection;
-
- g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
-
- mc = empathy_mission_control_new ();
- connection = mission_control_get_tpconnection (mc, account, NULL);
list = g_object_new (EMPATHY_TYPE_TP_ROOMLIST,
- "connection", connection,
+ "account", account,
NULL);
- g_object_unref (mc);
- g_object_unref (connection);
-
return list;
}
EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
g_return_if_fail (EMPATHY_IS_TP_ROOMLIST (list));
- g_return_if_fail (TP_IS_CHANNEL (priv->channel));
-
- tp_cli_channel_type_room_list_call_list_rooms (priv->channel, -1,
- NULL, NULL, NULL,
- G_OBJECT (list));
+ if (priv->channel != NULL) {
+ tp_cli_channel_type_room_list_call_list_rooms (priv->channel, -1,
+ call_list_rooms_cb, list, NULL, NULL);
+ } else {
+ priv->start_requested = TRUE;
+ }
}
void
EmpathyTpRoomlistPriv *priv = GET_PRIV (list);
g_return_if_fail (EMPATHY_IS_TP_ROOMLIST (list));
+
+ if (priv->channel == NULL)
+ return;
+
g_return_if_fail (TP_IS_CHANNEL (priv->channel));
tp_cli_channel_type_room_list_call_stop_listing (priv->channel, -1,
- NULL, NULL, NULL,
- G_OBJECT (list));
+ stop_listing_cb, list, NULL, NULL);
}