Index: gui/main.c
===================================================================
--- gui/main.c (revision e6881d679c9940cd32cddd82948f638a97a8df98)
+++ gui/main.c (revision 3abed82be77c9f7efdc2dc5a20ca1e2d5672e3ff)
@@ -1054,4 +1054,19 @@
 }
 
+static void room_appeared(const char * opath, const char * name, const char * template)
+{
+  log_info("room \"%s\" appeared (%s). template is \"%s\"", name, opath, template);
+}
+
+static void room_disappeared(const char * opath, const char * name, const char * template)
+{
+  log_info("room \"%s\" disappeared (%s). template is \"%s\"", name, opath, template);
+}
+
+static void room_changed(const char * opath, const char * name, const char * template)
+{
+  log_info("%s changed. name is \"%s\". template is \"%s\"", opath, name, template);
+}
+
 void
 set_main_window_title(
@@ -1338,4 +1353,5 @@
 
   studio_proxy_set_renamed_callback(on_studio_renamed);
+  studio_proxy_set_room_callbacks(room_appeared, room_disappeared, room_changed);
 
   g_signal_connect(G_OBJECT(g_main_win), "destroy", G_CALLBACK(gtk_main_quit), NULL);
Index: proxies/studio_proxy.c
===================================================================
--- proxies/studio_proxy.c (revision 15350decd4777a2d9a9e21175b7d62307f235434)
+++ proxies/studio_proxy.c (revision 3abed82be77c9f7efdc2dc5a20ca1e2d5672e3ff)
@@ -3,5 +3,5 @@
  * LADI Session Handler (ladish)
  *
- * Copyright (C) 2009 Nedko Arnaudov <nedko@arnaudov.name>
+ * Copyright (C) 2009, 2010 Nedko Arnaudov <nedko@arnaudov.name>
  *
  **************************************************************************
@@ -33,4 +33,8 @@
 static void (* g_crashed_callback)(void) = NULL;
 
+static void (* g_room_appeared_calback)(const char * opath, const char * name, const char * template) = NULL;
+static void (* g_room_disappeared_calback)(const char * opath, const char * name, const char * template) = NULL;
+static void (* g_room_changed_calback)(const char * opath, const char * name, const char * template) = NULL;
+
 static void on_studio_renamed(void * context, DBusMessage * message_ptr)
 {
@@ -53,4 +57,43 @@
 }
 
+static bool extract_room_info(DBusMessageIter * iter_ptr, const char ** opath, const char ** name, const char ** template)
+{
+  dbus_message_iter_get_basic(iter_ptr, opath);
+  //log_info("opath is \"%s\"", *opath);
+  dbus_message_iter_next(iter_ptr);
+
+  if (!dbus_iter_get_dict_entry_string(iter_ptr, "name", name))
+  {
+    log_error("dbus_iter_get_dict_entry() failed");
+    return false;
+  }
+  //log_info("name is \"%s\"", *name);
+
+  if (!dbus_iter_get_dict_entry_string(iter_ptr, "template", template))
+  {
+    *template = NULL;
+  }
+  //log_info("template is \"%s\"", *template);
+
+  return true;
+}
+
+static bool extract_room_info_from_signal(DBusMessage * message_ptr, const char ** opath, const char ** name, const char ** template)
+{
+  const char * signature;
+  DBusMessageIter iter;
+
+  signature = dbus_message_get_signature(message_ptr);
+  if (strcmp(signature, "sa{sv}") != 0)
+  {
+    log_error("Invalid signature of room signal");
+    return false;
+  }
+
+  dbus_message_iter_init(message_ptr, &iter);
+
+  return extract_room_info(&iter, opath, name, template);
+}
+
 static void on_studio_started(void * context, DBusMessage * message_ptr)
 {
@@ -85,10 +128,42 @@
 static void on_room_appeared(void * context, DBusMessage * message_ptr)
 {
+  const char * opath;
+  const char * name;
+  const char * template;
+
   log_info("RoomAppeared");
+
+  if (g_room_appeared_calback != NULL && extract_room_info_from_signal(message_ptr, &opath, &name, &template))
+  {
+    g_room_appeared_calback(opath, name, template);
+  }
 }
 
 static void on_room_disappeared(void * context, DBusMessage * message_ptr)
 {
+  const char * opath;
+  const char * name;
+  const char * template;
+
   log_info("RoomDisappeared");
+
+  if (g_room_disappeared_calback != NULL && extract_room_info_from_signal(message_ptr, &opath, &name, &template))
+  {
+    g_room_disappeared_calback(opath, name, template);
+  }
+}
+
+static void on_room_changed(void * context, DBusMessage * message_ptr)
+{
+  const char * opath;
+  const char * name;
+  const char * template;
+
+  log_info("RoomChanged");
+
+  if (g_room_changed_calback != NULL && extract_room_info_from_signal(message_ptr, &opath, &name, &template))
+  {
+    g_room_changed_calback(opath, name, template);
+  }
 }
 
@@ -103,4 +178,5 @@
   {"RoomAppeared", on_room_appeared},
   {"RoomDisappeared", on_room_disappeared},
+  {"RoomChanged", on_room_changed},
   {NULL, NULL}
 };
@@ -201,2 +277,55 @@
   return true;
 }
+
+void
+studio_proxy_set_room_callbacks(
+  void (* appeared)(const char * opath, const char * name, const char * template),
+  void (* disappeared)(const char * opath, const char * name, const char * template),
+  void (* changed)(const char * opath, const char * name, const char * template))
+{
+  DBusMessage * reply_ptr;
+  const char * signature;
+  DBusMessageIter top_iter;
+  DBusMessageIter array_iter;
+  DBusMessageIter struct_iter;
+  const char * opath;
+  const char * name;
+  const char * template;
+
+  g_room_appeared_calback = appeared;
+  g_room_disappeared_calback = disappeared;
+  g_room_changed_calback = changed;
+
+  if (!dbus_call(SERVICE_NAME, STUDIO_OBJECT_PATH, IFACE_STUDIO, "GetRoomList", "", NULL, &reply_ptr))
+  {
+    log_error("Cannot fetch studio room list");
+    return;
+  }
+
+  signature = dbus_message_get_signature(reply_ptr);
+  if (strcmp(signature, "a(sa{sv})") != 0)
+  {
+    log_error("Invalid signature of GetRoomList reply");
+    goto unref;
+  }
+
+  dbus_message_iter_init(reply_ptr, &top_iter);
+
+  for (dbus_message_iter_recurse(&top_iter, &array_iter);
+       dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_INVALID;
+       dbus_message_iter_next(&array_iter))
+  {
+    dbus_message_iter_recurse(&array_iter, &struct_iter);
+
+    if (!extract_room_info(&struct_iter, &opath, &name, &template))
+    {
+      log_error("extract_room_info() failed.");
+      goto unref;
+    }
+
+    g_room_appeared_calback(opath, name, template);
+  }
+
+unref:
+  dbus_message_unref(reply_ptr);
+}
Index: proxies/studio_proxy.h
===================================================================
--- proxies/studio_proxy.h (revision 15350decd4777a2d9a9e21175b7d62307f235434)
+++ proxies/studio_proxy.h (revision 3abed82be77c9f7efdc2dc5a20ca1e2d5672e3ff)
@@ -3,5 +3,5 @@
  * LADI Session Handler (ladish)
  *
- * Copyright (C) 2009 Nedko Arnaudov <nedko@arnaudov.name>
+ * Copyright (C) 2009, 2010 Nedko Arnaudov <nedko@arnaudov.name>
  *
  **************************************************************************
@@ -45,3 +45,9 @@
 bool studio_proxy_is_started(bool * is_started_ptr);
 
+void
+studio_proxy_set_room_callbacks(
+  void (* appeared)(const char * opath, const char * name, const char * template),
+  void (* disappeared)(const char * opath, const char * name, const char * template),
+  void (* changed)(const char * opath, const char * name, const char * template));
+
 #endif /* #ifndef STUDIO_PROXY_H__2CEC623F_C998_4618_A947_D1A0016DF978__INCLUDED */
