diff --git a/hudson-sflphone-script.sh b/hudson-sflphone-script.sh
index 3f64d9334de143b27997c66270c91d7ebfdc93c9..412ea00cbd1cddf424f74096c1ad0616c8a52c24 100755
--- a/hudson-sflphone-script.sh
+++ b/hudson-sflphone-script.sh
@@ -16,6 +16,7 @@ pushd libs/pjproject
 make && make dep
 popd
 ./configure --prefix=/usr
+make clean
 make
 make doc
 popd
@@ -31,6 +32,7 @@ popd
 pushd sflphone-client-gnome
 ./autogen.sh
 ./configure --prefix=/usr
+make clean
 make
 popd
 
diff --git a/sflphone-client-gnome/src/actions.c b/sflphone-client-gnome/src/actions.c
index a787748a8132021f57d39209a0230bcd2adb4b13..d6c73039998f8fc6693fc6cc6bbfd45af0baace3 100644
--- a/sflphone-client-gnome/src/actions.c
+++ b/sflphone-client-gnome/src/actions.c
@@ -51,7 +51,8 @@
 #include <sys/ioctl.h>
 #include <linux/if.h>
 
-
+#include <widget/imwidget.h>
+#include <imwindow.h>
 
 GHashTable * ip2ip_profile=NULL;
 
@@ -199,8 +200,11 @@ sflphone_hung_up (callable_obj_t * c)
     call_remove_all_errors (c);
     update_actions();
 
-    /* Update the IM interface */
-    im_widget_update_state (c->_im_widget, FALSE);
+    // test wether the widget contain text, if not remove it
+    if ( (im_window_get_nb_tabs() > 1) && c->_im_widget && ! (IM_WIDGET (c->_im_widget)->containText))
+        im_window_remove_tab (c->_im_widget);
+    else
+        im_widget_update_state (IM_WIDGET (c->_im_widget), FALSE);
 
 #if GTK_CHECK_VERSION(2,10,0)
     status_tray_icon_blink (FALSE);
@@ -380,7 +384,13 @@ sflphone_hang_up()
                 call_remove_all_errors (selectedCall);
                 selectedCall->_state = CALL_STATE_DIALING;
                 set_timestamp (&selectedCall->_time_stop);
-                im_widget_update_state (selectedCall->_im_widget, FALSE);
+
+                //if ( (im_window_get_nb_tabs() > 1) && selectedCall->_im_widget &&
+                //        ! (IM_WIDGET (selectedCall->_im_widget)->containText))
+                //    im_window_remove_tab (selectedCall->_im_widget);
+                //else
+                im_widget_update_state (IM_WIDGET (selectedCall->_im_widget), FALSE);
+
                 break;
             case CALL_STATE_FAILURE:
                 dbus_hang_up (selectedCall);
@@ -404,6 +414,7 @@ sflphone_hang_up()
                 break;
         }
     } else if (selectedConf) {
+        im_widget_update_state (IM_WIDGET (selectedConf->_im_widget), FALSE);
         dbus_hang_up_conference (selectedConf);
     }
 
@@ -436,10 +447,20 @@ sflphone_pick_up()
         switch (selectedCall->_state) {
             case CALL_STATE_DIALING:
                 sflphone_place_call (selectedCall);
+
+                // if instant messaging window is visible, create new tab (deleted automatically if not used)
+                if (im_window_is_visible())
+                    im_widget_display ( (IMWidget **) (&selectedCall->_im_widget), NULL, selectedCall->_callID, NULL);
+
                 break;
             case CALL_STATE_INCOMING:
                 selectedCall->_history_state = INCOMING;
                 calltree_update_call (history, selectedCall, NULL);
+
+                // if instant messaging window is visible, create new tab (deleted automatically if not used)
+                if (im_window_is_visible())
+                    im_widget_display ( (IMWidget **) (&selectedCall->_im_widget), NULL, selectedCall->_callID, NULL);
+
                 dbus_accept (selectedCall);
                 DEBUG ("from sflphone_pick_up : ");
                 stop_notification();
@@ -972,6 +993,10 @@ sflphone_detach_participant (const gchar* callID)
             selectedCall->_confID = NULL;
         }
 
+        // Instant messaging widget should have been deactivated during the conference
+        if (selectedCall->_im_widget)
+            im_widget_update_state (IM_WIDGET (selectedCall->_im_widget), TRUE);
+
         calltree_remove_call (current_calls, selectedCall, NULL);
         calltree_add_call (current_calls, selectedCall, NULL);
         dbus_detach_participant (selectedCall->_callID);
@@ -984,6 +1009,10 @@ sflphone_detach_participant (const gchar* callID)
             selectedCall->_confID = NULL;
         }
 
+        // Instant messagin widget should have been deactivated during the conference
+        if (selectedCall->_im_widget)
+            im_widget_update_state (IM_WIDGET (selectedCall->_im_widget), TRUE);
+
         calltree_remove_call (current_calls, selectedCall, NULL);
         calltree_add_call (current_calls, selectedCall, NULL);
         dbus_detach_participant (callID);
diff --git a/sflphone-client-gnome/src/callable_obj.c b/sflphone-client-gnome/src/callable_obj.c
index f3cf8e9efee6b219d00081b8d46bc4474cb4162d..189c891ef8fbdd8c7a3be6f030721e627f5c8d8f 100644
--- a/sflphone-client-gnome/src/callable_obj.c
+++ b/sflphone-client-gnome/src/callable_obj.c
@@ -537,8 +537,6 @@ gchar*
 get_peer_information (callable_obj_t *c)
 {
 
-    gchar *res;
-
     if (g_strcasecmp (c->_peer_name,"") == 0)
         return g_strdup (c->_peer_number);
     else
diff --git a/sflphone-client-gnome/src/codeclist.c b/sflphone-client-gnome/src/codeclist.c
index 284bc21d8168c45719217169377f0558eacc7dd2..d6fcadb3c910296f2e32b715a04c9c6598afa6ee 100644
--- a/sflphone-client-gnome/src/codeclist.c
+++ b/sflphone-client-gnome/src/codeclist.c
@@ -105,7 +105,6 @@ void codec_capabilities_load (void)
 void account_create_codec_list (account_t **acc)
 {
 
-    gchar **order = NULL;
     GQueue *_codecs;
 
     _codecs = (*acc)->codecs;
diff --git a/sflphone-client-gnome/src/conference_obj.h b/sflphone-client-gnome/src/conference_obj.h
index edec21a7880ae38ad207da00753756949ff0c654..56b731f7c8489ec94ce56dc1a86e3a99eece6c7c 100644
--- a/sflphone-client-gnome/src/conference_obj.h
+++ b/sflphone-client-gnome/src/conference_obj.h
@@ -56,10 +56,11 @@ typedef enum {
 typedef struct  {
 
     conference_state_t _state;       // The state of the call
-    gchar* _confID;                  // The call ID
+    gchar *_confID;                  // The call ID
     gboolean _conference_secured;    // the security state of the conference
     gboolean _conf_srtp_enabled;     // security required for this conference
-    GSList* participant_list;             // participant list for this
+    GSList *participant_list;        // participant list for this
+    GtkWidget *_im_widget;           // associated instant messaging widget
 
 } conference_obj_t;
 
diff --git a/sflphone-client-gnome/src/config/accountconfigdialog.c b/sflphone-client-gnome/src/config/accountconfigdialog.c
index cb718fb473500e5948af916154f1cd0b95824779..9ab3de9e4f5a65df5d254e24df00564f398db074 100644
--- a/sflphone-client-gnome/src/config/accountconfigdialog.c
+++ b/sflphone-client-gnome/src/config/accountconfigdialog.c
@@ -31,6 +31,8 @@
  *  as that of the covered work.
  */
 
+
+
 #include <actions.h>
 #include <mainwindow.h>
 #include <accountlist.h>
@@ -74,7 +76,7 @@ GtkWidget * entryMailbox;
 GtkWidget * entryUseragent;
 GtkWidget * entryResolveNameOnlyOnce;
 GtkWidget * expireSpinBox;
-GtkListStore * credentialStore;
+GtkListStore * credentialStore = NULL;
 GtkWidget * deleteCredButton;
 GtkWidget * treeViewCredential;
 // GtkWidget * scrolledWindowCredential;
@@ -259,10 +261,15 @@ static GPtrArray* getNewCredential (GHashTable * properties)
 static void update_credential_cb (GtkWidget *widget, gpointer data UNUSED)
 {
     GtkTreeIter iter;
-    gtk_tree_model_get_iter_from_string ( (GtkTreeModel *) credentialStore, &iter, "0");
-    gint column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "column"));
-    // g_print ("set password to %s\n", (gchar *) gtk_entry_get_text(GTK_ENTRY(widget)));
-    gtk_list_store_set (GTK_LIST_STORE (credentialStore), &iter, column, (gchar *) gtk_entry_get_text (GTK_ENTRY (widget)), -1);
+
+    if (credentialStore) {
+        if (gtk_tree_model_get_iter_from_string ( (GtkTreeModel *) credentialStore, &iter, "0")) {
+            gint column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "column"));
+            // g_print ("set password to %s\n", (gchar *) gtk_entry_get_text(GTK_ENTRY(widget)));
+            gtk_list_store_set (GTK_LIST_STORE (credentialStore), &iter, column, (gchar *) gtk_entry_get_text (GTK_ENTRY (widget)), -1);
+        }
+    }
+
 }
 
 static GtkWidget* create_basic_tab (account_t **a)
@@ -1474,8 +1481,10 @@ void show_account_window (account_t * a)
         }
 
         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (overrtp))) {
+            DEBUG ("Config: Set dtmf over rtp");
             g_hash_table_replace (currentAccount->properties, g_strdup (ACCOUNT_DTMF_TYPE), g_strdup (OVERRTP));
         } else {
+            DEBUG ("Config: Set dtmf over sip");
             g_hash_table_replace (currentAccount->properties, g_strdup (ACCOUNT_DTMF_TYPE), g_strdup (SIPINFO));
         }
 
diff --git a/sflphone-client-gnome/src/config/audioconf.c b/sflphone-client-gnome/src/config/audioconf.c
index 6f767ea32ff912fb6e0f4bc0777307f768c4fdbc..7413c6047954919818591109d5e58f40ec84ee18 100644
--- a/sflphone-client-gnome/src/config/audioconf.c
+++ b/sflphone-client-gnome/src/config/audioconf.c
@@ -28,6 +28,7 @@
  *  as that of the covered work.
  */
 
+
 #include <audioconf.h>
 #include <utils.h>
 #include <string.h>
@@ -752,28 +753,6 @@ select_audio_manager (void)
 
 }
 
-void
-active_echo_cancel (void)
-{
-
-    gchar* state;
-    gchar* newstate;
-
-    DEBUG ("Audio: Active echo cancel clicked");
-    state = dbus_get_echo_cancel_state();
-
-    DEBUG ("Audio: Get echo cancel state %s", state);
-
-    if (strcmp (state, "enabled") == 0)
-        newstate = "disabled";
-    else
-        newstate = "enabled";
-
-    dbus_set_echo_cancel_state (newstate);
-
-}
-
-
 void
 active_noise_suppress (void)
 {
@@ -781,10 +760,10 @@ active_noise_suppress (void)
     gchar *state;
     gchar *newstate;
 
-    DEBUG ("Audio: Active noise suppress clicked");
+    DEBUG ("Audio: Active noise suppression clicked");
     state = dbus_get_noise_suppress_state();
 
-    DEBUG ("Audio: Get echo cancel state %s", state);
+    DEBUG ("Audio: Get noise suppression cancel state %s", state);
 
     if (strcmp (state, "enabled") == 0)
         newstate = "disabled";
@@ -919,9 +898,8 @@ GtkWidget* create_audio_configuration()
     GtkWidget *ret;
     // Sub boxes
     GtkWidget *frame;
-    GtkWidget *enableEchoCancel;
     GtkWidget *enableNoiseReduction;
-    gboolean echocancelActive, noisesuppressActive;
+    gboolean noisesuppressActive;
     gchar *state;
 
     ret = gtk_vbox_new (FALSE, 10);
@@ -988,19 +966,6 @@ GtkWidget* create_audio_configuration()
     gnome_main_section_new_with_table (_ ("Voice enhancement settings"), &frame, &table, 2, 1);
     gtk_box_pack_start (GTK_BOX (ret), frame, FALSE, FALSE, 0);
 
-    enableEchoCancel = gtk_check_button_new_with_mnemonic (_ ("_Echo Suppression"));
-    state = dbus_get_echo_cancel_state();
-    echocancelActive = FALSE;
-
-    if (strcmp (state, "enabled") == 0)
-        echocancelActive = TRUE;
-    else
-        echocancelActive = FALSE;
-
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (enableEchoCancel), echocancelActive);
-    g_signal_connect (G_OBJECT (enableEchoCancel), "clicked", active_echo_cancel, NULL);
-    gtk_table_attach (GTK_TABLE (table), enableEchoCancel, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
-
     enableNoiseReduction = gtk_check_button_new_with_mnemonic (_ ("_Noise Reduction"));
     state = dbus_get_noise_suppress_state();
     noisesuppressActive = FALSE;
diff --git a/sflphone-client-gnome/src/config/preferencesdialog.c b/sflphone-client-gnome/src/config/preferencesdialog.c
index 03a93e2ee37ec184c9c5ef59e9488bf8b67ca3a2..75bab7c8b91cccc9bad1ac524086c982ccf592f0 100644
--- a/sflphone-client-gnome/src/config/preferencesdialog.c
+++ b/sflphone-client-gnome/src/config/preferencesdialog.c
@@ -80,10 +80,13 @@ typedef struct {
     gint page_number;
 } browser_t;
 
-
+// history preference parameters
 static int history_limit;
 static gboolean history_enabled = TRUE;
 
+// instant messaging preference parameters
+static gboolean instant_messaging_enabled = TRUE;
+
 static void
 start_hidden (void)
 {
@@ -124,6 +127,14 @@ history_enabled_cb (GtkWidget *widget)
     eel_gconf_set_integer (HISTORY_ENABLED, !eel_gconf_get_integer (HISTORY_ENABLED));
 }
 
+static void
+instant_messaging_enabled_cb (GtkWidget *widget)
+{
+    instant_messaging_enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+
+    eel_gconf_set_integer (INSTANT_MESSAGING_ENABLED, !eel_gconf_get_integer (INSTANT_MESSAGING_ENABLED));
+}
+
 void
 clean_history (void)
 {
@@ -160,6 +171,9 @@ create_general_settings ()
     // Load history configuration
     history_load_configuration ();
 
+    // Load instant messaging configuration
+    instant_messaging_load_configuration();
+
     // Main widget
     ret = gtk_vbox_new (FALSE, 10);
     gtk_container_set_border_width (GTK_CONTAINER (ret), 10);
@@ -248,6 +262,18 @@ create_general_settings ()
     gtk_table_attach (GTK_TABLE (table), label, 2, 3, 0, 1, GTK_EXPAND | GTK_FILL,
                       GTK_EXPAND | GTK_FILL, 0, 5);
 
+    // INSTANT MESSAGING CONFIGURATION
+    gnome_main_section_new_with_table (_ ("Instant Messaging"), &frame, &table, 1, 1);
+    gtk_box_pack_start (GTK_BOX (ret), frame, FALSE, FALSE, 0);
+
+    checkBoxWidget = gtk_check_button_new_with_mnemonic (
+                         _ ("Enable instant messaging"));
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkBoxWidget),
+                                  instant_messaging_enabled);
+    g_signal_connect (G_OBJECT (checkBoxWidget) , "clicked" , G_CALLBACK (instant_messaging_enabled_cb) , NULL);
+    gtk_table_attach (GTK_TABLE (table), checkBoxWidget, 0, 1, 0, 1, GTK_EXPAND
+                      | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 5);
+
     gtk_widget_show_all (ret);
 
     return ret;
@@ -273,6 +299,14 @@ history_load_configuration ()
 {
     history_limit = dbus_get_history_limit ();
     history_enabled = eel_gconf_get_integer (HISTORY_ENABLED);
+
+}
+
+void
+instant_messaging_load_configuration ()
+{
+    instant_messaging_enabled = eel_gconf_get_integer (INSTANT_MESSAGING_ENABLED);
+
 }
 
 
@@ -402,7 +436,7 @@ GtkTreeModel* createModel()
 {
 
     browser_t browser_entries[5] = {
-        {_ ("General"), "start-here", 0},
+        {_ ("General"), "preferences-system", 0},
         {_ ("Audio"), "multimedia-volume-control", 1},
         {_ ("Address Book"), "address-book-new", 2},
         {_ ("Hooks"), "gnome-globe", 3},
diff --git a/sflphone-client-gnome/src/config/preferencesdialog.h b/sflphone-client-gnome/src/config/preferencesdialog.h
index c4a2a3f0be3036909f332490f96ab81afb8df3ed..c681e58be3d1fe056f1efcd969f6d6a72f075441 100644
--- a/sflphone-client-gnome/src/config/preferencesdialog.h
+++ b/sflphone-client-gnome/src/config/preferencesdialog.h
@@ -121,6 +121,8 @@ void save_configuration_parameters (void);
 
 void history_load_configuration (void);
 
+void instant_messaging_load_configuration (void);
+
 GtkTreeModel* createModel();
 
 #endif
diff --git a/sflphone-client-gnome/src/contacts/addressbook/eds.c b/sflphone-client-gnome/src/contacts/addressbook/eds.c
index 0678e473abd111b78fbc133e69014206230eb6f6..2046fa4cbb918ed487b160df6a39ffb7203a23ec 100644
--- a/sflphone-client-gnome/src/contacts/addressbook/eds.c
+++ b/sflphone-client-gnome/src/contacts/addressbook/eds.c
@@ -548,7 +548,8 @@ fill_books_data ()
             book_data->name = g_strdup (e_source_peek_name (source));
             book_data->uid = g_strdup (e_source_peek_uid (source));
 
-            gchar *prop = e_source_get_property (source, "default");
+            const gchar *property_name = "default";
+            const gchar *prop = e_source_get_property (source, property_name);
 
             if (prop)
                 if (strcmp (prop, "true") == 0)
diff --git a/sflphone-client-gnome/src/contacts/calltree.c b/sflphone-client-gnome/src/contacts/calltree.c
index d6e4a0341fde7142d8cb9298fd5d96fcff7b69cd..fc56c02f7fbd6ccd4a9474880a896b89310d833c 100644
--- a/sflphone-client-gnome/src/contacts/calltree.c
+++ b/sflphone-client-gnome/src/contacts/calltree.c
@@ -40,6 +40,7 @@
 #include <history.h>
 #include "uimanager.h"
 #include "actions.h"
+#include "../imwindow.h"
 
 GtkWidget *sw;
 GtkCellRenderer *rend;
@@ -130,6 +131,10 @@ call_selected_cb (GtkTreeSelection *sel, void* data UNUSED)
             selected_path = string_path;
             selected_call = NULL;
 
+            if (selected_conf->_im_widget) {
+                // show the coresponding widget
+                im_window_show_tab (selected_conf->_im_widget);
+            }
         }
 
         DEBUG ("CallTree: selected_path %s, selected_call_id %s, selected_path_depth %d",
@@ -152,6 +157,11 @@ call_selected_cb (GtkTreeSelection *sel, void* data UNUSED)
             selected_call_id = selected_call->_callID;
             selected_path = string_path;
             selected_conf = NULL;
+
+            if (selected_call->_im_widget) {
+                // show the coresponding widget
+                im_window_show_tab (selected_call->_im_widget);
+            }
         }
 
         DEBUG ("CallTree: selected_path %s, selected_call_id %s, selected_path_depth %d",
diff --git a/sflphone-client-gnome/src/contacts/searchbar.c b/sflphone-client-gnome/src/contacts/searchbar.c
index db416d659c1ebec6a4e7f09033ec88c660cf9397..5363ad496ec9cd7f84fce42e296949fee0dfbd55 100644
--- a/sflphone-client-gnome/src/contacts/searchbar.c
+++ b/sflphone-client-gnome/src/contacts/searchbar.c
@@ -39,7 +39,7 @@ GtkWidget * searchbox;
 GtkWidget * addressbookentry;
 
 GtkWidget * cbox;
-GtkListStore * liststore;
+GtkListStore * liststore = NULL;
 
 gint cboxSignalId;
 
@@ -109,7 +109,7 @@ void update_searchbar_addressbook_list()
             = book_list_iterator->next) {
         book_data = (book_data_t *) book_list_iterator->data;
 
-        if (book_data->active) {
+        if (book_data && book_data->active && activeText) {
 
             gtk_list_store_append (liststore, &iter);
             gtk_list_store_set (liststore, &iter, 0, book_data->name, -1);
diff --git a/sflphone-client-gnome/src/dbus/configurationmanager-introspec.xml b/sflphone-client-gnome/src/dbus/configurationmanager-introspec.xml
index c2818831f9e18520fe3bbfbe9c0982bd6a2133a2..f051f3b44bfb685a4408e18bf578024f49831f75 100755
--- a/sflphone-client-gnome/src/dbus/configurationmanager-introspec.xml
+++ b/sflphone-client-gnome/src/dbus/configurationmanager-introspec.xml
@@ -545,22 +545,6 @@
 		   </arg>
 	   </method>
 
-	   <method name="getEchoCancelState" tp:name-for-bindings="getEchoCancelState">
-	           <tp:docstring>
-	           </tp:docstring>
-	           <arg type="s" name="state" direction="out">
-		           <tp:docstring>
-			   </tp:docstring>
-	           </arg>
-	   </method>
-
-	   <method name="setEchoCancelState" tp:name-for-bindings="setEchoCancelState">
-	           <tp:docstring>
-		   </tp:docstring>
-		   <arg type="s" name="state" direction="in">
-		   </arg>
-	   </method>
-
            <method name="getNoiseSuppressState" tp:name-for-bindings="getNoiseSuppressState">
 	           <tp:docstring>
 		   </tp:docstring>
diff --git a/sflphone-client-gnome/src/dbus/dbus.c b/sflphone-client-gnome/src/dbus/dbus.c
index 1b5beb16a7cf2c31325ded46ba8661cfa4bb1f10..69354e26d7f606640728373521bdd144bad8d2dc 100644
--- a/sflphone-client-gnome/src/dbus/dbus.c
+++ b/sflphone-client-gnome/src/dbus/dbus.c
@@ -49,6 +49,8 @@
 
 #include <widget/imwidget.h>
 
+#include <eel-gconf-extensions.h>
+
 #define DEFAULT_DBUS_TIMEOUT 30000
 
 DBusGConnection * connection;
@@ -122,19 +124,38 @@ voice_mail_cb (DBusGProxy *proxy UNUSED, const gchar* accountID, const guint nb,
 static void
 incoming_message_cb (DBusGProxy *proxy UNUSED, const gchar* callID UNUSED, const gchar *from, const gchar* msg, void * foo  UNUSED)
 {
-    DEBUG ("Message %s!",msg);
+    DEBUG ("Message \"%s\" from %s!", msg, from);
 
-    // Get the call information. Does this call exist?
-    callable_obj_t * c = calllist_get (current_calls, callID);
+    callable_obj_t *call = NULL;
+    conference_obj_t *conf = NULL;
+
+    // do not display message if instant messaging is disabled
+    gboolean instant_messaging_enabled = TRUE;
+
+    if (eel_gconf_key_exists (INSTANT_MESSAGING_ENABLED))
+        instant_messaging_enabled = eel_gconf_get_integer (INSTANT_MESSAGING_ENABLED);
+
+    if (!instant_messaging_enabled)
+        return;
+
+    // Get the call information. (if this call exist)
+    call = calllist_get (current_calls, callID);
+
+    // Get the conference information (if this conference exist)
+    conf = conferencelist_get (callID);
 
     /* First check if the call is valid */
-    if (c) {
+    if (call) {
 
         /* Make the instant messaging main window pops, add messages only if the main window exist.
-        Elsewhere the message is displayed asynchronously*/
-        if (im_widget_display (&c, msg))
-            im_widget_add_message (c->_im_widget, get_peer_information (c), msg, 0);
-
+           Elsewhere the message is displayed asynchronously*/
+        if (im_widget_display ( (IMWidget **) (&call->_im_widget), msg, call->_callID, from))
+            im_widget_add_message (IM_WIDGET (call->_im_widget), from, msg, 0);
+    } else if (conf) {
+        /* Make the instant messaging main window pops, add messages only if the main window exist.
+           Elsewhere the message is displayed asynchronously*/
+        if (im_widget_display ( (IMWidget **) (&conf->_im_widget), msg, conf->_confID, from))
+            im_widget_add_message (IM_WIDGET (conf->_im_widget), from, msg, 0);
     } else {
         ERROR ("Message received, but no recipient found");
     }
@@ -218,9 +239,13 @@ conference_changed_cb (DBusGProxy *proxy UNUSED, const gchar* confID,
                        const gchar* state, void * foo  UNUSED)
 {
 
+    gchar** part;
+    callable_obj_t *call;
+    gchar* call_id;
+
     // sflphone_display_transfer_status("Transfer successfull");
     conference_obj_t* changed_conf = conferencelist_get (confID);
-    gchar** participants;
+    gchar** old_participants, new_participants;
 
     DEBUG ("conference new state %s\n", state);
 
@@ -239,10 +264,32 @@ conference_changed_cb (DBusGProxy *proxy UNUSED, const gchar* confID,
             DEBUG ("Error: conference state not recognized");
         }
 
-        participants = (gchar**) dbus_get_participant_list (changed_conf->_confID);
+        // reactivate instant messaging window for these calls
+        old_participants = (gchar**) changed_conf->participant_list;
+
+        for (part = old_participants; *part; part++) {
+            call_id = (gchar*) (*part);
+            call = calllist_get (current_calls, call_id);
+
+            if (call && call->_im_widget)
+                im_widget_update_state (IM_WIDGET (call->_im_widget), TRUE);
+        }
+
+        new_participants = (gchar **) dbus_get_participant_list (changed_conf->_confID);
 
         // update conferece participants
-        conference_participant_list_update (participants, changed_conf);
+        conference_participant_list_update (new_participants, changed_conf);
+
+        // deactivate instant messaging window for new participants
+        new_participants = (gchar**) changed_conf->participant_list;
+
+        for (part = new_participants; *part; part++) {
+            call_id = (gchar*) (*part);
+            call = calllist_get (current_calls, call_id);
+
+            if (call && call->_im_widget)
+                im_widget_update_state (IM_WIDGET (call->_im_widget), FALSE);
+        }
 
         // add new conference to calltree
         calltree_add_conference (current_calls, changed_conf);
@@ -271,6 +318,11 @@ conference_created_cb (DBusGProxy *proxy UNUSED, const gchar* confID, void * foo
     for (part = participants; *part; part++) {
         call_id = (gchar*) (*part);
         call = calllist_get (current_calls, call_id);
+
+        // if a text widget is already created, disable it, use conference widget instead
+        if (call->_im_widget)
+            im_widget_update_state (IM_WIDGET (call->_im_widget), FALSE);
+
         call->_confID = g_strdup (confID);
     }
 
@@ -289,6 +341,11 @@ conference_removed_cb (DBusGProxy *proxy UNUSED, const gchar* confID, void * foo
     GSList *participant = c->participant_list;
     callable_obj_t *call;
 
+    // deactivate instant messaging window for this conference
+    if (c->_im_widget)
+        im_widget_update_state (IM_WIDGET (c->_im_widget), FALSE);
+
+    // remove all participant for this conference
     while (participant) {
 
         call = calllist_get (current_calls, (const gchar *) (participant->data));
@@ -300,6 +357,10 @@ conference_removed_cb (DBusGProxy *proxy UNUSED, const gchar* confID, void * foo
                 g_free (call->_confID);
                 call->_confID = NULL;
             }
+
+            // if an instant messaging was previously disabled, enabled it
+            if (call->_im_widget)
+                im_widget_update_state (IM_WIDGET (call->_im_widget), TRUE);
         }
 
         participant = conference_next_participant (participant);
@@ -1404,40 +1465,6 @@ dbus_get_current_audio_output_plugin()
     return plugin;
 }
 
-/**
- * Get echo canceller state
- */
-gchar*
-dbus_get_echo_cancel_state()
-{
-    gchar* state = "";
-    GError* error = NULL;
-    org_sflphone_SFLphone_ConfigurationManager_get_echo_cancel_state (configurationManagerProxy, &state, &error);
-
-    if (error) {
-        ERROR ("DBus: Failed to call get_echo_cancel_state() on ConfigurationManager: %s", error->message);
-        g_error_free (error);
-    }
-
-    return state;
-}
-
-/**
- * Set echo canceller state
- */
-void
-dbus_set_echo_cancel_state (gchar* state)
-{
-    GError* error = NULL;
-    org_sflphone_SFLphone_ConfigurationManager_set_echo_cancel_state (
-        configurationManagerProxy, state, &error);
-
-    if (error) {
-        ERROR ("Failed to call set_echo_cancel_state() on ConfigurationManager: %s", error->message);
-        g_error_free (error);
-    }
-}
-
 
 /**
  * Get noise reduction state
@@ -1458,7 +1485,7 @@ dbus_get_noise_suppress_state()
 }
 
 /**
- * Set echo canceller state
+ * Set noise reduction state
  */
 void
 dbus_set_noise_suppress_state (gchar* state)
@@ -1958,10 +1985,10 @@ dbus_get_conference_list (void)
 }
 
 gchar**
-dbus_get_participant_list (const char *confID)
+dbus_get_participant_list (const gchar *confID)
 {
     GError *error = NULL;
-    gchar **list = NULL;
+    char **list = NULL;
 
     DEBUG ("DBUS: Get conference %s participant list", confID);
 
diff --git a/sflphone-client-gnome/src/dbus/dbus.h b/sflphone-client-gnome/src/dbus/dbus.h
index 99dce013df8db99d36ef8a262c3c72fded03a5c5..38f1bfc47aef81420bd30da177d41b7042bb6469 100644
--- a/sflphone-client-gnome/src/dbus/dbus.h
+++ b/sflphone-client-gnome/src/dbus/dbus.h
@@ -250,6 +250,13 @@ gchar* dbus_get_current_codec_name (const callable_obj_t * c);
  */
 gchar** dbus_get_audio_plugin_list();
 
+
+/**
+ * ConfigurationManager - Select an input audio plugin
+ * @param audioPlugin The string description of the plugin
+ */
+void dbus_set_audio_plugin (gchar* audioPlugin);
+
 /**
  * ConfigurationManager - Select an input audio plugin
  * @param audioPlugin The string description of the plugin
@@ -308,19 +315,6 @@ int dbus_get_audio_device_index (const gchar* name);
  */
 gchar* dbus_get_current_audio_output_plugin();
 
-
-/**
- * ConfigurationManager - Get the current state of echo canceller
- * @return gchar* The state (enabled/disabled)
- */
-gchar *dbus_get_echo_cancel_state (void);
-
-/**
- * ConfigurationManager - Set the crrent state of echo canceller
- * @param gchar* The state (enabled/disabled)
- */
-void dbus_set_echo_cancel_state (gchar *state);
-
 /**
  * ConfigurationManager - Get the current noise suppressor state
  * @return gchar* The state (enabled/disabled)
@@ -435,11 +429,30 @@ void dbus_set_sip_address (const gchar* address);
 
 gint dbus_get_sip_address (void);
 
+
+/**
+ * Add a participant (callID) to this conference (confID)
+ */
 void dbus_add_participant (const gchar* callID, const gchar* confID);
 
+/**
+ * Return a list of participant for this conference (confID)
+ */
+gchar** dbus_get_participant_list (const gchar *confID);
+
+/**
+ * Toggle recording for this instance, may be call or conference
+ */
 void dbus_set_record (const gchar * id);
 
+/**
+ * Set the path where the recorded audio files will be stored
+ */
 void dbus_set_record_path (const gchar *path);
+
+/**
+ * Get the path where the recorded audio files are stored
+ */
 gchar* dbus_get_record_path (void);
 
 /**
@@ -539,9 +552,8 @@ void dbus_set_confirm_go_clear (const callable_obj_t * c);
  */
 gchar** dbus_get_supported_tls_method();
 
-gchar** dbus_get_participant_list (const char * confID);
-
 GHashTable* dbus_get_shortcuts (void);
+
 void dbus_set_shortcuts (GHashTable * shortcuts);
 
 void dbus_set_audio_ringtone_device (const int index);
diff --git a/sflphone-client-gnome/src/imwindow.c b/sflphone-client-gnome/src/imwindow.c
index 881e092e8800560e39cbec945d52351bdbf91d14..e9bb916c1f3938d08aa050b26482c7f3132e4940 100644
--- a/sflphone-client-gnome/src/imwindow.c
+++ b/sflphone-client-gnome/src/imwindow.c
@@ -37,12 +37,13 @@
 
 #include <imwindow.h>
 #include <contacts/calltab.h>
+#include <contacts/calltab.h>
 
 /** Local variables */
 GtkWidget *im_window = NULL;
 GtkWidget *im_notebook = NULL;
 
-static gboolean window_configure_cb (GtkWidget *win, GdkEventConfigure *event)
+static gboolean window_configure_cb (GtkWidget *wini UNUSED, GdkEventConfigure *event)
 {
     int pos_x, pos_y;
 
@@ -68,7 +69,7 @@ on_delete (GtkWidget * widget UNUSED, gpointer data UNUSED)
 }
 
 static void
-on_switch_page (GtkNotebook *notebook, GtkNotebookPage *page, guint page_num, gpointer userdata)
+on_switch_page (GtkNotebook *notebook, GtkNotebookPage *page UNUSED, guint page_num, gpointer userdata UNUSED)
 {
     guint index = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook));
 
@@ -85,9 +86,6 @@ static void
 im_window_init()
 {
     const char *window_title = "SFLphone IM Client";
-    gchar *path;
-    GError *error = NULL;
-    gboolean ret;
     int width, height, position_x, position_y;
 
     // Get configuration stored in gconf
@@ -140,10 +138,27 @@ im_window_get()
     return im_window;
 }
 
+
+gboolean
+im_window_is_active ()
+{
+
+    if (!im_window)
+        return FALSE;
+    else
+        return gtk_window_is_active (im_window);
+}
+
+gboolean
+im_window_is_visible ()
+{
+    return gtk_widget_get_visible (im_window);
+}
+
 void
 im_window_show ()
 {
-    gtk_widget_show (im_window_get ());
+    gtk_window_present (GTK_WINDOW (im_window_get ()));
 }
 
 void
@@ -156,11 +171,20 @@ im_window_add (GtkWidget *widget)
         /* Show it all */
         gtk_widget_show_all (im_window);
     } else
-        error ("Could not create the main instant messaging window");
+        ERROR ("Could not create the main instant messaging window");
+}
+
+gint
+im_window_get_nb_tabs()
+{
+    if (im_notebook)
+        return gtk_notebook_get_n_pages (im_notebook);
+    else
+        return 0;
 }
 
 static void
-close_tab_cb (GtkButton *button, gpointer userdata)
+close_tab_cb (GtkButton *button UNUSED, gpointer userdata)
 {
     /* We want here to close the current tab */
     im_window_remove_tab (GTK_WIDGET (userdata));
@@ -177,10 +201,20 @@ im_window_add_tab (GtkWidget *widget)
 
     /* Fetch the call */
     callable_obj_t *im_widget_call = calllist_get (current_calls, im->call_id);
+    conference_obj_t *im_widget_conf = conferencelist_get (im->call_id);
 
     /* A container to include the tab label and the close button */
     GtkWidget *tab_Container = gtk_hbox_new (FALSE, 3);
-    GtkWidget *tab_Label = gtk_label_new (get_peer_information (im_widget_call));
+    GtkWidget *tab_Label;
+    im->tab = tab_Container;
+
+    if (im_widget_call)
+        tab_Label = gtk_label_new (get_peer_information (im_widget_call));
+    else if (im_widget_conf)
+        tab_Label = gtk_label_new ("Conferencing");
+    else
+        tab_Label = gtk_label_new ("");
+
     GtkWidget *tab_CloseButton = gtk_button_new ();
 
     /* Pack it all */
@@ -218,6 +252,15 @@ im_window_hide_show_tabs ()
 
 }
 
+void
+im_window_show_tab (GtkWidget *widget)
+{
+    int pageIndex = gtk_notebook_page_num (GTK_NOTEBOOK (im_notebook), widget);
+
+    if (pageIndex != -1)
+        gtk_notebook_set_current_page (GTK_NOTEBOOK (im_notebook), pageIndex);
+}
+
 void
 im_window_remove_tab (GtkWidget *widget)
 {
@@ -230,10 +273,14 @@ im_window_remove_tab (GtkWidget *widget)
     /* Need to do some memory clean up, so that we could re-open an Im widget for this call later. */
     IMWidget *im = IM_WIDGET (widget);
     callable_obj_t *call = calllist_get (current_calls, im->call_id);
+    conference_obj_t *conf = conferencelist_get (im->call_id);
 
     if (call)
         call->_im_widget = NULL;
 
+    if (conf)
+        conf->_im_widget = NULL;
+
     /* Decide whether or not displaying the tabs of the notebook */
     im_window_hide_show_tabs ();
 }
diff --git a/sflphone-client-gnome/src/imwindow.h b/sflphone-client-gnome/src/imwindow.h
index 028efc677a74d280d057d9c7ec4aac3c80d63107..f0d1de2e0774a4da3eb11345c69952cd2084cc40 100644
--- a/sflphone-client-gnome/src/imwindow.h
+++ b/sflphone-client-gnome/src/imwindow.h
@@ -60,6 +60,21 @@ void im_window_remove_tab (GtkWidget *widget);
 
 void im_window_show ();
 
+/**
+ * Return wether the instant messaging window have been created or not
+ */
+gboolean im_window_is_active (void);
+
+/**
+ * Return wether the instant messaging window is visible
+ */
+gboolean im_window_is_visible (void);
+
+/**
+ * Return the number of tabs already open in instant messaging window
+ */
+gint im_window_get_nb_tabs (void);
+
 /*! @function
 @abstract	Add a new tab in the notebook. Each tab is an IM Widget
 @param		The IM widget
@@ -71,4 +86,10 @@ void im_window_add_tab (GtkWidget *widget);
 */
 void im_window_hide_show_tabs ();
 
+/*! @function
+@abstract Select the specified tab as current in instant messaging window
+@param The tab to be set as current
+*/
+void im_window_show_tab (GtkWidget *widget);
+
 #endif
diff --git a/sflphone-client-gnome/src/sflnotify.c b/sflphone-client-gnome/src/sflnotify.c
index 76de2d319460f15a9e9f950d32e51467373ec805..b90586c280f17d010a8448c7c296057b120cfce8 100644
--- a/sflphone-client-gnome/src/sflnotify.c
+++ b/sflphone-client-gnome/src/sflnotify.c
@@ -72,7 +72,6 @@ void
 notify_incoming_message (const gchar *callID, const gchar *msg)
 {
 
-    gchar* text;
     gchar* title;
 
     title = g_markup_printf_escaped (_ ("%s says:"), callID);
diff --git a/sflphone-client-gnome/src/sflphone_const.h b/sflphone-client-gnome/src/sflphone_const.h
index 034a40bb44bbdccc3f750f41a4b67b9f984558a3..fb74d0219806158340bacdb909a109cbe5a9525f 100644
--- a/sflphone-client-gnome/src/sflphone_const.h
+++ b/sflphone-client-gnome/src/sflphone_const.h
@@ -194,5 +194,6 @@
 #define START_HIDDEN				CONF_PREFIX "/state/start_hidden"
 #define POPUP_ON_CALL				CONF_PREFIX "/state/popup"
 #define HISTORY_ENABLED				CONF_PREFIX "/state/history"
+#define INSTANT_MESSAGING_ENABLED               CONF_PREFIX "/state/instant_messaging"
 
 #endif
diff --git a/sflphone-client-gnome/src/uimanager.c b/sflphone-client-gnome/src/uimanager.c
index 6fa9319b6a2c9b4831ce802c0cc88f5a78822d81..d896db30dd2c3b638df1d7054ffa3349b15140c2 100644
--- a/sflphone-client-gnome/src/uimanager.c
+++ b/sflphone-client-gnome/src/uimanager.c
@@ -191,6 +191,11 @@ update_actions()
     callable_obj_t * selectedCall = calltab_get_selected_call (active_calltree);
     conference_obj_t * selectedConf = calltab_get_selected_conf (active_calltree);
 
+    gboolean instant_messaging_enabled = TRUE;
+
+    if (eel_gconf_key_exists (INSTANT_MESSAGING_ENABLED))
+        instant_messaging_enabled = eel_gconf_get_integer (INSTANT_MESSAGING_ENABLED);
+
     if (selectedCall) {
         // update icon in systray
         show_status_hangup_icon();
@@ -215,11 +220,16 @@ update_actions()
                 gtk_widget_set_sensitive (GTK_WIDGET (holdMenu), TRUE);
                 gtk_widget_set_sensitive (GTK_WIDGET (offHoldToolbar), TRUE);
                 gtk_widget_set_sensitive (GTK_WIDGET (newCallWidget), TRUE);
+
                 // Replace the hold button with the off-hold button
-                gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (hangUpWidget),
-                                    1);
-                gtk_toolbar_insert (GTK_TOOLBAR (toolbar),
-                                    GTK_TOOL_ITEM (offHoldToolbar), 2);
+                gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (hangUpWidget), 1);
+                gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (offHoldToolbar), 2);
+
+                if (instant_messaging_enabled) {
+                    gtk_action_set_sensitive (GTK_ACTION (imAction), TRUE);
+                    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (imToolbar), 3);
+                }
+
                 break;
             case CALL_STATE_RINGING:
                 gtk_action_set_sensitive (GTK_ACTION (pickUpAction), TRUE);
@@ -250,21 +260,21 @@ update_actions()
                 gtk_widget_set_sensitive (GTK_WIDGET (holdToolbar), TRUE);
                 gtk_widget_set_sensitive (GTK_WIDGET (transferToolbar), TRUE);
                 gtk_action_set_sensitive (GTK_ACTION (recordAction), TRUE);
-                gtk_action_set_sensitive (GTK_ACTION (imAction), TRUE);
-                gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (holdToolbar),
-                                    2);
-                gtk_toolbar_insert (GTK_TOOLBAR (toolbar),
-                                    GTK_TOOL_ITEM (transferToolbar), 3);
-                gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (recordWidget),
-                                    4);
-                gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (imToolbar),
-                                    5);
+                gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (holdToolbar), 2);
+                gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (transferToolbar), 3);
+                gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (recordWidget), 4);
                 gtk_signal_handler_block (GTK_OBJECT (transferToolbar), transfertButtonConnId);
                 gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (transferToolbar), FALSE);
                 gtk_signal_handler_unblock (transferToolbar, transfertButtonConnId);
                 g_signal_handler_block (GTK_OBJECT (recordWidget), recordButtonConnId);
                 gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (recordWidget), FALSE);
                 g_signal_handler_unblock (GTK_OBJECT (recordWidget), recordButtonConnId);
+
+                if (instant_messaging_enabled) {
+                    gtk_action_set_sensitive (GTK_ACTION (imAction), TRUE);
+                    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (imToolbar), 5);
+                }
+
                 break;
 
             case CALL_STATE_RECORD:
@@ -284,6 +294,12 @@ update_actions()
                 g_signal_handler_block (GTK_OBJECT (recordWidget), recordButtonConnId);
                 gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (recordWidget), TRUE);
                 g_signal_handler_unblock (GTK_OBJECT (recordWidget), recordButtonConnId);
+
+                if (instant_messaging_enabled) {
+                    gtk_action_set_sensitive (GTK_ACTION (imAction), TRUE);
+                    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (imToolbar), 5);
+                }
+
                 break;
             case CALL_STATE_BUSY:
             case CALL_STATE_FAILURE:
@@ -319,6 +335,12 @@ update_actions()
                 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (hangUpWidget), 1);
                 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (holdToolbar), 2);
                 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (recordWidget), 3);
+
+                if (instant_messaging_enabled) {
+                    gtk_action_set_sensitive (GTK_ACTION (imAction), TRUE);
+                    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (imToolbar), 4);
+                }
+
                 break;
 
             case CONFERENCE_STATE_ACTIVE_DETACHED:
@@ -328,6 +350,12 @@ update_actions()
                 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (hangUpWidget), 1);
                 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (holdToolbar), 2);
                 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (recordWidget), 3);
+
+                if (instant_messaging_enabled) {
+                    gtk_action_set_sensitive (GTK_ACTION (imAction), TRUE);
+                    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (imToolbar), 4);
+                }
+
                 break;
 
             case CONFERENCE_STATE_RECORD:
@@ -338,6 +366,12 @@ update_actions()
                 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (hangUpWidget), 1);
                 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (holdToolbar), 2);
                 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (recordWidget), 3);
+
+                if (instant_messaging_enabled) {
+                    gtk_action_set_sensitive (GTK_ACTION (imAction), TRUE);
+                    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (imToolbar), 4);
+                }
+
                 break;
 
             case CONFERENCE_STATE_HOLD:
@@ -347,6 +381,12 @@ update_actions()
                 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (hangUpWidget), 1);
                 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (offHoldToolbar), 2);
                 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (recordWidget), 3);
+
+                if (instant_messaging_enabled) {
+                    gtk_action_set_sensitive (GTK_ACTION (imAction), TRUE);
+                    gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (imToolbar), 4);
+                }
+
                 break;
 
             default:
@@ -534,12 +574,22 @@ call_hold (void* foo UNUSED)
 static void
 call_im (void* foo UNUSED)
 {
-    callable_obj_t * selectedCall = calltab_get_selected_call (current_calls);
+    callable_obj_t *selectedCall = calltab_get_selected_call (current_calls);
+    conference_obj_t *selectedConf = calltab_get_selected_conf();
 
-    if (selectedCall) {
-        im_widget_display (&selectedCall, NULL);
+    if (calltab_get_selected_type (current_calls) == A_CALL) {
+
+        if (selectedCall) {
+            im_widget_display ( (IMWidget **) (&selectedCall->_im_widget), NULL, selectedCall->_callID, NULL);
+        } else {
+            WARN ("Sorry. Instant messaging is not allowed outside a call\n");
+        }
     } else {
-        warn ("Sorry. Instant messaging is not allowed outside a call\n");
+        if (selectedConf) {
+            im_widget_display ( (IMWidget **) (&selectedConf->_im_widget), NULL, selectedConf->_confID, NULL);
+        } else {
+            WARN ("Sorry. Instant messaging is not allowed outside a call\n");
+        }
     }
 }
 
@@ -1191,18 +1241,28 @@ show_popup_menu (GtkWidget *my_widget, GdkEventButton *event)
         }
 
         if (im) {
-            menu_items = gtk_separator_menu_item_new();
-            gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items);
-            gtk_widget_show (menu_items);
 
-            menu_items = gtk_image_menu_item_new_with_mnemonic (_ ("Send _message"));
-            image = gtk_image_new_from_stock (GTK_STOCK_IM, GTK_ICON_SIZE_MENU);
-            gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_items), image);
-            gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items);
-            g_signal_connect (G_OBJECT (menu_items), "activate",
-                              G_CALLBACK (call_im),
-                              NULL);
-            gtk_widget_show (menu_items);
+            // do not display message if instant messaging is disabled
+            gboolean instant_messaging_enabled = TRUE;
+
+            if (eel_gconf_key_exists (INSTANT_MESSAGING_ENABLED))
+                instant_messaging_enabled = eel_gconf_get_integer (INSTANT_MESSAGING_ENABLED);
+
+            if (instant_messaging_enabled) {
+
+                menu_items = gtk_separator_menu_item_new();
+                gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items);
+                gtk_widget_show (menu_items);
+
+                menu_items = gtk_image_menu_item_new_with_mnemonic (_ ("Send _message"));
+                image = gtk_image_new_from_stock (GTK_STOCK_IM, GTK_ICON_SIZE_MENU);
+                gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_items), image);
+                gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items);
+                g_signal_connect (G_OBJECT (menu_items), "activate",
+                                  G_CALLBACK (call_im),
+                                  NULL);
+                gtk_widget_show (menu_items);
+            }
         }
 
     } else {
diff --git a/sflphone-client-gnome/src/widget/imwidget.c b/sflphone-client-gnome/src/widget/imwidget.c
index 494af52617b2bc20d33075106358506ac195347c..367a200b73a357bed69e63bed83bbb58ea1cf3db 100644
--- a/sflphone-client-gnome/src/widget/imwidget.c
+++ b/sflphone-client-gnome/src/widget/imwidget.c
@@ -27,34 +27,46 @@
  *  as that of the covered work.
  */
 
+#include <imwindow.h>
 #include "imwidget.h"
 #include <icons/icon_factory.h>
 #include <contacts/calltab.h>
+#include <contacts/conferencelist.h>
 #include <JavaScriptCore/JavaScript.h>
 #include <gdk/gdkkeysyms.h>
 
 #define WEBKIT_DIR "file://" DATA_DIR "/webkit/"
 
 static void
-on_frame_loading_done (GObject *gobject, GParamSpec *pspec, gpointer user_data)
+on_frame_loading_done (GObject *gobject UNUSED, GParamSpec *pspec UNUSED, gpointer user_data)
 {
     IMWidget *im = IM_WIDGET (user_data);
-    callable_obj_t *c;
+    callable_obj_t *call;
+    conference_obj_t *conf;
 
-    if (im->first_message) {
+    if (im->first_message && im->first_message_from) {
         switch (webkit_web_frame_get_load_status (WEBKIT_WEB_FRAME (im->web_frame))) {
             case WEBKIT_LOAD_PROVISIONAL:
             case WEBKIT_LOAD_COMMITTED:
                 break;
             case WEBKIT_LOAD_FINISHED:
-                c = calllist_get (current_calls, im->call_id);
-                im_widget_add_message (im, get_peer_information (c), im->first_message, 0);
+                call = calllist_get (current_calls, im->call_id);
+                conf = conferencelist_get (im->call_id);
+
+                if (call)
+                    im_widget_add_message (im, im->first_message_from, im->first_message, 0);
+
+                if (conf)
+                    im_widget_add_message (im, im->first_message_from, im->first_message, 0);
+
                 g_free (im->first_message);
+                g_free (im->first_message_from);
                 im->first_message = NULL;
+                im->first_message_from = NULL;
                 DEBUG ("JavaScrip loading frame finished");
                 break;
             case WEBKIT_LOAD_FIRST_VISUALLY_NON_EMPTY_LAYOUT:
-            case WEBKIT_LOAD_FAILED:
+                // case WEBKIT_LOAD_FAILED: // only available in webkit-1.0-2
                 break;
         }
     }
@@ -62,42 +74,24 @@ on_frame_loading_done (GObject *gobject, GParamSpec *pspec, gpointer user_data)
 }
 
 gchar *
-escape_single_quotes (gchar *message)
+escape_single_quotes (const gchar *message)
 {
     gchar **ptr_token;
-    gchar *string;
+    gchar *string = "";
 
     DEBUG ("message: %s", message);
 
-    if (ptr_token = g_strsplit (message, "'", NULL)) {
-        string = *ptr_token;
-        ptr_token++;
+    if ( (ptr_token = g_strsplit (message, "'", 0))) {
         DEBUG ("SPLITTING");
-        // string = g_strjoinv ("\\'", ptr_token);
-
-        while (*ptr_token) {
-            DEBUG ("tokens: %s", *ptr_token);
-
-            // if (g_strcmp0 (string[ (strlen (string)-1) ], "\\") == 0) {
-            //     DEBUG ("already escaped last character %s", string[ (strlen (string)-1) ]);
-            //     string = g_strdup_printf ("%s'%s", string, *ptr_token);
-            // } else
-            string = g_strdup_printf ("%s\\'%s", string, *ptr_token);
-
-            ptr_token++;
-        }
+        string = g_strjoinv ("\\'", ptr_token);
     }
 
-
-    DEBUG ("string: %s", string);
-
     return string;
 }
 
 void
 im_widget_add_message (IMWidget *im, const gchar *from, const gchar *message, gint level)
 {
-    gboolean loadingDone = FALSE;
 
     if (im) {
 
@@ -107,24 +101,30 @@ im_widget_add_message (IMWidget *im, const gchar *from, const gchar *message, gi
         /* Check for the message level */
         gchar *css_class = (level == MESSAGE_LEVEL_ERROR) ? "error" : "";
 
+        gchar *message_escaped = escape_single_quotes (message);
+
         /* Prepare and execute the Javascript code */
-        gchar *script = g_strdup_printf ("add_message('%s', '%s', '%s', '%s');", escape_single_quotes (message), from, css_class, msgtime);
+        gchar *script = g_strdup_printf ("add_message('%s', '%s', '%s', '%s');", message_escaped, from, css_class, msgtime);
         webkit_web_view_execute_script (WEBKIT_WEB_VIEW (im->web_view), script);
 
+        /* Mark it as used */
+        im->containText = TRUE;
+
         /* Cleanup */
         g_free (script);
+        g_free (message_escaped);
 
     }
 }
 
 static gboolean
 web_view_nav_requested_cb (
-    WebKitWebView             *web_view,
-    WebKitWebFrame            *frame,
+    WebKitWebView             *web_view UNUSED,
+    WebKitWebFrame            *frame UNUSED,
     WebKitNetworkRequest      *request,
-    WebKitWebNavigationAction *navigation_action,
+    WebKitWebNavigationAction *navigation_action UNUSED,
     WebKitWebPolicyDecision   *policy_decision,
-    gpointer                   user_data)
+    gpointer                   user_data UNUSED)
 {
     const gchar *uri = webkit_network_request_get_uri (request);
 
@@ -134,7 +134,10 @@ web_view_nav_requested_cb (
     } else {
         /* Running a system command to open the URL in the user's default browser */
         gchar *cmd = g_strdup_printf ("x-www-browser %s", uri);
-        system (cmd);
+
+        if (system (cmd) == -1)
+            ERROR ("Error executing command %s", cmd);
+
         webkit_web_policy_decision_ignore (policy_decision);
         g_free (cmd);
     }
@@ -143,21 +146,13 @@ web_view_nav_requested_cb (
 }
 
 static gboolean
-on_Textview_changed (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
+on_Textview_changed (GtkWidget *widget UNUSED, GdkEventKey *event, gpointer user_data)
 {
 
     GtkTextIter start, end;
     /* Get all the text in the buffer */
     IMWidget *im =  user_data;
-    callable_obj_t *im_widget_call = calllist_get (current_calls, im->call_id);
 
-    /* If the call has been hungup, it is not anymore in the current_calls calltab */
-    if (!im_widget_call) {
-        /* So try the history tab */
-        im_widget_call = calllist_get (history, im->call_id);
-    }
-
-    /* Fetch the text entered in the GtkTextView */
     GtkTextBuffer *buffer =  gtk_text_view_get_buffer (GTK_TEXT_VIEW (im->textarea));
 
     /* Catch the keyboard events */
@@ -177,7 +172,7 @@ on_Textview_changed (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
                     im_widget_add_message (im, "Me", message, MESSAGE_LEVEL_NORMAL);
 
                     /* Send the message to the peer */
-                    im_widget_send_message (im_widget_call, message);
+                    im_widget_send_message (im->call_id, message);
 
                     /* Empty the buffer */
                     gtk_text_buffer_delete (GTK_TEXT_BUFFER (buffer), &start, &end);
@@ -205,31 +200,45 @@ im_widget_add_message_time ()
 
     /* Get the time of the message. Format: HH:MM::SS */
     strftime ( (char *) str, 100, "%R", (const struct tm *) ptr);
-    gchar *res = g_strdup (str);
+    gchar *res = g_strdup ( (gchar *) str);
 
     /* Return the new value */
     return res;
 }
 
 void
-im_widget_send_message (callable_obj_t *call, const gchar *message)
+im_widget_send_message (gchar *id, const gchar *message)
 {
 
+    callable_obj_t *im_widget_call = calllist_get (current_calls, id);
+    conference_obj_t *im_widget_conf = conferencelist_get (id);
+
+    /* If the call has been hungup, it is not anymore in the current_calls calltab */
+    if (!im_widget_call) {
+        /* So try the history tab */
+        im_widget_call = calllist_get (history, id);
+    }
+
+    if (im_widget_conf) {
+        dbus_send_text_message (id, message);
+    }
     /* First check if the call is in CURRENT state, otherwise it could not be sent */
-    if (call) {
-        if (call->_type == CALL && (call->_state == CALL_STATE_CURRENT || call->_state == CALL_STATE_HOLD)) {
+    else if (im_widget_call) {
+        if (im_widget_call->_type == CALL && (im_widget_call->_state == CALL_STATE_CURRENT ||
+                                              im_widget_call->_state == CALL_STATE_HOLD ||
+                                              im_widget_call->_state == CALL_STATE_RECORD)) {
             /* Ship the message through D-Bus */
-            dbus_send_text_message (call->_callID, message);
+            dbus_send_text_message (id, message);
         } else {
             /* Display an error message */
-            im_widget_add_message (IM_WIDGET (call->_im_widget), "sflphoned", "Oups, something went wrong! Unable to send text messages outside a call.", MESSAGE_LEVEL_ERROR);
+            im_widget_add_message (IM_WIDGET (im_widget_call->_im_widget), "sflphoned", "Oups, something went wrong! Unable to send text messages outside a call.", MESSAGE_LEVEL_ERROR);
         }
     }
 }
 
 
 static void
-im_widget_class_init (IMWidgetClass *klass)
+im_widget_class_init (IMWidgetClass *klass UNUSED)
 {
 }
 
@@ -269,6 +278,8 @@ im_widget_init (IMWidget *im)
     im->js_global = JSContextGetGlobalObject (im->js_context);
     webkit_web_view_load_uri (WEBKIT_WEB_VIEW (im->web_view), "file://" DATA_DIR "/webkit/im/im.html");
 
+    im->containText = FALSE;
+
     g_signal_connect (G_OBJECT (im->web_frame), "notify", G_CALLBACK (on_frame_loading_done), im);
 }
 
@@ -279,7 +290,7 @@ im_widget_new()
 }
 
 GtkWidget *
-im_widget_new_with_first_message (gchar *message)
+im_widget_new_with_first_message (const gchar *message UNUSED)
 {
     return GTK_WIDGET (g_object_new (IM_WIDGET_TYPE, NULL));
     // return GTK_WIDGET (g_object_new (IM_WIDGET_TYPE, "first_message", message, NULL));
@@ -316,51 +327,58 @@ im_widget_get_type (void)
 }
 
 gboolean
-im_widget_display (callable_obj_t **call, gchar *message)
+im_widget_display (IMWidget **im, const gchar *message, const gchar *id, const gchar *from)
 {
 
     /* Work with a copy of the object */
-    callable_obj_t *tmp = *call;
+    // callable_obj_t *tmp = *call;
 
     /* Use the widget for this specific call, if exists */
-    if (tmp) {
-        IMWidget *im = IM_WIDGET (tmp->_im_widget);
+    // if (tmp) {
+    IMWidget *imwidget = *im;// = IM_WIDGET (tmp->_im_widget);
 
-        if (!im) {
-            DEBUG ("creating the im widget for this call\n");
+    if (!imwidget) {
+        DEBUG ("creating the im widget for this call\n");
 
-            /* Create the im object */
-            if (message)
-                im = IM_WIDGET (im_widget_new ());
-            else
-                im = IM_WIDGET (im_widget_new_with_first_message (message));
+        /* Create the im object, first message must be created asynchronously */
+        if (message)
+            imwidget = IM_WIDGET (im_widget_new ());
+        else
+            imwidget = IM_WIDGET (im_widget_new_with_first_message (message));
 
-            /* Keep a reference on this object in the call struct */
-            tmp->_im_widget = im;
-            *call = tmp;
+        /* Keep a reference on this object in the call struct */
+        // tmp->_im_widget = im;
+        // *call = tmp;
 
-            /* Update the widget with some useful call information: ie the call ID */
-            im->call_id = tmp->_callID;
+        /* Update the widget with some useful call information: ie the call ID */
+        imwidget->call_id = id;
 
-            /* Create the GtkInfoBar, used to display call information, and status of the IM widget */
-            im_widget_infobar (im);
+        /* Create the GtkInfoBar, used to display call information, and status of the IM widget */
+        im_widget_infobar (imwidget);
 
-            /* Add it to the main instant messaging window */
-            im_window_add (im);
+        /* Add it to the main instant messaging window */
+        im_window_add (GTK_WIDGET (imwidget));
 
-            /* Update the first message to appears at widget creation*/
-            im->first_message = g_strdup (message);
+        /* Update the first message to appears at widget creation*/
+        if (message)
+            imwidget->first_message = g_strdup (message);
 
-            return FALSE;
-        } else {
-            DEBUG ("im widget exists for this call\n");
-            im_window_show ();
+        if (from)
+            imwidget->first_message_from = g_strdup (from);
 
-            return TRUE;
-        }
+        *im = imwidget;
+
+        return FALSE;
+    } else {
+        DEBUG ("im widget exists for this call\n");
+        im_window_show ();
+
+        return TRUE;
     }
 
-    return FALSE;
+    // }
+
+    // return FALSE;
 }
 
 void
@@ -371,13 +389,28 @@ im_widget_infobar (IMWidget *im)
     GtkWidget *infobar = im->info_bar;
     GtkWidget *content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (infobar));
 
-    /* Fetch call information */
+    /* Fetch call/conference information */
     callable_obj_t *im_widget_call = calllist_get (current_calls, im->call_id);
+    conference_obj_t *im_widget_conf = conferencelist_get (im->call_id);
 
     /* Create the label widgets with the call information saved in the IM Widget struct */
-    gchar *msg1 = g_strdup_printf ("Calling %s  %s", im_widget_call->_peer_number, im_widget_call->_peer_name);
+    gchar *msg1;
+
+    if (im_widget_call)
+        msg1 = g_strdup_printf ("Calling %s  %s", im_widget_call->_peer_number, im_widget_call->_peer_name);
+    else if (im_widget_conf)
+        msg1 = g_strdup_printf ("Conferencing"); // im_widget_conf->_confID);
+    else
+        msg1 = g_strdup ("");
+
     GtkWidget *call_label = gtk_label_new (msg1);
-    im->info_state = call_state_image_widget (im_widget_call->_state);
+
+    if (im_widget_call)
+        im->info_state = call_state_image_widget (im_widget_call->_state);
+
+    if (im_widget_conf)
+        im->info_state = conf_state_image_widget (im_widget_conf->_state);
+
     /* Add a nice icon from our own icon factory */
     GtkWidget *logoUser = gtk_image_new_from_stock (GTK_STOCK_USER, GTK_ICON_SIZE_LARGE_TOOLBAR);
 
@@ -404,10 +437,12 @@ call_state_image_widget (call_state_t state)
 
     switch (state) {
         case CALL_STATE_CURRENT:
+        case CALL_STATE_HOLD:
+        case CALL_STATE_RECORD:
             image = gtk_image_new_from_stock (GTK_STOCK_IM, GTK_ICON_SIZE_LARGE_TOOLBAR);
             break;
         default:
-            image = gtk_image_new_from_stock (GTK_STOCK_FAIL, GTK_ICON_SIZE_LARGE_TOOLBAR);
+            image = gtk_image_new_from_stock (GTK_STOCK_IM, GTK_ICON_SIZE_LARGE_TOOLBAR);
             break;
 
     }
@@ -415,6 +450,27 @@ call_state_image_widget (call_state_t state)
     return image;
 }
 
+GtkWidget*
+conf_state_image_widget (conference_state_t state)
+{
+
+    GtkWidget *image;
+
+    switch (state) {
+        case CONFERENCE_STATE_ACTIVE_ATACHED:
+        case CONFERENCE_STATE_ACTIVE_DETACHED:
+        case CONFERENCE_STATE_RECORD:
+        case CONFERENCE_STATE_HOLD:
+            image = gtk_image_new_from_stock (GTK_STOCK_IM, GTK_ICON_SIZE_LARGE_TOOLBAR);
+            break;
+        default:
+            image = gtk_image_new_from_stock (GTK_STOCK_FAIL, GTK_ICON_SIZE_LARGE_TOOLBAR);
+            break;
+    }
+
+    return image;
+}
+
 void
 im_widget_update_state (IMWidget *im, gboolean active)
 {
diff --git a/sflphone-client-gnome/src/widget/imwidget.h b/sflphone-client-gnome/src/widget/imwidget.h
index f8816877e4c969f1030c37672cdcf80c9f2be8c3..ea0909f2135701b43e2951cad68821cd836ad722 100644
--- a/sflphone-client-gnome/src/widget/imwidget.h
+++ b/sflphone-client-gnome/src/widget/imwidget.h
@@ -34,6 +34,7 @@
 #include <gtk/gtk.h>
 #include <callable_obj.h>
 #include <webkit/webkit.h>
+#include <conference_obj.h>
 
 G_BEGIN_DECLS
 
@@ -55,15 +56,18 @@ struct _IMWidget {
     GtkVBox parent_instance;
 
     /* Private */
+    GtkWidget *tab;
     GtkWidget *textarea;
     GtkWidget *web_view;
     GtkWidget *info_bar;
     GtkWidget *info_state;
     gchar *call_id;
-    gchar *first_message;
+    gchar *first_message;           // Message displayed at widget's creation time
+    gchar *first_message_from;      // Sender of the first message (usefull in case of a conference)
     WebKitWebFrame *web_frame;      // Our web frame
     JSGlobalContextRef js_context;  // The frame's global JS context
     JSObjectRef js_global;          // The frame's global context JS object
+    gboolean containText;
 };
 
 struct _IMWidgetClass {
@@ -75,9 +79,11 @@ struct _IMWidgetClass {
 @abstract	Display the instant messaging interface for this call. If it has not been created yet, create it and attached it to the imWindow.
 @param		A reference on the call attached to the current IM widget
 @param          The first message to be displayed, webkit's frames are loaded asynchronously
+@param 	        The call id to be associated with the IMWidget
+@param          The first message sender, could be different of call id for conferences
 @return         TRUE if window is already created, FALSE elsewhere
  */
-gboolean im_widget_display (callable_obj_t**, gchar*);
+gboolean im_widget_display (IMWidget**, const gchar*, const gchar*, const gchar*);
 
 GType im_widget_get_type (void) G_GNUC_CONST;
 
@@ -89,7 +95,7 @@ GtkWidget *im_widget_new ();
 /*! @function
 @abstract 	Create a new widget with first_message
 */
-GtkWidget *im_widget_new_with_first_message (gchar *message);
+GtkWidget *im_widget_new_with_first_message (const gchar *message);
 
 
 /*! @function
@@ -101,7 +107,7 @@ GtkWidget *im_widget_new_with_first_message (gchar *message);
 */
 void im_widget_add_message (IMWidget *im, const gchar *from, const gchar *message, gint level);
 
-void im_widget_send_message (callable_obj_t *call, const gchar *message);
+void im_widget_send_message (gchar *id, const gchar *message);
 
 gchar* im_widget_add_message_time ();
 
@@ -113,6 +119,8 @@ void im_widget_infobar (IMWidget *im);
 
 GtkWidget* call_state_image_widget (call_state_t state);
 
+GtkWidget* conf_state_image_widget (conference_state_t state);
+
 void im_widget_update_state (IMWidget *im, gboolean active);
 
 G_END_DECLS
diff --git a/sflphone-common/configure.ac b/sflphone-common/configure.ac
index 80790e831c78ce5cfa501b981af9816eed31f0f5..43799dccc018df0047bdbf7662f1fb9379db8948 100644
--- a/sflphone-common/configure.ac
+++ b/sflphone-common/configure.ac
@@ -52,7 +52,7 @@ AC_CONFIG_FILES([Makefile])
 
 	AC_CONFIG_FILES([src/Makefile \
 			src/sip/Makefile \
-			src/sip/im/Makefile \
+			src/im/Makefile \
 			src/iax/Makefile \
 			src/audio/Makefile \
 			src/audio/audiortp/Makefile \
diff --git a/sflphone-common/src/Makefile.am b/sflphone-common/src/Makefile.am
index fff35078332d02e3e7d3abe45747ec52f11dee66..c3b4b75d1f60103d26250161eec99f40d51f42a5 100644
--- a/sflphone-common/src/Makefile.am
+++ b/sflphone-common/src/Makefile.am
@@ -3,7 +3,7 @@ include ../globals.mak
 libexecdir=$(libdir)/sflphone
 libexec_PROGRAMS = sflphoned
 
-SUBDIRS = dbus audio config plug-in hooks history sip iax
+SUBDIRS = dbus audio config plug-in hooks history sip iax im
 
 # Add here the cpp files to be build with sflphone
 sflphoned_SOURCES = \
@@ -66,6 +66,7 @@ libsflphone_la_LIBADD = \
 	$(src)/libs/iax2/libiax2.la \
 	$(src)/libs/dbus-c++/src/libdbus-c++-1.la \
 	$(IAX_LIB) \
+	./im/libim.la \
 	./sip/libsiplink.la \
 	./audio/libaudio.la \
 	./dbus/libdbus.la \
@@ -85,7 +86,8 @@ libsflphone_la_LDFLAGS = \
 		@SAMPLERATE_LIBS@ \
 		@libssl_LIBS@ \
 		@UUID_LIBS@ \
-		@yaml_LIBS@
+		@yaml_LIBS@ \
+		@xml_LIBS@
 
 libsflphone_la_CFLAGS = \
 		@CCGNU2_CFLAGS@ \
@@ -98,7 +100,8 @@ libsflphone_la_CFLAGS = \
 		@SAMPLERATE_CFLAGS@ \
 		@libssl_CFLAGS@ \
 		@UUID_CFLAGS@ \
-		@yaml_CFLAGS@
+		@yaml_CFLAGS@ \
+	 	@xml_CFLAGS@
 
 libsflphone_la_SOURCES =
 
diff --git a/sflphone-common/src/account.h b/sflphone-common/src/account.h
index fd75f67a67abf365aab9046bd59ab8ee44ae192c..793ddd5a806577bf616424db8dde8eb47fe869c6 100644
--- a/sflphone-common/src/account.h
+++ b/sflphone-common/src/account.h
@@ -163,8 +163,16 @@ class Account : public Serializable
          */
         virtual ~Account();
 
+        /**
+         * Method called by the configuration engine to serialize instance's information
+         * into configuration file.
+         */
         virtual void serialize (Conf::YamlEmitter *emitter) = 0;
 
+        /**
+         * Method called by the configuration engine to restore instance internal state
+         * from configuration file.
+         */
         virtual void unserialize (Conf::MappingNode *map) = 0;
 
         virtual void setAccountDetails (const std::map<std::string, std::string>& details) = 0;
diff --git a/sflphone-common/src/audio/Makefile.am b/sflphone-common/src/audio/Makefile.am
index 8f49c29cc547b096cd2a47d42a951fe4bbbc1c68..67542c2a6c469e6513d61c4d34187346bb7a668e 100644
--- a/sflphone-common/src/audio/Makefile.am
+++ b/sflphone-common/src/audio/Makefile.am
@@ -21,6 +21,7 @@ libaudio_la_SOURCES = \
 		delaydetection.cpp \
 		echocancel.cpp \
 		speexechocancel.cpp \
+		noisesuppress.cpp \
 		audioprocessing.cpp \
 		dcblocker.cpp \
 		jitterbuf.cpp \
@@ -40,6 +41,7 @@ noinst_HEADERS = \
 		delaydetection.h \
 		echocancel.h \
 		speexechocancel.h \
+		noisesuppress.h \
 		audioprocessing.h \
 		dcblocker.h \
 		jitterbuf.h \
diff --git a/sflphone-common/src/audio/alsa/alsalayer.cpp b/sflphone-common/src/audio/alsa/alsalayer.cpp
index 895a072e7609a68d3007176795340073b69f18d9..83bec76ab13815ed782f5ff225cb920fe4f32745 100644
--- a/sflphone-common/src/audio/alsa/alsalayer.cpp
+++ b/sflphone-common/src/audio/alsa/alsalayer.cpp
@@ -62,8 +62,10 @@ AlsaLayer::AlsaLayer (ManagerImpl* manager)
 
     _audioPlugin = AudioLayer::_manager->audioPreference.getPlugin();
 
-    AudioLayer::_echocancelstate = true;
     AudioLayer::_noisesuppressstate = true;
+
+    // captureFile = new ofstream ("probeFile", ofstream::binary);
+
 }
 
 // Destructor
@@ -76,6 +78,9 @@ AlsaLayer::~AlsaLayer (void)
         delete _converter;
         _converter = NULL;
     }
+
+    // captureFile->close();
+    // delete captureFile;
 }
 
 bool
@@ -95,6 +100,7 @@ AlsaLayer::closeLayer()
         throw;
     }
 
+
     /* Then close the audio devices */
     closeCaptureStream();
     closePlaybackStream();
@@ -137,12 +143,6 @@ AlsaLayer::openDevice (int indexIn, int indexOut, int indexRing, int sampleRate,
     // use 1 sec buffer for resampling
     _converter = new SamplerateConverter (_audioSampleRate, 1000);
 
-    AudioLayer::_echoCancel = new EchoCancel();
-    AudioLayer::_echoCanceller = new AudioProcessing (static_cast<Algorithm *> (_echoCancel));
-
-    AudioLayer::_echoCancel->setEchoCancelState (AudioLayer::_echocancelstate);
-    AudioLayer::_echoCancel->setNoiseSuppressState (AudioLayer::_noisesuppressstate);
-
     AudioLayer::_dcblocker = new DcBlocker();
     AudioLayer::_audiofilter = new AudioProcessing (static_cast<Algorithm *> (_dcblocker));
 
@@ -158,9 +158,6 @@ AlsaLayer::startStream (void)
     if (_audiofilter)
         _audiofilter->resetAlgorithm();
 
-    if (_echoCanceller)
-        _echoCanceller->resetAlgorithm();
-
     if (is_playback_running() && is_capture_running())
         return;
 
@@ -255,22 +252,9 @@ bool AlsaLayer::isCaptureActive (void)
         return false;
 }
 
-
-void AlsaLayer::setEchoCancelState (bool state)
-{
-    // if a stream already running
-    if (AudioLayer::_echoCancel)
-        _echoCancel->setEchoCancelState (state);
-
-    AudioLayer::_echocancelstate = state;
-}
-
 void AlsaLayer::setNoiseSuppressState (bool state)
 {
     // if a stream already opened
-    if (AudioLayer::_echoCancel)
-        _echoCancel->setNoiseSuppressState (state);
-
     AudioLayer::_noisesuppressstate = state;
 
 }
@@ -934,6 +918,7 @@ void AlsaLayer::audioCallback (void)
         // Urgent data (dtmf, incoming call signal) come first.
         toGet = (urgentAvailBytes < (int) (playbackAvailBytes)) ? urgentAvailBytes : playbackAvailBytes;
         out = (SFLDataFormat*) malloc (toGet);
+        memset (out, 0, toGet);
 
         if (out) {
             _urgentRingBuffer.Get (out, toGet, spkrVolume);
@@ -953,6 +938,7 @@ void AlsaLayer::audioCallback (void)
         if (tone && (normalAvailBytes <= 0)) {
 
             out = (SFLDataFormat *) malloc (playbackAvailBytes);
+            memset (out, 0, playbackAvailBytes);
 
             if (out) {
                 tone->getNext (out, playbackAvailSmpl, spkrVolume);
@@ -965,6 +951,7 @@ void AlsaLayer::audioCallback (void)
         } else if (file_tone && !_RingtoneHandle && (normalAvailBytes <= 0)) {
 
             out = (SFLDataFormat *) malloc (playbackAvailBytes);
+            memset (out, 0, playbackAvailBytes);
 
             if (out) {
                 file_tone->getNext (out, playbackAvailSmpl, spkrVolume);
@@ -996,15 +983,12 @@ void AlsaLayer::audioCallback (void)
             toGet = (normalAvailBytes < (int) maxNbBytesToGet) ? normalAvailBytes : maxNbBytesToGet;
 
             out = (SFLDataFormat*) malloc (maxNbBytesToGet);
+            memset (out, 0, maxNbBytesToGet);
 
             if (normalAvailBytes) {
 
                 getMainBuffer()->getData (out, toGet, spkrVolume);
 
-                // TODO: Audio processing should be performed inside mainbuffer
-                // to avoid such problem
-                AudioLayer::_echoCancel->setSamplingRate (_mainBufferSampleRate);
-
                 if (_mainBufferSampleRate && ( (int) _audioSampleRate != _mainBufferSampleRate)) {
 
                     // Do sample rate conversion
@@ -1012,6 +996,8 @@ void AlsaLayer::audioCallback (void)
 
                     if (rsmpl_out) {
                         rsmpl_out = (SFLDataFormat*) malloc (playbackAvailBytes);
+                        memset (out, 0, playbackAvailBytes);
+
                         int nbSample = _converter->upsampleData ( (SFLDataFormat*) out, rsmpl_out, _mainBufferSampleRate, _audioSampleRate, nb_sample_down);
                         write (rsmpl_out, nbSample*sizeof (SFLDataFormat), _PlaybackHandle);
                         free (rsmpl_out);
@@ -1025,9 +1011,6 @@ void AlsaLayer::audioCallback (void)
 
                 }
 
-                // Copy far-end signal in echo canceller to adapt filter coefficient
-                // AudioLayer::_echoCanceller->putData (out, toGet);
-
             } else {
 
                 if (!tone && !file_tone) {
@@ -1092,8 +1075,6 @@ void AlsaLayer::audioCallback (void)
     int toPut;
 
     SFLDataFormat* in = NULL;
-    SFLDataFormat echoCancelledMic[5000];
-    memset (echoCancelledMic, 0, 5000);
 
     if (is_capture_running()) {
 
@@ -1123,11 +1104,7 @@ void AlsaLayer::audioCallback (void)
 
                     _audiofilter->processAudio (rsmpl_out, nbSample*sizeof (SFLDataFormat));
 
-                    // echo cancellation processing
-                    // int sampleready = AudioLayer::_echoCanceller->processAudio (rsmpl_out, echoCancelledMic, nbSample*sizeof (SFLDataFormat));
-
                     getMainBuffer()->putData (rsmpl_out, nbSample * sizeof (SFLDataFormat), 100);
-                    // getMainBuffer()->putData (echoCancelledMic, sampleready*sizeof (SFLDataFormat), 100);
 
                     free (rsmpl_out);
                     rsmpl_out = 0;
@@ -1139,8 +1116,7 @@ void AlsaLayer::audioCallback (void)
 
                     if (filter_out) {
                         _audiofilter->processAudio (in, filter_out, toPut);
-                        // int sampleready = AudioLayer::_echoCanceller->processAudio (filter_out, echoCancelledMic, toPut);
-                        // getMainBuffer()->putData (echoCancelledMic, sampleready*sizeof (SFLDataFormat), 100);
+                        // captureFile->write ( (const char *) filter_out, toPut);
                         getMainBuffer()->putData (filter_out, toPut, 100);
                         free (filter_out);
                     }
diff --git a/sflphone-common/src/audio/alsa/alsalayer.h b/sflphone-common/src/audio/alsa/alsalayer.h
index ca42673f39fbd198585b09b10fcf1bc7fd4819b0..7eebc11d5ad58121907eb137ec2215b4b2e8187b 100644
--- a/sflphone-common/src/audio/alsa/alsalayer.h
+++ b/sflphone-common/src/audio/alsa/alsalayer.h
@@ -37,6 +37,8 @@
 #include "eventthread.h"
 #include <alsa/asoundlib.h>
 
+// #include <fstream>
+
 class RingBuffer;
 class ManagerImpl;
 
@@ -157,20 +159,6 @@ class AlsaLayer : public AudioLayer
 
         bool isCaptureActive (void);
 
-        /**
-         * Get the echo canceller state
-         * @return true if echo cancel activated
-         */
-        virtual bool getEchoCancelState (void) {
-            return AudioLayer::_echocancelstate;
-        }
-
-        /**
-         * Set the echo canceller state
-         * @param state true if echocancel active, false elsewhere
-         */
-        virtual void setEchoCancelState (bool state);
-
         /**
          * Get the noise suppressor state
          * @return true if noise suppressor activated
@@ -350,6 +338,8 @@ class AlsaLayer : public AudioLayer
         /** Sample rate converter object */
         SamplerateConverter* _converter;
 
+        // ofstream *captureFile;
+
 };
 
 #endif // _ALSA_LAYER_H_
diff --git a/sflphone-common/src/audio/audiolayer.h b/sflphone-common/src/audio/audiolayer.h
index 9859398d6728879af718bdb286c49ab2254bd3bf..62a4de683bad0f1d4dc2bbd5495f4592940bdd59 100644
--- a/sflphone-common/src/audio/audiolayer.h
+++ b/sflphone-common/src/audio/audiolayer.h
@@ -254,18 +254,6 @@ class AudioLayer
             return _recorder;
         }
 
-        /**
-         * Get the echo canceller state
-         * @return true if echo cancel activated
-             */
-        virtual bool getEchoCancelState (void) = 0;
-
-        /**
-         * Set the echo canceller state
-         * @param state true if echocancel active, false elsewhere
-         */
-        virtual void setEchoCancelState (bool state) = 0;
-
         /**
          * Get the noise suppressor state
          * @return true if noise suppressor activated
@@ -367,14 +355,9 @@ class AudioLayer
          */
         ost::Mutex _mutex;
 
-        EchoCancel *_echoCancel;
-        AudioProcessing *_echoCanceller;
-
         DcBlocker *_dcblocker;
         AudioProcessing *_audiofilter;
 
-        bool _echocancelstate;
-
         bool _noisesuppressstate;
 
 };
diff --git a/sflphone-common/src/audio/audiortp/AudioRtpSession.h b/sflphone-common/src/audio/audiortp/AudioRtpSession.h
index 5db39baf38adda0e91c9dde019b97eb6f79f66fc..eb40be808df3ed35b5a97013c4da8a67290aa66b 100644
--- a/sflphone-common/src/audio/audiortp/AudioRtpSession.h
+++ b/sflphone-common/src/audio/audiortp/AudioRtpSession.h
@@ -54,9 +54,14 @@
 
 #include "audio/jitterbuf.h"
 
+#include <fstream>
+
 // Frequency (in packet number)
 #define RTP_TIMESTAMP_RESET_FREQ 100
 
+// Factor use to increase volume in fade in
+#define FADEIN_STEP_SIZE 4;
+
 namespace sfl
 {
 
@@ -79,6 +84,7 @@ typedef struct DtmfEvent {
 
 typedef list<DtmfEvent *> EventQueue;
 
+
 template <typename D>
 class AudioRtpSession : public ost::Thread, public ost::TimerPort
 {
@@ -121,18 +127,51 @@ class AudioRtpSession : public ost::Thread, public ost::TimerPort
 
     private:
 
+        /**
+         * Allocate memory for RTP buffers and fill them with zeros
+         */
         void initBuffers (void);
 
+        /**
+         * Set RTP Sockets send/receive timeouts
+         */
         void setSessionTimeouts (void);
+
+        /**
+         * Set the audio codec for this RTP session
+         */
         void setSessionMedia (AudioCodec*);
+
+        /**
+         * Retreive destination address for this session. Stored in CALL
+         */
         void setDestinationIpAddress (void);
 
+        /**
+         * Encode audio data from mainbuffer
+         */
         int processDataEncode (void);
+
+        /**
+         * Decode audio data received from peer
+         */
         void processDataDecode (unsigned char * spkrData, unsigned int size);
 
+        /**
+         * Send encoded data to peer
+         */
         void sendMicData();
+
+        /**
+         * Receive data from peer
+         */
         void receiveSpeakerData ();
 
+        /**
+        * Ramp In audio data to avoid audio click from peer
+        */
+        bool fadeIn (SFLDataFormat *audio, int size, SFLDataFormat *factor);
+
         ost::Time * _time;
 
         // This semaphore is not used
@@ -235,11 +274,6 @@ class AudioRtpSession : public ost::Thread, public ost::TimerPort
          */
         EventQueue _eventQueue;
 
-        /**
-         * Adaptive jitter buffer
-         */
-        jitterbuf * _jbuffer;
-
         /**
          * Packet size in ms
          */
@@ -252,8 +286,32 @@ class AudioRtpSession : public ost::Thread, public ost::TimerPort
          */
         int _currentTime;
 
+        /**
+         * Preprocess internal data
+         */
         SpeexPreprocessState *_noiseState;
 
+        /**
+         * State of mic fade in
+         */
+        bool _micFadeInComplete;
+
+        /**
+           * State of spkr fade in
+         */
+        bool _spkrFadeInComplete;
+
+        /**
+         * Ampliturde factor to fade in mic data
+         */
+        SFLDataFormat _micAmplFactor;
+
+        /**
+         * Amplitude factor to fade in spkr data
+         */
+        SFLDataFormat _spkrAmplFactor;
+
+
     protected:
 
         SIPCall * _ca;
@@ -282,8 +340,11 @@ AudioRtpSession<D>::AudioRtpSession (ManagerImpl * manager, SIPCall * sipcall) :
         _timestampIncrement (0),
         _timestampCount (0),
         _countNotificationTime (0),
-        _jbuffer (NULL),
         _noiseState (NULL),
+        _micFadeInComplete (false),
+        _spkrFadeInComplete (false),
+        _micAmplFactor (32000),
+        _spkrAmplFactor (32000),
         _ca (sipcall)
 {
     setCancel (cancelDefault);
@@ -302,15 +363,10 @@ AudioRtpSession<D>::AudioRtpSession (ManagerImpl * manager, SIPCall * sipcall) :
     _layerFrameSize = _audiolayer->getFrameSize(); // in ms
     _layerSampleRate = _audiolayer->getSampleRate();
 
-    _jbuffer = jb_new();
-
-    _jbuffer->info.conf.max_jitterbuf = 1000;
-    _jbuffer->info.conf.target_extra = 100;
-    _jbuffer->info.silence_begin_ts = 0;
-
     _ts= 0;
     _packetLength = 20;
     _currentTime = 0;
+
 }
 
 template <typename D>
@@ -360,10 +416,6 @@ AudioRtpSession<D>::~AudioRtpSession()
         _audiocodec = NULL;
     }
 
-    if (_jbuffer) {
-        jb_destroy (_jbuffer);
-    }
-
     if (_noiseState) {
         speex_preprocess_state_destroy (_noiseState);
     }
@@ -386,16 +438,16 @@ void AudioRtpSession<D>::initBuffers()
     int nbSamplesMax = (int) (_codecSampleRate * _layerFrameSize /1000) *2;
     _micData = new SFLDataFormat[nbSamplesMax];
     _micDataConverted = new SFLDataFormat[nbSamplesMax];
-    _micDataEncoded = new unsigned char[nbSamplesMax];
+    _micDataEncoded = new unsigned char[nbSamplesMax*2];
     _spkrDataConverted = new SFLDataFormat[nbSamplesMax];
     _spkrDataDecoded = new SFLDataFormat[nbSamplesMax];
 
 
-    memset (_micData, 0, nbSamplesMax);
-    memset (_micDataConverted, 0, nbSamplesMax);
-    memset (_micDataEncoded, 0, nbSamplesMax);
-    memset (_spkrDataConverted, 0, nbSamplesMax);
-    memset (_spkrDataDecoded, 0, nbSamplesMax);
+    memset (_micData, 0, nbSamplesMax*sizeof (SFLDataFormat));
+    memset (_micDataConverted, 0, nbSamplesMax*sizeof (SFLDataFormat));
+    memset (_micDataEncoded, 0, nbSamplesMax*2);
+    memset (_spkrDataConverted, 0, nbSamplesMax*sizeof (SFLDataFormat));
+    memset (_spkrDataDecoded, 0, nbSamplesMax*sizeof (SFLDataFormat));
 
     _manager->addStream (_ca->getCallId());
 }
@@ -613,6 +665,12 @@ int AudioRtpSession<D>::processDataEncode (void)
     // Get bytes from micRingBuffer to data_from_mic
     int nbSample = _manager->getAudioDriver()->getMainBuffer()->getData (_micData , bytesAvail, 100, _ca->getCallId()) / sizeof (SFLDataFormat);
 
+    if (!_micFadeInComplete)
+        _micFadeInComplete = fadeIn (_micData, nbSample, &_micAmplFactor);
+
+    if (nbSample == 0)
+        return nbSample;
+
     // nb bytes to be sent over RTP
     int compSize = 0;
 
@@ -624,14 +682,15 @@ int AudioRtpSession<D>::processDataEncode (void)
 
         nbSample = _converter->downsampleData (_micData , _micDataConverted , _audiocodec->getClockRate(), _mainBufferSampleRate, nb_sample_up);
 
-        compSize = _audiocodec->codecEncode (_micDataEncoded, _micDataConverted, nbSample*sizeof (int16));
+        compSize = _audiocodec->codecEncode (_micDataEncoded, _micDataConverted, nbSample*sizeof (SFLDataFormat));
 
     } else {
 
         _nSamplesMic = nbSample;
 
         // no resampling required
-        compSize = _audiocodec->codecEncode (_micDataEncoded, _micData, nbSample*sizeof (int16));
+        compSize = _audiocodec->codecEncode (_micDataEncoded, _micData, nbSample*sizeof (SFLDataFormat));
+
     }
 
     return compSize;
@@ -640,7 +699,6 @@ int AudioRtpSession<D>::processDataEncode (void)
 template <typename D>
 void AudioRtpSession<D>::processDataDecode (unsigned char * spkrData, unsigned int size)
 {
-
     if (_audiocodec != NULL) {
 
 
@@ -652,6 +710,9 @@ void AudioRtpSession<D>::processDataDecode (unsigned char * spkrData, unsigned i
         // buffer _receiveDataDecoded ----> short int or int16, coded on 2 bytes
         int nbSample = expandedSize / sizeof (SFLDataFormat);
 
+        if (!_spkrFadeInComplete)
+            _spkrFadeInComplete = fadeIn (_spkrDataDecoded, nbSample, &_spkrAmplFactor);
+
         // test if resampling is required
         if (_audiocodec->getClockRate() != _mainBufferSampleRate) {
 
@@ -751,36 +812,44 @@ void AudioRtpSession<D>::receiveSpeakerData ()
 
     unsigned char* spkrDataIn = NULL;
     unsigned int size = 0;
-    int result;
-
-    jb_frame frame;
-
-    _jbuffer->info.conf.resync_threshold = 0;
 
     if (adu) {
 
         spkrDataIn  = (unsigned char*) adu->getData(); // data in char
         size = adu->getSize(); // size in char
 
-        result = jb_put (_jbuffer, spkrDataIn, JB_TYPE_VOICE, _packetLength, _ts+=20, _currentTime);
-
     } else {
         _debug ("No RTP packet available !!!!!!!!!!!!!!!!!!!!!!!\n");
     }
 
-    result = jb_get (_jbuffer, &frame, _currentTime+=20, _packetLength);
-
     // DTMF over RTP, size must be over 4 in order to process it as voice data
     if (size > 4) {
         processDataDecode (spkrDataIn, size);
-        //if(result == JB_OK) {
-        //   processDataDecode((unsigned char *)(frame.data), 160);
-        //}
     }
 
     delete adu;
 }
 
+template <typename D>
+bool AudioRtpSession<D>::fadeIn (SFLDataFormat *audio, int size, SFLDataFormat *factor)
+{
+
+    // apply amplitude factor;
+    while (size) {
+        size--;
+        audio[size] /= *factor;
+    }
+
+    // decrease factor
+    *factor /= FADEIN_STEP_SIZE;
+
+    // if factor reach 0, thsi function should no be called anymore
+    if (*factor == 0)
+        return true;
+
+    return false;
+}
+
 template <typename D>
 int AudioRtpSession<D>::startRtpThread (AudioCodec* audiocodec)
 {
@@ -822,6 +891,8 @@ void AudioRtpSession<D>::run ()
 
     _debug ("RTP: Entering mainloop for call %s",_ca->getCallId().c_str());
 
+    _manager->getAudioDriver()->getMainBuffer()->getInternalSamplingRate();
+
     while (!testCancel()) {
 
         // Reset timestamp to make sure the timing information are up to date
diff --git a/sflphone-common/src/audio/noisesuppress.cpp b/sflphone-common/src/audio/noisesuppress.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bf27eb352241f423f4889a30176d5fd10211cbac
--- /dev/null
+++ b/sflphone-common/src/audio/noisesuppress.cpp
@@ -0,0 +1,89 @@
+/*
+ *  Copyright (C) 2004, 2005, 2006, 2009, 2008, 2009, 2010 Savoir-Faire Linux Inc.
+ *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Additional permission under GNU GPL version 3 section 7:
+ *
+ *  If you modify this program, or any covered work, by linking or
+ *  combining it with the OpenSSL project's OpenSSL library (or a
+ *  modified version of that library), containing parts covered by the
+ *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
+ *  grants you additional permission to convey the resulting work.
+ *  Corresponding Source for a non-source form of such a combination
+ *  shall include the source code for the parts of OpenSSL used as well
+ *  as that of the covered work.
+ */
+
+#include "noisesuppress.h"
+
+NoiseSuppress::NoiseSuppress (int smplPerFrame, int samplingRate) : _noiseState (NULL)
+        , _smplPerFrame (smplPerFrame)
+        , _samplingRate (samplingRate)
+{
+    initNewNoiseSuppressor (_smplPerFrame, _samplingRate);
+}
+
+
+NoiseSuppress::~NoiseSuppress()
+{
+    speex_preprocess_state_destroy (_noiseState);
+}
+
+void NoiseSuppress::reset (void)
+{
+
+    speex_preprocess_state_destroy (_noiseState);
+
+    initNewNoiseSuppressor (_smplPerFrame, _samplingRate);
+}
+
+void NoiseSuppress::putData (SFLDataFormat *inputData, int nbBytes) {}
+
+int NoiseSuppress::getData (SFLDataFormat *outputData) {}
+
+void NoiseSuppress::process (SFLDataFormat *data, int nbBytes)
+{
+    if (_noiseState)
+        speex_preprocess_run (_noiseState, data);
+}
+
+int NoiseSuppress::process (SFLDataFormat *inputData, SFLDataFormat *outputData, int nbBytes) {}
+
+void NoiseSuppress::process (SFLDataFormat *micData, SFLDataFormat *spkrData, SFLDataFormat *outputData, int nbBytes) {}
+
+void NoiseSuppress::initNewNoiseSuppressor (int smplPerFrame, int samplingRate)
+{
+    _noiseState = speex_preprocess_state_init (smplPerFrame, samplingRate);
+    int i=1;
+    speex_preprocess_ctl (_noiseState, SPEEX_PREPROCESS_SET_DENOISE, &i);
+    i=-20;
+    speex_preprocess_ctl (_noiseState, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &i);
+    i=0;
+    speex_preprocess_ctl (_noiseState, SPEEX_PREPROCESS_SET_AGC, &i);
+    i=8000;
+    speex_preprocess_ctl (_noiseState, SPEEX_PREPROCESS_SET_AGC_TARGET, &i);
+    i=16000;
+    speex_preprocess_ctl (_noiseState, SPEEX_PREPROCESS_SET_AGC_LEVEL, &i);
+    i=0;
+    speex_preprocess_ctl (_noiseState, SPEEX_PREPROCESS_SET_DEREVERB, &i);
+    float f=0.0;
+    speex_preprocess_ctl (_noiseState, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &f);
+    f=0.0;
+    speex_preprocess_ctl (_noiseState, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &f);
+    i = 0;
+    speex_preprocess_ctl (_noiseState, SPEEX_PREPROCESS_SET_VAD, &i);
+}
diff --git a/sflphone-common/src/audio/noisesuppress.h b/sflphone-common/src/audio/noisesuppress.h
new file mode 100644
index 0000000000000000000000000000000000000000..fe9494013073d7a75c5e89618e7526ac2e03da07
--- /dev/null
+++ b/sflphone-common/src/audio/noisesuppress.h
@@ -0,0 +1,93 @@
+/*
+ *  Copyright (C) 2004, 2005, 2006, 2009, 2008, 2009, 2010 Savoir-Faire Linux Inc.
+ *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Additional permission under GNU GPL version 3 section 7:
+ *
+ *  If you modify this program, or any covered work, by linking or
+ *  combining it with the OpenSSL project's OpenSSL library (or a
+ *  modified version of that library), containing parts covered by the
+ *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
+ *  grants you additional permission to convey the resulting work.
+ *  Corresponding Source for a non-source form of such a combination
+ *  shall include the source code for the parts of OpenSSL used as well
+ *  as that of the covered work.
+ */
+
+#ifndef NOISESUPPRESS_H
+#define NOISESUPPRESS_H
+
+#include <speex/speex_preprocess.h>
+#include "algorithm.h"
+#include "audioprocessing.h"
+
+
+class NoiseSuppress : public Algorithm
+{
+
+    public:
+
+        NoiseSuppress (int smplPerFrame, int samplingRate);
+
+        ~NoiseSuppress (void);
+
+        /**
+             * Reset noise suppressor internal state at runtime. Usefull when making a new call
+             */
+        virtual void reset (void);
+
+        /**
+         * Unused
+        */
+        virtual void putData (SFLDataFormat *inputData, int nbBytes);
+
+        /**
+        * Unused
+         */
+        virtual int getData (SFLDataFormat *outputData);
+
+        /**
+         * Unused
+         */
+        virtual void process (SFLDataFormat *data, int nbBytes);
+
+        /**
+         * Unused
+        */
+        virtual int process (SFLDataFormat *inputData, SFLDataFormat *outputData, int nbBytes);
+
+        /**
+        * Unused
+         */
+        virtual void process (SFLDataFormat *micData, SFLDataFormat *spkrData, SFLDataFormat *outputData, int nbBytes);
+
+    private:
+
+        void initNewNoiseSuppressor (int _smplPerFrame, int samplingRate);
+
+        /**
+             * Noise reduction processing state
+             */
+        SpeexPreprocessState *_noiseState;
+
+        int _smplPerFrame;
+
+        int _samplingRate;
+
+};
+
+#endif
diff --git a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp
index 84044628336dc56c68cddef637126790f6dd786a..e90d0698f1a5d988ff171bba01697bbb4d3bf669 100644
--- a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp
+++ b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp
@@ -33,9 +33,13 @@
 #include "managerimpl.h"
 
 
+// #include <fstream>
+
 int framesPerBuffer = 2048;
 
 
+
+
 static  void playback_callback (pa_stream* s, size_t bytes, void* userdata)
 {
 
@@ -161,7 +165,7 @@ static void source_input_info_callback (pa_context *c UNUSED, const pa_source_in
 }
 
 
-static void context_changed_callback (pa_context* c, pa_subscription_event_type_t t, uint32_t idx, void* userdata)
+static void context_changed_callback (pa_context* c, pa_subscription_event_type_t t, uint32_t idx UNUSED, void* userdata)
 {
 
     switch (t) {
@@ -241,16 +245,14 @@ PulseLayer::PulseLayer (ManagerImpl* manager)
 
     is_started = false;
 
-    AudioLayer::_echocancelstate = true;
     AudioLayer::_noisesuppressstate = true;
 
     byteCounter = 0;
 
-    /*
-    captureFile = new ofstream("captureFile", ofstream::binary);
-    captureRsmplFile = new ofstream("captureRsmplFile", ofstream::binary);
-    captureFilterFile = new ofstream("captureFilterFile", ofstream::binary);
-    */
+
+    // captureFile = new ofstream ("probeCaptureFile", ofstream::binary);
+    // spkrFile = new ofstream ("probeSpkrFile", ofstream::binary);
+
     openLayer();
 }
 
@@ -264,27 +266,18 @@ PulseLayer::~PulseLayer (void)
         _converter = NULL;
     }
 
-    delete AudioLayer::_echoCancel;
-    AudioLayer::_echoCancel = NULL;
-
-    delete AudioLayer::_echoCanceller;
-    AudioLayer::_echoCanceller = NULL;
-
     delete AudioLayer::_dcblocker;
     AudioLayer::_dcblocker = NULL;
 
     delete AudioLayer::_audiofilter;
     AudioLayer::_audiofilter = NULL;
 
-    /*
-    captureFile->close();
-    captureRsmplFile->close();
-    captureFilterFile->close();
 
-    delete captureFile;
-    delete captureRsmplFile;
-    delete captureFilterFile;
-    */
+    // captureFile->close();
+    // spkrFile->close();
+
+    // delete captureFile;
+    // delete spkrFile;
 }
 
 void
@@ -436,9 +429,6 @@ bool PulseLayer::openDevice (int indexIn UNUSED, int indexOut UNUSED, int indexR
     _converter = new SamplerateConverter (_audioSampleRate, 1000);
 
     // Instantiate the algorithm
-    AudioLayer::_echoCancel = new EchoCancel (_audioSampleRate, _frameSize);
-    AudioLayer::_echoCanceller = new AudioProcessing (static_cast<Algorithm *> (_echoCancel));
-
     AudioLayer::_dcblocker = new DcBlocker();
     AudioLayer::_audiofilter = new AudioProcessing (static_cast<Algorithm *> (_dcblocker));
 
@@ -649,11 +639,6 @@ int PulseLayer::canGetMic()
 
 void PulseLayer::startStream (void)
 {
-    if (_audiofilter)
-        _audiofilter->resetAlgorithm();
-
-    if (_echoCanceller)
-        _echoCanceller->resetAlgorithm();
 
     // Create Streams
     if (!playback || !record)
@@ -749,21 +734,9 @@ void PulseLayer::processData (void)
 
 }
 
-void PulseLayer::setEchoCancelState (bool state)
-{
-    // if a stream already running
-    if (AudioLayer::_echoCancel)
-        _echoCancel->setEchoCancelState (state);
-
-    AudioLayer::_echocancelstate = state;
-}
-
 void PulseLayer::setNoiseSuppressState (bool state)
 {
     // if a stream already opened
-    if (AudioLayer::_echoCancel)
-        _echoCancel->setNoiseSuppressState (state);
-
     AudioLayer::_noisesuppressstate = state;
 
 }
@@ -792,8 +765,11 @@ void PulseLayer::writeToSpeaker (void)
     if (urgentAvailBytes > writeableSize) {
 
         out = (SFLDataFormat*) pa_xmalloc (writeableSize);
+        memset (out, 0, writeableSize);
+
         _urgentRingBuffer.Get (out, writeableSize, 100);
 
+        // spkrFile->write ( (const char *) out, writeableSize);
         pa_stream_write (playback->pulseStream(), out, writeableSize, NULL, 0, PA_SEEK_RELATIVE);
 
         pa_xfree (out);
@@ -818,8 +794,11 @@ void PulseLayer::writeToSpeaker (void)
             if (playback->getStreamState() == PA_STREAM_READY) {
 
                 out = (SFLDataFormat*) pa_xmalloc (writeableSize);
+                memset (out, 0, writeableSize);
+
                 int copied = tone->getNext (out, writeableSize / sizeof (SFLDataFormat), 100);
 
+                //spkrFile->write ( (const char *) out, copied*sizeof (SFLDataFormat));
                 pa_stream_write (playback->pulseStream(), out, copied * sizeof (SFLDataFormat), NULL, 0, PA_SEEK_RELATIVE);
 
                 pa_xfree (out);
@@ -857,17 +836,15 @@ void PulseLayer::writeToSpeaker (void)
                     byteToGet = byteToGet-1;
 
                 out = (SFLDataFormat*) pa_xmalloc (maxNbBytesToGet);
+                memset (out, 0, maxNbBytesToGet);
 
                 getMainBuffer()->getData (out, byteToGet, 100);
 
-                // TODO: Audio processing should be performed inside mainbuffer
-                // to avoid such problem
-                AudioLayer::_echoCancel->setSamplingRate (_mainBufferSampleRate);
-
                 // test if resampling is required
                 if (_mainBufferSampleRate && ( (int) _audioSampleRate != _mainBufferSampleRate)) {
 
                     SFLDataFormat* rsmpl_out = (SFLDataFormat*) pa_xmalloc (writeableSize);
+                    memset (out, 0, writeableSize);
 
                     // Do sample rate conversion
                     int nb_sample_down = byteToGet / sizeof (SFLDataFormat);
@@ -877,19 +854,17 @@ void PulseLayer::writeToSpeaker (void)
                     if ( (nbSample*sizeof (SFLDataFormat)) > (unsigned int) writeableSize)
                         _warn ("Audio: Error: nbsbyte exceed buffer length");
 
+                    // spkrFile->write ( (const char *) out, nbSample*sizeof (SFLDataFormat));
                     pa_stream_write (playback->pulseStream(), rsmpl_out, nbSample*sizeof (SFLDataFormat), NULL, 0, PA_SEEK_RELATIVE);
 
                     pa_xfree (rsmpl_out);
 
                 } else {
-
+                    // spkrFile->write ( (const char *) out, byteToGet);
                     pa_stream_write (playback->pulseStream(), out, byteToGet, NULL, 0, PA_SEEK_RELATIVE);
 
-                }
-
 
-                // Copy far-end signal in echo canceller to adapt filter coefficient
-                // AudioLayer::_echoCanceller->putData(out, byteToGet);
+                }
 
                 pa_xfree (out);
 
@@ -898,9 +873,9 @@ void PulseLayer::writeToSpeaker (void)
                 if (tone == 0) {
 
                     SFLDataFormat* zeros = (SFLDataFormat*) pa_xmalloc (writeableSize);
-
                     bzero (zeros, writeableSize);
 
+                    // spkrFile->write ( (const char *) zeros, writeableSize);
                     pa_stream_write (playback->pulseStream(), zeros, writeableSize, NULL, 0, PA_SEEK_RELATIVE);
 
                     pa_xfree (zeros);
@@ -922,9 +897,6 @@ void PulseLayer::readFromMic (void)
     const char* data = NULL;
     size_t r;
 
-    SFLDataFormat echoCancelledMic[10000];
-    memset (echoCancelledMic, 0, 10000*sizeof (SFLDataFormat));
-
     int readableSize = pa_stream_readable_size (record->pulseStream());
 
 
@@ -940,13 +912,12 @@ void PulseLayer::readFromMic (void)
         if (_mainBufferSampleRate && ( (int) _audioSampleRate != _mainBufferSampleRate)) {
 
             SFLDataFormat* rsmpl_out = (SFLDataFormat*) pa_xmalloc (readableSize);
+            memset (rsmpl_out, 0, readableSize);
 
             int nbSample = r / sizeof (SFLDataFormat);
 
             int nb_sample_up = nbSample;
 
-            // captureFile->write ((const char *)data, nbSample*sizeof(SFLDataFormat));
-
             nbSample = _converter->downsampleData ( (SFLDataFormat *) data, rsmpl_out, _mainBufferSampleRate, _audioSampleRate, nb_sample_up);
 
             // captureRsmplFile->write ((const char *)rsmpl_out, nbSample*sizeof(SFLDataFormat));
@@ -956,28 +927,21 @@ void PulseLayer::readFromMic (void)
 
             // captureFilterFile->write ((const char *)rsmpl_out, nbSample*sizeof(SFLDataFormat));
 
-            // echo cancellation processing
-            // int sampleready = _echoCanceller->processAudio(rsmpl_out, echoCancelledMic, nbSample*sizeof(SFLDataFormat));
-
-            // getMainBuffer()->putData ( (void*) rsmpl_out, nbSample*sizeof (SFLDataFormat), 100);
-            // if(sampleready)
-            // getMainBuffer()->putData ( echoCancelledMic, sampleready*sizeof (SFLDataFormat), 100);
             getMainBuffer()->putData (rsmpl_out, nbSample*sizeof (SFLDataFormat), 100);
 
             pa_xfree (rsmpl_out);
 
         } else {
 
+
             SFLDataFormat* filter_out = (SFLDataFormat*) pa_xmalloc (r);
+            memset (filter_out, 0, r);
 
             // remove dc offset
             _audiofilter->processAudio ( (SFLDataFormat *) data, filter_out, r);
 
-            // echo cancellation processing
-            // int sampleready = _echoCanceller->processAudio((SFLDataFormat *)filter_out, echoCancelledMic, r);
+            // captureFile->write ( (const char *) filter_out, r);
 
-            // no resampling required
-            // getMainBuffer()->putData (echoCancelledMic, sampleready*sizeof (SFLDataFormat), 100);
             getMainBuffer()->putData (filter_out, r, 100);
 
             pa_xfree (filter_out);
@@ -1007,6 +971,8 @@ void PulseLayer::ringtoneToSpeaker (void)
         if (ringtone->getStreamState() == PA_STREAM_READY) {
 
             out = (SFLDataFormat *) pa_xmalloc (writableSize);
+            memset (out, 0, writableSize);
+
             int copied = file_tone->getNext (out, writableSize/sizeof (SFLDataFormat), 100);
             pa_stream_write (ringtone->pulseStream(), out, copied*sizeof (SFLDataFormat), NULL, 0, PA_SEEK_RELATIVE);
 
@@ -1018,6 +984,7 @@ void PulseLayer::ringtoneToSpeaker (void)
 
             out = (SFLDataFormat*) pa_xmalloc (writableSize);
             memset (out, 0, writableSize);
+
             pa_stream_write (ringtone->pulseStream(), out, writableSize, NULL, 0, PA_SEEK_RELATIVE);
 
             pa_xfree (out);
diff --git a/sflphone-common/src/audio/pulseaudio/pulselayer.h b/sflphone-common/src/audio/pulseaudio/pulselayer.h
index 2cfb2595d17e473c2b4fa9b8e9aafd166c94e061..d06bec75b07fb5855692b9f3735ca92f50caf450 100644
--- a/sflphone-common/src/audio/pulseaudio/pulselayer.h
+++ b/sflphone-common/src/audio/pulseaudio/pulselayer.h
@@ -191,20 +191,6 @@ class PulseLayer : public AudioLayer
 
         void processData (void);
 
-        /**
-         * Get the echo canceller state
-         * @return true if echo cancel activated
-         */
-        bool getEchoCancelState (void) {
-            return AudioLayer::_echocancelstate;
-        }
-
-        /**
-         * Set the echo canceller state
-         * @param state true if echocancel active, false elsewhere
-         */
-        void setEchoCancelState (bool state);
-
         /**
          * Get the noise suppressor state
          * @return true if noise suppressor activated
@@ -292,11 +278,9 @@ class PulseLayer : public AudioLayer
         int spkrVolume;
         int micVolume;
 
-        /*
-        ofstream *captureFile;
-        ofstream *captureRsmplFile;
-        ofstream *captureFilterFile;
-        */
+
+        // ofstream *captureFile;
+        // ofstream *spkrFile;
 
         DeviceList _sinkList;
 
diff --git a/sflphone-common/src/audio/recordable.cpp b/sflphone-common/src/audio/recordable.cpp
index 87c3f2b302aac7020335f3d25d5cbfdfa41f2c12..d0ed8bf1316fb16bda5a27daea514328ec18aa11 100644
--- a/sflphone-common/src/audio/recordable.cpp
+++ b/sflphone-common/src/audio/recordable.cpp
@@ -48,10 +48,9 @@ Recordable::~Recordable()
 }
 
 
-void Recordable::initRecFileName()
+void Recordable::initRecFileName (std::string filename)
 {
-
-    recAudio.initFileName (getRecFileId());
+    recAudio.initFileName (filename);
 }
 
 
diff --git a/sflphone-common/src/audio/recordable.h b/sflphone-common/src/audio/recordable.h
index 4ec7362afe78e39d127700d6632b423e43b9da03..9a99724217bff8900de6e2a9a76c535a58afb2d4 100644
--- a/sflphone-common/src/audio/recordable.h
+++ b/sflphone-common/src/audio/recordable.h
@@ -65,7 +65,7 @@ class Recordable
         /**
          * Init the recording file name according to path specified in configuration
          */
-        void initRecFileName();
+        void initRecFileName (std::string filename);
 
         /**
          * Set recording sampling rate.
diff --git a/sflphone-common/src/audio/samplerateconverter.cpp b/sflphone-common/src/audio/samplerateconverter.cpp
index 320d70b5cd1396dc331267993d66230de828e45f..c491c865a12a051c113f56dcc7ac86b7af70fe4a 100644
--- a/sflphone-common/src/audio/samplerateconverter.cpp
+++ b/sflphone-common/src/audio/samplerateconverter.cpp
@@ -30,20 +30,6 @@
 #include "samplerateconverter.h"
 #include "manager.h"
 
-SamplerateConverter::SamplerateConverter (void)
-        : _frequence (Manager::instance().getConfigInt (AUDIO , AUDIO_SAMPLE_RATE)) //44100
-        , _framesize (Manager::instance().getConfigInt (AUDIO , ALSA_FRAME_SIZE))
-        , _floatBufferDownMic (NULL)
-        , _floatBufferUpMic (NULL)
-        , _src_state_mic (NULL)
-        , _floatBufferDownSpkr (NULL)
-        , _floatBufferUpSpkr (NULL)
-        , _src_state_spkr (NULL)
-        , _src_err (0)
-{
-    init();
-}
-
 SamplerateConverter::SamplerateConverter (int freq , int fs)
         : _frequence (freq)
         , _framesize (fs)
@@ -61,19 +47,36 @@ SamplerateConverter::SamplerateConverter (int freq , int fs)
 SamplerateConverter::~SamplerateConverter (void)
 {
 
-    delete [] _floatBufferUpMic;
-    _floatBufferUpMic = NULL;
-    delete [] _floatBufferDownMic;
-    _floatBufferDownMic = NULL;
+    if (_floatBufferUpMic) {
+        delete [] _floatBufferUpMic;
+        _floatBufferUpMic = NULL;
+    }
+
+    if (_floatBufferDownMic) {
+        delete [] _floatBufferDownMic;
+        _floatBufferDownMic = NULL;
+    }
+
+    if (_floatBufferUpSpkr) {
+        delete [] _floatBufferUpSpkr;
+        _floatBufferUpSpkr = NULL;
+    }
 
-    delete [] _floatBufferUpSpkr;
-    _floatBufferUpSpkr = NULL;
-    delete [] _floatBufferDownSpkr;
-    _floatBufferDownSpkr = NULL;
+    if (_floatBufferDownSpkr) {
+        delete [] _floatBufferDownSpkr;
+        _floatBufferDownSpkr = NULL;
+    }
 
     // libSamplerateConverter-related
-    _src_state_mic  = src_delete (_src_state_mic);
-    _src_state_spkr = src_delete (_src_state_spkr);
+    if (_src_state_mic) {
+        _src_state_mic  = src_delete (_src_state_mic);
+        _src_state_mic = NULL;
+    }
+
+    if (_src_state_spkr) {
+        _src_state_spkr = src_delete (_src_state_spkr);
+        _src_state_spkr = NULL;
+    }
 }
 
 void SamplerateConverter::init (void)
diff --git a/sflphone-common/src/audio/samplerateconverter.h b/sflphone-common/src/audio/samplerateconverter.h
index 5645a64a4bc8d9a93a7123aa37c4764113e43515..f3616b65f12568a945bd6b2951cbca234dc2b747 100644
--- a/sflphone-common/src/audio/samplerateconverter.h
+++ b/sflphone-common/src/audio/samplerateconverter.h
@@ -1,6 +1,7 @@
 /*
  *  Copyright (C) 2004, 2005, 2006, 2009, 2008, 2009, 2010 Savoir-Faire Linux Inc.
  *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
+ *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -39,9 +40,15 @@
 class SamplerateConverter
 {
     public:
-        /** Constructor */
-        SamplerateConverter (void);
-        SamplerateConverter (int freq , int fs);
+        /**
+         * Samplerate converter is used for several situation:
+        * streaming conversion (RTP, IAX), audiolayer conversion,
+        * audio files conversion. Parameters are used to compute
+        * internal buffer size. Converter must be reinitialized
+        * every time these parameters change
+        */
+        SamplerateConverter (int freq=44100, int frameSize=20);
+
         /** Destructor */
         ~SamplerateConverter (void);
 
diff --git a/sflphone-common/src/call.h b/sflphone-common/src/call.h
index f7fb935f167d4320fdc703c729bd3fcb67bc3a52..712e60d58892b75ed745ff4334123df56de1d10e 100644
--- a/sflphone-common/src/call.h
+++ b/sflphone-common/src/call.h
@@ -271,7 +271,7 @@ class Call: public Recordable
         }
 
         std::string getFileName (void) {
-            return _filename;
+            return _peerNumber;
         }
 
         virtual bool setRecording (void);
@@ -323,7 +323,7 @@ class Call: public Recordable
         /** Display Name */
         std::string _displayName;
 
-        /** File name for his call : time YY-MM-DD */
+        /** File name for his call, should be peer number */
         std::string _filename;
 
 
diff --git a/sflphone-common/src/conference.cpp b/sflphone-common/src/conference.cpp
index 3e645628ddc70a52c88fac9f0337a1380e66f7b7..044b889f845afc9effc7f8ff14d87c4ba66acb88 100644
--- a/sflphone-common/src/conference.cpp
+++ b/sflphone-common/src/conference.cpp
@@ -55,7 +55,7 @@ Conference::Conference()
     _nbParticipant = 0;
     _id = conf.append (s);
 
-    Recordable::initRecFileName();
+    Recordable::initRecFileName (_id);
 
 }
 
diff --git a/sflphone-common/src/config/yamlemitter.cpp b/sflphone-common/src/config/yamlemitter.cpp
index 3b6ba5c0c35d50e2e6d6b8a0071239f9d380a424..0f07f777538417112d7c1f6723238ef5f559e3cd 100644
--- a/sflphone-common/src/config/yamlemitter.cpp
+++ b/sflphone-common/src/config/yamlemitter.cpp
@@ -47,7 +47,8 @@ YamlEmitter::~YamlEmitter()
 
 void YamlEmitter::open()
 {
-    fd = fopen (filename.c_str(), "wb");
+
+    fd = fopen (filename.c_str(), "w");
 
     if (!fd)
         throw YamlEmitterException ("Could not open file descriptor");
@@ -55,12 +56,13 @@ void YamlEmitter::open()
     if (!yaml_emitter_initialize (&emitter))
         throw YamlEmitterException ("Could not initialize emitter");
 
-    // Use unicode format
+    // Allows unescaped unicode characters
     yaml_emitter_set_unicode (&emitter, 1);
 
     yaml_emitter_set_output_file (&emitter, fd);
 
-    yaml_document_initialize (&document, NULL, NULL, NULL, 0, 0);
+    if (!yaml_document_initialize (&document, NULL, NULL, NULL, 0, 0))
+        throw YamlEmitterException ("Could not initialize yaml document while saving configuration");
 
     // Init the main configuration mapping
     if ( (topLevelMapping = yaml_document_add_mapping (&document, NULL, YAML_BLOCK_MAPPING_STYLE)) == 0)
@@ -74,13 +76,13 @@ void YamlEmitter::close()
     if (!fd)
         throw YamlEmitterException ("File descriptor not valid");
 
-    fclose (fd);
-    /*
-    if(!fclose(fd))
-      throw YamlEmitterException("Error closing file descriptor");
-    */
 
-    yaml_document_delete (&document);
+    if (fclose (fd))
+        throw YamlEmitterException ("Error closing file descriptor");
+
+
+    _debug ("Config: Configuration file closed successfully");
+
 }
 
 void YamlEmitter::read() {}
@@ -92,7 +94,9 @@ void YamlEmitter::write()
 
 void YamlEmitter::serializeData()
 {
-    yaml_emitter_dump (&emitter, &document);
+    // Document object is destroyed once its content is emitted
+    if (!yaml_emitter_dump (&emitter, &document))
+        throw YamlEmitterException ("Error while emitting configuration yaml document");
 }
 
 
diff --git a/sflphone-common/src/config/yamlparser.cpp b/sflphone-common/src/config/yamlparser.cpp
index b4d8c5de47ac3afd76f36f778bbffa970b7ff614..90b46c8470c39bdab5774ddd84578b4b647dc5aa 100644
--- a/sflphone-common/src/config/yamlparser.cpp
+++ b/sflphone-common/src/config/yamlparser.cpp
@@ -79,9 +79,9 @@ void YamlParser::close()
     if (!fd)
         throw YamlParserException ("File descriptor not valid");
 
-    fclose (fd);
-    // if(!fclose(fd))
-    // throw YamlParserException("Error closing file descriptor");
+    // fclose (fd);
+    if (fclose (fd))
+        throw YamlParserException ("Error closing file descriptor");
 
 
 }
diff --git a/sflphone-common/src/dbus/callmanager.cpp b/sflphone-common/src/dbus/callmanager.cpp
index a5498d0e6488c756ceecf97a173fa93aaf7bda8b..26eaa53fda60c725c18891240c8dfa32d03da8f5 100644
--- a/sflphone-common/src/dbus/callmanager.cpp
+++ b/sflphone-common/src/dbus/callmanager.cpp
@@ -464,6 +464,6 @@ CallManager::setPBXEnrollment (const std::string& callID, const bool& yesNo)
 void
 CallManager::sendTextMessage (const std::string& callID, const std::string& message)
 {
-    if (!Manager::instance().sendTextMessage (callID, message))
+    if (!Manager::instance().sendTextMessage (callID, message, "Me"))
         throw CallManagerException();
 }
diff --git a/sflphone-common/src/dbus/configurationmanager-introspec.xml b/sflphone-common/src/dbus/configurationmanager-introspec.xml
index c2818831f9e18520fe3bbfbe9c0982bd6a2133a2..f051f3b44bfb685a4408e18bf578024f49831f75 100755
--- a/sflphone-common/src/dbus/configurationmanager-introspec.xml
+++ b/sflphone-common/src/dbus/configurationmanager-introspec.xml
@@ -545,22 +545,6 @@
 		   </arg>
 	   </method>
 
-	   <method name="getEchoCancelState" tp:name-for-bindings="getEchoCancelState">
-	           <tp:docstring>
-	           </tp:docstring>
-	           <arg type="s" name="state" direction="out">
-		           <tp:docstring>
-			   </tp:docstring>
-	           </arg>
-	   </method>
-
-	   <method name="setEchoCancelState" tp:name-for-bindings="setEchoCancelState">
-	           <tp:docstring>
-		   </tp:docstring>
-		   <arg type="s" name="state" direction="in">
-		   </arg>
-	   </method>
-
            <method name="getNoiseSuppressState" tp:name-for-bindings="getNoiseSuppressState">
 	           <tp:docstring>
 		   </tp:docstring>
diff --git a/sflphone-common/src/dbus/configurationmanager.cpp b/sflphone-common/src/dbus/configurationmanager.cpp
index c14c491bb55e2b18b4777da63bcd2944244be96c..2273ce8381b24e44df1c198007ab245d28d43d98 100644
--- a/sflphone-common/src/dbus/configurationmanager.cpp
+++ b/sflphone-common/src/dbus/configurationmanager.cpp
@@ -332,8 +332,16 @@ int32_t ConfigurationManager::getNumberOfCredential (
     const std::string& accountID)
 {
 
-    SIPAccount *sipaccount = (SIPAccount *) Manager::instance().getAccount (accountID);
-    return sipaccount->getCredentialCount();
+    Account *account = Manager::instance().getAccount (accountID);
+
+    if (!account)
+        return 0;
+
+    if (account->getType() == "SIP") {
+        SIPAccount *sipaccount = static_cast<SIPAccount *> (account);
+        return sipaccount->getCredentialCount();
+    } else
+        return 0;
 }
 
 void ConfigurationManager::setCredential (const std::string& accountID,
@@ -550,16 +558,6 @@ std::string ConfigurationManager::getCurrentAudioOutputPlugin (void)
     return Manager::instance().getCurrentAudioOutputPlugin();
 }
 
-std::string ConfigurationManager::getEchoCancelState (void)
-{
-    return Manager::instance().getEchoCancelState();
-}
-
-void ConfigurationManager::setEchoCancelState (const std::string& state)
-{
-    Manager::instance().setEchoCancelState (state);
-}
-
 std::string ConfigurationManager::getNoiseSuppressState (void)
 {
     return Manager::instance().getNoiseSuppressState();
diff --git a/sflphone-common/src/dbus/configurationmanager.h b/sflphone-common/src/dbus/configurationmanager.h
index 469114922870232c8fceb5267f40dec3b71bd5cd..df510731c0ee45c3b220e6f3e77a132739fcdd6f 100644
--- a/sflphone-common/src/dbus/configurationmanager.h
+++ b/sflphone-common/src/dbus/configurationmanager.h
@@ -89,8 +89,6 @@ class ConfigurationManager
         std::vector< std::string > getCurrentAudioDevicesIndex();
         int32_t getAudioDeviceIndex (const std::string& name);
         std::string getCurrentAudioOutputPlugin (void);
-        std::string getEchoCancelState (void);
-        void setEchoCancelState (const std::string& state);
         std::string getNoiseSuppressState (void);
         void setNoiseSuppressState (const std::string& state);
 
diff --git a/sflphone-common/src/eventthread.cpp b/sflphone-common/src/eventthread.cpp
index cc16b5e77f45e448e13455b5ed99853c9b17fcda..a1aa2416e6b0b3f62d8791695699cb7e44620619 100644
--- a/sflphone-common/src/eventthread.cpp
+++ b/sflphone-common/src/eventthread.cpp
@@ -46,7 +46,8 @@ EventThread::EventThread (VoIPLink *link)
 void EventThread::run (void)
 {
     while (!testCancel()) {
-        _linkthread->getEvent();
+        if (_linkthread)
+            _linkthread->getEvent();
     }
 }
 
diff --git a/sflphone-common/src/iax/iaxvoiplink.cpp b/sflphone-common/src/iax/iaxvoiplink.cpp
index a9d4f117ea361c1fdba5731c715dcc57b9b2c77e..6679bbf4b783bdb4880ec9d39c5ceaaf71aa2e89 100644
--- a/sflphone-common/src/iax/iaxvoiplink.cpp
+++ b/sflphone-common/src/iax/iaxvoiplink.cpp
@@ -51,20 +51,26 @@
 #define CHK_VALID_CALL   if (call == NULL) { _debug("IAX: Call doesn't exists"); \
 	return false; }
 
-IAXVoIPLink::IAXVoIPLink (const AccountID& accountID)
-        : VoIPLink (accountID)
+IAXVoIPLink::IAXVoIPLink (const AccountID& accountID) : VoIPLink (accountID)
+        , _evThread (NULL)
+        , _regSession (NULL)
+        , _nextRefreshStamp (0)
+        , audiolayer (NULL)
+        , micData (NULL)
+        , micDataConverted (NULL)
+        , micDataEncoded (NULL)
+        , spkrDataDecoded (NULL)
+        , spkrDataConverted (NULL)
+        , converter (NULL)
+        , converterSamplingRate (NULL)
+        , urlhook (NULL)
+        , countTime (0)
 {
-    // _debug("IAXVoIPLink::IAXVoIPLink : creating eventhread  ");
     _evThread = new EventThread (this);
-    _regSession = NULL;
-    _nextRefreshStamp = 0;
-    countTime = 0;
 
     // to get random number for RANDOM_PORT
     srand (time (NULL));
 
-    audiolayer = NULL;
-
     converter = new SamplerateConverter();
 
     int nbSamplesMax = (int) (converter->getFrequence() * converter->getFramesize() / 1000);
@@ -82,26 +88,46 @@ IAXVoIPLink::IAXVoIPLink (const AccountID& accountID)
 
 IAXVoIPLink::~IAXVoIPLink()
 {
-    delete _evThread;
-    _evThread = NULL;
+    if (_evThread) {
+        delete _evThread;
+        _evThread = NULL;
+    }
+
     _regSession = NULL; // shall not delete it
     terminate();
 
     audiolayer = NULL;
 
-    delete converter;
+    if (converter) {
+        delete converter;
+        converter = NULL;
+    }
+
+    if (micData) {
+        delete [] micData;
+        micData = NULL;
+    }
+
+    if (micDataConverted) {
+        delete [] micDataConverted;
+        micDataConverted = NULL;
+    }
+
+    if (micDataEncoded) {
+        delete [] micDataEncoded;
+        micDataEncoded = NULL;
+    }
+
+    if (spkrDataDecoded) {
+        delete [] spkrDataDecoded;
+        spkrDataDecoded = NULL;
+    }
 
-    delete [] micData;
-    micData = NULL;
-    delete [] micDataConverted;
-    micDataConverted = NULL;
-    delete [] micDataEncoded;
-    micDataEncoded = NULL;
+    if (spkrDataConverted) {
+        delete [] spkrDataConverted;
+        spkrDataConverted = NULL;
+    }
 
-    delete [] spkrDataDecoded;
-    spkrDataDecoded = NULL;
-    delete [] spkrDataConverted;
-    spkrDataConverted = NULL;
 }
 
 bool
@@ -219,6 +245,8 @@ IAXVoIPLink::getEvent()
 {
     IAXCall* call = NULL;
 
+    Manager::instance().getAudioLayerMutex()->enter();
+
     // lock iax_ stuff..
     _mutexIAX.enterMutex();
     iax_event* event = NULL;
@@ -254,11 +282,7 @@ IAXVoIPLink::getEvent()
 
     sendAudioFromMic();
 
-    if (call) {
-        call->recAudio.recData (spkrDataDecoded, micData, nbSampleForRec_, nbSampleForRec_);
-
-        // Do the doodle-moodle to send audio from the microphone to the IAX channel.
-    }
+    Manager::instance().getAudioLayerMutex()->leave();
 
     // Do the doodle-moodle to send audio from the microphone to the IAX channel.
     // sendAudioFromMic();
@@ -495,7 +519,7 @@ IAXVoIPLink::newOutgoingCall (const CallID& id, const std::string& toUrl)
 
     if (call) {
         call->setPeerNumber (toUrl);
-        call->initRecFileName();
+        call->initRecFileName (toUrl);
 
         if (iaxOutgoingInvite (call)) {
             call->setConnectionState (Call::Progressing);
@@ -537,7 +561,7 @@ IAXVoIPLink::answer (const CallID& id)
 bool
 IAXVoIPLink::hangup (const CallID& id)
 {
-    _debug ("IAXVoIPLink::hangup() : function called once hangup ");
+    _debug ("IAXVoIPLink: Hangup");
     IAXCall* call = getIAXCall (id);
     std::string reason = "Dumped Call";
     CHK_VALID_CALL;
@@ -565,7 +589,7 @@ IAXVoIPLink::hangup (const CallID& id)
 bool
 IAXVoIPLink::peerHungup (const CallID& id)
 {
-    _debug ("IAXVoIPLink::peerHangup() : function called once hangup ");
+    _debug ("IAXVoIPLink: Peer hung up");
     IAXCall* call = getIAXCall (id);
     std::string reason = "Dumped Call";
     CHK_VALID_CALL;
@@ -681,6 +705,24 @@ IAXVoIPLink::carryingDTMFdigits (const CallID& id, char code)
     return true;
 }
 
+bool
+IAXVoIPLink::sendTextMessage (sfl::InstantMessaging *module, const std::string& callID, const std::string& message, const std::string& from)
+{
+    IAXCall* call = getIAXCall (callID);
+
+    CHK_VALID_CALL;
+
+    // Must active the mutex for this session
+    _mutexIAX.enterMutex();
+
+    module->send_iax_message (call->getSession(), callID, message.c_str());
+
+    // iax_send_text (call->getSession(), message.c_str());
+    _mutexIAX.leaveMutex();
+
+    return true;
+}
+
 
 std::string
 IAXVoIPLink::getCurrentCodecName()
@@ -870,6 +912,7 @@ IAXVoIPLink::iaxHandleCallEvent (iax_event* event, IAXCall* call)
             break;
 
         case IAX_EVENT_TEXT:
+            Manager::instance ().incomingMessage (call->getCallId (), call->getPeerNumber(), std::string ( (const char*) event->data));
             break;
 
         case IAX_EVENT_RINGA:
@@ -898,6 +941,37 @@ IAXVoIPLink::iaxHandleCallEvent (iax_event* event, IAXCall* call)
             break;
 
         case IAX_EVENT_TRANSFER:
+            _debug ("IAX_EVENT_TRANSFER");
+
+            if (call->getConnectionState() != Call::Connected) {
+
+                Manager::instance().addStream (call->getCallId());
+
+                call->setConnectionState (Call::Connected);
+                call->setState (Call::Active);
+                // audiolayer->startStream();
+
+                _debug ("IAX_EVENT_ANSWER: codec format: ");
+
+                if (event->ies.format) {
+                    // Should not get here, should have been set in EVENT_ACCEPT
+                    printf ("%i", event->ies.format);
+                    call->setFormat (event->ies.format);
+                }
+
+                {
+                    printf ("no codec format");
+                }
+
+                Manager::instance().peerAnsweredCall (id);
+
+                // start audio here?
+                audiolayer->startStream();
+                audiolayer->flushMain();
+            } else {
+                // deja connecté ?
+            }
+
             break;
 
         default:
@@ -1117,7 +1191,7 @@ IAXVoIPLink::iaxHandlePrecallEvent (iax_event* event)
                 call->setPeerName (std::string (event->ies.calling_name));
 
             // if peerNumber exist append it to the name string
-            call->initRecFileName();
+            call->initRecFileName (std::string (event->ies.calling_number));
 
             if (Manager::instance().incomingCall (call, getAccountID())) {
                 /** @todo Faudra considérer éventuellement le champ CODEC PREFS pour
diff --git a/sflphone-common/src/iax/iaxvoiplink.h b/sflphone-common/src/iax/iaxvoiplink.h
index 4fe101b4d07029b51947dd8cda6c9273fbaf3e5c..d01436caf50b9c8fd508483e748d90d7a9664939 100644
--- a/sflphone-common/src/iax/iaxvoiplink.h
+++ b/sflphone-common/src/iax/iaxvoiplink.h
@@ -40,6 +40,8 @@
 #include "audio/samplerateconverter.h"
 #include "hooks/urlhook.h"
 
+#include "im/InstantMessaging.h"
+
 class EventThread;
 class IAXCall;
 
@@ -188,9 +190,8 @@ class IAXVoIPLink : public VoIPLink
          */
         bool carryingDTMFdigits (const CallID& id, char code);
 
-        bool sendMessage (const std::string& to UNUSED, const std::string& body UNUSED) {
-            return false;
-        }
+
+        bool sendTextMessage (sfl::InstantMessaging *module, const std::string& callID, const std::string& message, const std::string& from);
 
         bool isContactPresenceSupported() {
             return false;
diff --git a/sflphone-common/src/im/InstantMessaging.cpp b/sflphone-common/src/im/InstantMessaging.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0f927ab291ee73da85ecc372e34e4078640c3cf4
--- /dev/null
+++ b/sflphone-common/src/im/InstantMessaging.cpp
@@ -0,0 +1,399 @@
+#include "InstantMessaging.h"
+
+#include "expat.h"
+
+namespace sfl
+{
+
+static inline char* duplicateString (char dst[], const char src[], size_t len)
+{
+    memcpy (dst, src, len);
+    dst[len] = 0;
+    return dst;
+}
+
+static void XMLCALL startElementCallback (void *userData, const char *name, const char **atts)
+{
+
+    char attribute[100];
+    char value[100];
+
+    const char **att;
+
+    // _debug ("InstantMessaging: StartElement Callback: %s", name);
+
+    if (strcmp (name, "entry") == 0) {
+
+        sfl::InstantMessaging::UriList *list = static_cast<sfl::InstantMessaging::UriList *> (userData);
+        sfl::InstantMessaging::UriEntry entry = sfl::InstantMessaging::UriEntry();
+
+        for (att = atts; *att; att += 2) {
+
+            const char **val = att+1;
+
+            duplicateString (attribute, *att, strlen (*att));
+            duplicateString (value, *val, strlen (*val));
+
+            // _debug ("InstantMessaging: attribute: %s, value: %s", attribute, value);
+
+            entry.insert (std::pair<std::string, std::string> (std::string (attribute), std::string (value)));
+        }
+
+        list->push_back (entry);
+    }
+
+}
+
+static void XMLCALL endElementCallback (void *userData, const char *name)
+{
+    // std::cout << "endElement " << name << std::endl;
+}
+
+
+InstantMessaging::InstantMessaging()
+        : imFiles ()
+        , messageMaxSize (MAXIMUM_MESSAGE_LENGTH) {}
+
+
+InstantMessaging::~InstantMessaging() {}
+
+bool InstantMessaging::init ()
+{
+    return true;
+}
+
+int InstantMessaging::openArchive (CallID& id)
+{
+
+    // Create a new file stream
+    std::ofstream File (id.c_str (), std::ios::out | std::ios::app);
+    imFiles[id] = &File;
+
+    // Attach it to the call ID
+    return (int) imFiles.size ();
+}
+
+int InstantMessaging::closeArchive (CallID& id)
+{
+
+    // Erase it from the map
+    imFiles.erase (id);
+    return (int) imFiles.size ();
+}
+
+bool InstantMessaging::saveMessage (const std::string& message, const std::string& author, CallID& id, int mode)
+{
+
+    // We need here to write the text message in the right file.
+    // We will use the Call ID
+
+    std::ofstream File;
+    std::string filename = "im:";
+
+    filename.append (id);
+    File.open (filename.c_str (), (std::_Ios_Openmode) mode);
+
+    if (!File.good () || !File.is_open ())
+        return false;
+
+    File << "[" << author << "] " << message << '\n';
+    File.close ();
+
+    return true;
+}
+
+std::string InstantMessaging::receive (const std::string& message, const std::string& author, CallID& id)
+{
+
+    // We just receive a TEXT message. Before sent it to the recipient, we must assure that the message is complete.
+    // We should use a queue to push these messages in
+
+    _debug ("New message : %s", message.c_str ());
+
+    // TODO Security check
+    // TODO String cleaning
+
+    // Archive the message
+    this->saveMessage (message, author, id);
+
+
+    return message;
+
+}
+
+pj_status_t InstantMessaging::notify (CallID& id)
+{
+    // Notify the clients through a D-Bus signal
+    return PJ_SUCCESS;
+}
+
+pj_status_t InstantMessaging::sip_send (pjsip_inv_session *session, CallID& id, const std::string& text)
+{
+
+    pjsip_method msg_method;
+    const pj_str_t type =  STR_TEXT;
+    const pj_str_t subtype = STR_PLAIN;
+    pjsip_tx_data *tdata;
+    pj_status_t status;
+    pjsip_dialog* dialog;
+    pj_str_t message;
+
+    msg_method.id = PJSIP_OTHER_METHOD;
+    msg_method.name = METHOD_NAME;
+
+    // Get the dialog associated to the call
+    dialog = session->dlg;
+    // Convert the text into a format readable by pjsip
+
+    message = pj_str ( (char*) text.c_str ());
+
+    // Must lock dialog
+    pjsip_dlg_inc_lock (dialog);
+
+    // Create the message request
+    status = pjsip_dlg_create_request (dialog, &msg_method, -1, &tdata);
+    PJ_ASSERT_RETURN (status == PJ_SUCCESS, 1);
+
+    // Attach "text/plain" body
+    tdata->msg->body = pjsip_msg_body_create (tdata->pool, &type, &subtype, &message);
+
+    // Create the Require header to handle recipient-list Content-Disposition type
+    // pjsip_generic_string_hdr reqhdr;
+    // pj_str_t reqhname = pj_str ("Require");
+    // pj_str_t reqhvalue = pj_str ("recipient-list");
+
+    // Create the Content-Type header to handle multipart/mixed and boundary MIME types
+    // pj_str_t ctype = pj_str ("Content-Type");
+    // pj_str_t sctype = pj_str ("ctype"); // small version of the header name
+    // ctypehdr = pjsip_msg_find_hdr_by_names (tdata->msg, &ctype, &sctype, NULL);
+    // pjsip_generic_string_hdr ctypehdr;
+    // pj_str_t ctypehname = pj_str ("Content-Type");
+    // pj_str_t ctypehvalue = pj_str ("multipart/mixed;boundary=\"boundary\"");
+
+    // Add headers to the message
+    // pjsip_generic_string_hdr_init2 (&reqhdr, &reqhname, &reqhvalue);
+    // pj_list_push_back (& (tdata->msg->hdr), (pjsip_hdr*) (&reqhdr));
+    // pj_list_push_back (& (tdata->msg->hdr), (pjsip_hdr*) (&ctypehdr));
+
+    // Send the request
+    status = pjsip_dlg_send_request (dialog, tdata, -1, NULL);
+    // PJ_ASSERT_RETURN (status == PJ_SUCCESS, 1);
+
+    // Done
+    pjsip_dlg_dec_lock (dialog);
+
+    // Archive the message
+    this->saveMessage (text, "Me", id);
+
+    printf ("SIPVoIPLink::sendTextMessage %s %s\n", id.c_str(), text.c_str());
+    return PJ_SUCCESS;
+}
+
+pj_status_t InstantMessaging::send_sip_message (pjsip_inv_session *session, CallID& id, const std::string& message)
+{
+
+    /* Check the length of the message */
+    if (message.length() < getMessageMaximumSize()) {
+        /* No problem here */
+        sip_send (session, id, message);
+    }
+
+    else {
+        /* It exceeds the size limit of a SIP MESSAGE (1300 bytes), o plit it and send multiple messages */
+        std::vector<std::string> multiple_messages = split_message (message);
+        /* Send multiple messages */
+        // int size = multiple_messages.size();
+        int i = 0;
+
+        // Maximum is above 1500 character
+        // TODO: Send every messages
+        sip_send (session, id, multiple_messages[i]);
+    }
+
+    return PJ_SUCCESS;
+}
+
+
+bool InstantMessaging::iax_send (iax_session* session, const CallID& id, const std::string& message)
+{
+    if (iax_send_text (session, message.c_str()) != -1)
+        return true;
+    else
+        return false;
+
+
+}
+
+bool InstantMessaging::send_iax_message (iax_session* session, const CallID& id, const std::string& message)
+{
+
+    bool ret;
+
+    /* Check the length of the message */
+    if (message.length() < getMessageMaximumSize()) {
+        /* No problem here */
+        ret = iax_send (session, id, message);
+    }
+
+    else {
+        /* It exceeds the size limit of a SIP MESSAGE (1300 bytes), o plit it and send multiple messages */
+        std::vector<std::string> multiple_messages = split_message (message);
+        /* Send multiple messages */
+        // int size = multiple_messages.size();
+        int i = 0;
+
+        // Maximum is above 1500 character
+        // TODO: Send every messages
+        ret = iax_send (session, id, multiple_messages[i]);
+    }
+
+    return ret;
+}
+
+
+std::vector<std::string> InstantMessaging::split_message (const std::string& text)
+{
+
+    std::vector<std::string> messages;
+    std::string text_to_split = text;
+
+    /* Iterate over the message length */
+    while (text_to_split.length() > getMessageMaximumSize()) {
+        /* The remaining string is still too long */
+
+        /* Compute the substring */
+        std::string split_message = text_to_split.substr (0, (size_t) getMessageMaximumSize());
+        /* Append our split character \n\n */
+        split_message.append (DELIMITER_CHAR);
+        /* Append in the vector */
+        messages.push_back (split_message);
+        /* Use the remaining string to not loop forever */
+        text_to_split = text_to_split.substr ( (size_t) getMessageMaximumSize());
+    }
+
+    /* Push the last message */
+    /* If the message length does not exceed the maximum size of a SIP MESSAGE, we go directly here */
+    messages.push_back (text_to_split);
+
+    return messages;
+}
+
+std::string InstantMessaging::generateXmlUriList (UriList& list)
+{
+
+    std::string xmlbuffer = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+    xmlbuffer.append ("<resource-lists xmlns=\"urn:ietf:params:xml:ns:resource-lists\" xmlns:cp=\"urn:ietf:params:xml:ns:copycontrol\">");
+    xmlbuffer.append ("<list>");
+
+    // An iterator over xml attribute
+    UriEntry::iterator iterAttr;
+
+    // An iterator over list entries
+    UriList::iterator iterEntry = list.begin();
+
+    while (iterEntry != list.end()) {
+        xmlbuffer.append ("<entry uri=");
+        UriEntry entry = static_cast<UriEntry> (*iterEntry);
+        iterAttr = entry.find (sfl::IM_XML_URI);
+        xmlbuffer.append (iterAttr->second);
+        xmlbuffer.append (" cp:copyControl=\"to\" />");
+
+        iterEntry++;
+    }
+
+    xmlbuffer.append ("</list>");
+    xmlbuffer.append ("</resource-lists>");
+
+    return xmlbuffer;
+}
+
+
+InstantMessaging::UriList InstantMessaging::parseXmlUriList (std::string& urilist)
+{
+    InstantMessaging::UriList list;
+
+    XML_Parser parser = XML_ParserCreate (NULL);
+    XML_SetUserData (parser, &list);
+    XML_SetElementHandler (parser, startElementCallback, endElementCallback);
+
+    if (XML_Parse (parser, urilist.c_str(), urilist.size(), 1) == XML_STATUS_ERROR) {
+        std::cout << "Error: " << XML_ErrorString (XML_GetErrorCode (parser))
+                  << " at line " << XML_GetCurrentLineNumber (parser) << std::endl;
+        throw InstantMessageException ("Error while parsing uri-list xml content");
+    }
+
+    return list;
+}
+
+std::string InstantMessaging::appendUriList (std::string text, UriList& list)
+{
+
+    std::string formatedText = "--boundary Content-Type: text/plain";
+
+    formatedText.append (text);
+    formatedText.append ("--boundary Content-Type: application/resource-lists+xml");
+    formatedText.append ("Content-Disposition: recipient-list");
+
+    std::string recipientlist = generateXmlUriList (list);
+
+    formatedText.append (recipientlist);
+
+    formatedText.append ("--boundary--");
+
+    return formatedText;
+}
+
+std::string InstantMessaging::findTextUriList (std::string& text)
+{
+    std::string ctype = "Content-Type: application/resource-lists+xml";
+    std::string cdispo = "Content-Disposition: recipient-list";
+    std::string boundary = ("--boundary--");
+
+    // init position pointer
+    size_t pos = 0;
+    size_t begin = 0;
+    size_t end = 0;
+
+    // find the content type
+    if ( (pos = text.find (ctype)) == std::string::npos)
+        throw InstantMessageException ("Could not find Content-Type tag while parsing sip message for recipient-list");
+
+    // find the content disposition
+    if ( (pos = text.find (cdispo, pos)) == std::string::npos)
+        throw InstantMessageException ("Could not find Content-Disposition tag while parsing sip message for recipient-list");
+
+    // xml content start after content disposition tag (plus \n\n)
+    begin = pos+cdispo.size();
+
+    // find final boundary
+    if ( (end = text.find (boundary, begin)) == std::string::npos)
+        throw InstantMessageException ("Could not find final \"boundary\" while parsing sip message for recipient-list");
+
+    return text.substr (begin, end-begin);
+}
+
+std::string InstantMessaging::findTextMessage (std::string& text)
+{
+    std::string ctype = "Content-Type: text/plain";
+    std::string boundary = "--boundary";
+
+    size_t pos = 0;
+    size_t begin = 0;
+    size_t end = 0;
+
+    // find the content type
+    if ( (pos = text.find (ctype)) == std::string::npos)
+        throw InstantMessageException ("Could not find Content-Type tag while parsing sip message for text");
+
+    // plain text content start after content type tag (plus \n\n)
+    begin = pos+ctype.size();
+
+    // retrive end of the text content
+    if ( (end = text.find (boundary, begin)) == std::string::npos)
+        throw InstantMessageException ("Could not find end of text \"boundary\" while parsing sip message for text");
+
+    return text.substr (begin, end-begin);
+}
+
+
+}
diff --git a/sflphone-common/src/sip/im/InstantMessaging.h b/sflphone-common/src/im/InstantMessaging.h
similarity index 57%
rename from sflphone-common/src/sip/im/InstantMessaging.h
rename to sflphone-common/src/im/InstantMessaging.h
index bcc25d85c11dbeb6577ea2d574e99fb7b78bacb1..3ba52df45c1b9ab394c1e2767ccff9dd979270e9 100644
--- a/sflphone-common/src/sip/im/InstantMessaging.h
+++ b/sflphone-common/src/im/InstantMessaging.h
@@ -12,6 +12,12 @@
 #include "call.h"
 #include "sip/sipcall.h"
 
+#include <map>
+#include <list>
+#include <exception>
+
+#include <iax-client.h>
+
 #define EMPTY_MESSAGE   pj_str((char*)"")
 #define STR_TEXT        pj_str((char*)"text")
 #define STR_PLAIN       pj_str((char*)"plain")
@@ -25,9 +31,34 @@
 namespace sfl
 {
 
+const std::string IM_XML_URI ("uri");
+const std::string BOUNDARY ("--boundary");
+
+class InstantMessageException : public std::exception
+{
+    public:
+        InstantMessageException (const std::string& str="") throw() : errstr (str) {}
+
+        virtual ~InstantMessageException() throw() {}
+
+        virtual const char *what() const throw() {
+            std::string expt ("InstantMessageException occured: ");
+            expt.append (errstr);
+
+            return expt.c_str();
+        }
+    private:
+        std::string errstr;
+};
+
 class InstantMessaging
 {
+
     public:
+
+        typedef std::map <std::string, std::string> UriEntry;
+        typedef std::list <UriEntry> UriList;
+
         /*
          * Class constructor
          */
@@ -100,9 +131,13 @@ class InstantMessaging
          * @return pj_status_t  0 on success
          *                      1 otherwise
          */
-        pj_status_t send (pjsip_inv_session*, CallID& id, const std::string&);
+        pj_status_t sip_send (pjsip_inv_session*, CallID& id, const std::string&);
 
-        pj_status_t send_message (pjsip_inv_session*, CallID& id, const std::string&);
+        pj_status_t send_sip_message (pjsip_inv_session*, CallID& id, const std::string&);
+
+        bool iax_send (iax_session* session, const CallID& id, const std::string& message);
+
+        bool send_iax_message (iax_session *session, const CallID& id, const std::string&);
 
         std::vector<std::string> split_message (const std::string&);
 
@@ -114,6 +149,54 @@ class InstantMessaging
          */
         pj_status_t notify (CallID& id);
 
+
+        /**
+         * Generate Xml participant list for multi recipient based on RFC Draft 5365
+         *
+        * @param A UriList of UriEntry
+        *
+        * @return A string containing the full XML formated information to be included in the
+        *         sip instant message.
+        */
+        std::string generateXmlUriList (UriList& list);
+
+        /**
+         * Parse the Urilist from a SIP Instant Message provided by a UriList service.
+         *
+         * @param A XML formated string as obtained from a SIP instant message.
+         *
+         * @return An UriList of UriEntry containing parsed XML information as a map.
+         */
+        UriList parseXmlUriList (std::string& urilist);
+
+        /**
+         * Format text message according to RFC 5365, append recipient-list to the message
+         *
+         * @param text to be displayed
+         * @param list containing the recipients
+         *
+         * @return formated text stored into a string to be included in sip MESSAGE
+         */
+        std::string appendUriList (std::string text, UriList& list);
+
+        /**
+             * Retreive the xml formated uri list in formated text data according to RFC 5365
+             *
+         * @param text The formated text message as retreived in the SIP message
+         *
+         * @return A string containing the XML content
+         */
+        std::string findTextUriList (std::string& text);
+
+        /**
+             * Retrive the plain text message in formated text data according to RFC 5365
+             *
+         * @param text The formated text message as retreived in the SIP message
+         *
+         * @return A string containing the actual message
+         */
+        std::string findTextMessage (std::string& text);
+
     private:
 
         /**
diff --git a/sflphone-common/src/sip/im/Makefile.am b/sflphone-common/src/im/Makefile.am
similarity index 100%
rename from sflphone-common/src/sip/im/Makefile.am
rename to sflphone-common/src/im/Makefile.am
diff --git a/sflphone-common/src/managerimpl.cpp b/sflphone-common/src/managerimpl.cpp
index ccdfa03f8afdb004de41d531bbec9753dc703084..8bbc44abbce67a2dde7a19e3952ec0d170913136 100644
--- a/sflphone-common/src/managerimpl.cpp
+++ b/sflphone-common/src/managerimpl.cpp
@@ -48,6 +48,7 @@
 #include "history/historymanager.h"
 #include "accountcreator.h" // create new account
 #include "sip/sipvoiplink.h"
+#include "iax/iaxvoiplink.h"
 #include "manager.h"
 #include "dbus/configurationmanager.h"
 
@@ -92,6 +93,7 @@ ManagerImpl::ManagerImpl (void) :
 
     _cleaner = new NumberCleaner();
     _history = new HistoryManager();
+    _imModule = new sfl::InstantMessaging();
 
 #ifdef TEST
     testAccountMap();
@@ -117,6 +119,8 @@ ManagerImpl::~ManagerImpl (void)
     _cleaner = NULL;
     delete _history;
     _history = NULL;
+    delete _imModule;
+    _imModule = NULL;
 
     _debug ("Manager: %s stop correctly.", PROGNAME);
 }
@@ -159,6 +163,11 @@ void ManagerImpl::init ()
 
     // Load the history
     _history->load_history (preferences.getHistoryLimit());
+
+    // Init the instant messaging module
+    _imModule->init();
+
+
 }
 
 void ManagerImpl::terminate ()
@@ -1712,7 +1721,6 @@ void ManagerImpl::incomingMessage (const CallID& callID,
                                    const std::string& from,
                                    const std::string& message)
 {
-    SIPVoIPLink *link = NULL;
 
     if (participToConference (callID)) {
         _debug ("Manager: Particip to a conference, send message to everyone");
@@ -1724,38 +1732,104 @@ void ManagerImpl::incomingMessage (const CallID& callID,
 
         while (iter_participant != participants.end()) {
 
+            if (*iter_participant == callID)
+                continue;
+
             AccountID accountId = getAccountFromCall (*iter_participant);
 
             _debug ("Manager: Send message to %s, (%s)", (*iter_participant).c_str(), accountId.c_str());
 
-            if (*iter_participant != callID) {
+            Account *account = getAccount (accountId);
 
-                link = SIPVoIPLink::instance (""); // dynamic_cast<SIPVoIPLink *> (getAccountLink (*iter_participant));
+            if (!account) {
+                _debug ("Manager: Failed to get account while sending instant message");
+                return;
+            }
 
-                if (link)
-                    link->sendTextMessage (*iter_participant, message);
+            if (account->getType() == "SIP")
+                // link = dynamic_cast<SIPVoIPLink *> (getAccountLink (accountId));
+                dynamic_cast<SIPVoIPLink *> (getAccountLink (accountId))->sendTextMessage (_imModule, callID, message, from);
+            else if (account->getType() == "IAX")
+                // link = dynamic_cast<IAXVoIPLink *> (account->getVoIPLink());
+                dynamic_cast<IAXVoIPLink *> (account->getVoIPLink())->sendTextMessage (_imModule, callID, message, from);
+            else {
+                _debug ("Manager: Failed to get voip link while sending instant message");
+                return;
             }
 
             iter_participant++;
         }
-    }
 
-    if (_dbus) {
-        _dbus->getCallManager()->incomingMessage (callID, from, message);
+        // in case of a conference we must notify client using conference id
+        if (_dbus) {
+            _dbus->getCallManager()->incomingMessage (conf->getConfID(), from, message);
+        }
+
+    } else {
+
+        if (_dbus) {
+            _dbus->getCallManager()->incomingMessage (callID, from, message);
+        }
     }
 }
 
 
 //THREAD=VoIP
-bool ManagerImpl::sendTextMessage (const CallID& callID, const std::string& message)
+bool ManagerImpl::sendTextMessage (const CallID& callID, const std::string& message, const std::string& from)
 {
-    SIPVoIPLink * link = NULL;
+
+    if (isConference (callID)) {
+        _debug ("Manager: Is a conference, send instant message to everyone");
+
+        ConferenceMap::iterator it = _conferencemap.find (callID);
+
+        if (it == _conferencemap.end())
+            return false;
+
+        Conference *conf = it->second;
+
+        if (!conf)
+            return false;
+
+        ParticipantSet participants = conf->getParticipantList();
+        ParticipantSet::iterator iter_participant = participants.begin();
+
+        while (iter_participant != participants.end()) {
+
+            AccountID accountId = getAccountFromCall (*iter_participant);
+
+            Account *account = getAccount (accountId);
+
+            if (!account) {
+                _debug ("Manager: Failed to get account while sending instant message");
+                return false;
+            }
+
+            if (account->getType() == "SIP")
+                // link = dynamic_cast<SIPVoIPLink *> (getAccountLink (accountId));
+                dynamic_cast<SIPVoIPLink *> (getAccountLink (accountId))->sendTextMessage (_imModule, *iter_participant, message, from);
+            else if (account->getType() == "IAX")
+                // link = dynamic_cast<IAXVoIPLink *> (account->getVoIPLink());
+                dynamic_cast<IAXVoIPLink *> (account->getVoIPLink())->sendTextMessage (_imModule, *iter_participant, message, from);
+            else {
+                _debug ("Manager: Failed to get voip link while sending instant message");
+                return false;
+            }
+
+            iter_participant++;
+        }
+
+        return true;
+    }
 
     if (participToConference (callID)) {
-        _debug ("Manager: Particip to a conference, send message on everyone");
+        _debug ("Manager: Particip to a conference, send instant message to everyone");
 
         Conference *conf = getConferenceFromCallID (callID);
 
+        if (!conf)
+            return false;
+
         ParticipantSet participants = conf->getParticipantList();
         ParticipantSet::iterator iter_participant = participants.begin();
 
@@ -1763,12 +1837,23 @@ bool ManagerImpl::sendTextMessage (const CallID& callID, const std::string& mess
 
             AccountID accountId = getAccountFromCall (*iter_participant);
 
-            _debug ("Manager: Send message to %s (%s)", (*iter_participant).c_str(), accountId.c_str());
-            link = SIPVoIPLink::instance (""); // dynamic_cast<SIPVoIPLink *> (getAccountLink (*iter_participant));
+            Account *account = getAccount (accountId);
 
+            if (!account) {
+                _debug ("Manager: Failed to get account while sending instant message");
+                return false;
+            }
 
-            if (link)
-                link->sendTextMessage (*iter_participant, message);
+            if (account->getType() == "SIP")
+                // link = dynamic_cast<SIPVoIPLink *> (getAccountLink (accountId));
+                dynamic_cast<SIPVoIPLink *> (getAccountLink (accountId))->sendTextMessage (_imModule, *iter_participant, message, from);
+            else if (account->getType() == "IAX")
+                // link = dynamic_cast<IAXVoIPLink *> (account->getVoIPLink());
+                dynamic_cast<IAXVoIPLink *> (account->getVoIPLink())->sendTextMessage (_imModule, *iter_participant, message, from);
+            else {
+                _debug ("Manager: Failed to get voip link while sending instant message");
+                return false;
+            }
 
             iter_participant++;
         }
@@ -1777,15 +1862,23 @@ bool ManagerImpl::sendTextMessage (const CallID& callID, const std::string& mess
 
         AccountID accountId = getAccountFromCall (callID);
 
-        link = dynamic_cast<SIPVoIPLink *> (getAccountLink (accountId));
+        Account *account = getAccount (accountId);
 
-        if (link == NULL) {
-            _debug ("Manager: Failed to get sip link");
+        if (!account) {
+            _debug ("Manager: Failed to get account while sending instant message");
             return false;
         }
 
-        _debug ("Manager: Send message to %s (%s)", callID.c_str(), accountId.c_str());
-        link->sendTextMessage (callID, message);
+        if (account->getType() == "SIP")
+            // link = dynamic_cast<SIPVoIPLink *> (getAccountLink (accountId));
+            dynamic_cast<SIPVoIPLink *> (getAccountLink (accountId))->sendTextMessage (_imModule, callID, message, from);
+        else if (account->getType() == "IAX")
+            // link = dynamic_cast<IAXVoIPLink *> (account->getVoIPLink());
+            dynamic_cast<IAXVoIPLink *> (account->getVoIPLink())->sendTextMessage (_imModule, callID, message, from);
+        else {
+            _debug ("Manager: Failed to get voip link while sending instant message");
+            return false;
+        }
     }
 
     return true;
@@ -2733,30 +2826,6 @@ std::string ManagerImpl::getCurrentAudioOutputPlugin (void)
 }
 
 
-std::string ManagerImpl::getEchoCancelState (void)
-{
-
-    std::string state;
-
-    state = audioPreference.getEchoCancel() ? "enabled" : "disabled";
-
-    return state;
-}
-
-void ManagerImpl::setEchoCancelState (std::string state)
-{
-    _debug ("Manager: Set echo suppress state: %s", state.c_str());
-
-    bool isEnabled = state == "enabled" ? true : false;
-
-    audioPreference.setEchoCancel (isEnabled);
-
-    if (_audiodriver) {
-        _audiodriver->setEchoCancelState (isEnabled);
-    }
-}
-
-
 std::string ManagerImpl::getNoiseSuppressState (void)
 {
 
@@ -3790,7 +3859,7 @@ void ManagerImpl::unloadAccountMap ()
 
     while (iter != _accountMap.end()) {
 
-        _debug ("Unloading account %s", iter->first.c_str());
+        _debug ("Manager: Unloading account %s", iter->first.c_str());
 
         delete iter->second;
         iter->second = NULL;
diff --git a/sflphone-common/src/managerimpl.h b/sflphone-common/src/managerimpl.h
index db6c91ccf705d10148ed118d493cbbd8ac1c5286..2e2c729b804ed8829df7af63cdc4db059069c59c 100644
--- a/sflphone-common/src/managerimpl.h
+++ b/sflphone-common/src/managerimpl.h
@@ -59,6 +59,8 @@
 #include "yamlparser.h"
 #include "preferences.h"
 
+#include "im/InstantMessaging.h"
+
 class AudioLayer;
 class GuiFramework;
 class TelephoneTone;
@@ -448,11 +450,12 @@ class ManagerImpl
 
 
         /**
-           * Send a new text message to the call, if participate to a conference, send to all participant.
+         * Send a new text message to the call, if participate to a conference, send to all participant.
          * @param callID	The call to send the message
          * @param message	The content of the message
-             */
-        bool sendTextMessage (const CallID& callID, const std::string& message);
+        * @param from	        The sender of this message (could be another participant of a conference)
+         */
+        bool sendTextMessage (const CallID& callID, const std::string& message, const std::string& from);
 
         /**
          * Notify the client he has voice mails
@@ -616,12 +619,16 @@ class ManagerImpl
          */
         std::string getCurrentAudioOutputPlugin (void);
 
-        std::string getEchoCancelState (void);
-
-        void setEchoCancelState (std::string state);
-
+        /**
+         * Get the noise reduction engin state from
+         * the current audio layer.
+         */
         std::string getNoiseSuppressState (void);
 
+        /**
+         * Set the noise reduction engin state in the current
+         * audio layer.
+         */
         void setNoiseSuppressState (std::string state);
 
         /**
@@ -1308,6 +1315,13 @@ class ManagerImpl
         MainBuffer _mainBuffer;
 
 
+        /**
+         * Instant messaging module, resposible to initiate, format, parse,
+         * send, and receive instant messages.
+         */
+        sfl::InstantMessaging *_imModule;
+
+
     public:
 
         /**
@@ -1317,6 +1331,13 @@ class ManagerImpl
             return &_mainBuffer;
         }
 
+        /**
+         * Return a pointer to the instance of InstantMessaging
+         */
+        sfl::InstantMessaging *getInstantMessageModule (void) {
+            return _imModule;
+        }
+
 
         /**
          * Tell if there is a current call processed
diff --git a/sflphone-common/src/preferences.cpp b/sflphone-common/src/preferences.cpp
index 310e214e7f51a7002455abc4868d7ba05781a24d..2354ad15bc62c0b0414c8ea1ecb46d8e907ed5a0 100644
--- a/sflphone-common/src/preferences.cpp
+++ b/sflphone-common/src/preferences.cpp
@@ -34,7 +34,7 @@
 #include "user_cfg.h"
 
 Preferences::Preferences() :  _accountOrder ("")
-        , _audioApi (0)
+        , _audioApi (1) // 1 is pulseaudio, 0 alsa
         , _historyLimit (30)
         , _historyMaxCalls (20)
         , _notifyMails (false)
@@ -59,9 +59,9 @@ void Preferences::serialize (Conf::YamlEmitter *emiter)
     Conf::MappingNode preferencemap (NULL);
 
     Conf::ScalarNode order (_accountOrder);
-    std::stringstream audiostr;
-    audiostr << _audioApi;
-    Conf::ScalarNode audioapi (audiostr.str());
+    // std::stringstream audiostr;
+    // audiostr << _audioApi;
+    Conf::ScalarNode audioapi (_audioApi == 1 ? "pulseaudio" : "alsa");
     std::stringstream histlimitstr;
     histlimitstr << _historyLimit;
     Conf::ScalarNode historyLimit (histlimitstr.str());
@@ -115,7 +115,8 @@ void Preferences::unserialize (Conf::MappingNode *map)
     val = (Conf::ScalarNode *) (map->getValue (audioApiKey));
 
     if (val) {
-        _audioApi = atoi (val->getValue().data());
+        // 1 is pulseaudio, 0 is alsa
+        _audioApi = (val->getValue().compare ("pulseaudio") == 0) ? 1 : 0;
         val = NULL;
     }
 
@@ -190,7 +191,6 @@ void Preferences::unserialize (Conf::MappingNode *map)
 VoipPreference::VoipPreference() :  _playDtmf (true)
         , _playTones (true)
         , _pulseLength (atoi (DFT_PULSE_LENGTH_STR)) // DFT_PULSE_LENGTH_STR
-        , _sendDtmfAs (0)
         , _symmetricRtp (true)
         , _zidFile (ZRTP_ZIDFILE) // ZRTP_ZID_FILENAME
 {
@@ -211,16 +211,12 @@ void VoipPreference::serialize (Conf::YamlEmitter *emitter)
     std::stringstream pulselengthstr;
     pulselengthstr << _pulseLength;
     Conf::ScalarNode pulseLength (pulselengthstr.str());
-    std::stringstream senddtmfstr;
-    senddtmfstr << _sendDtmfAs;
-    Conf::ScalarNode sendDtmfAs (senddtmfstr.str());
     Conf::ScalarNode symmetricRtp (_symmetricRtp ? "true" : "false");
     Conf::ScalarNode zidFile (_zidFile.c_str());
 
     preferencemap.setKeyValue (playDtmfKey, &playDtmf);
     preferencemap.setKeyValue (playTonesKey, &playTones);
     preferencemap.setKeyValue (pulseLengthKey, &pulseLength);
-    preferencemap.setKeyValue (sendDtmfAsKey, &sendDtmfAs);
     preferencemap.setKeyValue (symmetricRtpKey, &symmetricRtp);
     preferencemap.setKeyValue (zidFileKey, &zidFile);
 
@@ -258,13 +254,6 @@ void VoipPreference::unserialize (Conf::MappingNode *map)
         val = NULL;
     }
 
-    val = (Conf::ScalarNode *) (map->getValue (sendDtmfAsKey));
-
-    if (val) {
-        _sendDtmfAs = atoi (val->getValue().data());
-        val = NULL;
-    }
-
     val = (Conf::ScalarNode *) (map->getValue (symmetricRtpKey));
 
     if (val && !val->getValue().empty()) {
@@ -489,7 +478,6 @@ AudioPreference::AudioPreference() : _cardin (atoi (ALSA_DFT_CARD)) // ALSA_DFT_
         , _volumemic (atoi (DFT_VOL_SPKR_STR)) // DFT_VOL_SPKR_STR
         , _volumespkr (atoi (DFT_VOL_MICRO_STR)) // DFT_VOL_MICRO_STR
         , _noisereduce (true)
-        , _echocancel (true)
 {
 
 }
@@ -536,8 +524,6 @@ void AudioPreference::serialize (Conf::YamlEmitter *emitter)
     spkrstr << _volumespkr;
     Conf::ScalarNode volumespkr (spkrstr.str()); //: 100
     Conf::ScalarNode noise (_noisereduce ? "true":"false");
-    Conf::ScalarNode echo (_echocancel ? "true":"false");
-
     preferencemap.setKeyValue (recordpathKey, &recordpath);
     preferencemap.setKeyValue (volumemicKey, &volumemic);
     preferencemap.setKeyValue (volumespkrKey, &volumespkr);
@@ -556,7 +542,6 @@ void AudioPreference::serialize (Conf::YamlEmitter *emitter)
     pulsepreferencemap.setKeyValue (deviceRingtoneKey, &deviceRingtone);
 
     preferencemap.setKeyValue (noiseReduceKey, &noise);
-    preferencemap.setKeyValue (echocancelKey, &echo);
 
     emitter->serializeAudioPreference (&preferencemap);
 
@@ -603,13 +588,6 @@ void AudioPreference::unserialize (Conf::MappingNode *map)
         val = NULL;
     }
 
-    val = (Conf::ScalarNode *) (map->getValue (echocancelKey));
-
-    if (val) {
-        _echocancel = (val->getValue() == "true");
-        val = NULL;
-    }
-
     alsamap = (Conf::MappingNode *) (map->getValue ("alsa"));
 
     // did found alsa
diff --git a/sflphone-common/src/preferences.h b/sflphone-common/src/preferences.h
index eb22c6cc3a1022bac105ac77f4534e058fb2003d..7a5c78cb5ff4c28e659f15da43612cb1bcfea4c7 100644
--- a/sflphone-common/src/preferences.h
+++ b/sflphone-common/src/preferences.h
@@ -50,7 +50,6 @@ const Conf::Key md5HashKey ("md5Hash");                     // :	false
 const Conf::Key playDtmfKey ("playDtmf"); // true                    true
 const Conf::Key playTonesKey ("playTones"); // true
 const Conf::Key pulseLengthKey ("pulseLength"); //=250
-const Conf::Key sendDtmfAsKey ("sendDtmfAs");// =0
 const Conf::Key symmetricRtpKey ("symmetric");// =true
 const Conf::Key zidFileKey ("zidFile");// =sfl.zid
 
@@ -74,21 +73,19 @@ const Conf::Key urlSipFieldKey ("urlSipField"); //:		X-sflphone-url
 // audio preferences
 const Conf::Key alsamapKey ("alsa");
 const Conf::Key pulsemapKey ("pulse");
-const Conf::Key cardinKey ("cardin");// : 0
-const Conf::Key cardoutKey ("cardout");// 0
-const Conf::Key cardringKey ("cardring");// : 0
-const Conf::Key framesizeKey ("framesize");// : 20
+const Conf::Key cardinKey ("cardIn");// : 0
+const Conf::Key cardoutKey ("cardOut");// 0
+const Conf::Key cardringKey ("cardRing");// : 0
+const Conf::Key framesizeKey ("frameSize");// : 20
 const Conf::Key pluginKey ("plugin"); //: default
-const Conf::Key smplrateKey ("smplrate");//: 44100
+const Conf::Key smplrateKey ("smplRate");//: 44100
 const Conf::Key devicePlaybackKey ("devicePlayback");//:
 const Conf::Key deviceRecordKey ("deviceRecord");// :
 const Conf::Key deviceRingtoneKey ("deviceRingtone");// :
-const Conf::Key recordpathKey ("recordpath");//: /home/msavard/Bureau
-const Conf::Key volumemicKey ("volumemic");//:  100
-const Conf::Key volumespkrKey ("volumespkr");//: 100
+const Conf::Key recordpathKey ("recordPath");//: /home/msavard/Bureau
+const Conf::Key volumemicKey ("volumeMic");//:  100
+const Conf::Key volumespkrKey ("volumeSpkr");//: 100
 const Conf::Key noiseReduceKey ("noiseReduce");
-const Conf::Key echocancelKey ("echocancel");
-
 
 // shortcut preferences
 const Conf::Key hangupShortKey ("hangUp");
@@ -242,13 +239,6 @@ class VoipPreference : public Serializable
             _pulseLength = length;
         }
 
-        int getSendDtmfAs (void) {
-            return _sendDtmfAs;
-        }
-        void setSendDtmfAs (int dtmf) {
-            _sendDtmfAs = dtmf;
-        }
-
         bool getSymmetricRtp (void) {
             return _symmetricRtp;
         }
@@ -268,7 +258,6 @@ class VoipPreference : public Serializable
         bool _playDtmf;
         bool _playTones;
         int _pulseLength;
-        int _sendDtmfAs;
         bool _symmetricRtp;
         std::string _zidFile;
 
@@ -524,14 +513,6 @@ class AudioPreference : public Serializable
             _noisereduce = noise;
         }
 
-        bool getEchoCancel (void) {
-            return _echocancel;
-        }
-
-        void setEchoCancel (bool echo) {
-            _echocancel = echo;
-        }
-
     private:
 
         // alsa preference
@@ -553,7 +534,6 @@ class AudioPreference : public Serializable
         int _volumespkr; //: 100
 
         bool _noisereduce;
-        bool _echocancel;
 };
 
 
diff --git a/sflphone-common/src/sip/Makefile.am b/sflphone-common/src/sip/Makefile.am
index 9043a15a5badd977412259d78ce0bcc3cf2e320e..c20fea5c288d339dded2e64d178dfd2ad5896e68 100644
--- a/sflphone-common/src/sip/Makefile.am
+++ b/sflphone-common/src/sip/Makefile.am
@@ -1,5 +1,3 @@
-SUBDIRS=im
-
 include $(top_srcdir)/globals.mak
 
 noinst_LTLIBRARIES = libsiplink.la
@@ -13,8 +11,6 @@ libsiplink_la_SOURCES = \
 		sipcall.cpp \
 		sipvoiplink.cpp
 
-libsiplink_la_LIBADD =	im/libim.la 
-
 noinst_HEADERS = \
 		Pattern.h \
 		SdesNegotiator.h \
diff --git a/sflphone-common/src/sip/im/InstantMessaging.cpp b/sflphone-common/src/sip/im/InstantMessaging.cpp
deleted file mode 100644
index d44acfdff140df5b451d8c2f8c6736edfa1690a0..0000000000000000000000000000000000000000
--- a/sflphone-common/src/sip/im/InstantMessaging.cpp
+++ /dev/null
@@ -1,178 +0,0 @@
-#include "InstantMessaging.h"
-
-namespace sfl
-{
-
-InstantMessaging::InstantMessaging()
-        : imFiles ()
-        , messageMaxSize (MAXIMUM_MESSAGE_LENGTH) {}
-
-
-InstantMessaging::~InstantMessaging() {}
-
-bool InstantMessaging::init ()
-{
-    return true;
-}
-
-int InstantMessaging::openArchive (CallID& id)
-{
-
-    // Create a new file stream
-    std::ofstream File (id.c_str (), std::ios::out | std::ios::app);
-    imFiles[id] = &File;
-
-    // Attach it to the call ID
-    return (int) imFiles.size ();
-}
-
-int InstantMessaging::closeArchive (CallID& id)
-{
-
-    // Erase it from the map
-    imFiles.erase (id);
-    return (int) imFiles.size ();
-}
-
-bool InstantMessaging::saveMessage (const std::string& message, const std::string& author, CallID& id, int mode)
-{
-
-    // We need here to write the text message in the right file.
-    // We will use the Call ID
-
-    std::ofstream File;
-    std::string filename = "im:";
-
-    filename.append (id);
-    File.open (filename.c_str (), (std::_Ios_Openmode) mode);
-
-    if (!File.good () || !File.is_open ())
-        return false;
-
-    File << "[" << author << "] " << message << '\n';
-    File.close ();
-
-    return true;
-}
-
-std::string InstantMessaging::receive (const std::string& message, const std::string& author, CallID& id)
-{
-
-    // We just receive a TEXT message. Before sent it to the recipient, we must assure that the message is complete.
-    // We should use a queue to push these messages in
-
-    _debug ("New message : %s", message.c_str ());
-
-    // TODO Security check
-    // TODO String cleaning
-
-    // Archive the message
-    this->saveMessage (message, author, id);
-
-
-    return message;
-
-}
-
-pj_status_t InstantMessaging::notify (CallID& id)
-{
-    // Notify the clients through a D-Bus signal
-    return PJ_SUCCESS;
-}
-
-pj_status_t InstantMessaging::send (pjsip_inv_session *session, CallID& id, const std::string& text)
-{
-
-    pjsip_method msg_method;
-    const pj_str_t type =  STR_TEXT;
-    const pj_str_t subtype = STR_PLAIN;
-    pjsip_tx_data *tdata;
-    pj_status_t status;
-    pjsip_dialog* dialog;
-    pj_str_t message;
-
-    msg_method.id = PJSIP_OTHER_METHOD;
-    msg_method.name = METHOD_NAME ;
-
-
-    // Get the dialog associated to the call
-    dialog = session->dlg;
-    // Convert the text into a format readable by pjsip
-    message = pj_str ( (char*) text.c_str ());
-
-    // Must lock dialog
-    pjsip_dlg_inc_lock (dialog);
-
-    // Create the message request
-    status = pjsip_dlg_create_request (dialog, &msg_method, -1, &tdata);
-    PJ_ASSERT_RETURN (status == PJ_SUCCESS, 1);
-
-    // Attach "text/plain" body
-    tdata->msg->body = pjsip_msg_body_create (tdata->pool, &type, &subtype, &message);
-
-    // Send the request
-    status = pjsip_dlg_send_request (dialog, tdata, -1, NULL);
-    // PJ_ASSERT_RETURN (status == PJ_SUCCESS, 1);
-
-    // Done
-    pjsip_dlg_dec_lock (dialog);
-
-    // Archive the message
-    this->saveMessage (text, "Me", id);
-
-    printf ("SIPVoIPLink::sendTextMessage %s %s\n", id.c_str(), text.c_str());
-    return PJ_SUCCESS;
-}
-
-pj_status_t InstantMessaging::send_message (pjsip_inv_session *session, CallID& id, const std::string& message)
-{
-
-    /* Check the length of the message */
-    if (message.length() < getMessageMaximumSize()) {
-        /* No problem here */
-        send (session, id, message);
-    }
-
-    else {
-        /* It exceeds the size limit of a SIP MESSAGE (1300 bytes), o plit it and send multiple messages */
-        std::vector<std::string> multiple_messages = split_message (message);
-        /* Send multiple messages */
-        int size = multiple_messages.size();
-        int i = 0;
-
-        // Maximum is above 1500 character
-        // TODO: Send every messages
-        send (session, id, multiple_messages[i]);
-    }
-
-    return PJ_SUCCESS;
-}
-
-
-std::vector<std::string> InstantMessaging::split_message (const std::string& text)
-{
-
-    std::vector<std::string> messages;
-    std::string text_to_split = text;
-
-    /* Iterate over the message length */
-    while (text_to_split.length() > getMessageMaximumSize()) {
-        /* The remaining string is still too long */
-
-        /* Compute the substring */
-        std::string split_message = text_to_split.substr (0, (size_t) getMessageMaximumSize());
-        /* Append our split character \n\n */
-        split_message.append (DELIMITER_CHAR);
-        /* Append in the vector */
-        messages.push_back (split_message);
-        /* Use the remaining string to not loop forever */
-        text_to_split = text_to_split.substr ( (size_t) getMessageMaximumSize());
-    }
-
-    /* Push the last message */
-    /* If the message length does not exceed the maximum size of a SIP MESSAGE, we go directly here */
-    messages.push_back (text_to_split);
-
-    return messages;
-}
-}
diff --git a/sflphone-common/src/sip/sipaccount.cpp b/sflphone-common/src/sip/sipaccount.cpp
index 0a31e1f98a9367a12afe5828582bfc945eef1954..7bba0b5b63a85c6026fe7b75d71aa8a5cf26cfc7 100644
--- a/sflphone-common/src/sip/sipaccount.cpp
+++ b/sflphone-common/src/sip/sipaccount.cpp
@@ -98,7 +98,7 @@ SIPAccount::SIPAccount (const AccountID& accountID)
         , _realm (DEFAULT_REALM)
         , _authenticationUsername ("")
         , _tlsSetting (NULL)
-        , _dtmfType (OVERRTP)
+        , _dtmfType (SIPINFO)
         , _tlsEnable ("false")
         , _tlsPortStr (DEFAULT_SIP_TLS_PORT)
         , _tlsCaListFile ("")
@@ -190,7 +190,7 @@ void SIPAccount::serialize (Conf::YamlEmitter *emitter)
     Conf::ScalarNode stunServer (_stunServer);
     Conf::ScalarNode stunEnabled (_stunEnabled ? "true" : "false");
     Conf::ScalarNode displayName (_displayName);
-    Conf::ScalarNode dtmfType (_dtmfType==0 ? "overrtp" : "sipinfo");
+    Conf::ScalarNode dtmfType (_dtmfType==OVERRTP ? "overrtp" : "sipinfo");
 
     std::stringstream countstr;
     countstr << 0;
@@ -415,6 +415,7 @@ void SIPAccount::unserialize (Conf::MappingNode *map)
     val = (Conf::ScalarNode *) (map->getValue (dtmfTypeKey));
 
     if (val) {
+        _dtmfType = (val->getValue() == "overrtp") ? OVERRTP : SIPINFO;
         val = NULL;
     }
 
@@ -423,6 +424,7 @@ void SIPAccount::unserialize (Conf::MappingNode *map)
 
     if (val) {
         _serviceRoute = val->getValue();
+        val = NULL;
     }
 
     // stun enabled
@@ -723,6 +725,8 @@ void SIPAccount::setAccountDetails (const std::map<std::string, std::string>& de
         setPublishedPort (atoi (publishedPort.data()));
         setStunServer (stunServer);
         setStunEnabled ( (stunEnable == "true"));
+        setDtmfType ( (dtmfType == "overrtp") ? OVERRTP : SIPINFO);
+
         setResolveOnce ( (resolveOnce.compare ("true") ==0) ? true : false);
         setRegistrationExpire (registrationExpire);
 
@@ -879,7 +883,7 @@ std::map<std::string, std::string> SIPAccount::getAccountDetails()
         a.insert (std::pair<std::string, std::string> (PUBLISHED_PORT, publishedport.str()));
         a.insert (std::pair<std::string, std::string> (STUN_ENABLE, isStunEnabled() ? "true" : "false"));
         a.insert (std::pair<std::string, std::string> (STUN_SERVER, getStunServer()));
-        a.insert (std::pair<std::string, std::string> (ACCOUNT_DTMF_TYPE, (getDtmfType() == 0) ? "0" : "1"));
+        a.insert (std::pair<std::string, std::string> (ACCOUNT_DTMF_TYPE, (getDtmfType() == OVERRTP) ? "overrtp" : "sipinfo"));
 
         a.insert (std::pair<std::string, std::string> (SRTP_KEY_EXCHANGE, getSrtpKeyExchange()));
         a.insert (std::pair<std::string, std::string> (SRTP_ENABLE, getSrtpEnable() ? "true" : "false"));
diff --git a/sflphone-common/src/sip/sipvoiplink.cpp b/sflphone-common/src/sip/sipvoiplink.cpp
index a9cb6ff1e4163c85bfbafa8174eab26e31b9f8e3..134256a7919e87d1471e219ac5fa7cf76a5d0bfe 100644
--- a/sflphone-common/src/sip/sipvoiplink.cpp
+++ b/sflphone-common/src/sip/sipvoiplink.cpp
@@ -45,6 +45,8 @@
 #include "dbus/dbusmanager.h"
 #include "dbus/callmanager.h"
 
+#include "im/InstantMessaging.h"
+
 #include "pjsip/sip_endpoint.h"
 #include "pjsip/sip_transport_tls.h"
 #include "pjsip/sip_transport_tls.h"
@@ -165,11 +167,6 @@ pj_thread_desc desc;
  */
 UrlHook *urlhook;
 
-/*
- * Instant Messaging module
- */
-InstantMessaging *imModule;
-
 /**
  * Get the number of voicemail waiting in a SIP message
  */
@@ -280,9 +277,6 @@ SIPVoIPLink::SIPVoIPLink (const AccountID& accountID)
 
     urlhook = new UrlHook ();
 
-    // Load the chat module
-    imModule = new InstantMessaging ();
-
     /* Start pjsip initialization step */
     init();
 }
@@ -830,7 +824,8 @@ SIPVoIPLink::newOutgoingCall (const CallID& id, const std::string& toUrl)
             _error ("UserAgent: Error: Failed to create rtp thread from newOutGoingCall");
         }
 
-        call->initRecFileName();
+        // init file name according to peer phone number
+        call->initRecFileName (toUrl);
 
         _debug ("UserAgent: Try to make a call to: %s with call ID: %s", toUrl.data(), id.data());
 
@@ -1062,17 +1057,33 @@ SIPVoIPLink::onhold (const CallID& id)
 }
 
 bool
-SIPVoIPLink::sendTextMessage (const std::string& callID, const std::string& message)
+SIPVoIPLink::sendTextMessage (sfl::InstantMessaging *module, const std::string& callID, const std::string& message, const std::string& from)
 {
-    _debug ("SipVoipLink: Send text message to %s", callID.c_str());
+    _debug ("SipVoipLink: Send text message to %s, from %s", callID.c_str(), from.c_str());
 
     SIPCall *call = getSIPCall (callID);
     pj_status_t status = !PJ_SUCCESS;
 
 
     if (call) {
+        std::string formatedFrom = from;
+
+        // add double quotes for xml formating
+        formatedFrom.insert (0,"\"");
+        formatedFrom.append ("\"");
+
         /* Send IM message */
-        status = imModule->send_message (call->getInvSession (), (CallID&) callID, message);
+        sfl::InstantMessaging::UriList list;
+
+        sfl::InstantMessaging::UriEntry entry;
+        entry[sfl::IM_XML_URI] = std::string (formatedFrom);
+
+        list.push_front (entry);
+
+        std::string formatedMessage = module->appendUriList (message, list);
+
+        status = module->send_sip_message (call->getInvSession (), (CallID&) callID, formatedMessage);
+
     } else {
         /* Notify the client of an error */
         /*Manager::instance ().incomingMessage (	"",
@@ -1679,7 +1690,9 @@ bool SIPVoIPLink::new_ip_to_ip_call (const CallID& id, const std::string& to)
     if (call) {
 
         call->setCallConfiguration (Call::IPtoIP);
-        call->initRecFileName();
+
+        // Init recfile name using to uri
+        call->initRecFileName (to);
 
         SIPAccount * account = NULL;
         account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (IP2IP_PROFILE));
@@ -2081,9 +2094,6 @@ bool SIPVoIPLink::pjsip_init()
     const pj_str_t STR_MIME_TEXT_PLAIN = { (char*) "text/plain", 10 };
     pjsip_endpt_add_capability (_endpt, &_mod_ua, PJSIP_H_ACCEPT, NULL, 1, &STR_MIME_TEXT_PLAIN);
 
-    // Registering and initializing IM module
-    imModule->init ();
-
     // Register "application/sdp" in ACCEPT header
     pjsip_endpt_add_capability (_endpt, &_mod_ua, PJSIP_H_ACCEPT, NULL, 1, &accepted);
 
@@ -3103,6 +3113,25 @@ void call_on_state_changed (pjsip_inv_session *inv, pjsip_event *e)
         return;
     }
 
+    /*
+    pjsip_hdr *allow_header = NULL;
+    std::string *allowed_options = NULL;
+
+    char header_buffer[500];
+
+    if (e->body.tsx_state.src.rdata->msg_info.msg)
+        allow_header = (pjsip_hdr *) pjsip_msg_find_hdr (e->body.tsx_state.src.rdata->msg_info.msg, PJSIP_H_ALLOW, NULL);
+
+    if (allow_header) {
+        allowed_options = new std::string (allow_header->name.ptr, allow_header->name.slen);
+        allow_header->vptr->print_on (allow_header, header_buffer, 5000);
+        std::string theHeader (header_buffer);
+    }
+
+    if (allowed_options)
+        delete allowed_options;
+    */
+
     // If this is an outgoing INVITE that was created because of
     // REFER/transfer, send NOTIFY to transferer.
     if (call->getXferSub() && e->type==PJSIP_EVENT_TSX_STATE) {
@@ -3441,15 +3470,15 @@ void call_on_tsx_changed (pjsip_inv_session *inv UNUSED, pjsip_transaction *tsx,
         // Incoming TEXT message
         if (e && e->body.tsx_state.src.rdata) {
 
-            std::string message;
-            SIPCall * call;
+            // sender of this message
+            std::string from;
 
             // Get the message inside the transaction
             r_data = e->body.tsx_state.src.rdata;
-            message = (char*) r_data->msg_info.msg->body->data;
+            std::string formatedMessage = (char*) r_data->msg_info.msg->body->data;
 
             // Try to determine who is the recipient of the message
-            call = reinterpret_cast<SIPCall *> (inv->mod_data[getModId() ]);
+            SIPCall *call = reinterpret_cast<SIPCall *> (inv->mod_data[getModId() ]);
 
             if (!call) {
                 _debug ("Incoming TEXT message: Can't find the recipient of the message");
@@ -3460,12 +3489,55 @@ void call_on_tsx_changed (pjsip_inv_session *inv UNUSED, pjsip_transaction *tsx,
             pjsip_dlg_create_response (inv->dlg, r_data, PJSIP_SC_OK, NULL, &t_data);
             pjsip_dlg_send_response (inv->dlg, tsx, t_data);
 
+            std::string message;
+            std::string urilist;
+            sfl::InstantMessaging::UriList list;
+
+            sfl::InstantMessaging *module = Manager::instance().getInstantMessageModule();
+
+            try {
+                // retrive message from formated text
+                message = module->findTextMessage (formatedMessage);
+
+                // retreive the recipient-list of this message
+                urilist = module->findTextUriList (formatedMessage);
+
+                // parse the recipient list xml
+                list = module->parseXmlUriList (urilist);
+
+                // If no item present in the list, peer is considered as the sender
+                if (list.empty()) {
+                    from = call->getPeerNumber ();
+                } else {
+                    sfl::InstantMessaging::UriEntry entry = list.front();
+                    sfl::InstantMessaging::UriEntry::iterator iterAttr = entry.find (IM_XML_URI);
+
+                    if (iterAttr->second != "Me")
+                        from = iterAttr->second;
+                    else
+                        from = call->getPeerNumber ();
+                }
+
+            } catch (sfl::InstantMessageException &e) {
+                _error ("SipVoipLink: %s", e.what());
+                message = "";
+                from = call->getPeerNumber ();
+            }
+
+
+            // strip < and > characters in case of an IP address
+            std::string stripped;
+
+            if (from[0] == '<' && from[from.size()-1] == '>')
+                stripped = from.substr (1, from.size()-2);
+            else
+                stripped = from;
+
             // Pass through the instant messaging module if needed
             // Right now, it does do anything.
             // And notify the clients
-            Manager::instance ().incomingMessage (call->getCallId (),
-                                                  call->getPeerNumber (),
-                                                  imModule->receive (message, call->getPeerNumber (), call->getCallId ()));
+
+            Manager::instance ().incomingMessage (call->getCallId (), stripped, module->receive (message, stripped, call->getCallId ()));
         }
 
 
@@ -3818,7 +3890,7 @@ mod_on_rx_request (pjsip_rx_data *rdata)
     call->setConnectionState (Call::Progressing);
     call->setPeerNumber (peerNumber);
     call->setDisplayName (displayName);
-    call->initRecFileName();
+    call->initRecFileName (peerNumber);
 
     _debug ("UserAgent: DisplayName: %s", displayName.c_str());
 
diff --git a/sflphone-common/src/sip/sipvoiplink.h b/sflphone-common/src/sip/sipvoiplink.h
index e90db00a80e1e08f699300169beac0b40c9b0825..8513725bf6bd01b7002621b4e578bfb232db067e 100644
--- a/sflphone-common/src/sip/sipvoiplink.h
+++ b/sflphone-common/src/sip/sipvoiplink.h
@@ -37,7 +37,7 @@
 
 #include "voiplink.h"
 #include "hooks/urlhook.h"
-#include "im/InstantMessaging.h"
+#include "../im/InstantMessaging.h"
 
 //////////////////////////////
 /* PJSIP imports */
@@ -364,7 +364,18 @@ class SIPVoIPLink : public VoIPLink
          */
         void shutdownSipTransport (const AccountID& accountID);
 
-        bool sendTextMessage (const std::string& callID, const std::string& message);
+
+        /**
+         * Send a SIP message to a call identified by its callid
+         *
+        * @param The InstantMessaging module which contains formating, parsing and sending method
+         * @param The Id of the call to send the message to
+         * @param The actual message to be transmitted
+         * @param The sender of this message (could be another participant of a conference)
+         *
+         * @return True if the message is sent without error, false elsewhere
+         */
+        bool sendTextMessage (sfl::InstantMessaging *module, const std::string& callID, const std::string& message, const std::string& from);
 
     private:
         /**
diff --git a/sflphone-common/test/configurationtest.cpp b/sflphone-common/test/configurationtest.cpp
index e79fc1d07eefe62e2bc6230d9217ed2538f2fc60..e3ff1339dd21484864d768e64ced98d6d483e123 100644
--- a/sflphone-common/test/configurationtest.cpp
+++ b/sflphone-common/test/configurationtest.cpp
@@ -65,7 +65,6 @@ void ConfigurationTest::testDefaultValueSignalisation()
     CPPUNIT_ASSERT (Manager::instance().voipPreferences.getPlayDtmf() == true);
     CPPUNIT_ASSERT (Manager::instance().voipPreferences.getPlayTones() == true);
     CPPUNIT_ASSERT (Manager::instance().voipPreferences.getPulseLength() == 250);
-    CPPUNIT_ASSERT (Manager::instance().voipPreferences.getSendDtmfAs() == 0);
 }
 
 void ConfigurationTest::testLoadSIPAccount()
diff --git a/sflphone-common/test/instantmessagingtest.cpp b/sflphone-common/test/instantmessagingtest.cpp
index 99f49970786253f9b076c9bdc0310415e5864ab5..fb0f49308e57d00641e5906c2632c001d5ef4bac 100644
--- a/sflphone-common/test/instantmessagingtest.cpp
+++ b/sflphone-common/test/instantmessagingtest.cpp
@@ -34,12 +34,16 @@
 
 #include "instantmessagingtest.h"
 
+#include "expat.h"
+#include <stdio.h>
+
 #define MAXIMUM_SIZE	10
 #define DELIMITER_CHAR	"\n\n"
 
 using std::cout;
 using std::endl;
 
+
 void InstantMessagingTest::setUp()
 {
     _im = new sfl::InstantMessaging ();
@@ -139,6 +143,225 @@ void InstantMessagingTest::testSplitMessage ()
     CPPUNIT_ASSERT (messages[size- 1] == very_long_message.substr (maxSize * (size-1)));
 }
 
+static inline char* duplicateString(char dst[], const char src[], size_t len)
+{
+    memcpy(dst, src, len);
+    dst[len] = 0;
+    return dst;
+}
+
+static void XMLCALL startElementCallback(void *userData, const char *name, const char **atts)
+{
+    
+    std::cout << "startElement " << name << std::endl;
+
+    int *nbEntry = (int *)userData;
+
+    char attribute[50];
+    char value[50];
+
+    const char **att;
+    const char **val; 
+    for (att = atts; *att; att += 2) {
+
+	const char **val = att+1;
+
+	duplicateString(attribute, *att, strlen(*att));
+	std::cout << "att: " << attribute << std::endl;
+	
+	duplicateString(value, *val, strlen(*val));
+	std::cout << "val: " << value << std::endl;
+
+	if (strcmp(attribute, "uri") == 0) {
+	    if((strcmp(value, "sip:alex@example.com") == 0) ||
+	       (strcmp(value, "sip:manu@example.com") == 0))
+		CPPUNIT_ASSERT(true);
+	    else
+		CPPUNIT_ASSERT(false);
+	}
+    }
+
+    *nbEntry += 1;
+
+}
+
+static void XMLCALL endElementCallback(void *userData, const char *name)
+{
+    // std::cout << "endElement " << name << std::endl;    
+}
+
+void InstantMessagingTest::testGenerateXmlUriList ()
+{
+    
+    std::cout << std::endl;
+
+    // Create a test list with two entries
+    sfl::InstantMessaging::UriList list;
+
+    sfl::InstantMessaging::UriEntry entry1;
+    entry1[sfl::IM_XML_URI] = "\"sip:alex@example.com\"";
+
+    sfl::InstantMessaging::UriEntry entry2;
+    entry2[sfl::IM_XML_URI] = "\"sip:manu@example.com\"";
+
+    list.push_front(entry1);
+    list.push_front(entry2);
+
+    std::string buffer = _im->generateXmlUriList(list);
+    CPPUNIT_ASSERT(buffer.size() != 0);
+
+    std::cout << buffer << std::endl;
+	
+    // parse the resuling xml (further tests are performed in callbacks)
+    XML_Parser parser = XML_ParserCreate(NULL);
+    int nbEntry = 0;
+    XML_SetUserData(parser, &nbEntry);
+    XML_SetElementHandler(parser, startElementCallback, endElementCallback);
+    if (XML_Parse(parser, buffer.c_str(), buffer.size(), 1) == XML_STATUS_ERROR) {
+	std::cout << "Error: " << XML_ErrorString(XML_GetErrorCode(parser)) 
+                  << " at line " << XML_GetCurrentLineNumber(parser) << std::endl;
+        CPPUNIT_ASSERT(false);
+    }
+    XML_ParserFree(parser);
+
+    CPPUNIT_ASSERT(nbEntry == 4);
+
+    CPPUNIT_ASSERT(true);
+}
+
+void InstantMessagingTest::testXmlUriListParsing ()
+{
+    std::string xmlbuffer = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+    xmlbuffer.append ("<resource-lists xmlns=\"urn:ietf:params:xml:ns:resource-lists\" xmlns:cp=\"urn:ietf:params:xml:ns:copycontrol\">");
+    xmlbuffer.append ("<list>");
+    xmlbuffer.append ("<entry uri=\"sip:alex@example.com\" cp:copyControl=\"to\" />");
+    xmlbuffer.append ("<entry uri=\"sip:manu@example.com\" cp:copyControl=\"to\" />");
+    xmlbuffer.append ("</list>");
+    xmlbuffer.append ("</resource-lists>");
+
+
+    sfl::InstantMessaging::UriList list = _im->parseXmlUriList(xmlbuffer);
+    CPPUNIT_ASSERT(list.size() == 2);
+
+    // An iterator over xml attribute
+    sfl::InstantMessaging::UriEntry::iterator iterAttr;
+
+    // An iterator over list entries
+    sfl::InstantMessaging::UriList::iterator iterEntry = list.begin();
+
+    
+    while (iterEntry != list.end()) {
+        sfl::InstantMessaging::UriEntry entry = static_cast<sfl::InstantMessaging::UriEntry> (*iterEntry);
+        iterAttr = entry.find (sfl::IM_XML_URI);
+		
+        if((iterAttr->second == std::string("sip:alex@example.com")) ||
+           (iterAttr->second == std::string("sip:manu@example.com")))
+	    CPPUNIT_ASSERT(true);
+	else
+	    CPPUNIT_ASSERT(false);
+        iterEntry++;
+    }
+}
+
+void InstantMessagingTest::testGetTextArea ()
+{
+
+    std::string formatedText = "--boundary Content-Type: text/plain";
+    formatedText.append ("Here is the text area");
+
+    formatedText.append ("--boundary Content-Type: application/resource-lists+xml");
+    formatedText.append ("Content-Disposition: recipient-list");
+    formatedText.append ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+    formatedText.append ("<resource-lists xmlns=\"urn:ietf:params:xml:ns:resource-lists\" xmlns:cp=\"urn:ietf:params:xml:ns:copycontrol\">");
+    formatedText.append ("<list>");
+    formatedText.append ("<entry uri=\"sip:alex@example.com\" cp:copyControl=\"to\" />");
+    formatedText.append ("<entry uri=\"sip:manu@example.com\" cp:copyControl=\"to\" />");
+    formatedText.append ("</list>");
+    formatedText.append ("</resource-lists>");
+    formatedText.append ("--boundary--");
+
+    std::string message = _im->findTextMessage(formatedText);
+
+    std::cout << "message " << message << std::endl;
+
+    CPPUNIT_ASSERT(message == "Here is the text area");
+}
+
+
+void InstantMessagingTest::testGetUriListArea ()
+{
+    std::string formatedText = "--boundary Content-Type: text/plain";
+    formatedText.append ("Here is the text area");
+
+    formatedText.append ("--boundary Content-Type: application/resource-lists+xml");
+    formatedText.append ("Content-Disposition: recipient-list");
+    formatedText.append ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+    formatedText.append ("<resource-lists xmlns=\"urn:ietf:params:xml:ns:resource-lists\" xmlns:cp=\"urn:ietf:params:xml:ns:copycontrol\">");
+    formatedText.append ("<list>");
+    formatedText.append ("<entry uri=\"sip:alex@example.com\" cp:copyControl=\"to\" />");
+    formatedText.append ("<entry uri=\"sip:manu@example.com\" cp:copyControl=\"to\" />");
+    formatedText.append ("</list>");
+    formatedText.append ("</resource-lists>");
+    formatedText.append ("--boundary--");
+
+    std::string urilist = _im->findTextUriList(formatedText);
+
+    CPPUNIT_ASSERT(urilist.compare("<?xml version=\"1.0\" encoding=\"UTF-8\"?><resource-lists xmlns=\"urn:ietf:params:xml:ns:resource-lists\" xmlns:cp=\"urn:ietf:params:xml:ns:copycontrol\"><list><entry uri=\"sip:alex@example.com\" cp:copyControl=\"to\" /><entry uri=\"sip:manu@example.com\" cp:copyControl=\"to\" /></list></resource-lists>") == 0);
+
+    std::cout << "urilist: " << urilist << std::endl;
+
+    sfl::InstantMessaging::UriList list = _im->parseXmlUriList(urilist);
+    CPPUNIT_ASSERT(list.size() == 2);
+
+    // order may be important, for example to identify message sender
+    sfl::InstantMessaging::UriEntry entry = list.front();
+    CPPUNIT_ASSERT(entry.size() == 2);
+
+    sfl::InstantMessaging::UriEntry::iterator iterAttr = entry.find (sfl::IM_XML_URI);
+
+    if(iterAttr == entry.end()) {
+	std::cout << "Error, did not found attribute" << std::endl;
+	CPPUNIT_ASSERT(false);
+    }
+
+    std::string from = iterAttr->second;
+    CPPUNIT_ASSERT(from == "sip:alex@example.com");
+}
+
+
+void InstantMessagingTest::testIllFormatedMessage ()
+{
+    bool exceptionCaught = false;
+
+    // SHOULD BE: Content-Type: text/plain
+    std::string formatedText = "--boundary Content-Ty";
+    formatedText.append ("Here is the text area");
+
+    formatedText.append ("--boundary Content-Type: application/resource-lists+xml");
+    formatedText.append ("Content-Disposition: recipient-list");
+    formatedText.append ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+    formatedText.append ("<resource-lists xmlns=\"urn:ietf:params:xml:ns:resource-lists\" xmlns:cp=\"urn:ietf:params:xml:ns:copycontrol\">");
+    formatedText.append ("<list>");
+    formatedText.append ("<entry uri=\"sip:alex@example.com\" cp:copyControl=\"to\" />");
+    formatedText.append ("<entry uri=\"sip:manu@example.com\" cp:copyControl=\"to\" />");
+    formatedText.append ("</list>");
+    formatedText.append ("</resource-lists>");
+    formatedText.append ("--boundary--");
+
+    try {
+	std::string message = _im->findTextMessage(formatedText);
+    } catch (sfl::InstantMessageException &e) {
+	exceptionCaught = true;	
+    }
+
+    if(exceptionCaught)
+	CPPUNIT_ASSERT(true);
+    else
+	CPPUNIT_ASSERT(false);
+
+}
+
+
 void InstantMessagingTest::tearDown()
 {
     delete _im;
diff --git a/sflphone-common/test/instantmessagingtest.h b/sflphone-common/test/instantmessagingtest.h
index e349096b1189459b9ac28af3c2c86457779e047e..4375471d237cbea97b8f950ad3cb91d3a9f6eb69 100644
--- a/sflphone-common/test/instantmessagingtest.h
+++ b/sflphone-common/test/instantmessagingtest.h
@@ -37,7 +37,7 @@
 #include <assert.h>
 
 // Application import
-#include "sip/im/InstantMessaging.h"
+#include "im/InstantMessaging.h"
 
 /*
  * @file instantmessagingtest.h 
@@ -56,6 +56,11 @@ class InstantMessagingTest : public CppUnit::TestCase {
         CPPUNIT_TEST (testSaveSingleMessage);
         CPPUNIT_TEST (testSaveMultipleMessage);
         CPPUNIT_TEST (testSplitMessage);
+	CPPUNIT_TEST (testGenerateXmlUriList);
+	CPPUNIT_TEST (testXmlUriListParsing);
+	CPPUNIT_TEST (testGetTextArea);
+	CPPUNIT_TEST (testGetUriListArea);
+	CPPUNIT_TEST (testIllFormatedMessage);
     CPPUNIT_TEST_SUITE_END();
 
     public:
@@ -78,7 +83,17 @@ class InstantMessagingTest : public CppUnit::TestCase {
         void testSaveMultipleMessage ();
 
         void testSplitMessage ();
-        
+
+	void testGenerateXmlUriList ();
+
+	void testXmlUriListParsing ();
+
+	void testGetTextArea ();
+
+	void testGetUriListArea ();
+
+	void testIllFormatedMessage ();        
+
     private:
 		sfl::InstantMessaging *_im;
 };
diff --git a/tools/build-system/launchpad/sflphone-client-gnome/debian/control.karmic b/tools/build-system/launchpad/sflphone-client-gnome/debian/control.karmic
index c72878afda415cff757f8bb6da1167c5d431544f..53b4e025bbfa95a8a182b9feb2a54e2ba055cab6 100644
--- a/tools/build-system/launchpad/sflphone-client-gnome/debian/control.karmic
+++ b/tools/build-system/launchpad/sflphone-client-gnome/debian/control.karmic
@@ -2,13 +2,13 @@ Source: sflphone-client-gnome
 Maintainer: SavoirFaireLinux Inc <julien.bonjean@savoirfairelinux.com>
 Section: gnome
 Priority: optional
-Build-Depends: debhelper, libgcc1, autoconf, automake, libtool, libgtk2.0-dev, libdbus-glib-1-dev, libnotify-dev, libebook1.2-dev, check, liblog4c-dev, libgnomeui-dev, gnome-doc-utils, rarian-compat
+Build-Depends: debhelper, libgcc1, autoconf, automake, libtool, libgtk2.0-dev, libdbus-glib-1-dev, libnotify-dev, libebook1.2-dev, check, liblog4c-dev, libgnomeui-dev, gnome-doc-utils, rarian-compat, libwebkit-dev
 Standards-Version: 3.7.3
 
 Package: sflphone-client-gnome
 Priority: optional
 Architecture: any
-Depends: sflphone-common (=${source:Version}), libdbus-glib-1-2, libgtk2.0-0, libc6, libglib2.0-0, libdbus-glib-1-2, libnotify1, librsvg2-common, liblog4c3, libebook1.2-9, libgnomeui-0
+Depends: sflphone-common (=${source:Version}), libdbus-glib-1-2, libgtk2.0-0, libc6, libglib2.0-0, libdbus-glib-1-2, libnotify1, librsvg2-common, liblog4c3, libebook1.2-9, libgnomeui-0, libwebkit-1.0-2
 Replaces: sflphone
 Conflicts: sflphone
 Homepage: http://www.sflphone.org
diff --git a/tools/build-system/launchpad/sflphone-client-gnome/debian/control.lucid b/tools/build-system/launchpad/sflphone-client-gnome/debian/control.lucid
index c72878afda415cff757f8bb6da1167c5d431544f..53b4e025bbfa95a8a182b9feb2a54e2ba055cab6 100644
--- a/tools/build-system/launchpad/sflphone-client-gnome/debian/control.lucid
+++ b/tools/build-system/launchpad/sflphone-client-gnome/debian/control.lucid
@@ -2,13 +2,13 @@ Source: sflphone-client-gnome
 Maintainer: SavoirFaireLinux Inc <julien.bonjean@savoirfairelinux.com>
 Section: gnome
 Priority: optional
-Build-Depends: debhelper, libgcc1, autoconf, automake, libtool, libgtk2.0-dev, libdbus-glib-1-dev, libnotify-dev, libebook1.2-dev, check, liblog4c-dev, libgnomeui-dev, gnome-doc-utils, rarian-compat
+Build-Depends: debhelper, libgcc1, autoconf, automake, libtool, libgtk2.0-dev, libdbus-glib-1-dev, libnotify-dev, libebook1.2-dev, check, liblog4c-dev, libgnomeui-dev, gnome-doc-utils, rarian-compat, libwebkit-dev
 Standards-Version: 3.7.3
 
 Package: sflphone-client-gnome
 Priority: optional
 Architecture: any
-Depends: sflphone-common (=${source:Version}), libdbus-glib-1-2, libgtk2.0-0, libc6, libglib2.0-0, libdbus-glib-1-2, libnotify1, librsvg2-common, liblog4c3, libebook1.2-9, libgnomeui-0
+Depends: sflphone-common (=${source:Version}), libdbus-glib-1-2, libgtk2.0-0, libc6, libglib2.0-0, libdbus-glib-1-2, libnotify1, librsvg2-common, liblog4c3, libebook1.2-9, libgnomeui-0, libwebkit-1.0-2
 Replaces: sflphone
 Conflicts: sflphone
 Homepage: http://www.sflphone.org