diff --git a/sflphone-client-gnome/pixmaps/Makefile.am b/sflphone-client-gnome/pixmaps/Makefile.am
index d18c3356c6c5752f0e1e615b0c008e4ae708a7cf..aab059e630c6f72f6f5311dd2100b8c2e8dcc1ae 100644
--- a/sflphone-client-gnome/pixmaps/Makefile.am
+++ b/sflphone-client-gnome/pixmaps/Makefile.am
@@ -2,7 +2,7 @@ icondir   = $(datadir)/pixmaps
 
 icon_DATA = sflphone.svg
 
-buttons_DATA = accept.svg current.svg transfert.svg hang_up.svg hold.svg unhold.svg refuse.svg call.svg ring.svg dial.svg mic.svg mic_25.svg mic_50.svg mic_75.svg speaker.svg speaker_25.svg speaker_50.svg speaker_75.svg fail.svg incoming.svg outgoing.svg missed.svg mailbox.svg busy.svg icon_accept.svg icon_hold.svg icon_unhold.svg icon_hangup.svg icon_call.svg icon_dialpad.svg icon_volume.svg icon_dialpad_off.svg icon_volume_off.svg history2.svg sflphone.svg sflphone_small.svg stock_person.svg icon_rec.svg rec_call.svg addressbook.svg contact_default.svg face-monkey.svg users.svg home.svg wait-on.gif lock_certified.svg  lock_confirmed.svg  lock_error.svg  lock_off.svg  lock_unconfirmed.svg
+buttons_DATA = accept.svg current.svg transfert.svg hang_up.svg hold.svg unhold.svg refuse.svg call.svg ring.svg dial.svg mic.svg mic_25.svg mic_50.svg mic_75.svg speaker.svg speaker_25.svg speaker_50.svg speaker_75.svg fail.svg incoming.svg outgoing.svg missed.svg mailbox.svg busy.svg icon_accept.svg icon_hold.svg icon_unhold.svg icon_hangup.svg icon_call.svg icon_dialpad.svg icon_volume.svg icon_dialpad_off.svg icon_volume_off.svg history2.svg sflphone.svg sflphone_small.svg stock_person.svg icon_rec.svg rec_call.svg addressbook.svg contact_default.svg face-monkey.svg users.svg usersActive.svg home.svg wait-on.gif lock_certified.svg lock_confirmed.svg lock_error.svg lock_off.svg lock_unconfirmed.svg
 
 buttonsdir   = $(datadir)/sflphone
 EXTRA_DIST   = $(buttons_DATA) $(icon_DATA)
diff --git a/sflphone-client-gnome/pixmaps/usersActive.svg b/sflphone-client-gnome/pixmaps/usersActive.svg
index 85b8e7977319198db0eda97e274e8f6a4dbb41eb..1a7d6fc90a389c329f6cee04ac1854290c517718 100644
--- a/sflphone-client-gnome/pixmaps/usersActive.svg
+++ b/sflphone-client-gnome/pixmaps/usersActive.svg
@@ -27,7 +27,7 @@
       <stop
          id="stop4910"
          offset="0"
-         style="stop-color:#ff0000;stop-opacity:1;" />
+         style="stop-color:#0000ff;stop-opacity:1;" />
       <stop
          id="stop4912"
          offset="1"
@@ -430,7 +430,7 @@
        xlink:href="#linearGradient3824"
        id="linearGradient5073"
        gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1.33835,0,0,1.33835,19.045003,-13.796172)"
+       gradientTransform="matrix(1.33835,0,0,1.33835,-46.329997,-7.296172)"
        x1="30.935921"
        y1="29.553486"
        x2="30.935921"
@@ -440,7 +440,7 @@
        xlink:href="#linearGradient4356"
        id="linearGradient5075"
        gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(-1.308485,0.281154,0.281154,1.308485,91.615243,-19.308382)"
+       gradientTransform="matrix(-1.308485,0.281154,0.281154,1.308485,26.240243,-12.808382)"
        x1="22.686766"
        y1="36.390400"
        x2="21.408455"
@@ -482,7 +482,7 @@
        xlink:href="#linearGradient4908"
        id="radialGradient5083"
        gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1.046177,0,-2.580083e-8,1.017815,46.621787,0.6353743)"
+       gradientTransform="matrix(1.046177,0,-2.580083e-8,1.017815,-18.753213,7.1353743)"
        cx="24.753788"
        cy="26.814409"
        fx="24.753788"
@@ -493,7 +493,7 @@
        xlink:href="#linearGradient4356"
        id="linearGradient5085"
        gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(-0.999008,0.214863,0.214657,0.999968,97.340213,-6.148422)"
+       gradientTransform="matrix(-0.999008,0.214863,0.214657,0.999968,31.965213,0.351578)"
        x1="22.686766"
        y1="36.390400"
        x2="21.408455"
@@ -503,7 +503,7 @@
        xlink:href="#linearGradient4356"
        id="linearGradient5087"
        gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1.004822,0.185726,-0.185548,1.005788,46.523971,-4.993292)"
+       gradientTransform="matrix(1.004822,0.185726,-0.185548,1.005788,-18.851029,1.506708)"
        x1="20.661695"
        y1="35.817974"
        x2="22.626925"
@@ -541,16 +541,16 @@
      inkscape:zoom="8"
      inkscape:cx="31.452526"
      inkscape:cy="23.601838"
-     inkscape:current-layer="layer2"
+     inkscape:current-layer="g5058"
      showgrid="true"
      inkscape:grid-bbox="true"
      inkscape:document-units="px"
      fill="#9db029"
      stroke="#727e0a"
-     inkscape:window-width="1920"
+     inkscape:window-width="1910"
      inkscape:window-height="1003"
      inkscape:window-x="0"
-     inkscape:window-y="25" />
+     inkscape:window-y="143" />
   <metadata
      id="metadata4">
     <rdf:RDF>
@@ -604,18 +604,18 @@
      style="display:inline">
     <g
        id="g5058"
-       transform="translate(-42.497844,-5.9675144)">
+       transform="translate(23.252156,-12.592514)">
       <path
          id="path2498"
-         d="M 65.889651,31.754099 L 71.567789,31.754099 L 68.255543,28.67844 L 67.545775,29.624797 L 66.836007,28.91503 L 65.889651,31.754099 z"
+         d="M 0.514651,38.254099 L 6.192789,38.254099 L 2.880543,35.17844 L 2.170775,36.124797 L 1.461007,35.41503 L 0.514651,38.254099 z"
          style="opacity:0.78857141;fill:url(#linearGradient5073);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
       <path
          style="opacity:0.17967446;fill:url(#linearGradient5075);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-         d="M 72.407105,39.394412 C 74.05495,38.61686 74.821997,36.714605 74.821997,36.714605 C 73.538359,31.303678 69.500518,27.556514 69.500518,27.556514 C 69.500518,27.556514 72.799006,36.045137 72.407105,39.394412 z"
+         d="M 7.032105,45.894412 C 8.67995,45.11686 9.446997,43.214605 9.446997,43.214605 C 8.163359,37.803678 4.125518,34.056514 4.125518,34.056514 C 4.125518,34.056514 7.424006,42.545137 7.032105,45.894412 z"
          id="path2500"
          sodipodi:nodetypes="cccc" />
       <g
-         transform="matrix(1.443435e-2,0,0,1.697277e-2,85.708613,36.961608)"
+         transform="matrix(1.443435e-2,0,0,1.697277e-2,20.333613,43.461608)"
          id="g2502"
          style="opacity:0.78857141;display:inline">
         <rect
@@ -639,13 +639,13 @@
       <path
          sodipodi:nodetypes="cczcczc"
          id="path2510"
-         d="M 67.372347,40.403867 L 78.336289,40.403867 C 81.44274,40.403867 84.518259,39.305326 85.645582,36.174277 C 86.716113,33.200974 85.828316,27.53886 78.884486,22.956803 L 65.910486,22.956803 C 58.966657,27.186393 58.098898,32.970738 59.697587,36.350509 C 61.326264,39.793675 64.083164,40.403867 67.372347,40.403867 z"
+         d="M 1.997347,46.903867 L 12.961289,46.903867 C 16.06774,46.903867 19.143259,45.805326 20.270582,42.674277 C 21.341113,39.700974 20.453316,34.03886 13.509486,29.456803 L 0.535486,29.456803 C -6.408343,33.686393 -7.276102,39.470738 -5.677413,42.850509 C -4.048736,46.293675 -1.291836,46.903867 1.997347,46.903867 z"
          style="opacity:1;fill:url(#radialGradient5083);fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:0.99999928px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
       <path
          inkscape:r_cy="true"
          inkscape:r_cx="true"
          style="opacity:0.22963891;fill:url(#linearGradient5085);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-         d="M 82.675104,38.713326 C 83.933208,38.119107 84.518836,36.66537 84.518836,36.66537 C 83.538799,32.53024 80.455969,29.66659 80.455969,29.66659 C 80.455969,29.66659 82.974314,36.153749 82.675104,38.713326 z"
+         d="M 17.300104,45.213326 C 18.558208,44.619107 19.143836,43.16537 19.143836,43.16537 C 18.163799,39.03024 15.080969,36.16659 15.080969,36.16659 C 15.080969,36.16659 17.599314,42.653749 17.300104,45.213326 z"
          id="path2512"
          sodipodi:nodetypes="cccc" />
       <path
@@ -653,15 +653,15 @@
          inkscape:r_cx="true"
          sodipodi:nodetypes="cccc"
          id="path2514"
-         d="M 62.48471,39.423138 C 61.209893,38.865747 60.639327,37.522507 60.639327,37.522507 C 61.498956,33.360629 64.440382,30.315697 64.440382,30.315697 C 64.440382,30.315697 62.11135,36.87334 62.48471,39.423138 z"
+         d="M -2.89029,45.923138 C -4.165107,45.365747 -4.735673,44.022507 -4.735673,44.022507 C -3.876044,39.860629 -0.934618,36.815697 -0.934618,36.815697 C -0.934618,36.815697 -3.26365,43.37334 -2.89029,45.923138 z"
          style="opacity:0.43328097;fill:url(#linearGradient5087);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
       <path
          style="opacity:0.50693874;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.99999863px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-         d="M 67.320507,39.403853 L 78.250226,39.381596 C 80.999701,39.381596 83.721793,38.406717 84.719571,35.628131 C 85.667083,32.989533 84.620911,27.964804 78.475034,23.898549 L 66.471159,23.653733 C 60.32528,27.407199 59.135735,32.540401 60.573725,35.784525 C 62.011717,39.028649 64.110095,39.381596 67.320507,39.403853 z"
+         d="M 1.945507,45.903853 L 12.875226,45.881596 C 15.624701,45.881596 18.346793,44.906717 19.344571,42.128131 C 20.292083,39.489533 19.245911,34.464804 13.100034,30.398549 L 1.096159,30.153733 C -5.04972,33.907199 -6.239265,39.040401 -4.801275,42.284525 C -3.363283,45.528649 -1.264905,45.881596 1.945507,45.903853 z"
          id="path2516"
          sodipodi:nodetypes="cczcczc" />
       <path
-         transform="matrix(1.021809,0,0,1.022791,40.595633,1.5419983)"
+         transform="matrix(1.021809,0,0,1.022791,-24.779367,8.0419983)"
          sodipodi:type="arc"
          style="opacity:0.78857141;fill:url(#radialGradient5089);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
          id="path2518"
@@ -671,17 +671,17 @@
          sodipodi:ry="8.6620579"
          d="M 39.774755,19.008621 A 8.6620579,8.6620579 0 1 1 22.45064,19.008621 A 8.6620579,8.6620579 0 1 1 39.774755,19.008621 z" />
       <path
-         transform="matrix(0.981291,0,0,0.981291,41.993573,-0.7491257)"
+         transform="matrix(0.981291,0,0,0.981291,-23.381427,5.7508743)"
          d="M 39.774755,19.008621 A 8.6620579,8.6620579 0 1 1 22.45064,19.008621 A 8.6620579,8.6620579 0 1 1 39.774755,19.008621 z"
          sodipodi:ry="8.6620579"
          sodipodi:rx="8.6620579"
          sodipodi:cy="19.008621"
          sodipodi:cx="31.112698"
          id="path2520"
-         style="opacity:1;fill:url(#radialGradient5091);fill-opacity:1;fill-rule:evenodd;stroke:#8a8586;stroke-width:1.0190649px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+         style="opacity:1;fill:url(#radialGradient5091);fill-opacity:1;fill-rule:evenodd;stroke:#8a8586;stroke-width:1.01906574;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
          sodipodi:type="arc" />
       <path
-         transform="matrix(0.865845,0,0,0.865845,45.585403,1.4453403)"
+         transform="matrix(0.865845,0,0,0.865845,-19.789597,7.9453403)"
          sodipodi:type="arc"
          style="opacity:0.41456329;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.15494144px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
          id="path2522"
diff --git a/sflphone-client-gnome/src/Makefile.am b/sflphone-client-gnome/src/Makefile.am
index 80a6165a815494b99a923f4f9129b784f4e573a3..0d69be795377135e87800d62fde39adeb4a159e2 100644
--- a/sflphone-client-gnome/src/Makefile.am
+++ b/sflphone-client-gnome/src/Makefile.am
@@ -18,6 +18,7 @@ sflphone_client_gnome_SOURCES = \
   menus.c \
   toolbar.c \
   callable_obj.c \
+  conference_obj.c \
   actions.c \
   accountlist.c \
   sliders.c \
@@ -27,7 +28,8 @@ sflphone_client_gnome_SOURCES = \
 
 noinst_HEADERS =  actions.h sflnotify.h mainwindow.h dialpad.h codeclist.h \
                   reqaccount.h errors.h sflphone_const.h \
-                  menus.h accountlist.h sliders.h statusicon.h callable_obj.h toolbar.h
+                  menus.h accountlist.h sliders.h statusicon.h callable_obj.h conference_obj.h toolbar.h
+
 
 
 sflphone_client_gnome_LDADD = $(DEPS_LIBS) $(NOTIFY_LIBS) $(SFLPHONEGTK_LIBS) $(LIBSEXY_LIBS) $(LOG4C)
diff --git a/sflphone-client-gnome/src/actions.c b/sflphone-client-gnome/src/actions.c
index 25bb9b11a4b6a547adff7fb59d35a4e5cf793e41..ff0c693730ee40d0bad7c3854c9d725a37e9f203 100644
--- a/sflphone-client-gnome/src/actions.c
+++ b/sflphone-client-gnome/src/actions.c
@@ -124,7 +124,7 @@ sflphone_quit ()
 sflphone_hold (callable_obj_t * c )
 {
     c->_state = CALL_STATE_HOLD;
-    calltree_update_call(current_calls,c);
+    calltree_update_call(current_calls, c, NULL);
     update_menus();
 }
 
@@ -132,7 +132,7 @@ sflphone_hold (callable_obj_t * c )
 sflphone_ringing(callable_obj_t * c )
 {
     c->_state = CALL_STATE_RINGING;
-    calltree_update_call(current_calls,c);
+    calltree_update_call(current_calls, c, NULL);
     update_menus();
 }
 
@@ -140,7 +140,7 @@ sflphone_ringing(callable_obj_t * c )
 sflphone_hung_up( callable_obj_t * c)
 {
     calllist_remove( current_calls, c->_callID);
-    calltree_remove_call(current_calls, c);
+    calltree_remove_call(current_calls, c, NULL);
     c->_state = CALL_STATE_DIALING;
     call_remove_all_errors(c);
     update_menus();
@@ -279,6 +279,7 @@ gboolean sflphone_init()
 
         account_list_init ();
         codec_list_init();
+	conferencelist_init();
 
         // Fetch the configured accounts
         sflphone_fill_account_list(FALSE);
@@ -289,6 +290,9 @@ gboolean sflphone_init()
         // Fetch the audio codecs
         sflphone_fill_codec_list();
 
+	// Fetch the conference list
+	sflphone_fill_conference_list();
+
         return TRUE;
     }
 }
@@ -350,7 +354,17 @@ sflphone_hang_up()
                 break;
         }
     }
-    calltree_update_call( history , selectedCall );
+    calltree_update_call(history, selectedCall, NULL);
+}
+
+
+void
+sflphone_conference_hang_up()
+{
+    conference_obj_t * selectedConf = calltab_get_selected_conf();
+
+    if(selectedConf)
+	dbus_hang_up_conference(selectedConf);
 }
 
 
@@ -370,7 +384,7 @@ sflphone_pick_up()
                 break;
             case CALL_STATE_INCOMING:
                 selectedCall->_history_state = INCOMING;
-                calltree_update_call( history , selectedCall );
+                calltree_update_call( history, selectedCall, NULL);
                 dbus_accept (selectedCall);
                 DEBUG("from sflphone_pick_up : "); stop_notification();
                 break;
@@ -453,7 +467,7 @@ sflphone_off_hold ()
 sflphone_fail( callable_obj_t * c )
 {
     c->_state = CALL_STATE_FAILURE;
-    calltree_update_call(current_calls,c);
+    calltree_update_call(current_calls, c, NULL);
     update_menus();
 }
 
@@ -461,7 +475,7 @@ sflphone_fail( callable_obj_t * c )
 sflphone_busy( callable_obj_t * c )
 {
     c->_state = CALL_STATE_BUSY;
-    calltree_update_call(current_calls, c);
+    calltree_update_call(current_calls, c, NULL);
     update_menus();
 }
 
@@ -471,7 +485,7 @@ sflphone_current( callable_obj_t * c )
     if( c->_state != CALL_STATE_HOLD )
         set_timestamp (&c->_time_start);
     c->_state = CALL_STATE_CURRENT;
-    calltree_update_call(current_calls,c);
+    calltree_update_call(current_calls, c, NULL);
     update_menus();
 }
 
@@ -481,7 +495,7 @@ sflphone_record( callable_obj_t * c )
     if( c->_state != CALL_STATE_HOLD )
         set_timestamp (&c->_time_start);
     c->_state = CALL_STATE_RECORD;
-    calltree_update_call(current_calls,c);
+    calltree_update_call(current_calls, c, NULL);
     update_menus();
 }
 
@@ -493,7 +507,7 @@ sflphone_set_transfert()
     {
         c->_state = CALL_STATE_TRANSFERT;
         c->_trsft_to = g_strdup("");
-        calltree_update_call(current_calls,c);
+        calltree_update_call(current_calls, c, NULL);
         update_menus();
     }
     toolbar_update_buttons();
@@ -507,7 +521,7 @@ sflphone_unset_transfert()
     {
         c->_state = CALL_STATE_CURRENT;
         c->_trsft_to = g_strdup("");
-        calltree_update_call(current_calls,c);
+        calltree_update_call(current_calls, c, NULL);
         update_menus();
     }
     toolbar_update_buttons();
@@ -525,7 +539,7 @@ sflphone_incoming_call (callable_obj_t * c)
     c->_history_state = MISSED;
     calllist_add ( current_calls, c );
     calllist_add( history, c );
-    calltree_add_call( current_calls , c );
+    calltree_add_call( current_calls, c, NULL);
     update_menus();
     calltree_display (current_calls);
 }
@@ -566,7 +580,7 @@ process_dialing(callable_obj_t * c, guint keyval, gchar * key)
 						g_free(before);
 						DEBUG("TO: backspace %s", c->_peer_number);
                     }
-                    calltree_update_call(current_calls,c);
+					calltree_update_call(current_calls, c, NULL);
                 }
                 else if(strlen(c->_peer_number) == 0)
                 {
@@ -601,7 +615,7 @@ process_dialing(callable_obj_t * c, guint keyval, gchar * key)
                     //g_free(c->_peer_name);
                     //c->_peer_name = g_strconcat("\"\" <", c->_peer_number, ">", NULL);
                 }
-                calltree_update_call(current_calls,c);
+                calltree_update_call(current_calls, c, NULL);
             }
             break;
     }
@@ -627,7 +641,7 @@ sflphone_new_call()
     create_new_call (CALL, CALL_STATE_DIALING, "", "", peer_name, peer_number, &c);
 
     calllist_add (current_calls,c);
-    calltree_add_call (current_calls,c);
+    calltree_add_call (current_calls, c, NULL);
     update_menus();
 
     return c;
@@ -671,7 +685,7 @@ sflphone_keypad( guint keyval, gchar * key)
                     case 65307: /* ESCAPE */
                         dbus_hang_up(c);
                         set_timestamp (&c->_time_stop);
-                        calltree_update_call( history , c );
+                        calltree_update_call(history, c, NULL);
                         break;
                     default:
                         // To play the dtmf when calling mail box for instance
@@ -694,7 +708,7 @@ sflphone_keypad( guint keyval, gchar * key)
                     case 65293: /* ENTER */
                     case 65421: /* ENTER numpad */
                         c->_history_state = INCOMING;
-                        calltree_update_call( history , c );
+                        calltree_update_call(history, c, NULL);
                         dbus_accept(c);
                         DEBUG("from sflphone_keypad ( enter ) : "); stop_notification();
                         break;
@@ -744,7 +758,7 @@ sflphone_keypad( guint keyval, gchar * key)
                     case 65307: /* ESCAPE */
                         dbus_hang_up(c);
                         //c->_stop = 0;
-                        calltree_update_call( history , c );
+                        calltree_update_call(history, c, NULL);
                         break;
                 }
                 break;
@@ -913,26 +927,125 @@ sflphone_get_current_codec_name()
     return dbus_get_current_codec_name(selectedCall);
 }
 
+    void
+sflphone_detach_participant(const gchar* callID)
+{
+    DEBUG("sflphone detach participant from conference");
+
+    
+
+    if(callID == NULL) {
+        callable_obj_t * selectedCall = calltab_get_selected_call(current_calls);
+	DEBUG("    sflphone_detach_participant %s\n", selectedCall->_callID);
+
+	calltree_remove_call(current_calls, selectedCall, NULL);
+	calltree_add_call(current_calls, selectedCall, NULL);
+        dbus_detach_participant(selectedCall->_callID);
+    }
+    else {
+	callable_obj_t * selectedCall = calllist_get(current_calls, callID);
+	DEBUG("    sflphone_detach_participant %s\n", callID);
+
+	calltree_remove_call(current_calls, selectedCall, NULL);
+	calltree_add_call(current_calls, selectedCall, NULL);
+	dbus_detach_participant(callID);	
+    }
+     
+}
+
+    void
+sflphone_join_participant(const gchar* sel_callID, const gchar* drag_callID)
+{
+    DEBUG("sflphone join participants %s and %s", sel_callID, drag_callID);
+
+    
+    dbus_join_participant(sel_callID, drag_callID);
+}
+
+
+    void
+sflphone_add_participant(const gchar* callID, const gchar* confID)
+{
+    DEBUG("sflphone add participant %s to conference %s", callID, confID);
+
+    dbus_add_participant(callID, confID);
+}
+
+    void
+sflphone_add_conference()
+{
+    DEBUG("sflphone add a conference to tree view");
+    // dbus_join_participant(selected_call, dragged_call);
+}
+
+    void
+sflphone_join_conference(const gchar* sel_confID, const gchar* drag_confID)
+{
+    DEBUG("sflphone join two conference");
+    dbus_join_conference(sel_confID, drag_confID);
+}
+
+void
+sflphone_add_main_participant(const conference_obj_t * c)
+{
+    DEBUG("sflphone add main participant");
+    dbus_add_main_participant(c->_confID);
+}
+
+void
+sflphone_conference_on_hold(const conference_obj_t * c)
+{
+    DEBUG("sflphone_conference_on_hold");
+    dbus_hold_conference(c);
+}
+
+void
+sflphone_conference_off_hold(const conference_obj_t * c)
+{
+    DEBUG("sflphone_conference_off_hold");
+    dbus_unhold_conference(c);
+}
+
+
     void
 sflphone_rec_call()
 {
     callable_obj_t * selectedCall = calltab_get_selected_call(current_calls);
-    dbus_set_record(selectedCall);
+    conference_obj_t * selectedConf = calltab_get_selected_conf(current_calls);
 
-
-    switch(selectedCall->_state)
+    if(selectedCall)
     {
-        case CALL_STATE_CURRENT:
-            selectedCall->_state = CALL_STATE_RECORD;
-            break;
-        case CALL_STATE_RECORD:
-            selectedCall->_state = CALL_STATE_CURRENT;
-            break;
-        default:
-            WARN("Should not happen in sflphone_off_hold ()!");
-            break;
+	dbus_set_record(selectedCall->_callID);
+	switch(selectedCall->_state)
+	{
+            case CALL_STATE_CURRENT:
+		selectedCall->_state = CALL_STATE_RECORD;
+		break;
+            case CALL_STATE_RECORD:
+		selectedCall->_state = CALL_STATE_CURRENT;
+		break;
+            default:
+		WARN("Should not happen in sflphone_off_hold ()!");
+		break;
+	}
     }
-    calltree_update_call(current_calls,selectedCall);
+    else if(selectedConf)
+    {
+	dbus_set_record(selectedConf->_confID);
+	switch(selectedConf->_state)
+	{
+            case CONFERENCE_STATE_ACTIVE_ATACHED:
+		selectedCall->_state = CONFERENCE_STATE_RECORD;
+		break;
+            case CONFERENCE_STATE_RECORD:
+		selectedCall->_state = CONFERENCE_STATE_ACTIVE_ATACHED;
+		break;
+            default:
+		WARN("Should not happen in sflphone_off_hold ()!");
+		break;
+	}
+    }
+    calltree_update_call(current_calls, selectedCall, NULL);
     update_menus();
 
     // gchar* codname = sflphone_get_current_codec_name();
@@ -1019,11 +1132,38 @@ void sflphone_fill_call_list (void)
             DEBUG ("Add call retrieved from server side: %s\n", c->_callID);
             calllist_add (current_calls, c);
             // Update the GUI
-            calltree_add_call (current_calls, c);
+            calltree_add_call (current_calls, c, NULL);
         }
     }
 }
 
+
+void sflphone_fill_conference_list(void)
+{
+    gchar** conferences = (gchar**)dbus_get_conference_list();
+    gchar** pl;
+    GHashTable *conference_details;
+    gchar* conf_id;
+    conference_obj_t* c;
+
+    DEBUG("sflphone_fill_conference_list");
+
+    if(conferences)
+    {
+	for (pl = conferences; *conferences; conferences++)
+	{
+	    c = g_new0(conference_obj_t, 1);
+	    conf_id = (gchar*)(*conferences);
+
+	    conference_details = dbus_get_conference_details(conf_id);
+	    create_new_call_from_details (conf_id, conference_details, &c);
+	    c->_confID = g_strdup(conf_id);
+
+	    conferencelist_add(c);
+	}
+    }
+}
+
 void sflphone_fill_history (void)
 {
     GHashTable *entries;
@@ -1086,7 +1226,7 @@ sflphone_srtp_on( callable_obj_t * c)
 {
     c->_srtp_state = SRTP_STATE_SAS_UNCONFIRMED;
 
-    calltree_update_call(current_calls, c);
+    calltree_update_call(current_calls, c, NULL);
     update_menus();
 }
 
@@ -1094,7 +1234,7 @@ sflphone_srtp_on( callable_obj_t * c)
 sflphone_srtp_off( callable_obj_t * c )
 {
     c->_srtp_state = SRTP_STATE_UNLOCKED;
-    calltree_update_call(current_calls, c);
+    calltree_update_call(current_calls, c, NULL);
     update_menus();
 }
 
@@ -1110,7 +1250,7 @@ sflphone_srtp_show_sas( callable_obj_t * c, const gchar* sas, const gboolean ver
     } else {
         c->_srtp_state = SRTP_STATE_SAS_UNCONFIRMED;
     }
-    calltree_update_call(current_calls, c);
+    calltree_update_call(current_calls, c, NULL);
     update_menus();
 }
 
@@ -1158,6 +1298,6 @@ sflphone_call_state_changed( callable_obj_t * c, const gchar * description, cons
         c->_state_code = code;   
     }
     
-    calltree_update_call(current_calls, c);
+    calltree_update_call(current_calls, c, NULL);
     update_menus();
 }
diff --git a/sflphone-client-gnome/src/actions.h b/sflphone-client-gnome/src/actions.h
index f201c248ef9814d78f6819e3af6a3be539ecaaa3..083ba441482b63e76bd8f09a1a6b8f403eaef6c1 100644
--- a/sflphone-client-gnome/src/actions.h
+++ b/sflphone-client-gnome/src/actions.h
@@ -28,6 +28,7 @@
 #include <codeclist.h>
 #include <sflphone_const.h>
 #include <errors.h>
+#include <conference_obj.h>
 
 /** @file actions.h
   * @brief General functions that change the state of the application.
@@ -178,6 +179,8 @@ void sflphone_set_current_account();
  */
 void sflphone_fill_codec_list();
 
+void sflphone_add_participant();
+
 void sflphone_record (callable_obj_t *c);
 
 void sflphone_rec_call (void);
@@ -192,6 +195,14 @@ void sflphone_fill_history (void);
 
 void sflphone_save_history (void);
 
+void sflphone_join_participant(const gchar* sel_callID, const gchar* drag_callID);
+
+void sflphone_add_participant(const gchar* callID, const gchar* confID);
+
+void sflphone_detach_participant(const gchar* callID);
+
+void sflphone_join_conference(const gchar* sel_confID, const gchar* drag_confID);
+
 /** Nofity that the communication is 
  *  now secured.
  * @param c* The current call
@@ -243,4 +254,5 @@ void sflphone_request_go_clear(void);
 
 void sflphone_call_state_changed(callable_obj_t * c, const gchar * description, const guint code);
 
+
 #endif
diff --git a/sflphone-client-gnome/src/conference_obj.c b/sflphone-client-gnome/src/conference_obj.c
new file mode 100644
index 0000000000000000000000000000000000000000..52e31bff503118de5b38fde2f2fcefc375a72328
--- /dev/null
+++ b/sflphone-client-gnome/src/conference_obj.c
@@ -0,0 +1,96 @@
+/*
+ *  Copyright (C) 2009 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.
+ */
+
+#include <callable_obj.h>
+#include <sflphone_const.h>
+#include <time.h>
+
+gint is_confID_confstruct ( gconstpointer a, gconstpointer b)
+{
+    conference_obj_t * c = (conference_obj_t*)a;
+    if(g_strcasecmp(c->_confID, (const gchar*) b) == 0)
+    {
+        return 0;
+    }
+    else
+    {
+        return 1;
+    }
+}
+
+void create_new_conference (conference_state_t state, const gchar* confID, conference_obj_t ** new_conf)
+{
+
+    conference_obj_t *obj;
+    gchar *conf_id;
+
+    // Allocate memory
+    obj = g_new0 (conference_obj_t, 1);
+
+    // Set state field    
+    obj->_state = state;
+
+    // Set the ID field
+    conf_id = confID;
+    obj->_confID = g_strdup (conf_id);
+    *new_conf = obj;
+    
+}
+
+void create_new_conference_from_details (const gchar *conf_id, GHashTable *details, conference_obj_t *conf)
+{
+    /*
+    gchar *peer_name, *peer_number, *accountID, *state_str;
+    callable_obj_t *new_call;
+    call_state_t state;
+
+    accountID = g_hash_table_lookup (details, "ACCOUNTID");
+    peer_number = g_hash_table_lookup (details, "PEER_NUMBER");
+    peer_name = g_strdup ("");
+    state_str = g_hash_table_lookup (details, "CALL_STATE");
+
+
+    if (g_strcasecmp (state_str, "CURRENT") == 0)
+        state = CALL_STATE_CURRENT;
+
+	else if (g_strcasecmp (state_str, "RINGING") == 0)
+		state = CALL_STATE_RINGING;
+
+	else if (g_strcasecmp (state_str, "INCOMING") == 0)
+		state = CALL_STATE_INCOMING;
+
+    else if (g_strcasecmp (state_str, "HOLD") == 0)
+        state = CALL_STATE_HOLD;
+
+    else if (g_strcasecmp (state_str, "BUSY") == 0)
+        state = CALL_STATE_BUSY;
+
+    else
+        state = CALL_STATE_FAILURE;
+
+    create_new_call (CALL, state, (gchar*)call_id, accountID, peer_name, peer_number, &new_call);
+    *call = new_call;
+    */
+}
+
+void free_conference_obj_t (conference_obj_t *c)
+{
+    g_free (c->_confID);
+    g_free (c);
+}
diff --git a/sflphone-client-gnome/src/conference_obj.h b/sflphone-client-gnome/src/conference_obj.h
new file mode 100644
index 0000000000000000000000000000000000000000..7f0dac5cb10d5ed9b755b0b869f366c7d795c503
--- /dev/null
+++ b/sflphone-client-gnome/src/conference_obj.h
@@ -0,0 +1,66 @@
+/*
+ *  Copyright (C) 2009 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.
+ */
+
+#ifndef __CONFERENCE_OBJ_H__
+#define __CONFERENCE_OBJ_H__
+
+#include <gtk/gtk.h>
+#include <glib/gprintf.h>
+#include <stdlib.h>
+#include <time.h>
+
+
+
+/** @enum conference_state_t
+  * This enum have all the states a conference can take.
+  */
+typedef enum
+{
+   CONFERENCE_STATE_ACTIVE_ATACHED = 0,
+   CONFERENCE_STATE_ACTIVE_DETACHED,
+   CONFERENCE_STATE_RECORD,
+   CONFERENCE_STATE_HOLD
+} conference_state_t;
+
+
+/** @struct conference_obj_t
+  * @brief Conference information.
+  * This struct holds information about a conference.
+  */
+typedef struct  {
+
+    conference_state_t _state;       // The state of the call
+    gchar* _confID;                  // The call ID
+    gboolean _conference_secured;    // the security state of the conference
+    gboolean _conf_srtp_enabled;     // security required for this conference
+
+} conference_obj_t;
+
+void create_new_conference (conference_state_t, const gchar*, conference_obj_t **);
+
+void create_new_conference_from_details (const gchar *, GHashTable *, conference_obj_t *);
+
+void free_conference_obj_t (conference_obj_t *c);
+
+/* 
+ * GCompareFunc to compare a confID (gchar* and a callable_obj_t) 
+ */
+gint is_confID_confstruct ( gconstpointer, gconstpointer);
+
+#endif
diff --git a/sflphone-client-gnome/src/contacts/Makefile.am b/sflphone-client-gnome/src/contacts/Makefile.am
index 8afd0f4dc01a53dfd633191c6663ade77b3fcd8e..288196626b1825dc76be5d094d32f81ed8d7bfbe 100644
--- a/sflphone-client-gnome/src/contacts/Makefile.am
+++ b/sflphone-client-gnome/src/contacts/Makefile.am
@@ -10,7 +10,8 @@ libcontacts_la_SOURCES = \
   calltab.c \
   calltree.c \
   history.c \
-  addressbook.c
+  addressbook.c \
+  conferencelist.c
 
 libcontacts_la_LDFLAGS = @DEPS_LDFLAGS@
 					  
diff --git a/sflphone-client-gnome/src/contacts/calllist.c b/sflphone-client-gnome/src/contacts/calllist.c
index 7bcf5f75d9dac8e836a96813e43fe2334f56ab1c..5fba11456bd82991a90034b38f31eb6ba51a1b7b 100644
--- a/sflphone-client-gnome/src/contacts/calllist.c
+++ b/sflphone-client-gnome/src/contacts/calllist.c
@@ -54,7 +54,7 @@ void calllist_add_contact (gchar *contact_name, gchar *contact_phone, contact_ty
         }
 
         calllist_add (contacts, new_call);
-        calltree_add_call(contacts, new_call);
+        calltree_add_call(contacts, new_call, NULL);
     }
 }
 
@@ -83,7 +83,7 @@ void calllist_add_history_entry (callable_obj_t *obj)
     if ( g_strcasecmp (dbus_get_history_enabled (), "true") == 0)
     {
         g_queue_push_tail (history->callQueue, (gpointer *) obj);
-        calltree_add_call (history, obj);
+        calltree_add_call (history, obj, NULL);
     }
 }
 
@@ -111,7 +111,7 @@ calllist_clean_history( void )
     callable_obj_t* c = calllist_get_nth( history , i );
     // Delete the call from the call tree
     DEBUG("Delete calls");
-    calltree_remove_call(history , c);
+    calltree_remove_call(history, c, NULL);
   }
   calllist_reset( history );
 }
@@ -121,7 +121,7 @@ void
 calllist_remove_from_history( callable_obj_t* c )
 {
   calllist_remove( history, c->_callID );
-  calltree_remove_call( history, c );
+  calltree_remove_call(history, c, NULL);
   DEBUG("Size of history = %i" , calllist_get_size( history ));
 }
 
diff --git a/sflphone-client-gnome/src/contacts/calllist.h b/sflphone-client-gnome/src/contacts/calllist.h
index 3caccad439c4689374c411b296125ac8cff5bf18..befb97048e8a867298551eb1afb69a2a584678b7 100644
--- a/sflphone-client-gnome/src/contacts/calllist.h
+++ b/sflphone-client-gnome/src/contacts/calllist.h
@@ -21,6 +21,7 @@
 #define __CALLLIST_H__
 
 #include <callable_obj.h>
+#include <conference_obj.h>
 #include <gtk/gtk.h>
 
 /** @file calllist.h
@@ -28,15 +29,17 @@
   */
 
 typedef struct {
-	GtkListStore* store;
+	GtkTreeStore* store;
 	GtkWidget* view;
 	GtkWidget* tree;
-    GtkWidget* searchbar;
+        GtkWidget* searchbar;
 
-  // Calllist vars
+        // Calllist vars
 	GQueue* callQueue;
+        gint selectedType;
 	callable_obj_t* selectedCall;
-    gchar *_name;
+        conference_obj_t* selectedConf;
+        gchar *_name;
 } calltab_t;
 
 void
diff --git a/sflphone-client-gnome/src/contacts/calltab.c b/sflphone-client-gnome/src/contacts/calltab.c
index 00cfc85343213d062e0b11d96d35dc2737300745..f832d6c561f5c65baa091b0e13b80c1c48d2cfe6 100644
--- a/sflphone-client-gnome/src/contacts/calltab.c
+++ b/sflphone-client-gnome/src/contacts/calltab.c
@@ -32,10 +32,11 @@ calltab_t* calltab_init (gboolean searchbar_type, gchar *name)
 	ret->store = NULL;
 	ret->view = NULL;
 	ret->tree = NULL;
-    ret->searchbar = NULL;
+        ret->searchbar = NULL;
 	ret->callQueue = NULL;
 	ret->selectedCall = NULL;
-    ret->_name = g_strdup (name);
+	ret->selectedConf = NULL;
+        ret->_name = g_strdup (name);
 
 	calltree_create (ret, searchbar_type);
 	calllist_init(ret);
@@ -47,16 +48,36 @@ calltab_t* calltab_init (gboolean searchbar_type, gchar *name)
 void
 calltab_select_call (calltab_t* tab, callable_obj_t * c )
 {
-  tab->selectedCall = c;
+    tab->selectedType = A_CALL;
+    tab->selectedCall = c;
 }
 
 
+void
+calltab_select_conf (conference_obj_t * c )
+{
+    current_calls->selectedType = A_CONFERENCE;
+    current_calls->selectedConf = c;
+}
+
+gint
+calltab_get_selected_type(calltab_t* tab)
+{
+    return tab->selectedType;
+}
+
 callable_obj_t *
 calltab_get_selected_call (calltab_t* tab)
 {
   return tab->selectedCall;
 }
 
+conference_obj_t*
+calltab_get_selected_conf ()
+{
+    return current_calls->selectedConf;
+}
+
 void
 calltab_create_searchbar (calltab_t* tab)
 {
diff --git a/sflphone-client-gnome/src/contacts/calltab.h b/sflphone-client-gnome/src/contacts/calltab.h
index 25c3ddb70f99effcd6f507e3a169821e9ca25eb5..bf3b11b8407efda3ab1e7a74c4ff9b3050279860 100644
--- a/sflphone-client-gnome/src/contacts/calltab.h
+++ b/sflphone-client-gnome/src/contacts/calltab.h
@@ -21,6 +21,7 @@
 #define __CALLTAB_H__
 
 #include <calllist.h>
+#include <conferencelist.h>
 #include <gtk/gtk.h>
 
 calltab_t* active_calltree;
@@ -30,17 +31,28 @@ calltab_t* contacts;
 
 calltab_t* calltab_init (gboolean searchbar_type, gchar *name);
 
+
+
 /** Mark a call as selected.  There can be only one selected call.  This call
   * is the currently highlighted one in the list.
   * @param c The call */
 void
 calltab_select_call (calltab_t*, callable_obj_t *);
 
+void
+calltab_select_conf (conference_obj_t *);
+
+gint
+calltab_get_selected_type(calltab_t* tab);
+
 /** Return the selected call.
   * @return The number of the caller */
 callable_obj_t *
 calltab_get_selected_call (calltab_t*);
 
+conference_obj_t *
+calltab_get_selected_conf ();
+
 void
 calltab_create_searchbar (calltab_t *);
 
diff --git a/sflphone-client-gnome/src/contacts/calltree.c b/sflphone-client-gnome/src/contacts/calltree.c
index 96cebea0d8477da5bb08d7b126e33e9db7d4cb2f..40e772bbd67c1823fdc43edc16bfb7c1b5d9b101 100644
--- a/sflphone-client-gnome/src/contacts/calltree.c
+++ b/sflphone-client-gnome/src/contacts/calltree.c
@@ -2,6 +2,7 @@
  *  Copyright (C) 2007 Savoir-Faire Linux inc.
  *  Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com>
  *  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
@@ -22,6 +23,7 @@
 #include <stdlib.h>
 #include <glib/gprintf.h>
 #include <calllist.h>
+#include <conferencelist.h>
 #include <toolbar.h>
 #include <mainwindow.h>
 #include <history.h>
@@ -31,6 +33,30 @@ GtkCellRenderer *rend;
 GtkTreeViewColumn *col;
 GtkTreeSelection *sel;
 
+gint dragged_type;
+gint selected_type;
+
+gchar *dragged_call_id;
+gchar *selected_call_id;
+
+gchar *dragged_path;
+gchar *selected_path;
+
+gint dragged_path_depth;
+gint selected_path_depth;
+ 
+callable_obj_t *dragged_call;
+callable_obj_t *selected_call;
+
+conference_obj_t *dragged_conf;
+conference_obj_t *selected_conf;
+
+
+static void drag_begin_cb(GtkWidget *widget, GdkDragContext *dc, gpointer data);
+static void drag_end_cb(GtkWidget * mblist, GdkDragContext * context, gpointer data);
+void drag_data_received_cb(GtkWidget *widget, GdkDragContext *dc, gint x, gint y, GtkSelectionData *selection_data, guint info, guint t, gpointer data);
+
+
 enum {
     COLUMN_ACCOUNT_STATE = 0,
     COLUMN_ACCOUNT_DESC,
@@ -38,10 +64,11 @@ enum {
     COLUMN_ACCOUNT_PTR,
 };
 
+
 /**
  * Show popup menu
  */
-    static gboolean
+static gboolean
 popup_menu (GtkWidget *widget,
         gpointer   user_data UNUSED)
 {
@@ -50,87 +77,170 @@ popup_menu (GtkWidget *widget,
 }
 
 /* Call back when the user click on a call in the list */
-    static void
+static void
 call_selected_cb(GtkTreeSelection *sel, void* data UNUSED )
 {
-    GtkTreeIter  iter;
+
+    DEBUG("Selection Callback");
+
+    GtkTreeIter iter;
     GValue val;
     GtkTreeModel *model = (GtkTreeModel*)active_calltree->store;
 
+    GtkTreePath* path;
+    gchar* string_path;
+
+
     if (! gtk_tree_selection_get_selected (sel, &model, &iter))
         return;
 
-    val.g_type = 0;
-    gtk_tree_model_get_value (model, &iter, COLUMN_ACCOUNT_PTR, &val);
 
-    calltab_select_call(active_calltree, (callable_obj_t*) g_value_get_pointer(&val));
-    g_value_unset(&val);
+    // store info for dragndrop
+    path = gtk_tree_model_get_path(model, &iter);
+    string_path = gtk_tree_path_to_string(path);
+    selected_path_depth = gtk_tree_path_get_depth(path);
+
+    if(gtk_tree_model_iter_has_child(GTK_TREE_MODEL(model), &iter))
+    {
+	DEBUG("SELECTED A CONFERENCE");
+	selected_type = A_CONFERENCE;
+
+	val.g_type = 0;
+	gtk_tree_model_get_value (model, &iter, COLUMN_ACCOUNT_PTR, &val);
+
+	calltab_select_conf((conference_obj_t*) g_value_get_pointer(&val));
 
+	selected_conf = (conference_obj_t*)g_value_get_pointer(&val);
+
+	if(selected_conf) 
+	{
+
+	    selected_call_id = selected_conf->_confID;
+	    selected_path = string_path;
+
+	}
+
+    }
+    else
+    {
+	DEBUG("SELECTED A CALL");
+	selected_type = A_CALL;
+	// gtk_tree_model_iter_parent(GTK_TREE_MODEL(model), parent_conference, &iter);
+
+	val.g_type = 0;
+        gtk_tree_model_get_value (model, &iter, COLUMN_ACCOUNT_PTR, &val);
+
+        calltab_select_call(active_calltree, (callable_obj_t*) g_value_get_pointer(&val));
+
+        selected_call = (callable_obj_t*)g_value_get_pointer(&val);
+
+	selected_call_id = selected_call->_callID;
+	selected_path = string_path;
+    }
+
+    DEBUG("selected_cb\n");
+    DEBUG("  selected_path %s, selected_call_id %s, selected_path_depth %i\n", selected_path, selected_call_id, selected_path_depth);
+
+    // conferencelist_reset ();
+    // sflphone_fill_conference_list();
+
+    g_value_unset(&val);
     toolbar_update_buttons();
 
-    // set_focus_on_mainwindow();
 }
 
 /* A row is activated when it is double clicked */
-void  row_activated(GtkTreeView       *tree_view UNUSED,
+void 
+row_activated(GtkTreeView       *tree_view UNUSED,
         GtkTreePath       *path UNUSED,
         GtkTreeViewColumn *column UNUSED,
         void * data UNUSED)
 {
-    callable_obj_t* selectedCall;
+    callable_obj_t* selectedCall = NULL;
     callable_obj_t* new_call;
+    conference_obj_t* selectedConf = NULL;
     gchar *account_id;
 
     DEBUG("double click action");
 
-    selectedCall = calltab_get_selected_call( active_calltree );
-
-    if (selectedCall)
+    if( active_calltree == current_calls )
     {
-        // Get the right event from the right calltree
-        if( active_calltree == current_calls )
-        {
-            switch(selectedCall->_state)
-            {
-                case CALL_STATE_INCOMING:
-                    dbus_accept(selectedCall);
-                    stop_notification();
-                    break;
-                case CALL_STATE_HOLD:
-                    dbus_unhold(selectedCall);
-                    break;
-                case CALL_STATE_RINGING:
-                case CALL_STATE_CURRENT:
-                case CALL_STATE_BUSY:
-                case CALL_STATE_FAILURE:
-                    break;
-                case CALL_STATE_DIALING:
-                    sflphone_place_call (selectedCall);
-                    break;
-                default:
-                    WARN("Row activated - Should not happen!");
-                    break;
-            }
-        }
-
-        // If history or contact: double click action places a new call
-        else
-        {
-            account_id = g_strdup (selectedCall->_accountID);
-
-            // Create a new call
-            create_new_call (CALL, CALL_STATE_DIALING, "", account_id, selectedCall->_peer_name, selectedCall->_peer_number, &new_call);
-
-            calllist_add(current_calls, new_call);
-            calltree_add_call(current_calls, new_call);
-            sflphone_place_call(new_call);
-            calltree_display(current_calls);
-        }
+	
+	if(calltab_get_selected_type(current_calls) == A_CALL)
+	{
+	    selectedCall = calltab_get_selected_call(current_calls);
+
+	    if (selectedCall)
+	    {
+		// Get the right event from the right calltree
+		if( active_calltree == current_calls )
+		{
+		    switch(selectedCall->_state)
+		    {
+		    case CALL_STATE_INCOMING:
+			dbus_accept(selectedCall);
+			stop_notification();
+			break;
+		    case CALL_STATE_HOLD:
+			dbus_unhold(selectedCall);
+			break;
+		    case CALL_STATE_RINGING:
+		    case CALL_STATE_CURRENT:
+		    case CALL_STATE_BUSY:
+		    case CALL_STATE_FAILURE:
+			break;
+		    case CALL_STATE_DIALING:
+			sflphone_place_call (selectedCall);
+			break;
+		    default:
+			WARN("Row activated - Should not happen!");
+			break;
+		    }
+		}
+
+		// If history or contact: double click action places a new call
+		else
+		{
+		    account_id = g_strdup (selectedCall->_accountID);
+
+		    // Create a new call
+		    create_new_call (CALL, CALL_STATE_DIALING, "", account_id, selectedCall->_peer_name, selectedCall->_peer_number, &new_call);
+		    
+		    calllist_add(current_calls, new_call);
+		    calltree_add_call(current_calls, new_call, NULL);
+		    sflphone_place_call(new_call);
+		    calltree_display(current_calls);
+		}
+	    }
+	}
+	else
+	{
+	    selectedConf = calltab_get_selected_conf(current_calls);
+ 
+	    if(selectedConf)
+	    {
+		switch(selectedConf->_state)
+		{
+	            case CONFERENCE_STATE_ACTIVE_ATACHED:
+		        sflphone_add_main_participant(selectedConf);
+			break;
+		    case CONFERENCE_STATE_ACTIVE_DETACHED:
+			sflphone_add_main_participant(selectedConf);
+			break;
+	            case CONFERENCE_STATE_HOLD:
+			sflphone_conference_off_hold(selectedConf);
+			break;
+		}
+	    }
+	}
     }
+    
+    
 }
 
 /* Catch cursor-activated signal. That is, when the entry is single clicked */
-void  row_single_click(GtkTreeView *tree_view UNUSED, void * data UNUSED)
+void  
+row_single_click(GtkTreeView *tree_view UNUSED, void * data UNUSED)
 {
     DEBUG("single click action");
     callable_obj_t * selectedCall=NULL;
@@ -167,12 +277,12 @@ void  row_single_click(GtkTreeView *tree_view UNUSED, void * data UNUSED)
                         selectedCall->_zrtp_confirmed = TRUE;
                     }
                     dbus_confirm_sas(selectedCall);
-                    calltree_update_call(current_calls, selectedCall);
+                    calltree_update_call(current_calls, selectedCall, NULL);
                     break;
                 case SRTP_STATE_SAS_CONFIRMED:
                     selectedCall->_srtp_state = SRTP_STATE_SAS_UNCONFIRMED;
                     dbus_reset_sas(selectedCall);
-                    calltree_update_call(current_calls, selectedCall);
+                    calltree_update_call(current_calls, selectedCall, NULL);
                     break;
                 default:
                     DEBUG("Single click but no action");
@@ -182,7 +292,7 @@ void  row_single_click(GtkTreeView *tree_view UNUSED, void * data UNUSED)
     }
 }
 
-    static gboolean
+static gboolean
 button_pressed(GtkWidget* widget, GdkEventButton *event, gpointer user_data UNUSED)
 {
     if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
@@ -208,10 +318,10 @@ button_pressed(GtkWidget* widget, GdkEventButton *event, gpointer user_data UNUS
 /**
  * Reset call tree
  */
-    void
+void
 calltree_reset (calltab_t* tab)
 {
-    gtk_list_store_clear (tab->store);
+    gtk_tree_store_clear (tab->store);
 }
 
 void
@@ -228,7 +338,7 @@ focus_on_calltree_in(){
     focus_is_on_calltree = TRUE;
 }
 
-    void
+void
 calltree_create (calltab_t* tab, gboolean searchbar_type)
 {
 
@@ -243,7 +353,8 @@ calltree_create (calltab_t* tab, gboolean searchbar_type)
     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
     gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN);
 
-    tab->store = gtk_list_store_new (4,
+
+    tab->store = gtk_tree_store_new (4,
             GDK_TYPE_PIXBUF,// Icon
             G_TYPE_STRING,  // Description
             GDK_TYPE_PIXBUF, // Security Icon
@@ -280,6 +391,23 @@ calltree_create (calltab_t* tab, gboolean searchbar_type)
     g_signal_connect_after (G_OBJECT (tab->view), "focus-out-event",
             G_CALLBACK (focus_on_calltree_out), NULL);
 
+
+    if(tab != history || tab!=contacts) {
+
+	DEBUG("SET TREE VIEW REORDABLE");
+        // Make calltree reordable for drag n drop
+        gtk_tree_view_set_reorderable(GTK_TREE_VIEW(tab->view), TRUE); 
+
+        // source widget drag n drop signals
+        g_signal_connect (G_OBJECT (tab->view), "drag_begin", G_CALLBACK (drag_begin_cb), NULL);
+        g_signal_connect (G_OBJECT (tab->view), "drag_end", G_CALLBACK (drag_end_cb), NULL);
+
+        // destination widget drag n drop signals
+        g_signal_connect (G_OBJECT (tab->view), "drag_data_received", G_CALLBACK (drag_data_received_cb), NULL);
+
+    }
+
+
     gtk_widget_grab_focus(GTK_WIDGET(tab->view));
 
     rend = gtk_cell_renderer_pixbuf_new();
@@ -328,20 +456,29 @@ calltree_create (calltab_t* tab, gboolean searchbar_type)
     gtk_widget_show(tab->tree);
 }
 
-    void
-calltree_remove_call (calltab_t* tab, callable_obj_t * c)
+
+void
+calltree_remove_call (calltab_t* tab, callable_obj_t * c, GtkTreeIter *parent)
 {
+
+    DEBUG("calltree_remove_call %s", c->_callID);
+
     GtkTreeIter iter;
     GValue val;
     callable_obj_t * iterCall;
-    GtkListStore* store = tab->store;
+    GtkTreeStore* store = tab->store;
 
-    int nbChild = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), NULL);
+    int nbChild = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), parent);
     int i;
     for( i = 0; i < nbChild; i++)
     {
-        if(gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, NULL, i))
+        if(gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, parent, i))
         {
+	    if(gtk_tree_model_iter_has_child(GTK_TREE_MODEL(store), &iter))
+	    {
+		calltree_remove_call (tab, c, &iter);
+	    }
+
             val.g_type = 0;
             gtk_tree_model_get_value (GTK_TREE_MODEL(store), &iter, COLUMN_ACCOUNT_PTR, &val);
 
@@ -350,7 +487,7 @@ calltree_remove_call (calltab_t* tab, callable_obj_t * c)
 
             if(iterCall == c)
             {
-                gtk_list_store_remove(store, &iter);
+                gtk_tree_store_remove(store, &iter);
             }
         }
     }
@@ -360,22 +497,24 @@ calltree_remove_call (calltab_t* tab, callable_obj_t * c)
     toolbar_update_buttons();
 }
 
-    void
-calltree_update_call (calltab_t* tab, callable_obj_t * c)
+void
+calltree_update_call (calltab_t* tab, callable_obj_t * c, GtkTreeIter *parent)
 {
     GdkPixbuf *pixbuf=NULL;
     GdkPixbuf *pixbuf_security=NULL;
     GtkTreeIter iter;
     GValue val;
     callable_obj_t * iterCall;
-    GtkListStore* store = tab->store;
+    GtkTreeStore* store = tab->store;
+
     gchar* srtp_enabled = "";
     gboolean display_sas = TRUE;
     account_t* account_details=NULL;
+
     
-    int nbChild = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), NULL);
+    int nbChild = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), parent);
     int i;
-    
+
     if(c != NULL) {
         account_details = account_list_get_by_id(c->_accountID);
         if(account_details != NULL) {
@@ -391,190 +530,157 @@ calltree_update_call (calltab_t* tab, callable_obj_t * c)
             }
         }
     } 
-    
+
     for( i = 0; i < nbChild; i++)
     {
-        if(!gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, NULL, i)) {
-            continue;
-        }
-        
-        val.g_type = 0;
-        gtk_tree_model_get_value (GTK_TREE_MODEL(store), &iter, COLUMN_ACCOUNT_PTR, &val);
 
-        iterCall = (callable_obj_t*) g_value_get_pointer(&val);
-        g_value_unset(&val);
+        if(gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, parent, i))
+        {
 
-        if(iterCall != c) {
-            continue;
-        }
+	    if(gtk_tree_model_iter_has_child(GTK_TREE_MODEL(store), &iter))
+	    {
+		calltree_update_call (tab, c, &iter);
+	    }
+
+            val.g_type = 0;
+            gtk_tree_model_get_value (GTK_TREE_MODEL(store), &iter, COLUMN_ACCOUNT_PTR, &val);
+
+
+	    iterCall = (callable_obj_t*) g_value_get_pointer(&val);
+	    g_value_unset(&val);
+
+	    if(iterCall != c) {
+		continue;
+	    }
         
-        /* Update text */
-        gchar * description;
-        gchar * date="";
-        gchar * duration="";
+	    /* Update text */
+	    gchar * description;
+	    gchar * date="";
+	    gchar * duration="";
         
-        if(c->_state == CALL_STATE_TRANSFERT)
-        {
-            description = g_markup_printf_escaped("<b>%s</b> <i>%s</i>\n<i>Transfert to:%s</i> ",
-                    c->_peer_number,
-                    c->_peer_name,
-                    c->_trsft_to
-                    );
-        }
-        else
-        {
-            // c->_zrtp_confirmed == FALSE : Hack explained in callable_obj.h
-            if((c->_sas != NULL) && (display_sas == TRUE) && (c->_srtp_state == SRTP_STATE_SAS_UNCONFIRMED) && (c->_zrtp_confirmed == FALSE)) {
-                description = g_markup_printf_escaped("<b>%s</b> <i>%s</i>\n<i>Confirm SAS <b>%s</b> ?</i> ",
-                    c->_peer_number,
-                    c->_peer_name,
-                    c->_sas
-                    );
-            } else {
-                DEBUG("Updating state code %d %s", c->_state_code, c->_state_code_description);
-                if (c->_state_code) {
-                    description = g_markup_printf_escaped("<b>%s</b> <i>%s</i>\n<i>%s (%d)</i>",
-                        c->_peer_number,
-                        c->_peer_name,
-                        c->_state_code_description,
-                        c->_state_code);
-                } else {
-                    description = g_markup_printf_escaped("<b>%s</b> <i>%s</i>",
-                        c->_peer_number,
-                        c->_peer_name );                
+	    if(c->_state == CALL_STATE_TRANSFERT)
+	    {
+		description = g_markup_printf_escaped("<b>%s</b> <i>%s</i>\n<i>Transfert to:%s</i> ",
+						      c->_peer_number,
+						      c->_peer_name,
+						      c->_trsft_to);
+	    }
+	    else
+	    {
+		// c->_zrtp_confirmed == FALSE : Hack explained in callable_obj.h
+		if((c->_sas != NULL) && (display_sas == TRUE) && (c->_srtp_state == SRTP_STATE_SAS_UNCONFIRMED) && (c->_zrtp_confirmed == FALSE)) {
+		    description = g_markup_printf_escaped("<b>%s</b> <i>%s</i>\n<i>Confirm SAS <b>%s</b> ?</i> ",
+							  c->_peer_number,
+							  c->_peer_name,
+							  c->_sas);
+		} else {
+		    DEBUG("Updating state code %d %s", c->_state_code, c->_state_code_description);
+		    if (c->_state_code) {
+			description = g_markup_printf_escaped("<b>%s</b> <i>%s</i>\n<i>%s (%d)</i>",
+							      c->_peer_number,
+							      c->_peer_name,
+							      c->_state_code_description,
+							      c->_state_code);
+		    } else {
+			description = g_markup_printf_escaped("<b>%s</b> <i>%s</i>",
+							      c->_peer_number,
+							      c->_peer_name );                
+		    }
+		}
+	    }
+
+	    /* Update icons */
+	    if( tab == current_calls )
+	    {
+		DEBUG("Receiving in state %d", c->_state);
+		switch(c->_state)
+		{
+                    case CALL_STATE_HOLD:
+			pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/hold.svg", NULL);
+			break;
+                    case CALL_STATE_INCOMING:
+                    case CALL_STATE_RINGING:
+			pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/ring.svg", NULL);
+			break;
+                    case CALL_STATE_CURRENT:
+			pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/current.svg", NULL);
+			break;
+                    case CALL_STATE_DIALING:
+			pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/dial.svg", NULL);
+			break;
+                    case CALL_STATE_FAILURE:
+			pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/fail.svg", NULL);
+			break;
+                    case CALL_STATE_BUSY:
+			pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/busy.svg", NULL);
+			break;
+                    case CALL_STATE_TRANSFERT:
+			pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/transfert.svg", NULL);
+			break;
+                    case CALL_STATE_RECORD:
+			pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/icon_rec.svg", NULL);
+			break;
+                    default:
+			WARN("Update calltree - Should not happen!");
+		}        
+
+		switch(c->_srtp_state)
+		{
+                    case SRTP_STATE_SAS_UNCONFIRMED:
+			DEBUG("Secure is ON");
+			pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_unconfirmed.svg", NULL);
+                        if(c->_sas != NULL) { DEBUG("SAS is ready with value %s", c->_sas); }
+			break;
+                    case SRTP_STATE_SAS_CONFIRMED:
+			DEBUG("SAS is confirmed");
+			pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_confirmed.svg", NULL);   
+                        break;
+                    case SRTP_STATE_SAS_SIGNED:   
+			DEBUG("Secure is ON with SAS signed and verified");
+			pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_certified.svg", NULL);
+			break;
+                    case SRTP_STATE_UNLOCKED:  
+                        DEBUG("Secure is off calltree %d", c->_state);
+                        if(g_strcasecmp(srtp_enabled,"true") == 0) {
+			    pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_off.svg", NULL); 
+			}
+			break;
+                    default:
+			WARN("Update calltree srtp state #%d- Should not happen!", c->_srtp_state); 
+			if(g_strcasecmp(srtp_enabled,"true") == 0) {
+			    pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_off.svg", NULL);    
+			}
+
                 }
-            }
-        }
+                gtk_tree_store_set(store, &iter,
+                        0, pixbuf, // Icon
+                        1, description, // Description
+			2, pixbuf_security,
+			3, c,
+                        -1);
 
-        /* Update icons */
-        if( tab == current_calls )
-        {
-            DEBUG("Receiving in state %d", c->_state);
-            switch(c->_state)
-            {
-                case CALL_STATE_HOLD:
-                    pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/hold.svg", NULL);
-                    break;
-                case CALL_STATE_INCOMING:
-                case CALL_STATE_RINGING:
-                    pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/ring.svg", NULL);
-                    break;
-                case CALL_STATE_CURRENT:
-                    pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/current.svg", NULL);
-                    break;
-                case CALL_STATE_DIALING:
-                    pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/dial.svg", NULL);
-                    break;
-                case CALL_STATE_FAILURE:
-                    pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/fail.svg", NULL);
-                    break;
-                case CALL_STATE_BUSY:
-                    pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/busy.svg", NULL);
-                    break;
-                case CALL_STATE_TRANSFERT:
-                    pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/transfert.svg", NULL);
-                    break;
-                case CALL_STATE_RECORD:
-                    pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/rec_call.svg", NULL);
-                    break;
-                default:
-                    WARN("Update calltree - Should not happen!");
-            }        
+                if (pixbuf != NULL)
+                    g_object_unref(G_OBJECT(pixbuf));
 
-            switch(c->_srtp_state)
-            {
-                case SRTP_STATE_SAS_UNCONFIRMED:
-                    DEBUG("Secure is ON");
-                    pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_unconfirmed.svg", NULL);
-                    if(c->_sas != NULL) { DEBUG("SAS is ready with value %s", c->_sas); }
-                    break;
-                case SRTP_STATE_SAS_CONFIRMED:
-                    DEBUG("SAS is confirmed");
-                    pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_confirmed.svg", NULL);   
-                    break;
-                case SRTP_STATE_SAS_SIGNED:   
-                    DEBUG("Secure is ON with SAS signed and verified");
-                    pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_certified.svg", NULL);
-                    break;
-                case SRTP_STATE_UNLOCKED:  
-                    DEBUG("Secure is off calltree %d", c->_state);
-                    if(g_strcasecmp(srtp_enabled,"true") == 0) {
-                        pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_off.svg", NULL); 
-                    }
-                    break;
-                default:
-                    WARN("Update calltree srtp state #%d- Should not happen!", c->_srtp_state); 
-                    if(g_strcasecmp(srtp_enabled,"true") == 0) {
-                        pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_off.svg", NULL);    
-                    }
-            }
-        }
-        else
-        {
-            switch(c->_history_state)
-            {
-                case OUTGOING:
-                    DEBUG("Outgoing state");
-                    pixbuf = gdk_pixbuf_new_from_file( ICONS_DIR "/outgoing.svg", NULL);
-                    break;
-                case INCOMING:
-                    DEBUG("Incoming state");
-                    pixbuf = gdk_pixbuf_new_from_file( ICONS_DIR "/incoming.svg", NULL);
-                    break;
-                case MISSED:
-                    DEBUG("Missed state");
-                    pixbuf = gdk_pixbuf_new_from_file( ICONS_DIR "/missed.svg", NULL);
-                    break;
-                default:
-                    DEBUG("No history state");
-                    break;
-            }
-            date = get_formatted_start_timestamp (c);
-            duration = get_call_duration (c);
-            duration = g_strconcat( date , duration , NULL);
-            description = g_strconcat( description , duration, NULL);
-        }
-        
-        //Resize it
-        if(pixbuf != NULL)
-        {
-            if(gdk_pixbuf_get_width(pixbuf) > 32 || gdk_pixbuf_get_height(pixbuf) > 32)
-            {
-                pixbuf =  gdk_pixbuf_scale_simple(pixbuf, 32, 32, GDK_INTERP_BILINEAR);
-            }
-        }
-        
-        if(pixbuf_security != NULL)
-        {
-            if(gdk_pixbuf_get_width(pixbuf_security) > 32 || gdk_pixbuf_get_height(pixbuf_security) > 32)
-            {
-                pixbuf_security =  gdk_pixbuf_scale_simple(pixbuf_security, 32, 32, GDK_INTERP_BILINEAR);
             }
         }
-        
-        gtk_list_store_set(store, &iter,
-                0, pixbuf, // Icon
-                1, description, // Description
-                2, pixbuf_security, // Icon
-                -1);
-
-        if (pixbuf != NULL)
-            { g_object_unref(G_OBJECT(pixbuf)); }
-            
-        if (pixbuf_security != NULL)
-            { g_object_unref(G_OBJECT(pixbuf_security)); }
+
     }
-    
     toolbar_update_buttons();
 }
 
-void calltree_add_call (calltab_t* tab, callable_obj_t * c)
+
+void calltree_add_call (calltab_t* tab, callable_obj_t * c, GtkTreeIter *parent)
 {
+
+    DEBUG("calltree_add_call %s", c->_callID);
+
     if (tab == history)
     {
         calltree_add_history_entry (c);
         return;
     }
+
     account_t* account_details=NULL;
 
     GdkPixbuf *pixbuf=NULL;
@@ -587,11 +693,24 @@ void calltree_add_call (calltab_t* tab, callable_obj_t * c)
     gchar * description;
     gchar * date="";
     gchar *duration="";
-    description = g_markup_printf_escaped("<b>%s</b> <i>%s</i>",
-            c->_peer_number,
-            c->_peer_name);
 
-    gtk_list_store_prepend (tab->store, &iter);
+    if(c->_state_code == 0) {
+
+	description = g_markup_printf_escaped("<b>%s</b> <i>%s</i>",
+							      c->_peer_number,
+							      c->_peer_name);
+
+    }
+    else {
+
+	description = g_markup_printf_escaped("<b>%s</b> <i>%s</i>\n<i>%s (%d)</i>",
+							      c->_peer_number,
+							      c->_peer_name,
+							      c->_state_code_description,
+							      c->_state_code);
+    }
+
+    gtk_tree_store_prepend (tab->store, &iter, parent);
 
     if(c != NULL) {
         account_details = account_list_get_by_id(c->_callID);
@@ -662,13 +781,12 @@ void calltree_add_call (calltab_t* tab, callable_obj_t * c)
         }
     }
     
-    gtk_list_store_set(tab->store, &iter,
-            0, pixbuf, // Icon
-            1, description, // Description
-            2, pixbuf_security, // Informs user about the state of security
-            3, c,      // Pointer
-            -1);
-
+    gtk_tree_store_set(tab->store, &iter,
+		       0, pixbuf, // Icon
+		       1, description, // Description
+		       2, pixbuf_security, // Informs user about the state of security
+		       3, c,      // Pointer
+		       -1);
 
     if (pixbuf != NULL)
        { g_object_unref(G_OBJECT(pixbuf)); }
@@ -685,6 +803,8 @@ void calltree_add_call (calltab_t* tab, callable_obj_t * c)
 void calltree_add_history_entry (callable_obj_t * c)
 {
 
+    DEBUG("calltree_add_history_entry %s", c->_callID);
+
     if ( g_strcasecmp (dbus_get_history_enabled (), "false") == 0)
         return;
 
@@ -698,7 +818,7 @@ void calltree_add_history_entry (callable_obj_t * c)
             c->_peer_number,
             c->_peer_name);
 
-    gtk_list_store_prepend (history->store, &iter);
+    gtk_tree_store_prepend (history->store, &iter, NULL);
 
     switch(c->_history_state)
     {
@@ -738,7 +858,7 @@ void calltree_add_history_entry (callable_obj_t * c)
             pixbuf_security =  gdk_pixbuf_scale_simple(pixbuf_security, 32, 32, GDK_INTERP_BILINEAR);
         }
     }
-    gtk_list_store_set(history->store, &iter,
+    gtk_tree_store_set(history->store, &iter,
             0, pixbuf, // Icon
             1, description, // Description
             2, pixbuf_security, // Icon
@@ -755,6 +875,270 @@ void calltree_add_history_entry (callable_obj_t * c)
     history_reinit(history);
 }
 
+
+void calltree_add_conference (calltab_t* tab, conference_obj_t* conf)
+{
+
+    DEBUG("calltree_add_conference conf->_confID %s\n", conf->_confID);
+
+    GdkPixbuf *pixbuf=NULL;
+    GdkPixbuf *pixbuf_security=NULL;
+    GtkTreeIter iter;
+    GtkTreePath *path;
+    GtkTreeModel *model = (GtkTreeModel*)active_calltree->store;
+
+    gchar** participant = (gchar**)dbus_get_participant_list(conf->_confID);
+    gchar** pl;
+    gchar* call_id;
+
+    callable_obj_t * call;
+
+    account_t* account_details=NULL;
+    gchar* srtp_enabled="";
+
+    // New call in the list
+    
+    gchar * description;
+    // description = g_markup_printf_escaped("<b>%s</b>", conf->_confID);
+    description = g_markup_printf_escaped("<b>%s</b>", "");
+
+    gtk_tree_store_append (tab->store, &iter, NULL);
+
+    if( tab == current_calls )
+    {
+	switch(conf->_state)
+	{
+	    case CONFERENCE_STATE_ACTIVE_ATACHED:
+	    {
+		
+		pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/usersActive.svg", NULL);
+	        break;
+	    }
+            case CONFERENCE_STATE_ACTIVE_DETACHED:
+            case CONFERENCE_STATE_HOLD:
+	    {
+
+		
+	        pixbuf = gdk_pixbuf_new_from_file(ICONS_DIR "/users.svg", NULL);
+	        break;
+	    }
+	    default:
+                WARN("Update conference add - Should not happen!");
+	}
+
+    }
+    
+    else {
+        WARN ("Conferences cannot be added in this widget - This is a bug in the application.");
+    }
+
+    //Resize it
+    if(pixbuf)
+    {
+        if(gdk_pixbuf_get_width(pixbuf) > 32 || gdk_pixbuf_get_height(pixbuf) > 32)
+        {
+            pixbuf =  gdk_pixbuf_scale_simple(pixbuf, 32, 32, GDK_INTERP_BILINEAR);
+        }
+    }
+    else 
+    {
+	DEBUG("Error no pixbuff for conference from %s", ICONS_DIR);
+    }
+
+
+    // Used to determine if at least one participant use a security feature
+    // If true (at least on call use a security feature) we need to display security icons 
+    conf->_conf_srtp_enabled = FALSE;
+
+    // Used to determine if the conference is secured
+    // Every participant to a conference must be secured, the conference is not secured elsewhere
+    conf->_conference_secured = TRUE;
+
+
+    participant = (gchar**)dbus_get_participant_list(conf->_confID);
+    if(participant)
+    {
+	participant = (gchar**)dbus_get_participant_list(conf->_confID);
+	for (pl = participant; *participant; participant++)
+	{	    
+	    call_id = (gchar*)(*participant);
+	    call = calllist_get (tab, call_id);
+
+	    if(call != NULL) {
+		
+		account_details = account_list_get_by_id(call->_callID);
+		if(account_details != NULL) {
+		    srtp_enabled = g_hash_table_lookup(account_details->properties, ACCOUNT_SRTP_ENABLED);
+		}
+
+		if(g_strcasecmp(srtp_enabled,"true") == 0) {
+		    conf->_conf_srtp_enabled = TRUE;
+		    break;
+		}
+
+		
+	    }
+
+	}
+
+	if(conf->_conf_srtp_enabled)
+	{
+	    participant = (gchar**)dbus_get_participant_list(conf->_confID);
+	    for (pl = participant; *participant; participant++)
+	    {	    
+		call_id = (gchar*)(*participant);
+		call = calllist_get (tab, call_id);
+		
+		if(call != NULL) {
+		    
+		    if(call->_srtp_state == 0)
+		    {
+			conf->_conference_secured = FALSE;
+			break;
+		    }
+		}
+	    }
+	}
+    }
+
+    if(conf->_conf_srtp_enabled)
+    {
+	if(conf->_conference_secured)
+	{
+	    pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_confirmed.svg", NULL);
+	}
+	else
+	{
+	    pixbuf_security = gdk_pixbuf_new_from_file(ICONS_DIR "/lock_off.svg", NULL);
+	}
+    }
+
+    DEBUG("add conference to tree store");
+    
+    gtk_tree_store_set(tab->store, &iter,
+            0, pixbuf, // Icon
+            1, description, // Description
+	    2, pixbuf_security,
+	    3, conf, // Pointer
+            -1);
+
+    DEBUG("add conference to tree store");
+
+    
+    if (pixbuf != NULL)
+        g_object_unref(G_OBJECT(pixbuf));
+
+
+    participant = (gchar**)dbus_get_participant_list(conf->_confID);
+    if(participant)
+    {
+	for (pl = participant; *participant; participant++)
+	{
+	    
+	    
+	    call_id = (gchar*)(*participant);
+	    call = calllist_get (tab, call_id);
+	    // create_new_call_from_details (conf_id, conference_details, &c);
+
+	    calltree_remove_call(tab, call, NULL);
+	    calltree_add_call (tab, call, &iter);
+	}
+    }
+
+    gtk_tree_view_set_model(GTK_TREE_VIEW(tab->view), GTK_TREE_MODEL(tab->store));
+
+    path = gtk_tree_model_get_path(model, &iter);
+
+    gtk_tree_view_expand_row(GTK_TREE_VIEW(tab->view), path, FALSE);
+
+    toolbar_update_buttons();
+
+}
+
+
+void calltree_update_conference (calltab_t* tab, const gchar* confID)
+{
+
+    DEBUG("calltree_update_conference");
+    
+
+}
+
+
+void calltree_remove_conference (calltab_t* tab, const conference_obj_t* conf, GtkTreeIter *parent)
+{
+
+    DEBUG("calltree_remove_conference %s\n", conf->_confID);
+
+    GtkTreeIter iter_parent;
+    GtkTreeIter iter_child;
+    GValue confval;
+    GValue callval;
+    conference_obj_t * tempconf;
+    callable_obj_t * call;
+    GtkTreeStore* store = tab->store;
+
+    int nbChild = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), parent);
+
+    int nbParticipant;
+    
+    int i, j;
+    for( i = 0; i < nbChild; i++)
+    {
+	
+        if(gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter_parent, parent, i))
+        {
+	    
+	    if (gtk_tree_model_iter_has_child(GTK_TREE_MODEL(store), &iter_parent))
+	    {
+		
+		calltree_remove_conference (tab, conf, &iter_parent);
+	    
+		confval.g_type = 0;
+		gtk_tree_model_get_value (GTK_TREE_MODEL(store), &iter_parent, COLUMN_ACCOUNT_PTR, &confval);
+
+		tempconf = (conference_obj_t*) g_value_get_pointer(&confval);
+		g_value_unset(&confval);
+
+		if(tempconf == conf)
+		{
+		    nbParticipant = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), &iter_parent);
+		    DEBUG("nbParticipant: %i\n", nbParticipant);
+		    for( j = 0; j < nbParticipant; j++)
+		    {
+			call = NULL;
+			if(gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter_child, &iter_parent, j))
+			{
+			    
+			    callval.g_type = 0;
+			    gtk_tree_model_get_value (GTK_TREE_MODEL(store), &iter_child, COLUMN_ACCOUNT_PTR, &callval);
+			    
+			    call = (callable_obj_t*)g_value_get_pointer(&callval);
+			    g_value_unset(&callval);
+			    
+			    if(call)
+			    {
+				calltree_add_call (tab, call, NULL);
+			    }
+			}
+			
+		    }
+
+		    gtk_tree_store_remove(store, &iter_parent);
+		}
+	    }
+        }
+    }
+
+    // callable_obj_t * selectedCall = calltab_get_selected_call(tab);
+    // if(selectedCall == c)
+    // calltab_select_call(tab, NULL);
+
+    toolbar_update_buttons();
+    
+}
+
+
 void calltree_display (calltab_t *tab) {
 
 
@@ -813,3 +1197,297 @@ void calltree_display (calltab_t *tab) {
     g_signal_emit_by_name(sel, "changed");
     toolbar_update_buttons();
 }
+
+
+
+
+static void drag_begin_cb(GtkWidget *widget, GdkDragContext *dc, gpointer data)
+{
+
+    GtkTargetList* target_list;
+
+    // g_print("drag_begin_cb %s\n", dragged_path);
+    if((target_list = gtk_drag_source_get_target_list(widget)) != NULL);
+        
+    
+}
+
+static void drag_end_cb(GtkWidget * widget, GdkDragContext * context, gpointer data)
+{
+    DEBUG("drag_end_cb\n");
+    DEBUG("    selected_path %s, selected_call_id %s, selected_path_depth %i\n", selected_path, selected_call_id, selected_path_depth);
+    DEBUG("    dragged path %s, dragged_call_id %s, dragged_path_depth %i\n", selected_path, selected_call_id, dragged_path_depth);
+
+    GtkTreeModel* model = (GtkTreeModel*)current_calls->store;
+    GtkTreePath *path = gtk_tree_path_new_from_string(dragged_path);
+    GtkTreePath *dpath = gtk_tree_path_new_from_string(dragged_path);
+    GtkTreePath *spath = gtk_tree_path_new_from_string(selected_path);
+
+    GtkTreeIter iter;
+    GtkTreeIter iter_parent;
+    GtkTreeIter iter_children;
+    GtkTreeIter parent_conference;
+
+    GValue val;
+
+    conference_obj_t* conf;
+
+
+    if(selected_path_depth == 1)
+    {
+        if(dragged_path_depth == 1)
+        {
+	    
+	    if (selected_type == A_CALL && dragged_type == A_CALL) 
+	    {
+ 
+		if(gtk_tree_path_compare (dpath, spath) == 0)
+		{
+		    // draged a call on itself
+		}
+		else
+		{
+		    // dragged a single call on a single call
+		    if(selected_call != NULL && dragged_call != NULL)
+			sflphone_join_participant(selected_call->_callID, dragged_call->_callID);
+		}
+	    }
+	    else if(selected_type == A_CALL && dragged_type == A_CONFERENCE)
+	    {
+		// dragged a single call on a conference
+		sflphone_add_participant(selected_call_id, dragged_call_id);
+	    }
+	    else if(selected_type == A_CONFERENCE && dragged_type == A_CALL)
+	    {
+		// dragged a conference on a single call (make no sence)
+		calltree_remove_conference(current_calls, selected_conf, NULL);
+		calltree_add_conference(current_calls, selected_conf);
+		
+		
+	    }
+	    else if(selected_type == A_CONFERENCE && dragged_type == A_CONFERENCE)
+	    {
+		// dragged a conference on a conference
+		if(gtk_tree_path_compare (dpath, spath) == 0) 
+		{
+		    DEBUG("Joined the same conference!\n");
+		    gtk_tree_view_expand_row(GTK_TREE_VIEW(current_calls->view), path, FALSE);
+		}
+		else
+		{
+      		    DEBUG("Joined two conference %s, %s!\n", dragged_path, selected_path);
+		    sflphone_join_conference(selected_conf->_confID, dragged_conf->_confID);
+		}
+	    }
+
+	    // TODO: dragged a single call on a NULL element (should do nothing)
+	    // TODO: dragged a conference on a NULL element (should do nothing)
+	
+        }
+	else // dragged_path_depth == 2
+	{
+	    if (selected_type == A_CALL && dragged_type == A_CALL)
+	    {
+		// TODO: dragged a call on a conference call
+		calltree_remove_call(current_calls, selected_call, NULL);
+		calltree_add_call(current_calls, selected_call, NULL);
+	    }
+	    else if(selected_type == A_CONFERENCE && dragged_type == A_CALL)
+	    {
+		// TODO: dragged a conference on a conference call
+		calltree_remove_conference(current_calls, selected_conf, NULL);
+		calltree_add_conference(current_calls, selected_conf);
+	    }
+ 
+	    // TODO: dragged a single call on a NULL element 
+	    // TODO: dragged a conference on a NULL element
+	}
+    }
+    else // selected_path_depth == 2
+    {
+	
+	if(dragged_path_depth == 1)
+	{
+	    
+	    if(selected_type == A_CALL && dragged_type == A_CALL)
+	    {
+
+		// dragged a conference call on a call
+		sflphone_detach_participant(selected_call_id);
+
+		if(selected_call != NULL && dragged_call != NULL)
+		    sflphone_join_participant(selected_call->_callID, dragged_call->_callID);
+    
+	    }
+	    else if(selected_type == A_CALL && dragged_type == A_CONFERENCE)
+	    {
+	        // dragged a conference call on a conference
+		sflphone_detach_participant(selected_call_id);
+
+		if(selected_call != NULL && dragged_conf != NULL)
+		{
+		    DEBUG("Adding a participant, since dragged call on a conference");
+	  
+		    sflphone_add_participant(selected_call_id, dragged_call_id);
+		}
+	    }
+	    else
+	    {
+		// dragged a conference call on a NULL element
+		sflphone_detach_participant(selected_call_id);
+	    }
+
+	}
+	else // dragged_path_depth == 2
+	{
+	    // dragged a conference call on another conference call (same conference)
+	    // TODO: dragged a conference call on another conference call (different conference)
+	    
+	    gtk_tree_path_up(path);
+
+	    gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &parent_conference, path);
+
+	    gtk_tree_path_up(dpath);
+	    gtk_tree_path_up(spath);
+
+	    if(gtk_tree_path_compare (dpath, spath) == 0)
+	    {
+		
+		DEBUG("Dragged a call in the same conference");
+		calltree_remove_call (current_calls, selected_call, NULL);
+		calltree_add_call (current_calls, selected_call, &parent_conference);
+	    }
+	    else
+	    {
+		DEBUG("Dragged a conference call onto another conference call %s, %s", gtk_tree_path_to_string(dpath), gtk_tree_path_to_string(spath));
+
+		conf = NULL;
+
+		val.g_type = 0;
+		if(gtk_tree_model_get_iter (model, &iter, dpath))
+		{
+		    DEBUG("we got an iter!");
+		    gtk_tree_model_get_value (model, &iter, COLUMN_ACCOUNT_PTR, &val);
+
+		    conf = (conference_obj_t*)g_value_get_pointer(&val);
+		}
+		g_value_unset(&val);
+
+		sflphone_detach_participant(selected_call_id);
+
+		if(conf)
+		{
+		    DEBUG("we got a conf!");
+		    sflphone_add_participant(selected_call_id, conf->_confID);
+		}
+		else
+		{
+		    DEBUG("didn't find a conf!");
+		}
+	    }
+
+
+	    // TODO: dragged a conference call on another conference call (different conference)
+	    // TODO: dragged a conference call on a NULL element (same conference)
+	    // TODO: dragged a conference call on a NULL element (different conference)
+	}
+
+    }	
+    
+}
+
+
+void drag_data_received_cb(GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *selection_data, guint info, guint t, gpointer data)
+{
+
+    // g_print("drag_data_received_cb\n");
+    GtkTreeView *tree_view = GTK_TREE_VIEW(widget);
+    GtkTreePath *drop_path;
+    GtkTreeViewDropPosition position;
+    GValue val;
+
+    GtkTreeModel *model = (GtkTreeModel*)active_calltree->store;
+    GtkTreeModel* tree_model = gtk_tree_view_get_model(tree_view);
+
+    GtkTreeIter iter;
+    gchar value;
+
+
+    val.g_type = 0;
+    gtk_tree_view_get_drag_dest_row(tree_view, &drop_path, &position);
+
+    if(drop_path)
+    {
+
+        gtk_tree_model_get_iter(tree_model, &iter, drop_path);
+        gtk_tree_model_get_value(tree_model, &iter, COLUMN_ACCOUNT_PTR, &val);
+
+
+	if(gtk_tree_model_iter_has_child(tree_model, &iter))
+	{
+	    DEBUG("DRAGGING ON A CONFERENCE");
+	    dragged_type = A_CONFERENCE;
+	}
+	else
+	{
+	    DEBUG("DRAGGING ON A CALL");
+	    dragged_type = A_CALL;
+	}
+
+        switch (position) 
+        {
+            case GTK_TREE_VIEW_DROP_AFTER:
+                dragged_path = gtk_tree_path_to_string(drop_path);
+		dragged_path_depth = gtk_tree_path_get_depth(drop_path);
+		dragged_call_id = "NULL";
+		dragged_call = NULL;
+		dragged_conf = NULL;
+                g_print("    AFTER dragged_path %s, dragged_call_id %s, dragged_path_depth %i\n", dragged_path, dragged_call_id, dragged_path_depth);
+                break;
+
+            case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
+                dragged_path = gtk_tree_path_to_string(drop_path);
+		dragged_path_depth = gtk_tree_path_get_depth(drop_path);
+		if (dragged_type == A_CALL)
+		{
+		    dragged_call_id = ((callable_obj_t*)g_value_get_pointer(&val))->_callID;
+		    dragged_call = (callable_obj_t*)g_value_get_pointer(&val);
+		}
+		else
+		{
+		    dragged_call_id = ((conference_obj_t*)g_value_get_pointer(&val))->_confID;
+		    dragged_conf = (conference_obj_t*)g_value_get_pointer(&val);
+		}
+                g_print("    INTO_OR_AFTER dragged_path %s, dragged_call_id %s, dragged_path_depth %i\n", dragged_path, dragged_call_id, dragged_path_depth);
+                break;
+
+            case GTK_TREE_VIEW_DROP_BEFORE:
+                dragged_path = gtk_tree_path_to_string(drop_path);
+		dragged_path_depth = gtk_tree_path_get_depth(drop_path);
+		dragged_call_id = "NULL";
+		dragged_call = NULL;
+		dragged_conf = NULL;
+                g_print("    BEFORE dragged_path %s, dragged_call_id %s, dragged_path_depth %i\n", dragged_path, dragged_call_id, dragged_path_depth);
+                break;
+
+            case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
+                dragged_path = gtk_tree_path_to_string(drop_path);
+		dragged_path_depth = gtk_tree_path_get_depth(drop_path);
+		if (dragged_type == A_CALL)
+		{
+		    dragged_call_id = ((callable_obj_t*)g_value_get_pointer(&val))->_callID;
+		    dragged_call = (callable_obj_t*)g_value_get_pointer(&val);
+		}
+		else
+		{
+		    dragged_call_id = ((conference_obj_t*)g_value_get_pointer(&val))->_confID;
+		    dragged_conf = (conference_obj_t*)g_value_get_pointer(&val);
+		}
+                g_print("    INTO_OR_BEFORE dragged_path %s, dragged_call_id %s, dragged_path_depth %i\n", dragged_path, dragged_call_id, dragged_path_depth);
+                break;
+
+            default:
+                return;
+        }
+    }
+}
diff --git a/sflphone-client-gnome/src/contacts/calltree.h b/sflphone-client-gnome/src/contacts/calltree.h
index ca8fa76cf08cfc2bae30c1385a91ca861a0fb718..a01565bc4b29f245bf94c745d5780f9bfd4647ce 100644
--- a/sflphone-client-gnome/src/contacts/calltree.h
+++ b/sflphone-client-gnome/src/contacts/calltree.h
@@ -1,6 +1,7 @@
 /*
  *  Copyright (C) 2007 Savoir-Faire Linux inc.
  *  Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com>
+ *  Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@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
@@ -33,6 +34,12 @@
   * @brief The GtkTreeView that list calls in the main window.
   */
 
+enum
+{
+    A_CALL,
+    A_CONFERENCE
+};
+
 /**
  * Create a new widget calltree
  * @return GtkWidget* A new widget
@@ -45,21 +52,33 @@ calltree_create(calltab_t* tab, gboolean searchbar_type);
  * @param c The call to add
  */
 void
-calltree_add_call (calltab_t* ct, callable_obj_t * c);
+calltree_add_call (calltab_t* ct, callable_obj_t * c, GtkTreeIter *parent);
 
 /*
  * Update the call tree if the call state changes
  * @param c The call to update
  */
 void
-calltree_update_call (calltab_t* ct, callable_obj_t * c);
+calltree_update_call (calltab_t* ct, callable_obj_t * c, GtkTreeIter *parent);
 
 /**
  * Remove a call from the call tree
  * @param c The call to remove
  */
 void
-calltree_remove_call (calltab_t* ct, callable_obj_t * c);
+calltree_remove_call (calltab_t* ct, callable_obj_t * c, GtkTreeIter *parent);
+
+void 
+calltree_add_history_entry (callable_obj_t * c);
+
+void
+calltree_add_conference (calltab_t* tab, conference_obj_t* conf);
+
+void
+calltree_update_conference (calltab_t* tab, const gchar* confID);
+
+void
+calltree_remove_conference (calltab_t* tab, const conference_obj_t* conf, GtkTreeIter *parent);
 
 void
 calltree_reset (calltab_t* tab);
diff --git a/sflphone-client-gnome/src/contacts/conferencelist.c b/sflphone-client-gnome/src/contacts/conferencelist.c
new file mode 100644
index 0000000000000000000000000000000000000000..9dee60e481f979646486623414c20a86f5122d42
--- /dev/null
+++ b/sflphone-client-gnome/src/contacts/conferencelist.c
@@ -0,0 +1,112 @@
+/*
+ *  Copyright (C) 2007 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.
+ */
+
+#include <conferencelist.h>
+
+
+gchar* 
+generate_conf_id (void)
+{
+    gchar *conf_id;
+
+    conf_id = g_new0(gchar, 30);
+    g_sprintf(conf_id, "%d", rand());
+    return conf_id;
+}
+
+
+void
+conferencelist_init()
+{
+    conferenceQueue = g_queue_new ();
+}
+
+
+void
+conferencelist_clean()
+{
+    g_queue_free (conferenceQueue);
+}
+
+
+void
+conferencelist_reset()
+{
+    g_queue_free (conferenceQueue);
+    conferenceQueue = g_queue_new();
+}
+
+
+void
+conferencelist_add(const conference_obj_t* conf)
+{
+    gchar* c = (gchar*)conferencelist_get(conf->_confID);
+    if(!c)
+    {
+        g_queue_push_tail (conferenceQueue, (gpointer)conf);
+    }
+}
+
+
+void
+conferencelist_remove (const gchar* conf)
+{
+    gchar* c = (gchar*)conferencelist_get(conf);
+    if (c)
+    {
+        g_queue_remove(conferenceQueue, c);
+    }
+}
+
+conference_obj_t* 
+conferencelist_get (const gchar* conf_id)
+{
+
+    GList* c = g_queue_find_custom(conferenceQueue, conf_id, is_confID_confstruct);
+    if (c)
+    {
+	return (conference_obj_t*)c->data;
+    }
+    else
+    {
+	return NULL;
+    }
+}
+
+
+conference_obj_t* 
+conferencelist_get_nth ( guint n )
+{
+    GList* c = g_queue_peek_nth(conferenceQueue, n);
+    if (c)
+    {
+	return (conference_obj_t*)c->data;
+    }
+    else
+    {
+	return NULL;
+    }
+}
+
+
+guint
+conferencelist_get_size ()
+{
+    return g_queue_get_length (conferenceQueue);
+}
diff --git a/sflphone-client-gnome/src/contacts/conferencelist.h b/sflphone-client-gnome/src/contacts/conferencelist.h
new file mode 100644
index 0000000000000000000000000000000000000000..4836914f7a36008731935531366542eb2c1ce6f2
--- /dev/null
+++ b/sflphone-client-gnome/src/contacts/conferencelist.h
@@ -0,0 +1,75 @@
+/*
+ *  Copyright (C) 2009 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.
+ */
+
+#ifndef __CONFERENCELIST_H__
+#define __CONFERENCELIST_H__
+
+
+#include <conference_obj.h>
+#include <gtk/gtk.h>
+
+/** @file conferencelist.h
+  * @brief A list to store conferences.
+  */
+
+GQueue* conferenceQueue;
+
+/** This function initialize a conference list. */
+void
+conferencelist_init ();
+
+/** This function empty and free the conference list. */
+void
+conferencelist_clean ();
+
+/** This function empty, free the conference list and allocate a new one. */
+void
+conferencelist_reset ();
+
+/** This function append a conference to the list.
+  * @param conf The conference you want to add
+  * */
+void
+conferencelist_add (const conference_obj_t* conf);
+
+/** This function remove a conference from list.
+  * @param callID The callID of the conference you want to remove
+  */
+void
+conferencelist_remove (const gchar* conf);
+
+/** Return the number of calls in the list
+  * @return The number of calls in the list */
+guint
+conferencelist_get_size ();
+
+/** Return the call at the nth position in the list
+  * @param n The position of the call you want
+  * @return A call or NULL */
+conference_obj_t*
+conferencelist_get_nth (guint n );
+
+/** Return the call corresponding to the callID
+  * @param n The callID of the call you want
+  * @return A call or NULL */
+conference_obj_t*
+conferencelist_get (const gchar* conf);
+
+
+#endif
diff --git a/sflphone-client-gnome/src/dbus/callmanager-introspec.xml b/sflphone-client-gnome/src/dbus/callmanager-introspec.xml
index e8f6e1da08d10e37238fcd862727b1aa53ea5a35..ba4e42577b4b546a1cb001049cbe63622e491dda 100644
--- a/sflphone-client-gnome/src/dbus/callmanager-introspec.xml
+++ b/sflphone-client-gnome/src/dbus/callmanager-introspec.xml
@@ -19,6 +19,10 @@
     <method name="hangUp">
       <arg type="s" name="callID" direction="in"/>
     </method>
+
+    <method name="hangUpConference">
+      <arg type="s" name="confID" direction="in"/>
+    </method>
     
     <method name="hold">
       <arg type="s" name="callID" direction="in"/>
@@ -52,6 +56,39 @@
       <arg type="d" name="value" direction="out"/>
     </method>
 
+    <method name="joinParticipant">
+      <arg type="s" name="sel_callID" direction="in"/>
+      <arg type="s" name="drag_callID" direction="in"/>
+    </method>
+
+    <method name="addParticipant">
+      <arg type="s" name="callID" direction="in"/>
+      <arg type="s" name="confID" direction="in"/>
+    </method>
+
+    <method name="addMainParticipant">
+      <arg type="s" name="confID" direction="in"/>
+    </method>
+
+    <method name="detachParticipant">
+      <arg type="s" name="callID" direction="in"/>
+    </method>
+
+    <method name="joinConference">
+      <arg type="s" name="sel_confID" direction="in"/>
+      <arg type="s" name="drag_confID" direction="in"/>
+    </method>
+
+    <method name="getConferenceDetails">
+      <arg type="s" name="callID" direction="in"/>
+      <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/>
+      <arg type="a{ss}" name="infos" direction="out"/>
+    </method>
+    
+    <method name="getConferenceList">
+        <arg type="as" name="list" direction="out"/>
+    </method>
+
     <method name="setRecording">
       <arg type="s" name="callID" direction="in"/>
     </method>
@@ -101,18 +138,43 @@
       <arg type="s" name="state"  direction="out"/>
     </signal>
 
+    <signal name="conferenceChanged">
+      <arg type="s" name="confID"  direction="out"/>
+      <arg type="s" name="state"  direction="out"/>
+    </signal>
+
+    <method name="getParticipantList">
+      <arg type="s" name="confID" direction="in"/>
+      <arg type="as" name="list" direction="out"/>
+    </method>
+
+    <signal name="conferenceCreated">
+      <arg type="s" name="confID"  direction="out"/>
+    </signal>
+
+    <signal name="conferenceRemoved">
+      <arg type="s" name="confID"  direction="out"/>
+    </signal>
+
+    <method name="holdConference">
+      <arg type="s" name="confID" direction="in"/>
+    </method>
+
+    <method name="unholdConference">
+      <arg type="s" name="confID" direction="in"/>
+    </method>
+
     <signal name="sipCallStateChanged">
       <arg type="s" name="callID"  direction="out"/>
       <arg type="s" name="state"  direction="out"/>
       <arg type="i" name="code"  direction="out"/>            
     </signal>   
-       
+
     <signal name="voiceMailNotify">
       <arg type="s" name="accountID"  direction="out"/>
       <arg type="i" name="count"  direction="out"/>
     </signal>
     
-    
     <signal name="volumeChanged">
       <arg type="s" name="device"  direction="out"/>
       <arg type="d" name="value"  direction="out"/>
@@ -169,7 +231,7 @@
      <signal name="confirmGoClear">
       <arg type="s" name="callID"  direction="out" />
     </signal>
- 
+
 <!--
     <signal name="error">
       <annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="MapStringString"/>
diff --git a/sflphone-client-gnome/src/dbus/dbus.c b/sflphone-client-gnome/src/dbus/dbus.c
index d02aed7446c241455899a6b7e6847f56c3825063..8a00188806bbf91413d08960d5a5bdb610a025a7 100644
--- a/sflphone-client-gnome/src/dbus/dbus.c
+++ b/sflphone-client-gnome/src/dbus/dbus.c
@@ -141,11 +141,11 @@ call_state_cb (DBusGProxy *proxy UNUSED,
                 // peer hung up, the conversation was established, so _stop has been initialized with the current time value
                 DEBUG("call state current");
                 set_timestamp (&c->_time_stop);
-                calltree_update_call( history, c );
+                calltree_update_call( history, c, NULL);
             }
             stop_notification();
             sflphone_hung_up (c);
-            calltree_update_call( history, c );
+            calltree_update_call( history, c, NULL );
             status_bar_display_account();
         }
         else if ( strcmp(state, "UNHOLD_CURRENT") == 0 )
@@ -211,7 +211,7 @@ call_state_cb (DBusGProxy *proxy UNUSED,
 
             calllist_add (current_calls, new_call);
             calllist_add (history, new_call);
-            calltree_add_call (current_calls, new_call);
+            calltree_add_call (current_calls, new_call, NULL);
             update_menus ();
             calltree_display (current_calls);
 
@@ -220,6 +220,68 @@ call_state_cb (DBusGProxy *proxy UNUSED,
     }
 }
 
+static void
+conference_changed_cb (DBusGProxy *proxy UNUSED,
+	const gchar* confID,
+        const gchar* state,
+        void * foo  UNUSED )
+{
+    DEBUG ("-------------------- Conference changed ---------------------\n");
+    // sflphone_display_transfer_status("Transfer successfull");
+    conference_obj_t* changed_conf = conferencelist_get(confID);
+
+    DEBUG("    %s\n", state);
+
+    if(changed_conf)
+    {
+	calltree_remove_conference (current_calls, changed_conf, NULL);
+
+	if ( strcmp(state, "ACTIVE_ATACHED") == 0 )
+	{
+	    changed_conf->_state = CONFERENCE_STATE_ACTIVE_ATACHED;
+	}
+	else if ( strcmp(state, "ACTIVE_DETACHED") == 0 )
+	{
+	    changed_conf->_state = CONFERENCE_STATE_ACTIVE_DETACHED;
+	}
+	else if ( strcmp(state, "HOLD") == 0 )
+	{
+	    changed_conf->_state = CONFERENCE_STATE_HOLD;
+	}
+
+	calltree_add_conference (current_calls, changed_conf);
+    }
+}
+
+
+static void
+conference_created_cb (DBusGProxy *proxy UNUSED,
+	const gchar* confID,
+        void * foo  UNUSED )
+{
+    DEBUG ("Conference added %s\n", confID);
+
+    conference_obj_t* new_conf;
+
+    create_new_conference(CONFERENCE_STATE_ACTIVE_ATACHED, confID, &new_conf);
+    new_conf->_confID = g_strdup(confID);
+    conferencelist_add(new_conf);
+    calltree_add_conference (current_calls, new_conf);
+}
+
+
+static void
+conference_removed_cb (DBusGProxy *proxy UNUSED,
+	const gchar* confID,
+        void * foo  UNUSED )
+{
+    DEBUG ("Conference removed %s\n", confID);
+
+    conference_obj_t * c = conferencelist_get(confID);
+    calltree_remove_conference (current_calls, c, NULL);
+    conferencelist_remove(c->_confID); 
+}
+
 
     static void
 accounts_changed_cb (DBusGProxy *proxy UNUSED,
@@ -468,6 +530,25 @@ dbus_connect ()
     dbus_g_proxy_connect_signal (callManagerProxy,
             "transferFailed", G_CALLBACK(transfer_failed_cb), NULL, NULL);
 
+    /* Conference related callback */
+
+    dbus_g_object_register_marshaller(g_cclosure_user_marshal_VOID__STRING,
+            G_TYPE_NONE, G_TYPE_STRING, G_TYPE_INVALID);
+    dbus_g_proxy_add_signal (callManagerProxy,
+            "conferenceChanged", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+    dbus_g_proxy_connect_signal (callManagerProxy,
+            "conferenceChanged", G_CALLBACK(conference_changed_cb), NULL, NULL);
+
+    dbus_g_proxy_add_signal (callManagerProxy,
+            "conferenceCreated", G_TYPE_STRING, G_TYPE_INVALID);
+    dbus_g_proxy_connect_signal (callManagerProxy,
+            "conferenceCreated", G_CALLBACK(conference_created_cb), NULL, NULL);
+
+    dbus_g_proxy_add_signal (callManagerProxy,
+            "conferenceRemoved", G_TYPE_STRING, G_TYPE_INVALID);
+    dbus_g_proxy_connect_signal (callManagerProxy,
+            "conferenceRemoved", G_CALLBACK(conference_removed_cb), NULL, NULL);
+
     /* Security related callbacks */
     
     /* Register a marshaller for STRING,STRING,BOOL */
@@ -504,6 +585,7 @@ dbus_connect ()
     dbus_g_object_register_marshaller(g_cclosure_user_marshal_VOID__STRING_STRING_INT,
             G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INVALID);
 
+
     dbus_g_proxy_add_signal (callManagerProxy,
             "sipCallStateChanged", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INVALID);
     dbus_g_proxy_connect_signal (callManagerProxy,
@@ -562,6 +644,8 @@ dbus_clean ()
     void
 dbus_hold (const callable_obj_t * c)
 {
+    DEBUG("dbus_hold %s\n", c->_callID);
+
     GError *error = NULL;
     org_sflphone_SFLphone_CallManager_hold ( callManagerProxy, c->_callID, &error);
     if (error)
@@ -575,6 +659,8 @@ dbus_hold (const callable_obj_t * c)
     void
 dbus_unhold (const callable_obj_t * c)
 {
+    DEBUG("dbus_unhold %s\n", c->_callID);
+
     GError *error = NULL;
     org_sflphone_SFLphone_CallManager_unhold ( callManagerProxy, c->_callID, &error);
     if (error)
@@ -585,9 +671,41 @@ dbus_unhold (const callable_obj_t * c)
     }
 }
 
+    void
+dbus_hold_conference (const conference_obj_t * c)
+{
+    DEBUG("dbus_hold_conference %s\n", c->_confID);
+
+    GError *error = NULL;
+    org_sflphone_SFLphone_CallManager_hold_conference ( callManagerProxy, c->_confID, &error);
+    if (error)
+    {
+        ERROR ("Failed to call hold() on CallManager: %s",
+                error->message);
+        g_error_free (error);
+    }
+}
+
+    void
+dbus_unhold_conference (const conference_obj_t * c)
+{
+    DEBUG("dbus_unhold_conference %s\n", c->_confID);
+
+    GError *error = NULL;
+    org_sflphone_SFLphone_CallManager_unhold_conference ( callManagerProxy, c->_confID, &error);
+    if (error)
+    {
+        ERROR ("Failed to call unhold() on CallManager: %s",
+                error->message);
+        g_error_free (error);
+    }
+}
+
     void
 dbus_hang_up (const callable_obj_t * c)
 {
+    DEBUG("dbus_hang_up %s\n", c->_callID);
+    
     GError *error = NULL;
     org_sflphone_SFLphone_CallManager_hang_up ( callManagerProxy, c->_callID, &error);
     if (error)
@@ -598,6 +716,22 @@ dbus_hang_up (const callable_obj_t * c)
     }
 }
 
+
+    void
+dbus_hang_up_conference (const conference_obj_t * c)
+{
+    DEBUG("dbus_hang_up_conference %s\n", c->_confID);
+    
+    GError *error = NULL;
+    org_sflphone_SFLphone_CallManager_hang_up_conference ( callManagerProxy, c->_confID, &error);
+    if (error)
+    {
+        ERROR ("Failed to call hang_up() on CallManager: %s",
+                error->message);
+        g_error_free (error);
+    }
+}
+
     void
 dbus_transfert (const callable_obj_t * c)
 {
@@ -617,6 +751,9 @@ dbus_accept (const callable_obj_t * c)
 #if GTK_CHECK_VERSION(2,10,0)
     status_tray_icon_blink( FALSE );
 #endif
+
+    DEBUG("dbus_accept %s\n", c->_callID);
+
     GError *error = NULL;
     org_sflphone_SFLphone_CallManager_accept ( callManagerProxy, c->_callID, &error);
     if (error)
@@ -633,6 +770,9 @@ dbus_refuse (const callable_obj_t * c)
 #if GTK_CHECK_VERSION(2,10,0)
     status_tray_icon_blink( FALSE );
 #endif
+
+    DEBUG("dbus_refuse %s\n", c->_callID);
+
     GError *error = NULL;
     org_sflphone_SFLphone_CallManager_refuse ( callManagerProxy, c->_callID, &error);
     if (error)
@@ -647,6 +787,8 @@ dbus_refuse (const callable_obj_t * c)
     void
 dbus_place_call (const callable_obj_t * c)
 {
+    DEBUG("dbus_place_call %s\n", c->_callID);
+
     GError *error = NULL;
     org_sflphone_SFLphone_CallManager_place_call ( callManagerProxy, c->_accountID, c->_callID, c->_peer_number, &error);
     if (error)
@@ -1535,16 +1677,113 @@ dbus_set_volume_controls(  )
     }
 }
 
+void
+dbus_join_participant(const gchar* sel_callID, const gchar* drag_callID)
+{
+
+    DEBUG("dbus_join_participant %s and %s\n", sel_callID, drag_callID);
+
+    GError* error = NULL;
+    
+    org_sflphone_SFLphone_CallManager_join_participant (
+             callManagerProxy, 
+	     sel_callID, 
+	     drag_callID, 
+	     &error);
+    if(error)
+    {
+        g_error_free(error);
+    }
+    
+}
+
+void
+dbus_add_participant(const gchar* callID, const gchar* confID)
+{
+
+    DEBUG("dbus_add_participant %s and %s\n", callID, confID);
+
+    GError* error = NULL;
+    
+    org_sflphone_SFLphone_CallManager_add_participant (
+             callManagerProxy, 
+	     callID, 
+	     confID, 
+	     &error);
+    if(error)
+    {
+        g_error_free(error);
+    }
+    
+}
+
+void
+dbus_add_main_participant(const gchar* confID)
+{
+    DEBUG("dbus_add_participant %s\n", confID);
+
+    GError* error = NULL;
+
+    org_sflphone_SFLphone_CallManager_add_main_participant (
+             callManagerProxy, 
+	     confID, 
+	     &error);
+    if(error)
+    {
+        g_error_free(error);
+    }
+}
+
 
     void
-dbus_set_record(const callable_obj_t * c)
+dbus_detach_participant(const gchar* callID)
 {
-    DEBUG("calling dbus_set_record on CallManager");
-    DEBUG("CallID : %s", c->_callID);
+
+    DEBUG("dbus_detach_participant %s\n", callID);
+
+    GError* error = NULL;
+    org_sflphone_SFLphone_CallManager_detach_participant(
+            callManagerProxy,
+            callID,
+            &error);
+    if(error)
+    {
+        g_error_free(error);
+    }
+    
+}
+
+
+dbus_join_conference(const gchar* sel_confID, const gchar* drag_confID)
+{
+
+    DEBUG("dbus_join_conference %s and %s\n", sel_confID, drag_confID);
+
+    GError* error = NULL;
+    
+    org_sflphone_SFLphone_CallManager_join_conference (
+             callManagerProxy, 
+	     sel_confID, 
+	     drag_confID, 
+	     &error);
+    if(error)
+    {
+        g_error_free(error);
+    }
+    
+}
+
+
+
+    void
+dbus_set_record(const gchar* id)
+{
+    DEBUG("dbus_set_record %s\n", id);
+
     GError* error = NULL;
     org_sflphone_SFLphone_CallManager_set_recording (
             callManagerProxy,
-            c->_callID,
+            id,
             &error);
     if(error)
     {
@@ -1552,10 +1791,11 @@ dbus_set_record(const callable_obj_t * c)
     }
 }
 
+
     gboolean
 dbus_get_is_recording(const callable_obj_t * c)
 {
-    DEBUG("calling dbus_get_is_recording on CallManager");
+    DEBUG("dbus_get_is_recording %s\n", c->_callID);
     GError* error = NULL;
     gboolean isRecording;
     org_sflphone_SFLphone_CallManager_get_is_recording (
@@ -2037,6 +2277,50 @@ gchar** dbus_get_call_list (void)
     return list;
 }
 
+gchar** dbus_get_conference_list (void)
+{
+    GError *error = NULL;
+    gchar **list = NULL;
+
+    org_sflphone_SFLphone_CallManager_get_conference_list (callManagerProxy, &list, &error);
+    if (error){
+        ERROR ("Error calling org_sflphone_SFLphone_CallManager_get_conference_list");
+        g_error_free (error);
+    }
+
+    return list;
+}
+
+
+gchar** dbus_get_participant_list (const char * confID)
+{
+    GError *error = NULL;
+    gchar **list = NULL;
+
+    org_sflphone_SFLphone_CallManager_get_participant_list (callManagerProxy, confID, &list, &error);
+    if (error){
+        ERROR ("Error calling org_sflphone_SFLphone_CallManager_get_participant_list");
+        g_error_free (error);
+    }
+
+    return list;
+}
+
+
+GHashTable* dbus_get_conference_details (const gchar *confID)
+{
+    GError *error = NULL;
+    GHashTable *details = NULL;
+
+    org_sflphone_SFLphone_CallManager_get_conference_details (callManagerProxy, confID, &details, &error);
+    if (error){
+        ERROR ("Error calling org_sflphone_SFLphone_CallManager_get_conference_details");
+        g_error_free (error);
+    }
+
+    return details;
+}
+
 void dbus_set_accounts_order (const gchar* order) {
 
     GError *error = NULL;
diff --git a/sflphone-client-gnome/src/dbus/dbus.h b/sflphone-client-gnome/src/dbus/dbus.h
index 58e977d6f1cffc0b70c8eb7450006f8804bffb41..123322b2816652ce28162c92c78fdf04031fab46 100644
--- a/sflphone-client-gnome/src/dbus/dbus.h
+++ b/sflphone-client-gnome/src/dbus/dbus.h
@@ -27,6 +27,8 @@
 
 #include <accountlist.h>
 #include <calllist.h>
+#include <conferencelist.h>
+#include <conference_obj.h>
 #include <sflnotify.h>
 
 /** @file dbus.h
@@ -518,7 +520,9 @@ void dbus_set_stun_server( gchar* server);
 gint dbus_stun_is_enabled (void);
 void dbus_enable_stun (void);
 
-void dbus_set_record (const callable_obj_t * c);
+void dbus_add_participant(const gchar* callID, const gchar* confID);
+
+void dbus_set_record (const gchar * id);
 
 void dbus_set_record_path (const gchar *path);
 gchar* dbus_get_record_path (void);
diff --git a/sflphone-client-gnome/src/menus.c b/sflphone-client-gnome/src/menus.c
index 0039d9dc22d1eae0c67bbc7911dd063e446ef665..cac13584d57296bf57f628ac2a7fbed4f459dfb1 100644
--- a/sflphone-client-gnome/src/menus.c
+++ b/sflphone-client-gnome/src/menus.c
@@ -254,6 +254,34 @@ call_hold  (void* foo UNUSED)
     }
 }
 
+    static void
+conference_hold  (void* foo UNUSED)
+{
+    conference_obj_t * selectedConf = calltab_get_selected_conf();
+
+    switch(selectedConf->_state)
+    {
+        case CONFERENCE_STATE_HOLD:
+            {
+                gtk_image_menu_item_set_image( GTK_IMAGE_MENU_ITEM ( holdMenu ), gtk_image_new_from_file( ICONS_DIR "/icon_unhold.svg"));
+	        selectedConf->_state = CONFERENCE_STATE_ACTIVE_ATACHED;
+                sflphone_conference_off_hold(selectedConf);
+            }
+	    break;
+	
+        case CONFERENCE_STATE_ACTIVE_ATACHED:
+	case CONFERENCE_STATE_ACTIVE_DETACHED:
+            {
+		gtk_image_menu_item_set_image( GTK_IMAGE_MENU_ITEM ( holdMenu ), gtk_image_new_from_file( ICONS_DIR "/icon_hold.svg"));
+		selectedConf->_state = CONFERENCE_STATE_HOLD;
+		sflphone_conference_on_hold(selectedConf);
+            }
+	    break;
+        default:
+	    break;
+    }
+}
+
     static void
 call_pick_up ( void * foo UNUSED)
 {
@@ -266,6 +294,12 @@ call_hang_up ( void * foo UNUSED)
     sflphone_hang_up();
 }
 
+    static void
+conference_hang_up ( void * foo UNUSED)
+{
+    sflphone_conference_hang_up();
+}
+
     static void
 call_record ( void * foo UNUSED)
 {
@@ -302,7 +336,7 @@ call_back( void * foo UNUSED)
         create_new_call (CALL, CALL_STATE_DIALING, "", "", selected_call->_peer_name, selected_call->_peer_number, &new_call);
 
         calllist_add(current_calls, new_call);
-        calltree_add_call(current_calls, new_call);
+        calltree_add_call(current_calls, new_call, NULL);
         sflphone_place_call(new_call);
         calltree_display (current_calls);
     }
@@ -469,7 +503,7 @@ edit_paste ( void * foo UNUSED)
                     {
                         selectedCall->_peer_info = g_strconcat("\"\" <", selectedCall->_peer_number, ">", NULL);	        		
                     }
-                    calltree_update_call(current_calls, selectedCall);
+                    calltree_update_call(current_calls, selectedCall, NULL);
                 }
                 break;
             case CALL_STATE_RINGING:
@@ -486,7 +520,7 @@ edit_paste ( void * foo UNUSED)
 
                     selectedCall->_peer_info = g_strconcat("\"\" <", selectedCall->_peer_number, ">", NULL);
 
-                    calltree_update_call(current_calls, selectedCall);
+                    calltree_update_call(current_calls, selectedCall, NULL);
                 }
                 break;
             case CALL_STATE_CURRENT:
@@ -502,7 +536,7 @@ edit_paste ( void * foo UNUSED)
                         gchar * temp = g_strconcat(selectedCall->_peer_number, oneNo, NULL);
                         selectedCall->_peer_info = get_peer_info (temp, selectedCall->_peer_name);
                         // g_free(temp);
-                        calltree_update_call(current_calls, selectedCall);
+                        calltree_update_call(current_calls, selectedCall, NULL);
 
                     }
                 }
@@ -521,7 +555,7 @@ edit_paste ( void * foo UNUSED)
 
         g_free(selectedCall->_peer_info);
         selectedCall->_peer_info = g_strconcat("\"\" <", selectedCall->_peer_number, ">", NULL);
-        calltree_update_call(current_calls,selectedCall);
+        calltree_update_call(current_calls, selectedCall, NULL);
     }
 
 }
@@ -706,45 +740,87 @@ show_popup_menu (GtkWidget *my_widget, GdkEventButton *event)
 {
     // TODO update the selection to make sure the call under the mouse is the call selected
 
-    gboolean pickup = FALSE, hangup = FALSE, hold = FALSE, copy = FALSE, record = FALSE;
+    // call type boolean
+    gboolean pickup = FALSE, hangup = FALSE, hold = FALSE, copy = FALSE, record = FALSE, detach = FALSE;
     gboolean accounts = FALSE;
 
-    callable_obj_t * selectedCall = calltab_get_selected_call(current_calls);
-    if (selectedCall)
+    // conference type boolean
+    gboolean hangup_conf = FALSE, hold_conf = FALSE; 
+
+    callable_obj_t * selectedCall;
+    conference_obj_t * selectedConf;
+
+    if (calltab_get_selected_type(current_calls) == A_CALL)
     {
-        copy = TRUE;
-        switch(selectedCall->_state)
-        {
-            case CALL_STATE_INCOMING:
-                pickup = TRUE;
-                hangup = TRUE;
-                break;
-            case CALL_STATE_HOLD:
-                hangup = TRUE;
-                hold   = TRUE;
-                break;
-            case CALL_STATE_RINGING:
-                hangup = TRUE;
-                break;
-            case CALL_STATE_DIALING:
-                pickup = TRUE;
-                hangup = TRUE;
-                accounts = TRUE;
-                break;
-            case CALL_STATE_RECORD:
-            case CALL_STATE_CURRENT:
-                hangup = TRUE;
-                hold   = TRUE;
-                record = TRUE;
-                break;
-            case CALL_STATE_BUSY:
-            case CALL_STATE_FAILURE:
-                hangup = TRUE;
-                break;
-            default:
-                WARN("Should not happen in show_popup_menu!");
-                break;
-        }
+	DEBUG("MENUS: SELECTED A CALL");
+        selectedCall = calltab_get_selected_call(current_calls);
+
+	if (selectedCall)
+	{
+	    copy = TRUE;
+	    switch(selectedCall->_state)
+	    {
+                case CALL_STATE_INCOMING:
+		    pickup = TRUE;
+		    hangup = TRUE;
+		    detach = TRUE;
+		    break;
+                case CALL_STATE_HOLD:
+		    hangup = TRUE;
+		    hold   = TRUE;
+		    detach = TRUE;
+		    break;
+                case CALL_STATE_RINGING:
+		    hangup = TRUE;
+		    detach = TRUE;
+		    break;
+                case CALL_STATE_DIALING:
+		    pickup = TRUE;
+		    hangup = TRUE;
+		    accounts = TRUE;
+		    break;
+                case CALL_STATE_RECORD:
+                case CALL_STATE_CURRENT:
+		    hangup = TRUE;
+		    hold   = TRUE;
+		    record = TRUE;
+		    detach = TRUE;
+		    break;
+                case CALL_STATE_BUSY:
+                case CALL_STATE_FAILURE:
+		    hangup = TRUE;
+		    break;
+                default:
+		    WARN("Should not happen in show_popup_menu for calls!");
+		    break;
+	    }
+	}
+    }
+    else
+    {
+        DEBUG("MENUS: SELECTED A CONF");	
+	selectedConf = calltab_get_selected_conf();
+
+	if (selectedConf)
+	{
+	    switch(selectedConf->_state)
+	    {
+	        case CONFERENCE_STATE_ACTIVE_ATACHED:
+		    hangup_conf = TRUE;
+		    hold_conf = TRUE;
+		    break;
+	        case CONFERENCE_STATE_ACTIVE_DETACHED:
+		    break;
+	        case CONFERENCE_STATE_HOLD:
+		    hangup_conf = TRUE;
+		    hold_conf = TRUE;
+		    break;
+	        default:
+		    WARN("Should not happen in show_popup_menu for conferences!");
+		    break;
+	    }
+	}
+
     }
 
     GtkWidget *menu;
@@ -755,94 +831,127 @@ show_popup_menu (GtkWidget *my_widget, GdkEventButton *event)
     menu = gtk_menu_new ();
     //g_signal_connect (menu, "deactivate",
     //       G_CALLBACK (gtk_widget_destroy), NULL);
-
-    if(copy)
+    if (calltab_get_selected_type(current_calls) == A_CALL)
     {
-        menu_items = gtk_image_menu_item_new_from_stock( GTK_STOCK_COPY, get_accel_group());
-        gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items);
-        g_signal_connect (G_OBJECT (menu_items), "activate",
-                G_CALLBACK (edit_copy),
-                NULL);
-        gtk_widget_show (menu_items);
-    }
-
-    menu_items = gtk_image_menu_item_new_from_stock( GTK_STOCK_PASTE, get_accel_group());
-    gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items);
-    g_signal_connect (G_OBJECT (menu_items), "activate",
-            G_CALLBACK (edit_paste),
-            NULL);
-    gtk_widget_show (menu_items);
-
-    if(pickup || hangup || hold)
-    {
-        menu_items = gtk_separator_menu_item_new ();
-        gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items);
-        gtk_widget_show (menu_items);
-    }
-
-    if(pickup)
-    {
-
-        menu_items = gtk_image_menu_item_new_with_mnemonic(_("_Pick up"));
-        image = gtk_image_new_from_file( ICONS_DIR "/icon_accept.svg");
-        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_pick_up),
-                NULL);
-        gtk_widget_show (menu_items);
-    }
-
-    if(hangup)
-    {
-        menu_items = gtk_image_menu_item_new_with_mnemonic(_("_Hang up"));
-        image = gtk_image_new_from_file( ICONS_DIR "/icon_hangup.svg");
-        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_hang_up),
-                NULL);
-        gtk_widget_show (menu_items);
-    }
+	DEBUG("BUILD CALL MENU");
+
+	if(copy)
+	{
+	    menu_items = gtk_image_menu_item_new_from_stock( GTK_STOCK_COPY, get_accel_group());
+	    gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items);
+	    g_signal_connect (G_OBJECT (menu_items), "activate",
+			      G_CALLBACK (edit_copy),
+			      NULL);
+	    gtk_widget_show (menu_items);
+	}
+
+	menu_items = gtk_image_menu_item_new_from_stock( GTK_STOCK_PASTE, get_accel_group());
+	gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items);
+	g_signal_connect (G_OBJECT (menu_items), "activate",
+			  G_CALLBACK (edit_paste),
+			  NULL);
+	gtk_widget_show (menu_items);
+	
+	if(pickup || hangup || hold)
+	{
+	    menu_items = gtk_separator_menu_item_new ();
+	    gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items);
+	    gtk_widget_show (menu_items);
+	}
+	
+	if(pickup)
+	{
+	    
+	    menu_items = gtk_image_menu_item_new_with_mnemonic(_("_Pick up"));
+	    image = gtk_image_new_from_file( ICONS_DIR "/icon_accept.svg");
+	    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_pick_up),
+			      NULL);
+	    gtk_widget_show (menu_items);
+	}
+
+	if(hangup)
+	{
+	    menu_items = gtk_image_menu_item_new_with_mnemonic(_("_Hang up"));
+	    image = gtk_image_new_from_file( ICONS_DIR "/icon_hangup.svg");
+	    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_hang_up),
+			      NULL);
+	    gtk_widget_show (menu_items);
+	}
+
+	if(hold)
+	{
+	    menu_items = gtk_check_menu_item_new_with_mnemonic (_("On _Hold"));
+	    gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items);
+	    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_items),
+					   (selectedCall->_state == CALL_STATE_HOLD ? TRUE : FALSE));
+	    g_signal_connect(G_OBJECT (menu_items), "activate",
+			     G_CALLBACK (call_hold),
+			     NULL);
+	    gtk_widget_show (menu_items);
+	}
+	
+	if(record)
+	{
+	    menu_items = gtk_image_menu_item_new_with_mnemonic(_("_Record"));
+	    image = gtk_image_new_from_stock (GTK_STOCK_MEDIA_RECORD, 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_record),
+			      NULL);
+	    gtk_widget_show (menu_items);
+	}
 
-    if(hold)
-    {
-        menu_items = gtk_check_menu_item_new_with_mnemonic (_("On _Hold"));
-        gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items);
-        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_items),
-                (selectedCall->_state == CALL_STATE_HOLD ? TRUE : FALSE));
-        g_signal_connect(G_OBJECT (menu_items), "activate",
-                G_CALLBACK (call_hold),
-                NULL);
-        gtk_widget_show (menu_items);
     }
-
-    if(record)
+    else
     {
-        menu_items = gtk_image_menu_item_new_with_mnemonic(_("_Record"));
-        image = gtk_image_new_from_stock (GTK_STOCK_MEDIA_RECORD, 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_record),
-                NULL);
-        gtk_widget_show (menu_items);
+	DEBUG("BUILD CONFERENCE MENU");
+
+	if(hangup_conf)
+	{
+	    menu_items = gtk_image_menu_item_new_with_mnemonic(_("_Hang up"));
+	    image = gtk_image_new_from_file( ICONS_DIR "/icon_hangup.svg");
+	    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 (conference_hang_up),
+			      NULL);
+	    gtk_widget_show (menu_items);
+	}
+
+	if(hold_conf)
+	{
+	    menu_items = gtk_check_menu_item_new_with_mnemonic (_("On _Hold"));
+	    gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items);
+	    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_items),
+					   (selectedCall->_state == CALL_STATE_HOLD ? TRUE : FALSE));
+	    g_signal_connect(G_OBJECT (menu_items), "activate",
+			     G_CALLBACK (conference_hold),
+			     NULL);
+	    gtk_widget_show (menu_items);
+	}
     }
 
     if(accounts)
     {
-        add_registered_accounts_to_menu (menu);
+	add_registered_accounts_to_menu (menu);
     }
-
+	
     if (event)
     {
-        button = event->button;
-        event_time = event->time;
+	button = event->button;
+	event_time = event->time;
     }
     else
     {
-        button = 0;
-        event_time = gtk_get_current_event_time ();
+	button = 0;
+	event_time = gtk_get_current_event_time ();
     }
 
     gtk_menu_attach_to_widget (GTK_MENU (menu), my_widget, NULL);
@@ -1037,7 +1146,7 @@ static void ok_cb (GtkWidget *widget UNUSED, gpointer userdata) {
 
     // Update the internal data structure and the GUI
     calllist_add(current_calls, modified_call);
-    calltree_add_call(current_calls, modified_call);
+    calltree_add_call(current_calls, modified_call, NULL);
     sflphone_place_call(modified_call);
     calltree_display (current_calls);
 
diff --git a/sflphone-client-gnome/src/toolbar.c b/sflphone-client-gnome/src/toolbar.c
index 428e829c492b57017f527951fd3e55f67bde7a69..e320920458af6ba10779ec2902d7f5a0502fb0b9 100644
--- a/sflphone-client-gnome/src/toolbar.c
+++ b/sflphone-client-gnome/src/toolbar.c
@@ -52,7 +52,7 @@ call_mailbox( GtkWidget* widget UNUSED, gpointer data UNUSED)
     create_new_call (CALL, CALL_STATE_DIALING, "", account_id, _("Voicemail"), to, &mailbox_call);
     DEBUG("TO : %s" , mailbox_call->_peer_number);
     calllist_add( current_calls , mailbox_call );
-    calltree_add_call( current_calls , mailbox_call );
+    calltree_add_call( current_calls, mailbox_call, NULL);
     update_menus();
     sflphone_place_call( mailbox_call );
     calltree_display(current_calls);
@@ -79,7 +79,7 @@ call_button( GtkWidget *widget UNUSED, gpointer   data UNUSED)
             create_new_call (CALL, CALL_STATE_DIALING, "", "", "", selectedCall->_peer_number, &new_call);
 
             calllist_add(current_calls, new_call);
-            calltree_add_call(current_calls, new_call);
+            calltree_add_call(current_calls, new_call, NULL);
             sflphone_place_call(new_call);
             calltree_display (current_calls);
         }
@@ -267,7 +267,6 @@ GtkWidget *create_toolbar ()
             G_CALLBACK (rec_button), NULL);
     gtk_toolbar_insert(GTK_TOOLBAR(ret), GTK_TOOL_ITEM(recButton), -1);
 
-
     return ret;
 }
 
@@ -308,6 +307,7 @@ toolbar_update_buttons ()
     gtk_signal_handler_unblock(transfertButton, transfertButtonConnId);
 
     callable_obj_t * selectedCall = calltab_get_selected_call(active_calltree);
+    conference_obj_t * selectedConf = calltab_get_selected_conf(active_calltree);
     if (selectedCall)
     {
         switch(selectedCall->_state)
@@ -373,6 +373,26 @@ toolbar_update_buttons ()
                 break;
         }
     }
+    else if(selectedConf)
+    {
+	switch(selectedConf->_state)
+	{
+	    case CONFERENCE_STATE_ACTIVE_ATACHED:
+	        gtk_widget_set_sensitive( GTK_WIDGET(recButton),        FALSE);
+	        break;
+	    case CONFERENCE_STATE_ACTIVE_DETACHED:
+		gtk_widget_set_sensitive( GTK_WIDGET(recButton),        FALSE);
+		break;
+            case CONFERENCE_STATE_RECORD:
+		gtk_widget_set_sensitive( GTK_WIDGET(recButton),        FALSE);
+		break;
+            case CONFERENCE_STATE_HOLD:
+		gtk_widget_set_sensitive( GTK_WIDGET(recButton),        FALSE);
+		break;
+	    default:
+		break;
+	}
+    }
     else
     {
         if( account_list_get_size() > 0 )
diff --git a/sflphone-client-gnome/src/toolbar.h b/sflphone-client-gnome/src/toolbar.h
index 5af6e834e9de2cbac201408566cb3eaa0ecb0fcf..7c539f34fa95d480a6aeeff2f503a9d0bbd1f094 100644
--- a/sflphone-client-gnome/src/toolbar.h
+++ b/sflphone-client-gnome/src/toolbar.h
@@ -34,6 +34,7 @@ GtkToolItem * holdButton;
 GtkToolItem * transfertButton;
 GtkToolItem * unholdButton;
 GtkToolItem * mailboxButton;
+GtkToolItem * detachButton;
 GtkToolItem * recButton;
 GtkToolItem * historyButton;
 GtkToolItem * contactButton;
diff --git a/sflphone-client-gnome/tests/check_contacts.c b/sflphone-client-gnome/tests/check_contacts.c
index 55625a5fc8f8a78fc8b5266098004d9f8f7dc64d..193cab4b8fb99bd4591487ea188a729523aa9563 100644
--- a/sflphone-client-gnome/tests/check_contacts.c
+++ b/sflphone-client-gnome/tests/check_contacts.c
@@ -37,23 +37,23 @@ END_TEST
 Suite *
 contacts_suite (void)
 {
-  Suite *s = suite_create ("Contacts");
+    Suite *s = suite_create("Contacts");
 
-  TCase *tc_cases = tcase_create ("EDS");
-  tcase_add_test (tc_cases, test_eds);
-  suite_add_tcase (s, tc_cases);
+    TCase *tc_cases = tcase_create("EDS");
+    tcase_add_test (tc_cases, test_eds);
+    suite_add_tcase (s, tc_cases);
 
-  return s;
+    return s;
 }
 
 int
 main (void)
 {
-  int number_failed;
-  Suite *s = contacts_suite ();
-  SRunner *sr = srunner_create (s);
-  srunner_run_all (sr, CK_NORMAL);
-  number_failed = srunner_ntests_failed (sr);
-  srunner_free (sr);
-  return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+    int number_failed;
+    Suite *s = contacts_suite ();
+    SRunner *sr = srunner_create (s);
+    srunner_run_all (sr, CK_NORMAL);
+    number_failed = srunner_ntests_failed (sr);
+    srunner_free (sr);
+   return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
 }
diff --git a/sflphone-common/libs/pjproject/build.mak b/sflphone-common/libs/pjproject/build.mak
index f3797ba67d9838efe7d22810639513c458686761..80ff11095e0fa962c6089f73eb1e8031f2fd8214 100644
--- a/sflphone-common/libs/pjproject/build.mak
+++ b/sflphone-common/libs/pjproject/build.mak
@@ -3,7 +3,7 @@ export MACHINE_NAME := auto
 export OS_NAME := auto
 export HOST_NAME := unix
 export CC_NAME := gcc
-export TARGET_NAME := x86_64-unknown-linux-gnu
+export TARGET_NAME := i686-pc-linux-gnu
 export CROSS_COMPILE := 
 export LINUX_POLL := select 
 
@@ -42,7 +42,7 @@ endif
 
 
 # CFLAGS, LDFLAGS, and LIBS to be used by applications
-export PJDIR := /home/emilou/git-repos/sflphone/sflphone-common/libs/pjproject
+export PJDIR := /home/alexandresavard/Development/sflphone/sflphone-common/libs/pjproject
 export APP_CC := $(CROSS_COMPILE)$(CC_NAME)
 export APP_CFLAGS := -DPJ_AUTOCONF=1\
 	-O2\
diff --git a/sflphone-common/libs/pjproject/config.log b/sflphone-common/libs/pjproject/config.log
index 22c00bbf045aea53ab3d41718071485913d6d703..656155f0ee52e06effbf9cbb591f01b20230ae85 100644
--- a/sflphone-common/libs/pjproject/config.log
+++ b/sflphone-common/libs/pjproject/config.log
@@ -10,11 +10,11 @@ generated by GNU Autoconf 2.61.  Invocation command line was
 ## Platform. ##
 ## --------- ##
 
-hostname = emilou-desktop
-uname -m = x86_64
+hostname = alexandresavard-desktop
+uname -m = i686
 uname -r = 2.6.28-15-generic
 uname -s = Linux
-uname -v = #49-Ubuntu SMP Tue Aug 18 19:25:34 UTC 2009
+uname -v = #52-Ubuntu SMP Wed Sep 9 10:49:34 UTC 2009
 
 /usr/bin/uname -p = unknown
 /bin/uname -X     = unknown
@@ -27,7 +27,6 @@ uname -v = #49-Ubuntu SMP Tue Aug 18 19:25:34 UTC 2009
 /usr/bin/oslevel       = unknown
 /bin/universe          = unknown
 
-PATH: /home/emilou/bin
 PATH: /usr/local/sbin
 PATH: /usr/local/bin
 PATH: /usr/sbin
@@ -35,7 +34,6 @@ PATH: /usr/bin
 PATH: /sbin
 PATH: /bin
 PATH: /usr/games
-PATH: /usr/local/share/OpenSceneGraph/bin
 
 
 ## ----------- ##
@@ -43,11 +41,11 @@ PATH: /usr/local/share/OpenSceneGraph/bin
 ## ----------- ##
 
 aconfigure:1802: checking build system type
-aconfigure:1820: result: x86_64-unknown-linux-gnu
+aconfigure:1820: result: i686-pc-linux-gnu
 aconfigure:1842: checking host system type
-aconfigure:1857: result: x86_64-unknown-linux-gnu
+aconfigure:1857: result: i686-pc-linux-gnu
 aconfigure:1879: checking target system type
-aconfigure:1894: result: x86_64-unknown-linux-gnu
+aconfigure:1894: result: i686-pc-linux-gnu
 aconfigure:1984: checking for gcc
 aconfigure:2000: found /usr/bin/gcc
 aconfigure:2011: result: gcc
@@ -61,8 +59,8 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 aconfigure:2259: $? = 0
 aconfigure:2266: gcc -v >&5
 Using built-in specs.
-Target: x86_64-linux-gnu
-Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.3.3-5ubuntu4' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
+Target: i486-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.3.3-5ubuntu4' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
 Thread model: posix
 gcc version 4.3.3 (Ubuntu 4.3.3-5ubuntu4) 
 aconfigure:2269: $? = 0
@@ -112,8 +110,8 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 aconfigure:2981: $? = 0
 aconfigure:2988: g++ -v >&5
 Using built-in specs.
-Target: x86_64-linux-gnu
-Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.3.3-5ubuntu4' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
+Target: i486-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.3.3-5ubuntu4' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
 Thread model: posix
 gcc version 4.3.3 (Ubuntu 4.3.3-5ubuntu4) 
 aconfigure:2991: $? = 0
@@ -303,9 +301,9 @@ aconfigure:3848: $? = 0
 aconfigure:3866: result: yes
 aconfigure:3877: checking for uuid_generate in -luuid
 aconfigure:3936: result: yes
-aconfigure:3943: result: Setting PJ_M_NAME to x86_64
+aconfigure:3943: result: Setting PJ_M_NAME to i686
 aconfigure:3950: checking memory alignment
-aconfigure:3958: result: 8 bytes
+aconfigure:3966: result: 4 bytes (default)
 aconfigure:3977: checking how to run the C preprocessor
 aconfigure:4017: gcc -E  conftest.c
 aconfigure:4023: $? = 0
@@ -323,8 +321,8 @@ aconfigure: failed program was:
 | #define HAVE_LIBRT 1
 | #define HAVE_LIBNSL 1
 | #define HAVE_LIBUUID 1
-| #define PJ_M_NAME "x86_64"
-| #define PJ_POOL_ALIGNMENT 8
+| #define PJ_M_NAME "i686"
+| #define PJ_POOL_ALIGNMENT 4
 | /* end confdefs.h.  */
 | #include <ac_nonexistent.h>
 aconfigure:4093: result: gcc -E
@@ -344,8 +342,8 @@ aconfigure: failed program was:
 | #define HAVE_LIBRT 1
 | #define HAVE_LIBNSL 1
 | #define HAVE_LIBUUID 1
-| #define PJ_M_NAME "x86_64"
-| #define PJ_POOL_ALIGNMENT 8
+| #define PJ_M_NAME "i686"
+| #define PJ_POOL_ALIGNMENT 4
 | /* end confdefs.h.  */
 | #include <ac_nonexistent.h>
 aconfigure:4203: checking for grep that handles long lines and -e
@@ -417,8 +415,8 @@ aconfigure: failed program was:
 | #define HAVE_LIBRT 1
 | #define HAVE_LIBNSL 1
 | #define HAVE_LIBUUID 1
-| #define PJ_M_NAME "x86_64"
-| #define PJ_POOL_ALIGNMENT 8
+| #define PJ_M_NAME "i686"
+| #define PJ_POOL_ALIGNMENT 4
 | #define STDC_HEADERS 1
 | #define HAVE_SYS_TYPES_H 1
 | #define HAVE_SYS_STAT_H 1
@@ -699,8 +697,8 @@ aconfigure: failed program was:
 | #define HAVE_LIBRT 1
 | #define HAVE_LIBNSL 1
 | #define HAVE_LIBUUID 1
-| #define PJ_M_NAME "x86_64"
-| #define PJ_POOL_ALIGNMENT 8
+| #define PJ_M_NAME "i686"
+| #define PJ_POOL_ALIGNMENT 4
 | #define STDC_HEADERS 1
 | #define HAVE_SYS_TYPES_H 1
 | #define HAVE_SYS_STAT_H 1
@@ -793,8 +791,8 @@ aconfigure: failed program was:
 | #define HAVE_LIBRT 1
 | #define HAVE_LIBNSL 1
 | #define HAVE_LIBUUID 1
-| #define PJ_M_NAME "x86_64"
-| #define PJ_POOL_ALIGNMENT 8
+| #define PJ_M_NAME "i686"
+| #define PJ_POOL_ALIGNMENT 4
 | #define STDC_HEADERS 1
 | #define HAVE_SYS_TYPES_H 1
 | #define HAVE_SYS_STAT_H 1
@@ -856,8 +854,8 @@ aconfigure: failed program was:
 | #define HAVE_LIBRT 1
 | #define HAVE_LIBNSL 1
 | #define HAVE_LIBUUID 1
-| #define PJ_M_NAME "x86_64"
-| #define PJ_POOL_ALIGNMENT 8
+| #define PJ_M_NAME "i686"
+| #define PJ_POOL_ALIGNMENT 4
 | #define STDC_HEADERS 1
 | #define HAVE_SYS_TYPES_H 1
 | #define HAVE_SYS_STAT_H 1
@@ -950,8 +948,8 @@ aconfigure: failed program was:
 | #define HAVE_LIBRT 1
 | #define HAVE_LIBNSL 1
 | #define HAVE_LIBUUID 1
-| #define PJ_M_NAME "x86_64"
-| #define PJ_POOL_ALIGNMENT 8
+| #define PJ_M_NAME "i686"
+| #define PJ_POOL_ALIGNMENT 4
 | #define STDC_HEADERS 1
 | #define HAVE_SYS_TYPES_H 1
 | #define HAVE_SYS_STAT_H 1
@@ -1013,8 +1011,8 @@ aconfigure: failed program was:
 | #define HAVE_LIBRT 1
 | #define HAVE_LIBNSL 1
 | #define HAVE_LIBUUID 1
-| #define PJ_M_NAME "x86_64"
-| #define PJ_POOL_ALIGNMENT 8
+| #define PJ_M_NAME "i686"
+| #define PJ_POOL_ALIGNMENT 4
 | #define STDC_HEADERS 1
 | #define HAVE_SYS_TYPES_H 1
 | #define HAVE_SYS_STAT_H 1
@@ -1081,8 +1079,8 @@ aconfigure: failed program was:
 | #define HAVE_LIBRT 1
 | #define HAVE_LIBNSL 1
 | #define HAVE_LIBUUID 1
-| #define PJ_M_NAME "x86_64"
-| #define PJ_POOL_ALIGNMENT 8
+| #define PJ_M_NAME "i686"
+| #define PJ_POOL_ALIGNMENT 4
 | #define STDC_HEADERS 1
 | #define HAVE_SYS_TYPES_H 1
 | #define HAVE_SYS_STAT_H 1
@@ -1175,8 +1173,8 @@ aconfigure: failed program was:
 | #define HAVE_LIBRT 1
 | #define HAVE_LIBNSL 1
 | #define HAVE_LIBUUID 1
-| #define PJ_M_NAME "x86_64"
-| #define PJ_POOL_ALIGNMENT 8
+| #define PJ_M_NAME "i686"
+| #define PJ_POOL_ALIGNMENT 4
 | #define STDC_HEADERS 1
 | #define HAVE_SYS_TYPES_H 1
 | #define HAVE_SYS_STAT_H 1
@@ -1237,7 +1235,7 @@ aconfigure:9229: checking for net/if.h
 aconfigure:9253: gcc -c -O2  conftest.c >&5
 aconfigure:9259: $? = 0
 aconfigure:9274: result: yes
-aconfigure:9285: result: Setting PJ_OS_NAME to x86_64-unknown-linux-gnu
+aconfigure:9285: result: Setting PJ_OS_NAME to i686-pc-linux-gnu
 aconfigure:9292: result: Setting PJ_HAS_ERRNO_VAR to 1
 aconfigure:9299: result: Setting PJ_HAS_HIGH_RES_TIMER to 1
 aconfigure:9306: result: Setting PJ_HAS_MALLOC to 1
@@ -1275,8 +1273,8 @@ aconfigure: failed program was:
 | #define HAVE_LIBRT 1
 | #define HAVE_LIBNSL 1
 | #define HAVE_LIBUUID 1
-| #define PJ_M_NAME "x86_64"
-| #define PJ_POOL_ALIGNMENT 8
+| #define PJ_M_NAME "i686"
+| #define PJ_POOL_ALIGNMENT 4
 | #define STDC_HEADERS 1
 | #define HAVE_SYS_TYPES_H 1
 | #define HAVE_SYS_STAT_H 1
@@ -1319,7 +1317,7 @@ aconfigure: failed program was:
 | #define PJ_HAS_TIME_H 1
 | #define PJ_HAS_UNISTD_H 1
 | #define PJ_HAS_NET_IF_H 1
-| #define PJ_OS_NAME "x86_64-unknown-linux-gnu"
+| #define PJ_OS_NAME "i686-pc-linux-gnu"
 | #define PJ_HAS_ERRNO_VAR 1
 | #define PJ_HAS_HIGH_RES_TIMER 1
 | #define PJ_HAS_MALLOC 1
@@ -1372,8 +1370,8 @@ aconfigure: failed program was:
 | #define HAVE_LIBRT 1
 | #define HAVE_LIBNSL 1
 | #define HAVE_LIBUUID 1
-| #define PJ_M_NAME "x86_64"
-| #define PJ_POOL_ALIGNMENT 8
+| #define PJ_M_NAME "i686"
+| #define PJ_POOL_ALIGNMENT 4
 | #define STDC_HEADERS 1
 | #define HAVE_SYS_TYPES_H 1
 | #define HAVE_SYS_STAT_H 1
@@ -1416,7 +1414,7 @@ aconfigure: failed program was:
 | #define PJ_HAS_TIME_H 1
 | #define PJ_HAS_UNISTD_H 1
 | #define PJ_HAS_NET_IF_H 1
-| #define PJ_OS_NAME "x86_64-unknown-linux-gnu"
+| #define PJ_OS_NAME "i686-pc-linux-gnu"
 | #define PJ_HAS_ERRNO_VAR 1
 | #define PJ_HAS_HIGH_RES_TIMER 1
 | #define PJ_HAS_MALLOC 1
@@ -1455,8 +1453,8 @@ aconfigure: failed program was:
 | #define HAVE_LIBRT 1
 | #define HAVE_LIBNSL 1
 | #define HAVE_LIBUUID 1
-| #define PJ_M_NAME "x86_64"
-| #define PJ_POOL_ALIGNMENT 8
+| #define PJ_M_NAME "i686"
+| #define PJ_POOL_ALIGNMENT 4
 | #define STDC_HEADERS 1
 | #define HAVE_SYS_TYPES_H 1
 | #define HAVE_SYS_STAT_H 1
@@ -1499,7 +1497,7 @@ aconfigure: failed program was:
 | #define PJ_HAS_TIME_H 1
 | #define PJ_HAS_UNISTD_H 1
 | #define PJ_HAS_NET_IF_H 1
-| #define PJ_OS_NAME "x86_64-unknown-linux-gnu"
+| #define PJ_OS_NAME "i686-pc-linux-gnu"
 | #define PJ_HAS_ERRNO_VAR 1
 | #define PJ_HAS_HIGH_RES_TIMER 1
 | #define PJ_HAS_MALLOC 1
@@ -1560,8 +1558,8 @@ aconfigure: failed program was:
 | #define HAVE_LIBRT 1
 | #define HAVE_LIBNSL 1
 | #define HAVE_LIBUUID 1
-| #define PJ_M_NAME "x86_64"
-| #define PJ_POOL_ALIGNMENT 8
+| #define PJ_M_NAME "i686"
+| #define PJ_POOL_ALIGNMENT 4
 | #define STDC_HEADERS 1
 | #define HAVE_SYS_TYPES_H 1
 | #define HAVE_SYS_STAT_H 1
@@ -1604,7 +1602,7 @@ aconfigure: failed program was:
 | #define PJ_HAS_TIME_H 1
 | #define PJ_HAS_UNISTD_H 1
 | #define PJ_HAS_NET_IF_H 1
-| #define PJ_OS_NAME "x86_64-unknown-linux-gnu"
+| #define PJ_OS_NAME "i686-pc-linux-gnu"
 | #define PJ_HAS_ERRNO_VAR 1
 | #define PJ_HAS_HIGH_RES_TIMER 1
 | #define PJ_HAS_MALLOC 1
@@ -1668,8 +1666,8 @@ aconfigure: failed program was:
 | #define HAVE_LIBRT 1
 | #define HAVE_LIBNSL 1
 | #define HAVE_LIBUUID 1
-| #define PJ_M_NAME "x86_64"
-| #define PJ_POOL_ALIGNMENT 8
+| #define PJ_M_NAME "i686"
+| #define PJ_POOL_ALIGNMENT 4
 | #define STDC_HEADERS 1
 | #define HAVE_SYS_TYPES_H 1
 | #define HAVE_SYS_STAT_H 1
@@ -1712,7 +1710,7 @@ aconfigure: failed program was:
 | #define PJ_HAS_TIME_H 1
 | #define PJ_HAS_UNISTD_H 1
 | #define PJ_HAS_NET_IF_H 1
-| #define PJ_OS_NAME "x86_64-unknown-linux-gnu"
+| #define PJ_OS_NAME "i686-pc-linux-gnu"
 | #define PJ_HAS_ERRNO_VAR 1
 | #define PJ_HAS_HIGH_RES_TIMER 1
 | #define PJ_HAS_MALLOC 1
@@ -1797,7 +1795,7 @@ generated by GNU Autoconf 2.61.  Invocation command line was
   CONFIG_COMMANDS = 
   $ ./config.status 
 
-on emilou-desktop
+on alexandresavard-desktop
 
 config.status:642: creating build.mak
 config.status:642: creating build/os-auto.mak
@@ -1808,9 +1806,7 @@ config.status:642: creating pjsip/build/os-auto.mak
 config.status:642: creating third_party/build/portaudio/os-auto.mak
 config.status:642: creating third_party/build/os-auto.mak
 config.status:642: creating pjlib/include/pj/compat/os_auto.h
-config.status:920: pjlib/include/pj/compat/os_auto.h is unchanged
 config.status:642: creating pjlib/include/pj/compat/m_auto.h
-config.status:920: pjlib/include/pj/compat/m_auto.h is unchanged
 config.status:642: creating pjmedia/include/pjmedia/config_auto.h
 config.status:920: pjmedia/include/pjmedia/config_auto.h is unchanged
 config.status:642: creating pjmedia/include/pjmedia-codec/config_auto.h
@@ -1832,7 +1828,7 @@ The next step now is to run 'make dep' and 'make'.
 ## Cache variables. ##
 ## ---------------- ##
 
-ac_cv_build=x86_64-unknown-linux-gnu
+ac_cv_build=i686-pc-linux-gnu
 ac_cv_c_bigendian=no
 ac_cv_c_compiler_gnu=yes
 ac_cv_cxx_compiler_gnu=yes
@@ -1904,7 +1900,7 @@ ac_cv_header_uuid_uuid_h=yes
 ac_cv_header_winsock2_h=no
 ac_cv_header_winsock_h=no
 ac_cv_header_ws2tcpip_h=no
-ac_cv_host=x86_64-unknown-linux-gnu
+ac_cv_host=i686-pc-linux-gnu
 ac_cv_lib_crypto_ERR_load_BIO_strings=yes
 ac_cv_lib_m_fmod=yes
 ac_cv_lib_nsl_puts=yes
@@ -1926,7 +1922,7 @@ ac_cv_prog_ac_ct_CXX=g++
 ac_cv_prog_cc_c89=
 ac_cv_prog_cc_g=yes
 ac_cv_prog_cxx_g=yes
-ac_cv_target=x86_64-unknown-linux-gnu
+ac_cv_target=i686-pc-linux-gnu
 
 ## ----------------- ##
 ## Output variables. ##
@@ -1979,24 +1975,24 @@ ac_os_objs='ioqueue_select.o file_access_unistd.o file_io_ansi.o os_core_unix.o
 ac_pa_cflags=' -DHAVE_SYS_SOUNDCARD_H -DHAVE_LINUX_SOUNDCARD_H -DPA_LITTLE_ENDIAN'
 ac_pa_use_alsa='1'
 ac_pa_use_oss='1'
-ac_pjdir='/home/emilou/git-repos/sflphone/sflphone-common/libs/pjproject'
+ac_pjdir='/home/alexandresavard/Development/sflphone/sflphone-common/libs/pjproject'
 ac_pjmedia_snd='pa_unix'
 bindir='${exec_prefix}/bin'
-build='x86_64-unknown-linux-gnu'
+build='i686-pc-linux-gnu'
 build_alias=''
-build_cpu='x86_64'
+build_cpu='i686'
 build_os='linux-gnu'
-build_vendor='unknown'
+build_vendor='pc'
 datadir='${datarootdir}'
 datarootdir='${prefix}/share'
 docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
 dvidir='${docdir}'
 exec_prefix='${prefix}'
-host='x86_64-unknown-linux-gnu'
+host='i686-pc-linux-gnu'
 host_alias=''
-host_cpu='x86_64'
+host_cpu='i686'
 host_os='linux-gnu'
-host_vendor='unknown'
+host_vendor='pc'
 htmldir='${docdir}'
 includedir='${prefix}/include'
 infodir='${datarootdir}/info'
@@ -2016,11 +2012,11 @@ psdir='${docdir}'
 sbindir='${exec_prefix}/sbin'
 sharedstatedir='${prefix}/com'
 sysconfdir='${prefix}/etc'
-target='x86_64-unknown-linux-gnu'
+target='i686-pc-linux-gnu'
 target_alias=''
-target_cpu='x86_64'
+target_cpu='i686'
 target_os='linux-gnu'
-target_vendor='unknown'
+target_vendor='pc'
 
 ## ----------- ##
 ## confdefs.h. ##
@@ -2035,8 +2031,8 @@ target_vendor='unknown'
 #define HAVE_LIBRT 1
 #define HAVE_LIBNSL 1
 #define HAVE_LIBUUID 1
-#define PJ_M_NAME "x86_64"
-#define PJ_POOL_ALIGNMENT 8
+#define PJ_M_NAME "i686"
+#define PJ_POOL_ALIGNMENT 4
 #define STDC_HEADERS 1
 #define HAVE_SYS_TYPES_H 1
 #define HAVE_SYS_STAT_H 1
@@ -2079,7 +2075,7 @@ target_vendor='unknown'
 #define PJ_HAS_TIME_H 1
 #define PJ_HAS_UNISTD_H 1
 #define PJ_HAS_NET_IF_H 1
-#define PJ_OS_NAME "x86_64-unknown-linux-gnu"
+#define PJ_OS_NAME "i686-pc-linux-gnu"
 #define PJ_HAS_ERRNO_VAR 1
 #define PJ_HAS_HIGH_RES_TIMER 1
 #define PJ_HAS_MALLOC 1
diff --git a/sflphone-common/libs/pjproject/config.status b/sflphone-common/libs/pjproject/config.status
index d38dfde47d27e397640b3fd570fcec8ada978935..ef4e31bd2d421f0bf73109faa0cf7a588e85ca25 100755
--- a/sflphone-common/libs/pjproject/config.status
+++ b/sflphone-common/libs/pjproject/config.status
@@ -337,7 +337,7 @@ Copyright (C) 2006 Free Software Foundation, Inc.
 This config.status script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it."
 
-ac_pwd='/home/emilou/git-repos/sflphone/sflphone-common/libs/pjproject'
+ac_pwd='/home/alexandresavard/Development/sflphone/sflphone-common/libs/pjproject'
 srcdir='.'
 # If no file are specified by the user, then we need to provide default
 # value.  By we need to know if files were specified by the user.
@@ -530,17 +530,17 @@ s,@LIBS@,|#_!!_#|-lm -luuid -lnsl -lrt -lpthread  -lasound -lssl -lcrypto,g
 s,@build_alias@,|#_!!_#|,g
 s,@host_alias@,|#_!!_#|,g
 s,@target_alias@,|#_!!_#|,g
-s,@build@,|#_!!_#|x86_64-unknown-linux-gnu,g
-s,@build_cpu@,|#_!!_#|x86_64,g
-s,@build_vendor@,|#_!!_#|unknown,g
+s,@build@,|#_!!_#|i686-pc-linux-gnu,g
+s,@build_cpu@,|#_!!_#|i686,g
+s,@build_vendor@,|#_!!_#|pc,g
 s,@build_os@,|#_!!_#|linux-gnu,g
-s,@host@,|#_!!_#|x86_64-unknown-linux-gnu,g
-s,@host_cpu@,|#_!!_#|x86_64,g
-s,@host_vendor@,|#_!!_#|unknown,g
+s,@host@,|#_!!_#|i686-pc-linux-gnu,g
+s,@host_cpu@,|#_!!_#|i686,g
+s,@host_vendor@,|#_!!_#|pc,g
 s,@host_os@,|#_!!_#|linux-gnu,g
-s,@target@,|#_!!_#|x86_64-unknown-linux-gnu,g
-s,@target_cpu@,|#_!!_#|x86_64,g
-s,@target_vendor@,|#_!!_#|unknown,g
+s,@target@,|#_!!_#|i686-pc-linux-gnu,g
+s,@target_cpu@,|#_!!_#|i686,g
+s,@target_vendor@,|#_!!_#|pc,g
 s,@target_os@,|#_!!_#|linux-gnu,g
 s,@CC@,|#_!!_#|gcc,g
 s,@CFLAGS@,|#_!!_#|-O2,g
@@ -552,7 +552,7 @@ s,@OBJEXT@,|#_!!_#|o,g
 s,@CXX@,|#_!!_#|g++,g
 s,@CXXFLAGS@,|#_!!_#|-O2 ,g
 s,@ac_ct_CXX@,|#_!!_#|g++,g
-s,@ac_pjdir@,|#_!!_#|/home/emilou/git-repos/sflphone/sflphone-common/libs/pjproject,g
+s,@ac_pjdir@,|#_!!_#|/home/alexandresavard/Development/sflphone/sflphone-common/libs/pjproject,g
 s,@ac_build_mak_vars@,|#_!!_#|,g
 s,@CPP@,|#_!!_#|gcc -E,g
 s,@GREP@,|#_!!_#|/bin/grep,g
@@ -837,8 +837,8 @@ s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_LIBPTHREAD\)[	 (].*,\1define\2 1 ,
 s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_LIBRT\)[	 (].*,\1define\2 1 ,
 s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_LIBNSL\)[	 (].*,\1define\2 1 ,
 s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_LIBUUID\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*PJ_M_NAME\)[	 (].*,\1define\2 "x86_64" ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*PJ_POOL_ALIGNMENT\)[	 (].*,\1define\2 8 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*PJ_M_NAME\)[	 (].*,\1define\2 "i686" ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*PJ_POOL_ALIGNMENT\)[	 (].*,\1define\2 4 ,
 s,^\([	 #]*\)[^	 ]*\([	 ]*STDC_HEADERS\)[	 (].*,\1define\2 1 ,
 s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_SYS_TYPES_H\)[	 (].*,\1define\2 1 ,
 s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_SYS_STAT_H\)[	 (].*,\1define\2 1 ,
@@ -889,7 +889,7 @@ s,^\([	 #]*\)[^	 ]*\([	 ]*PJ_HAS_SYS_TYPES_H\)[	 (].*,\1define\2 1 ,
 s,^\([	 #]*\)[^	 ]*\([	 ]*PJ_HAS_TIME_H\)[	 (].*,\1define\2 1 ,
 s,^\([	 #]*\)[^	 ]*\([	 ]*PJ_HAS_UNISTD_H\)[	 (].*,\1define\2 1 ,
 s,^\([	 #]*\)[^	 ]*\([	 ]*PJ_HAS_NET_IF_H\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*PJ_OS_NAME\)[	 (].*,\1define\2 "x86_64-unknown-linux-gnu" ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*PJ_OS_NAME\)[	 (].*,\1define\2 "i686-pc-linux-gnu" ,
 s,^\([	 #]*\)[^	 ]*\([	 ]*PJ_HAS_ERRNO_VAR\)[	 (].*,\1define\2 1 ,
 s,^\([	 #]*\)[^	 ]*\([	 ]*PJ_HAS_HIGH_RES_TIMER\)[	 (].*,\1define\2 1 ,
 s,^\([	 #]*\)[^	 ]*\([	 ]*PJ_HAS_MALLOC\)[	 (].*,\1define\2 1 ,
diff --git a/sflphone-common/libs/pjproject/pjlib/include/pj/compat/m_auto.h b/sflphone-common/libs/pjproject/pjlib/include/pj/compat/m_auto.h
index 4a068ac65a955e829f481233706fe11e14eb6a8f..4d4dce96418ea4b80512a1d4a3be7101373d0e78 100644
--- a/sflphone-common/libs/pjproject/pjlib/include/pj/compat/m_auto.h
+++ b/sflphone-common/libs/pjproject/pjlib/include/pj/compat/m_auto.h
@@ -27,7 +27,7 @@
  */
 
 /* Machine name, filled in by autoconf script */
-#define PJ_M_NAME "x86_64"
+#define PJ_M_NAME "i686"
 
 /* Endianness. It's reported on pjsip list on 09/02/13 that autoconf
  * endianness detection failed for universal build, so special case
diff --git a/sflphone-common/libs/pjproject/pjlib/include/pj/compat/os_auto.h b/sflphone-common/libs/pjproject/pjlib/include/pj/compat/os_auto.h
index 7186ad9b458747c04a989f1c38c83d8bc43de7a3..cf51c14d8e224b3958dfbea9f8d58ba754a43770 100644
--- a/sflphone-common/libs/pjproject/pjlib/include/pj/compat/os_auto.h
+++ b/sflphone-common/libs/pjproject/pjlib/include/pj/compat/os_auto.h
@@ -28,7 +28,7 @@
  */
 
 /* Canonical OS name */
-#define PJ_OS_NAME "x86_64-unknown-linux-gnu"
+#define PJ_OS_NAME "i686-pc-linux-gnu"
 
 /* Legacy macros */
 /* #undef PJ_WIN32 */
@@ -162,7 +162,7 @@
 #define PJ_NATIVE_STRING_IS_UNICODE 0
 
 /* Pool alignment in bytes */
-#define PJ_POOL_ALIGNMENT 8
+#define PJ_POOL_ALIGNMENT 4
 
 /* The type of atomic variable value: */
 #define PJ_ATOMIC_VALUE_TYPE long
diff --git a/sflphone-common/src/Makefile.am b/sflphone-common/src/Makefile.am
index 928aadb91ec79a73486d3d61e774f2258152fa29..b0fdb972aa33695c20810a087eb8faf4185824d6 100644
--- a/sflphone-common/src/Makefile.am
+++ b/sflphone-common/src/Makefile.am
@@ -7,6 +7,7 @@ SUBDIRS = dbus audio config plug-in hooks history sip iax
 
 # Add here the cpp files to be build with sflphone
 sflphoned_SOURCES = \
+		conference.cpp \
 		voiplink.cpp \
 		main.cpp \
 		managerimpl.cpp \
@@ -51,7 +52,8 @@ sflphoned_LDFLAGS= $(UUID_LIBS)
 noinst_LTLIBRARIES = libsflphone.la
 
 noinst_HEADERS = \
-        voiplink.h \
+		conference.h \
+        	voiplink.h \
 		managerimpl.h \
 		manager.h \
 		global.h \
diff --git a/sflphone-common/src/audio/Makefile.am b/sflphone-common/src/audio/Makefile.am
index cf9e02da72100ebbd211a46fe83c53c5c827338a..cfbbf30f31c7eeb284814347fd5956bbd7862fbf 100644
--- a/sflphone-common/src/audio/Makefile.am
+++ b/sflphone-common/src/audio/Makefile.am
@@ -14,6 +14,8 @@ SUBDIRS = codecs audiortp sound alsa pulseaudio
 libaudio_la_SOURCES = \
 		audioloop.cpp \
 		ringbuffer.cpp \
+		mainbuffer.cpp \
+		recordable.cpp \
 		audiolayer.cpp \
 		audiodevice.cpp \
 		samplerateconverter.cpp \
@@ -25,5 +27,8 @@ noinst_HEADERS = \
 		ringbuffer.h \
 		audiolayer.h \
 		audiodevice.h \
+		mainbuffer.h \
+	 	recordable.h \
 		samplerateconverter.h
 
+
diff --git a/sflphone-common/src/audio/alsa/alsalayer.cpp b/sflphone-common/src/audio/alsa/alsalayer.cpp
index 93f2aa2bf804b19759ab77232af65ec15181b8e7..16ebe977e065258e8ffa4a2b3d840535b4b4ac70 100644
--- a/sflphone-common/src/audio/alsa/alsalayer.cpp
+++ b/sflphone-common/src/audio/alsa/alsalayer.cpp
@@ -43,6 +43,8 @@ AlsaLayer::AlsaLayer (ManagerImpl* manager)
     _debug (" Constructor of AlsaLayer called\n");
     /* Instanciate the audio thread */
     _audioThread = new AudioThread (this);
+
+    _urgentRingBuffer.createReadPointer();
 }
 
 // Destructor
@@ -128,6 +130,10 @@ AlsaLayer::startStream (void)
     startCaptureStream ();
     startPlaybackStream ();
 
+    _urgentRingBuffer.flush();
+    _mainBuffer.flush();
+    _mainBuffer.flushDefault();
+
 }
 
 void
@@ -146,6 +152,8 @@ AlsaLayer::stopStream (void)
 int
 AlsaLayer::canGetMic()
 {
+
+    /*
     int avail;
 
     if (!_CaptureHandle)
@@ -159,12 +167,13 @@ AlsaLayer::canGetMic()
     } else
         return ( (avail<0) ?0:avail);
 
-    /*
     if(_CaptureHandle)
 
         return _micRingBuffer.AvailForGet();
     else
         return 0;*/
+
+    return 0;
 }
 
 int
@@ -175,7 +184,7 @@ AlsaLayer::getMic (void *buffer, int toCopy)
         return _micRingBuffer.Get(buffer, toCopy,100);
     }
     else
-        return 0;*/
+        return 0;
     int res = 0;
 
     if (_CaptureHandle) {
@@ -183,7 +192,9 @@ AlsaLayer::getMic (void *buffer, int toCopy)
         adjustVolume (buffer, toCopy, SFL_PCM_CAPTURE);
     }
 
-    return res;
+    return res;*/
+
+    return 0;
 }
 
 bool AlsaLayer::isCaptureActive (void)
@@ -716,43 +727,55 @@ void AlsaLayer::audioCallback (void)
     // AvailForGet tell the number of chars inside the buffer
     // framePerBuffer are the number of data for one channel (left)
     urgentAvail = _urgentRingBuffer.AvailForGet();
-
     if (urgentAvail > 0) {
+
         // Urgent data (dtmf, incoming call signal) come first.
         toGet = (urgentAvail < (int) (framesPerBufferAlsa * sizeof (SFLDataFormat))) ? urgentAvail : framesPerBufferAlsa * sizeof (SFLDataFormat);
         out = (SFLDataFormat*) malloc (toGet * sizeof (SFLDataFormat));
         _urgentRingBuffer.Get (out, toGet, spkrVolume);
         /* Play the sound */
-        write (out , toGet);
+        write (out, toGet);
         free (out);
         out=0;
         // Consume the regular one as well (same amount of bytes)
-        _voiceRingBuffer.Discard (toGet);
+        _mainBuffer.discard (toGet);
+
     } else {
+
         tone = _manager->getTelephoneTone();
         toGet = 940  ;
         maxBytes = toGet * sizeof (SFLDataFormat)  ;
 
         if (tone != 0) {
+
             out = (SFLDataFormat*) malloc (maxBytes * sizeof (SFLDataFormat));
             tone->getNext (out, toGet, spkrVolume);
             write (out , maxBytes);
+
         } else if ( (tone=_manager->getTelephoneFile()) != 0) {
+
             out = (SFLDataFormat*) malloc (maxBytes * sizeof (SFLDataFormat));
             tone->getNext (out, toGet, spkrVolume);
             write (out , maxBytes);
+
         } else {
+
             // If nothing urgent, play the regular sound samples
-            normalAvail = _voiceRingBuffer.AvailForGet();
+            normalAvail = _mainBuffer.availForGet();
             toGet = (normalAvail < (int) (framesPerBufferAlsa * sizeof (SFLDataFormat))) ? normalAvail : framesPerBufferAlsa * sizeof (SFLDataFormat);
             out = (SFLDataFormat*) malloc (framesPerBufferAlsa * sizeof (SFLDataFormat));
 
             if (toGet) {
-                _voiceRingBuffer.Get (out, toGet, spkrVolume);
+
+                _mainBuffer.getData(out, toGet, spkrVolume);
                 write (out, toGet);
+
             } else {
+
                 bzero (out, framesPerBufferAlsa * sizeof (SFLDataFormat));
             }
+
+	    _urgentRingBuffer.Discard (toGet); 
         }
 
         free (out);
@@ -761,19 +784,30 @@ void AlsaLayer::audioCallback (void)
     }
 
     // Additionally handle the mic's audio stream
-    //if(is_capture_running()){
-    /*micAvailAlsa = snd_pcm_avail_update(_CaptureHandle);
-    if(micAvailAlsa > 0) {
-        micAvailPut = _micRingBuffer.AvailForPut();
-        toPut = (micAvailAlsa <= micAvailPut) ? micAvailAlsa : micAvailPut;
-        in = (SFLDataFormat*)malloc(toPut * sizeof(SFLDataFormat));
-        toPut = read (in, toPut);
-        if (in != 0)
-        {
-            _micRingBuffer.Put(in, toPut, 100);
+    int micAvailAlsa;
+    int micAvailPut;
+    int toPut;
+    SFLDataFormat* in;
+
+
+    // snd_pcm_sframes_t micAvailAlsa;
+    in = 0;
+    if(is_capture_running())
+    {
+        micAvailAlsa = snd_pcm_avail_update(_CaptureHandle);
+	if(micAvailAlsa > 0) 
+	{
+            micAvailPut = _mainBuffer.availForPut();
+            toPut = (micAvailAlsa <= micAvailPut) ? micAvailAlsa : micAvailPut;
+            in = (SFLDataFormat*)malloc(toPut * sizeof(SFLDataFormat));
+            toPut = read (in, toPut* sizeof(SFLDataFormat));
+            if (in != 0)
+            {
+                _mainBuffer.putData(in, toPut, 100);
+	    }
+            free(in); in=0;
         }
-        free(in); in=0;
-    }*/
+    }
 }
 
 void* AlsaLayer::adjustVolume (void* buffer , int len, int stream)
diff --git a/sflphone-common/src/audio/audiolayer.cpp b/sflphone-common/src/audio/audiolayer.cpp
index 68eca5a9c7bc2045732f1588ceac705ca107c339..9f1119ff694baf871e77d9fa9c17b4b13818a667 100644
--- a/sflphone-common/src/audio/audiolayer.cpp
+++ b/sflphone-common/src/audio/audiolayer.cpp
@@ -22,7 +22,9 @@
 void AudioLayer::flushMain (void)
 {
     ost::MutexLock guard (_mutex);
-    _voiceRingBuffer.flush();
+
+    // should pass call id 
+    _mainBuffer.flush();
 }
 
 void AudioLayer::flushUrgent (void)
@@ -34,7 +36,7 @@ void AudioLayer::flushUrgent (void)
 void AudioLayer::flushMic (void)
 {
     ost::MutexLock guard (_mutex);
-    _micRingBuffer.flush();
+    _mainBuffer.flushDefault();
 }
 
 int AudioLayer::putUrgent (void* buffer, int toCopy)
@@ -53,18 +55,18 @@ int AudioLayer::putUrgent (void* buffer, int toCopy)
     return 0;
 }
 
-int AudioLayer::putMain (void *buffer, int toCopy)
+int AudioLayer::putMain (void *buffer, int toCopy, CallID call_id)
 {
     int a;
 
     ost::MutexLock guard (_mutex);
-    a = _voiceRingBuffer.AvailForPut();
+    a = _mainBuffer.availForPut(call_id);
 
     if (a >= toCopy) {
-        return _voiceRingBuffer.Put (buffer, toCopy, _defaultVolume);
+        return _mainBuffer.putData (buffer, toCopy, _defaultVolume, call_id);
     } else {
         _debug ("Chopping sound, Ouch! RingBuffer full ?\n");
-        return _voiceRingBuffer.Put (buffer, a, _defaultVolume);
+        return _mainBuffer.putData (buffer, a, _defaultVolume, call_id);
     }
 
     return 0;
diff --git a/sflphone-common/src/audio/audiolayer.h b/sflphone-common/src/audio/audiolayer.h
index 9f17d75bcd75de65cac71d9190459cdce2b7c83e..816306221e0909d1c2dacee9e7dc7bdad16d0c02 100644
--- a/sflphone-common/src/audio/audiolayer.h
+++ b/sflphone-common/src/audio/audiolayer.h
@@ -25,11 +25,10 @@
 #include "global.h"
 #include "audiodevice.h"
 #include "ringbuffer.h"
-
+#include "mainbuffer.h"
 
 #include <cc++/thread.h> // for ost::Mutex
 
-
 #define FRAME_PER_BUFFER	160
 
 /**
@@ -37,8 +36,11 @@
  * @brief Main sound class. Manages the data transfers between the application and the hardware. 
  */
 
+
+class Recordable;
 class ManagerImpl;
 
+
 class AudioLayer {
 
     private:
@@ -58,9 +60,7 @@ class AudioLayer {
             : _defaultVolume(100)
 			  , _layerType( type )
               , _manager(manager)
-              , _voiceRingBuffer( SIZEBUF )
-              , _urgentRingBuffer( SIZEBUF)
-              , _micRingBuffer( SIZEBUF )
+	      , _urgentRingBuffer( SIZEBUF, default_id )
               , _indexIn ( 0 )
               , _indexOut ( 0 )
               , _sampleRate ( 0 )
@@ -138,7 +138,7 @@ class AudioLayer {
          * @param toCopy    The size of the buffer
          * @return int      The number of bytes copied
          */
-        int putMain(void* buffer, int toCopy);
+        int putMain(void* buffer, int toCopy, CallID call_id = default_id);
 
         void flushMain (void);
 
@@ -193,13 +193,40 @@ class AudioLayer {
          */
         unsigned int getFrameSize() { return _frameSize; }
 
+	/**
+         * Get the layer type for this instance (either Alsa or PulseAudio)
+         * @return unsigned int The layer type
+         *
+         */
         int getLayerType( void ) { return _layerType; }
 
+	/**
+         * Get a pointer to the application MainBuffer class.
+	 *
+	 * In order to send signal to other parts of the application, one must pass through the mainbuffer.
+	 * Audio instances must be registered into the MainBuffer and bound together via the ManagerImpl.
+	 *
+         * @return MainBuffer* a pointer to the MainBuffer instance
+         */
+	MainBuffer* getMainBuffer( void ) { return &_mainBuffer; }
+
         /**
          * Default volume for incoming RTP and Urgent sounds.
          */
         unsigned short _defaultVolume; // 100
 
+	
+	/**
+	 * Set the audio recorder
+	 */
+	void setRecorderInstance(Recordable* rec) {_recorder = NULL; _recorder = rec;}
+
+	/**
+	 * Get the audio recorder
+	 */
+	Recordable* getRecorderInstance(Recordable* rec) {return _recorder;}
+
+
     protected:
 
         int _layerType;
@@ -220,9 +247,21 @@ class AudioLayer {
         /**
          * Urgent ring buffer used for ringtones
          */
-        RingBuffer _voiceRingBuffer;
         RingBuffer _urgentRingBuffer;
-        RingBuffer _micRingBuffer;
+
+	/**
+	 * Instance of the MainBuffer for the whole application
+	 *
+	 * In order to send signal to other parts of the application, one must pass through the mainbuffer.
+	 * Audio instances must be registered into the MainBuffer and bound together via the ManagerImpl.
+	 *
+	 */ 
+	MainBuffer _mainBuffer;
+
+	/**
+	 * A pointer to the recordable instance (may be a call or a conference)
+	 */
+	Recordable* _recorder;
 
         /**
          * Number of audio cards on which capture stream has been opened 
diff --git a/sflphone-common/src/audio/audiortp.cpp b/sflphone-common/src/audio/audiortp.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3f6527f3498406e1eee0dfd6ac110e0a48ce2fb8
--- /dev/null
+++ b/sflphone-common/src/audio/audiortp.cpp
@@ -0,0 +1,681 @@
+/*
+ *  Copyright (C) 2004-2008 Savoir-Faire Linux inc.
+ *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
+ *  Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com>
+ *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
+ *  Author: Laurielle Lea <laurielle.lea@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
+ *  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.
+ */
+
+#include <cstdio>
+#include <cstdlib>
+#include <ccrtp/rtp.h>
+#include <assert.h>
+#include <cstring>
+#include <math.h>
+#include <dlfcn.h>
+#include <iostream>
+#include <sstream>
+
+#include "../global.h"
+#include "../manager.h"
+#include "codecDescriptor.h"
+#include "audiortp.h"
+#include "audiolayer.h"
+#include "ringbuffer.h"
+#include "../user_cfg.h"
+#include "../sipcall.h"
+
+
+int AudioRtpRTX::count_rtp = 0;
+
+////////////////////////////////////////////////////////////////////////////////
+// AudioRtp
+////////////////////////////////////////////////////////////////////////////////
+AudioRtp::AudioRtp() :_RTXThread (0), _symmetric(), _rtpMutex()
+{
+
+}
+
+AudioRtp::~AudioRtp (void)
+{
+    ost::MutexLock m (_rtpMutex);
+
+    if (_RTXThread != _RTXThread)
+    {
+        delete _RTXThread;
+        _RTXThread = 0;
+    }
+
+}
+
+void
+AudioRtp::createNewSession (SIPCall *ca)
+{
+
+    ost::MutexLock m (_rtpMutex);
+
+    _debug ("AudioRtp::Create new rtp session\n");
+
+    // something should stop the thread before...
+
+    if (_RTXThread != 0) {
+        _debug ("**********************************************************\n");
+        _debug ("! ARTP Failure: Thread already exists..., stopping it\n");
+        _debug ("**********************************************************\n");
+        delete _RTXThread;
+        _RTXThread = 0;
+    }
+
+    // Start RTP Send/Receive threads
+    _symmetric = Manager::instance().getConfigInt (SIGNALISATION,SYMMETRIC) ? true : false;
+
+    _RTXThread = new AudioRtpRTX (ca, _symmetric);
+
+}
+
+int
+AudioRtp::start (void)
+{
+    ost::MutexLock m (_rtpMutex);
+
+    if (_RTXThread == 0) {
+        _debug ("! ARTP Failure: Cannot start audiortp thread since not yet created\n");
+        throw AudioRtpException();
+    }
+
+
+    try {
+        if (_RTXThread->start() != 0) {
+            _debug ("! ARTP Failure: unable to start RTX Thread\n");
+            return -1;
+        }
+    } catch (...) {
+        _debugException ("! ARTP Failure: when trying to start a thread");
+        throw;
+    }
+
+    return 0;
+}
+
+
+bool
+AudioRtp::closeRtpSession ()
+{
+
+    ost::MutexLock m (_rtpMutex);
+    // This will make RTP threads finish.
+    _debug ("AudioRtp::Stopping rtp session\n");
+
+    try {
+	if (_RTXThread != 0) {
+            delete _RTXThread;
+            _RTXThread = 0;
+	}
+    } catch (...) {
+        _debugException ("! ARTP Exception: when stopping audiortp\n");
+        throw;
+    }
+
+    _debug ("AudioRtp::Audio rtp stopped\n");
+
+    return true;
+}
+
+/*
+void
+AudioRtp::setRecording()
+{
+
+    _debug ("AudioRtp::setRecording\n");
+    _RTXThread->_ca->setRecording();
+
+}
+*/
+
+////////////////////////////////////////////////////////////////////////////////
+// AudioRtpRTX Class                                                          //
+////////////////////////////////////////////////////////////////////////////////
+AudioRtpRTX::AudioRtpRTX (SIPCall *sipcall, bool sym) : time (new ost::Time()), _ca (sipcall), _sessionSend (NULL), _sessionRecv (NULL), _session (NULL),
+        _sym (sym), micData (NULL), micDataConverted (NULL), micDataEncoded (NULL), spkrDataDecoded (NULL), spkrDataConverted (NULL),
+        converter (NULL), _layerSampleRate(),_codecSampleRate(), _layerFrameSize(), _audiocodec (NULL)
+{
+
+    setCancel (cancelDefault);
+    // AudioRtpRTX should be close if we change sample rate
+    // TODO: Change bind address according to user settings.
+    // TODO: this should be the local ip not the external (router) IP
+    std::string localipConfig = _ca->getLocalIp(); // _ca->getLocalIp();
+    ost::InetHostAddress local_ip (localipConfig.c_str());
+
+    _debug ("%i\n", _ca->getLocalAudioPort());
+    _session = new ost::SymmetricRTPSession (local_ip, _ca->getLocalAudioPort());
+    // _session = new ost::RTPSessionBase(local_ip, _ca->getLocalAudioPort());
+    _sessionRecv = NULL;
+    _sessionSend = NULL;
+
+    //mic, we receive from soundcard in stereo, and we send encoded
+    //encoding before sending
+    _audiolayer = Manager::instance().getAudioDriver();
+    _layerFrameSize = _audiolayer->getFrameSize(); // in ms
+    _layerSampleRate = _audiolayer->getSampleRate();
+
+    // initBuffers();
+
+    // initAudioRtpSession();
+
+    _payloadIsSet = false;
+    _remoteIpIsSet = false;
+
+
+    count_rtp++;
+    // open files
+    std::string s_input;
+    std::string s_output;
+
+    // convert count into string
+    std::stringstream out;
+    out << count_rtp;
+    
+    s_input = "/home/alexandresavard/Desktop/buffer_record/rtp_input_";
+    s_input.append(out.str());
+
+    s_output = "/home/alexandresavard/Desktop/buffer_record/rtp_output_";
+    s_output.append(out.str());
+
+    rtp_input_rec = new std::fstream();
+    rtp_output_rec = new std::fstream();
+
+    rtp_input_rec->open(s_input.c_str(), std::fstream::out);
+    rtp_output_rec->open(s_output.c_str(), std::fstream::out);
+
+}
+
+AudioRtpRTX::~AudioRtpRTX ()
+{
+
+    ost::MutexLock m (_rtpRtxMutex);
+
+    _debug ("Delete AudioRtpRTX instance in callid %s\n", _ca->getCallId().c_str());
+
+    try {
+        this->terminate();
+    } catch (...) {
+        _debugException ("! ARTP: Thread destructor didn't terminate correctly");
+        throw;
+    }
+
+    _debug("Remove audio stream for call id %s\n", _ca->getCallId().c_str());
+    _audiolayer->getMainBuffer()->unBindAll(_ca->getCallId());
+    // Manager::instance().removeStream(_ca->getCallId());
+
+    _debug("DELETE print micData address %p\n", micData);
+    delete [] micData;
+    micData = NULL;
+    delete [] micDataConverted;
+    micDataConverted = NULL;
+    delete [] micDataEncoded;
+    micDataEncoded = NULL;
+
+    delete [] spkrDataDecoded;
+    spkrDataDecoded = NULL;
+    delete [] spkrDataConverted;
+    spkrDataConverted = NULL;
+
+    delete time;
+    time = NULL;
+
+    delete converter;
+    converter = NULL;
+
+    _ca = 0;
+    // _session->terminate();
+
+    delete _session;
+    _session = NULL;
+
+    _debug ("AudioRtpRTX instance deleted\n");
+
+    rtp_input_rec->close();
+    rtp_output_rec->close();
+
+}
+
+
+void
+AudioRtpRTX::initBuffers()
+{
+    ost::MutexLock m (_rtpRtxMutex);
+    
+    _debug("AudioRtpRTX::initBuffers Init RTP buffers for %s\n", _ca->getCallId().c_str());
+    
+    converter = new SamplerateConverter (_layerSampleRate , _layerFrameSize);
+
+    nbSamplesMax = (int) (_layerSampleRate * _layerFrameSize /1000);
+
+    
+    _debug("AudioRtpRTX::initBuffers NBSAMPLEMAX %i\n", nbSamplesMax);
+
+    micData = new SFLDataFormat[nbSamplesMax];
+    _debug("CREATE print micData address %p\n", micData);
+    micDataConverted = new SFLDataFormat[nbSamplesMax];
+    micDataEncoded = new unsigned char[nbSamplesMax];
+
+    spkrDataConverted = new SFLDataFormat[nbSamplesMax];
+    spkrDataDecoded = new SFLDataFormat[nbSamplesMax];
+
+    Manager::instance().addStream(_ca->getCallId());
+    // _audiolayer->getMainBuffer()->bindCallID(_ca->getCallId());
+}
+
+
+void
+AudioRtpRTX::initAudioRtpSession (void)
+{
+
+    try {
+
+        _session->setSchedulingTimeout (100000);
+        _session->setExpireTimeout (1000000);
+
+
+    } catch (...) {
+        _debugException ("! ARTP Failure: initialisation failed");
+        throw;
+    }
+
+}
+
+void
+AudioRtpRTX::setRtpSessionMedia (void)
+{
+
+    if (_ca == 0) {
+        _debug (" !ARTP: No call, can't init RTP media\n");
+        return;
+    }
+
+    AudioCodecType pl = (AudioCodecType)_ca->getLocalSDP()->get_session_media()->getPayload();
+    _audiocodec = Manager::instance().getCodecDescriptorMap().instantiateCodec(pl);
+
+    if (_audiocodec == NULL) {
+        _debug (" !ARTP: No audiocodec, can't init RTP media\n");
+        return;
+    }
+
+    _debug ("Init audio RTP session: codec payload %i\n", _audiocodec->getPayload());
+
+    // _audioCodecInstance = *_audiocodec;
+
+    _codecSampleRate = _audiocodec->getClockRate();
+
+    _codecFrameSize = _audiocodec->getFrameSize();
+
+    if (_audiocodec->getPayload() == 9) {
+        _payloadIsSet = _session->setPayloadFormat (ost::DynamicPayloadFormat ( (ost::PayloadType) _audiocodec->getPayload(), _audiocodec->getClockRate()));
+    } else if (_audiocodec->hasDynamicPayload()) {
+        _payloadIsSet = _session->setPayloadFormat (ost::DynamicPayloadFormat ( (ost::PayloadType) _audiocodec->getPayload(), _audiocodec->getClockRate()));
+    } else if (!_audiocodec->hasDynamicPayload() && _audiocodec->getPayload() != 9) {
+        _payloadIsSet = _session->setPayloadFormat (ost::StaticPayloadFormat ( (ost::StaticPayloadType) _audiocodec->getPayload()));
+    }
+
+
+
+}
+
+void
+AudioRtpRTX::setRtpSessionRemoteIp (void)
+{
+
+    if (!_remoteIpIsSet) {
+
+        _debug ("++++++++++++++++++++++++++ SET IP ADDRESS ++++++++++++++++++++++++++++\n");
+
+        if (_ca == 0) {
+            _debug (" !ARTP: No call, can't init RTP media \n");
+            return;
+        }
+
+        ost::InetHostAddress remote_ip (_ca->getLocalSDP()->get_remote_ip().c_str());
+
+        _debug ("Init audio RTP session: remote ip %s\n", _ca->getLocalSDP()->get_remote_ip().data());
+
+        if (!remote_ip) {
+            _debug (" !ARTP Thread Error: Target IP address [%s] is not correct!\n", _ca->getLocalSDP()->get_remote_ip().data());
+            return;
+        }
+
+        _debug ("++++Address: %s, audioport: %d\n", _ca->getLocalSDP()->get_remote_ip().c_str(), _ca->getLocalSDP()->get_remote_audio_port());
+
+        _debug ("++++Audioport: %d\n", (int) _ca->getLocalSDP()->get_remote_audio_port());
+
+        if (!_session->addDestination (remote_ip, (unsigned short) _ca->getLocalSDP()->get_remote_audio_port())) {
+            _debug (" !ARTP Thread Error: can't add destination to session!\n");
+            return;
+        }
+
+        _remoteIpIsSet = true;
+    } else {
+        _debug ("+++++++++++++++++++++++ IP ADDRESS ALREADY SET ++++++++++++++++++++++++\n");
+    }
+
+}
+
+
+
+float
+AudioRtpRTX::computeCodecFrameSize (int codecSamplePerFrame, int codecClockRate)
+{
+    return ( (float) codecSamplePerFrame * 1000.0) / (float) codecClockRate;
+}
+
+int
+AudioRtpRTX::computeNbByteAudioLayer (float codecFrameSize)
+{
+    return (int) ( (float) _layerSampleRate * codecFrameSize * (float) sizeof (SFLDataFormat) / 1000.0);
+}
+
+
+int
+AudioRtpRTX::processDataEncode()
+{
+
+    // compute codec framesize in ms
+    float fixed_codec_framesize = computeCodecFrameSize (_audiocodec->getFrameSize(), _audiocodec->getClockRate());
+
+    // compute nb of byte to get coresponding to 20 ms at audio layer frame size (44.1 khz)
+    int maxBytesToGet = computeNbByteAudioLayer (fixed_codec_framesize);
+
+    // available bytes inside ringbuffer
+    int availBytesFromMic = _audiolayer->getMainBuffer()->availForGet(_ca->getCallId());
+
+    // _debug("AudioRtpRTX::processDataEncode() callid: %s availBytesFromMic %i\n", _ca->getCallId().c_str(), availBytesFromMic);
+
+    // _debug("AudioRtpRTX::processDataEncode: availBytesFromMic: %i\n", availBytesFromMic);
+    // set available byte to maxByteToGet
+    int bytesAvail = (availBytesFromMic < maxBytesToGet) ? availBytesFromMic : maxBytesToGet;
+    // _debug("bytesAvail %i\n", bytesAvail);
+    if (bytesAvail == 0)
+        return 0;
+
+    // _debug("AudioRtpRTX::processDataEncode: bytesAvail: %i\n", bytesAvail);
+    // Get bytes from micRingBuffer to data_from_mic
+    int nbSample = _audiolayer->getMainBuffer()->getData(micData , bytesAvail, 100, _ca->getCallId()) / sizeof (SFLDataFormat);
+
+    rtp_output_rec->write((char*)micData, bytesAvail);
+
+    // _debug("AudioRtpRTX::processDataEncode: nbSample: %i\n", nbSample);
+
+    // nb bytes to be sent over RTP
+    int compSize = 0;
+
+    // test if resampling is required
+    if (_audiocodec->getClockRate() != _layerSampleRate) {
+
+        int nb_sample_up = nbSample;
+        //_debug("_nbSample audiolayer->getMic(): %i \n", nbSample);
+
+        // Store the length of the mic buffer in samples for recording
+        _nSamplesMic = nbSample;
+
+        nbSample = reSampleData (micData , micDataConverted, _audiocodec->getClockRate(), nb_sample_up, DOWN_SAMPLING);
+
+        compSize = _audiocodec->codecEncode (micDataEncoded, micDataConverted, nbSample*sizeof (int16));
+
+    } else {
+        // no resampling required
+        compSize = _audiocodec->codecEncode (micDataEncoded, micData, nbSample*sizeof (int16));
+    }
+
+    return compSize;
+}
+
+
+void
+AudioRtpRTX::processDataDecode (unsigned char* spkrData, unsigned int size, int& countTime)
+{
+    if (_audiocodec != NULL) {
+
+        // Return the size of data in bytes
+        int expandedSize = _audiocodec->codecDecode (spkrDataDecoded , spkrData , size);
+
+        // buffer _receiveDataDecoded ----> short int or int16, coded on 2 bytes
+        int nbSample = expandedSize / sizeof (SFLDataFormat);
+
+        // test if resampling is required
+
+        if (_audiocodec->getClockRate() != _layerSampleRate) {
+
+            // Do sample rate conversion
+            int nb_sample_down = nbSample;
+            nbSample = reSampleData (spkrDataDecoded, spkrDataConverted, _codecSampleRate, nb_sample_down, UP_SAMPLING);
+
+	    rtp_input_rec->write((char*)spkrDataConverted, nbSample * sizeof (SFLDataFormat));
+
+            // Store the number of samples for recording
+            _nSamplesSpkr = nbSample;
+
+
+
+            // put data in audio layer, size in byte
+            _audiolayer->getMainBuffer()->putData (spkrDataConverted, nbSample * sizeof (SFLDataFormat), 100, _ca->getCallId());
+
+        } else {
+
+            // Stor the number of samples for recording
+            _nSamplesSpkr = nbSample;
+
+            // put data in audio layer, size in byte
+            _audiolayer->getMainBuffer()->putData (spkrDataDecoded, nbSample * sizeof (SFLDataFormat), 100, _ca->getCallId());
+        }
+
+        // Notify (with a beep) an incoming call when there is already a call
+        countTime += time->getSecond();
+
+        if (Manager::instance().incomingCallWaiting() > 0) {
+            countTime = countTime % 500; // more often...
+
+            if (countTime == 0) {
+                Manager::instance().notificationIncomingCall();
+            }
+        }
+
+    } else {
+        countTime += time->getSecond();
+    }
+}
+
+void
+AudioRtpRTX::sendSessionFromMic (int timestamp)
+{
+    // STEP:
+    //   1. get data from mic
+    //   2. convert it to int16 - good sample, good rate
+    //   3. encode it
+    //   4. send it
+
+    timestamp += time->getSecond();
+    // no call, so we do nothing
+
+    if (_ca==0) {
+        _debug (" !ARTP: No call associated (mic)\n");
+        return;
+    }
+
+    // AudioLayer* audiolayer = Manager::instance().getAudioDriver();
+    if (!_audiolayer) {
+        _debug (" !ARTP: No audiolayer available for MIC\n");
+        return;
+    }
+
+    if (!_audiocodec) {
+        _debug (" !ARTP: No audiocodec available for MIC\n");
+        return;
+    }
+
+ 
+
+    int compSize = processDataEncode();
+
+    // putData put the data on RTP queue, sendImmediate bypass this queue
+    // _debug("AudioRtpRTX::sendSessionFromMic: timestamp: %i, compsize: %i\n", timestamp, compSize);
+    if((compSize != 0) && (micDataEncoded != NULL))
+        _session->putData (timestamp, micDataEncoded, compSize);
+    // _session->sendImmediate(timestamp, micDataEncoded, compSize);
+
+
+}
+
+
+void
+AudioRtpRTX::receiveSessionForSpkr (int& countTime)
+{
+
+    if (_ca == 0) {
+        return;
+    }
+
+    if (!_audiolayer) {
+        _debug (" !ARTP: No audiolayer available for SPEAKER\n");
+        return;
+    }
+
+    if (!_audiocodec) {
+        _debug (" !ARTP: No audiocodec available for SPEAKER\n");
+        return;
+    }
+
+    const ost::AppDataUnit* adu = NULL;
+
+    // int is_waiting = _session->isWaiting();
+
+    // if (is_waiting != 0)
+    adu = _session->getData (_session->getFirstTimestamp());
+    // else
+    //   return;
+
+    
+
+    if (adu == NULL)
+        return;
+
+    unsigned char* spkrData  = (unsigned char*) adu->getData(); // data in char
+
+    unsigned int size = adu->getSize(); // size in char
+
+    processDataDecode (spkrData, size, countTime);
+
+    if (adu != NULL)
+    {
+        delete adu;
+	adu = NULL;
+    }
+
+}
+
+
+int
+AudioRtpRTX::reSampleData (SFLDataFormat *input, SFLDataFormat *output, int sampleRate_codec, int nbSamples, int status)
+{
+    if (status==UP_SAMPLING) {
+        return converter->upsampleData (input, output, sampleRate_codec , _layerSampleRate , nbSamples);
+    } else if (status==DOWN_SAMPLING) {
+        return converter->downsampleData (micData , micDataConverted , sampleRate_codec , _layerSampleRate , nbSamples);
+    } else
+
+        return 0;
+}
+
+
+
+void
+AudioRtpRTX::run ()
+{
+
+    int sessionWaiting;
+
+    initBuffers();
+    initAudioRtpSession();
+    setRtpSessionRemoteIp();
+    setRtpSessionMedia();
+
+    int timestep = _codecFrameSize;
+
+    int countTime = 0; // for receive
+
+    int threadSleep = 0;
+
+    if (_codecSampleRate != 0)
+        threadSleep = (_codecFrameSize * 1000) / _codecSampleRate;
+    else
+        threadSleep = _layerFrameSize;
+
+    TimerPort::setTimer (threadSleep);
+
+    _audiolayer->startStream();
+
+    _audiolayer->getMainBuffer()->flush(_ca->getCallId());
+
+    _session->startRunning();
+
+    int timestamp = _session->getCurrentTimestamp(); // for mic
+
+    _debug ("- ARTP Action: Start call %s\n",_ca->getCallId().c_str());
+
+    while (!testCancel()) {
+
+
+	// _debug("Main while loop for call: %s\n", _ca->getCallId().c_str());
+        // Send session
+        sessionWaiting = _session->isWaiting();
+
+        sendSessionFromMic (timestamp);
+        timestamp += timestep;
+        // timestamp = _session->getCurrentTimestamp();
+
+        // Recv session
+        receiveSessionForSpkr (countTime);
+
+        // Let's wait for the next transmit cycle
+
+	
+        if (sessionWaiting == 1) {
+            // Record mic and speaker during conversation
+            _ca->recAudio.recData (spkrDataConverted,micData,_nSamplesSpkr,_nSamplesMic);
+        } else {
+            // Record mic only while leaving a message
+            _ca->recAudio.recData (micData,_nSamplesMic);
+        }
+	
+
+        // Let's wait for the next transmit cycle
+        Thread::sleep (TimerPort::getTimer());
+	
+
+        // TimerPort::incTimer(20); // 'frameSize' ms
+        TimerPort::incTimer (threadSleep);
+	
+    }
+
+    // _audiolayer->stopStream();
+    _debug ("- ARTP Action: Stop call %s\n",_ca->getCallId().c_str());
+
+
+}
+
+
+// EOF
diff --git a/sflphone-common/src/audio/audiortp.h b/sflphone-common/src/audio/audiortp.h
new file mode 100644
index 0000000000000000000000000000000000000000..f9dc1671a9297b15cd79bab4a537b456340a370d
--- /dev/null
+++ b/sflphone-common/src/audio/audiortp.h
@@ -0,0 +1,299 @@
+/*
+ *  Copyright (C) 2004-2008 Savoir-Faire Linux inc.
+ *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
+ *  Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com>
+ *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
+ *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
+ *  Author: Laurielle Lea <laurielle.lea@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.
+ */
+
+#ifndef __AUDIO_RTP_H__
+#define __AUDIO_RTP_H__
+
+#include <cstdio>
+#include <cstdlib>
+#include <iostream>
+#include <ccrtp/rtp.h>
+#include <cc++/numbers.h>
+
+#include "../global.h"
+// #include "plug-in/audiorecorder/audiorecord.h"
+#include "../samplerateconverter.h"
+#include "codecDescriptor.h"
+
+#include <fstream>
+
+#define UP_SAMPLING 0
+#define DOWN_SAMPLING 1
+
+
+
+class AudioRtpException: public std::exception
+{
+  virtual const char* what() const throw()
+  {
+    return "AudioRtpException occured";
+  }
+};
+
+
+/**
+ * @file audiortp.h
+ * @brief Manage the real-time data transport in a SIP call
+ */
+
+
+class SIPCall;
+
+///////////////////////////////////////////////////////////////////////////////
+// Two pair of sockets
+///////////////////////////////////////////////////////////////////////////////
+class AudioRtpRTX : public ost::Thread, public ost::TimerPort {
+  public:
+    /**
+     * Constructor
+     * @param sipcall The pointer on the SIP call
+     * @param sym     Tells whether or not the voip links are symmetric
+     */
+    AudioRtpRTX (SIPCall* sipcall, bool sym);
+
+    /**
+     * Destructor
+     */
+    ~AudioRtpRTX();
+
+    /** For incoming call notification */ 
+    ost::Time *time;
+
+    /** Thread associated method */    
+    virtual void run ();
+
+    /** A SIP call */
+    SIPCall* _ca;
+
+    /**
+     * Update RTP session media info as received from SDP negociation 
+     */
+    void setRtpSessionMedia(void);
+
+    /**
+     * Update RTP session remote ip destination as received from sip transaction 
+     */
+    void setRtpSessionRemoteIp(void); 
+
+    
+    friend class RtpTest;
+
+  private:
+
+    // copy constructor
+    AudioRtpRTX(const AudioRtpRTX& rh);
+  
+    // assignment operator
+    AudioRtpRTX& operator=(const AudioRtpRTX& rh);
+
+    /** RTP session to send data */
+    ost::RTPSession *_sessionSend;
+    
+    /** RTP session to receive data */
+    ost::RTPSession *_sessionRecv;
+
+    /** RTP symmetric session ( receive and send data in the same session ) */
+    ost::SymmetricRTPSession *_session;
+
+    /** Semaphore */
+    // ost::Semaphore _start;
+
+    /** Is the session symmetric or not */
+    bool _sym;
+
+    /** Mic-data related buffers */
+    SFLDataFormat* micData;
+    SFLDataFormat* micDataConverted;
+    unsigned char* micDataEncoded;
+
+    /** Speaker-data related buffers */
+    SFLDataFormat* spkrDataDecoded;
+    SFLDataFormat* spkrDataConverted;
+
+    /** Sample rate converter object */
+    SamplerateConverter* converter;
+
+    /** audio layer */
+    AudioLayer *_audiolayer;
+
+    /** Variables to process audio stream: sample rate for playing sound (typically 44100HZ) */
+    int _layerSampleRate;  
+
+    /** Sample rate of the codec we use to encode and decode (most of time 8000HZ) */
+    int _codecSampleRate;
+
+    /** Length of the sound frame we capture in ms (typically 20ms) */
+    int _layerFrameSize; 
+
+    /** Codecs frame size in samples (20 ms => 882 at 44.1kHz)
+        The exact value is stored in the codec */
+    int _codecFrameSize;
+
+    /** Speaker buffer length in samples once the data are resampled
+     *  (used for mixing and recording)
+     */
+    int _nSamplesSpkr; 
+
+    /** Mic buffer length in samples once the data are resampled
+     *  (used for mixing and recording)
+     */
+    int _nSamplesMic;
+    
+    /**
+     * Maximum number of sample for audio buffers (mic and spkr)
+     */
+    int nbSamplesMax;
+
+
+    
+    bool _payloadIsSet;
+    bool _remoteIpIsSet;
+    
+    /**
+     * Init the RTP session. Create either symmetric or double sessions to manage data transport
+     * Set the payloads according to the manager preferences
+     */
+    void initAudioRtpSession(void);
+    
+    /**
+     * Return the lenth the codec frame in ms 
+     */
+    float computeCodecFrameSize(int codecSamplePerFrame, int codecClockRate);
+
+    /**
+     * Compute nb of byte to get coresponding to X ms at audio layer frame size (44.1 khz) 
+     */
+    int computeNbByteAudioLayer(float codecFrameSize);
+
+
+    int processDataEncode();
+
+
+    void processDataDecode(unsigned char* spkrData, unsigned int size, int& countTime);
+
+
+    /**
+     * Get the data from the mic, encode it and send it through the RTP session
+     * @param timestamp	To manage time and synchronizing
+     */ 		 	
+    void sendSessionFromMic(int timestamp);
+    
+    /**
+     * Get the data from the RTP packets, decode it and send it to the sound card
+     * @param countTime	To manage time and synchronizing
+     */		 	
+    void receiveSessionForSpkr(int& countTime);
+
+    /**
+     * Init the buffers used for processing sound data
+     */ 
+    void initBuffers(void);
+
+    /**
+     * Call the appropriate function, up or downsampling
+     * @param sampleRate_codec	The sample rate of the codec selected to encode/decode the data
+     * @param nbSamples		Number of samples to process
+     * @param status  Type of resampling
+     *		      UPSAMPLING
+     *		      DOWNSAMPLING
+     * @return int The number of samples after process
+     */ 
+    int reSampleData(SFLDataFormat *input, SFLDataFormat *output,int sampleRate_codec, int nbSamples, int status);
+    
+    /** The audio codec used during the session */
+    AudioCodec *_audiocodec;
+    // AudioCodec _audioCodecInstance;
+
+    /** Mutex */
+    ost::Mutex _rtpRtxMutex;
+
+  public:
+
+    std::fstream *rtp_input_rec;
+    std::fstream *rtp_output_rec;
+
+    static int count_rtp;
+
+   
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Main class rtp
+///////////////////////////////////////////////////////////////////////////////
+class AudioRtp {
+  public:
+    /**
+     * Constructor
+     */
+    AudioRtp();
+    
+    /**
+     * Destructor
+     */
+    ~AudioRtp();
+
+    /**
+     * Create a brand new RTP session by calling the AudioRtpRTX constructor
+     * @param ca A pointer on a SIP call
+     */
+    void createNewSession (SIPCall *ca);
+    
+    /**
+     * Start the AudioRtpRTX thread created with createNewSession
+     */
+    int start(void);
+    
+    /**
+     * Close a RTP session and kills the remaining threads
+     */
+    bool closeRtpSession( void );
+
+    /**
+     * Start recording
+     */
+    // void setRecording ();
+
+    friend class RtpTest;
+
+    /**
+     * 
+     */ 
+    inline AudioRtpRTX * getAudioRtpRtxThread(void) { return _RTXThread; }
+  private:
+    // copy constructor
+    AudioRtp(const AudioRtp& rh);
+  
+    // assignment operator
+    AudioRtp& operator=(const AudioRtp& rh);
+
+    /** The RTP thread */
+    AudioRtpRTX* _RTXThread;
+
+    /** Symmetric session or not */
+    bool _symmetric;
+
+    /** Mutex */
+    ost::Mutex _rtpMutex;
+
+};
+
+#endif // __AUDIO_RTP_H__
diff --git a/sflphone-common/src/audio/audiortp/AudioRtpSession.h b/sflphone-common/src/audio/audiortp/AudioRtpSession.h
index 244ba129967196c4ca738dbf2d74a402b52c7015..6fb54b53ca91b66f03de2cee764f54ecef6a391b 100644
--- a/sflphone-common/src/audio/audiortp/AudioRtpSession.h
+++ b/sflphone-common/src/audio/audiortp/AudioRtpSession.h
@@ -199,6 +199,9 @@ namespace sfl {
             throw;
         }
 
+	_debug("Unbind audio RTP stream for call id %i\n", _ca->getCallId().c_str());
+	_audiolayer->getMainBuffer()->unBindAll(_ca->getCallId());
+
         delete [] _micData;
         delete [] _micDataConverted;
         delete [] _micDataEncoded;
@@ -219,6 +222,8 @@ namespace sfl {
         _micDataEncoded = new unsigned char[nbSamplesMax];
         _spkrDataConverted = new SFLDataFormat[nbSamplesMax];
         _spkrDataDecoded = new SFLDataFormat[nbSamplesMax];
+
+	_manager->addStream(_ca->getCallId());
     }
     
     template <typename D>
@@ -237,8 +242,10 @@ namespace sfl {
     void AudioRtpSession<D>::setSessionMedia(void)
     {
         assert(_ca);
-        
-        _audiocodec = _ca->getLocalSDP()->get_session_media ();
+
+	AudioCodecType pl = (AudioCodecType)_ca->getLocalSDP()->get_session_media()->getPayload();
+	_audiocodec = _manager->getCodecDescriptorMap().instantiateCodec(pl);
+
         if (_audiocodec == NULL) {
             _debug ("No audiocodec, can't init RTP media\n");
             throw AudioRtpSessionException();
@@ -299,7 +306,7 @@ namespace sfl {
         int maxBytesToGet = computeNbByteAudioLayer (fixed_codec_framesize);
 
         // available bytes inside ringbuffer
-        int availBytesFromMic = _audiolayer->canGetMic();
+        int availBytesFromMic = _audiolayer->getMainBuffer()->availForGet(_ca->getCallId());
 
         // set available byte to maxByteToGet
         int bytesAvail = (availBytesFromMic < maxBytesToGet) ? availBytesFromMic : maxBytesToGet;
@@ -308,7 +315,7 @@ namespace sfl {
             return 0;
 
         // Get bytes from micRingBuffer to data_from_mic
-        int nbSample = _audiolayer->getMic (_micData , bytesAvail) / sizeof (SFLDataFormat);
+        int nbSample = _audiolayer->getMainBuffer()->getData(_micData , bytesAvail, 100, _ca->getCallId()) / sizeof (SFLDataFormat);
 
         // nb bytes to be sent over RTP
         int compSize = 0;
@@ -347,14 +354,14 @@ namespace sfl {
                 _nSamplesSpkr = nbSample;
 
                 // put data in audio layer, size in byte
-                _audiolayer->putMain (_spkrDataConverted, nbSample * sizeof (SFLDataFormat));
+		_audiolayer->getMainBuffer()->putData (_spkrDataConverted, nbSample * sizeof (SFLDataFormat), 100, _ca->getCallId());
 
             } else {
                 // Store the number of samples for recording
                 _nSamplesSpkr = nbSample;
 
                 // put data in audio layer, size in byte
-                _audiolayer->putMain (_spkrDataDecoded, nbSample * sizeof (SFLDataFormat));
+                _audiolayer->getMainBuffer()->putData (_spkrDataConverted, nbSample * sizeof (SFLDataFormat), 100, _ca->getCallId());
             }
 
             // Notify (with a beep) an incoming call when there is already a call
diff --git a/sflphone-common/src/audio/codecs/Makefile.am b/sflphone-common/src/audio/codecs/Makefile.am
index b294d3e779499f1594455be3795eaa817d101b08..230ee7bbc0dce19ecfd5f02f18236afefb84965d 100644
--- a/sflphone-common/src/audio/codecs/Makefile.am
+++ b/sflphone-common/src/audio/codecs/Makefile.am
@@ -110,7 +110,7 @@ uninstall-libcodec_speex_wb_so:
 	rm -f $(sflcodecdir)/libcodec_speex_wb.so
 uninstall-libcodec_speex_ub_so:
 	rm -f $(sflcodecdir)/libcodec_speex_ub.so
+uninstall-libcodec_celt_so:
+	rm -f $(sflcodecdir)/libcodec_celt.so
 	rm -rf $(sflcodecdir)
-uninstall-libcodec_celt_so: libcodec_celt.so
-	$(INSTALL_PROGRAM)  libcodec_celt.so $(sflcodecdir)
 
diff --git a/sflphone-common/src/audio/codecs/codecDescriptor.cpp b/sflphone-common/src/audio/codecs/codecDescriptor.cpp
index d0fa1da9274a5325ab164a90cfe3aa0f89ce691d..edf8586f2198f823faae914c32033d29d7b24e57 100644
--- a/sflphone-common/src/audio/codecs/codecDescriptor.cpp
+++ b/sflphone-common/src/audio/codecs/codecDescriptor.cpp
@@ -3,6 +3,7 @@
  *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
  *  Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com>
  *  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
@@ -125,7 +126,7 @@ CodecDescriptor::addCodec (AudioCodecType payload UNUSED)
 double
 CodecDescriptor::getBitRate (AudioCodecType payload)
 {
-    CodecsMap::iterator iter = _CodecsMap.find (payload);
+    CodecsMap::iterator iter = _CodecsMap.find(payload);
 
     if (iter!=_CodecsMap.end())
         return (iter->second->getBitRate());
@@ -250,13 +251,14 @@ CodecDescriptor::loadCodec (std::string path)
 
     AudioCodec* a = createCodec();
 
-    p = CodecHandlePointer (a, codecHandle);
+    p = CodecHandlePointer(a, codecHandle);
 
-    _CodecInMemory.push_back (p);
+    _CodecInMemory.push_back(p);
 
     return a;
 }
 
+
 void
 CodecDescriptor::unloadCodec (CodecHandlePointer p)
 {
@@ -272,6 +274,34 @@ CodecDescriptor::unloadCodec (CodecHandlePointer p)
     dlclose (p.second);
 }
 
+AudioCodec*
+CodecDescriptor::instantiateCodec(AudioCodecType payload)
+{
+
+    using std::cerr;
+
+    std::vector< CodecHandlePointer >::iterator iter = _CodecInMemory.begin();
+    while(iter != _CodecInMemory.end())
+    {
+	if (iter->first->getPayload() == payload)
+	{
+	    create_t* createCodec = (create_t*) dlsym (iter->second , "create");
+
+	    if (dlerror())
+		cerr << dlerror() << '\n';
+
+	    AudioCodec* a = createCodec();
+
+	    return a;
+
+	}
+
+	iter++;
+    }
+
+    return NULL;
+}
+
 AudioCodec*
 CodecDescriptor::getFirstCodecAvailable (void)
 {
diff --git a/sflphone-common/src/audio/codecs/codecDescriptor.h b/sflphone-common/src/audio/codecs/codecDescriptor.h
index 3462afbcd1f73e1eb7ec7d735aeebe0814b97cb9..9ca8773a4c8986c4ba015caafafb1963b0d0b98f 100644
--- a/sflphone-common/src/audio/codecs/codecDescriptor.h
+++ b/sflphone-common/src/audio/codecs/codecDescriptor.h
@@ -193,6 +193,12 @@ class CodecDescriptor {
      */
     AudioCodec* getFirstCodecAvailable( void );
 
+    /**
+     * Instantiate a codec, used in AudioRTP to get an instance of Codec per call
+     * @param CodecHandlePointer	The map containing the pointer on the object and the pointer on the handle function
+     */
+    AudioCodec* instantiateCodec(AudioCodecType payload);
+
   private:
 
     /**
diff --git a/sflphone-common/src/audio/codecs/g722.cpp b/sflphone-common/src/audio/codecs/g722.cpp
index a95a0a865304dfcd0b72eb46579fe4219a04e118..5280fa1f337869b0a9e4ab49b74fe660d4bcd236 100644
--- a/sflphone-common/src/audio/codecs/g722.cpp
+++ b/sflphone-common/src/audio/codecs/g722.cpp
@@ -40,7 +40,7 @@ class G722 : public AudioCodec
         G722 (int payload=9)
                 : AudioCodec (payload, "G722") {
             _clockRate = 16000;
-            _frameSize = 320; // samples, 10 ms at 16kHz
+            _frameSize = 320; // samples, 20 ms at 16kHz
             _channel   = 1;
             _bitrate = 64;
             _bandwidth = 80;
diff --git a/sflphone-common/src/audio/mainbuffer.cpp b/sflphone-common/src/audio/mainbuffer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fb88bc5a6f2d41f220eb52708a35a72edcd0333d
--- /dev/null
+++ b/sflphone-common/src/audio/mainbuffer.cpp
@@ -0,0 +1,583 @@
+/*
+ *  Copyright (C) 2009 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.
+ */
+
+#include "mainbuffer.h"
+
+MainBuffer::MainBuffer()
+{
+    mixBuffer = new SFLDataFormat[STATIC_BUFSIZE];
+}
+
+
+MainBuffer::~MainBuffer()
+{
+
+    delete mixBuffer;
+    mixBuffer = NULL;
+}
+
+CallIDSet* MainBuffer::getCallIDSet(CallID call_id)
+{
+
+    // _debug("MainBuffer::getCallIDSet\n");
+
+    CallIDMap::iterator iter = _callIDMap.find(call_id);
+    if (iter == _callIDMap.end())
+    {
+	// _debug("CallIDSet with ID: \"%s\" doesn't exist! \n", call_id.c_str());
+	return NULL;
+    }
+    else
+	return iter->second;
+
+}
+
+bool MainBuffer::createCallIDSet(CallID set_id)
+{
+    _debug("---- MainBuffer::createCallIDSet %s\n", set_id.c_str());
+    
+    CallIDSet* newCallIDSet = new CallIDSet;
+
+    _callIDMap.insert(pair<CallID, CallIDSet*>(set_id, newCallIDSet));
+    // _callIDMap[set_id] = new CallIDSet;
+
+    return true;
+
+}
+
+bool MainBuffer::removeCallIDSet(CallID set_id)
+{
+
+    _debug("---- MainBuffer::removeCallIDSet %s\n", set_id.c_str());
+
+
+    CallIDSet* callid_set = getCallIDSet(set_id);
+
+    if(callid_set != NULL)
+    {
+        if (_callIDMap.erase(set_id) != 0)
+	{
+	    _debug("          callid set %s erased!\n", set_id.c_str());
+	    return true;
+	}
+        else
+	{
+	    _debug("          error while removing callid set %s!\n", set_id.c_str());
+	    return false;
+	}
+    }
+    else
+    {
+	_debug("          callid set %s does not exist!\n", set_id.c_str());
+	return false;
+    }
+
+}
+
+void MainBuffer::addCallIDtoSet(CallID set_id, CallID call_id)
+{
+    _debug("---- MainBuffer::addCallIDtoSet %s in %s\n", set_id.c_str(), call_id.c_str());
+
+    CallIDSet* callid_set = getCallIDSet(set_id);
+    callid_set->insert(call_id);
+
+}
+
+void MainBuffer::removeCallIDfromSet(CallID set_id, CallID call_id)
+{
+    _debug("---- MainBuffer::removeCallIDfromSet element %s from %s\n", call_id.c_str(), set_id.c_str());
+
+    CallIDSet* callid_set = getCallIDSet(set_id);
+    if(callid_set != NULL)
+    {
+	if( callid_set->erase(call_id) != 0)
+	{
+	    _debug("          callid %s erased from set %s!\n", call_id.c_str(), set_id.c_str());
+	}
+	else
+	{
+	    _debug("          error while removing callid %s from set %s!\n", call_id.c_str(), set_id.c_str());
+	}
+    }
+    else
+    {
+	    _debug("          callid set %s does not exist!\n", set_id.c_str());
+    }
+}
+
+
+RingBuffer* MainBuffer::getRingBuffer(CallID call_id)
+{
+    
+    RingBufferMap::iterator iter = _ringBufferMap.find(call_id);
+    if (iter == _ringBufferMap.end())
+    {
+	// _debug("ringBuffer with ID: \"%s\" doesn't exist! \n", call_id.c_str());
+	return NULL;
+    }
+    else
+	return iter->second;
+}
+
+
+RingBuffer* MainBuffer::createRingBuffer(CallID call_id)
+{
+
+    _debug("---- MainBuffer::createRingBuffer callid %s\n", call_id.c_str());
+
+    RingBuffer* newRingBuffer = new RingBuffer(SIZEBUF, call_id);
+
+    _ringBufferMap.insert(pair<CallID, RingBuffer*>(call_id, newRingBuffer));
+
+    return newRingBuffer;
+}
+
+
+bool MainBuffer::removeRingBuffer(CallID call_id)
+{
+
+    _debug("---- MainBuffer::removeRingBuffer call_id %s\n", call_id.c_str());
+
+    RingBuffer* ring_buffer = getRingBuffer(call_id);
+    if(ring_buffer != NULL)
+    {
+        if (_ringBufferMap.erase(call_id) != 0)
+	{
+	    _debug("          ringbuffer %s removed!\n", call_id.c_str());
+            return true;
+	}
+        else
+	{
+	    _debug("          error while deleting ringbuffer %s!\n", call_id.c_str());
+	    return false;
+	}
+    }
+    else
+    {
+	_debug("          error ringbuffer %s does not exist!\n", call_id.c_str());
+	return true;
+    }
+}
+
+
+void MainBuffer::bindCallID(CallID call_id1, CallID call_id2)
+{
+
+    ost::MutexLock guard (_mutex);
+
+    _debug("---- MainBuffer::bindCallID %s and callid %s\n", call_id1.c_str(), call_id2.c_str());
+
+    RingBuffer* ring_buffer;
+    CallIDSet* callid_set;
+
+    if((ring_buffer = getRingBuffer(call_id1)) == NULL)
+	createRingBuffer(call_id1);
+
+    if((callid_set = getCallIDSet(call_id1)) == NULL)
+	createCallIDSet(call_id1);
+
+    if((ring_buffer = getRingBuffer(call_id2)) == NULL)
+	createRingBuffer(call_id2);
+
+    if((callid_set = getCallIDSet(call_id2)) == NULL)
+	createCallIDSet(call_id2);
+
+    getRingBuffer(call_id1)->createReadPointer(call_id2);
+    getRingBuffer(call_id2)->createReadPointer(call_id1);
+
+    addCallIDtoSet(call_id1, call_id2);
+    addCallIDtoSet(call_id2, call_id1);
+
+}
+
+
+void MainBuffer::unBindCallID(CallID call_id1, CallID call_id2)
+{
+
+    ost::MutexLock guard (_mutex);
+
+    _debug("---- MainBuffer::unBindCallID %s and callid %s\n", call_id1.c_str(), call_id2.c_str());
+
+    removeCallIDfromSet(call_id1, call_id2);
+    removeCallIDfromSet(call_id2, call_id1);
+
+    RingBuffer* ringbuffer;
+
+    ringbuffer = getRingBuffer(call_id2);
+    if(ringbuffer != NULL)
+    {
+
+	ringbuffer->removeReadPointer(call_id1);
+
+	if(ringbuffer->getNbReadPointer() == 0)
+        {
+	    removeCallIDSet(call_id2);
+	    removeRingBuffer(call_id2);
+        }
+
+    }
+
+    ringbuffer = getRingBuffer(call_id1);
+    if(ringbuffer != NULL)
+    {
+	ringbuffer->removeReadPointer(call_id2);
+
+        if(ringbuffer->getNbReadPointer() == 0)
+        {
+	    removeCallIDSet(call_id1);
+	    removeRingBuffer(call_id1);
+        }
+    }
+
+
+}
+
+void MainBuffer::unBindAll(CallID call_id)
+{
+
+    ost::MutexLock guard (_mutex);
+
+    CallIDSet* callid_set = getCallIDSet(call_id);
+
+    if (callid_set == NULL)
+	return;
+
+    if (callid_set->empty())
+	return;
+    
+    CallIDSet temp_set = *callid_set;
+ 
+    CallIDSet::iterator iter_set = temp_set.begin();
+
+    _debug("MainBuffer::unBindAll\n");
+    while (iter_set != temp_set.end())
+    {
+	CallID call_id_in_set = *iter_set;
+	unBindCallID(call_id, call_id_in_set);
+
+	iter_set++;
+    }
+
+}
+
+
+int MainBuffer::putData(void *buffer, int toCopy, unsigned short volume, CallID call_id)
+{
+
+    ost::MutexLock guard (_mutex);
+
+    RingBuffer* ring_buffer = getRingBuffer(call_id);
+
+    if (ring_buffer == NULL)
+    {
+	// _debug("Input RingBuffer ID: \"%s\" does not exist!\n", call_id.c_str());
+	return 0;
+    }
+
+    int a;
+
+    // ost::MutexLock guard (_mutex);
+    a = ring_buffer->AvailForPut();
+
+    if (a >= toCopy) {
+        return ring_buffer->Put (buffer, toCopy, volume);
+    } else {
+        // _debug ("Chopping sound, Ouch! RingBuffer full ?\n");
+        return ring_buffer->Put (buffer, a, volume);
+    }
+
+    return 0;
+
+}
+
+int MainBuffer::availForPut(CallID call_id)
+{
+
+    ost::MutexLock guard (_mutex);
+
+    RingBuffer* ringbuffer = getRingBuffer(call_id);
+
+    if (ringbuffer == NULL)
+	return 0;
+    else
+	return ringbuffer->AvailForPut();
+    
+}
+
+
+int MainBuffer::getData(void *buffer, int toCopy, unsigned short volume, CallID call_id)
+{
+    ost::MutexLock guard (_mutex);
+
+    // _debug("MainBuffer::getData by \"%s\", toCopy %i\n",call_id.c_str(), toCopy);
+
+    CallIDSet* callid_set = getCallIDSet(call_id);
+
+    int nbSmplToCopy = toCopy / sizeof(SFLDataFormat);
+
+    if(callid_set == NULL)
+	return 0;
+
+    if(callid_set->empty())
+    {
+	// _debug("CallIDSet with ID: \"%s\" is empty!\n", call_id.c_str());
+	return 0;
+    }
+    
+    if (callid_set->size() == 1)
+    {
+	// _debug("callid_set->size() == %i\n", callid_set->size());
+	CallIDSet::iterator iter_id = callid_set->begin();
+
+	if (iter_id != callid_set->end())
+	{
+	    // _debug("MainBuffer::getData in buffer %s by %s \n", (*iter_id).c_str(), call_id.c_str());
+	    return getDataByID(buffer, toCopy, volume, *iter_id, call_id);
+	}
+	else 
+	    return 0;
+    }
+    else
+    {
+
+	// _debug("callid_set->size() == %i\n", callid_set->size());
+
+	for (int k = 0; k < nbSmplToCopy; k++)
+	{
+	    ((SFLDataFormat*)(buffer))[k] = 0;
+	}
+
+	int size;
+	// _debug("CallIDSet with ID: \"%s\" is a conference!\n", call_id.c_str());
+	CallIDSet::iterator iter_id;
+	for(iter_id = callid_set->begin(); iter_id != callid_set->end(); iter_id++)
+	{
+	    // _debug("MainBuffer::getData in buffer %s by %s \n", (*iter_id).c_str(), call_id.c_str());
+	    
+	    size = getDataByID(mixBuffer, toCopy, volume, (CallID)(*iter_id), call_id);
+	    // _debug("MainBuffer::getData: tocopy %i, size: %i \n", toCopy, size);
+	    
+	    if (size > 0)
+	    {
+	        for (int k = 0; k < nbSmplToCopy; k++)
+	        {
+		    ((SFLDataFormat*)(buffer))[k] += mixBuffer[k];
+	        }
+	    }
+	}
+	
+	// _debug("MainBuffer::getData  data mixed successfully\n");
+
+	return size;
+    }
+}
+
+
+int MainBuffer::getDataByID(void *buffer, int toCopy, unsigned short volume, CallID call_id, CallID reader_id)
+{
+
+    // _debug("MainBuffer::getDataByID in buffer %s by %s \n", call_id.c_str(), reader_id.c_str());
+
+    RingBuffer* ring_buffer = getRingBuffer(call_id);
+
+    if (ring_buffer == NULL)
+    {
+	// _debug("Output RingBuffer ID: \"%s\" does not exist!\n", call_id.c_str());
+	return 0;
+    }
+
+    return ring_buffer->Get (buffer, toCopy, volume, reader_id);
+
+    return 0;
+
+}
+
+
+int MainBuffer::availForGet(CallID call_id)
+{
+
+    ost::MutexLock guard (_mutex);
+
+    CallIDSet* callid_set = getCallIDSet(call_id);
+
+    if (callid_set == NULL)
+	return 0;
+
+    if (callid_set->empty())
+    {
+	_debug("CallIDSet with ID: \"%s\" is empty!\n", call_id.c_str());
+	return 0;
+    }
+
+    if (callid_set->size() == 1)
+    {
+	CallIDSet::iterator iter_id = callid_set->begin();
+	// _debug("MainBuffer::availForGet availForGetByID(%s,%s)\n", (*iter_id).c_str(), call_id.c_str());
+	if((call_id != default_id) && (*iter_id == call_id))
+	{
+	    _debug("**********************************************************************\n");
+	    _debug("Error an RTP session ring buffer is not supposed to have a readpointer on tiself\n");
+	    _debug("This problem should not occur since we have %i element\n", callid_set->size());
+	}
+	// else
+	return availForGetByID(*iter_id, call_id);
+    }
+    else
+    {
+	// _debug("CallIDSet with ID: \"%s\" is a conference!\n", call_id.c_str());
+	int avail_bytes = 99999;
+	int nb_bytes;
+	CallIDSet::iterator iter_id = callid_set->begin();
+	for(iter_id = callid_set->begin(); iter_id != callid_set->end(); iter_id++)
+	{
+	    nb_bytes = availForGetByID(*iter_id, call_id);
+	    if (nb_bytes < avail_bytes)
+		avail_bytes = nb_bytes;
+	}
+	return avail_bytes;
+    }
+
+}
+
+
+int MainBuffer::availForGetByID(CallID call_id, CallID reader_id)
+{
+
+    if((call_id != default_id) && (reader_id == call_id))
+    {
+	_debug("**********************************************************************\n");
+	_debug("Error an RTP session ring buffer is not supposed to have a readpointer on tiself\n");
+    }
+
+    RingBuffer* ringbuffer = getRingBuffer(call_id);
+    
+    if (ringbuffer == NULL)
+    {
+	_debug("Error: ring buffer does not exist\n");
+	return 0;
+    }
+    else
+	return ringbuffer->AvailForGet(reader_id);
+
+}
+
+
+int MainBuffer::discard(int toDiscard, CallID call_id)
+{
+    // _debug("MainBuffer::discard\n");
+
+    ost::MutexLock guard (_mutex);
+
+    CallIDSet* callid_set = getCallIDSet(call_id);
+
+    if (callid_set == NULL)
+	return 0;
+
+    if(callid_set->empty())
+    {
+	// _debug("CallIDSet with ID: \"%s\" is empty!\n", call_id.c_str());
+	return 0;
+    }
+
+
+    if (callid_set->size() == 1)
+    {
+	CallIDSet::iterator iter_id = callid_set->begin();
+	// _debug("Discard Data in \"%s\" RingBuffer for \"%s\" ReaderPointer\n",(*iter_id).c_str(),call_id.c_str());
+	return discardByID(toDiscard, *iter_id, call_id);
+    }
+    else
+    {
+	// _debug("CallIDSet with ID: \"%s\" is a conference!\n", call_id.c_str());
+	CallIDSet::iterator iter_id;
+	for(iter_id = callid_set->begin(); iter_id != callid_set->end(); iter_id++)
+	{
+	    discardByID(toDiscard, *iter_id, call_id);
+	}
+	return toDiscard;
+    }
+
+}
+
+
+int MainBuffer::discardByID(int toDiscard, CallID call_id, CallID reader_id)
+{
+
+    RingBuffer* ringbuffer = getRingBuffer(call_id);
+    
+    if(ringbuffer == NULL)
+	return 0;
+    else
+	return ringbuffer->Discard(toDiscard, reader_id);
+
+}
+
+
+
+void MainBuffer::flush(CallID call_id)
+{
+    ost::MutexLock guard (_mutex);
+
+    // _debug("MainBuffer::flush\n");
+
+    CallIDSet* callid_set = getCallIDSet(call_id);
+
+    if (callid_set == NULL)
+	return;
+
+    if(callid_set->empty())
+    {
+	// _debug("CallIDSet with ID: \"%s\" is empty!\n", call_id.c_str());
+    }
+
+    if (callid_set->size() == 1)
+    {
+	CallIDSet::iterator iter_id = callid_set->begin();
+	flushByID(*iter_id, call_id);
+    }
+    else
+    {
+	// _debug("CallIDSet with ID: \"%s\" is a conference!\n", call_id.c_str());
+	CallIDSet::iterator iter_id;
+	for(iter_id = callid_set->begin(); iter_id != callid_set->end(); iter_id++)
+	{
+	    flushByID(*iter_id, call_id);
+	}
+    }
+
+}
+
+void MainBuffer::flushDefault()
+{
+    ost::MutexLock guard (_mutex);
+
+    flushByID(default_id, default_id);
+
+}
+
+
+void MainBuffer::flushByID(CallID call_id, CallID reader_id)
+{
+
+    RingBuffer* ringbuffer = getRingBuffer(call_id);
+
+    if(ringbuffer != NULL)
+	ringbuffer->flush(reader_id);
+}
diff --git a/sflphone-common/src/audio/mainbuffer.h b/sflphone-common/src/audio/mainbuffer.h
new file mode 100644
index 0000000000000000000000000000000000000000..ed122e207461183a114a59920c0281791e94f5d0
--- /dev/null
+++ b/sflphone-common/src/audio/mainbuffer.h
@@ -0,0 +1,107 @@
+/*
+ *  Copyright (C) 2004-2005 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.
+ */
+
+#ifndef __MAIN_BUFFER__
+#define __MAIN_BUFFER__
+
+#include <map>
+#include <set>
+#include <cc++/thread.h> // for ost::Mutex
+
+#include "../global.h"
+#include "../call.h"
+#include "ringbuffer.h"
+
+
+
+typedef std::map<CallID, RingBuffer*> RingBufferMap;
+
+typedef std::set<CallID> CallIDSet;
+
+typedef std::map<CallID, CallIDSet*> CallIDMap;
+
+class MainBuffer {
+
+public:
+
+        MainBuffer();
+
+        ~MainBuffer();
+
+	CallIDSet* getCallIDSet(CallID call_id);
+
+	bool createCallIDSet(CallID set_id);
+
+	bool removeCallIDSet(CallID set_id);
+
+	void addCallIDtoSet(CallID set_id, CallID call_id);
+
+	void removeCallIDfromSet(CallID set_id, CallID call_id);
+
+	RingBuffer* createRingBuffer(CallID call_id);
+
+	bool removeRingBuffer(CallID call_id);
+
+	void bindCallID(CallID call_id1, CallID call_id2 = default_id);
+
+	void unBindCallID(CallID call_id1, CallID call_id2 = default_id);
+
+	void unBindAll(CallID call_id);
+
+	int putData(void *buffer, int toCopy, unsigned short volume = 100, CallID call_id = default_id);
+
+	int getData(void *buffer, int toCopy, unsigned short volume = 100, CallID call_id = default_id);
+
+	int availForPut(CallID call_id = default_id);
+
+	int availForGet(CallID call_id = default_id);
+
+	int discard(int toDiscard, CallID call_id = default_id);
+
+	void flush(CallID call_id = default_id);
+
+	void flushDefault();
+
+    private:
+
+	RingBuffer* getRingBuffer(CallID call_id);
+
+	int getDataByID(void *buffer, int toCopy, unsigned short volume, CallID call_id, CallID reader_id);
+
+	int availForGetByID(CallID call_id, CallID reader_id);
+
+	int discardByID(int toDiscard, CallID call_id, CallID reader_id);
+
+	void flushByID(CallID call_id, CallID reader_id);
+
+	RingBufferMap _ringBufferMap;
+
+	CallIDMap _callIDMap;
+
+	SFLDataFormat* mixBuffer;
+
+	ost::Mutex _mutex;
+
+    public:
+
+	friend class MainBufferTest;
+};
+
+#endif
diff --git a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp
index fb576f882c295c98a736deeec80e7761c1f1c95c..bc83dcc6261d7fe3e9eb306a15f93c6c13483ba9 100644
--- a/sflphone-common/src/audio/pulseaudio/pulselayer.cpp
+++ b/sflphone-common/src/audio/pulseaudio/pulselayer.cpp
@@ -40,6 +40,7 @@ PulseLayer::PulseLayer (ManagerImpl* manager)
 {
     _debug ("PulseLayer::Pulse audio constructor: Create context\n");
 
+    _urgentRingBuffer.createReadPointer();
 }
 
 // Destructor
@@ -245,7 +246,7 @@ void PulseLayer::closePlaybackStream (void)
 int PulseLayer::canGetMic()
 {
     if (record)
-        return  _micRingBuffer.AvailForGet();
+        return 0; // _micRingBuffer.AvailForGet();
     else
         return 0;
 }
@@ -253,7 +254,7 @@ int PulseLayer::canGetMic()
 int PulseLayer::getMic (void *buffer, int toCopy)
 {
     if (record) {
-        return _micRingBuffer.Get (buffer, toCopy, 100);
+        return 0; // _micRingBuffer.Get (buffer, toCopy, 100);
     } else
         return 0;
 }
@@ -261,9 +262,10 @@ int PulseLayer::getMic (void *buffer, int toCopy)
 void PulseLayer::startStream (void)
 {
     _debug ("PulseLayer::Start stream\n");
+
     _urgentRingBuffer.flush();
-    _micRingBuffer.flush();
-    _voiceRingBuffer.flush();
+
+    _mainBuffer.flush();
 
     pa_threaded_mainloop_lock (m);
 
@@ -288,9 +290,13 @@ PulseLayer::stopStream (void)
     flushMain();
     flushUrgent();
 
+    pa_threaded_mainloop_lock (m);
+
     pa_stream_cork (playback->pulseStream(), 1, NULL, NULL);
     pa_stream_cork (record->pulseStream(), 1, NULL, NULL);
 
+    pa_threaded_mainloop_unlock (m);
+
     isCorked = true;
 
 }
@@ -349,46 +355,62 @@ void PulseLayer::writeToSpeaker (void)
     urgentAvail = _urgentRingBuffer.AvailForGet();
 
     if (urgentAvail > 0) {
+
         // Urgent data (dtmf, incoming call signal) come first.
         //_debug("Play urgent!: %i\e" , urgentAvail);
         toGet = (urgentAvail < (int) (framesPerBuffer * sizeof (SFLDataFormat))) ? urgentAvail : framesPerBuffer * sizeof (SFLDataFormat);
         out = (SFLDataFormat*) pa_xmalloc (toGet * sizeof (SFLDataFormat));
         _urgentRingBuffer.Get (out, toGet, 100);
-        pa_stream_write (playback->pulseStream() , out , toGet  , pa_xfree, 0 , PA_SEEK_RELATIVE);
+        pa_stream_write (playback->pulseStream(), out, toGet, NULL, 0, PA_SEEK_RELATIVE);
         // Consume the regular one as well (same amount of bytes)
-        _voiceRingBuffer.Discard (toGet);
+        _mainBuffer.discard (toGet);
+
+	pa_xfree(out);
+
     } else {
+
         AudioLoop* tone = _manager->getTelephoneTone();
 
         if (tone != 0) {
+
             toGet = framesPerBuffer;
             out = (SFLDataFormat*) pa_xmalloc (toGet * sizeof (SFLDataFormat));
             tone->getNext (out, toGet , 100);
-            pa_stream_write (playback->pulseStream() , out , toGet  * sizeof (SFLDataFormat)   , pa_xfree, 0 , PA_SEEK_RELATIVE);
+            pa_stream_write (playback->pulseStream(), out, toGet  * sizeof (SFLDataFormat), NULL, 0, PA_SEEK_RELATIVE);
+
+	    pa_xfree (out);
         }
 
         if ( (tone=_manager->getTelephoneFile()) != 0) {
+
             toGet = framesPerBuffer;
             toPlay = ( (int) (toGet * sizeof (SFLDataFormat)) > framesPerBuffer) ? framesPerBuffer : toGet * sizeof (SFLDataFormat) ;
             out = (SFLDataFormat*) pa_xmalloc (toPlay);
             tone->getNext (out, toPlay/2 , 100);
-            pa_stream_write (playback->pulseStream() , out , toPlay   , pa_xfree, 0 , PA_SEEK_RELATIVE) ;
+            pa_stream_write (playback->pulseStream(), out, toPlay, NULL, 0, PA_SEEK_RELATIVE);
+
+	    pa_xfree (out);
+
         } else {
+
             out = (SFLDataFormat*) pa_xmalloc (framesPerBuffer * sizeof (SFLDataFormat));
-            normalAvail = _voiceRingBuffer.AvailForGet();
+            normalAvail = _mainBuffer.availForGet();
             toGet = (normalAvail < (int) (framesPerBuffer * sizeof (SFLDataFormat))) ? normalAvail : framesPerBuffer * sizeof (SFLDataFormat);
 
             if (toGet) {
-                _voiceRingBuffer.Get (out, toGet, 100);
-                _voiceRingBuffer.Discard (toGet);
+
+                _mainBuffer.getData (out, toGet, 100);
+		pa_stream_write (playback->pulseStream(), out, toGet, NULL, 0, PA_SEEK_RELATIVE);
+
             } else {
+
                 bzero (out, framesPerBuffer * sizeof (SFLDataFormat));
             }
 
-            pa_stream_write (playback->pulseStream() , out , toGet  , NULL, 0 , PA_SEEK_RELATIVE);
-
             pa_xfree (out);
         }
+
+	_urgentRingBuffer.Discard(toGet);
     }
 
 }
@@ -403,7 +425,7 @@ void PulseLayer::readFromMic (void)
     }
 
     if (data != 0) {
-        _micRingBuffer.Put ( (void*) data ,r, 100);
+        _mainBuffer.putData ( (void*) data ,r, 100);
     }
 
     if (pa_stream_drop (record->pulseStream()) < 0) {
diff --git a/sflphone-common/src/audio/recordable.cpp b/sflphone-common/src/audio/recordable.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ab1bf343aee0bce7cf19b1055ab0a0273ea4bda4
--- /dev/null
+++ b/sflphone-common/src/audio/recordable.cpp
@@ -0,0 +1,44 @@
+/*
+ *  Copyright (C) 2004-2008 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.
+ */
+
+#include "recordable.h"
+#include "manager.h"
+
+Recordable::Recordable()
+{
+
+    FILE_TYPE fileType = FILE_WAV;
+    SOUND_FORMAT soundFormat = INT16;
+
+    recAudio.setRecordingOption (fileType, soundFormat, 44100, Manager::instance().getConfigString (AUDIO, RECORD_PATH));
+}
+
+
+Recordable::~Recordable()
+{
+    if (recAudio.isOpenFile()) {
+        recAudio.closeFile();
+    }
+}
+
+
+void Recordable::initRecFileName()
+{
+
+    recAudio.initFileName (getRecFileId());
+}
diff --git a/sflphone-common/src/audio/recordable.h b/sflphone-common/src/audio/recordable.h
new file mode 100644
index 0000000000000000000000000000000000000000..ece673c903a84107fcd6437e18a863ce596eb0d1
--- /dev/null
+++ b/sflphone-common/src/audio/recordable.h
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (C) 2004-2008 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.
+ */
+
+#ifndef RECORDABLE_H
+#define RECORDABLE_H
+
+#include "../plug-in/audiorecorder/audiorecord.h"
+
+class Recordable {
+
+    public:
+
+        Recordable();
+
+	~Recordable();
+
+	bool isRecording(){ return recAudio.isRecording(); }
+
+	bool setRecording(){ return recAudio.setRecording(); }
+
+	void stopRecording(){ recAudio.stopRecording(); }
+
+	void initRecFileName();
+
+	virtual std::string getRecFileId() = 0;
+
+	// virtual std::string getFileName() = 0;
+
+	// std::string getFileName() { return _filename; }
+
+	/**
+	 * An instance of audio recorder
+	 */
+         AudioRecord recAudio;
+
+
+    private:
+
+	/** File name for his call : time YY-MM-DD */
+        // std::string _filename;
+
+        
+
+};
+
+#endif
diff --git a/sflphone-common/src/audio/ringbuffer.cpp b/sflphone-common/src/audio/ringbuffer.cpp
index ea27fdc23d95e649475dffc45014f7d2ec6179ba..d93a4ed25de8ea85f1ba7f4a68b114dbdc13ea19 100644
--- a/sflphone-common/src/audio/ringbuffer.cpp
+++ b/sflphone-common/src/audio/ringbuffer.cpp
@@ -1,5 +1,6 @@
 /*
- *  Copyright (C) 2004, 2005, 2006 Savoir-Faire Linux inc.
+ *  Copyright (C) 2004, 2005, 2006, 2009Savoir-Faire Linux inc.
+ *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
  *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
  *  Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com>
  *
@@ -29,13 +30,39 @@
 
 #define MIN_BUFFER_SIZE	1280
 
+int RingBuffer::count_rb = 0;
+
 // Create  a ring buffer with 'size' bytes
-RingBuffer::RingBuffer (int size) : mStart (0), mEnd (0)
+RingBuffer::RingBuffer (int size, CallID call_id) : mEnd (0)
         , mBufferSize (size > MIN_BUFFER_SIZE ? size : MIN_BUFFER_SIZE)
         , mBuffer (NULL)
+	, buffer_id(call_id)
 {
     mBuffer = new unsigned char[mBufferSize];
     assert (mBuffer != NULL);
+
+    count_rb++;
+
+    // open files
+    std::string s_input;
+    std::string s_output;
+
+    // convert count into string
+    std::stringstream out;
+    out << count_rb;
+    
+    s_input = "/home/alexandresavard/Desktop/buffer_record/buffer_input_";
+    s_input.append(out.str());
+
+    s_output = "/home/alexandresavard/Desktop/buffer_record/buffer_output_";
+    s_output.append(out.str());
+
+    buffer_input_rec = new std::fstream();
+    buffer_output_rec = new std::fstream();
+
+    buffer_input_rec->open(s_input.c_str(), std::fstream::out);
+    buffer_output_rec->open(s_output.c_str(), std::fstream::out);
+    
 }
 
 // Free memory on object deletion
@@ -43,35 +70,181 @@ RingBuffer::~RingBuffer()
 {
     delete[] mBuffer;
     mBuffer = NULL;
+
+    buffer_input_rec->close();
+    delete buffer_input_rec; buffer_input_rec = NULL;
+
+    buffer_output_rec->close();
+    delete buffer_output_rec; buffer_output_rec = NULL;
 }
 
 void
-RingBuffer::flush (void)
+RingBuffer::flush (CallID call_id)
+{
+    storeReadPointer(mEnd, call_id);
+}
+
+int
+RingBuffer::putLen()
 {
-    mStart = 0;
-    mEnd = 0;
+    int mStart;
+
+    if(_readpointer.size() >= 1)
+    {
+	mStart = getSmallestReadPointer();
+    }
+    else
+    {
+        mStart = 0;
+    }
+
+    int length = (mEnd + mBufferSize - mStart) % mBufferSize;
+    // _debug("RingBuffer::putLen length %i\n", length);
+    // _debug("    *RingBuffer::putLen: buffer_id %s, mStart %i, mEnd %i, length %i, buffersie %i\n", buffer_id.c_str(), mStart, mEnd, length, mBufferSize);
+    return length;
 }
 
 int
-RingBuffer::Len() const
+RingBuffer::getLen(CallID call_id)
 {
+
+    int mStart = getReadPointer(call_id);
+
+    int length = (mEnd + mBufferSize - mStart) % mBufferSize;
+    // _debug("    *RingBuffer::getLen: buffer_id %s, call_id %s, mStart %i, mEnd %i, length %i, buffersie %i\n", buffer_id.c_str(), call_id.c_str(), mStart, mEnd, length, mBufferSize);
     return (mEnd + mBufferSize - mStart) % mBufferSize;
+
 }
 
 void
 RingBuffer::debug()
 {
+    int mStart = getSmallestReadPointer();
+
     _debug ("Start=%d; End=%d; BufferSize=%d\n", mStart, mEnd, mBufferSize);
 }
 
+int
+RingBuffer::getReadPointer(CallID call_id)
+{
+
+    if(getNbReadPointer() == 0)
+	return 0;
+
+    // _debug("RingBuffer::getReadPointer() id %s\n", call_id.c_str());
+    
+    ReadPointer::iterator iter = _readpointer.find(call_id);
+    if (iter == _readpointer.end())
+    {
+	// _debug("                RingBuffer::getReadPointer Error read pointer size: %i\n", _readpointer.size());
+	// _debug("                RingBuffer::getReadPointer Error read pointer \"%s\" is null\n", call_id.c_str());
+	ReadPointer::iterator iter2;
+	for( iter2 = _readpointer.begin(); iter2 != _readpointer.end(); iter2++)
+	{
+	    // x_debug("                RingBuffer::getReadPointer list avail pointer \"%s\"\n", iter2->first.c_str());
+	}
+	return 0;
+    }
+    else
+    {
+        return iter->second;
+    }
+    
+}
+
+int
+RingBuffer::getSmallestReadPointer()
+{
+    if (getNbReadPointer() == 0)
+	return 0;
+
+    int smallest = mBufferSize;	
+
+    ReadPointer::iterator iter = _readpointer.begin();
+    while (iter != _readpointer.end())
+    {
+	if(iter->second < smallest)
+	    smallest = iter->second;
+
+	iter++;
+    }
+
+    return smallest;
+}
+
+void
+RingBuffer::storeReadPointer(int pointer_value, CallID call_id)
+{
+
+    ReadPointer::iterator iter = _readpointer.find(call_id);
+    if(iter != _readpointer.end())
+    {	
+	iter->second = pointer_value;
+	// _debug("store read pointer call_id %s, size: %i \n",call_id.c_str(), _readpointer.size());
+    }
+    else
+    {
+	_debug("Cannot find \"%s\" readPointer\n", call_id.c_str());
+    }
+
+}
+
+
+void
+RingBuffer::createReadPointer(CallID call_id)
+{
+
+    _debug("---- createReadPointer ringbuffer_id %s, call_id %s\n", buffer_id.c_str(), call_id.c_str());
+ 
+    _readpointer.insert(pair<CallID, int>(call_id, mEnd));
+    _debug("---- createReadPointer ringbuffer_id %s, size %i\n", buffer_id.c_str(),_readpointer.size());
+
+}
+
+
+void
+RingBuffer::removeReadPointer(CallID call_id)
+{
+
+    _debug("---- removeReadPointer ringbuffer_id %s, call_id %s\n", buffer_id.c_str(), call_id.c_str());
+
+    _readpointer.erase(call_id);
+    _debug("---- removeReadPointer ringbuffer_id %s, size %i\n", buffer_id.c_str(), _readpointer.size());
+
+}
+
+
+bool
+RingBuffer::hasThisReadPointer(CallID call_id)
+{
+    ReadPointer::iterator iter = _readpointer.find(call_id);
+    if(iter == _readpointer.end())
+    {
+	return false;
+    }
+    else
+    {
+	return true;
+    }
+}
+
+
+int
+RingBuffer::getNbReadPointer()
+{
+    return _readpointer.size();
+}
+
 //
 // For the writer only:
 //
 int
-RingBuffer::AvailForPut() const
+RingBuffer::AvailForPut()
 {
     // Always keep 4 bytes safe (?)
-    return (mBufferSize-4) - Len();
+    // z_debug("RingBuffer::AvailForPut: putLen %i\n", putLen());
+    // _debug("RingBuffer::AvailForPut %s --------------------\n", buffer_id.c_str());
+    return (mBufferSize-4) - putLen();
 }
 
 // This one puts some data inside the ring buffer.
@@ -83,7 +256,9 @@ RingBuffer::Put (void* buffer, int toCopy, unsigned short volume)
     int block;
     int copied;
     int pos;
-    int len = Len();
+    // _debug("RingBuffer::Put buffer_id %s, call_id %s --------------------\n", buffer_id.c_str(), call_id.c_str());
+    int len = putLen();
+    // _debug("    RingBuffer::Put bufferid %s, putlen %i\n", buffer_id.c_str(), len);
 
     if (toCopy > (mBufferSize-4) - len)
         toCopy = (mBufferSize-4) - len;
@@ -117,6 +292,7 @@ RingBuffer::Put (void* buffer, int toCopy, unsigned short volume)
 
         // bcopy(src, dest, len)
         //fprintf(stderr, "has %d put %d\t", len, block);
+	buffer_input_rec->write((char*)src, block);
         bcopy (src, mBuffer + pos, block);
 
         src += block;
@@ -139,20 +315,30 @@ RingBuffer::Put (void* buffer, int toCopy, unsigned short volume)
 //
 
 int
-RingBuffer::AvailForGet() const
+RingBuffer::AvailForGet(CallID call_id)
 {
     // Used space
-    return Len();
+    // _debug("RingBuffer::AvailForGet buffer_id %s, call_id %s --------------------\n", buffer_id.c_str(), call_id.c_str());
+    return getLen(call_id);
 }
 
 // Get will move 'toCopy' bytes from the internal FIFO to 'buffer'
 int
-RingBuffer::Get (void *buffer, int toCopy, unsigned short volume)
+RingBuffer::Get (void *buffer, int toCopy, unsigned short volume, CallID call_id)
 {
+
+    if(getNbReadPointer() == 0)
+        return 0;
+
+    if(!hasThisReadPointer(call_id))
+	return 0;
+
     samplePtr dest;
     int block;
     int copied;
-    int len = Len();
+    // _debug("RingBuffer::Get buffer_id %s, call_id %s --------------------\n", buffer_id.c_str(), call_id.c_str());
+    int len = getLen(call_id);
+    // _debug("    RingBuffer::Get bufferid %s, getlen %i\n", buffer_id.c_str(), len);
 
     if (toCopy > len)
         toCopy = len;
@@ -161,6 +347,8 @@ RingBuffer::Get (void *buffer, int toCopy, unsigned short volume)
 
     copied = 0;
 
+    int mStart = getReadPointer(call_id);
+
     //fprintf(stderr, "G");
     while (toCopy) {
         block = toCopy;
@@ -180,6 +368,7 @@ RingBuffer::Get (void *buffer, int toCopy, unsigned short volume)
 
         // bcopy(src, dest, len)
         bcopy (mBuffer + mStart, dest, block);
+	buffer_output_rec->write((char*)dest, block);
 
         dest += block;
 
@@ -190,19 +379,26 @@ RingBuffer::Get (void *buffer, int toCopy, unsigned short volume)
         copied += block;
     }
 
+    storeReadPointer(mStart, call_id);
+
     return copied;
 }
 
 // Used to discard some bytes.
 int
-RingBuffer::Discard (int toDiscard)
+RingBuffer::Discard (int toDiscard, CallID call_id)
 {
-    int len = Len();
+    // _debug("RingBuffer::Discard buffer_id %s, call_id %s --------------------\n", buffer_id.c_str(), call_id.c_str());
+    int len = getLen(call_id);
+
+    int mStart = getReadPointer(call_id);
 
     if (toDiscard > len)
         toDiscard = len;
 
     mStart = (mStart + toDiscard) % mBufferSize;
 
+    storeReadPointer(mStart, call_id);
+
     return toDiscard;
 }
diff --git a/sflphone-common/src/audio/ringbuffer.h b/sflphone-common/src/audio/ringbuffer.h
index 27db3e31b3deaa8a195c02e1c82a7f876f054418..0dcfbf27e40a811928dbf8aa3ce35c6f01d4413e 100644
--- a/sflphone-common/src/audio/ringbuffer.h
+++ b/sflphone-common/src/audio/ringbuffer.h
@@ -1,7 +1,8 @@
 /*
- *  Copyright (C) 2004-2005 Savoir-Faire Linux inc.
+ *  Copyright (C) 2004-2009 Savoir-Faire Linux inc.
  *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
- *  Author : Laurielle Lea <laurielle.lea@savoirfairelinux.com>
+ *  Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com>
+ *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
  * 
  *  Portions Copyright (C) Dominic Mazzoni (Audacity)
  *                                                                              
@@ -23,15 +24,22 @@
 #ifndef __RING_BUFFER__
 #define __RING_BUFFER__
 
+#include "../call.h"
+
+#include <fstream>
+
+
 typedef unsigned char* samplePtr;
 
+typedef map<CallID, int> ReadPointer;
+
 class RingBuffer {
   public:
     /**
      * Constructor
      * @param size  Size of the buffer to create
      */
-    RingBuffer(int size);
+    RingBuffer(int size, CallID call_id);
 
     /**
      * Destructor
@@ -42,13 +50,28 @@ class RingBuffer {
     /**
      * Reset the counters to 0
      */
-    void flush (void);
+    void flush (CallID call_id = default_id);
+
+
+    int getReadPointer(CallID call_id = default_id);
+
+    int getSmallestReadPointer();
+
+    void storeReadPointer(int pointer_value, CallID call_id = default_id);
+
+    void createReadPointer(CallID call_id = default_id);
+
+    void removeReadPointer(CallID call_id = default_id);
+
+    bool hasThisReadPointer(CallID call_id);
+
+    int getNbReadPointer();
 
     /**
      * To get how much space is available in the buffer to write in
      * @return int The available size
      */
-    int AvailForPut (void) const;
+    int AvailForPut (void);
 
     /**
      * Write data in the ring buffer
@@ -63,7 +86,7 @@ class RingBuffer {
      * To get how much space is available in the buffer to read in
      * @return int The available size
      */
-    int AvailForGet (void) const;
+    int AvailForGet (CallID call_id = default_id);
 
     /**
      * Get data in the ring buffer
@@ -72,20 +95,22 @@ class RingBuffer {
      * @param volume The volume
      * @return int Number of bytes copied
      */
-    int Get (void* buffer, int toCopy, unsigned short volume = 100);
+    int Get (void* buffer, int toCopy, unsigned short volume = 100, CallID call_id = default_id);
 
     /**
      * Discard data from the buffer
      * @param toDiscard Number of bytes to discard
      * @return int Number of bytes discarded 
      */
-    int Discard(int toDiscard);
+    int Discard(int toDiscard, CallID call_id = default_id);
 
     /**
      * Total length of the ring buffer
      * @return int  
      */
-    int Len() const;
+    int putLen();
+
+    int getLen(CallID call_id = default_id);
     
     /**
      * Debug function print mEnd, mStart, mBufferSize
@@ -100,13 +125,28 @@ class RingBuffer {
     RingBuffer& operator=(const RingBuffer& rh);
 
     /** Pointer on the first data */
-    int           mStart;
+    // int           mStart;
     /** Pointer on the last data */
     int           mEnd;
     /** Buffer size */
     int           mBufferSize;
     /** Data */
     samplePtr     mBuffer;
+
+    ReadPointer   _readpointer;
+
+    CallID buffer_id;
+
+  public:
+
+    friend class MainBufferTest;
+
+    std::fstream *buffer_input_rec;
+    std::fstream *buffer_output_rec;
+
+    static int count_rb;
+    
 };
 
+
 #endif /*  __RING_BUFFER__ */
diff --git a/sflphone-common/src/call.cpp b/sflphone-common/src/call.cpp
index b10dcaebda1f4c64f190d8296d6a666f87be6e5b..94a7e79519cfd3294692ec3d5077734147f32041 100644
--- a/sflphone-common/src/call.cpp
+++ b/sflphone-common/src/call.cpp
@@ -27,6 +27,7 @@ Call::Call (const CallID& id, Call::CallType type)
         , _localAudioPort (0)
         , _localExternalAudioPort (0)
         , _id (id)
+	, _confID ("")
         , _type (type)
         , _connectionState (Call::Disconnected)
         , _callState (Call::Inactive)
@@ -35,18 +36,11 @@ Call::Call (const CallID& id, Call::CallType type)
         , _peerNumber()
 {
 
-    FILE_TYPE fileType = FILE_WAV;
-    SOUND_FORMAT soundFormat = INT16;
-
-    recAudio.setRecordingOption (fileType,soundFormat,44100, Manager::instance().getConfigString (AUDIO, RECORD_PATH),id);
 }
 
 
 Call::~Call()
 {
-    if (recAudio.isOpenFile()) {
-        recAudio.closeFile();
-    }
 }
 
 void
@@ -134,6 +128,10 @@ Call::getStateStr ()
 
             break;
 
+        case Conferencing:
+	    state_str = "CONFERENCING";
+	    break;
+
         case Refused:
 
         case Error:
@@ -175,27 +173,3 @@ Call::isAudioStarted()
     return _audioStarted;
 }
 
-void
-Call::setRecording()
-{
-    recAudio.setRecording();
-}
-
-void
-Call::initRecFileName()
-{
-    recAudio.initFileName (_peerNumber);
-}
-
-void
-Call::stopRecording()
-{
-    recAudio.stopRecording();
-}
-
-bool
-Call::isRecording()
-{
-    return recAudio.isRecording();
-}
-
diff --git a/sflphone-common/src/call.h b/sflphone-common/src/call.h
index b46f58a6f88cf894208608974741e05349466290..aed0168c90eeb59c9152f3166e17b9e9bd9f7e7e 100644
--- a/sflphone-common/src/call.h
+++ b/sflphone-common/src/call.h
@@ -24,7 +24,8 @@
 #include <cc++/thread.h> // for mutex
 #include <sstream>
 
-#include "plug-in/audiorecorder/audiorecord.h"
+// #include "plug-in/audiorecorder/audiorecord.h"
+#include "audio/recordable.h"
 
 #define SIP_SCHEME       "sip:"
 #define SIPS_SCHEME      "sips:"
@@ -38,9 +39,9 @@
 
 typedef std::string CallID;
 
-class AudioRecord;
+static CallID default_id = "default_id";
 
-class Call{
+class Call: public Recordable{
     public:
 
         /**
@@ -67,7 +68,7 @@ class Call{
         /**
          * The Call State.
          */
-        enum CallState {Inactive, Active, Hold, Busy, Refused, Error};
+        enum CallState {Inactive, Active, Hold, Busy, Conferencing, Refused, Error};
 
         /**
          * Constructor of a call
@@ -83,6 +84,14 @@ class Call{
          */
         CallID& getCallId() {return _id; }
 
+	/** 
+         * Return a reference on the conference id
+         * @return call id
+         */
+        CallID& getConfId() {return _confID; }
+
+	void setConfId(CallID id) {_confID = id; }
+
         inline CallType getCallType (void)
         {
             return _type;
@@ -203,35 +212,9 @@ class Call{
          */
         unsigned int getLocalAudioPort();
 
-        /**
-         * @return Return the file name for this call
-         */
-        std::string getFileName() {return _filename;}
-
-        /**
-         * A recorder for this call
-         */
-        AudioRecord recAudio;
-
-        /**
-         * SetRecording
-         */
-        void setRecording();
-
-        /**
-         * stopRecording, make sure the recording is stopped (whe transfering call)
-         */
-        void stopRecording();
-
-        /**
-         * Return Recording state
-         */
-        bool isRecording(); 
+	std::string getRecFileId(){ return getPeerName(); }
 
-        /**
-         *
-         */
-        void initRecFileName();
+	std::string getFileName() { return _filename; }
 
     protected:
         /** Protect every attribute that can be changed by two threads */
@@ -256,10 +239,15 @@ class Call{
         /** Unique ID of the call */
         CallID _id;
 
+	/** Unique conference ID, used exclusively in case of a conferece */
+	CallID _confID;
+
         /** Type of the call */
         CallType _type;
+
         /** Disconnected/Progressing/Trying/Ringing/Connected */
         ConnectionState _connectionState;
+
         /** Inactive/Active/Hold/Busy/Refused/Error */
         CallState _callState;
 
@@ -272,7 +260,7 @@ class Call{
         /** Number of the peer */
         std::string _peerNumber;
 
-        /** File name for his call : time YY-MM-DD */
+	/** File name for his call : time YY-MM-DD */
         std::string _filename;
 };
 
diff --git a/sflphone-common/src/conference.cpp b/sflphone-common/src/conference.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..563dff49037ee6fb20d8f76c952820d4305903cb
--- /dev/null
+++ b/sflphone-common/src/conference.cpp
@@ -0,0 +1,149 @@
+/*
+ *  Copyright (C) 2009 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.
+ */
+
+#include <sstream>
+
+#include "conference.h"
+#include "manager.h"
+#include "audio/audiolayer.h"
+
+int Conference::count = 0;
+
+Conference::Conference()
+{
+    _nbParticipant = 0;
+
+    ++count;
+
+    std::string conf("conf_");
+
+    // convert count into string
+    std::string s;
+    std::stringstream out;
+    out << count;
+    s = out.str();
+
+    _nbParticipant = 0;
+    _id = conf.append(s);
+
+    
+
+}
+
+
+Conference::~Conference()
+{
+
+    
+
+}
+
+
+int Conference::getState()
+{
+    return _confState;
+}
+
+
+void Conference::setState(ConferenceState state)
+{
+    _confState = state;
+}
+
+
+void Conference::add(CallID participant_id)
+{
+
+    _debug("---- Conference:: add participant %s\n", participant_id.c_str());
+
+    _participants.insert(participant_id);
+
+    _nbParticipant++;
+}
+
+
+void Conference::remove(CallID participant_id)
+{
+
+    _debug("---- Conference::remove participant %s\n", participant_id.c_str());
+
+    _participants.erase(participant_id);
+    
+    _nbParticipant--;
+
+}
+
+void Conference::bindParticipant(CallID participant_id)
+{
+
+    if(_nbParticipant >= 1) {
+	ParticipantSet::iterator iter = _participants.begin();
+
+	while (iter != _participants.end()) {
+
+	    if (participant_id != (*iter)) {
+
+	        _debug("---- Conference:: bind callid %s with %s in conference add\n", participant_id.c_str(), (*iter).c_str());
+	        Manager::instance().getAudioDriver()->getMainBuffer()->bindCallID(participant_id, *iter);
+	    }
+	    iter++;
+	}
+
+    }
+
+    _debug("---- Conference::bind callid %s with default_id in conference add\n", participant_id.c_str());
+
+    Manager::instance().getAudioDriver()->getMainBuffer()->bindCallID(participant_id);
+
+}
+
+
+std::string Conference::getStateStr()
+{
+
+    std::string state_str;
+
+    switch(_confState) {
+
+        case Active_Atached:
+	    state_str = "ACTIVE_ATACHED";
+	    break;
+
+	case Active_Detached:
+	    state_str = "ACTIVE_DETACHED";
+	    break;
+	   
+        case Hold:
+	    state_str = "HOLD";
+	    break;
+
+        default:
+	    break;
+    }
+
+    return state_str;
+}
+
+
+ParticipantSet Conference::getParticipantList()
+{
+    return _participants;   
+}
+
diff --git a/sflphone-common/src/conference.h b/sflphone-common/src/conference.h
new file mode 100644
index 0000000000000000000000000000000000000000..733b338add7edac43c790bb7a88107a73bf5c5ca
--- /dev/null
+++ b/sflphone-common/src/conference.h
@@ -0,0 +1,82 @@
+/*
+ *  Copyright (C) 2009 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.
+ */
+#ifndef CONFERENCE_H
+#define CONFERENCE_H
+
+#include <set>
+#include <string>
+
+#include "audio/recordable.h"
+#include "call.h"
+
+// class ManagerImpl;
+// class Call;
+
+typedef std::string ConfID;
+
+typedef std::set<CallID> ParticipantSet;
+
+class Conference: public Recordable{
+
+    public:
+
+        enum ConferenceState {Active_Atached, Active_Detached, Hold};
+
+	static int count;
+
+        Conference();
+
+        ~Conference();
+
+	std::string getConfID() { return _id; }
+
+	int getState();
+
+	void setState(ConferenceState state);
+
+	std::string getStateStr();
+
+	int getNbParticipants() { return _nbParticipant; }
+
+	void add(CallID participant_id);
+
+	void remove(CallID participant_id);
+
+	void bindParticipant(CallID participant_id);
+
+	ParticipantSet getParticipantList();
+
+	std::string getRecFileId(){ return getConfID(); }
+
+    private:  
+
+        /** Unique ID of the conference */
+        CallID _id;
+
+	ConferenceState _confState;
+
+        ParticipantSet _participants;
+
+        int _nbParticipant;
+
+};
+
+// Conference::count = 0;
+
+#endif
diff --git a/sflphone-common/src/dbus/callmanager-introspec.xml b/sflphone-common/src/dbus/callmanager-introspec.xml
index 743dd70f3e1d5803e27b8cbb09ea5cbaec26fe1a..77d48b130c62b371cba633573e4453c1a0100736 100644
--- a/sflphone-common/src/dbus/callmanager-introspec.xml
+++ b/sflphone-common/src/dbus/callmanager-introspec.xml
@@ -19,6 +19,10 @@
     <method name="hangUp">
       <arg type="s" name="callID" direction="in"/>
     </method>
+
+    <method name="hangUpConference">
+      <arg type="s" name="confID" direction="in"/>
+    </method>
     
     <method name="hold">
       <arg type="s" name="callID" direction="in"/>
@@ -52,6 +56,39 @@
       <arg type="d" name="value" direction="out"/>
     </method>
 
+    <method name="joinParticipant">
+      <arg type="s" name="sel_callID" direction="in"/>
+      <arg type="s" name="drag_callID" direction="in"/>
+    </method>
+
+    <method name="addParticipant">
+      <arg type="s" name="callID" direction="in"/>
+      <arg type="s" name="confID" direction="in"/>
+    </method>
+
+    <method name="addMainParticipant">
+      <arg type="s" name="confID" direction="in"/>
+    </method>
+
+    <method name="detachParticipant">
+      <arg type="s" name="callID" direction="in"/>
+    </method>
+
+    <method name="joinConference">
+      <arg type="s" name="sel_confID" direction="in"/>
+      <arg type="s" name="drag_confID" direction="in"/>
+    </method>
+
+    <method name="getConferenceDetails">
+      <arg type="s" name="callID" direction="in"/>
+      <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="MapStringString"/>
+      <arg type="a{ss}" name="infos" direction="out"/>
+    </method>
+    
+    <method name="getConferenceList">
+        <arg type="as" name="list" direction="out"/>
+    </method>
+
     <method name="setRecording">
       <arg type="s" name="callID" direction="in"/>
     </method>
@@ -100,6 +137,32 @@
       <arg type="s" name="callID"  direction="out"/>
       <arg type="s" name="state"  direction="out"/>
     </signal>
+
+    <signal name="conferenceChanged">
+      <arg type="s" name="confID"  direction="out"/>
+      <arg type="s" name="state"  direction="out"/>
+    </signal>
+
+    <method name="getParticipantList">
+      <arg type="s" name="confID" direction="in"/>
+      <arg type="as" name="list" direction="out"/>
+    </method>
+
+    <signal name="conferenceCreated">
+      <arg type="s" name="confID"  direction="out"/>
+    </signal>
+
+    <signal name="conferenceRemoved">
+      <arg type="s" name="confID"  direction="out"/>
+    </signal>
+
+    <method name="holdConference">
+      <arg type="s" name="confID" direction="in"/>
+    </method>
+
+    <method name="unholdConference">
+      <arg type="s" name="confID" direction="in"/>
+    </method>
     
     <signal name="sipCallStateChanged">
       <arg type="s" name="callID"  direction="out"/>
diff --git a/sflphone-common/src/dbus/callmanager.cpp b/sflphone-common/src/dbus/callmanager.cpp
index d742a86ae0278bbe291f35f0595b7495a702159b..b069cd2150be2759bf232f259d385ba87f81ed05 100644
--- a/sflphone-common/src/dbus/callmanager.cpp
+++ b/sflphone-common/src/dbus/callmanager.cpp
@@ -63,15 +63,24 @@ CallManager::accept (const std::string& callID)
 void
 CallManager::hangUp (const std::string& callID)
 {
-    _debug ("CallManager::hangUp received\n");
+    _debug ("CallManager::hangUp received %s\n", callID.c_str());
     Manager::instance().hangupCall (callID);
 
 }
 
+void
+CallManager::hangUpConference (const std::string& confID)
+{
+    _debug ("CallManager::hangUpConference received %s\n", confID.c_str());
+    Manager::instance().hangupConference (confID);
+
+}
+
+
 void
 CallManager::hold (const std::string& callID)
 {
-    _debug ("CallManager::hold received\n");
+    _debug ("CallManager::hold received %s\n", callID.c_str());
     Manager::instance().onHoldCall (callID);
 
 }
@@ -79,7 +88,7 @@ CallManager::hold (const std::string& callID)
 void
 CallManager::unhold (const std::string& callID)
 {
-    _debug ("CallManager::unhold received\n");
+    _debug ("CallManager::unhold received %s\n", callID.c_str());
     Manager::instance().offHoldCall (callID);
 }
 
@@ -122,6 +131,75 @@ CallManager::getVolume (const std::string& device)
     return 0;
 }
 
+void
+CallManager::joinParticipant (const std::string& sel_callID, const std::string& drag_callID)
+{
+    _debug ("CallManager::joinParticipant received %s, %s\n", sel_callID.c_str(), drag_callID.c_str());
+    Manager::instance().joinParticipant(sel_callID, drag_callID);
+}
+
+void
+CallManager::addParticipant (const std::string& callID, const std::string& confID)
+{
+    _debug ("CallManager::addParticipant received %s, %s\n", callID.c_str(), confID.c_str());
+    Manager::instance().addParticipant(callID, confID);
+}
+
+void
+CallManager::addMainParticipant (const std::string& confID)
+{
+    _debug ("CallManager::addMainParticipant received %s\n", confID.c_str());
+    Manager::instance().addMainParticipant(confID);
+}
+
+void
+CallManager::detachParticipant (const std::string& callID)
+{
+    _debug ("CallManager::detachParticipant received %s\n", callID.c_str());
+    Manager::instance().detachParticipant(callID, "");
+}
+
+void
+CallManager::joinConference (const std::string& sel_confID, const std::string& drag_confID)
+{
+    _debug ("CallManager::joinConference received %s, %s\n", sel_confID.c_str(), drag_confID.c_str());
+    Manager::instance().joinConference(sel_confID, drag_confID);
+}
+
+void
+CallManager::holdConference (const std::string& confID)
+{
+    _debug ("CallManager::holdConference received %s\n", confID.c_str());
+    Manager::instance().holdConference(confID);
+}
+
+void
+CallManager::unholdConference (const std::string& confID)
+{
+    _debug ("CallManager::unHoldConference received %s\n", confID.c_str());
+    Manager::instance().unHoldConference(confID);
+}
+
+std::map< std::string, std::string >
+CallManager::getConferenceDetails (const std::string& callID)
+{
+    _debug ("CallManager::getCallDetails received\n");
+    return Manager::instance().getConferenceDetails (callID);
+}
+
+std::vector< std::string >
+CallManager::getConferenceList (void)
+{
+    _debug("CallManager::getConferenceList\n");
+    return Manager::instance().getConferenceList();
+}
+
+std::vector< std::string >
+CallManager::getParticipantList (const std::string& confID)
+{
+    return Manager::instance().getParticipantList(confID);
+}
+
 void
 CallManager::setRecording (const std::string& callID)
 {
@@ -132,7 +210,7 @@ CallManager::setRecording (const std::string& callID)
 bool
 CallManager::getIsRecording (const std::string& callID)
 {
-    _debug ("CallManager::getIsRecording received  \n");
+    _debug ("CallManager::getIsRecording received \n");
     return Manager::instance().isRecording (callID);
 }
 
@@ -187,7 +265,7 @@ CallManager::startTone (const int32_t& start , const int32_t& type)
 // for conferencing in order to get
 // the right pointer for the given
 // callID.
-sfl::AudioZrtpSession * CallManager::getAudioZrtpSession (void)
+sfl::AudioZrtpSession * CallManager::getAudioZrtpSession(const std::string& callID)
 {
     SIPVoIPLink * link = NULL;
     link = dynamic_cast<SIPVoIPLink *> (Manager::instance().getAccountLink (AccountNULL));
@@ -197,10 +275,10 @@ sfl::AudioZrtpSession * CallManager::getAudioZrtpSession (void)
         throw CallManagerException();
     }
 
+    SIPCall *call = link->getSIPCall(callID);
+    
     sfl::AudioRtpFactory * audioRtp = NULL;
-
-    audioRtp = link->getAudioRtp();
-
+    audioRtp = call->getAudioRtp();
     if (audioRtp == NULL) {
         _debug ("Failed to get AudioRtpFactory\n");
         throw CallManagerException();
@@ -225,7 +303,7 @@ CallManager::setSASVerified (const std::string& callID)
 
     try {
         sfl::AudioZrtpSession * zSession;
-        zSession = getAudioZrtpSession();
+        zSession = getAudioZrtpSession(callID);        
         zSession->SASVerified();
     } catch (...) {
         throw;
@@ -240,7 +318,7 @@ CallManager::resetSASVerified (const std::string& callID)
 
     try {
         sfl::AudioZrtpSession * zSession;
-        zSession = getAudioZrtpSession();
+        zSession = getAudioZrtpSession(callID);        
         zSession->resetSASVerified();
     } catch (...) {
         throw;
@@ -255,7 +333,7 @@ CallManager::setConfirmGoClear (const std::string& callID)
 
     try {
         sfl::AudioZrtpSession * zSession;
-        zSession = getAudioZrtpSession();
+        zSession = getAudioZrtpSession(callID);        
         zSession->goClearOk();
     } catch (...) {
         throw;
@@ -270,7 +348,7 @@ CallManager::requestGoClear (const std::string& callID)
 
     try {
         sfl::AudioZrtpSession * zSession;
-        zSession = getAudioZrtpSession();
+        zSession = getAudioZrtpSession(callID);        
         zSession->requestGoClear();
     } catch (...) {
         throw;
@@ -286,8 +364,8 @@ CallManager::acceptEnrollment (const std::string& callID, const bool& accepted)
 
     try {
         sfl::AudioZrtpSession * zSession;
-        zSession = getAudioZrtpSession();
-        zSession->acceptEnrollment (accepted);
+        zSession = getAudioZrtpSession(callID);        
+        zSession->acceptEnrollment(accepted);
     } catch (...) {
         throw;
     }
@@ -302,8 +380,8 @@ CallManager::setPBXEnrollment (const std::string& callID, const bool& yesNo)
 
     try {
         sfl::AudioZrtpSession * zSession;
-        zSession = getAudioZrtpSession();
-        zSession->setPBXEnrollment (yesNo);
+        zSession = getAudioZrtpSession(callID);        
+        zSession->setPBXEnrollment(yesNo);
     } catch (...) {
         throw;
     }
diff --git a/sflphone-common/src/dbus/callmanager.h b/sflphone-common/src/dbus/callmanager.h
index 041ba405d5efbfe3db4edfb373a57386a658b5c8..8c3bab14c0646a373bf83442f2a8035b17ef68e1 100644
--- a/sflphone-common/src/dbus/callmanager.h
+++ b/sflphone-common/src/dbus/callmanager.h
@@ -50,6 +50,8 @@ class CallManager
         /* methods exported by this interface,
          * you will have to implement them in your ObjectAdaptor
          */
+
+	/* Call related methods */
         void placeCall( const std::string& accountID, const std::string& callID, const std::string& to );
         void refuse( const std::string& callID );
         void accept( const std::string& callID );
@@ -57,19 +59,33 @@ class CallManager
         void hold( const std::string& callID );
         void unhold( const std::string& callID );
         void transfert( const std::string& callID, const std::string& to );
+	std::map< std::string, std::string > getCallDetails( const std::string& callID );
+        std::vector< std::string > getCallList (void);
+	std::string getCurrentCallID(  );
+
+	/* Conference related methods */
+	void joinParticipant( const std::string& sel_callID, const std::string& drag_callID );
+	void addParticipant( const std::string& callID, const std::string& confID );
+	void addMainParticipant( const std::string& confID );
+	void detachParticipant( const std::string& callID );
+	void joinConference( const std::string& sel_confID, const std::string& drag_confID );
+	void hangUpConference( const std::string& confID );
+	void holdConference( const std::string& confID );
+	void unholdConference( const std::string& confID );
+	std::vector< std::string > getConferenceList (void);
+	std::vector< std::string > getParticipantList (const std::string& confID);
+	std::map< std::string, std::string > getConferenceDetails ( const std::string& callID );
+
+	/* General audio methods */
         void setVolume( const std::string& device, const double& value );
         double getVolume( const std::string& device );
         void setRecording( const std::string& callID );
         bool getIsRecording(const std::string& callID);
         std::string getCurrentCodecName(const std::string& callID);
-        
-        std::map< std::string, std::string > getCallDetails( const std::string& callID );
-        std::vector< std::string > getCallList (void);
-
-        std::string getCurrentCallID(  );
         void playDTMF( const std::string& key );
         void startTone( const int32_t& start, const int32_t& type );
 
+	/* Security related methods */
         void setSASVerified(const std::string& callID);
         void resetSASVerified(const std::string& callID);
         void setConfirmGoClear(const std::string& callID);
@@ -79,7 +95,7 @@ class CallManager
         
     private:
 
-        sfl::AudioZrtpSession * getAudioZrtpSession(void);
+        sfl::AudioZrtpSession * getAudioZrtpSession(const std::string& callID);
 };
 
 
diff --git a/sflphone-common/src/global.h b/sflphone-common/src/global.h
index b8ebe7789fc3b28981603aba8ff010fe326d19ea..12529fe3ef86a7f11f055cee864452d9425e06b2 100644
--- a/sflphone-common/src/global.h
+++ b/sflphone-common/src/global.h
@@ -90,6 +90,7 @@ static const SOUND_FORMAT INT32 = 0x8;
 #define CODECDIR         "codecs"		/** Codecs directory */
 
 #define SIZEBUF 				1024*1024
+#define STATIC_BUFSIZE 	 5000
 
 #define ALSA_DFT_CARD_ID     0			/** Index of the default soundcard */
 
diff --git a/sflphone-common/src/iax/iaxvoiplink.cpp b/sflphone-common/src/iax/iaxvoiplink.cpp
index 2a02e5e87c08e19176fb3ada072fde84050bb557..3faabe566a7fff8cc51445408da73ad4ebe51053 100644
--- a/sflphone-common/src/iax/iaxvoiplink.cpp
+++ b/sflphone-common/src/iax/iaxvoiplink.cpp
@@ -207,6 +207,8 @@ IAXVoIPLink::getEvent()
     _mutexIAX.enterMutex();
     iax_event* event = NULL;
 
+    
+
     while ( (event = iax_get_event (IAX_NONBLOCKING)) != NULL) {
         // If we received an 'ACK', libiax2 tells apps to ignore them.
         if (event->etype == IAX_EVENT_NULL) {
@@ -238,7 +240,7 @@ IAXVoIPLink::getEvent()
 
 
     if (call) {
-        call->recAudio.recData (spkrDataConverted,micData,nbSampleForRec_,nbSampleForRec_);
+         call->recAudio.recData (spkrDataConverted,micData,nbSampleForRec_,nbSampleForRec_);
     }
 
     // Do the doodle-moodle to send audio from the microphone to the IAX channel.
@@ -250,8 +252,8 @@ IAXVoIPLink::getEvent()
     }
 
     // reinitialize speaker buffer for recording (when recording a voice mail)
-    for (int i = 0; i < nbSampleForRec_; i++)
-        spkrDataConverted[i] = 0;
+    // for (int i = 0; i < nbSampleForRec_; i++)
+    //     spkrDataConverted[i] = 0;
 
 
     // thread wait 3 millisecond
@@ -269,6 +271,8 @@ IAXVoIPLink::sendAudioFromMic (void)
     AudioCodec *ac;
     IAXCall *currentCall;
 
+
+    
     // We have to update the audio layer type in case we switched
     // TODO Find out a better way to do it
     updateAudiolayer();
@@ -276,10 +280,14 @@ IAXVoIPLink::sendAudioFromMic (void)
     currentCall = getIAXCall (Manager::instance().getCurrentCallId());
 
     if (!currentCall) {
+
+
         // Let's mind our own business.
         return;
     }
 
+    
+
     if (currentCall -> getAudioCodec() < 0)
         return;
 
@@ -305,15 +313,19 @@ IAXVoIPLink::sendAudioFromMic (void)
         return;
     }
 
+    
+
     // Send sound here
     if (audiolayer) {
 
+	
+
         // we have to get 20ms of data from the mic *20/1000 = /50
         // rate/50 shall be lower than IAX__20S_48KHZ_MAX
         maxBytesToGet = audiolayer->getSampleRate() * audiolayer->getFrameSize() / 1000 * sizeof (SFLDataFormat);
 
         // available bytes inside ringbuffer
-        availBytesFromMic = audiolayer->canGetMic();
+        availBytesFromMic = audiolayer->getMainBuffer()->availForGet(currentCall->getCallId());
 
         if (availBytesFromMic < maxBytesToGet) {
             // We need packets full!
@@ -326,7 +338,9 @@ IAXVoIPLink::sendAudioFromMic (void)
         //_debug("available = %d, maxBytesToGet = %d\n", availBytesFromMic, maxBytesToGet);
 
         // Get bytes from micRingBuffer to data_from_mic
-        nbSample_ = audiolayer->getMic (micData, bytesAvail) / sizeof (SFLDataFormat);
+        nbSample_ = audiolayer->getMainBuffer()->getData (micData, bytesAvail, 100, currentCall->getCallId()) / sizeof (SFLDataFormat);
+
+	
 
         // Store the number of samples for recording
         nbSampleForRec_ = nbSample_;
@@ -473,6 +487,8 @@ IAXVoIPLink::answer (const CallID& id)
     IAXCall* call = getIAXCall (id);
     call->setCodecMap (Manager::instance().getCodecDescriptorMap());
 
+    Manager::instance().addStream(call->getCallId());
+
     CHK_VALID_CALL;
 
     _mutexIAX.enterMutex();
@@ -494,6 +510,9 @@ IAXVoIPLink::hangup (const CallID& id)
     IAXCall* call = getIAXCall (id);
     std::string reason = "Dumped Call";
     CHK_VALID_CALL;
+
+    audiolayer->getMainBuffer()->unBindAll(call->getCallId());
+
     _mutexIAX.enterMutex();
 
     iax_hangup (call->getSession(), (char*) reason.c_str());
@@ -519,6 +538,9 @@ IAXVoIPLink::peerHungup (const CallID& id)
     IAXCall* call = getIAXCall (id);
     std::string reason = "Dumped Call";
     CHK_VALID_CALL;
+
+    audiolayer->getMainBuffer()->unBindAll(call->getCallId());
+
     _mutexIAX.enterMutex();
 
     _mutexIAX.leaveMutex();
@@ -544,6 +566,8 @@ IAXVoIPLink::onhold (const CallID& id)
 
     CHK_VALID_CALL;
 
+    audiolayer->getMainBuffer()->unBindAll(call->getCallId());
+
     //if (call->getState() == Call::Hold) { _debug("Call is already on hold\n"); return false; }
 
     _mutexIAX.enterMutex();
@@ -561,6 +585,8 @@ IAXVoIPLink::offhold (const CallID& id)
 
     CHK_VALID_CALL;
 
+    Manager::instance().addStream(call->getCallId());
+
     //if (call->getState() == Call::Active) { _debug("Call is already active\n"); return false; }
     _mutexIAX.enterMutex();
     iax_unquelch (call->getSession());
@@ -610,29 +636,6 @@ IAXVoIPLink::refuse (const CallID& id)
 }
 
 
-void
-IAXVoIPLink::setRecording (const CallID& id)
-{
-    _debug ("IAXVoIPLink::setRecording()!");
-
-    IAXCall* call = getIAXCall (id);
-
-    call->setRecording();
-}
-
-bool
-IAXVoIPLink::isRecording (const CallID& id)
-{
-    _debug ("IAXVoIPLink::setRecording()!");
-
-    IAXCall* call = getIAXCall (id);
-
-    return call->isRecording();
-}
-
-
-
-
 bool
 IAXVoIPLink::carryingDTMFdigits (const CallID& id, char code)
 {
@@ -651,11 +654,19 @@ IAXVoIPLink::carryingDTMFdigits (const CallID& id, char code)
 std::string
 IAXVoIPLink::getCurrentCodecName()
 {
-    IAXCall *call = getIAXCall (Manager::instance().getCurrentCallId());
+    IAXCall *call = NULL;
+    AudioCodec *ac = NULL;
+    std::string name = "";
+
+    call = getIAXCall (Manager::instance().getCurrentCallId());
 
-    AudioCodec *ac = call->getCodecMap().getCodec (call->getAudioCodec());
+    if(call)
+	ac = call->getCodecMap().getCodec (call->getAudioCodec());
 
-    return ac->getCodecName();
+    if(ac)
+	name = ac->getCodecName();
+    
+    return name;
 }
 
 
@@ -777,6 +788,9 @@ IAXVoIPLink::iaxHandleCallEvent (iax_event* event, IAXCall* call)
         case IAX_EVENT_ANSWER:
 
             if (call->getConnectionState() != Call::Connected) {
+
+		Manager::instance().addStream(call->getCallId());
+
                 call->setConnectionState (Call::Connected);
                 call->setState (Call::Active);
                 audiolayer->startStream();
@@ -858,6 +872,8 @@ IAXVoIPLink::iaxHandleVoiceEvent (iax_event* event, IAXCall* call)
     int expandedSize, nbSample_;
     AudioCodec *ac;
 
+
+    
     // If we receive datalen == 0, some things of the jitter buffer in libiax2/iax.c
     // were triggered
 
@@ -867,7 +883,8 @@ IAXVoIPLink::iaxHandleVoiceEvent (iax_event* event, IAXCall* call)
         return;
     }
 
-    if (audiolayer) {
+    if (audiolayer) {	
+
         // On-the-fly codec changing (normally, when we receive a full packet)
         // as per http://tools.ietf.org/id/draft-guy-iax-03.txt
         // - subclass holds the voiceformat property.
@@ -905,7 +922,7 @@ IAXVoIPLink::iaxHandleVoiceEvent (iax_event* event, IAXCall* call)
         nbInt16 = converter->upsampleData (spkrDataDecoded , spkrDataConverted , ac->getClockRate() , audiolayer->getSampleRate() , nbSample_);
 
         /* Write the data to the mic ring buffer */
-        audiolayer->putMain (spkrDataConverted , nbInt16 * sizeof (SFLDataFormat));
+        audiolayer->getMainBuffer()->putData (spkrDataConverted , nbInt16 * sizeof (SFLDataFormat), 100, call->getCallId());
 
     } else {
         _debug ("IAX: incoming audio, but no sound card open");
@@ -1008,6 +1025,8 @@ IAXVoIPLink::iaxHandlePrecallEvent (iax_event* event)
 
             id = Manager::instance().getNewCallID();
 
+	    _debug("-------------------------------------------------------------- callid %s", id.c_str());
+
             call = new IAXCall (id, Call::Incoming);
 
             if (!call) {
diff --git a/sflphone-common/src/iax/iaxvoiplink.h b/sflphone-common/src/iax/iaxvoiplink.h
index a08c40a39a8aa78c9678fb2c25c528cb6d30b509..747cc0509ea08af5d2303041a6fc73d34a97d595 100644
--- a/sflphone-common/src/iax/iaxvoiplink.h
+++ b/sflphone-common/src/iax/iaxvoiplink.h
@@ -165,18 +165,6 @@ class IAXVoIPLink : public VoIPLink
      *		  false otherwise
      */
     bool refuse (const CallID& id);
-   
-    /**
-     * Set Recording
-     * @param id The call identifier
-     */
-    void setRecording(const CallID& id);
-
-    /**
-     * Return recording state
-     * @param id The call identifier
-     */
-    bool isRecording(const CallID& id);
  
     /**
      * Send DTMF  
diff --git a/sflphone-common/src/managerimpl.cpp b/sflphone-common/src/managerimpl.cpp
index dab69f95cf639a55ee81279812f5c3874ec0514d..46163a25d5ea5ad6fea3e74fe223dced0350a9ad 100644
--- a/sflphone-common/src/managerimpl.cpp
+++ b/sflphone-common/src/managerimpl.cpp
@@ -4,6 +4,7 @@
  *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
  *  Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com>
  *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
+ *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
  *  Author: Guillaume Carmel-Archambault <guillaume.carmel-archambault@savoirfairelinux.com>
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -39,6 +40,8 @@
 #include "manager.h"
 #include "dbus/configurationmanager.h"
 
+#include "conference.h"
+
 #include <errno.h>
 #include <time.h>
 #include <cstdlib>
@@ -49,6 +52,7 @@
 #include <sys/stat.h>  // mkdir(2)
 #include <pwd.h>       // getpwuid
 
+
 #define fill_config_str(name, value) \
   (_config.addConfigTreeItem(section, Conf::ConfigTreeItem(std::string(name), std::string(value), type_str)))
 #define fill_config_int(name, value) \
@@ -185,7 +189,7 @@ ManagerImpl::isCurrentCall (const CallID& callId)
 bool
 ManagerImpl::hasCurrentCall()
 {
-    _debug ("Current call ID = %s\n", _currentCallId2.c_str());
+    _debug ("ManagerImpl::hasCurrentCall current call ID = %s\n", _currentCallId2.c_str());
 
     if (_currentCallId2 != "") {
         return true;
@@ -204,7 +208,40 @@ void
 ManagerImpl::switchCall (const CallID& id)
 {
     ost::MutexLock m (_currentCallMutex);
+    _debug("------------------------- SWITCH %s ---------------------------\n", id.c_str());
     _currentCallId2 = id;
+
+    /*
+    AudioLayer *al = getAudioDriver();
+
+    if (id != "") {
+
+	if(isConference(id)) {
+
+	    Conference *conf;
+
+	    ConferenceMap::iterator iter = _conferencemap.find(id);
+	    if(iter != _conferencemap.end())
+	    {
+		_debug("    set call recordable in audio layer\n");
+		conf = iter->second;
+		al->setRecorderInstance((Recordable*)conf);
+	    }
+	}
+	else {
+
+	    // set the recordable instance in audiolayer
+	    AccountID account_id = getAccountFromCall(id);
+	
+
+	    Call *call = NULL;
+	    call = getAccountLink (account_id)->getCall(id);
+
+	    _debug("    set call recordable in audio layer\n");
+	    al->setRecorderInstance((Recordable*)call);
+	}
+    }
+    */
 }
 
 
@@ -214,13 +251,15 @@ ManagerImpl::switchCall (const CallID& id)
 /* Main Thread */
 
 bool
-ManagerImpl::outgoingCall (const std::string& accountid, const CallID& id, const std::string& to)
+ManagerImpl::outgoingCall (const std::string& account_id, const CallID& call_id, const std::string& to)
 {
     std::string pattern, to_cleaned;
     Call::CallConfiguration callConfig;
     SIPVoIPLink *siplink;
 
-    _debug ("ManagerImpl::outgoingCall() method \n");
+    _debug ("ManagerImpl::outgoingCall(%s)\n", call_id.c_str());
+
+    CallID current_call_id = getCurrentCallId();
 
     if (getConfigString (HOOKS, PHONE_NUMBER_HOOK_ENABLED) ==  "1")
         _cleaner->set_phone_number_prefix (getConfigString (HOOKS, PHONE_NUMBER_HOOK_ADD_PREFIX));
@@ -230,47 +269,61 @@ ManagerImpl::outgoingCall (const std::string& accountid, const CallID& id, const
     to_cleaned = _cleaner->clean (to);
 
     /* Check what kind of call we are dealing with */
-    check_call_configuration (id, to_cleaned, &callConfig);
+    check_call_configuration (call_id, to_cleaned, &callConfig);
+
+    // in any cases we have to detach from current communication
+    if (hasCurrentCall()) {
+	
+	_debug ("    outgoingCall: Has current call (%s) put it onhold\n", current_call_id.c_str());
+
+	// if this is not a conferenceand this and is not a conference participant
+	if (!isConference(current_call_id) && !participToConference(current_call_id))
+	{
+	    _debug ("    outgoingCall: Put the current call (%s) on hold\n", current_call_id.c_str());
+	    onHoldCall (current_call_id);
+	}
+	else if (isConference(current_call_id) && !participToConference(call_id))
+	{
+	    _debug ("    outgoingCall: detach main participant from conference\n");
+	    detachParticipant(default_id, current_call_id);
+	}
+    }
 
     if (callConfig == Call::IPtoIP) {
-        _debug ("Start IP to IP call\n");
+        _debug ("    outgoingCall: Start IP to IP call\n");
         /* We need to retrieve the sip voiplink instance */
         siplink = SIPVoIPLink::instance ("");
 
-        if (siplink->new_ip_to_ip_call (id, to_cleaned)) {
-            switchCall (id);
+        if (siplink->new_ip_to_ip_call (call_id, to_cleaned)) {
+            switchCall (call_id);
             return true;
         } else {
-            callFailure (id);
+            callFailure (call_id);
         }
 
         return false;
     }
 
-    if (!accountExists (accountid)) {
+    if (!accountExists (account_id)) {
         _debug ("! Manager Error: Outgoing Call: account doesn't exist\n");
         return false;
     }
 
-    if (getAccountFromCall (id) != AccountNULL) {
+    if (getAccountFromCall (call_id) != AccountNULL) {
         _debug ("! Manager Error: Outgoing Call: call id already exists\n");
         return false;
     }
 
-    if (hasCurrentCall()) {
-        _debug ("* Manager Info: there is currently a call, try to hold it\n");
-        onHoldCall (getCurrentCallId());
-    }
 
-    _debug ("- Manager Action: Adding Outgoing Call %s on account %s\n", id.data(), accountid.data());
+    _debug ("- Manager Action: Adding Outgoing Call %s on account %s\n", call_id.data(), account_id.data());
 
-    associateCallToAccount (id, accountid);
+    associateCallToAccount (call_id, account_id);
 
-    if (getAccountLink (accountid)->newOutgoingCall (id, to_cleaned)) {
-        switchCall (id);
+    if (getAccountLink (account_id)->newOutgoingCall (call_id, to_cleaned)) {
+        switchCall (call_id);
         return true;
     } else {
-        callFailure (id);
+        callFailure (call_id);
         _debug ("! Manager Error: An error occur, the call was not created\n");
     }
 
@@ -279,126 +332,180 @@ ManagerImpl::outgoingCall (const std::string& accountid, const CallID& id, const
 
 //THREAD=Main : for outgoing Call
 bool
-ManagerImpl::answerCall (const CallID& id)
+ManagerImpl::answerCall (const CallID& call_id)
 {
-    stopTone (true);
-
-    AccountID currentAccountId;
-    currentAccountId = getAccountFromCall (id);
 
-    if (currentAccountId == AccountNULL) {
-        _debug ("ManagerImpl::answerCall : AccountId is null\n");
-    }
+    _debug("ManagerImpl::answerCall(%s)", call_id.c_str());
 
-    Call* currentCall = NULL;
+    stopTone (true);
 
-    currentCall = getAccountLink (currentAccountId)->getCall (id);
+    // store the current call id
+    CallID current_call_id = getCurrentCallId();
 
-    if (currentCall == NULL) {
-        _debug ("ManagerImpl::answerCall : currentCall is null\n");
+    AccountID account_id = getAccountFromCall (call_id);
+    if(account_id == AccountNULL) {
+        _debug("    answerCall : AccountId is null\n");
     }
-
-    Call* lastCall = NULL;
-
-    if (!getCurrentCallId().empty()) {
-        lastCall = getAccountLink (currentAccountId)->getCall (getCurrentCallId());
-
-        if (lastCall == NULL) {
-            _debug ("ManagerImpl::answerCall : lastCall is null\n");
-        }
+    
+    Call* call = NULL;
+    call = getAccountLink (account_id)->getCall (call_id);
+    if (call == NULL) {
+        _debug("    answerCall: currentCall is null\n");
     }
 
-    _debug ("ManagerImpl::answerCall :: current call->getState %i \n", currentCall->getState());
-
-    _debug ("Try to answer call: %s\n", id.data());
-
-    if (lastCall != NULL) {
-        if (lastCall->getState() == Call::Active) {
-            _debug ("* Manager Info: there is currently a call, try to hold it\n");
-            onHoldCall (getCurrentCallId());
-        }
-    }
-
-    if (!getAccountLink (currentAccountId)->answer (id)) {
+    // in any cases we have to detach from current communication
+    if (hasCurrentCall()) {
+	
+	_debug ("    answerCall: Has current call or conference (%s)\n", current_call_id.c_str());	
+	// if it is not a conference and is not a conference participant
+	if (!isConference(current_call_id) && !participToConference(current_call_id))
+	{
+	    _debug ("    answerCall: Put the current call (%s) on hold\n", current_call_id.c_str());
+	    onHoldCall (current_call_id);
+	}
+	// if we are talking to a conference and we are answering an incoming call
+	else if (isConference(current_call_id) && !participToConference(call_id))
+	{
+	    _debug ("    answerCall: detach main participant from conference\n");
+	    detachParticipant(default_id, current_call_id);
+	}
+    }
+
+    if (!getAccountLink (account_id)->answer (call_id)) {
         // error when receiving...
-        removeCallAccount (id);
+        removeCallAccount (call_id);
         return false;
     }
 
     // if it was waiting, it's waiting no more
-    if (_dbus) _dbus->getCallManager()->callStateChanged (id, "CURRENT");
-
-    std::string codecName = Manager::instance().getCurrentCodecName (id);
+    if (_dbus) _dbus->getCallManager()->callStateChanged (call_id, "CURRENT");
+        
+    std::string codecName = Manager::instance().getCurrentCodecName (call_id);
+    if (_dbus) _dbus->getCallManager()->currentSelectedCodec (call_id, codecName.c_str());
+        
+    removeWaitingCall (call_id);
 
-    if (_dbus) _dbus->getCallManager()->currentSelectedCodec (id,codecName.c_str());
-
-    removeWaitingCall (id);
-
-    switchCall (id);
+    switchCall (call_id);
 
     return true;
 }
 
 //THREAD=Main
 bool
-ManagerImpl::hangupCall (const CallID& id)
+ManagerImpl::hangupCall (const CallID& call_id)
 {
-    _debug ("ManagerImpl::hangupCall()\n");
+    _debug ("ManagerImpl::hangupCall(%s)\n", call_id.c_str());
     PulseLayer *pulselayer;
-    AccountID accountid;
+    AccountID account_id;
     bool returnValue;
     AudioLayer *audiolayer;
 
+    // store the current call id
+    CallID current_call_id = getCurrentCallId();
+
     stopTone (false);
+    // switchCall (call_id);
 
     /* Broadcast a signal over DBus */
+    _debug("    hangupCall: Send DBUS call state change (HUNGUP) for id %s\n", call_id.c_str());
+    if (_dbus) _dbus->getCallManager()->callStateChanged (call_id, "HUNGUP");
 
-    if (_dbus) _dbus->getCallManager()->callStateChanged (id, "HUNGUP");
-
-    _debug ("Stop audio stream\n");
+    int nbCalls = getCallList().size();
 
     audiolayer = getAudioDriver();
+    // stop streamx
+    if (! (nbCalls >= 1))
+    {
+	_debug("    hangupCall: stop audio stream, ther is only %i call(s) remaining\n", nbCalls);
+        audiolayer->stopStream();
+    }
+   
+    if(participToConference(call_id))
+    {
 
-    int nbCalls = getCallList().size();
+	Conference *conf = getConferenceFromCallID(call_id);
 
-    _debug ("hangupCall: callList is of size %i call(s)\n", nbCalls);
+	if(conf != NULL)
+	{
+	    // remove this participant
+	    removeParticipant(call_id);
 
-    // stop stream
-    if (! (nbCalls > 1))
-        audiolayer->stopStream();
+	    processRemainingParticipant(current_call_id, conf);
+	}
+    }
+    else
+    {
+	// we are not participating to a conference, current call switched to ""
+	if (!isConference(current_call_id))
+	    switchCall("");
+    }
 
     /* Direct IP to IP call */
-    if (getConfigFromCall (id) == Call::IPtoIP) {
-        returnValue = SIPVoIPLink::instance (AccountNULL)->hangup (id);
+    if (getConfigFromCall (call_id) == Call::IPtoIP) {
+        returnValue = SIPVoIPLink::instance (AccountNULL)->hangup (call_id);
     }
-
     /* Classic call, attached to an account */
     else {
-        accountid = getAccountFromCall (id);
+        account_id = getAccountFromCall (call_id);
 
-        if (accountid == AccountNULL) {
+        if (account_id == AccountNULL) 
+	{
             _debug ("! Manager Hangup Call: Call doesn't exists\n");
             return false;
         }
 
-        returnValue = getAccountLink (accountid)->hangup (id);
+        returnValue = getAccountLink (account_id)->hangup (call_id);
 
-        removeCallAccount (id);
+        removeCallAccount (call_id);
     }
 
-    switchCall ("");
-
     if (_audiodriver->getLayerType() == PULSEAUDIO && getConfigInt (PREFERENCES , CONFIG_PA_VOLUME_CTRL)) {
         pulselayer = dynamic_cast<PulseLayer *> (getAudioDriver());
 
         if (pulselayer)  pulselayer->restorePulseAppsVolume();
     }
 
+    return returnValue;
+}
+
 
+bool
+ManagerImpl::hangupConference (const ConfID& id)
+{
+    _debug ("ManagerImpl::hangupConference()\n");
 
-    return returnValue;
+    Conference *conf;
+    ConferenceMap::iterator iter_conf = _conferencemap.find(id);
+
+    AccountID currentAccountId;
+
+    // Call* call = NULL;
+
+    if(iter_conf != _conferencemap.end())
+    {
+	conf = iter_conf->second;
+ 
+	ParticipantSet participants = conf->getParticipantList();
+	ParticipantSet::iterator iter_participant = participants.begin();
+
+	while(iter_participant != participants.end())
+	{
+	    _debug("ManagerImpl::hangupConference participant %s\n", (*iter_participant).c_str());
+
+	    hangupCall (*iter_participant);
+
+	    iter_participant++;
+
+	}
+
+    }
+
+    switchCall ("");
+
+    return true;
 }
 
+
 //THREAD=Main
 bool
 ManagerImpl::cancelCall (const CallID& id)
@@ -438,37 +545,38 @@ ManagerImpl::cancelCall (const CallID& id)
 
 //THREAD=Main
 bool
-ManagerImpl::onHoldCall (const CallID& id)
+ManagerImpl::onHoldCall (const CallID& call_id)
 {
-    AccountID accountid;
+    AccountID account_id;
     bool returnValue;
-    CallID call_id;
+
+    _debug("ManagerImpl::onHoldCall(%s)\n", call_id.c_str());
 
     stopTone (true);
 
-    call_id = id;
+    // switchCall (id);
 
     /* Direct IP to IP call */
 
-    if (getConfigFromCall (id) == Call::IPtoIP) {
-        returnValue = SIPVoIPLink::instance (AccountNULL)-> onhold (id);
+    if (getConfigFromCall (call_id) == Call::IPtoIP) {
+        returnValue = SIPVoIPLink::instance (AccountNULL)-> onhold (call_id);
     }
 
     /* Classic call, attached to an account */
     else {
-        accountid = getAccountFromCall (id);
+        account_id = getAccountFromCall (call_id);
 
-        if (accountid == AccountNULL) {
-            _debug ("Manager On Hold Call: Account ID %s or callid %s doesn't exists\n", accountid.c_str(), id.c_str());
+        if (account_id == AccountNULL) {
+            _debug ("    onHoldCall: Account ID %s or callid %s doesn't exists\n", account_id.c_str(), call_id.c_str());
             return false;
         }
 
-        returnValue = getAccountLink (accountid)->onhold (id);
+        returnValue = getAccountLink (account_id)->onhold (call_id);
     }
+    
+    removeWaitingCall (call_id);
 
-    removeWaitingCall (id);
-
-    switchCall ("");
+    // switchCall ("");
 
     if (_dbus) _dbus->getCallManager()->callStateChanged (call_id, "HOLD");
 
@@ -477,60 +585,88 @@ ManagerImpl::onHoldCall (const CallID& id)
 
 //THREAD=Main
 bool
-ManagerImpl::offHoldCall (const CallID& id)
+ManagerImpl::offHoldCall (const CallID& call_id)
 {
 
-    AccountID accountid;
-    bool returnValue, rec;
+    AccountID account_id;
+    bool returnValue, is_rec;
     std::string codecName;
-    CallID call_id;
+
+
+    _debug ("ManagerImpl::offHoldCall(%s)\n", call_id.c_str());
 
     stopTone (false);
 
-    call_id = id;
-    //Place current call on hold if it isn't
+    CallID current_call_id = getCurrentCallId();
 
-    if (hasCurrentCall()) {
-        _debug ("Put the current call (ID=%s) on hold\n", getCurrentCallId().c_str());
-        onHoldCall (getCurrentCallId());
-    }
+    //Place current call on hold if it isn't
+    if (hasCurrentCall()) 
+    {
+	// if this is not a conferenceand this and is not a conference participant
+	if (!isConference(current_call_id) && !participToConference(current_call_id))
+	{
+	    _debug ("    offHoldCall: put current call (%s) on hold\n", current_call_id.c_str());
+	    onHoldCall (current_call_id);
+	}
+	else if (isConference(current_call_id) && !participToConference(call_id))
+	{
+	    _debug ("    offHoldCall Put current conference (%s) on hold\n", current_call_id.c_str());
+	    detachParticipant(default_id, current_call_id);
+	}
+    }
+
+    // switch current call id to id since sipvoip link need it to amke a call 
+    // switchCall(id);
 
     /* Direct IP to IP call */
-    if (getConfigFromCall (id) == Call::IPtoIP) {
-        rec = SIPVoIPLink::instance (AccountNULL)-> isRecording (id);
-        returnValue = SIPVoIPLink::instance (AccountNULL)-> offhold (id);
+    if (getConfigFromCall (call_id) == Call::IPtoIP) {
+        // is_rec = SIPVoIPLink::instance (AccountNULL)-> isRecording (call_id);
+        returnValue = SIPVoIPLink::instance (AccountNULL)-> offhold (call_id);
     }
 
     /* Classic call, attached to an account */
     else {
-        accountid = getAccountFromCall (id);
+        account_id = getAccountFromCall (call_id);
 
-        if (accountid == AccountNULL) {
+        if (account_id == AccountNULL) {
             _debug ("Manager OffHold Call: Call doesn't exists\n");
             return false;
         }
 
-        _debug ("Setting OFFHOLD, Account %s, callid %s\n", accountid.c_str(), id.c_str());
+        _debug ("Setting OFFHOLD, Account %s, callid %s\n", account_id.c_str(), call_id.c_str());
 
-        rec = getAccountLink (accountid)->isRecording (id);
-        returnValue = getAccountLink (accountid)->offhold (id);
+        is_rec = getAccountLink (account_id)->getCall(call_id)->isRecording();
+        returnValue = getAccountLink (account_id)->offhold (call_id);
     }
 
 
     if (_dbus) {
-        if (rec)
+        if (is_rec)
             _dbus->getCallManager()->callStateChanged (call_id, "UNHOLD_RECORD");
         else
             _dbus->getCallManager()->callStateChanged (call_id, "UNHOLD_CURRENT");
 
     }
 
-    switchCall (id);
+    if ( participToConference(call_id) ) {
+	 
+	AccountID currentAccountId;
+        Call* call = NULL;
+
+	currentAccountId = getAccountFromCall (call_id);
+	call = getAccountLink (currentAccountId)->getCall (call_id);
+	
+	switchCall(call->getConfId());
+    }
+    else
+    {
+	switchCall(call_id);
+    }
 
-    codecName = getCurrentCodecName (id);
+    codecName = getCurrentCodecName (call_id);
     // _debug("ManagerImpl::hangupCall(): broadcast codec name %s \n",codecName.c_str());
 
-    if (_dbus) _dbus->getCallManager()->currentSelectedCodec (id,codecName.c_str());
+    if (_dbus) _dbus->getCallManager()->currentSelectedCodec (call_id,codecName.c_str());
 
     return returnValue;
 }
@@ -627,6 +763,678 @@ ManagerImpl::refuseCall (const CallID& id)
     return returnValue;
 }
 
+
+Conference*
+ManagerImpl::createConference(const CallID& id1, const CallID& id2)
+{
+    _debug("ManagerImpl::createConference()\n");
+    
+    Conference* conf = new Conference();
+
+    // _conferencecall.insert(pair<CallID, Conference*>(id1, conf));
+    // _conferencecall.insert(pair<CallID, Conference*>(id2, conf));
+    _conferencemap.insert(pair<CallID, Conference*>(conf->getConfID(), conf));
+
+    conf->add(id1);
+    conf->add(id2);
+
+    // broadcast a signal over dbus
+    _dbus->getCallManager()->conferenceCreated(conf->getConfID());
+    
+    return conf;
+}
+
+void
+ManagerImpl::removeConference(const ConfID& conference_id)
+{
+
+    _debug("ManagerImpl::removeConference(%s)\n", conference_id.c_str());
+
+    Conference* conf = NULL;
+
+    _debug("    removeConference: _conferencemap.size: %i\n", _conferencemap.size());
+    ConferenceMap::iterator iter = _conferencemap.find(conference_id);
+
+    if (iter != _conferencemap.end()) {
+	_debug("    removeConference: Found conference id %s in conferencemap\n", conference_id.c_str());
+        conf = iter->second;
+    }
+
+    if(conf == NULL) {
+
+	_debug("    removeConference: Error conference not found\n");
+	return;
+    }
+
+
+    // We now need to bind the audio to the remain participant
+
+    // unbind main participant from conference (just to be sure)
+    _audiodriver->getMainBuffer()->unBindAll(default_id);
+
+    ParticipantSet participants = conf->getParticipantList();
+
+    // bind main participant to remaining conference call
+    ParticipantSet::iterator iter_p = participants.begin();
+    if (iter_p != participants.end()) {
+
+	// to avoid puting onhold the call
+	// switchCall("");	
+	_audiodriver->getMainBuffer()->bindCallID(*iter_p, default_id);
+    }
+    
+    // Then remove the conference from the conference map
+    _debug("ManagerImpl:: remove conference %s\n", conference_id.c_str());
+    if (_conferencemap.erase(conference_id) == 1)
+        _debug("ManagerImpl:: conference %s removed succesfully\n", conference_id.c_str());
+    else
+	_debug("ManagerImpl:: error cannot remove conference id: %s\n", conference_id.c_str());
+
+    // broadcast a signal over dbus
+    _debug("ManagerImpl::removeConference broadcast call removed on dbus: %s\n", conference_id.c_str());
+    _dbus->getCallManager()->conferenceRemoved(conference_id);
+
+}
+
+
+Conference*
+ManagerImpl::getConferenceFromCallID(const CallID& call_id)
+{
+    AccountID account_id;
+    Call* call = NULL;
+
+    account_id = getAccountFromCall (call_id);
+    call = getAccountLink (account_id)->getCall (call_id);
+
+    ConferenceMap::iterator iter = _conferencemap.find(call->getConfId());
+    if(iter != _conferencemap.end())
+    {
+	return iter->second;
+    }
+    else
+    {
+	return NULL;
+    }
+}
+
+void
+ManagerImpl::holdConference(const CallID& id)
+{
+    _debug ("ManagerImpl::holdConference()\n");
+
+    Conference *conf;
+    ConferenceMap::iterator iter_conf = _conferencemap.find(id);
+
+    AccountID currentAccountId;
+
+    Call* call = NULL;
+
+    if(iter_conf != _conferencemap.end())
+    {
+	conf = iter_conf->second;
+
+	ParticipantSet participants = conf->getParticipantList();
+	ParticipantSet::iterator iter_participant = participants.begin();
+
+	while(iter_participant != participants.end())
+	{
+	    _debug("    holdConference: participant %s\n", (*iter_participant).c_str());
+	    currentAccountId = getAccountFromCall (*iter_participant);
+	    call = getAccountLink (currentAccountId)->getCall (*iter_participant);
+
+	    switchCall(*iter_participant);
+	    onHoldCall(*iter_participant);
+
+	    iter_participant++;
+
+	}
+
+	conf->setState(Conference::Hold);
+
+	_dbus->getCallManager()->conferenceChanged(conf->getConfID(), conf->getStateStr());
+
+    }
+
+    
+
+    
+}
+
+
+void
+ManagerImpl::unHoldConference(const CallID& id)
+{
+
+    _debug ("ManagerImpl::unHoldConference()\n");
+
+    Conference *conf;
+    ConferenceMap::iterator iter_conf = _conferencemap.find(id);
+
+    AccountID currentAccountId;
+
+    Call* call = NULL;
+
+    if(iter_conf != _conferencemap.end())
+    {
+	conf = iter_conf->second;
+ 
+	ParticipantSet participants = conf->getParticipantList();
+	ParticipantSet::iterator iter_participant = participants.begin();
+
+	while(iter_participant != participants.end())
+	{
+	    _debug("    unholdConference: participant %s\n", (*iter_participant).c_str());
+	    currentAccountId = getAccountFromCall (*iter_participant);
+	    call = getAccountLink (currentAccountId)->getCall (*iter_participant);
+
+	    offHoldCall(*iter_participant);
+
+	    iter_participant++;
+
+	}
+
+	conf->setState(Conference::Active_Atached);
+
+	_dbus->getCallManager()->conferenceChanged(conf->getConfID(), conf->getStateStr());
+
+    }
+
+}
+
+bool
+ManagerImpl::isConference(const CallID& id)
+{
+    ConferenceMap::iterator iter = _conferencemap.find(id);
+    if(iter == _conferencemap.end()) {
+	return false;
+    }
+    else {
+	return true;
+    }
+}
+
+bool
+ManagerImpl::participToConference(const CallID& call_id)
+{
+
+    AccountID accountId;
+
+    Call* call = NULL;
+
+    accountId = getAccountFromCall (call_id);
+    call = getAccountLink (accountId)->getCall(call_id);
+
+    if (call == NULL)
+	return false;
+
+    if(call->getConfId() == "") {
+	return false;
+    }
+    else {
+	return true;
+    }
+}
+
+
+void
+ManagerImpl::addParticipant(const CallID& call_id, const CallID& conference_id)
+{
+    _debug("ManagerImpl::addParticipant(%s, %s)\n", call_id.c_str(), conference_id.c_str());
+
+    std::map<std::string, std::string> call_details = getCallDetails(call_id);
+
+    ConferenceMap::iterator iter = _conferencemap.find(conference_id);
+    std::map<std::string, std::string>::iterator iter_details;
+
+    // store the current call id (it will change in offHoldCall or in answerCall)
+    CallID current_call_id = getCurrentCallId();
+
+    _debug("    addParticipant: enter main process\n");
+    if(iter != _conferencemap.end()) {
+
+	Conference* conf = iter->second;
+
+	conf->add(call_id);
+	
+
+	iter_details = call_details.find("CALL_STATE");
+
+	switchCall("");
+
+	_debug("    addParticipant: call state: %s\n", iter_details->second.c_str());
+	if (iter_details->second == "HOLD")
+	{
+	    _debug("    OFFHOLD %s\n", call_id.c_str());
+
+	    // offHoldCall create a new rtp session which use addStream to bind participant
+	    offHoldCall(call_id);
+	}
+	else if(iter_details->second == "INCOMING")
+	{
+	    _debug("    ANSWER %s\n", call_id.c_str());
+	    // answerCall create a new rtp session which use addStream to bind participant
+	    answerCall(call_id);
+	}
+	else if(iter_details->second == "CURRENT")
+	{
+	    // Already a curent call, so we beed to reset audio stream bindings manually
+	    _audiodriver->getMainBuffer()->unBindAll(call_id);
+	    conf->bindParticipant(call_id);
+	}
+
+	// update this call conference id
+	AccountID currentAccountId;
+
+        Call* call = NULL;
+
+	currentAccountId = getAccountFromCall (call_id);
+	call = getAccountLink (currentAccountId)->getCall (call_id);
+	call->setConfId (conf->getConfID());
+
+	_dbus->getCallManager()->conferenceChanged(conference_id, conf->getStateStr());
+    }
+    {
+	_debug("    addParticipant: Error, conference %s conference_id not found!\n", conference_id.c_str());
+    }
+
+
+    // bind main participant to conference after adding new participant 
+    detachParticipant(default_id, current_call_id);
+
+    // to avoid puting onhold the added call
+    switchCall("");
+    addMainParticipant(conference_id);
+
+    
+    
+    
+}
+
+void
+ManagerImpl::addMainParticipant(const CallID& conference_id)
+{
+    if(hasCurrentCall())
+    {
+	CallID current_call_id = getCurrentCallId();
+
+	if(isConference(current_call_id))
+	{
+	    detachParticipant(default_id, current_call_id);
+	}    
+	else
+	{
+	    onHoldCall(current_call_id);
+	}
+    }
+
+    ConferenceMap::iterator iter = _conferencemap.find(conference_id);
+
+    Conference *conf = NULL;
+
+    if(iter != _conferencemap.end()) 
+    {
+	conf = iter->second;
+
+	ParticipantSet participants = conf->getParticipantList();
+
+	ParticipantSet::iterator iter_participant = participants.begin();
+	while(iter_participant != participants.end())
+	{
+	    _audiodriver->getMainBuffer()->bindCallID(*iter_participant, default_id);
+	    
+	    iter_participant++;
+	}
+
+	conf->setState(Conference::Active_Atached);
+
+	_dbus->getCallManager()->conferenceChanged(conference_id, conf->getStateStr());
+	
+    }
+
+    switchCall(conference_id);
+}
+
+
+void
+ManagerImpl::joinParticipant(const CallID& call_id1, const CallID& call_id2)
+{
+    _debug("ManagerImpl::joinParticipant(%s, %s)\n", call_id1.c_str(), call_id2.c_str());
+    // _debug("    Current call ID %s\n", getCurrentCallId().c_str());
+
+    std::map<std::string, std::string> call1_details = getCallDetails(call_id1);
+    std::map<std::string, std::string> call2_details = getCallDetails(call_id2);
+
+    ConferenceMap::iterator iter = _conferencemap.find(default_conf);
+    std::map<std::string, std::string>::iterator iter_details;
+
+    AccountID currentAccountId;
+    Call* call = NULL;
+
+    CallID current_call_id = getCurrentCallId();
+    _debug("    joinParticipant: current_call_id %s\n", current_call_id.c_str());
+
+
+    // detach from the conference and switch to this conference 
+    if ((current_call_id != call_id1) && (current_call_id != call_id2))
+    {
+	if (isConference(current_call_id))
+	    detachParticipant(default_id, current_call_id);
+	else
+	    onHoldCall(current_call_id);
+    }
+
+    if(iter == _conferencemap.end()){
+
+	 _debug("    joinParticipant: create a conference\n");
+	 Conference *conf = createConference(call_id1, call_id2);
+
+	 // AccountID currentAccountId;
+	 // Call* call = NULL;
+
+	 // unbind main participant from either call_id1 or call_id2
+	 // _audiodriver->getMainBuffer()->unBindAll(default_id);
+
+	 switchCall("");
+
+	 iter_details = call1_details.find("CALL_STATE");
+	 _debug("    joinParticipant: call1 %s state: %s\n", call_id1.c_str(), iter_details->second.c_str());
+	 if (iter_details->second == "HOLD")
+	 {
+	     _debug("    OFFHOLD %s\n", call_id1.c_str());
+	     offHoldCall(call_id1);
+	 }
+	 else if(iter_details->second == "INCOMING")
+	 {
+	     _debug("    ANSWER %s\n", call_id1.c_str());
+	     answerCall(call_id1);
+	 }
+	 else if(iter_details->second == "CURRENT")
+	 {
+	     _debug("    CURRENT %s\n", call_id1.c_str());
+	     _audiodriver->getMainBuffer()->unBindAll(call_id1);
+	     conf->bindParticipant(call_id1);
+	 }
+
+	 currentAccountId = getAccountFromCall (call_id1);
+	 call = getAccountLink (currentAccountId)->getCall (call_id1);
+	 call->setConfId (conf->getConfID());
+
+
+	 switchCall("");
+
+	 iter_details = call2_details.find("CALL_STATE");
+	 _debug("    joinParticipant: call2 %s state: %s\n", call_id2.c_str(), iter_details->second.c_str());
+	 if (iter_details->second == "HOLD")
+	 {
+	     _debug("    OFFHOLD %s\n", call_id2.c_str());
+	     offHoldCall (call_id2);
+	 }
+	 else if(iter_details->second == "INCOMING")
+	 {
+	     _debug("    ANSWER %s\n", call_id2.c_str());
+	     answerCall(call_id2);
+	 }
+	 else if(iter_details->second == "CURRENT")
+	 {
+	     _debug("    CURRENT %s\n", call_id2.c_str());
+	     _audiodriver->getMainBuffer()->unBindAll(call_id2);
+	     conf->bindParticipant(call_id2);
+	 }
+
+	 currentAccountId = getAccountFromCall (call_id2);
+	 call = getAccountLink (currentAccountId)->getCall (call_id2);
+	 call->setConfId (conf->getConfID());
+
+
+	 // finally bind main participant to conference
+	 // addMainParticipant(default_conf);
+
+
+	 switchCall(conf->getConfID());
+
+    }
+    else {
+
+	 _debug("ManagerImpl::joinParticipant already a conference created with this ID\n");
+	 
+    }
+
+}
+
+
+void
+ManagerImpl::detachParticipant(const CallID& call_id, const CallID& current_id)
+{
+    _debug("ManagerImpl::detachParticipant(%s)\n", call_id.c_str());
+
+    CallID current_call_id = current_id;
+    
+    if(current_call_id.compare("") == 0);
+        current_call_id = getCurrentCallId();
+
+    if(call_id != default_id)
+    {
+	AccountID currentAccountId;
+	Call* call = NULL;
+
+	currentAccountId = getAccountFromCall (call_id);
+	call = getAccountLink (currentAccountId)->getCall (call_id);
+
+	// TODO: add conference_id as a second parameter
+	ConferenceMap::iterator iter = _conferencemap.find(call->getConfId());
+
+	Conference *conf = getConferenceFromCallID(call_id);
+
+	if(conf != NULL) {
+
+	    _debug("    detachParticipant: detaching participant %s\n", call_id.c_str());
+
+	    std::map<std::string, std::string> call_details = getCallDetails(call_id);
+	    std::map<std::string, std::string>::iterator iter_details;
+
+	    iter_details = call_details.find("CALL_STATE");
+	    if (iter_details->second == "RINGING")
+	    {
+		removeParticipant(call_id);
+	    }
+	    else
+	    {
+		_debug("    ONHOLD %s\n", call_id.c_str());
+		onHoldCall(call_id);
+
+		removeParticipant(call_id);
+
+		processRemainingParticipant(current_call_id, conf);
+	    }
+	}	    
+        else {
+	
+
+	    _debug("    detachParticipant: call is not conferencing, cannot detach\n");
+       
+        }
+    }
+    else
+    {
+	_debug("    detachParticipant: unbind main participant from all\n");
+	_audiodriver->getMainBuffer()->unBindAll(default_id);
+
+	if( isConference(current_call_id) )
+	{
+
+	    ConferenceMap::iterator iter = _conferencemap.find(current_call_id);
+	    Conference *conf = iter->second;
+
+	    conf->setState(Conference::Active_Detached);
+
+	    _dbus->getCallManager()->conferenceChanged(conf->getConfID(), conf->getStateStr());
+	}
+	    
+    }
+    
+}
+
+
+void
+ManagerImpl::removeParticipant(const CallID& call_id)
+{
+    _debug("ManagerImpl::removeParticipant(%s)\n", call_id.c_str());
+
+    // TODO: add conference_id as a second parameter
+    Conference* conf;
+
+    AccountID currentAccountId;
+    Call* call = NULL;
+
+    // this call is no more a conference participant
+    currentAccountId = getAccountFromCall (call_id);
+    call = getAccountLink (currentAccountId)->getCall (call_id);
+
+    ConferenceMap conf_map = _conferencemap;
+    ConferenceMap::iterator iter = conf_map.find(call->getConfId());
+
+    if(iter == conf_map.end()) {
+	_debug("    no conference created, cannot remove participant \n");
+    }
+    else {
+
+	conf = iter->second;
+
+	_debug("    removeParticipant %s\n", call_id.c_str());
+	conf->remove(call_id);
+	call->setConfId ("");
+
+    }
+
+}
+
+
+void
+ManagerImpl::processRemainingParticipant(CallID current_call_id, Conference *conf)
+{
+
+    _debug("ManagerImpl::processRemainingParticipant()\n");
+
+    if(conf->getNbParticipants() > 1)
+    {
+
+    }
+    else if (conf->getNbParticipants() == 1)
+    {
+	AccountID currentAccountId;
+	Call* call = NULL;
+	
+	ParticipantSet participants = conf->getParticipantList();
+	ParticipantSet::iterator iter_participant = participants.begin();
+	
+	// bind main participant to remaining conference call
+	if (iter_participant != participants.end()) {
+	    
+	    // this call is no more a conference participant
+	    currentAccountId = getAccountFromCall (*iter_participant);
+	    call = getAccountLink (currentAccountId)->getCall (*iter_participant);
+	    call->setConfId ("");
+	    
+	    // if we are not listening to this conference
+	    if (current_call_id != conf->getConfID())
+	    {
+		onHoldCall(call->getCallId());
+	    }
+	    else
+	    {
+		switchCall(*iter_participant);
+	    }
+	}
+	
+	removeConference(conf->getConfID());
+    }
+    else
+    {
+	removeConference(conf->getConfID());
+	
+	switchCall("");
+    }
+
+}
+
+void
+ManagerImpl::joinConference(const CallID& conf_id1, const CallID& conf_id2)
+{
+    _debug("ManagerImpl::joinConference(%s, %s)\n", conf_id1.c_str(), conf_id2.c_str());
+    
+    ConferenceMap::iterator iter;
+
+    Conference *conf1 = NULL;
+    Conference *conf2 = NULL;
+
+    iter = _conferencemap.find(conf_id1);
+    
+    if(iter != _conferencemap.end())
+	conf1 = iter->second;
+
+    iter = _conferencemap.find(conf_id2);
+
+    if(iter != _conferencemap.end())
+	conf2 = iter->second;
+
+    ParticipantSet participants = conf1->getParticipantList();
+
+    ParticipantSet::iterator iter_participant = participants.begin();
+
+    while(iter_participant != participants.end())
+    {
+	detachParticipant(*iter_participant, "");
+	addParticipant(*iter_participant, conf_id2);
+
+	iter_participant++;
+    }
+
+    // detachParticipant(default_id, "");
+    
+}
+
+void
+ManagerImpl::addStream(const CallID& call_id)
+{
+    _debug("ManagerImpl::addStream %s\n", call_id.c_str());
+
+    AccountID currentAccountId;
+    Call* call = NULL;
+
+    currentAccountId = getAccountFromCall (call_id);
+    call = getAccountLink (currentAccountId)->getCall (call_id);
+
+    if(participToConference(call_id)) {
+
+	// bind to conference participant
+	ConferenceMap::iterator iter = _conferencemap.find(call->getConfId());
+	if (iter != _conferencemap.end())
+	{
+	    Conference* conf = iter->second;
+
+	    conf->bindParticipant(call_id);
+	}
+    }
+    else {
+
+	// bind to main 
+	getAudioDriver()->getMainBuffer()->bindCallID(call_id);
+    }
+}
+
+void
+ManagerImpl::removeStream(const CallID& call_id)
+{
+    _debug("ManagerImpl::removeStream %s\n", call_id.c_str());
+
+    getAudioDriver()->getMainBuffer()->unBindAll(call_id);
+
+    if(participToConference(call_id)) {
+	removeParticipant(call_id);
+    }
+    
+}
+
 //THREAD=Main
 bool
 ManagerImpl::saveConfig (void)
@@ -685,7 +1493,6 @@ ManagerImpl::sendDtmf (const CallID& id, char code)
     AccountID accountid = getAccountFromCall (id);
 
     if (accountid == AccountNULL) {
-        //_debug("Send DTMF: call doesn't exists\n");
         playDtmf (code, false);
         return false;
     }
@@ -728,13 +1535,19 @@ ManagerImpl::playDtmf (char code, bool isTalking)
     bool hasToPlayTone = getConfigBool (SIGNALISATION, PLAY_DTMF);
 
     if (!hasToPlayTone)
+    {
+	_debug("    playDtmf: Do not have to play a tone...\n");
         return false;
+    }
 
     // length in milliseconds
     pulselen = getConfigInt (SIGNALISATION, PULSE_LENGTH);
 
     if (!pulselen)
+    {
+	_debug("    playDtmf: Pulse length is not set...\n");
         return false;
+    }
 
     // numbers of int = length in milliseconds / 1000 (number of seconds)
     //                = number of seconds * SAMPLING_RATE by SECONDS
@@ -744,13 +1557,16 @@ ManagerImpl::playDtmf (char code, bool isTalking)
 
     // fast return, no sound, so no dtmf
     if (audiolayer==0 || _dtmfKey == 0)
+    {
+	_debug("    playDtmf: Error no audio layer...\n");
         return false;
+    }
 
     // number of data sampling in one pulselen depends on samplerate
     // size (n sampling) = time_ms * sampling/s
     //                     ---------------------
     //                            ms/s
-    size = (int) (pulselen * ( (float) audiolayer->getSampleRate() /1000));
+    size = (int) ((pulselen * (float) audiolayer->getSampleRate()) / 1000);
 
     // this buffer is for mono
     // TODO <-- this should be global and hide if same size
@@ -767,6 +1583,9 @@ ManagerImpl::playDtmf (char code, bool isTalking)
         audiolayer->startStream();
         audiolayer->putUrgent (buf, size * sizeof (SFLDataFormat));
     }
+    else {
+	_debug("    playDtmf: Error cannot play dtmf\n");
+    }
 
     ret = true;
 
@@ -835,12 +1654,12 @@ ManagerImpl::incomingCall (Call* call, const AccountID& accountId)
     if (accountId==AccountNULL)
         associateConfigToCall (call->getCallId(), Call::IPtoIP);
 
-    _debug ("ManagerImpl::incomingCall :: hasCurrentCall() %i \n",hasCurrentCall());
+    _debug ("ManagerImpl::incomingCall :: hasCurrentCall() %i \n", hasCurrentCall());
 
     if (!hasCurrentCall()) {
         call->setConnectionState (Call::Ringing);
         ringtone();
-        switchCall (call->getCallId());
+        // switchCall (call->getCallId());
 
     }
 
@@ -928,40 +1747,63 @@ ManagerImpl::peerRingingCall (const CallID& id)
 
 //THREAD=VoIP Call=Outgoing/Ingoing
 void
-ManagerImpl::peerHungupCall (const CallID& id)
+ManagerImpl::peerHungupCall (const CallID& call_id)
 {
     PulseLayer *pulselayer;
-    AccountID accountid;
+    AccountID account_id;
     bool returnValue;
 
-    /* Direct IP to IP call */
+    _debug("ManagerImpl::peerHungupCall(%s)\n", call_id.c_str());
 
-    if (getConfigFromCall (id) == Call::IPtoIP) {
-        SIPVoIPLink::instance (AccountNULL)->hangup (id);
+    // store the current call id
+    CallID current_call_id = getCurrentCallId();
+
+
+    if(participToConference(call_id))
+    {
+
+	Conference *conf = getConferenceFromCallID(call_id);
+
+	if(conf != NULL)
+	{
+
+	    removeParticipant(call_id);
+	    
+	    processRemainingParticipant(current_call_id, conf);
+	}
+    }
+    else
+    {
+	if (isCurrentCall(call_id)) 
+	{
+	    stopTone (true);
+	    switchCall ("");
+	}
+    }
+
+    /* Direct IP to IP call */
+    if (getConfigFromCall (call_id) == Call::IPtoIP) {
+        SIPVoIPLink::instance (AccountNULL)->hangup (call_id);
     }
 
     else {
-        accountid = getAccountFromCall (id);
 
-        if (accountid == AccountNULL) {
+        account_id = getAccountFromCall (call_id);
+
+        if (account_id == AccountNULL) {
             _debug ("peerHungupCall: Call doesn't exists\n");
             return;
         }
 
-        returnValue = getAccountLink (accountid)->peerHungup (id);
+        returnValue = getAccountLink (account_id)->peerHungup (call_id);
     }
 
     /* Broadcast a signal over DBus */
-    if (_dbus) _dbus->getCallManager()->callStateChanged (id, "HUNGUP");
-
-    if (isCurrentCall (id)) {
-        stopTone (true);
-        switchCall ("");
-    }
+    if (_dbus) _dbus->getCallManager()->callStateChanged (call_id, "HUNGUP");
 
-    removeWaitingCall (id);
+    removeWaitingCall (call_id);
 
-    removeCallAccount (id);
+    removeCallAccount (call_id);
 
     if (_audiodriver->getLayerType() == PULSEAUDIO && getConfigInt (PREFERENCES , CONFIG_PA_VOLUME_CTRL)) {
         pulselayer = dynamic_cast<PulseLayer *> (getAudioDriver());
@@ -1873,19 +2715,32 @@ ManagerImpl::setVolumeControls (void)
 void
 ManagerImpl::setRecordingCall (const CallID& id)
 {
+    /*
     _debug ("ManagerImpl::setRecording()! \n");
     AccountID accountid = getAccountFromCall (id);
 
     getAccountLink (accountid)->setRecording (id);
+    */
+    AccountID accountid = getAccountFromCall (id);
+    Recordable* rec = (Recordable*)getAccountLink (accountid)->getCall(id);
+
+    rec->setRecording();
 }
 
 bool
 ManagerImpl::isRecording (const CallID& id)
 {
+    /*
     _debug ("ManagerImpl::isRecording()! \n");
     AccountID accountid = getAccountFromCall (id);
 
     return getAccountLink (accountid)->isRecording (id);
+    */
+
+    AccountID accountid = getAccountFromCall (id);
+    Recordable* rec = (Recordable*)getAccountLink (accountid)->getCall(id);
+
+    return rec->isRecording();
 }
 
 void
@@ -2321,6 +3176,7 @@ ManagerImpl::getCallStatus (const std::string& sequenceId UNUSED)
             switch (call->getState()) {
 
                 case Call::Active:
+	        case Call::Conferencing:
                     code="112";
                     status = "Established";
                     break;
@@ -3626,3 +4482,68 @@ ManagerImpl::getCallList (void)
 
     return v;
 }
+
+
+std::map< std::string, std::string > 
+ManagerImpl::getConferenceDetails(const ConfID& confID)
+{
+
+    std::map<std::string, std::string> conf_details;
+    ConferenceMap::iterator iter_conf;
+
+    iter_conf = _conferencemap.find(confID);
+
+    Conference *conf = NULL;
+    if(iter_conf != _conferencemap.end()) {
+
+	
+        conf_details.insert (std::pair<std::string, std::string> ("CONFID", confID));
+        conf_details.insert (std::pair<std::string, std::string> ("CONF_STATE", conf->getStateStr()));
+    }
+
+    return conf_details;
+}
+
+
+std::vector< std::string >
+ManagerImpl::getConferenceList (void)
+{
+    _debug("ManagerImpl::getConferenceList\n");
+    std::vector< std::string > v;
+
+    ConferenceMap::iterator iter = _conferencemap.begin();
+    while (iter != _conferencemap.end ()) {
+        v.push_back (iter->first);
+        iter++;
+    }
+
+    return v;
+}
+
+
+std::vector< std::string >
+ManagerImpl::getParticipantList (const std::string& confID)
+{
+    _debug("ManagerImpl::getParticipantList\n");
+    std::vector< std::string > v;
+
+    ConferenceMap::iterator iter_conf = _conferencemap.find(confID);
+    Conference *conf = NULL;
+    if(iter_conf != _conferencemap.end())
+        conf = iter_conf->second;
+
+    if(conf != NULL)
+    {
+	ParticipantSet participants = conf->getParticipantList();
+	ParticipantSet::iterator iter_participant = participants.begin();
+	while (iter_participant != participants.end ()) {
+
+	    v.push_back (*iter_participant);
+	    
+	    iter_participant++;
+	}
+    }
+
+    return v;
+}
+
diff --git a/sflphone-common/src/managerimpl.h b/sflphone-common/src/managerimpl.h
index d5c2c1d3b0a00d3e7f3d2c5934b74ca0f4b0020f..bf25eecd1466af17b2a13fb08d0f914e36dcb524 100644
--- a/sflphone-common/src/managerimpl.h
+++ b/sflphone-common/src/managerimpl.h
@@ -35,6 +35,7 @@
 
 #include "account.h"
 #include "call.h"
+#include "conference.h"
 #include "numbercleaner.h"
 
 #include "audio/sound/tonelist.h"  // for Tone::TONEID declaration
@@ -46,6 +47,13 @@ class AudioLayer;
 class GuiFramework;
 class TelephoneTone;
 class VoIPLink;
+
+// class Conference;
+
+#ifdef USE_ZEROCONF
+class DNSService;
+#endif
+
 class HistoryManager;
 class SIPAccount;
 
@@ -63,6 +71,16 @@ typedef std::set<CallID> CallIDSet;
 /** To send multiple string */
 typedef std::list<std::string> TokenList;
 
+/** To store conference objects by call ids 
+    used to retreive the conference according to a call */
+typedef std::map<CallID, Conference*> ConferenceCallMap;
+
+/** To store conference objects by conference ids */
+typedef std::map<CallID, Conference*> ConferenceMap;
+
+static CallID default_conf = "conf"; 
+
+
 static char * mapStateToChar[] = {
     (char*) "UNREGISTERED",
     (char*) "TRYING",
@@ -136,6 +154,14 @@ class ManagerImpl {
      */
     bool hangupCall(const CallID& id);
 
+
+    /**
+     * Functions which occur with a user's action
+     * Hangup the conference (hangup every participants)
+     * @param id  The call identifier
+     */
+    bool hangupConference(const ConfID& id);
+
     /**
      * Functions which occur with a user's action
      * Cancel the call
@@ -182,6 +208,38 @@ class ManagerImpl {
      */
     bool refuseCall(const CallID& id);
 
+    Conference* createConference(const CallID& id1, const CallID& id2);
+
+    void removeConference(const CallID& conference_id);
+
+    Conference* getConferenceFromCallID(const CallID& call_id);
+
+    void holdConference(const CallID& conferece_id);
+
+    void unHoldConference(const CallID& conference_id);
+
+    bool isConference(const CallID& call_id);
+
+    bool participToConference(const CallID& call_id);
+
+    void addParticipant(const CallID& call_id, const CallID& conference_id);
+
+    void addMainParticipant(const CallID& conference_id);
+
+    void joinParticipant(const CallID& call_id1, const CallID& call_id2);
+
+    void detachParticipant(const CallID& call_id, const CallID& current_call_id);
+
+    void removeParticipant(const CallID& call_id);
+
+    void processRemainingParticipant(CallID current_call_id, Conference *conf);
+
+    void joinConference(const CallID& conf_id1, const CallID& conf_id2);
+
+    void addStream(const CallID& call_id);
+
+    void removeStream(const CallID& call_id);
+
     /**
      * Save config to file
      * @return true on success
@@ -325,6 +383,26 @@ class ManagerImpl {
      */
     std::vector< std::string >  getCallList (void);
 
+    /**
+     * Retrieve details about a given call
+     * @param callID	  The account identifier
+     * @return std::map< std::string, std::string > The call details
+     */
+    std::map< std::string, std::string > getConferenceDetails(const CallID& callID);
+
+    /**
+     * Get call list
+     * @return std::vector<std::string> A list of call IDs
+     */
+    std::vector< std::string >  getConferenceList (void);
+
+
+    /**
+     * Get a list of participant to a conference
+     * @return std::vector<std::string> A list of call IDs
+     */
+    std::vector< std::string >  getParticipantList (const std::string& confID);
+
     /**
      * Save the details of an existing account, given the account ID
      * This will load the configuration map with the given data.
@@ -1167,6 +1245,13 @@ class ManagerImpl {
 
     int isStunEnabled (void);
     void enableStun (void);
+
+    // Map 
+    ConferenceCallMap _conferencecall;
+
+    // 
+    ConferenceMap _conferencemap;
+
 private:
 
     // Copy Constructor
diff --git a/sflphone-common/src/plug-in/audiorecorder/audiorecord.cpp b/sflphone-common/src/plug-in/audiorecorder/audiorecord.cpp
index dc4bfa1b1eb0a800c9cb1e703830ac8edd429f82..466b6daffb0ade81a9e6a78baf42071b90d04938 100644
--- a/sflphone-common/src/plug-in/audiorecorder/audiorecord.cpp
+++ b/sflphone-common/src/plug-in/audiorecorder/audiorecord.cpp
@@ -68,7 +68,7 @@ void AudioRecord::setSndSamplingRate (int smplRate)
     sndSmplRate_ = smplRate;
 }
 
-void AudioRecord::setRecordingOption (FILE_TYPE type, SOUND_FORMAT format, int sndSmplRate, std::string path, std::string id)
+void AudioRecord::setRecordingOption (FILE_TYPE type, SOUND_FORMAT format, int sndSmplRate, std::string path)
 {
 
 
@@ -76,7 +76,6 @@ void AudioRecord::setRecordingOption (FILE_TYPE type, SOUND_FORMAT format, int s
     sndFormat_ = format;
     channels_ = 1;
     sndSmplRate_ = sndSmplRate;
-    call_id_ = id;
 
     savePath_ = path + "/";
 
diff --git a/sflphone-common/src/plug-in/audiorecorder/audiorecord.h b/sflphone-common/src/plug-in/audiorecorder/audiorecord.h
index 679625090403ac097ff40d1da5a64feb1aa86658..de61da019c6b24a4ca05df58025deeeeb03ae1ca 100644
--- a/sflphone-common/src/plug-in/audiorecorder/audiorecord.h
+++ b/sflphone-common/src/plug-in/audiorecorder/audiorecord.h
@@ -45,7 +45,7 @@ public:
   
   void setSndSamplingRate(int smplRate);
 
-  void setRecordingOption(FILE_TYPE type, SOUND_FORMAT format, int sndSmplRate, std::string path, std::string id);
+  void setRecordingOption(FILE_TYPE type, SOUND_FORMAT format, int sndSmplRate, std::string path);
 
   void initFileName( std::string peerNumber );
 
@@ -226,11 +226,6 @@ protected:
    * Path for this recording
    */
   std::string savePath_;
-  
-  /**
-   * Path for this recordingId for this call
-   */
-  std::string call_id_;
  
 };
 
diff --git a/sflphone-common/src/sip/sdp.cpp b/sflphone-common/src/sip/sdp.cpp
index d7be80a83a33a2467921497e7a2f9d86bea648ac..489e042cf606ad688825c63e90ce59c1f3febdb0 100644
--- a/sflphone-common/src/sip/sdp.cpp
+++ b/sflphone-common/src/sip/sdp.cpp
@@ -177,16 +177,24 @@ int Sdp::create_initial_offer()
     status = create_local_offer();
 
     if (status != PJ_SUCCESS) {
+	_debug ("    Error: Failled to create initial offer\n");
         return status;
     }
 
     // Create the SDP negociator instance with local offer
     status = pjmedia_sdp_neg_create_w_local_offer (_pool, get_local_sdp_session(), &_negociator);
 
+    if (status != PJ_SUCCESS) {
+	_debug ("    Error: Failled to create an initial SDP negociator\n");
+        return status;
+    }
+
     state = pjmedia_sdp_neg_get_state (_negociator);
 
     PJ_ASSERT_RETURN (status == PJ_SUCCESS, 1);
 
+    _debug ("    Initial offer created succesfully\n");
+
     return PJ_SUCCESS;
 }
 
diff --git a/sflphone-common/src/sip/sipcall.cpp b/sflphone-common/src/sip/sipcall.cpp
index e3c71e3fbf4c6aa1ed325e0cbc0a9e0ae1ed719c..81451d591362ba448aacd0428734d5f58165eefe 100644
--- a/sflphone-common/src/sip/sipcall.cpp
+++ b/sflphone-common/src/sip/sipcall.cpp
@@ -28,6 +28,7 @@ SIPCall::SIPCall (const CallID& id, Call::CallType type, pj_pool_t *pool) : Call
         , _cid (0)
         , _did (0)
         , _tid (0)
+	, _audiortp (new sfl::AudioRtpFactory())
         , _xferSub (NULL)
         , _invSession (NULL)
         , _local_sdp (0)
@@ -38,7 +39,8 @@ SIPCall::SIPCall (const CallID& id, Call::CallType type, pj_pool_t *pool) : Call
 
 SIPCall::~SIPCall()
 {
-
+    delete _audiortp;
+    _audiortp = 0;
     delete _local_sdp;
     _local_sdp = 0;
     _debug ("SIPCALL::Destructor for this class is called \n");
diff --git a/sflphone-common/src/sip/sipcall.h b/sflphone-common/src/sip/sipcall.h
index 8476febb57992d9b08f16229fd14d04cce3a9033..f2d93259da6872000a51a3491da79e2d37eef3b4 100644
--- a/sflphone-common/src/sip/sipcall.h
+++ b/sflphone-common/src/sip/sipcall.h
@@ -26,8 +26,15 @@
 #include <pjsip-simple/evsub.h>
 #include <pjsip_ua.h>
 
+#include "audio/audiortp/AudioRtpFactory.h"
+
 class AudioCodec;
 class Sdp;
+class AudioRtp;
+
+namespace sfl {
+    class AudioRtpFactory;
+}
 
 /**
  * @file sipcall.h
@@ -79,6 +86,8 @@ class SIPCall : public Call
      * @return int  SIP transaction id
      */
     int  getTid() { return _tid; }
+
+    
     
     
     /** 
@@ -97,6 +106,9 @@ class SIPCall : public Call
 
     void setLocalSDP (Sdp *local_sdp) { _local_sdp = local_sdp; }
 
+    /** Returns a pointer to the AudioRtp object */
+    inline sfl::AudioRtpFactory * getAudioRtp(void) { return _audiortp; }
+
   private:
 
     int _cid;
@@ -108,8 +120,10 @@ class SIPCall : public Call
 
     // Assignment Operator
     SIPCall& operator=( const SIPCall& rh);
-    
-    
+
+    /** Starting sound */
+    sfl::AudioRtpFactory * _audiortp;
+
     pjsip_evsub *_xferSub;
     
 	pjsip_inv_session *_invSession;
diff --git a/sflphone-common/src/sip/sipvoiplink.cpp b/sflphone-common/src/sip/sipvoiplink.cpp
index a9aa8bbe3db864bcea4d7f45f3b461937bd7fb0d..be814b18afee2ec44ae9c6a4bd97ee06110592f4 100644
--- a/sflphone-common/src/sip/sipvoiplink.cpp
+++ b/sflphone-common/src/sip/sipvoiplink.cpp
@@ -161,7 +161,7 @@ void call_on_state_changed (pjsip_inv_session *inv, pjsip_event *e);
  * @param	inv	A pointer on a pjsip_inv_session structure
  * @param	status	A pj_status_t structure
  */
-void call_on_media_update (pjsip_inv_session *inv UNUSED, pj_status_t status UNUSED);
+void call_on_media_update (pjsip_inv_session *inv, pj_status_t status UNUSED);
 
 /*
  * Called when the invite usage module has created a new dialog and invite
@@ -226,8 +226,7 @@ SIPVoIPLink::SIPVoIPLink (const AccountID& accountID)
         , _nbTryListenAddr (2)   // number of times to try to start SIP listener
         , _localExternAddress ("")
         , _localExternPort (0)
-        , _audiortp (new sfl::AudioRtpFactory())
-        ,_regPort (atoi (DEFAULT_SIP_PORT))
+        , _regPort (atoi (DEFAULT_SIP_PORT))
         , _clients (0)
 {
     // to get random number for RANDOM_PORT
@@ -368,7 +367,7 @@ std::string SIPVoIPLink::get_useragent_name (void)
 void
 SIPVoIPLink::getEvent()
 {
-    // We have to register the external thread so it could access the pjsip framework
+    // We have to register the external thread so it could access the pjsip frameworks
     if (!pj_thread_is_registered())
         pj_thread_register (NULL, desc, &thread);
 
@@ -394,6 +393,8 @@ int SIPVoIPLink::sendRegister (AccountID id)
     pjsip_generic_string_hdr *h;
     pjsip_hdr hdr_list;
 
+    _debug("SIPVoIPLink::sendRegister()\n");
+
     account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (id));
 
     if (account == NULL) {
@@ -447,6 +448,7 @@ int SIPVoIPLink::sendRegister (AccountID id)
     if (account->isTlsEnabled()) {
         pj_status_t status;
 
+	_debug("    sendRegister: createTlsTransport\n");
         status = createTlsTransportRetryOnFailure (id);
 
         if (status != PJ_SUCCESS) {
@@ -454,27 +456,30 @@ int SIPVoIPLink::sendRegister (AccountID id)
         }
     }
 
-	// Launch a new UDP listener/transport, using the published address
-	if (account->isStunEnabled ()) {
-		pj_status_t status;
+    // Launch a new UDP listener/transport, using the published address
+    if (account->isStunEnabled ()) {
+	pj_status_t status;
 
-		status = createAlternateUdpTransport (id);
+	_debug("    sendRegister: createAlternateUdpTransport\n");
+	status = createAlternateUdpTransport (id);
 		
-		if (status != PJ_SUCCESS) {
-			_debug ("Failed to initialize UDP transport with an extern published address for account %s\n", id.c_str());
-		}
+	if (status != PJ_SUCCESS) {
+	    _debug ("Failed to initialize UDP transport with an extern published address for account %s\n", id.c_str());
 	}
-	else
-	{
-		status = createUDPServer (id);
-		if (status != PJ_SUCCESS) {
-			_debug ("Failed to initialize UDP transport with a local address for account %s\n. Try to use the local UDT transport", id.c_str());
-			account->setAccountTransport (_localUDPTransport);
-		}
+    }
+    else
+    {
+	
+	status = createUDPServer (id);
+	if (status != PJ_SUCCESS) {
+	    _debug ("Failed to initialize UDP transport with a local address for account %s\n. Try to use the local UDT transport", id.c_str());
+	    account->setAccountTransport (_localUDPTransport);
 	}
+    }
+    
 
     _mutexSIP.enterMutex();
-
+    
     // Get the client registration information for this particular account
     regc = account->getRegistrationInfo();
     account->setRegister (true);
@@ -583,17 +588,17 @@ int SIPVoIPLink::sendRegister (AccountID id)
         _mutexSIP.leaveMutex();
         return false;
     }
+    
+    pjsip_tpselector *tp;
 
-	// Set the appropriate transport
-	pjsip_tpselector *tp;
-	init_transport_selector (account->getAccountTransport (), &tp);
-	status = pjsip_regc_set_transport (regc, tp);
-	
-	if (status != PJ_SUCCESS) {
-		_debug ("UserAgent: Unable to set transport.\n");
-		_mutexSIP.leaveMutex ();
-		return false;
-	}
+    init_transport_selector (account->getAccountTransport (), &tp);
+    status = pjsip_regc_set_transport (regc, tp);
+    
+    if (status != PJ_SUCCESS) {
+	_debug ("UserAgent: Unable to set transport.\n");
+	_mutexSIP.leaveMutex ();
+	return false;
+    }
 
     // Send registration request
     status = pjsip_regc_send (regc, tdata);
@@ -607,7 +612,7 @@ int SIPVoIPLink::sendRegister (AccountID id)
     _mutexSIP.leaveMutex();
 
     account->setRegistrationInfo (regc);
-
+    _debug("ok\n");
     return true;
 }
 
@@ -682,7 +687,7 @@ SIPVoIPLink::newOutgoingCall (const CallID& id, const std::string& toUrl)
 
         try {
             _debug ("Creating new rtp session in newOutgoingCall\n");
-            _audiortp->initAudioRtpSession (call);
+            call->getAudioRtp()->initAudioRtpSession (call);
         } catch (...) {
             _debug ("Failed to create rtp thread from newOutGoingCall\n");
         }
@@ -735,7 +740,7 @@ SIPVoIPLink::answer (const CallID& id)
     local_sdp = call->getLocalSDP();
 
     try {
-        _audiortp->initAudioRtpSession (call);
+        call->getAudioRtp()->initAudioRtpSession (call);
     } catch (...) {
         _debug ("Failed to create rtp thread from answer\n");
     }
@@ -770,7 +775,7 @@ SIPVoIPLink::answer (const CallID& id)
         _debug ("SIPVoIPLink::answer: fail terminate call %s \n",call->getCallId().c_str());
         terminateOneCall (call->getCallId());
         removeCall (call->getCallId());
-        _audiortp->stop ();
+        call->getAudioRtp()->stop ();
         return false;
     }
 }
@@ -813,7 +818,7 @@ SIPVoIPLink::hangup (const CallID& id)
     // Release RTP thread
     if (Manager::instance().isCurrentCall (id)) {
         _debug ("* SIP Info: Stopping AudioRTP for hangup\n");
-        _audiortp->stop();
+        call->getAudioRtp()->stop();
     }
 
     terminateOneCall (id);
@@ -856,7 +861,7 @@ SIPVoIPLink::peerHungup (const CallID& id)
     // Release RTP thread
     if (Manager::instance().isCurrentCall (id)) {
         _debug ("* SIP Info: Stopping AudioRTP for hangup\n");
-        _audiortp->stop();
+        call->getAudioRtp()->stop();
     }
 
     terminateOneCall (id);
@@ -906,7 +911,7 @@ SIPVoIPLink::onhold (const CallID& id)
 
     _debug ("* SIP Info: Stopping AudioRTP for onhold action\n");
 
-    _audiortp->stop();
+    call->getAudioRtp()->stop();
 
     /* Create re-INVITE with new offer */
     status = inv_session_reinvite (call, "sendonly");
@@ -977,7 +982,7 @@ SIPVoIPLink::offhold (const CallID& id)
     }
 
     try {
-        _audiortp->initAudioRtpSession (call);
+        call->getAudioRtp()->initAudioRtpSession (call);
     } catch (...) {
         _debug ("! SIP Failure: Unable to create RTP Session (%s:%d)\n", __FILE__, __LINE__);
     }
@@ -1074,9 +1079,9 @@ SIPVoIPLink::transfer (const CallID& id, const std::string& to)
     return true;
 }
 
-bool SIPVoIPLink::transferStep2()
+bool SIPVoIPLink::transferStep2(SIPCall* call)
 {
-    _audiortp->stop();
+    call->getAudioRtp()->stop();
     return true;
 }
 
@@ -1119,27 +1124,6 @@ SIPVoIPLink::refuse (const CallID& id)
     return true;
 }
 
-void
-SIPVoIPLink::setRecording (const CallID& id)
-{
-    SIPCall* call = getSIPCall (id);
-
-    if (call)
-        call->setRecording();
-}
-
-bool
-SIPVoIPLink::isRecording (const CallID& id)
-{
-    SIPCall* call = getSIPCall (id);
-    _debug ("call->isRecording() %i \n",call->isRecording());
-
-    if (call)
-        return call->isRecording();
-    else
-        return false;
-}
-
 
 std::string
 SIPVoIPLink::getCurrentCodecName()
@@ -1244,7 +1228,6 @@ SIPVoIPLink::SIPStartCall (SIPCall* call, const std::string& subject UNUSED)
     pjsip_inv_session *inv;
     pjsip_dialog *dialog;
     pjsip_tx_data *tdata;
-	pjsip_transport *transport;
 
     AccountID id;
 
@@ -1343,6 +1326,7 @@ SIPVoIPLink::SIPStartCall (SIPCall* call, const std::string& subject UNUSED)
     status = pjsip_inv_send_msg (inv, tdata);
 
     if (status != PJ_SUCCESS) {
+	_debug("    SIPStartCall: failed to send invite\n");
         return false;
     }
 
@@ -1358,7 +1342,7 @@ SIPVoIPLink::SIPCallServerFailure (SIPCall *call)
         Manager::instance().callFailure (id);
         terminateOneCall (id);
         removeCall (id);
-        _audiortp->stop();
+        call->getAudioRtp()->stop();
     }
 }
 
@@ -1374,7 +1358,7 @@ SIPVoIPLink::SIPCallClosed (SIPCall *call)
     if (Manager::instance().isCurrentCall (id)) {
         call->setAudioStart (false);
         _debug ("* SIP Info: Stopping AudioRTP when closing\n");
-        _audiortp->stop();
+        call->getAudioRtp()->stop();
     }
 
     _debug ("After close RTP\n");
@@ -1474,7 +1458,7 @@ bool SIPVoIPLink::new_ip_to_ip_call (const CallID& id, const std::string& to)
         call->getLocalSDP()->create_initial_offer();
 
         try {
-            _audiortp->initAudioRtpSession (call);
+            call->getAudioRtp()->initAudioRtpSession (call);
         } catch (...) {
             _debug ("! SIP Failure: Unable to create RTP Session  in SIPVoIPLink::new_ip_to_ip_call (%s:%d)\n", __FILE__, __LINE__);
         }
@@ -1716,7 +1700,7 @@ bool SIPVoIPLink::pjsip_init()
     account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (AccountNULL));
 
     if (account == NULL) {
-        _debug ("Account is null");
+        _debug ("Account is null in pjsip init\n");
     } else {
         directIpCallsTlsEnabled = account->isTlsEnabled();
     }
@@ -1863,7 +1847,7 @@ pj_status_t SIPVoIPLink::stunServerResolve (AccountID id)
 	account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (id));
 
 	if (account == NULL) {
-		_debug ("stunServerResolve: Account is null. Returning");
+		_debug ("stunServerResolve: Account is null. Returning\n");
 		return !PJ_SUCCESS;
 	}
 	// Get the STUN server name and port
@@ -1909,42 +1893,52 @@ int SIPVoIPLink::createUDPServer (AccountID id)
     pj_sockaddr_in bound_addr;
     pjsip_host_port a_name;
     char tmpIP[32];
-	pjsip_transport *transport;
+    pjsip_transport *transport;
 
-	/* 
-	 * Retrieve the account information
-	 */
-	SIPAccount * account = NULL;
-	account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (id));
 
-	// Set information to the local address and port
-	if (account == NULL) {
-		// We are trying to initialize a UDP transport available for all local accounts and direct IP calls
-		_debug ("Account is null.");
-		_localExternAddress = _localIPAddress;
-		_localExternPort = _localPort;
-	}
-	else
-	{
-		_localExternAddress = account->getSessionAddress ();
-		_localExternPort = account->getSessionPort ();
-	}
+    /* 
+     * Retrieve the account information
+     */
+    SIPAccount * account = NULL;
+    account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (id));
 
+    // Set information to the local address and port
+    if (account == NULL) {
+    // We are trying to initialize a UDP transport available for all local accounts and direct IP calls
+	_debug ("Account is null in createUDPServer.\n");
+	_localExternAddress = _localIPAddress;
+	_localExternPort = _localPort;
+    }
+    else
+    {
+	_localExternAddress = account->getSessionAddress ();
+	_localExternPort = account->getSessionPort ();
+    }
 
     // Init bound address to ANY
     pj_memset (&bound_addr, 0, sizeof (bound_addr));
-
+       
     bound_addr.sin_addr.s_addr = pj_htonl (PJ_INADDR_ANY);
     bound_addr.sin_port = pj_htons ( (pj_uint16_t) _localPort);
     bound_addr.sin_family = PJ_AF_INET;
     pj_bzero (bound_addr.sin_zero, sizeof (bound_addr.sin_zero));
-
+	
     // Create UDP-Server (default port: 5060)
     strcpy (tmpIP, _localExternAddress.data());
     pj_strdup2 (_pool, &a_name.host, tmpIP);
     a_name.port = (pj_uint16_t) _localExternPort;
-
+    
     status = pjsip_udp_transport_start (_endpt, &bound_addr, &a_name, 1, &transport);
+    
+
+    // Get the transport manager associated with
+    // this endpoint
+    pjsip_tpmgr * tpmgr = NULL;
+
+    tpmgr = pjsip_endpt_get_tpmgr (_endpt);
+
+    _debug("number of transport: %i\n", pjsip_tpmgr_get_transport_count(tpmgr));
+    pjsip_tpmgr_dump_transports(tpmgr);
 
     if (status != PJ_SUCCESS) {
         _debug ("UserAgent: (%d) Unable to start UDP transport!\n", status);
@@ -1965,11 +1959,13 @@ int SIPVoIPLink::createUDPServer (AccountID id)
     return PJ_SUCCESS;
 }
 
-std::string SIPVoIPLink::findLocalAddressFromUri (const std::string& uri, pjsip_transport *transport)
+std::string SIPVoIPLink::findLocalAddressFromUri(const std::string& uri, pjsip_transport *transport)
 {
     pj_str_t localAddress;
     pjsip_transport_type_e transportType;
-	pjsip_tpselector *tp_sel;
+    pjsip_tpselector *tp_sel;
+
+    _debug("SIPVoIPLink::findLocalAddressFromUri\n");
 
     // Find the transport that must be used with the given uri
     pj_str_t tmp;
@@ -2010,7 +2006,7 @@ std::string SIPVoIPLink::findLocalAddressFromUri (const std::string& uri, pjsip_
     // this endpoint
     pjsip_tpmgr * tpmgr = NULL;
 
-    tpmgr = pjsip_endpt_get_tpmgr (_endpt);
+    tpmgr = pjsip_endpt_get_tpmgr (_endpt); 	
 
     if (tpmgr == NULL) {
         _debug ("Unexpected: Cannot get tpmgr from endpoint.\n");
@@ -2023,21 +2019,23 @@ std::string SIPVoIPLink::findLocalAddressFromUri (const std::string& uri, pjsip_
 
     pj_status_t status;
 
+
 	/* Init the transport selector */
 	//_debug ("Transport ID: %s\n", transport->obj_name);
 	status = init_transport_selector (transport, &tp_sel);
 
-	if (status == PJ_SUCCESS)
-		status = pjsip_tpmgr_find_local_addr (tpmgr, _pool, transportType, tp_sel, &localAddress, &port);
-	else
-		status = pjsip_tpmgr_find_local_addr (tpmgr, _pool, transportType, NULL, &localAddress, &port);
+
+    if (status == PJ_SUCCESS)
+	status = pjsip_tpmgr_find_local_addr (tpmgr, _pool, transportType, tp_sel, &localAddress, &port);
+    else
+	status = pjsip_tpmgr_find_local_addr (tpmgr, _pool, transportType, NULL, &localAddress, &port);
 
     if (status != PJ_SUCCESS) {
         _debug ("Failed to find local address from transport\n");
         return machineName;
     }
 
-	_debug ("Local ADdress From URI: %s\n", localAddress.ptr);
+    // _debug ("Local ADdress From URI: %s\n", localAddress.ptr);
     return std::string (localAddress.ptr, localAddress.slen);
 }
 
@@ -2111,17 +2109,17 @@ int SIPVoIPLink::findLocalPortFromUri (const std::string& uri, pjsip_transport *
 
     // Find the local address (and port) based on the registered
     // transports and the transport type
-	
-	/* Init the transport selector */
-	_debug ("Transport ID: %s\n", transport->obj_name);
+    
+    /* Init the transport selector */
+    _debug ("Transport ID: %s\n", transport->obj_name);
     pj_status_t status;
 
-	status = init_transport_selector (transport, &tp_sel);
+    status = init_transport_selector (transport, &tp_sel);
 
-	if (status == PJ_SUCCESS)
-		status = pjsip_tpmgr_find_local_addr (tpmgr, _pool, transportType, tp_sel, &localAddress, &port);
-	else
-		status = pjsip_tpmgr_find_local_addr (tpmgr, _pool, transportType, NULL, &localAddress, &port);
+    if (status == PJ_SUCCESS)
+	status = pjsip_tpmgr_find_local_addr (tpmgr, _pool, transportType, tp_sel, &localAddress, &port);
+    else
+	status = pjsip_tpmgr_find_local_addr (tpmgr, _pool, transportType, NULL, &localAddress, &port);
 
     if (status != PJ_SUCCESS) {
         _debug ("Failed to find local address from transport\n");
@@ -2149,7 +2147,7 @@ pj_status_t SIPVoIPLink::createTlsTransportRetryOnFailure (AccountID id)
         account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (id));
 
         if (account == NULL) {
-            _debug ("createTlsTransportRetryOnFailure: Account is null. Returning");
+            _debug ("createTlsTransportRetryOnFailure: Account is null. Returning\n");
             return !PJ_SUCCESS;
         }
 
@@ -2187,7 +2185,7 @@ pj_status_t SIPVoIPLink::createAlternateUdpTransport (AccountID id)
     account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (id));
 
     if (account == NULL) {
-        _debug ("Account is null. Returning");
+        _debug ("Account is null. Returning\n");
         return !PJ_SUCCESS;
     }
 
@@ -2272,7 +2270,7 @@ pj_status_t SIPVoIPLink::createTlsTransport (AccountID id)
     account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (id));
 
     if (account == NULL) {
-        _debug ("Account is null. Returning");
+        _debug ("Account is null. Returning\n");
         return !PJ_SUCCESS;
     }
 
@@ -2467,13 +2465,13 @@ void set_voicemail_info (AccountID account, pjsip_msg_body *body)
 void SIPVoIPLink::handle_reinvite (SIPCall *call)
 {
     // Close the previous RTP session
-    _audiortp->stop ();
+    call->getAudioRtp()->stop ();
     call->setAudioStart (false);
 
     _debug ("Create new rtp session from handle_reinvite : %s:%i\n", call->getLocalIp().c_str(), call->getLocalAudioPort());
 
     try {
-        _audiortp->initAudioRtpSession (call);
+        call->getAudioRtp()->initAudioRtpSession (call);
     } catch (...) {
         _debug ("! SIP Failure: Unable to create RTP Session (%s:%d)\n", __FILE__, __LINE__);
     }
@@ -2495,6 +2493,11 @@ void call_on_state_changed (pjsip_inv_session *inv, pjsip_event *e)
         _debug ("Call is NULL in call_on_state_changed");
         return;
     }
+    else
+    {
+	// _debug("    call_on_state_changed: call id %s\n", call->getCallId().c_str());
+	// _debug("    call_on_state_changed: call state %s\n", invitationStateMap[call->getInvSession()->state]);
+    }
 
     //Retrieve the body message
     rdata = e->body.tsx_state.src.rdata;
@@ -2524,6 +2527,7 @@ void call_on_state_changed (pjsip_inv_session *inv, pjsip_event *e)
         pjsip_evsub_state ev_state = PJSIP_EVSUB_STATE_ACTIVE;
 
         switch (call->getInvSession()->state) {
+	// switch (inv->state) {
 
             case PJSIP_INV_STATE_NULL:
 
@@ -2702,6 +2706,10 @@ void call_on_media_update (pjsip_inv_session *inv, pj_status_t status)
         return;
     }
 
+    if(!inv->neg)
+    {
+	return;
+    }
     // Get the new sdp, result of the negotiation
     pjmedia_sdp_neg_get_active_local (inv->neg, &local_sdp);
 
@@ -2720,9 +2728,9 @@ void call_on_media_update (pjsip_inv_session *inv, pj_status_t status)
 
     try {
         call->setAudioStart (true);
-        link->getAudioRtp()->start();
-    } catch (exception& rtpException) {
-        _debug ("%s\n", rtpException.what());
+        call->getAudioRtp()->start();        
+    } catch(exception& rtpException) {
+        _debug("%s\n", rtpException.what());
     }
 
 }
@@ -3377,13 +3385,21 @@ void xfer_func_cb (pjsip_evsub *sub, pjsip_event *event)
             status_line.reason = *pjsip_get_status_text (500);
         }
 
+	// Get current call
+        SIPCall *call = dynamic_cast<SIPCall *> (link->getCall (Manager::instance().getCurrentCallId()));
+
+        if (!call) {
+            _debug ("UserAgent: Call doesn't exit!\n");
+            return;
+        }
+
 
         if (event->body.rx_msg.rdata->msg_info.msg_buf != NULL) {
             request = event->body.rx_msg.rdata->msg_info.msg_buf;
 
             if ( (int) request.find (noresource) != -1) {
                 _debug ("UserAgent: NORESOURCE for transfer!\n");
-                link->transferStep2();
+                link->transferStep2(call);
                 pjsip_evsub_terminate (sub, PJ_TRUE);
 
                 Manager::instance().transferFailed();
@@ -3392,7 +3408,7 @@ void xfer_func_cb (pjsip_evsub *sub, pjsip_event *event)
 
             if ( (int) request.find (ringing) != -1) {
                 _debug ("UserAgent: transfered call RINGING!\n");
-                link->transferStep2();
+                link->transferStep2(call);
                 pjsip_evsub_terminate (sub, PJ_TRUE);
 
                 Manager::instance().transferSucceded();
@@ -3401,15 +3417,6 @@ void xfer_func_cb (pjsip_evsub *sub, pjsip_event *event)
         }
 
 
-        // Get current call
-        SIPCall *call = dynamic_cast<SIPCall *> (link->getCall (Manager::instance().getCurrentCallId()));
-
-        if (!call) {
-            _debug ("UserAgent: Call doesn't exit!\n");
-            return;
-        }
-
-
         /* Notify application */
         is_last = (pjsip_evsub_get_state (sub) ==PJSIP_EVSUB_STATE_TERMINATED);
 
@@ -3431,7 +3438,7 @@ void xfer_func_cb (pjsip_evsub *sub, pjsip_event *event)
                     _debug ("UserAgent: Fail to send end session msg!\n");
             }
 
-            link->transferStep2();
+            link->transferStep2(call);
 
             cont = PJ_FALSE;
         }
@@ -3578,8 +3585,8 @@ bool setCallAudioLocal (SIPCall* call, std::string localIP)
         	//}
     	}
 
+	_debug ("            Setting local ip address: %s\n", localIP.c_str());
     	_debug ("            Setting local audio port to: %d\n", callLocalAudioPort);
-
     	_debug ("            Setting local audio port (external) to: %d\n", callLocalExternAudioPort);
 
     	// Set local audio port for SIPCall(id)
@@ -3644,7 +3651,7 @@ std::vector<std::string> SIPVoIPLink::getAllIpInterface (void)
 
     int i;
 
-    for (i = 0; i < addrCnt; i++) {
+    for (i = 0; i < (int)addrCnt; i++) {
         char tmpAddr[PJ_INET_ADDRSTRLEN];
         pj_sockaddr_print (&addrList[i], tmpAddr, sizeof (tmpAddr), 0);
         ifaceList.push_back (std::string (tmpAddr));
diff --git a/sflphone-common/src/sip/sipvoiplink.h b/sflphone-common/src/sip/sipvoiplink.h
index 634a8a4f1aa630289bb7e74f90a4f2dc2d904477..f2c49302b80f98d85ac29795e71f7cdd7064977e 100644
--- a/sflphone-common/src/sip/sipvoiplink.h
+++ b/sflphone-common/src/sip/sipvoiplink.h
@@ -26,7 +26,6 @@
 #include "voiplink.h"
 #include "hooks/urlhook.h"
 
-#include "audio/audiortp/AudioRtpFactory.h"
 
 //////////////////////////////
 /* PJSIP imports */
@@ -39,11 +38,6 @@
 
 class EventThread;
 class SIPCall;
-class AudioRtp;
-
-namespace sfl {
-    class AudioRtpFactory;
-}
 
 #define RANDOM_LOCAL_PORT ((rand() % 27250) + 5250)*2
 #define RANDOM_SIP_PORT   rand() % 64000 + 1024
@@ -168,7 +162,7 @@ class SIPVoIPLink : public VoIPLink
         bool transfer(const CallID& id, const std::string& to);
 
         /** Handle the incoming refer msg, not finished yet */
-        bool transferStep2();
+        bool transferStep2(SIPCall* call);
 
         /**
          * Refuse the call
@@ -252,9 +246,6 @@ class SIPVoIPLink : public VoIPLink
         /** when we init the listener, how many times we try to bind a port? */
         int _nbTryListenAddr;
 
-        /** Returns a pointer to the AudioRtp object */
-        inline sfl::AudioRtpFactory * getAudioRtp(void) { return _audiortp; }
-
         /** Increment the number of SIP account connected to this link */
         void incrementClients (void) { _clients++; }
 
@@ -388,9 +379,6 @@ class SIPVoIPLink : public VoIPLink
 
         /** Local Extern Port is the port seen by peers for SIP listener */
         unsigned int _localExternPort;
-
-        /** Starting sound */
-        sfl::AudioRtpFactory * _audiortp;
         
         /** For registration use only */
         int _regPort;
diff --git a/sflphone-common/src/voiplink.h b/sflphone-common/src/voiplink.h
index b78646b41f1c597ddd35f5bedcacc130c4a97748..09ea20b3c2708f63a6b0a38053a214755843c5fa 100644
--- a/sflphone-common/src/voiplink.h
+++ b/sflphone-common/src/voiplink.h
@@ -164,13 +164,13 @@ class VoIPLink {
      	* Set Recording
      	* @param id The call identifier
      	*/
-    	virtual void setRecording(const CallID& id) = 0;
+    	// virtual void setRecording(const CallID& id) = 0;
 
         /**
      	* Return recording state
      	* @param id The call identifier
      	*/
-    	virtual bool isRecording(const CallID& id) = 0;
+    	// virtual bool isRecording(const CallID& id) = 0;
 
         /**
          * Return the codec protocol used for this call 
diff --git a/sflphone-common/test/Makefile.am b/sflphone-common/test/Makefile.am
index 6700e93d458928c162c88582d355673500aa89ba..87264309aa0f6008c2e6a5704122de0593a5d097 100644
--- a/sflphone-common/test/Makefile.am
+++ b/sflphone-common/test/Makefile.am
@@ -1,6 +1,7 @@
 include ../globals.mak
 
-noinst_PROGRAMS = numbercleanerTester pluginmanagerTester hookmanagerTester audiolayerTester historyTester #rtpTester
+
+noinst_PROGRAMS = numbercleanerTester pluginmanagerTester hookmanagerTester audiolayerTester historyTester mainbufferTester #rtpTester
 
 OBJECT_FILES= \
 	../src/sflphoned-managerimpl.o \
@@ -15,13 +16,15 @@ OBJECT_FILES= \
 	../src/sip/sipaccount.o \
 	../src/iax/libiaxlink_la-iaxaccount.o \
 	../src/sflphoned-eventthread.o \
+	../src/sflphoned-conference.o \
 	../src/plug-in/pluginmanager.o \
 	../src/plug-in/audiorecorder/audiorecord.o \
 	../src/audio/samplerateconverter.o \
 	../src/sip/sdp.o \
 	../src/sip/sdpmedia.o \
 	../src/sflphoned-numbercleaner.o \
-    ../src/history/historymanager.o
+        ../src/history/historymanager.o
+	../
 
 numbercleanerTester_SOURCES = \
 		numbercleanerTest.h \
@@ -102,12 +105,12 @@ audiolayerTester_LDADD = \
 		$(PJSIP_LIBS) \
 		$(OBJECT_FILES)
 
-rtpTester_SOURCES = \
-		rtpTest.h \
-		rtpTest.cpp \
+historyTester_SOURCES = \
+		historyTest.h \
+		historyTest.cpp \
 		TestMain.cpp
 
-rtpTester_LDADD = \
+historyTester_LDADD = \
 		../src/libsflphone.la  \
 		$(SFLPHONE_LIBS) $(ZEROCONFLIB) $(LIB_DNSSD) \
 		@ALSA_LIBS@ \
@@ -116,18 +119,19 @@ rtpTester_LDADD = \
 		@CCEXT2_LIBS@ \
 		@CCGNU2_LIBS@ \
 		@CCRTP_LIBS@ \
-		@SAMPLERATE_LIBS@ \
 		@ZRTPCPP_LIBS@ \
 		@libssl_LIBS@ \
+		@SAMPLERATE_LIBS@ \
 		$(PJSIP_LIBS) \
 		$(OBJECT_FILES)
 
-historyTester_SOURCES = \
-		historyTest.h \
-		historyTest.cpp \
+
+mainbufferTester_SOURCES = \
+		mainbufferTest.h \
+		mainbufferTest.cpp \
 		TestMain.cpp
 
-historyTester_LDADD = \
+mainbufferTester_LDADD = \
 		../src/libsflphone.la  \
 		$(SFLPHONE_LIBS) $(ZEROCONFLIB) $(LIB_DNSSD) \
 		@ALSA_LIBS@ \
@@ -141,4 +145,3 @@ historyTester_LDADD = \
 		@SAMPLERATE_LIBS@ \
 		$(PJSIP_LIBS) \
 		$(OBJECT_FILES)
-
diff --git a/sflphone-common/test/mainbufferTest.cpp b/sflphone-common/test/mainbufferTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d3cdfa6515db33982fa4561f692d40291c234e74
--- /dev/null
+++ b/sflphone-common/test/mainbufferTest.cpp
@@ -0,0 +1,1772 @@
+/*
+ *  Copyright (C) 2009 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.
+ */
+
+#include <stdio.h>
+#include <sstream>
+#include <ccrtp/rtp.h>
+#include <assert.h>
+#include <string>
+#include <cstring>
+#include <math.h>
+#include <dlfcn.h>
+#include <iostream>
+#include <sstream>
+
+
+#include "mainbufferTest.h"
+
+#include <unistd.h>
+
+
+using std::cout;
+using std::endl;
+
+
+void MainBufferTest::setUp()
+{
+
+    
+}
+
+
+void MainBufferTest::tearDown()
+{
+
+}
+
+
+void MainBufferTest::testRingBufferCreation()
+{
+    _debug("MainBufferTest::testRingBufferCreation()\n");
+
+    CallID test_id = "1234";
+    CallID null_id = "null id";
+
+    RingBuffer* test_ring_buffer;
+    RingBufferMap::iterator iter;
+
+    // test mainbuffer ringbuffer map size
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 0);
+    test_ring_buffer = _mainbuffer.createRingBuffer(test_id);
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 1);
+
+    // test _mainbuffer.getRingBuffer method
+    CPPUNIT_ASSERT(test_ring_buffer != NULL);
+    CPPUNIT_ASSERT(_mainbuffer.getRingBuffer(null_id) == NULL);
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 1);
+    CPPUNIT_ASSERT(_mainbuffer.getRingBuffer(test_id) == test_ring_buffer);
+
+    // test _mainbuffer _ringBufferMap
+    iter = _mainbuffer._ringBufferMap.find(null_id);
+    CPPUNIT_ASSERT(iter == _mainbuffer._ringBufferMap.end());
+    iter = _mainbuffer._ringBufferMap.find(test_id);
+    CPPUNIT_ASSERT(iter->first == test_id);
+    CPPUNIT_ASSERT(iter->second == test_ring_buffer);
+    CPPUNIT_ASSERT(iter->second == _mainbuffer.getRingBuffer(test_id));
+
+    // test creating twice a buffer (should not create it)
+    _mainbuffer.createRingBuffer(test_id);
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 1);
+    CPPUNIT_ASSERT(_mainbuffer.getRingBuffer(test_id) == test_ring_buffer);
+
+    // test remove ring buffer
+    CPPUNIT_ASSERT(_mainbuffer.removeRingBuffer(null_id) == true);
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 1);
+    CPPUNIT_ASSERT(_mainbuffer.removeRingBuffer(test_id) == true);
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 0);
+    CPPUNIT_ASSERT(_mainbuffer.getRingBuffer(test_id) == NULL);
+
+    iter = _mainbuffer._ringBufferMap.find(test_id);
+    CPPUNIT_ASSERT(iter == _mainbuffer._ringBufferMap.end());
+    
+}
+
+
+void MainBufferTest::testRingBufferReadPointer()
+{
+    _debug("MainBufferTest::testRingBufferReadPointer()\n");
+
+    CallID call_id = "call id";
+    CallID read_id = "read id";
+    CallID null_id = "null id";
+    CallID other_id = "other id";
+
+    RingBuffer* test_ring_buffer;
+
+    // test ring buffer read pointers (one per participant)
+    test_ring_buffer = _mainbuffer.createRingBuffer(call_id);
+    CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(read_id) == (int)NULL);
+
+    // create a read pointer
+    test_ring_buffer->createReadPointer(read_id);
+    CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 1);
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(null_id) == (int)NULL);
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(read_id) == 0);
+
+    // store read pointer
+    test_ring_buffer->storeReadPointer(4, read_id);
+    CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 1);
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(read_id) == 4);
+
+    // recreate the same read pointer (should not add a pointer neither chage its value)
+    test_ring_buffer->createReadPointer(read_id);
+    CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 1);
+    test_ring_buffer->storeReadPointer(8, read_id);
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(read_id) == 8);
+
+    // test getSmallest read pointer (to get the length available to put data in the buffer)
+    test_ring_buffer->createReadPointer(other_id);
+    CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 2);
+    test_ring_buffer->storeReadPointer(4, other_id);
+    CPPUNIT_ASSERT(test_ring_buffer->getSmallestReadPointer() == 4);
+
+    // remove read pointers
+    test_ring_buffer->removeReadPointer(other_id);
+    CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 1);
+    test_ring_buffer->removeReadPointer(read_id);
+    CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 0);    
+}
+
+
+void MainBufferTest::testCallIDSet()
+{
+    _debug("MainBufferTest::testCallIDSet()\n");
+
+    CallID test_id = "set id";
+    CallID false_id = "false set id";
+    // CallIDSet* callid_set = 0;
+
+    CallIDMap::iterator iter_map;
+    CallIDSet::iterator iter_set;
+
+    CallID call_id_1 = "call id 1";
+    CallID call_id_2 = "call id 2";
+
+    // test initial settings
+    CPPUNIT_ASSERT(_mainbuffer._callIDMap.size() == 0);
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 0);
+    iter_map = _mainbuffer._callIDMap.find(test_id);
+    CPPUNIT_ASSERT(iter_map ==_mainbuffer._callIDMap.end());
+
+    // test callidset creation
+    CPPUNIT_ASSERT(_mainbuffer.createCallIDSet(test_id) == true);
+    CPPUNIT_ASSERT(_mainbuffer._callIDMap.size() == 1);
+    iter_map = _mainbuffer._callIDMap.find(test_id);
+    CPPUNIT_ASSERT(iter_map->first == test_id);
+    CPPUNIT_ASSERT(iter_map->second == _mainbuffer.getCallIDSet(test_id));
+
+    CPPUNIT_ASSERT(_mainbuffer.getCallIDSet(false_id) == NULL);
+    CPPUNIT_ASSERT(_mainbuffer.getCallIDSet(test_id) != NULL);
+
+
+    // Test callIDSet add call_ids
+    _mainbuffer.addCallIDtoSet(test_id, call_id_1);
+    iter_map = _mainbuffer._callIDMap.find(test_id);
+    CPPUNIT_ASSERT(iter_map->second->size() == 1);
+    iter_set = iter_map->second->find(call_id_1);
+    CPPUNIT_ASSERT(*iter_set == call_id_1);
+
+    // test add second call id to set
+    _mainbuffer.addCallIDtoSet(test_id, call_id_2);
+    iter_map = _mainbuffer._callIDMap.find(test_id);
+    CPPUNIT_ASSERT(iter_map->second->size() == 2);
+    iter_set = iter_map->second->find(call_id_2);
+    CPPUNIT_ASSERT(*iter_set == call_id_2);
+
+    // test add a call id twice 
+    _mainbuffer.addCallIDtoSet(test_id, call_id_2);
+    iter_map = _mainbuffer._callIDMap.find(test_id);
+    CPPUNIT_ASSERT(iter_map->second->size() == 2);
+    iter_set = iter_map->second->find(call_id_2);
+    CPPUNIT_ASSERT(*iter_set == call_id_2);
+
+    // test remove a call id
+    _mainbuffer.removeCallIDfromSet(test_id, call_id_2);
+    iter_map = _mainbuffer._callIDMap.find(test_id);
+    CPPUNIT_ASSERT(iter_map->second->size() == 1);
+    iter_set = iter_map->second->find(call_id_1);
+    CPPUNIT_ASSERT(*iter_set == call_id_1);
+    iter_set = iter_map->second->find(call_id_2);
+    CPPUNIT_ASSERT(iter_set == iter_map->second->end());
+
+    // test remove a call id twice
+    _mainbuffer.removeCallIDfromSet(test_id, call_id_2);
+    iter_map = _mainbuffer._callIDMap.find(test_id);
+    CPPUNIT_ASSERT(iter_map->second->size() == 1);
+    iter_set = iter_map->second->find(call_id_1);
+    CPPUNIT_ASSERT(*iter_set == call_id_1);
+    iter_set = iter_map->second->find(call_id_2);
+    CPPUNIT_ASSERT(iter_set == iter_map->second->end());
+
+    // Test removeCallIDSet
+    CPPUNIT_ASSERT(_mainbuffer.removeCallIDSet(false_id) == false);
+    CPPUNIT_ASSERT(_mainbuffer._callIDMap.size() == 1);
+    CPPUNIT_ASSERT(_mainbuffer.removeCallIDSet(test_id) == true);
+    CPPUNIT_ASSERT(_mainbuffer._callIDMap.size() == 0);
+
+    iter_map = _mainbuffer._callIDMap.find(test_id);
+    CPPUNIT_ASSERT(iter_map ==_mainbuffer._callIDMap.end());
+
+    
+}
+
+
+void MainBufferTest::testRingBufferInt()
+{
+
+    _debug("MainBufferTest::testRingbufferInt()\n");
+
+    // CallID test_id = "test_int";
+    
+    int testint1 = 12;
+    int testint2 = 13;
+    int init_put_size;
+
+
+    // test with default ring buffer
+    RingBuffer* test_ring_buffer = _mainbuffer.createRingBuffer(default_id);
+
+    // initial state
+    init_put_size = test_ring_buffer->AvailForPut();
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 0);
+
+    // add some data
+    CPPUNIT_ASSERT(test_ring_buffer->Put(&testint1, sizeof(int)) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - (int)sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 0);
+
+    // add some other data
+    CPPUNIT_ASSERT(test_ring_buffer->Put(&testint2, sizeof(int)) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 2*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - 2*(int)sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 0);
+
+    int testget = (int)NULL;
+
+    // get some data (without any read pointers)
+    CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == 2*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->getLen() == 2*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->Get(&testget, sizeof(int)) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == 2*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->getLen() == 2*sizeof(int));
+    CPPUNIT_ASSERT(testget == (int)NULL);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - 2*(int)sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 0);
+
+    // get some data (with a read pointer)
+    CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 0);
+    test_ring_buffer->createReadPointer(default_id);
+    CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 1);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->getLen() == 0);
+
+    // add some data
+    CPPUNIT_ASSERT(test_ring_buffer->Put(&testint1, sizeof(int)) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - (int)sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 2*sizeof(int));
+
+    // add some other data
+    CPPUNIT_ASSERT(test_ring_buffer->Put(&testint2, sizeof(int)) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 2*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - 2*(int)sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 2*sizeof(int));
+
+    CPPUNIT_ASSERT(test_ring_buffer->Get(&testget, sizeof(int), 100, default_id) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->getLen() == sizeof(int));
+    CPPUNIT_ASSERT(testget == testint1);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - (int)sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 3*sizeof(int));
+
+    CPPUNIT_ASSERT(test_ring_buffer->Get(&testget, sizeof(int)) == sizeof(int));
+    CPPUNIT_ASSERT(testget == testint2);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->getLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_size);
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 4*sizeof(int));
+
+
+    // test flush data
+    init_put_size = test_ring_buffer->AvailForPut();
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->Put(&testint1, sizeof(int)) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - (int)sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->getLen() == sizeof(int));
+
+
+    test_ring_buffer->flush();
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_size);
+    CPPUNIT_ASSERT(test_ring_buffer->getLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 5*sizeof(int));
+
+    // test flush data
+    init_put_size = test_ring_buffer->AvailForPut();
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->Put(&testint1, sizeof(int)) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - (int)sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->getLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 5*sizeof(int));
+
+    test_ring_buffer->Discard(sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_size);
+    CPPUNIT_ASSERT(test_ring_buffer->getLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 6*sizeof(int));
+
+    
+}
+
+
+void MainBufferTest::testRingBufferNonDefaultID()
+{
+
+    _debug("MainBufferTest::testRingBufferNonDefaultID()\n");
+
+    CallID test_id = "test_int";
+    
+    int testint1 = 12;
+    int testint2 = 13;
+    int init_put_size;
+
+    
+    // test putData, getData with arbitrary read pointer id
+    RingBuffer* test_ring_buffer = _mainbuffer.createRingBuffer(default_id);
+    test_ring_buffer->createReadPointer(test_id);
+
+    init_put_size = test_ring_buffer->AvailForPut();
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(default_id) == 0); 
+
+    CPPUNIT_ASSERT(test_ring_buffer->Put(&testint1, sizeof(int)) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - (int)sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(default_id) == 0);
+
+    CPPUNIT_ASSERT(test_ring_buffer->Put(&testint2, sizeof(int)) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 2*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - 2*(int)sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(default_id) == 0);
+
+    int testget;
+
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id) == 2*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->getLen(test_id) == 2*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->Get(&testget, sizeof(int), 100,  test_id) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->getLen(test_id) == sizeof(int));
+    CPPUNIT_ASSERT(testget == testint1);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - (int)sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(test_id) == sizeof(int));
+
+    CPPUNIT_ASSERT(test_ring_buffer->Get(&testget, sizeof(int), 100, test_id) == sizeof(int));
+    CPPUNIT_ASSERT(testget == testint2);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->getLen(test_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_size);
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(test_id) == 2*sizeof(int));
+
+
+    // test flush data
+    init_put_size = test_ring_buffer->AvailForPut();
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->Put(&testint1, sizeof(int)) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - (int)sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->getLen(test_id) == sizeof(int));
+
+
+    test_ring_buffer->flush(test_id);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_size);
+    CPPUNIT_ASSERT(test_ring_buffer->getLen(test_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(test_id) == 3*sizeof(int));
+
+    // test flush data
+    init_put_size = test_ring_buffer->AvailForPut();
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->Put(&testint1, sizeof(int)) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (init_put_size - (int)sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->getLen(test_id) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(test_id) == 3*sizeof(int));
+
+    test_ring_buffer->Discard(sizeof(int), test_id);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_size);
+    CPPUNIT_ASSERT(test_ring_buffer->getLen(test_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(test_id) == 4*sizeof(int));
+
+    test_ring_buffer->removeReadPointer(test_id);
+    
+}
+
+
+void MainBufferTest::testRingBufferFloat()
+{
+
+    _debug("MainBufferTest::testRingBufferFloat()\n");
+
+    float testfloat1 = 12.5;
+    float testfloat2 = 13.4;
+
+    RingBuffer* test_ring_buffer = _mainbuffer.createRingBuffer(default_id);
+    test_ring_buffer->createReadPointer(default_id);
+    
+
+    CPPUNIT_ASSERT(test_ring_buffer->Put(&testfloat1, sizeof(float)) == sizeof(float));
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(float));
+
+    CPPUNIT_ASSERT(test_ring_buffer->Put(&testfloat2, sizeof(float)) == sizeof(float));
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 2*sizeof(float));
+
+    float testget;
+
+    CPPUNIT_ASSERT(test_ring_buffer->Get(&testget, sizeof(float)) == sizeof(float));
+    CPPUNIT_ASSERT(test_ring_buffer->getLen() == sizeof(float));
+    CPPUNIT_ASSERT(testget == testfloat1);
+
+    CPPUNIT_ASSERT(test_ring_buffer->Get(&testget, sizeof(float)) == sizeof(float));
+    CPPUNIT_ASSERT(testget == testfloat2);
+    CPPUNIT_ASSERT(test_ring_buffer->getLen() == 0);
+
+    CPPUNIT_ASSERT(test_ring_buffer->Put(&testfloat1, sizeof(float)) == sizeof(float));
+    test_ring_buffer->flush();
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+
+}
+
+
+void MainBufferTest::testTwoPointer()
+{
+
+    _debug("MainBufferTest::testTwoPointer()\n");
+
+    
+    RingBuffer* input_buffer = _mainbuffer.createRingBuffer(default_id);
+    input_buffer->createReadPointer(default_id);
+    RingBuffer* output_buffer = _mainbuffer.getRingBuffer(default_id);
+
+    int test_input = 12;
+    int test_output;
+
+    CPPUNIT_ASSERT(input_buffer->Put(&test_input, sizeof(int)) == sizeof(int));
+    CPPUNIT_ASSERT(output_buffer->Get(&test_output, sizeof(float)) == sizeof(float));
+    CPPUNIT_ASSERT(test_input == test_output);
+
+}
+
+void MainBufferTest::testBindUnbindBuffer()
+{
+
+    _debug("MainBufferTest::testBindUnbindBuffer()\n");
+    
+    CallID test_id1 = "bind unbind 1";
+    CallID test_id2 = "bind unbind 2";
+
+    RingBufferMap::iterator iter_buffer;
+    CallIDMap::iterator iter_idset;
+    CallIDSet::iterator iter_id;
+
+    ReadPointer::iterator iter_readpointer;
+
+    RingBuffer* ringbuffer;
+
+    // test initial state with no ring brffer created
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 0);
+    CPPUNIT_ASSERT(_mainbuffer._callIDMap.size() == 0);
+
+    iter_buffer = _mainbuffer._ringBufferMap.find(default_id);
+    CPPUNIT_ASSERT(iter_buffer == _mainbuffer._ringBufferMap.end());
+    iter_idset = _mainbuffer._callIDMap.find(default_id);
+    CPPUNIT_ASSERT(iter_idset == _mainbuffer._callIDMap.end());
+
+    // bind test_id1 with default_id (both buffer not already created)
+    _mainbuffer.bindCallID(test_id1);
+
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 2);
+    CPPUNIT_ASSERT(_mainbuffer._callIDMap.size() == 2);
+
+    iter_buffer = _mainbuffer._ringBufferMap.find(default_id);
+    CPPUNIT_ASSERT(iter_buffer->first == default_id);
+    CPPUNIT_ASSERT(iter_buffer->second == _mainbuffer.getRingBuffer(default_id));
+
+    iter_buffer = _mainbuffer._ringBufferMap.find(test_id1);
+    CPPUNIT_ASSERT(iter_buffer->first == test_id1);
+    CPPUNIT_ASSERT(iter_buffer->second == _mainbuffer.getRingBuffer(test_id1));
+
+    iter_idset = _mainbuffer._callIDMap.find(default_id);
+    CPPUNIT_ASSERT(iter_idset->second->size() == 1);
+    iter_id = iter_idset->second->find(test_id1);
+    CPPUNIT_ASSERT(*iter_id == test_id1);
+
+    iter_idset = _mainbuffer._callIDMap.find(test_id1);
+    CPPUNIT_ASSERT(iter_idset->second->size() == 1);
+    iter_id = iter_idset->second->find(default_id);
+    CPPUNIT_ASSERT(*iter_id == default_id);
+
+    ringbuffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(ringbuffer != NULL);
+    CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 1);
+    iter_readpointer = ringbuffer->_readpointer.find(test_id1);
+    CPPUNIT_ASSERT(iter_readpointer->first == test_id1);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+
+    ringbuffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(ringbuffer != NULL);
+    CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 1);
+    iter_readpointer = ringbuffer->_readpointer.find(default_id);
+    CPPUNIT_ASSERT(iter_readpointer->first == default_id);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+
+
+    // unbind test_id1 with default_id 
+    _mainbuffer.unBindCallID(test_id1);
+
+    _debug("%i\n", _mainbuffer._ringBufferMap.size());
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 0);
+    CPPUNIT_ASSERT(_mainbuffer._callIDMap.size() == 0);
+
+    CPPUNIT_ASSERT(_mainbuffer.getRingBuffer(default_id) == NULL);
+    CPPUNIT_ASSERT(_mainbuffer.getRingBuffer(test_id1) == NULL);
+    
+
+    // bind test_id2 with default_id (default_id already created)
+    // calling it twice not supposed to break anything
+    _mainbuffer.bindCallID(test_id1, default_id);
+    _mainbuffer.bindCallID(test_id1, default_id);
+
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 2);
+    CPPUNIT_ASSERT(_mainbuffer._callIDMap.size() == 2);
+
+    iter_buffer = _mainbuffer._ringBufferMap.find(test_id2);
+    CPPUNIT_ASSERT(iter_buffer == _mainbuffer._ringBufferMap.end());
+    iter_idset = _mainbuffer._callIDMap.find(test_id2);
+    CPPUNIT_ASSERT(iter_idset == _mainbuffer._callIDMap.end());
+
+    _mainbuffer.bindCallID(test_id2, default_id);
+    _mainbuffer.bindCallID(test_id2, default_id);
+
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 3);
+    CPPUNIT_ASSERT(_mainbuffer._callIDMap.size() == 3);
+
+    iter_buffer = _mainbuffer._ringBufferMap.find(default_id);
+    CPPUNIT_ASSERT(iter_buffer->first == default_id);
+    CPPUNIT_ASSERT(iter_buffer->second == _mainbuffer.getRingBuffer(default_id));
+
+    iter_buffer = _mainbuffer._ringBufferMap.find(test_id1);
+    CPPUNIT_ASSERT(iter_buffer->first == test_id1);
+    CPPUNIT_ASSERT(iter_buffer->second == _mainbuffer.getRingBuffer(test_id1));
+
+    iter_buffer = _mainbuffer._ringBufferMap.find(test_id2);
+    CPPUNIT_ASSERT(iter_buffer->first == test_id2);
+    CPPUNIT_ASSERT(iter_buffer->second == _mainbuffer.getRingBuffer(test_id2));
+
+    iter_idset = _mainbuffer._callIDMap.find(default_id);
+    CPPUNIT_ASSERT(iter_idset->second->size() == 2);
+    iter_id = iter_idset->second->find(test_id1);
+    CPPUNIT_ASSERT(*iter_id == test_id1);
+    iter_id = iter_idset->second->find(test_id2);
+    CPPUNIT_ASSERT(*iter_id == test_id2);
+
+    iter_idset = _mainbuffer._callIDMap.find(test_id1);
+    CPPUNIT_ASSERT(iter_idset->second->size() == 1);
+    iter_id = iter_idset->second->find(default_id);
+    CPPUNIT_ASSERT(*iter_id == default_id);
+
+    iter_idset = _mainbuffer._callIDMap.find(test_id2);
+    CPPUNIT_ASSERT(iter_idset->second->size() == 1);
+    iter_id = iter_idset->second->find(default_id);
+    CPPUNIT_ASSERT(*iter_id == default_id);
+
+    ringbuffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(ringbuffer != NULL);
+    CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 2);
+    iter_readpointer = ringbuffer->_readpointer.find(test_id1);
+    CPPUNIT_ASSERT(iter_readpointer->first == test_id1);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+    iter_readpointer = ringbuffer->_readpointer.find(test_id2);
+    CPPUNIT_ASSERT(iter_readpointer->first == test_id2);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+
+    ringbuffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(ringbuffer != NULL);
+    CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 1);
+    iter_readpointer = ringbuffer->_readpointer.find(default_id);
+    CPPUNIT_ASSERT(iter_readpointer->first == default_id);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+
+    ringbuffer = _mainbuffer.getRingBuffer(test_id2);
+    CPPUNIT_ASSERT(ringbuffer != NULL);
+    CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 1);
+    iter_readpointer = ringbuffer->_readpointer.find(default_id);
+    CPPUNIT_ASSERT(iter_readpointer->first == default_id);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+
+    // bind test_id1 with test_id2 (both testid1 and test_id2 already created)
+    // calling it twice not supposed to break anything
+    _mainbuffer.bindCallID(test_id1, test_id2);
+    _mainbuffer.bindCallID(test_id1, test_id2);
+    
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 3);
+    CPPUNIT_ASSERT(_mainbuffer._callIDMap.size() == 3);
+
+    iter_buffer = _mainbuffer._ringBufferMap.find(default_id);
+    CPPUNIT_ASSERT(iter_buffer->first == default_id);
+    CPPUNIT_ASSERT(iter_buffer->second == _mainbuffer.getRingBuffer(default_id));
+
+    iter_buffer = _mainbuffer._ringBufferMap.find(test_id1);
+    CPPUNIT_ASSERT(iter_buffer->first == test_id1);
+    CPPUNIT_ASSERT(iter_buffer->second == _mainbuffer.getRingBuffer(test_id1));
+
+    iter_buffer = _mainbuffer._ringBufferMap.find(test_id2);
+    CPPUNIT_ASSERT(iter_buffer->first == test_id2);
+    CPPUNIT_ASSERT(iter_buffer->second == _mainbuffer.getRingBuffer(test_id2));
+
+    iter_idset = _mainbuffer._callIDMap.find(default_id);
+    CPPUNIT_ASSERT(iter_idset->second->size() == 2);
+    iter_id = iter_idset->second->find(test_id1);
+    CPPUNIT_ASSERT(*iter_id == test_id1);
+    iter_id = iter_idset->second->find(test_id2);
+    CPPUNIT_ASSERT(*iter_id == test_id2);
+
+    iter_idset = _mainbuffer._callIDMap.find(test_id1);
+    CPPUNIT_ASSERT(iter_idset->second->size() == 2);
+    iter_id = iter_idset->second->find(default_id);
+    CPPUNIT_ASSERT(*iter_id == default_id);
+    iter_id = iter_idset->second->find(test_id2);
+    CPPUNIT_ASSERT(*iter_id == test_id2);
+
+    iter_idset = _mainbuffer._callIDMap.find(test_id2);
+    CPPUNIT_ASSERT(iter_idset->second->size() == 2);
+    iter_id = iter_idset->second->find(default_id);
+    CPPUNIT_ASSERT(*iter_id == default_id);
+    iter_id = iter_idset->second->find(test_id1);
+    CPPUNIT_ASSERT(*iter_id == test_id1);
+
+    ringbuffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(ringbuffer != NULL);
+    CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 2);
+    iter_readpointer = ringbuffer->_readpointer.find(test_id1);
+    CPPUNIT_ASSERT(iter_readpointer->first == test_id1);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+    iter_readpointer = ringbuffer->_readpointer.find(test_id2);
+    CPPUNIT_ASSERT(iter_readpointer->first == test_id2);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+
+    ringbuffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(ringbuffer != NULL);
+    CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 2);
+    iter_readpointer = ringbuffer->_readpointer.find(default_id);
+    CPPUNIT_ASSERT(iter_readpointer->first == default_id);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+    iter_readpointer = ringbuffer->_readpointer.find(test_id2);
+    CPPUNIT_ASSERT(iter_readpointer->first == test_id2);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+
+    ringbuffer = _mainbuffer.getRingBuffer(test_id2);
+    CPPUNIT_ASSERT(ringbuffer != NULL);
+    CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 2);
+    iter_readpointer = ringbuffer->_readpointer.find(default_id);
+    CPPUNIT_ASSERT(iter_readpointer->first == default_id);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+    iter_readpointer = ringbuffer->_readpointer.find(test_id1);
+    CPPUNIT_ASSERT(iter_readpointer->first == test_id1);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+
+    // unbind test_id1 with test_id2
+    // calling it twice not supposed to break anything
+    _mainbuffer.unBindCallID(test_id1, test_id2);
+    _mainbuffer.unBindCallID(test_id1, test_id2);
+
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 3);
+    CPPUNIT_ASSERT(_mainbuffer._callIDMap.size() == 3);
+
+    iter_buffer = _mainbuffer._ringBufferMap.find(default_id);
+    CPPUNIT_ASSERT(iter_buffer->first == default_id);
+    CPPUNIT_ASSERT(iter_buffer->second == _mainbuffer.getRingBuffer(default_id));
+
+    iter_buffer = _mainbuffer._ringBufferMap.find(test_id1);
+    CPPUNIT_ASSERT(iter_buffer->first == test_id1);
+    CPPUNIT_ASSERT(iter_buffer->second == _mainbuffer.getRingBuffer(test_id1));
+
+    iter_buffer = _mainbuffer._ringBufferMap.find(test_id2);
+    CPPUNIT_ASSERT(iter_buffer->first == test_id2);
+    CPPUNIT_ASSERT(iter_buffer->second == _mainbuffer.getRingBuffer(test_id2));
+
+    iter_idset = _mainbuffer._callIDMap.find(default_id);
+    CPPUNIT_ASSERT(iter_idset->second->size() == 2);
+    iter_id = iter_idset->second->find(test_id1);
+    CPPUNIT_ASSERT(*iter_id == test_id1);
+    iter_id = iter_idset->second->find(test_id2);
+    CPPUNIT_ASSERT(*iter_id == test_id2);
+
+    iter_idset = _mainbuffer._callIDMap.find(test_id1);
+    CPPUNIT_ASSERT(iter_idset->second->size() == 1);
+    iter_id = iter_idset->second->find(default_id);
+    CPPUNIT_ASSERT(*iter_id == default_id);
+
+    iter_idset = _mainbuffer._callIDMap.find(test_id2);
+    CPPUNIT_ASSERT(iter_idset->second->size() == 1);
+    iter_id = iter_idset->second->find(default_id);
+    CPPUNIT_ASSERT(*iter_id == default_id);
+
+    ringbuffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(ringbuffer != NULL);
+    CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 2);
+    iter_readpointer = ringbuffer->_readpointer.find(test_id1);
+    CPPUNIT_ASSERT(iter_readpointer->first == test_id1);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+    iter_readpointer = ringbuffer->_readpointer.find(test_id2);
+    CPPUNIT_ASSERT(iter_readpointer->first == test_id2);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+
+    ringbuffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(ringbuffer != NULL);
+    CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 1);
+    iter_readpointer = ringbuffer->_readpointer.find(default_id);
+    CPPUNIT_ASSERT(iter_readpointer->first == default_id);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+
+    ringbuffer = _mainbuffer.getRingBuffer(test_id2);
+    CPPUNIT_ASSERT(ringbuffer != NULL);
+    CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 1);
+    iter_readpointer = ringbuffer->_readpointer.find(default_id);
+    CPPUNIT_ASSERT(iter_readpointer->first == default_id);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+
+
+    _debug("ok1\n");
+    
+    // unbind test_id1 with test_id2
+    // calling it twice not supposed to break anything
+    _mainbuffer.unBindCallID(default_id, test_id2);
+    _mainbuffer.unBindCallID(default_id, test_id2);
+
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 2);
+    CPPUNIT_ASSERT(_mainbuffer._callIDMap.size() == 2);
+
+    iter_buffer = _mainbuffer._ringBufferMap.find(default_id);
+    CPPUNIT_ASSERT(iter_buffer->first == default_id);
+    CPPUNIT_ASSERT(iter_buffer->second == _mainbuffer.getRingBuffer(default_id));
+
+    iter_buffer = _mainbuffer._ringBufferMap.find(test_id1);
+    CPPUNIT_ASSERT(iter_buffer->first == test_id1);
+    CPPUNIT_ASSERT(iter_buffer->second == _mainbuffer.getRingBuffer(test_id1));
+
+    iter_buffer = _mainbuffer._ringBufferMap.find(test_id2);
+    CPPUNIT_ASSERT(iter_buffer == _mainbuffer._ringBufferMap.end());
+
+    iter_idset = _mainbuffer._callIDMap.find(default_id);
+    CPPUNIT_ASSERT(iter_idset->second->size() == 1);
+    iter_id = iter_idset->second->find(test_id1);
+    CPPUNIT_ASSERT(*iter_id == test_id1);
+    iter_id = iter_idset->second->find(test_id2);
+    CPPUNIT_ASSERT(iter_id == iter_idset->second->end());
+
+    iter_idset = _mainbuffer._callIDMap.find(test_id1);
+    CPPUNIT_ASSERT(iter_idset->second->size() == 1);
+    iter_id = iter_idset->second->find(default_id);
+    CPPUNIT_ASSERT(*iter_id == default_id);
+
+    iter_idset = _mainbuffer._callIDMap.find(test_id2);
+    CPPUNIT_ASSERT(iter_idset == _mainbuffer._callIDMap.end());
+
+    ringbuffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(ringbuffer != NULL);
+    CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 1);
+    iter_readpointer = ringbuffer->_readpointer.find(test_id1);
+    CPPUNIT_ASSERT(iter_readpointer->first == test_id1);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+    iter_readpointer = ringbuffer->_readpointer.find(test_id2);
+    CPPUNIT_ASSERT(iter_readpointer == ringbuffer->_readpointer.end());
+
+    ringbuffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(ringbuffer != NULL);
+    CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 1);
+    iter_readpointer = ringbuffer->_readpointer.find(default_id);
+    CPPUNIT_ASSERT(iter_readpointer->first == default_id);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+    iter_readpointer = ringbuffer->_readpointer.find(test_id2);
+    CPPUNIT_ASSERT(iter_readpointer == ringbuffer->_readpointer.end());
+
+    CPPUNIT_ASSERT(_mainbuffer.getRingBuffer(test_id2) == NULL);
+
+
+    _mainbuffer.unBindCallID(default_id, test_id1);
+
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 0);
+    CPPUNIT_ASSERT(_mainbuffer._callIDMap.size() == 0);
+
+    // test unbind all function
+    _mainbuffer.bindCallID(default_id, test_id1);
+    _mainbuffer.bindCallID(default_id, test_id2);
+    _mainbuffer.bindCallID(test_id1, test_id2);
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 3);
+    CPPUNIT_ASSERT(_mainbuffer._callIDMap.size() == 3);
+
+    _mainbuffer.unBindAll(test_id2);
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 2);
+    CPPUNIT_ASSERT(_mainbuffer._callIDMap.size() == 2);
+
+    iter_buffer = _mainbuffer._ringBufferMap.find(default_id);
+    CPPUNIT_ASSERT(iter_buffer->first == default_id);
+    CPPUNIT_ASSERT(iter_buffer->second == _mainbuffer.getRingBuffer(default_id));
+
+    iter_buffer = _mainbuffer._ringBufferMap.find(test_id1);
+    CPPUNIT_ASSERT(iter_buffer->first == test_id1);
+    CPPUNIT_ASSERT(iter_buffer->second == _mainbuffer.getRingBuffer(test_id1));
+
+    iter_buffer = _mainbuffer._ringBufferMap.find(test_id2);
+    CPPUNIT_ASSERT(iter_buffer == _mainbuffer._ringBufferMap.end());
+
+    iter_idset = _mainbuffer._callIDMap.find(default_id);
+    CPPUNIT_ASSERT(iter_idset->second->size() == 1);
+    iter_id = iter_idset->second->find(test_id1);
+    CPPUNIT_ASSERT(*iter_id == test_id1);
+    iter_id = iter_idset->second->find(test_id2);
+    CPPUNIT_ASSERT(iter_id == iter_idset->second->end());
+
+    iter_idset = _mainbuffer._callIDMap.find(test_id1);
+    CPPUNIT_ASSERT(iter_idset->second->size() == 1);
+    iter_id = iter_idset->second->find(default_id);
+    CPPUNIT_ASSERT(*iter_id == default_id);
+
+    iter_idset = _mainbuffer._callIDMap.find(test_id2);
+    CPPUNIT_ASSERT(iter_idset == _mainbuffer._callIDMap.end());
+
+    ringbuffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(ringbuffer != NULL);
+    CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 1);
+    iter_readpointer = ringbuffer->_readpointer.find(test_id1);
+    CPPUNIT_ASSERT(iter_readpointer->first == test_id1);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+    iter_readpointer = ringbuffer->_readpointer.find(test_id2);
+    CPPUNIT_ASSERT(iter_readpointer == ringbuffer->_readpointer.end());
+
+    ringbuffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(ringbuffer != NULL);
+    CPPUNIT_ASSERT(ringbuffer->getNbReadPointer() == 1);
+    iter_readpointer = ringbuffer->_readpointer.find(default_id);
+    CPPUNIT_ASSERT(iter_readpointer->first == default_id);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+    iter_readpointer = ringbuffer->_readpointer.find(test_id2);
+    CPPUNIT_ASSERT(iter_readpointer == ringbuffer->_readpointer.end());
+    
+    
+}
+
+void MainBufferTest::testGetPutDataByID()
+{
+
+    _debug("MainBufferTest::testGetPutData()\n");
+    
+    CallID test_id = "getData putData";
+    CallID false_id = "false id";
+    
+    _mainbuffer.bindCallID(test_id);
+
+    int test_input1 = 12;
+    int test_input2 = 13;
+    int test_output;
+
+    int avail_for_put_testid;
+    int avail_for_put_defaultid;
+
+    // put by default_id get by test_id without preleminary put
+    avail_for_put_defaultid = _mainbuffer.availForPut();
+    CPPUNIT_ASSERT(_mainbuffer.availForGetByID(default_id, test_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.getDataByID(&test_output, sizeof(int), 100, default_id, test_id) == 0);
+
+    // put by default_id, get by test_id
+    CPPUNIT_ASSERT(_mainbuffer.availForPut() == avail_for_put_defaultid);
+    CPPUNIT_ASSERT(_mainbuffer.putData(&test_input1, sizeof(int)) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.availForPut() == (avail_for_put_defaultid - (int)sizeof(int)));
+    CPPUNIT_ASSERT(_mainbuffer.availForGetByID(default_id, test_id) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.getDataByID(&test_output, sizeof(int), 100, default_id, test_id) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.availForGetByID(default_id, test_id) == 0);
+    CPPUNIT_ASSERT(test_input1 == test_output);
+
+    // get by default_id without preliminary input
+    avail_for_put_testid = _mainbuffer.availForPut(test_id);
+    CPPUNIT_ASSERT(_mainbuffer.availForGetByID(test_id, default_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.getDataByID(&test_output, sizeof(int), 100, test_id, default_id) == 0);
+    
+    // pu by test_id get by test_id
+    CPPUNIT_ASSERT(_mainbuffer.availForPut(test_id) == avail_for_put_defaultid);
+    CPPUNIT_ASSERT(_mainbuffer.putData(&test_input2, sizeof(int), 100, test_id) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.availForGetByID(test_id, default_id) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.getDataByID(&test_output, sizeof(int), 100, test_id, default_id) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.availForGetByID(test_id, default_id) == 0);
+    CPPUNIT_ASSERT(test_input2 == test_output);
+
+    // put/get by false id
+    CPPUNIT_ASSERT(_mainbuffer.putData(&test_input2, sizeof(int), 100, false_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.getDataByID(&test_input2, sizeof(int), 100, false_id, false_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.getDataByID(&test_input2, sizeof(int), 100, default_id, false_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.getDataByID(&test_input2, sizeof(int), 100, false_id, default_id) == 0);
+
+    _mainbuffer.unBindCallID(test_id);
+
+}
+
+
+
+void MainBufferTest::testGetPutData()
+{
+
+    _debug("MainBufferTest::testGetDataAndCallID()\n");
+    
+    CallID test_id = "incoming rtp session";
+
+    _mainbuffer.bindCallID(test_id);
+
+    int test_input1 = 12;
+    int test_input2 = 13;
+    int test_output;
+
+    int avail_for_put_testid;
+    int avail_for_put_defaultid;
+
+    // get by test_id without preleminary put
+    avail_for_put_defaultid = _mainbuffer.availForPut();
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.getData(&test_output, sizeof(int), 100,  test_id) == 0);
+
+    // put by default_id, get by test_id
+    CPPUNIT_ASSERT(_mainbuffer.availForPut() == avail_for_put_defaultid);
+    CPPUNIT_ASSERT(_mainbuffer.putData(&test_input1, sizeof(int), 100) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.availForPut() == (avail_for_put_defaultid - (int)sizeof(int)));
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.getData(&test_output, sizeof(int), 100, test_id) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id) == 0);
+    CPPUNIT_ASSERT(test_input1 == test_output);
+
+    // get by default_id without preleminary put
+    avail_for_put_testid = _mainbuffer.availForPut(test_id);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet() == 0);
+    CPPUNIT_ASSERT(_mainbuffer.getData(&test_output, sizeof(int)) == 0);
+
+    // put by test_id, get by default_id
+    CPPUNIT_ASSERT(_mainbuffer.availForPut(test_id) == avail_for_put_testid);
+    CPPUNIT_ASSERT(_mainbuffer.putData(&test_input2, sizeof(int), 100, test_id) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.availForPut(test_id) == (avail_for_put_testid - (int)sizeof(int)));
+    CPPUNIT_ASSERT(_mainbuffer.availForGet() == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.getData(&test_output, sizeof(int), 100) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.availForGet() == 0);
+    CPPUNIT_ASSERT(test_input2 == test_output);
+
+    _mainbuffer.unBindCallID(test_id);
+
+}
+
+
+void MainBufferTest::testDiscardFlush()
+{
+
+    _debug("MainBufferTest::testDiscardFlush()\n");
+
+    CallID test_id = "flush discard";
+    // _mainbuffer.createRingBuffer(test_id);
+    _mainbuffer.bindCallID(test_id);
+
+    int test_input1 = 12;
+    // int test_output_size;
+    // int init_size;
+
+    CPPUNIT_ASSERT(_mainbuffer.putData(&test_input1, sizeof(int), 100, test_id) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.availForGet() == sizeof(int));
+    _mainbuffer.discard(sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.availForGet() == 0);
+
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id) == 0);
+    _mainbuffer.discard(sizeof(int), test_id);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id) == 0);
+
+    CPPUNIT_ASSERT(_mainbuffer.getRingBuffer(test_id)->getReadPointer(default_id) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.getRingBuffer(test_id)->getReadPointer(test_id) == 0);
+
+    
+    CPPUNIT_ASSERT(_mainbuffer.getRingBuffer(default_id)->getReadPointer(test_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.putData(&test_input1, sizeof(int), 100) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.getRingBuffer(default_id)->getReadPointer(test_id) == 0);
+    
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id) == sizeof(int));
+
+    CPPUNIT_ASSERT(_mainbuffer.getRingBuffer(default_id)->getReadPointer(test_id) == 0);
+    _mainbuffer.discard(sizeof(int), test_id);
+    CPPUNIT_ASSERT(_mainbuffer.getRingBuffer(default_id)->getReadPointer(test_id) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id) == 0);
+
+    // _mainbuffer.removeRingBuffer(test_id);
+    _mainbuffer.unBindCallID(test_id);
+
+}
+
+
+void MainBufferTest::testReadPointerInit()
+{
+
+    _debug("MainBufferTest::testReadPointerInit()\n");
+
+    CallID test_id = "test read pointer init";
+    // RingBuffer* test_ring_buffer = _mainbuffer.createRingBuffer(test_id);
+
+    _mainbuffer.bindCallID(test_id);
+
+    RingBuffer* test_ring_buffer = _mainbuffer.getRingBuffer(test_id);
+
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 0);
+    test_ring_buffer->storeReadPointer(30);
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer() == 30);
+
+    test_ring_buffer->createReadPointer(test_id);
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(test_id) == 0);
+    test_ring_buffer->storeReadPointer(10, test_id);
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(test_id) == 10);
+    test_ring_buffer->removeReadPointer(test_id);
+    CPPUNIT_ASSERT(test_ring_buffer->getReadPointer(test_id) == (int)NULL);
+    test_ring_buffer->removeReadPointer("false id");
+
+    // _mainbuffer.removeRingBuffer(test_id);
+    _mainbuffer.unBindCallID(test_id);
+}
+
+
+void MainBufferTest::testRingBufferSeveralPointers()
+{
+
+    _debug("MainBufferTest::testRingBufferSeveralPointers\n");
+
+    CallID test_id = "test multiple read pointer";
+    RingBuffer* test_ring_buffer = _mainbuffer.createRingBuffer(test_id);
+
+    CallID test_pointer1 = "test pointer 1";
+    CallID test_pointer2 = "test pointer 2";
+
+    test_ring_buffer->createReadPointer(test_pointer1);
+    test_ring_buffer->createReadPointer(test_pointer2);
+
+    int testint1 = 12;
+    int testint2 = 13;
+    int testint3 = 14;
+    int testint4 = 15;
+
+    int testoutput;
+
+    int initPutLen = test_ring_buffer->AvailForPut();
+
+    CPPUNIT_ASSERT(test_ring_buffer->Put(&testint1, sizeof(int)) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == initPutLen - (int)sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->getLen(test_pointer1) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->getLen(test_pointer2) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer1) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer2) == sizeof(int));
+
+    CPPUNIT_ASSERT(test_ring_buffer->Put(&testint2, sizeof(int)) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 2*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == initPutLen - 2*(int)sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->getLen(test_pointer1) == 2*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->getLen(test_pointer2) == 2*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer1) == 2*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer2) == 2*sizeof(int));
+
+    CPPUNIT_ASSERT(test_ring_buffer->Put(&testint3, sizeof(int)) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 3*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == initPutLen - 3*(int)sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->getLen(test_pointer1) == 3*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->getLen(test_pointer2) == 3*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer1) == 3*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer2) == 3*sizeof(int));
+
+    CPPUNIT_ASSERT(test_ring_buffer->Put(&testint4, sizeof(int)) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 4*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == initPutLen - 4*(int)sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->getLen(test_pointer1) == 4*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->getLen(test_pointer2) == 4*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer1) == 4*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer2) == 4*sizeof(int));
+
+
+    CPPUNIT_ASSERT(test_ring_buffer->Get(&testoutput, sizeof(int), 100, test_pointer1) == sizeof(int));
+    CPPUNIT_ASSERT(testoutput == testint1);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == initPutLen - 4*(int)sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer1) == 3*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer2) == 4*sizeof(int));
+
+    CPPUNIT_ASSERT(test_ring_buffer->Get(&testoutput, sizeof(int), 100, test_pointer2) == sizeof(int));
+    CPPUNIT_ASSERT(testoutput == testint1);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == initPutLen - 3*(int)sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer1) == 3*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer2) == 3*sizeof(int));
+    
+    // AvailForPut() is ok but AvailForGet(default_id) is not ok
+    // However, we should no be alowed to read in our own ring buffer 
+    // if we are either an AudioLayer or and RTP session
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == 4*sizeof(int));
+    
+    CPPUNIT_ASSERT(test_ring_buffer->Get(&testoutput, sizeof(int), 100, test_pointer1) == sizeof(int));
+    CPPUNIT_ASSERT(testoutput == testint2);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == initPutLen - 3*(int)sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer1) == 2*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer2) == 3*sizeof(int));
+
+    // AvailForPut() is ok but AvailForGet(default_id) is not ok
+    // However, we should no be alowed to read in our own ring buffer 
+    // if we are either an AudioLayer or and RTP session
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == 4*sizeof(int));
+
+    CPPUNIT_ASSERT(test_ring_buffer->Get(&testoutput, sizeof(int), 100, test_pointer2) == sizeof(int));
+    CPPUNIT_ASSERT(testoutput == testint2);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == initPutLen - 2*(int)sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer1) == 2*sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer2) == 2*sizeof(int));
+    
+    // AvailForPut() is ok but AvailForGet(default_id) is not ok
+    // However, we should no be alowed to read in our own ring buffer 
+    // if we are either an AudioLayer or and RTP session
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet() == 4*sizeof(int));
+
+    CPPUNIT_ASSERT(test_ring_buffer->Discard(sizeof(int), test_pointer1) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == initPutLen - 2*(int)sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer1) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer2) == 2*sizeof(int));
+
+    CPPUNIT_ASSERT(test_ring_buffer->Discard(sizeof(int), test_pointer2) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == initPutLen - (int)sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer1) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_pointer2) == sizeof(int));
+
+
+    test_ring_buffer->removeReadPointer(test_pointer1);
+    test_ring_buffer->removeReadPointer(test_pointer2);
+
+    _mainbuffer.removeRingBuffer(test_id);
+}
+
+
+
+void MainBufferTest::testConference()
+{
+
+    _debug("MainBufferTest::testConference()\n");
+
+    CallID test_id1 = "participant A";
+    CallID test_id2 = "participant B";
+    RingBuffer* test_ring_buffer;
+
+    RingBufferMap::iterator iter_ringbuffermap;
+    ReadPointer::iterator iter_readpointer;
+    CallIDMap::iterator iter_callidmap;
+    CallIDSet::iterator iter_callidset;
+
+    
+
+    // test initial setup
+    // ringbuffers
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 0);
+    test_ring_buffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(test_ring_buffer == NULL);
+
+    // callidmap
+    CPPUNIT_ASSERT(_mainbuffer._callIDMap.size() == 0);
+    iter_callidmap = _mainbuffer._callIDMap.find(default_id);
+    CPPUNIT_ASSERT(iter_callidmap == _mainbuffer._callIDMap.end());
+
+
+    // test bind Participant A with default 
+    _mainbuffer.bindCallID(test_id1);
+    // ringbuffers
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 2);
+    test_ring_buffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 1);
+    iter_readpointer = test_ring_buffer->_readpointer.find(test_id1);
+    CPPUNIT_ASSERT(iter_readpointer->first == test_id1);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 1);
+    iter_readpointer = test_ring_buffer->_readpointer.find(default_id);
+    CPPUNIT_ASSERT(iter_readpointer->first == default_id);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+    // callidmap
+    CPPUNIT_ASSERT(_mainbuffer._callIDMap.size() == 2);
+    iter_callidmap = _mainbuffer._callIDMap.find(default_id);
+    CPPUNIT_ASSERT(iter_callidmap->first == default_id);
+    CPPUNIT_ASSERT(iter_callidmap->second->size() == 1);
+    iter_callidset = iter_callidmap->second->find(test_id1);
+    CPPUNIT_ASSERT(*iter_callidset == test_id1);
+    iter_callidmap = _mainbuffer._callIDMap.find(test_id1);
+    CPPUNIT_ASSERT(iter_callidmap->first == test_id1);
+    CPPUNIT_ASSERT(iter_callidmap->second->size() == 1);
+    iter_callidset = iter_callidmap->second->find(default_id);
+    CPPUNIT_ASSERT(*iter_callidset == default_id);
+
+    // test bind Participant B with default
+    _mainbuffer.bindCallID(test_id2);
+    // ringbuffers
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 3);
+    test_ring_buffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 2);
+    iter_readpointer = test_ring_buffer->_readpointer.find(test_id1);
+    CPPUNIT_ASSERT(iter_readpointer->first == test_id1);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+    iter_readpointer = test_ring_buffer->_readpointer.find(test_id2);
+    CPPUNIT_ASSERT(iter_readpointer->first == test_id2);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 1);
+    iter_readpointer = test_ring_buffer->_readpointer.find(default_id);
+    CPPUNIT_ASSERT(iter_readpointer->first == default_id);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 1);
+    iter_readpointer = test_ring_buffer->_readpointer.find(default_id);
+    CPPUNIT_ASSERT(iter_readpointer->first == default_id);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+    // callidmap
+    CPPUNIT_ASSERT(_mainbuffer._callIDMap.size() == 3);
+    iter_callidmap = _mainbuffer._callIDMap.find(default_id);
+    CPPUNIT_ASSERT(iter_callidmap->first == default_id);
+    CPPUNIT_ASSERT(iter_callidmap->second->size() == 2);
+    iter_callidset = iter_callidmap->second->find(test_id1);
+    CPPUNIT_ASSERT(*iter_callidset == test_id1);
+    iter_callidset = iter_callidmap->second->find(test_id2);
+    CPPUNIT_ASSERT(*iter_callidset == test_id2);
+    iter_callidmap = _mainbuffer._callIDMap.find(test_id1);
+    CPPUNIT_ASSERT(iter_callidmap->first == test_id1);
+    CPPUNIT_ASSERT(iter_callidmap->second->size() == 1);
+    iter_callidset = iter_callidmap->second->find(default_id);
+    CPPUNIT_ASSERT(*iter_callidset == default_id);
+    iter_callidmap = _mainbuffer._callIDMap.find(test_id2);
+    CPPUNIT_ASSERT(iter_callidmap->first == test_id2);
+    CPPUNIT_ASSERT(iter_callidmap->second->size() == 1);
+    iter_callidset = iter_callidmap->second->find(default_id);
+    CPPUNIT_ASSERT(*iter_callidset == default_id);
+    
+    
+    // test bind Participant A with Participant B
+    _mainbuffer.bindCallID(test_id1, test_id2);
+    // ringbuffers
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 3);
+    test_ring_buffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 2);
+    iter_readpointer = test_ring_buffer->_readpointer.find(test_id1);
+    CPPUNIT_ASSERT(iter_readpointer->first == test_id1);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+    iter_readpointer = test_ring_buffer->_readpointer.find(test_id2);
+    CPPUNIT_ASSERT(iter_readpointer->first == test_id2);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 2);
+    iter_readpointer = test_ring_buffer->_readpointer.find(default_id);
+    CPPUNIT_ASSERT(iter_readpointer->first == default_id);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+    iter_readpointer = test_ring_buffer->_readpointer.find(test_id2);
+    CPPUNIT_ASSERT(iter_readpointer->first == test_id2);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->getNbReadPointer() == 2);
+    iter_readpointer = test_ring_buffer->_readpointer.find(default_id);
+    CPPUNIT_ASSERT(iter_readpointer->first == default_id);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+    iter_readpointer = test_ring_buffer->_readpointer.find(test_id1);
+    CPPUNIT_ASSERT(iter_readpointer->first == test_id1);
+    CPPUNIT_ASSERT(iter_readpointer->second == 0);
+    // callidmap
+    CPPUNIT_ASSERT(_mainbuffer._callIDMap.size() == 3);
+    iter_callidmap = _mainbuffer._callIDMap.find(default_id);
+    CPPUNIT_ASSERT(iter_callidmap->first == default_id);
+    CPPUNIT_ASSERT(iter_callidmap->second->size() == 2);
+    iter_callidset = iter_callidmap->second->find(test_id1);
+    CPPUNIT_ASSERT(*iter_callidset == test_id1);
+    iter_callidset = iter_callidmap->second->find(test_id2);
+    CPPUNIT_ASSERT(*iter_callidset == test_id2);
+    iter_callidmap = _mainbuffer._callIDMap.find(test_id1);
+    CPPUNIT_ASSERT(iter_callidmap->first == test_id1);
+    CPPUNIT_ASSERT(iter_callidmap->second->size() == 2);
+    iter_callidset = iter_callidmap->second->find(default_id);
+    CPPUNIT_ASSERT(*iter_callidset == default_id);
+    iter_callidset = iter_callidmap->second->find(test_id2);
+    CPPUNIT_ASSERT(*iter_callidset == test_id2);
+    iter_callidmap = _mainbuffer._callIDMap.find(test_id2);
+    CPPUNIT_ASSERT(iter_callidmap->first == test_id2);
+    CPPUNIT_ASSERT(iter_callidmap->second->size() == 2);
+    iter_callidset = iter_callidmap->second->find(default_id);
+    CPPUNIT_ASSERT(*iter_callidset == default_id);
+    iter_callidset = iter_callidmap->second->find(test_id1);
+    CPPUNIT_ASSERT(*iter_callidset == test_id1);
+    
+
+    // test putData default
+    int testint = 12;
+    int init_put_defaultid;
+    int init_put_id1;
+    int init_put_id2;
+
+    init_put_defaultid = _mainbuffer.getRingBuffer(default_id)->AvailForPut();
+    init_put_id1 = _mainbuffer.getRingBuffer(test_id1)->AvailForPut();
+    init_put_id2 = _mainbuffer.getRingBuffer(test_id2)->AvailForPut();
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(default_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id1) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id2) == 0);
+    // put data test ring buffers
+    CPPUNIT_ASSERT(_mainbuffer.putData(&testint, sizeof(int), 100) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == 0);
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0);
+    // test mainbuffer availforget
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(default_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id1) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id2) == 0);
+    //putdata test ring buffers
+    CPPUNIT_ASSERT(_mainbuffer.putData(&testint, sizeof(int), 100, test_id1) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0);
+    // test mainbuffer availforget
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(default_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id1) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id2) == sizeof(int));
+    //putdata test ring buffers
+    CPPUNIT_ASSERT(_mainbuffer.putData(&testint, sizeof(int), 100, test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id2 - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int));
+    // test mainbuffer availforget
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(default_id) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id1) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id2) == sizeof(int));
+
+
+    int test_output;
+
+    // test getData default id (audio layer)
+    CPPUNIT_ASSERT(_mainbuffer.getData(&test_output, sizeof(int), 100) == sizeof(int));
+    CPPUNIT_ASSERT(test_output == (testint + testint));
+    test_ring_buffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id2 - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int));
+    // test mainbuffer availforget
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(default_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id1) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id2) == sizeof(int));
+    // test getData test_id1 (audio layer)
+    CPPUNIT_ASSERT(_mainbuffer.getData(&test_output, sizeof(int), 100, test_id1) == sizeof(int));
+    CPPUNIT_ASSERT(test_output == (testint + testint));
+    test_ring_buffer = _mainbuffer.getRingBuffer(default_id); 
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0);
+    // test mainbuffer availforget
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(default_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id1) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id2) == sizeof(int));
+    // test getData test_id2 (audio layer)
+    CPPUNIT_ASSERT(_mainbuffer.getData(&test_output, sizeof(int), 100, test_id2) == sizeof(int));
+    CPPUNIT_ASSERT(test_output == (testint + testint));
+    test_ring_buffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_defaultid);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == 0);
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == 0);
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0);
+    // test mainbuffer availforget
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(default_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id1) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id2) == 0);
+
+
+    // test putData default (for discarting)
+    init_put_defaultid = _mainbuffer.getRingBuffer(default_id)->AvailForPut();
+    init_put_id1 = _mainbuffer.getRingBuffer(test_id1)->AvailForPut();
+    init_put_id2 = _mainbuffer.getRingBuffer(test_id2)->AvailForPut();
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(default_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id1) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id2) == 0);
+    // put data test ring buffers
+    CPPUNIT_ASSERT(_mainbuffer.putData(&testint, sizeof(int), 100) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == 0);
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0);
+    // test mainbuffer availforget
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(default_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id1) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id2) == 0);
+    //putdata test ring buffers
+    CPPUNIT_ASSERT(_mainbuffer.putData(&testint, sizeof(int), 100, test_id1) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0);
+    // test mainbuffer availforget
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(default_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id1) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id2) == sizeof(int));
+    //putdata test ring buffers
+    CPPUNIT_ASSERT(_mainbuffer.putData(&testint, sizeof(int), 100, test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id2 - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int));
+    // test mainbuffer availforget
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(default_id) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id1) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id2) == sizeof(int));
+    
+    // test discardData default id (audio layer)
+    CPPUNIT_ASSERT(_mainbuffer.discard(sizeof(int)) == sizeof(int));
+    CPPUNIT_ASSERT(test_output == (testint + testint));
+    test_ring_buffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id2 - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int));
+    // test mainbuffer availforget
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(default_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id1) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id2) == sizeof(int));
+    // test discardData test_id1 (audio layer)
+    CPPUNIT_ASSERT(_mainbuffer.discard(sizeof(int), test_id1) == sizeof(int));
+    CPPUNIT_ASSERT(test_output == (testint + testint));
+    test_ring_buffer = _mainbuffer.getRingBuffer(default_id); 
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0);
+    // test mainbuffer availforget
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(default_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id1) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id2) == sizeof(int));
+    // test discardData test_id2 (audio layer)
+    CPPUNIT_ASSERT(_mainbuffer.discard(sizeof(int), test_id2) == sizeof(int));
+    CPPUNIT_ASSERT(test_output == (testint + testint));
+    test_ring_buffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_defaultid);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == 0);
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == 0);
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0);
+    // test mainbuffer availforget
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(default_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id1) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id2) == 0);
+
+    
+    // test putData default (for flushing)
+    init_put_defaultid = _mainbuffer.getRingBuffer(default_id)->AvailForPut();
+    init_put_id1 = _mainbuffer.getRingBuffer(test_id1)->AvailForPut();
+    init_put_id2 = _mainbuffer.getRingBuffer(test_id2)->AvailForPut();
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(default_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id1) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id2) == 0);
+    // put data test ring buffers
+    CPPUNIT_ASSERT(_mainbuffer.putData(&testint, sizeof(int), 100) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == 0);
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0);
+    // test mainbuffer availforget
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(default_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id1) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id2) == 0);
+    //putdata test ring buffers
+    CPPUNIT_ASSERT(_mainbuffer.putData(&testint, sizeof(int), 100, test_id1) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0);
+    // test mainbuffer availforget
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(default_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id1) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id2) == sizeof(int));
+    //putdata test ring buffers
+    CPPUNIT_ASSERT(_mainbuffer.putData(&testint, sizeof(int), 100, test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id2 - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int));
+    // test mainbuffer availforget
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(default_id) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id1) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id2) == sizeof(int));
+
+    // test flush default id (audio layer)
+    _mainbuffer.flush();
+    CPPUNIT_ASSERT(test_output == (testint + testint));
+    test_ring_buffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id1);
+    _debug("%i\n", test_ring_buffer->putLen());
+    test_ring_buffer->debug();
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id2 - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == sizeof(int));
+    // test mainbuffer availforget
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(default_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id1) == sizeof(int));
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id2) == sizeof(int));
+    // test flush test_id1 (audio layer)
+    _mainbuffer.flush(test_id1);
+    CPPUNIT_ASSERT(test_output == (testint + testint));
+    test_ring_buffer = _mainbuffer.getRingBuffer(default_id); 
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_defaultid - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == sizeof(int));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == (int)(init_put_id1 - sizeof(int)));
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == sizeof(int));
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0);
+    // test mainbuffer availforget
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(default_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id1) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id2) == sizeof(int));
+    // test flush test_id2 (audio layer)
+    _mainbuffer.flush(test_id2);
+    CPPUNIT_ASSERT(test_output == (testint + testint));
+    test_ring_buffer = _mainbuffer.getRingBuffer(default_id);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_defaultid);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == 0);
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id1);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id2) == 0);
+    test_ring_buffer = _mainbuffer.getRingBuffer(test_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->putLen() == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForPut() == init_put_id2);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(default_id) == 0);
+    CPPUNIT_ASSERT(test_ring_buffer->AvailForGet(test_id1) == 0);
+    // test mainbuffer availforget
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(default_id) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id1) == 0);
+    CPPUNIT_ASSERT(_mainbuffer.availForGet(test_id2) == 0);
+    
+
+    _mainbuffer.unBindCallID(test_id1, test_id2);
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 3);
+    CPPUNIT_ASSERT(_mainbuffer._callIDMap.size() == 3);
+
+    _mainbuffer.unBindCallID(test_id1);
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 2);
+    CPPUNIT_ASSERT(_mainbuffer._callIDMap.size() == 2);
+
+    _mainbuffer.unBindCallID(test_id2);
+    CPPUNIT_ASSERT(_mainbuffer._ringBufferMap.size() == 0);
+    CPPUNIT_ASSERT(_mainbuffer._callIDMap.size() == 0);
+
+
+}
diff --git a/sflphone-common/test/mainbufferTest.h b/sflphone-common/test/mainbufferTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..330228f9a92d011d4540f74a4cb902c1ff525c20
--- /dev/null
+++ b/sflphone-common/test/mainbufferTest.h
@@ -0,0 +1,136 @@
+/*
+ *  Copyright (C) 2009 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.
+ */
+
+// Cppunit import
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCaller.h>
+#include <cppunit/TestCase.h>
+#include <cppunit/TestSuite.h>
+
+#include <assert.h>
+
+#include <stdio.h>
+#include <sstream>
+#include <ccrtp/rtp.h>
+
+
+// pjsip import
+#include <pjsip.h>
+#include <pjlib.h>
+#include <pjsip_ua.h>
+#include <pjlib-util.h>
+#include <pjnath/stun_config.h>
+
+// Application import
+#include "manager.h"
+#include "audio/mainbuffer.h"
+#include "audio/ringbuffer.h"
+#include "call.h"
+// #include "config/config.h"
+// #include "user_cfg.h"
+
+
+
+/*
+ * @file audiorecorderTest.cpp  
+ * @brief       Regroups unitary tests related to the plugin manager.
+ */
+
+#ifndef _MAINBUFFER_TEST_
+#define _MAINBUFFER_TEST_
+
+
+
+class MainBufferTest : public CppUnit::TestCase {
+
+    /*
+     * Use cppunit library macros to add unit test the factory
+     */
+    CPPUNIT_TEST_SUITE( MainBufferTest );
+       CPPUNIT_TEST( testRingBufferCreation );
+       CPPUNIT_TEST( testRingBufferReadPointer );
+       CPPUNIT_TEST( testCallIDSet );
+       CPPUNIT_TEST( testRingBufferInt );
+       CPPUNIT_TEST( testRingBufferNonDefaultID );
+       CPPUNIT_TEST( testRingBufferFloat );
+       CPPUNIT_TEST( testTwoPointer );
+       CPPUNIT_TEST( testBindUnbindBuffer );
+       CPPUNIT_TEST( testGetPutDataByID );
+       CPPUNIT_TEST( testGetPutData );
+       CPPUNIT_TEST( testDiscardFlush );
+       CPPUNIT_TEST( testReadPointerInit );
+       CPPUNIT_TEST( testRingBufferSeveralPointers );
+       CPPUNIT_TEST( testConference );
+    CPPUNIT_TEST_SUITE_END();
+
+    public:
+
+        MainBufferTest() : CppUnit::TestCase("Audio Layer Tests") {}
+        
+        /*
+         * Code factoring - Common resources can be initialized here.
+         * This method is called by unitcpp before each test
+         */
+        void setUp();
+
+        /*
+         * Code factoring - Common resources can be released here.
+         * This method is called by unitcpp after each test
+         */
+        inline void tearDown();
+
+        void testRingBufferCreation();
+
+	void testRingBufferReadPointer();
+
+	void testCallIDSet();
+
+	void testRingBufferInt();
+
+	void testRingBufferNonDefaultID();
+
+	void testRingBufferFloat();
+
+	void testTwoPointer();
+
+	void testBindUnbindBuffer();
+
+	void testGetPutDataByID();
+
+	void testGetPutData();
+
+	void testAvailForGetPut();
+
+	void testDiscardFlush();
+
+	void testReadPointerInit();
+
+	void testRingBufferSeveralPointers();
+
+	void testConference();
+
+    private:
+
+	MainBuffer _mainbuffer;
+};
+
+/* Register our test module */
+CPPUNIT_TEST_SUITE_REGISTRATION( MainBufferTest );
+
+#endif
diff --git a/sflphone-common/test/numbercleanerTest.h b/sflphone-common/test/numbercleanerTest.h
index 3152892a0053bcbb43b4e347933bc1bb576b2bca..3af6ab8c92a59e3125dd1d7d2aa2d9d648e32b2f 100644
--- a/sflphone-common/test/numbercleanerTest.h
+++ b/sflphone-common/test/numbercleanerTest.h
@@ -27,7 +27,7 @@
 
 // Application import
 #include "numbercleaner.h"
-
+// #include "../src/conference.h"
 /*
  * @file numbercleanerTest.cpp  
  * @brief       Regroups unitary tests related to the phone number cleanup function.
diff --git a/sflphone-common/test/rtpTest.cpp b/sflphone-common/test/rtpTest.cpp
index fba3f8aeb3adb7706dc05e415226983654a856cf..4a4d313314d20bdb6642bc7383deae0fd0f267a1 100644
--- a/sflphone-common/test/rtpTest.cpp
+++ b/sflphone-common/test/rtpTest.cpp
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 2009 Savoir-Faire Linux inc.
- *  Author: Alexandre Savarda <emmanuel.milou@savoirfairelinux.com>
+ *  Author: Alexandre Savarda <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