Updated Portuguese translation
[empathy-mirror.git] / libempathy / empathy-chatroom-manager.c
blob3a117b18e85176c4eae84acc889db8a8aa98711d
1 /*
2 * Copyright (C) 2004-2007 Imendio AB
3 * Copyright (C) 2007-2010 Collabora Ltd.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301 USA
20 * Authors: Xavier Claessens <xclaesse@gmail.com>
21 * Martyn Russell <martyn@imendio.com>
24 #include "config.h"
25 #include "empathy-chatroom-manager.h"
27 #include <sys/stat.h>
28 #include <tp-account-widgets/tpaw-utils.h>
29 #include <telepathy-glib/telepathy-glib-dbus.h>
31 #include "empathy-client-factory.h"
32 #include "empathy-utils.h"
34 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
35 #include "empathy-debug.h"
37 #define CHATROOMS_XML_FILENAME "chatrooms.xml"
38 #define CHATROOMS_DTD_RESOURCENAME "/org/gnome/Empathy/empathy-chatroom-manager.dtd"
39 #define SAVE_TIMER 4
41 static EmpathyChatroomManager *chatroom_manager_singleton = NULL;
43 static void observe_channels_cb (TpSimpleObserver *observer,
44 TpAccount *account,
45 TpConnection *connection,
46 GList *channels,
47 TpChannelDispatchOperation *dispatch_operation,
48 GList *requests,
49 TpObserveChannelsContext *context,
50 gpointer user_data);
52 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyChatroomManager)
53 typedef struct
55 GList *chatrooms;
56 gchar *file;
57 TpAccountManager *account_manager;
59 /* source id of the autosave timer */
60 gint save_timer_id;
61 gboolean ready;
62 GFileMonitor *monitor;
63 gboolean writing;
65 TpBaseClient *observer;
66 } EmpathyChatroomManagerPriv;
68 enum {
69 CHATROOM_ADDED,
70 CHATROOM_REMOVED,
71 LAST_SIGNAL
74 static guint signals[LAST_SIGNAL];
76 /* properties */
77 enum
79 PROP_FILE = 1,
80 PROP_READY,
81 LAST_PROPERTY
84 G_DEFINE_TYPE (EmpathyChatroomManager, empathy_chatroom_manager, G_TYPE_OBJECT);
87 * API to save/load and parse the chatrooms file.
90 static gboolean
91 chatroom_manager_file_save (EmpathyChatroomManager *manager)
93 EmpathyChatroomManagerPriv *priv;
94 xmlDocPtr doc;
95 xmlNodePtr root;
96 GList *l;
98 priv = GET_PRIV (manager);
100 priv->writing = TRUE;
102 doc = xmlNewDoc ((const xmlChar *) "1.0");
103 root = xmlNewNode (NULL, (const xmlChar *) "chatrooms");
104 xmlDocSetRootElement (doc, root);
106 for (l = priv->chatrooms; l; l = l->next)
108 EmpathyChatroom *chatroom;
109 xmlNodePtr node;
110 const gchar *account_id;
112 chatroom = l->data;
114 if (!empathy_chatroom_is_favorite (chatroom))
115 continue;
117 account_id = tp_proxy_get_object_path (empathy_chatroom_get_account (
118 chatroom));
120 node = xmlNewChild (root, NULL, (const xmlChar *) "chatroom", NULL);
121 xmlNewTextChild (node, NULL, (const xmlChar *) "name",
122 (const xmlChar *) empathy_chatroom_get_name (chatroom));
123 xmlNewTextChild (node, NULL, (const xmlChar *) "room",
124 (const xmlChar *) empathy_chatroom_get_room (chatroom));
125 xmlNewTextChild (node, NULL, (const xmlChar *) "account",
126 (const xmlChar *) account_id);
127 xmlNewTextChild (node, NULL, (const xmlChar *) "auto_connect",
128 empathy_chatroom_get_auto_connect (chatroom) ?
129 (const xmlChar *) "yes" : (const xmlChar *) "no");
130 xmlNewTextChild (node, NULL, (const xmlChar *) "always_urgent",
131 empathy_chatroom_is_always_urgent (chatroom) ?
132 (const xmlChar *) "yes" : (const xmlChar *) "no");
135 /* Make sure the XML is indented properly */
136 xmlIndentTreeOutput = 1;
138 DEBUG ("Saving file:'%s'", priv->file);
139 xmlSaveFormatFileEnc (priv->file, doc, "utf-8", 1);
140 xmlFreeDoc (doc);
142 xmlMemoryDump ();
144 priv->writing = FALSE;
145 return TRUE;
148 static gboolean
149 save_timeout (EmpathyChatroomManager *self)
151 EmpathyChatroomManagerPriv *priv = GET_PRIV (self);
153 priv->save_timer_id = 0;
154 chatroom_manager_file_save (self);
156 return FALSE;
159 static void
160 reset_save_timeout (EmpathyChatroomManager *self)
162 EmpathyChatroomManagerPriv *priv = GET_PRIV (self);
164 if (priv->save_timer_id > 0)
165 g_source_remove (priv->save_timer_id);
167 priv->save_timer_id = g_timeout_add_seconds (SAVE_TIMER,
168 (GSourceFunc) save_timeout, self);
171 static void
172 chatroom_changed_cb (EmpathyChatroom *chatroom,
173 GParamSpec *spec,
174 EmpathyChatroomManager *self)
176 reset_save_timeout (self);
179 static void
180 add_chatroom (EmpathyChatroomManager *self,
181 EmpathyChatroom *chatroom)
183 EmpathyChatroomManagerPriv *priv = GET_PRIV (self);
185 priv->chatrooms = g_list_prepend (priv->chatrooms, g_object_ref (chatroom));
187 /* Watch only those properties which are exported in the save file */
188 g_signal_connect (chatroom, "notify::name",
189 G_CALLBACK (chatroom_changed_cb), self);
190 g_signal_connect (chatroom, "notify::room",
191 G_CALLBACK (chatroom_changed_cb), self);
192 g_signal_connect (chatroom, "notify::account",
193 G_CALLBACK (chatroom_changed_cb), self);
194 g_signal_connect (chatroom, "notify::auto-connect",
195 G_CALLBACK (chatroom_changed_cb), self);
196 g_signal_connect (chatroom, "notify::always_urgent",
197 G_CALLBACK (chatroom_changed_cb), self);
198 g_signal_connect (chatroom, "notify::favorite",
199 G_CALLBACK (chatroom_changed_cb), self);
202 static void
203 chatroom_manager_parse_chatroom (EmpathyChatroomManager *manager,
204 xmlNodePtr node)
206 EmpathyChatroom *chatroom = NULL;
207 TpAccount *account;
208 xmlNodePtr child;
209 gchar *str;
210 gchar *name;
211 gchar *room;
212 gchar *account_id;
213 gboolean auto_connect;
214 gboolean always_urgent;
215 EmpathyClientFactory *factory;
216 GError *error = NULL;
218 /* default values. */
219 name = NULL;
220 room = NULL;
221 auto_connect = TRUE;
222 always_urgent = FALSE;
223 account_id = NULL;
225 for (child = node->children; child; child = child->next)
227 gchar *tag;
229 if (xmlNodeIsText (child))
230 continue;
232 tag = (gchar *) child->name;
233 str = (gchar *) xmlNodeGetContent (child);
235 if (strcmp (tag, "name") == 0)
237 name = g_strdup (str);
239 else if (strcmp (tag, "room") == 0)
241 room = g_strdup (str);
243 else if (strcmp (tag, "auto_connect") == 0)
245 if (strcmp (str, "yes") == 0)
246 auto_connect = TRUE;
247 else
248 auto_connect = FALSE;
250 else if (!tp_strdiff (tag, "always_urgent"))
252 if (strcmp (str, "yes") == 0)
253 always_urgent = TRUE;
254 else
255 always_urgent = FALSE;
257 else if (strcmp (tag, "account") == 0)
259 account_id = g_strdup (str);
262 xmlFree (str);
265 /* account has to be a valid Account object path */
266 if (!tp_dbus_check_valid_object_path (account_id, NULL) ||
267 !g_str_has_prefix (account_id, TP_ACCOUNT_OBJECT_PATH_BASE))
268 goto out;
270 factory = empathy_client_factory_dup ();
272 account = tp_simple_client_factory_ensure_account (
273 TP_SIMPLE_CLIENT_FACTORY (factory), account_id, NULL, &error);
274 g_object_unref (factory);
276 if (account == NULL)
278 DEBUG ("Failed to create account: %s", error->message);
279 g_error_free (error);
281 g_free (name);
282 g_free (room);
283 g_free (account_id);
284 return;
287 chatroom = empathy_chatroom_new_full (account, room, name, auto_connect);
288 empathy_chatroom_set_favorite (chatroom, TRUE);
289 empathy_chatroom_set_always_urgent (chatroom, always_urgent);
290 add_chatroom (manager, chatroom);
291 g_signal_emit (manager, signals[CHATROOM_ADDED], 0, chatroom);
293 out:
294 g_free (name);
295 g_free (room);
296 g_free (account_id);
297 tp_clear_object (&chatroom);
300 static gboolean
301 chatroom_manager_file_parse (EmpathyChatroomManager *manager,
302 const gchar *filename)
304 EmpathyChatroomManagerPriv *priv;
305 xmlParserCtxtPtr ctxt;
306 xmlDocPtr doc;
307 xmlNodePtr chatrooms;
308 xmlNodePtr node;
310 priv = GET_PRIV (manager);
312 DEBUG ("Attempting to parse file:'%s'...", filename);
314 ctxt = xmlNewParserCtxt ();
316 /* Parse and validate the file. */
317 doc = xmlCtxtReadFile (ctxt, filename, NULL, 0);
318 if (doc == NULL)
320 g_warning ("Failed to parse file:'%s'", filename);
321 xmlFreeParserCtxt (ctxt);
322 return FALSE;
325 if (!tpaw_xml_validate_from_resource (doc, CHATROOMS_DTD_RESOURCENAME))
327 g_warning ("Failed to validate file:'%s'", filename);
328 xmlFreeDoc (doc);
329 xmlFreeParserCtxt (ctxt);
330 return FALSE;
333 /* The root node, chatrooms. */
334 chatrooms = xmlDocGetRootElement (doc);
336 for (node = chatrooms->children; node; node = node->next)
338 if (strcmp ((gchar *) node->name, "chatroom") == 0)
339 chatroom_manager_parse_chatroom (manager, node);
342 DEBUG ("Parsed %d chatrooms", g_list_length (priv->chatrooms));
344 xmlFreeDoc (doc);
345 xmlFreeParserCtxt (ctxt);
347 return TRUE;
350 static gboolean
351 chatroom_manager_get_all (EmpathyChatroomManager *manager)
353 EmpathyChatroomManagerPriv *priv;
355 priv = GET_PRIV (manager);
357 /* read file in */
358 if (g_file_test (priv->file, G_FILE_TEST_EXISTS) &&
359 !chatroom_manager_file_parse (manager, priv->file))
360 return FALSE;
362 if (!priv->ready)
364 priv->ready = TRUE;
365 g_object_notify (G_OBJECT (manager), "ready");
368 return TRUE;
371 static void
372 empathy_chatroom_manager_get_property (GObject *object,
373 guint property_id,
374 GValue *value,
375 GParamSpec *pspec)
377 EmpathyChatroomManager *self = EMPATHY_CHATROOM_MANAGER (object);
378 EmpathyChatroomManagerPriv *priv = GET_PRIV (self);
380 switch (property_id)
382 case PROP_FILE:
383 g_value_set_string (value, priv->file);
384 break;
385 case PROP_READY:
386 g_value_set_boolean (value, priv->ready);
387 break;
388 default:
389 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
390 break;
394 static void
395 empathy_chatroom_manager_set_property (GObject *object,
396 guint property_id,
397 const GValue *value,
398 GParamSpec *pspec)
400 EmpathyChatroomManager *self = EMPATHY_CHATROOM_MANAGER (object);
401 EmpathyChatroomManagerPriv *priv = GET_PRIV (self);
403 switch (property_id)
405 case PROP_FILE:
406 g_free (priv->file);
407 priv->file = g_value_dup_string (value);
408 break;
409 default:
410 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
411 break;
415 static void
416 chatroom_manager_dispose (GObject *object)
418 EmpathyChatroomManagerPriv *priv;
420 priv = GET_PRIV (object);
422 tp_clear_object (&priv->observer);
423 tp_clear_object (&priv->monitor);
425 (G_OBJECT_CLASS (empathy_chatroom_manager_parent_class)->dispose) (object);
428 static void
429 clear_chatrooms (EmpathyChatroomManager *self)
431 EmpathyChatroomManagerPriv *priv = GET_PRIV (self);
432 GList *l, *tmp;
434 tmp = priv->chatrooms;
436 /* Unreffing the chatroom may result in destroying the underlying
437 * EmpathyTpChat which will fire the invalidated signal and so make us
438 * re-call this function. We already set priv->chatrooms to NULL so we won't
439 * try to destroy twice the same objects. */
440 priv->chatrooms = NULL;
442 for (l = tmp; l != NULL; l = g_list_next (l))
444 EmpathyChatroom *chatroom = l->data;
446 g_signal_handlers_disconnect_by_func (chatroom, chatroom_changed_cb,
447 self);
448 g_signal_emit (self, signals[CHATROOM_REMOVED], 0, chatroom);
450 g_object_unref (chatroom);
453 g_list_free (tmp);
456 static void
457 chatroom_manager_finalize (GObject *object)
459 EmpathyChatroomManager *self = EMPATHY_CHATROOM_MANAGER (object);
460 EmpathyChatroomManagerPriv *priv;
462 priv = GET_PRIV (object);
464 g_object_unref (priv->account_manager);
466 if (priv->save_timer_id > 0)
468 /* have to save before destroy the object */
469 g_source_remove (priv->save_timer_id);
470 priv->save_timer_id = 0;
471 chatroom_manager_file_save (self);
474 clear_chatrooms (self);
476 g_free (priv->file);
478 (G_OBJECT_CLASS (empathy_chatroom_manager_parent_class)->finalize) (object);
481 static void
482 file_changed_cb (GFileMonitor *monitor,
483 GFile *file,
484 GFile *other_file,
485 GFileMonitorEvent event_type,
486 gpointer user_data)
488 EmpathyChatroomManager *self = user_data;
489 EmpathyChatroomManagerPriv *priv = GET_PRIV (self);
491 if (event_type != G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
492 return;
494 if (priv->writing)
495 return;
497 DEBUG ("chatrooms file changed; reloading list");
499 clear_chatrooms (self);
500 chatroom_manager_get_all (self);
503 static void
504 account_manager_ready_cb (GObject *source_object,
505 GAsyncResult *result,
506 gpointer user_data)
508 EmpathyChatroomManager *self = EMPATHY_CHATROOM_MANAGER (user_data);
509 EmpathyChatroomManagerPriv *priv = GET_PRIV (self);
510 TpAccountManager *manager = TP_ACCOUNT_MANAGER (source_object);
511 GError *error = NULL;
512 GFile *file = NULL;
514 if (!tp_proxy_prepare_finish (manager, result, &error))
516 DEBUG ("Failed to prepare account manager: %s", error->message);
517 g_error_free (error);
518 goto out;
521 chatroom_manager_get_all (self);
523 /* Set up file monitor */
524 file = g_file_new_for_path (priv->file);
526 priv->monitor = g_file_monitor (file, 0, NULL, &error);
527 if (priv->monitor == NULL)
529 DEBUG ("Failed to create file monitor on %s: %s", priv->file,
530 error->message);
532 g_error_free (error);
533 goto out;
536 g_signal_connect (priv->monitor, "changed", G_CALLBACK (file_changed_cb),
537 self);
539 out:
540 tp_clear_object (&file);
541 g_object_unref (self);
544 static GObject *
545 empathy_chatroom_manager_constructor (GType type,
546 guint n_props,
547 GObjectConstructParam *props)
549 GObject *obj;
550 EmpathyChatroomManager *self;
551 EmpathyChatroomManagerPriv *priv;
552 GError *error = NULL;
554 if (chatroom_manager_singleton != NULL)
555 return g_object_ref (chatroom_manager_singleton);
557 /* Parent constructor chain */
558 obj = G_OBJECT_CLASS (empathy_chatroom_manager_parent_class)->
559 constructor (type, n_props, props);
561 self = EMPATHY_CHATROOM_MANAGER (obj);
562 priv = GET_PRIV (self);
564 priv->ready = FALSE;
566 chatroom_manager_singleton = self;
567 g_object_add_weak_pointer (obj, (gpointer) &chatroom_manager_singleton);
569 priv->account_manager = tp_account_manager_dup ();
571 tp_proxy_prepare_async (priv->account_manager, NULL,
572 account_manager_ready_cb, g_object_ref (self));
574 if (priv->file == NULL)
576 /* Set the default file path */
577 gchar *dir;
579 dir = g_build_filename (g_get_user_config_dir (), PACKAGE_NAME, NULL);
580 if (!g_file_test (dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
581 g_mkdir_with_parents (dir, S_IRUSR | S_IWUSR | S_IXUSR);
583 priv->file = g_build_filename (dir, CHATROOMS_XML_FILENAME, NULL);
584 g_free (dir);
587 /* Setup a room observer */
588 priv->observer = tp_simple_observer_new_with_am (priv->account_manager, TRUE,
589 "Empathy.ChatroomManager", TRUE, observe_channels_cb, self, NULL);
591 tp_base_client_take_observer_filter (priv->observer, tp_asv_new (
592 TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
593 TP_IFACE_CHANNEL_TYPE_TEXT,
594 TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT,
595 TP_HANDLE_TYPE_ROOM,
596 NULL));
598 if (!tp_base_client_register (priv->observer, &error))
600 g_critical ("Failed to register Observer: %s", error->message);
602 g_error_free (error);
605 return obj;
608 static void
609 empathy_chatroom_manager_class_init (EmpathyChatroomManagerClass *klass)
611 GObjectClass *object_class = G_OBJECT_CLASS (klass);
612 GParamSpec *param_spec;
614 object_class->constructor = empathy_chatroom_manager_constructor;
615 object_class->get_property = empathy_chatroom_manager_get_property;
616 object_class->set_property = empathy_chatroom_manager_set_property;
617 object_class->dispose = chatroom_manager_dispose;
618 object_class->finalize = chatroom_manager_finalize;
620 param_spec = g_param_spec_string (
621 "file",
622 "path of the favorite file",
623 "The path of the XML file containing user's favorites",
624 NULL,
625 G_PARAM_CONSTRUCT_ONLY |
626 G_PARAM_READWRITE |
627 G_PARAM_STATIC_NAME |
628 G_PARAM_STATIC_NICK |
629 G_PARAM_STATIC_BLURB);
630 g_object_class_install_property (object_class, PROP_FILE, param_spec);
632 param_spec = g_param_spec_boolean (
633 "ready",
634 "whether the manager is ready yet",
635 "whether the manager is ready yet",
636 FALSE,
637 G_PARAM_READABLE);
638 g_object_class_install_property (object_class, PROP_READY, param_spec);
640 signals[CHATROOM_ADDED] = g_signal_new ("chatroom-added",
641 G_TYPE_FROM_CLASS (klass),
642 G_SIGNAL_RUN_LAST,
643 0, NULL, NULL,
644 g_cclosure_marshal_generic,
645 G_TYPE_NONE,
646 1, EMPATHY_TYPE_CHATROOM);
648 signals[CHATROOM_REMOVED] = g_signal_new ("chatroom-removed",
649 G_TYPE_FROM_CLASS (klass),
650 G_SIGNAL_RUN_LAST,
651 0, NULL, NULL,
652 g_cclosure_marshal_generic,
653 G_TYPE_NONE,
654 1, EMPATHY_TYPE_CHATROOM);
656 g_type_class_add_private (object_class, sizeof (EmpathyChatroomManagerPriv));
659 static void
660 empathy_chatroom_manager_init (EmpathyChatroomManager *manager)
662 EmpathyChatroomManagerPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (manager,
663 EMPATHY_TYPE_CHATROOM_MANAGER, EmpathyChatroomManagerPriv);
665 manager->priv = priv;
668 EmpathyChatroomManager *
669 empathy_chatroom_manager_dup_singleton (const gchar *file)
671 return EMPATHY_CHATROOM_MANAGER (g_object_new (EMPATHY_TYPE_CHATROOM_MANAGER,
672 "file", file, NULL));
675 gboolean
676 empathy_chatroom_manager_add (EmpathyChatroomManager *manager,
677 EmpathyChatroom *chatroom)
679 g_return_val_if_fail (EMPATHY_IS_CHATROOM_MANAGER (manager), FALSE);
680 g_return_val_if_fail (EMPATHY_IS_CHATROOM (chatroom), FALSE);
682 /* don't add more than once */
683 if (!empathy_chatroom_manager_find (manager,
684 empathy_chatroom_get_account (chatroom),
685 empathy_chatroom_get_room (chatroom)))
687 add_chatroom (manager, chatroom);
689 if (empathy_chatroom_is_favorite (chatroom))
690 reset_save_timeout (manager);
692 g_signal_emit (manager, signals[CHATROOM_ADDED], 0, chatroom);
693 return TRUE;
696 return FALSE;
699 static void
700 chatroom_manager_remove_link (EmpathyChatroomManager *manager,
701 GList *l)
703 EmpathyChatroomManagerPriv *priv;
704 EmpathyChatroom *chatroom;
706 priv = GET_PRIV (manager);
708 chatroom = l->data;
710 if (empathy_chatroom_is_favorite (chatroom))
711 reset_save_timeout (manager);
713 priv->chatrooms = g_list_delete_link (priv->chatrooms, l);
715 g_signal_emit (manager, signals[CHATROOM_REMOVED], 0, chatroom);
716 g_signal_handlers_disconnect_by_func (chatroom, chatroom_changed_cb, manager);
718 g_object_unref (chatroom);
721 void
722 empathy_chatroom_manager_remove (EmpathyChatroomManager *manager,
723 EmpathyChatroom *chatroom)
725 EmpathyChatroomManagerPriv *priv;
726 GList *l;
728 g_return_if_fail (EMPATHY_IS_CHATROOM_MANAGER (manager));
729 g_return_if_fail (EMPATHY_IS_CHATROOM (chatroom));
731 priv = GET_PRIV (manager);
733 for (l = priv->chatrooms; l; l = l->next)
735 EmpathyChatroom *this_chatroom;
737 this_chatroom = l->data;
739 if (this_chatroom == chatroom ||
740 empathy_chatroom_equal (chatroom, this_chatroom))
742 chatroom_manager_remove_link (manager, l);
743 break;
748 EmpathyChatroom *
749 empathy_chatroom_manager_find (EmpathyChatroomManager *manager,
750 TpAccount *account,
751 const gchar *room)
753 EmpathyChatroomManagerPriv *priv;
754 GList *l;
756 g_return_val_if_fail (EMPATHY_IS_CHATROOM_MANAGER (manager), NULL);
757 g_return_val_if_fail (room != NULL, NULL);
759 priv = GET_PRIV (manager);
761 for (l = priv->chatrooms; l; l = l->next)
763 EmpathyChatroom *chatroom;
764 TpAccount *this_account;
765 const gchar *this_room;
767 chatroom = l->data;
768 this_account = empathy_chatroom_get_account (chatroom);
769 this_room = empathy_chatroom_get_room (chatroom);
771 if (this_account && this_room && account == this_account
772 && strcmp (this_room, room) == 0)
773 return chatroom;
776 return NULL;
779 EmpathyChatroom *
780 empathy_chatroom_manager_ensure_chatroom (EmpathyChatroomManager *manager,
781 TpAccount *account,
782 const gchar *room,
783 const gchar *name)
785 EmpathyChatroom *chatroom;
787 chatroom = empathy_chatroom_manager_find (manager, account, room);
789 if (chatroom)
791 return g_object_ref (chatroom);
793 else
795 chatroom = empathy_chatroom_new_full (account,
796 room,
797 name,
798 FALSE);
799 empathy_chatroom_manager_add (manager, chatroom);
800 return chatroom;
804 GList *
805 empathy_chatroom_manager_get_chatrooms (EmpathyChatroomManager *manager,
806 TpAccount *account)
808 EmpathyChatroomManagerPriv *priv;
809 GList *chatrooms, *l;
811 g_return_val_if_fail (EMPATHY_IS_CHATROOM_MANAGER (manager), NULL);
813 priv = GET_PRIV (manager);
815 if (!account)
816 return g_list_copy (priv->chatrooms);
818 chatrooms = NULL;
819 for (l = priv->chatrooms; l; l = l->next)
821 EmpathyChatroom *chatroom;
823 chatroom = l->data;
825 if (account == empathy_chatroom_get_account (chatroom))
826 chatrooms = g_list_append (chatrooms, chatroom);
829 return chatrooms;
832 static void
833 chatroom_manager_chat_invalidated_cb (EmpathyTpChat *chat,
834 guint domain,
835 gint code,
836 gchar *message,
837 gpointer manager)
839 EmpathyChatroomManagerPriv *priv = GET_PRIV (manager);
840 GList *l;
842 for (l = priv->chatrooms; l; l = l->next)
844 EmpathyChatroom *chatroom = l->data;
846 if (empathy_chatroom_get_tp_chat (chatroom) != chat)
847 continue;
849 empathy_chatroom_set_tp_chat (chatroom, NULL);
851 if (!empathy_chatroom_is_favorite (chatroom))
853 /* Remove the chatroom from the list, unless it's in the list of
854 * favourites..
855 * FIXME this policy should probably not be in libempathy */
856 chatroom_manager_remove_link (manager, l);
859 break;
863 static void
864 observe_channels_cb (TpSimpleObserver *observer,
865 TpAccount *account,
866 TpConnection *connection,
867 GList *channels,
868 TpChannelDispatchOperation *dispatch_operation,
869 GList *requests,
870 TpObserveChannelsContext *context,
871 gpointer user_data)
873 EmpathyChatroomManager *self = user_data;
874 GList *l;
876 for (l = channels; l != NULL; l = g_list_next (l))
878 EmpathyTpChat *tp_chat = l->data;
879 const gchar *roomname;
880 EmpathyChatroom *chatroom;
882 if (tp_proxy_get_invalidated ((TpChannel *) tp_chat) != NULL)
883 continue;
885 if (!EMPATHY_IS_TP_CHAT (tp_chat))
886 continue;
888 roomname = empathy_tp_chat_get_id (tp_chat);
889 chatroom = empathy_chatroom_manager_find (self, account, roomname);
891 if (chatroom == NULL)
893 chatroom = empathy_chatroom_new_full (account, roomname, roomname,
894 FALSE);
895 empathy_chatroom_manager_add (self, chatroom);
896 g_object_unref (chatroom);
899 empathy_chatroom_set_tp_chat (chatroom, tp_chat);
901 g_signal_connect (tp_chat, "invalidated",
902 G_CALLBACK (chatroom_manager_chat_invalidated_cb),
903 self);
906 tp_observe_channels_context_accept (context);