diff --git a/autogen.sh b/autogen.sh
index 06b6a97c95e0c7f4db9c8bd21a358a14784e9187..ac85bd137c9dcf2f99eef6992751d1a92876cdcd 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -4,6 +4,6 @@
 aclocal -I m4
 libtoolize --force
 autoheader
-autoconf -f
+autoconf -v -f
 automake -a
 ./configure $@
diff --git a/configure.ac b/configure.ac
index b07bc5ccf138ce263ede685185445b28019e9d81..b79bb61592859d9ab248973e624725313167b77c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -36,7 +36,10 @@ AC_CONFIG_FILES([src/Makefile \
   src/audio/codecs/Makefile
   src/audio/codecs/ilbc/Makefile \
   src/config/Makefile \
-  src/dbus/Makefile ]) 
+  src/dbus/Makefile \
+  src/plug-in/audiorecorder/Makefile \
+  src/plug-in/Makefile \
+  src/plug-in/test/Makefile]) 
   
   dnl Unitary test section
 AC_CONFIG_FILES([test/Makefile])
diff --git a/globals.mak b/globals.mak
index c03985035c4058b00b378f1b0809017241339313..7a0b085b9efbe0f7deefb226deed286cbba7982a 100644
--- a/globals.mak
+++ b/globals.mak
@@ -1,6 +1,7 @@
 # Global variables
 src=$(top_srcdir)
 sflcodecdir=$(libdir)/sflphone/codecs
+sflplugindir=$(libdir)/sflphone/plugins
 
 PJSIP_LIBS = -lpjnath-sfl -lpjsua-sfl -lpjsip-sfl -lpjmedia-sfl -lpjsip-simple-sfl -lpjsip-ua-sfl -lpjmedia-codec-sfl -lpjlib-util-sfl -lpj-sfl 
 
@@ -16,5 +17,6 @@ AM_CPPFLAGS = \
 	@SIP_CFLAGS@ \
 	@DBUSCPP_CFLAGS@ \
 	-DCODECS_DIR=\""$(sflcodecdir)"\" \
+	-DPLUGINS_DIR=\""$(sflplugindir)"\" \
 	-DENABLE_TRACE
 
diff --git a/src/Makefile.am b/src/Makefile.am
index b7c1a2839d2f02c089c3c17d24aa359d7c532dfa..dc83d84f8a88dce7600a278648ba0b2d265180b3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,7 +13,7 @@ IAXSOURCES =
 IAXHEADERS =
 endif
 
-SUBDIRS = audio config dbus
+SUBDIRS = audio config dbus plug-in
 
 # Add here the cpp files to be build with sflphone
 sflphoned_SOURCES = \
@@ -75,6 +75,8 @@ libsflphone_la_LIBADD = \
 	./audio/libaudio.la \
 	./dbus/libdbus.la \
 	./config/libconfig.la \
+	./plug-in/libplugin.la \
+	./plug-in/audiorecorder/libaudiorecorder.la \
 	$(IAX_LIBS) 
 
 libsflphone_la_SOURCES =
diff --git a/src/account.h b/src/account.h
index faf33dc162725e39c3dd4ad23985c0bb207b83c3..97e0b2bb3cbfa8510a03e675f0f8578a392d5a50 100644
--- a/src/account.h
+++ b/src/account.h
@@ -96,6 +96,8 @@ class Account{
          */
         inline VoIPLink* getVoIPLink() { return _link; }
 
+        inline void setVoIPLink (VoIPLink *link) { _link = link; }
+
         /**
          * Register the underlying VoIPLink. Launch the event listener.
          * This should update the getRegistrationState() return value.
diff --git a/src/audio/alsalayer.cpp b/src/audio/alsalayer.cpp
index 3ddb66a845e3a05ac1dbeed0a829a47433d63b79..bac1fe2fcd80275e6d232279846ec658b6c73cab 100644
--- a/src/audio/alsalayer.cpp
+++ b/src/audio/alsalayer.cpp
@@ -193,9 +193,10 @@ void AlsaLayer::startCaptureStream (void)
 void AlsaLayer::prepareCaptureStream (void)
 {
     if (is_capture_open() ) {
-        _debug("Prepare the capture\n");
-        if(snd_pcm_prepare (_CaptureHandle) < 0)    _debug("Error preparing the device\n");
-        prepare_capture ();
+        if(snd_pcm_prepare (_CaptureHandle) < 0)    
+            _debug("");
+        else
+            prepare_capture ();
     }
 }
 
@@ -383,11 +384,11 @@ AlsaLayer::open_device(std::string pcm_p, std::string pcm_c, int flag)
     }
 
     /* Start the secondary audio thread for callbacks */
-    try {
+    try{
         _audioThread->start();
     }
-    catch(...){
-        _debug("Fail to start audio thread\n");
+    catch (...) {
+        _debugException("Fail to start audio thread\n");
     }
 
     return true;
diff --git a/src/audio/audiorecord.cpp b/src/audio/audiorecord.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..65f63803942947e3cac58e91adcab2e76e1a9cf4
--- /dev/null
+++ b/src/audio/audiorecord.cpp
@@ -0,0 +1,177 @@
+/*
+ *  Copyright (C) 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 "audiorecord.h"
+
+AudioRecord::AudioRecord(){
+  sndSmplRate_ = 44100;
+  channels_ = 1;
+  byteCounter_ = 0;
+
+}
+
+
+void AudioRecord::setSndSamplingRate(int smplRate){
+  sndSmplRate_ = smplRate;
+}
+
+
+void AudioRecord::openFile(std::string fileName, FILE_TYPE type, SOUND_FORMAT format) {
+
+  channels_ =1;
+  fileType_ = type;
+  byteCounter_ = 0;
+  sndFormat_ = format;
+
+  bool result = false;
+
+  if(fileType_ == FILE_RAW){
+    result = setRawFile( fileName.c_str() );
+  }
+  else if (fileType_ == FILE_WAV){
+    result = setWavFile( fileName.c_str() );
+  }
+
+}
+
+
+void AudioRecord::closeFile() {
+
+  if (fp == 0) return;
+
+  if (fileType_ == FILE_RAW)
+    fclose(fp);
+  else if (fileType_ == FILE_WAV)
+    this->closeWavFile();
+
+}
+
+
+bool AudioRecord::isOpenFile() {
+  
+  if(fp)
+    return true;
+  else
+    return false;
+}
+
+
+bool AudioRecord::setRawFile(const char *fileName) {
+
+  char name[8192];
+  strncpy(name, fileName, 8192);
+  if ( strstr(name, ".raw") == NULL) strcat(name, ".raw");
+  fp = fopen(name, "wb");
+  if ( !fp ) {
+    cout << "AudioRecord: could not create RAW file: " << name << '.';
+    return false;
+  }
+
+  if ( sndFormat_ != INT16 ) { // TODO need to change INT16 to SINT16
+    sndFormat_ = INT16;
+    cout << "AudioRecord: using 16-bit signed integer data format for file " << name << '.';
+  }
+
+  cout << "AudioRecord: creating RAW file: " << name;
+  return true;
+}
+
+
+bool AudioRecord::setWavFile(const char *fileName) {
+  
+  char name[8192];
+  strncpy(name, fileName, 8192);
+  if ( strstr(name, ".wav") == NULL) strcat(name, ".wav");
+  fp = fopen(name, "wb");
+  if ( !fp ) {
+    cout << "AudioRecord: could not create WAV file: " << name;
+    return false;
+  }
+
+  struct wavhdr hdr = {"RIF", 44, "WAV", "fmt", 16, 1, 1,
+                        44100, 0, 2, 16, "dat", 0};
+  hdr.riff[3] = 'F';
+  hdr.wave[3] = 'E';
+  hdr.fmt[3]  = ' ';
+  hdr.data[3] = 'a';
+  hdr.num_chans = channels_;
+  if ( sndFormat_ == INT16 ) { //  TODO need to write INT16 to SINT16
+    hdr.bits_per_samp = 16;
+  }
+  hdr.bytes_per_samp = (SINT16) (channels_ * hdr.bits_per_samp / 8);
+  hdr.bytes_per_sec = (SINT32) (hdr.sample_rate * hdr.bytes_per_samp);
+
+
+  if ( fwrite(&hdr, 4, 11, fp) != 11 ) {
+    cout << "AudioRecord: could not write WAV header for file " << name << '.';
+    return false;
+  }
+
+  cout << "AudioRecord: creating WAV file: " << name;
+  return true;
+}
+
+
+void AudioRecord::closeWavFile()
+{
+  int bytes_per_sample = 1;
+  if ( sndFormat_ == INT16 )
+    bytes_per_sample = 2;
+
+
+  SINT32 bytes = byteCounter_ * channels_ * bytes_per_sample;
+  fseek(fp, 40, SEEK_SET); // jump to data length
+  fwrite(&bytes, 4, 1, fp);
+
+  bytes = byteCounter_ * channels_ * bytes_per_sample + 44; // + 44 for the wave header
+  fseek(fp, 4, SEEK_SET); // jump to file size
+  fwrite(&bytes, 4, 1, fp);
+  fclose( fp );
+}
+
+
+void AudioRecord::recData(SFLDataFormat* buffer, int nSamples) {
+
+  if (fp == 0){
+    cout << "AudioRecord: Can't record data, a file has not yet been opened!";
+    return;
+  }
+ 
+  if ( sndFormat_ == INT16 ) { // TODO change INT16 to SINT16
+    if (nSamples <= 1){
+      if ( fwrite(buffer, 2, 1, fp) != 1)
+        cout << "AudioRecord: Could not record data!";
+    }
+    else { 
+      for ( int k=0; k<nSamples; k++ ) {
+        cout << "Buffer[" << k << "] : " << buffer[k] << "\n";
+        if ( fwrite(&buffer[k], 2, 1, fp) != 1 )
+          cout << "AudioRecord: Could not record data!";
+      }
+    }
+  }
+
+  
+
+
+  byteCounter_ += (unsigned long)(sizeof(buffer) / sizeof(SINT16));
+
+  return;
+}
+
diff --git a/src/audio/audiorecord.h b/src/audio/audiorecord.h
new file mode 100644
index 0000000000000000000000000000000000000000..b38eefb29a59be117d896e9c2c6147ff43011ef3
--- /dev/null
+++ b/src/audio/audiorecord.h
@@ -0,0 +1,127 @@
+/*
+ *  Copyright (C) 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 <iostream>
+#include <string.h>
+
+#include "global.h"
+
+using namespace std;
+
+
+// structure for the wave header
+struct wavhdr {
+  char riff[4];           // "RIFF"
+  SINT32 file_size;       // in bytes
+  char wave[4];           // "WAVE"
+  char fmt[4];            // "fmt "
+  SINT32 chunk_size;      // in bytes (16 for PCM)
+  SINT16 format_tag;      // 1=PCM, 2=ADPCM, 3=IEEE float, 6=A-Law, 7=Mu-Law
+  SINT16 num_chans;       // 1=mono, 2=stereo
+  SINT32 sample_rate;
+  SINT32 bytes_per_sec;
+  SINT16 bytes_per_samp;  // 2=16-bit mono, 4=16-bit stereo
+  SINT16 bits_per_samp;
+  char data[4];           // "data"
+  SINT32 data_length;     // in bytes
+};
+
+class AudioRecord
+{
+
+public:
+
+  AudioRecord();
+
+  void setSndSamplingRate(int smplRate);
+
+  /**
+   * Check if no otehr file is opened, then create a new one
+   * @param fileName A string containing teh file (with/without extension)
+   * @param type     The sound file format (FILE_RAW, FILE_WAVE)
+   * @param format   Internal sound format (INT16 / INT32)
+   */
+  void openFile(std::string fileName, FILE_TYPE type, SOUND_FORMAT format);
+
+  /**
+   * Close the opend recording file. If wave: cout the number of byte
+   */
+  void closeFile();
+
+  /**
+   * Check if a file is already opened
+   */
+  bool isOpenFile();
+
+  /**
+   * Record a chunk of data in an openend file
+   * @param buffer  The data chunk to be recorded
+   * @param nSamples Number of samples (number of bytes) to be recorded 
+   */
+  void recData(SFLDataFormat* buffer, int nSamples); // TODO ad the data to rec
+
+protected:
+
+  /**
+   * Set the header for raw files
+   */
+  bool setRawFile(const char* fileName);
+
+  /**
+   * Set the header for wave files
+   */
+  bool setWavFile(const char* fileName);
+
+  /**
+   * Compute the number of byte recorded and close the file
+   */
+  void closeWavFile();
+
+  /**
+   * Pointer to the recorded file
+   */
+  FILE *fp;                      //file pointer
+
+  /**
+   * File format (RAW / WAVE)
+   */
+  FILE_TYPE fileType_;
+
+  /**
+   * Sound format (SINT16/SINT32)
+   */
+  SOUND_FORMAT sndFormat_;
+
+  /**
+   * Number of channels
+   */
+  int channels_;
+
+  /**
+   * Number f byte recorded
+   */
+  unsigned long byteCounter_;
+
+  /**
+   * Sampling rate
+   */
+  int sndSmplRate_;
+
+};
diff --git a/src/audio/audiortp.cpp b/src/audio/audiortp.cpp
index 56dc7174d9e6acd7229f3682dc6efd68e51538f4..34adf65db881d1e5fba25db81fd217e2315169c6 100644
--- a/src/audio/audiortp.cpp
+++ b/src/audio/audiortp.cpp
@@ -82,7 +82,7 @@ void
 AudioRtp::closeRtpSession () {
   ost::MutexLock m(_threadMutex);
   // This will make RTP threads finish.
-  // _debug("Stopping AudioRTP\n");
+  _debug("Stopping AudioRTP\n");
   try {
     delete _RTXThread; _RTXThread = 0;
   } catch(...) {
@@ -126,7 +126,6 @@ AudioRtpRTX::~AudioRtpRTX () {
     _debugException("! ARTP: Thread destructor didn't terminate correctly");
     throw;
   }
-  //_debug("terminate audiortprtx ended...\n");
   _ca = 0;
   if (!_sym) {
     delete _sessionRecv; _sessionRecv = NULL;
@@ -145,6 +144,7 @@ AudioRtpRTX::~AudioRtpRTX () {
   delete time; time = NULL;
 
   delete converter; converter = NULL;
+  
 }
 
   void
diff --git a/src/audio/pulselayer.cpp b/src/audio/pulselayer.cpp
index 45fb6edbae5810fec4c1b66935583532857327cf..8882ebe09ae56b369768b4b09a8b23e8034925e5 100644
--- a/src/audio/pulselayer.cpp
+++ b/src/audio/pulselayer.cpp
@@ -44,16 +44,10 @@ static  void audioCallback ( pa_stream* s, size_t bytes, void* userdata )
 // Destructor
 PulseLayer::~PulseLayer (void) 
 { 
-    //closeLayer();
-  
-    /* Delete the pointer streams */
-    delete playback;
-    delete record;
-  
+    closeLayer ();
+
     pa_context_disconnect( context );  
     pa_context_unref( context );
-
-    sleep(2);
 }
 
   void
diff --git a/src/audio/pulselayer.h b/src/audio/pulselayer.h
index bdb34085b62e9abea85f27f4517b4f76b701e780..36ca8057ce47dccc78c23455dfa9b4ae40cb6ce7 100644
--- a/src/audio/pulselayer.h
+++ b/src/audio/pulselayer.h
@@ -22,6 +22,7 @@
 
 #include "audiolayer.h"
 #include "audiostream.h"
+#include "plug-in/audiorecorder/audiorecord.h"
 
 #include <pulse/pulseaudio.h>
 
diff --git a/src/eventthread.cpp b/src/eventthread.cpp
index b0378c57ec651746988f822f6206254ac6bec2bd..0ecc444b41b1f2bdc52167d6796859d4173bf983 100644
--- a/src/eventthread.cpp
+++ b/src/eventthread.cpp
@@ -54,6 +54,7 @@ void AudioThread::run (void)
 {
     while(!testCancel()) {
         _alsa->audioCallback();
+        Thread::sleep(3);
     }
 }
 
diff --git a/src/global.h b/src/global.h
index 45332563dc0bbb28a0f22a777d997deafa5c32f5..6dfe9a1e1ba3c2a34eb2231a15f4b222ca033085 100644
--- a/src/global.h
+++ b/src/global.h
@@ -37,6 +37,19 @@
 typedef float float32;
 typedef short int16;
 
+//useful typedefs.
+typedef signed short SINT16;
+typedef signed int SINT32;
+
+typedef unsigned long FILE_TYPE;
+typedef unsigned long SOUND_FORMAT;
+
+const FILE_TYPE  FILE_RAW = 1;
+const FILE_TYPE  FILE_WAV = 2;
+
+static const SOUND_FORMAT INT16 = 0x2; // TODO shold change these symbols
+static const SOUND_FORMAT INT32 = 0x8;
+
 #define SUCCESS                 0
 
 #define ASSERT( expected , value)       if( value == expected ) return SUCCESS; \
diff --git a/src/managerimpl.cpp b/src/managerimpl.cpp
index e5292532c720e874939a541b2bc6c4ee436bc915..1881dae46c12cd08ff1fcf14523063e72758215a 100644
--- a/src/managerimpl.cpp
+++ b/src/managerimpl.cpp
@@ -249,6 +249,7 @@ ManagerImpl::answerCall(const CallID& id)
   bool
 ManagerImpl::hangupCall(const CallID& id)
 {
+  _debug("ManagerImpl::hangupCall(): This function is called when user hangup \n");
     PulseLayer *pulselayer;
     AccountID accountid;
     bool returnValue;
@@ -370,6 +371,7 @@ ManagerImpl::transferCall(const CallID& id, const std::string& to)
   bool
 ManagerImpl::refuseCall (const CallID& id)
 {
+  _debug("ManagerImpl::refuseCall(): method called");
   stopTone(true);
   AccountID accountid = getAccountFromCall( id );
   if (accountid == AccountNULL) {
@@ -510,6 +512,7 @@ ManagerImpl::playDtmf(char code, bool isTalking)
         // Put buffer to urgentRingBuffer 
         // put the size in bytes...
         // so size * 1 channel (mono) * sizeof (bytes for the data)
+        audiolayer->startStream();
         audiolayer->putUrgent (buf, size * sizeof(SFLDataFormat));
     }
     ret = true;
@@ -631,8 +634,10 @@ ManagerImpl::peerRingingCall(const CallID& id)
   void
 ManagerImpl::peerHungupCall(const CallID& id)
 {
+    _debug("ManagerImpl::peerHungupCall():this function is called when peer hangup \n");
     PulseLayer *pulselayer;
     AccountID accountid;
+    bool returnValue;
 
     accountid = getAccountFromCall( id );
     if (accountid == AccountNULL) {
@@ -648,6 +653,8 @@ ManagerImpl::peerHungupCall(const CallID& id)
         switchCall("");
     }
 
+    returnValue = getAccountLink(accountid)->hangup(id);
+
     removeWaitingCall(id);
     removeCallAccount(id);
   
@@ -1408,9 +1415,14 @@ int ManagerImpl::isStunEnabled (void)
 
 void ManagerImpl::enableStun (void)
 {
-  ( getConfigInt( SIGNALISATION , STUN_ENABLE ) == STUN_ENABLED )? setConfig(SIGNALISATION , STUN_ENABLE , NO_STR ) : setConfig( SIGNALISATION , STUN_ENABLE , YES_STR );
+    /* Update the config */
+    ( getConfigInt( SIGNALISATION , STUN_ENABLE ) == STUN_ENABLED )? setConfig(SIGNALISATION , STUN_ENABLE , NO_STR ) : setConfig( SIGNALISATION , STUN_ENABLE , YES_STR );
+
+    /* Restart PJSIP */
+    this->restartPJSIP (); 
 }
 
+
     int
 ManagerImpl::getVolumeControls( void )
 {
@@ -1945,6 +1957,7 @@ void ManagerImpl::setAccountDetails( const std::string& accountID, const std::ma
     setConfig(accountID, CONFIG_ACCOUNT_MAILBOX,(*details.find(CONFIG_ACCOUNT_MAILBOX)).second);
   
     // SIP SPECIFIC
+    /*
     if (accountType == "SIP") {
     
         link =  Manager::instance().getAccountLink( accountID );
@@ -1966,8 +1979,8 @@ void ManagerImpl::setAccountDetails( const std::string& accountID, const std::ma
         {
             link->setStunServer("");
         }
-        //restartPjsip();
-    }
+        restartPJSIP();
+    }*/
 
     saveConfig();
   
@@ -2232,6 +2245,30 @@ AccountMap ManagerImpl::getSipAccountMap( void )
     return sipaccounts;
 }
 
+void ManagerImpl::restartPJSIP (void)
+{
+    //SIPVoIPLink *siplink;
+
+    //unloadAccountMap ();
+
+    /* First unregister all SIP accounts */
+    //this->unregisterCurSIPAccounts();
+    /* Terminate and initialize the PJSIP library */
+    //siplink = dynamic_cast<SIPVoIPLink*> (getSIPAccountLink ());
+    //if (siplink) 
+    //{
+      //  siplink->terminate ();
+       // _debug ("*************************************************Terminate done\n");
+        //siplink = SIPVoIPLink::instance("");
+        //siplink->init ();
+    //}
+    //_debug("***************************************************Init Done\n");
+    //loadAccountMap();
+    //initRegisterAccounts ();
+    /* Then register all enabled SIP accounts */
+    //this->registerCurSIPAccounts(siplink);
+}
+
 VoIPLink* ManagerImpl::getAccountLink(const AccountID& accountID)
 {
   Account* acc = getAccount(accountID);
@@ -2241,6 +2278,23 @@ VoIPLink* ManagerImpl::getAccountLink(const AccountID& accountID)
   return 0;
 }
 
+VoIPLink* ManagerImpl::getSIPAccountLink()
+{
+    /* We are looking for the first SIP account we met because all the SIP accounts have the same voiplink */
+    Account *account;
+    AccountMap::iterator iter;
+    for(iter = _accountMap.begin(); iter != _accountMap.end(); ++iter) {
+        account = iter->second;
+        if( account->getType() == "sip" ){
+            return account->getVoIPLink();
+        }
+    }
+    return NULL;
+}
+
+
+
+
 pjsip_regc 
 *getSipRegcFromID(const AccountID& id UNUSED)
 {
@@ -2253,32 +2307,35 @@ pjsip_regc
 
 void ManagerImpl::unregisterCurSIPAccounts()
 {
-  AccountMap::iterator iter = _accountMap.begin();
-  while( iter != _accountMap.end() ) {
-    if ( iter->second) {
-        std::string p =  Manager::instance().getConfigString( iter->first , CONFIG_ACCOUNT_TYPE );
-      if ( iter->second->isEnabled() && p == "SIP") {
-	// NOW
-	iter->second->unregisterVoIPLink();
-      }
-    }
+    Account *current;
+
+    AccountMap::iterator iter = _accountMap.begin();
+    while( iter != _accountMap.end() ) {
+        current = iter->second;
+        if (current) {
+            if ( current->isEnabled() && current->getType() == "sip") {
+	            current->unregisterVoIPLink();
+            }
+        }
     iter++;
-  }
+    }
 }
 
-void ManagerImpl::registerCurSIPAccounts()
+void ManagerImpl::registerCurSIPAccounts(VoIPLink *link)
 {
-  AccountMap::iterator iter = _accountMap.begin();
-  while( iter != _accountMap.end() ) {
-    if ( iter->second) {
-        std::string p =  Manager::instance().getConfigString( iter->first , CONFIG_ACCOUNT_TYPE );
-      if ( iter->second->isEnabled() && p == "SIP") {
-	// NOW
-	iter->second->registerVoIPLink();
-      }
-    }
+    Account *current;
+  
+    AccountMap::iterator iter = _accountMap.begin();
+    while( iter != _accountMap.end() ) {
+        current = iter->second;
+        if (current) {
+            if ( current->isEnabled() && current->getType() == "sip") {
+                //current->setVoIPLink(link);
+	            current->registerVoIPLink();
+            }
+        }
     iter++;
-  }    
+    }    
 }
 
 #ifdef TEST
diff --git a/src/managerimpl.h b/src/managerimpl.h
index cc3411f3ade26470030f558b6cba32e18795bfdd..45471b7b211e5b23a93d2c40d74eceb958cbd85a 100644
--- a/src/managerimpl.h
+++ b/src/managerimpl.h
@@ -789,11 +789,11 @@ class ManagerImpl {
      * @param void
      * @return void
      */
-    void restartPjsip();
+    void restartPJSIP( );
 
     void unregisterCurSIPAccounts();
     
-    void registerCurSIPAccounts();
+    void registerCurSIPAccounts(VoIPLink *link);
     
     /**
      * Returns a map with only the existing SIP accounts
@@ -1014,6 +1014,8 @@ public:
      */
     VoIPLink* getAccountLink(const AccountID& accountID);
 
+    VoIPLink* getSIPAccountLink (void);
+
     AccountID getAccountIdFromNameAndServer(const std::string& userName, const std::string& server);
 
     int getSipPort();
diff --git a/src/plug-in/Makefile.am b/src/plug-in/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..c97ccdc21ad9d23126553e6efeda496aba88d944
--- /dev/null
+++ b/src/plug-in/Makefile.am
@@ -0,0 +1,12 @@
+include ../../globals.mak
+
+SUBDIRS=audiorecorder
+
+noinst_LTLIBRARIES = libplugin.la
+
+SUBDIRS=test
+
+libplugin_la_SOURCES = \
+		pluginmanager.cpp \
+		librarymanager.cpp
+
diff --git a/src/plug-in/audiorecorder/Makefile.am b/src/plug-in/audiorecorder/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..37a2ce4ed072fc300b0d85771f72e81d2fdf42e6
--- /dev/null
+++ b/src/plug-in/audiorecorder/Makefile.am
@@ -0,0 +1,7 @@
+include $(top_srcdir)/globals.mak
+
+noinst_LTLIBRARIES = libaudiorecorder.la
+
+libaudiorecorder_la_SOURCES = \
+		audiorecord.cpp 
+
diff --git a/src/plug-in/audiorecorder/audiorecord.cpp b/src/plug-in/audiorecorder/audiorecord.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..65f63803942947e3cac58e91adcab2e76e1a9cf4
--- /dev/null
+++ b/src/plug-in/audiorecorder/audiorecord.cpp
@@ -0,0 +1,177 @@
+/*
+ *  Copyright (C) 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 "audiorecord.h"
+
+AudioRecord::AudioRecord(){
+  sndSmplRate_ = 44100;
+  channels_ = 1;
+  byteCounter_ = 0;
+
+}
+
+
+void AudioRecord::setSndSamplingRate(int smplRate){
+  sndSmplRate_ = smplRate;
+}
+
+
+void AudioRecord::openFile(std::string fileName, FILE_TYPE type, SOUND_FORMAT format) {
+
+  channels_ =1;
+  fileType_ = type;
+  byteCounter_ = 0;
+  sndFormat_ = format;
+
+  bool result = false;
+
+  if(fileType_ == FILE_RAW){
+    result = setRawFile( fileName.c_str() );
+  }
+  else if (fileType_ == FILE_WAV){
+    result = setWavFile( fileName.c_str() );
+  }
+
+}
+
+
+void AudioRecord::closeFile() {
+
+  if (fp == 0) return;
+
+  if (fileType_ == FILE_RAW)
+    fclose(fp);
+  else if (fileType_ == FILE_WAV)
+    this->closeWavFile();
+
+}
+
+
+bool AudioRecord::isOpenFile() {
+  
+  if(fp)
+    return true;
+  else
+    return false;
+}
+
+
+bool AudioRecord::setRawFile(const char *fileName) {
+
+  char name[8192];
+  strncpy(name, fileName, 8192);
+  if ( strstr(name, ".raw") == NULL) strcat(name, ".raw");
+  fp = fopen(name, "wb");
+  if ( !fp ) {
+    cout << "AudioRecord: could not create RAW file: " << name << '.';
+    return false;
+  }
+
+  if ( sndFormat_ != INT16 ) { // TODO need to change INT16 to SINT16
+    sndFormat_ = INT16;
+    cout << "AudioRecord: using 16-bit signed integer data format for file " << name << '.';
+  }
+
+  cout << "AudioRecord: creating RAW file: " << name;
+  return true;
+}
+
+
+bool AudioRecord::setWavFile(const char *fileName) {
+  
+  char name[8192];
+  strncpy(name, fileName, 8192);
+  if ( strstr(name, ".wav") == NULL) strcat(name, ".wav");
+  fp = fopen(name, "wb");
+  if ( !fp ) {
+    cout << "AudioRecord: could not create WAV file: " << name;
+    return false;
+  }
+
+  struct wavhdr hdr = {"RIF", 44, "WAV", "fmt", 16, 1, 1,
+                        44100, 0, 2, 16, "dat", 0};
+  hdr.riff[3] = 'F';
+  hdr.wave[3] = 'E';
+  hdr.fmt[3]  = ' ';
+  hdr.data[3] = 'a';
+  hdr.num_chans = channels_;
+  if ( sndFormat_ == INT16 ) { //  TODO need to write INT16 to SINT16
+    hdr.bits_per_samp = 16;
+  }
+  hdr.bytes_per_samp = (SINT16) (channels_ * hdr.bits_per_samp / 8);
+  hdr.bytes_per_sec = (SINT32) (hdr.sample_rate * hdr.bytes_per_samp);
+
+
+  if ( fwrite(&hdr, 4, 11, fp) != 11 ) {
+    cout << "AudioRecord: could not write WAV header for file " << name << '.';
+    return false;
+  }
+
+  cout << "AudioRecord: creating WAV file: " << name;
+  return true;
+}
+
+
+void AudioRecord::closeWavFile()
+{
+  int bytes_per_sample = 1;
+  if ( sndFormat_ == INT16 )
+    bytes_per_sample = 2;
+
+
+  SINT32 bytes = byteCounter_ * channels_ * bytes_per_sample;
+  fseek(fp, 40, SEEK_SET); // jump to data length
+  fwrite(&bytes, 4, 1, fp);
+
+  bytes = byteCounter_ * channels_ * bytes_per_sample + 44; // + 44 for the wave header
+  fseek(fp, 4, SEEK_SET); // jump to file size
+  fwrite(&bytes, 4, 1, fp);
+  fclose( fp );
+}
+
+
+void AudioRecord::recData(SFLDataFormat* buffer, int nSamples) {
+
+  if (fp == 0){
+    cout << "AudioRecord: Can't record data, a file has not yet been opened!";
+    return;
+  }
+ 
+  if ( sndFormat_ == INT16 ) { // TODO change INT16 to SINT16
+    if (nSamples <= 1){
+      if ( fwrite(buffer, 2, 1, fp) != 1)
+        cout << "AudioRecord: Could not record data!";
+    }
+    else { 
+      for ( int k=0; k<nSamples; k++ ) {
+        cout << "Buffer[" << k << "] : " << buffer[k] << "\n";
+        if ( fwrite(&buffer[k], 2, 1, fp) != 1 )
+          cout << "AudioRecord: Could not record data!";
+      }
+    }
+  }
+
+  
+
+
+  byteCounter_ += (unsigned long)(sizeof(buffer) / sizeof(SINT16));
+
+  return;
+}
+
diff --git a/src/plug-in/audiorecorder/audiorecord.h b/src/plug-in/audiorecorder/audiorecord.h
new file mode 100644
index 0000000000000000000000000000000000000000..b38eefb29a59be117d896e9c2c6147ff43011ef3
--- /dev/null
+++ b/src/plug-in/audiorecorder/audiorecord.h
@@ -0,0 +1,127 @@
+/*
+ *  Copyright (C) 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 <iostream>
+#include <string.h>
+
+#include "global.h"
+
+using namespace std;
+
+
+// structure for the wave header
+struct wavhdr {
+  char riff[4];           // "RIFF"
+  SINT32 file_size;       // in bytes
+  char wave[4];           // "WAVE"
+  char fmt[4];            // "fmt "
+  SINT32 chunk_size;      // in bytes (16 for PCM)
+  SINT16 format_tag;      // 1=PCM, 2=ADPCM, 3=IEEE float, 6=A-Law, 7=Mu-Law
+  SINT16 num_chans;       // 1=mono, 2=stereo
+  SINT32 sample_rate;
+  SINT32 bytes_per_sec;
+  SINT16 bytes_per_samp;  // 2=16-bit mono, 4=16-bit stereo
+  SINT16 bits_per_samp;
+  char data[4];           // "data"
+  SINT32 data_length;     // in bytes
+};
+
+class AudioRecord
+{
+
+public:
+
+  AudioRecord();
+
+  void setSndSamplingRate(int smplRate);
+
+  /**
+   * Check if no otehr file is opened, then create a new one
+   * @param fileName A string containing teh file (with/without extension)
+   * @param type     The sound file format (FILE_RAW, FILE_WAVE)
+   * @param format   Internal sound format (INT16 / INT32)
+   */
+  void openFile(std::string fileName, FILE_TYPE type, SOUND_FORMAT format);
+
+  /**
+   * Close the opend recording file. If wave: cout the number of byte
+   */
+  void closeFile();
+
+  /**
+   * Check if a file is already opened
+   */
+  bool isOpenFile();
+
+  /**
+   * Record a chunk of data in an openend file
+   * @param buffer  The data chunk to be recorded
+   * @param nSamples Number of samples (number of bytes) to be recorded 
+   */
+  void recData(SFLDataFormat* buffer, int nSamples); // TODO ad the data to rec
+
+protected:
+
+  /**
+   * Set the header for raw files
+   */
+  bool setRawFile(const char* fileName);
+
+  /**
+   * Set the header for wave files
+   */
+  bool setWavFile(const char* fileName);
+
+  /**
+   * Compute the number of byte recorded and close the file
+   */
+  void closeWavFile();
+
+  /**
+   * Pointer to the recorded file
+   */
+  FILE *fp;                      //file pointer
+
+  /**
+   * File format (RAW / WAVE)
+   */
+  FILE_TYPE fileType_;
+
+  /**
+   * Sound format (SINT16/SINT32)
+   */
+  SOUND_FORMAT sndFormat_;
+
+  /**
+   * Number of channels
+   */
+  int channels_;
+
+  /**
+   * Number f byte recorded
+   */
+  unsigned long byteCounter_;
+
+  /**
+   * Sampling rate
+   */
+  int sndSmplRate_;
+
+};
diff --git a/src/plug-in/librarymanager.cpp b/src/plug-in/librarymanager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..138b59f5f49b2c2ed19b170deb36dfb373b00846
--- /dev/null
+++ b/src/plug-in/librarymanager.cpp
@@ -0,0 +1,103 @@
+/*
+ *  Copyright (C) 2009 Savoir-Faire Linux inc.
+ *  Author: Emmanuel Milou <emmanuel.milou@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 "librarymanager.h"
+    
+    LibraryManager::LibraryManager (const std::string &filename)
+    : _filename(filename), _handlePtr(NULL)
+{
+    _handlePtr = loadLibrary (filename);
+}
+
+LibraryManager::~LibraryManager (void)
+{
+    unloadLibrary ();
+}
+
+LibraryManager::LibraryHandle LibraryManager::loadLibrary (const std::string &filename)
+{
+    LibraryHandle pluginHandlePtr = NULL;
+    const char *error;
+
+    _debug("Loading dynamic library %s\n", filename.c_str());
+
+    /* Load the library */
+    pluginHandlePtr = dlopen( filename.c_str(), RTLD_LAZY );
+    if( !pluginHandlePtr ) {
+        error = dlerror();
+        _debug("Error while opening plug-in: %s\n", error);
+        return NULL;
+    }
+    dlerror();
+    return pluginHandlePtr;
+}
+
+int LibraryManager::unloadLibrary ()
+{
+    if (_handlePtr == NULL)
+        return 1;
+
+    _debug("Unloading dynamic library ...\n");
+    dlclose( _handlePtr );
+    if (dlerror())
+    {
+        _debug("Error unloading the library : %s\n...", dlerror());
+        return 1;
+    }
+    return 0;
+}
+
+int LibraryManager::resolveSymbol (const std::string &symbol, SymbolHandle *symbolPtr)
+{
+    SymbolHandle sy = 0;
+
+    if (_handlePtr){
+        try {
+            sy = dlsym(_handlePtr, symbol.c_str());
+            if(sy != NULL) {
+                *symbolPtr = sy;
+                return 0;
+            }
+        }
+        catch (...) {}
+        
+        throw LibraryManagerException ( _filename, symbol, LibraryManagerException::symbolNotFound);
+    }
+    else
+        return 1;
+}
+
+
+/************************************************************************************************/
+
+LibraryManagerException::LibraryManagerException (const std::string &libraryName, const std::string &details, Reason reason) :
+    _reason (reason), _details (""), std::runtime_error ("")
+    
+{
+    if (_reason == loadingFailed)
+        _details = "Error when loading " + libraryName + "\n" + details;
+    else
+        _details = "Error when resolving symbol " + details + " in " + libraryName;
+}
+
+const char* LibraryManagerException::what () const throw()
+{
+    return _details.c_str();
+}
diff --git a/src/plug-in/librarymanager.h b/src/plug-in/librarymanager.h
new file mode 100644
index 0000000000000000000000000000000000000000..e244d448a1152a46950d4b0ec95e06847eac4ff5
--- /dev/null
+++ b/src/plug-in/librarymanager.h
@@ -0,0 +1,70 @@
+/*
+ *  Copyright (C) 2009 Savoir-Faire Linux inc.
+ *  Author: Emmanuel Milou <emmanuel.milou@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 LIBRARY_MANAGER_H
+#define LIBRARY_MANAGER_H
+
+#include "dlfcn.h"
+#include <stdexcept> 
+
+#include "global.h"
+
+class LibraryManager {
+
+    public:
+        typedef void* LibraryHandle;
+        typedef void* SymbolHandle;
+
+        LibraryManager (const std::string &filename);
+        ~LibraryManager (void);
+
+        int resolveSymbol (const std::string &symbol, SymbolHandle *ptr);
+
+        int unloadLibrary (void);
+
+    protected:
+        LibraryHandle loadLibrary (const std::string &filename);
+
+    private:
+        std::string _filename;
+        LibraryHandle _handlePtr;
+};
+
+class LibraryManagerException : public std::runtime_error {
+
+    public:
+
+        typedef enum Reason {
+            loadingFailed = 0,
+            symbolNotFound
+        }Reason;
+
+        LibraryManagerException (const std::string &libraryName, const std::string &details, Reason reason);
+        ~LibraryManagerException (void) throw() {}
+
+        inline Reason getReason (void) { return _reason; } 
+
+        const char* what () const throw();
+
+    private:
+        Reason _reason;
+        std::string _details;
+};
+
+#endif // LIBRARY_MANAGER_H
diff --git a/src/plug-in/plugin.h b/src/plug-in/plugin.h
new file mode 100644
index 0000000000000000000000000000000000000000..2769c56c372e22be24334107ef6efdf5bf4e8b31
--- /dev/null
+++ b/src/plug-in/plugin.h
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (C) 2009 Savoir-Faire Linux inc.
+ *  Author: Emmanuel Milou <emmanuel.milou@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 PLUGIN_H
+#define PLUGIN_H
+
+#include "global.h" 
+
+#include "pluginmanager.h" 
+
+/*
+ * @file plugin.h
+ * @brief Define a plugin object 
+ */
+
+class Plugin {
+
+    public:
+        Plugin( const std::string &name ){
+            _name = name;
+        }
+
+        virtual ~Plugin()  {}
+
+        inline std::string getPluginName (void) { return _name; }
+
+        /**
+         * Return the minimal core version required so that the plugin could work
+         * @return int  The version required
+         */
+        virtual int initFunc (PluginInfo **info) = 0;
+
+    private:
+        Plugin &operator =(const Plugin &plugin);
+
+        std::string _name;
+};
+
+typedef Plugin* createFunc (void);
+
+typedef void destroyFunc (Plugin*);
+
+#endif //PLUGIN_H
+
diff --git a/src/plug-in/pluginmanager.cpp b/src/plug-in/pluginmanager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8d391f6ae6383c18220484b0c98d00991184ac9b
--- /dev/null
+++ b/src/plug-in/pluginmanager.cpp
@@ -0,0 +1,231 @@
+/*
+ *  Copyright (C) 2009 Savoir-Faire Linux inc.
+ *  Author: Emmanuel Milou <emmanuel.milou@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 <dirent.h>
+#include <dlfcn.h>
+
+#include "pluginmanager.h"
+
+PluginManager* PluginManager::_instance = 0;
+
+    PluginManager* 
+PluginManager::instance()
+{
+    if(!_instance){
+        return new PluginManager();
+    }
+    return _instance;
+}
+
+    PluginManager::PluginManager()
+:_loadedPlugins()
+{
+    _instance = this;
+}
+
+PluginManager::~PluginManager()
+{
+    _instance = 0;
+}
+
+    int 
+PluginManager::loadPlugins (const std::string &path)
+{
+    std::string pluginDir, current;
+    DIR *dir;
+    dirent *dirStruct;
+    LibraryManager *library;
+    Plugin *plugin;
+
+    const std::string pDir = "..";
+    const std::string cDir = ".";
+
+    /* The directory in which plugins are dropped. Default: /usr/lib/sflphone/plugins/ */
+    ( path == "" )? pluginDir = std::string(PLUGINS_DIR).append("/"):pluginDir = path;
+    _debug("Loading plugins from %s...\n", pluginDir.c_str());
+
+    dir = opendir( pluginDir.c_str() );
+    /* Test if the directory exists or is readable */
+    if( dir ){
+        /* Read the directory */
+        while( (dirStruct=readdir(dir)) ){
+            /* Get the name of the current item in the directory */
+            current = dirStruct->d_name;
+            /* Test if the current item is not the parent or the current directory */
+            if( current != pDir && current != cDir ){
+
+                /* Load the dynamic library */
+                library = loadDynamicLibrary( pluginDir + current );
+
+                /* Instanciate the plugin object */
+                if(instanciatePlugin (library, &plugin) != 0)       	        
+                {
+                    _debug("Error instanciating the plugin ...\n");
+                    return 1;
+                }
+
+                /* Regitering the current plugin */
+                if(registerPlugin (plugin, library) != 0)
+                {
+                    _debug("Error registering the plugin ...\n");
+                    return 1;
+                }
+            }
+        }
+    }
+    else
+        return 1;
+
+    /* Close the directory */
+    closedir( dir );
+
+    return 0;
+}
+
+int 
+PluginManager::unloadPlugins (void)
+{
+    PluginInfo *info;
+
+    if(_loadedPlugins.empty())    return 0;  
+
+    /* Use an iterator on the loaded plugins map */
+    pluginMap::iterator iter;
+
+    iter = _loadedPlugins.begin();
+    while( iter != _loadedPlugins.end() ) {
+        info = iter->second;
+        
+        if (deletePlugin (info) != 0)
+        {
+            _debug("Error deleting the plugin ... \n");
+            return 1;
+        }
+        
+        unloadDynamicLibrary (info->_libraryPtr);
+        
+        if (unregisterPlugin (info) != 0)
+        {
+            _debug("Error unregistering the plugin ... \n");
+            return 1;
+        }
+
+        iter++;
+    }
+    return 0;
+}
+
+    bool 
+PluginManager::isPluginLoaded (const std::string &name)
+{
+    if(_loadedPlugins.empty())    return false;  
+
+    /* Use an iterator on the loaded plugins map */
+    pluginMap::iterator iter;
+    iter = _loadedPlugins.find (name);
+
+    /* Returns map::end if the specified key has not been found */
+    if(iter==_loadedPlugins.end())
+        return false;
+
+    /* Returns the plugin pointer */
+    return true;
+}
+
+
+   LibraryManager* 
+PluginManager::loadDynamicLibrary (const std::string& filename) 
+{
+    /* Load the library through the library manager */
+    return new LibraryManager (filename);
+}
+
+    int 
+PluginManager::unloadDynamicLibrary (LibraryManager *libraryPtr) 
+{
+    _debug("Unloading dynamic library ...\n");
+    /* Close it */
+    return libraryPtr->unloadLibrary ();
+}
+
+    int 
+PluginManager::instanciatePlugin (LibraryManager *libraryPtr, Plugin **plugin)
+{
+    createFunc *createPlugin;
+    LibraryManager::SymbolHandle symbol;
+
+    if (libraryPtr->resolveSymbol ("createPlugin", &symbol) != 0)
+        return 1;
+    createPlugin = (createFunc*)symbol;
+    *plugin = createPlugin();
+    return 0;
+}
+
+    int 
+PluginManager::deletePlugin (PluginInfo *plugin)
+{
+    destroyFunc *destroyPlugin;
+    LibraryManager::SymbolHandle symbol;
+
+    if (plugin->_libraryPtr->resolveSymbol ("destroyPlugin", &symbol) != 0)
+        return 1;
+    destroyPlugin = (destroyFunc*)symbol;
+    /* Call it */
+    destroyPlugin (plugin->_plugin);
+    return 0;
+}
+
+    int 
+PluginManager::registerPlugin (Plugin *plugin, LibraryManager *library)
+{
+    std::string key;
+    PluginInfo *p_info;
+
+    if( plugin==0 )
+        return 1;
+    
+    p_info = new PluginInfo();
+    /* Retrieve information from the plugin */
+    plugin->initFunc (&p_info);
+    key = p_info->_name;
+
+    //p_info->_plugin = plugin;
+    p_info->_libraryPtr = library;
+
+    /* Add the data in the loaded plugin map */
+    _loadedPlugins[ key ] = p_info;
+    return 0;
+}
+
+int 
+PluginManager::unregisterPlugin (PluginInfo *plugin)
+{
+    pluginMap::iterator iter;
+    std::string key;
+
+    key = plugin->_name;
+
+    if (!isPluginLoaded(key))
+        return 1;
+
+    iter = _loadedPlugins.find (key);
+    _loadedPlugins.erase (iter);
+
+    return 0;
+}
diff --git a/src/plug-in/pluginmanager.h b/src/plug-in/pluginmanager.h
new file mode 100644
index 0000000000000000000000000000000000000000..4b3a1869200ce7deaac770d661d360223adbc7b0
--- /dev/null
+++ b/src/plug-in/pluginmanager.h
@@ -0,0 +1,111 @@
+/*
+ *  Copyright (C) 2009 Savoir-Faire Linux inc.
+ *  Author: Emmanuel Milou <emmanuel.milou@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 PLUGIN_MANAGER_H
+#define PLUGIN_MANAGER_H
+
+/*
+ * @file pluginmanager.h
+ * @brief   Base class of the plugin manager
+ */
+
+#include "librarymanager.h"
+#include "global.h"
+
+#include <map> 
+#include <string> 
+#include <vector> 
+
+class Plugin;
+
+typedef struct PluginInfo {
+    std::string _name;
+    LibraryManager *_libraryPtr;
+    Plugin *_plugin;
+    int _major_version;
+    int _minor_version;
+} PluginInfo;
+
+#include "plugin.h"
+
+class PluginManager {
+    public:
+        /**
+         * Destructor
+         */
+        ~PluginManager();
+
+        /**
+         * Returns the unique instance of the plugin manager
+         */
+        static PluginManager* instance();
+
+        /**
+         * Load all the plugins found in a specific directory
+         * @param path  The absolute path to the directory
+         * @return int  The number of items loaded
+         */
+        int loadPlugins (const std::string &path = "");
+
+        int unloadPlugins (void);
+
+        int instanciatePlugin (LibraryManager* libraryPtr, Plugin** plugin);
+
+        /**
+         * Check if a plugin has been already loaded
+         * @param name  The name of the plugin looked for
+         * @return bool  The pointer on the plugin or NULL if not found
+         */
+        bool isPluginLoaded (const std::string &name);
+
+        int registerPlugin (Plugin *plugin, LibraryManager *library);
+        
+        int unregisterPlugin (PluginInfo *plugin);
+
+        int deletePlugin (PluginInfo *plugin); 
+
+        /**
+         * Load a unix dynamic/shared library 
+         * @param filename  The path to the dynamic/shared library
+         * @return LibraryManager*    A pointer on the library
+         */
+        LibraryManager* loadDynamicLibrary (const std::string &filename);
+
+        /**
+         * Unload a unix dynamic/shared library 
+         * @param LibraryManager*  The pointer on the loaded library
+         */
+        int unloadDynamicLibrary (LibraryManager* libraryPtr);
+
+    private:
+        /**
+         * Default constructor
+         */
+        PluginManager();
+
+        /* Map of plugins associated by their string name */
+        typedef std::map<std::string, PluginInfo*> pluginMap;
+        pluginMap _loadedPlugins;
+
+        /* The unique static instance */
+        static PluginManager* _instance;
+
+};
+
+#endif //PLUGIN_MANAGER_H
diff --git a/src/plug-in/test/Makefile.am b/src/plug-in/test/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..6809be2c0a185e16f72edcef1b57103fbcbea8f8
--- /dev/null
+++ b/src/plug-in/test/Makefile.am
@@ -0,0 +1,19 @@
+include $(top_srcdir)/globals.mak
+
+PLUGIN_LIB = libplugintest.so
+libplugintest_so_SOURCES = pluginTest.cpp
+libplugintest_so_CXXFLAGS = -fPIC -g -Wall
+libplugintest_so_LDFLAGS = --shared -lc
+INSTALL_PLUGIN_RULE = install-libplugintest_so
+
+noinst_PROGRAMS = libplugintest.so
+
+install-exec-local:  install-libplugintest_so
+uninstall-local:  uninstall-libplugintest_so
+
+install-libplugintest_so: libplugintest.so
+	mkdir -p $(sflplugindir)
+	$(INSTALL_PROGRAM) libplugintest.so $(sflplugindir)
+
+uninstall-libplugintest_so:
+	rm -f $(sflplugindir)/libplugintest.so
diff --git a/src/plug-in/test/pluginTest.cpp b/src/plug-in/test/pluginTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cbd1b1d760dd79797bdafead09b73fb69c1836a4
--- /dev/null
+++ b/src/plug-in/test/pluginTest.cpp
@@ -0,0 +1,49 @@
+/*
+ *  Copyright (C) 2009 Savoir-Faire Linux inc.
+ *  Author: Emmanuel Milou <emmanuel.milou@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 "../plugin.h"
+
+#define MAJOR_VERSION   1
+#define MINOR_VERSION   0
+
+class PluginTest : public Plugin {
+
+    public:
+        PluginTest( const std::string &name )
+            :Plugin( name ) {
+            }
+
+        virtual int initFunc (PluginInfo **info) {
+
+            (*info)->_plugin = this;
+            (*info)->_major_version = MAJOR_VERSION;
+            (*info)->_minor_version = MINOR_VERSION;
+            (*info)->_name = getPluginName();
+
+            return 0;
+        }
+};
+
+extern "C" Plugin* createPlugin (void){
+    return new PluginTest("mytest");
+}
+
+extern "C" void destroyPlugin (Plugin *p){
+    delete p;
+}
diff --git a/src/sipvoiplink.cpp b/src/sipvoiplink.cpp
index 527876d6aefc78099b2366c37cfc4cf4f09623f9..21e899d63647ed257d112373ac5c471fe600aae2 100644
--- a/src/sipvoiplink.cpp
+++ b/src/sipvoiplink.cpp
@@ -149,18 +149,18 @@ SIPVoIPLink* SIPVoIPLink::_instance = NULL;
     , _useStun(false)
     , _clients(0)
 {
+    _debug("SIPVoIPLink::~SIPVoIPLink(): sipvoiplink constructor called \n");    
+
     // to get random number for RANDOM_PORT
     srand (time(NULL));
 
-    /* Instanciate the C++ thread */
-    _evThread = new EventThread(this);
-
     /* Start pjsip initialization step */
     init();
 }
 
 SIPVoIPLink::~SIPVoIPLink()
 {
+    _debug("SIPVoIPLink::~SIPVoIPLink(): sipvoiplink destructor called \n");
     terminate();
 }
 
@@ -187,6 +187,10 @@ bool SIPVoIPLink::init()
 {
     if(initDone())
         return false;
+    
+    /* Instanciate the C++ thread */
+    _evThread = new EventThread(this);
+
     /* Initialize the pjsip library */
     pjsip_init();
     initDone(true);
@@ -197,7 +201,9 @@ bool SIPVoIPLink::init()
     void 
 SIPVoIPLink::terminate()
 {
-    delete _evThread; _evThread = NULL;
+    if (_evThread){
+        delete _evThread; _evThread = NULL;
+    }
 
     /* Clean shutdown of pjsip library */
     if( initDone() )
@@ -210,7 +216,6 @@ SIPVoIPLink::terminate()
     void
 SIPVoIPLink::terminateSIPCall()
 {
-
     ost::MutexLock m(_callMapMutex);
     CallMap::iterator iter = _callMap.begin();
     SIPCall *call;
@@ -225,6 +230,23 @@ SIPVoIPLink::terminateSIPCall()
     _callMap.clear();
 }
 
+    void
+SIPVoIPLink::terminateOneCall(const CallID& id)
+{
+    _debug("SIPVoIPLink::terminateOneCall(): function called \n");
+  
+    SIPCall *call;
+    
+    call = getSIPCall(id);
+    if (call) {
+    // terminate the sip call
+        _debug("SIPVoIPLink::terminateOneCall()::the call is deleted, should close recording file \n");
+        delete call; call = 0;
+    }
+}
+
+
+
     void
 SIPVoIPLink::getEvent()
 {
@@ -235,6 +257,7 @@ SIPVoIPLink::getEvent()
     // PJSIP polling
     pj_time_val timeout = {0, 10};
     pjsip_endpt_handle_events( _endpt, &timeout);
+    
 }
 
 int SIPVoIPLink::sendRegister( AccountID id )
@@ -379,7 +402,7 @@ SIPVoIPLink::sendUnregister( AccountID id )
     return true;
 }
 
-    Call* 
+Call* 
 SIPVoIPLink::newOutgoingCall(const CallID& id, const std::string& toUrl)
 {
     Account* account;
@@ -449,6 +472,7 @@ SIPVoIPLink::answer(const CallID& id)
             _debug("! SIP Failure: Unable to start sound when answering %s/%d\n", __FILE__, __LINE__);
         }
     }
+    terminateOneCall(call->getCallId());
     removeCall(call->getCallId());
     return false;
 }
@@ -483,7 +507,8 @@ SIPVoIPLink::hangup(const CallID& id)
         _debug("* SIP Info: Stopping AudioRTP for hangup\n");
         _audiortp->closeRtpSession();
     }
-
+ 
+    terminateOneCall(id);
     removeCall(id);
 
     return true;
@@ -497,6 +522,7 @@ SIPVoIPLink::cancel(const CallID& id)
 
     _debug("- SIP Action: Cancel call %s [cid: %3d]\n", id.data(), call->getCid()); 
 
+    terminateOneCall(id);
     removeCall(id);
 
     return true;
@@ -684,7 +710,7 @@ SIPVoIPLink::refuse (const CallID& id)
     pj_status_t status;
     pjsip_tx_data *tdata;
 
-
+    _debug("SIPVoIPLink::refuse() : teh call is refused \n");
     call = getSIPCall(id);
 
     if (call==0) { 
@@ -708,6 +734,8 @@ SIPVoIPLink::refuse (const CallID& id)
         return false;
 
     call->getInvSession()->mod_data[getModId()] = NULL;
+
+    terminateOneCall(id);
     return true;
 }
 
@@ -899,59 +927,66 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
         return true;
     }
 
-    void
-        SIPVoIPLink::SIPCallServerFailure(SIPCall *call) 
-        {
-            //if (!event->response) { return; }
-            //switch(event->response->status_code) {
-            //case SIP_SERVICE_UNAVAILABLE: // 500
-            //case SIP_BUSY_EVRYWHERE:     // 600
-            //case SIP_DECLINE:             // 603
-            //SIPCall* call = findSIPCallWithCid(event->cid);
-            if (call != 0) {
-                _debug("Server error!\n");
-                CallID id = call->getCallId();
-                Manager::instance().callFailure(id);
-                removeCall(id);
-            }
-            //break;
-            //}
-        }
+void
+SIPVoIPLink::SIPCallServerFailure(SIPCall *call) 
+{
+    //if (!event->response) { return; }
+    //switch(event->response->status_code) {
+    //case SIP_SERVICE_UNAVAILABLE: // 500
+    //case SIP_BUSY_EVRYWHERE:     // 600
+    //case SIP_DECLINE:             // 603
+    //SIPCall* call = findSIPCallWithCid(event->cid);
+    if (call != 0) {
+        _debug("Server error!\n");
+        CallID id = call->getCallId();
+        Manager::instance().callFailure(id);
+        terminateOneCall(id);
+        removeCall(id);
+    }
+    //break;
+    //}
+}
 
-    void
-        SIPVoIPLink::SIPCallClosed(SIPCall *call) 
-        {
-            // it was without did before
-            //SIPCall* call = findSIPCallWithCid(event->cid);
-            if (!call) { return; }
+void
+SIPVoIPLink::SIPCallClosed(SIPCall *call) 
+{
 
-            CallID id = call->getCallId();
-            //call->setDid(event->did);
-            if (Manager::instance().isCurrentCall(id)) {
-                call->setAudioStart(false);
-                _debug("* SIP Info: Stopping AudioRTP when closing\n");
-                _audiortp->closeRtpSession();
-            }
-            _debug("After close RTP\n");
-            Manager::instance().peerHungupCall(id);
-            removeCall(id);
-            _debug("After remove call ID\n");
-        }
+void
+SIPVoIPLink::SIPCallClosed(SIPCall *call) 
+{
+    // it was without did before
+    //SIPCall* call = findSIPCallWithCid(event->cid);
+    if (!call) { return; }
 
-    void
-        SIPVoIPLink::SIPCallReleased(SIPCall *call)
-        {
-            // do cleanup if exists
-            // only cid because did is always 0 in these case..
-            //SIPCall* call = findSIPCallWithCid(event->cid);
-            if (!call) { return; }
-
-            // if we are here.. something when wrong before...
-            _debug("SIP call release\n");
-            CallID id = call->getCallId();
-            Manager::instance().callFailure(id);
-            removeCall(id);
-        }
+    CallID id = call->getCallId();
+    //call->setDid(event->did);
+    if (Manager::instance().isCurrentCall(id)) {
+        call->setAudioStart(false);
+        _debug("* SIP Info: Stopping AudioRTP when closing\n");
+        _audiortp->closeRtpSession();
+    }
+    _debug("After close RTP\n");
+    Manager::instance().peerHungupCall(id);
+    terminateOneCall(id);
+    removeCall(id);
+    _debug("After remove call ID\n");
+}
+
+void
+SIPVoIPLink::SIPCallReleased(SIPCall *call)
+{
+    // do cleanup if exists
+    // only cid because did is always 0 in these case..
+    //SIPCall* call = findSIPCallWithCid(event->cid);
+    if (!call) { return; }
+
+    // if we are here.. something when wrong before...
+    _debug("SIP call release\n");
+    CallID id = call->getCallId();
+    Manager::instance().callFailure(id);
+    terminateOneCall(id);
+    removeCall(id);
+}
 
     void
         SIPVoIPLink::SIPCallAnswered(SIPCall *call, pjsip_rx_data *rdata)
@@ -1287,8 +1322,42 @@ std::string SIPVoIPLink::getSipTo(const std::string& to_url, std::string hostnam
         return returnValue;
     }
 
+    void SIPVoIPLink::busy_sleep(unsigned msec)
+    {
+#if defined(PJ_SYMBIAN) && PJ_SYMBIAN != 0
+    /* Ideally we shouldn't call pj_thread_sleep() and rather
+     * CActiveScheduler::WaitForAnyRequest() here, but that will
+     * drag in Symbian header and it doesn't look pretty.
+     */
+        pj_thread_sleep(msec);
+#else
+        pj_time_val timeout, now, tv;
+
+        pj_gettimeofday(&timeout);
+        timeout.msec += msec;
+        pj_time_val_normalize(&timeout);
+
+        tv.sec = 0;
+        tv.msec = 10;
+        pj_time_val_normalize(&tv);
+    
+        do {
+            pjsip_endpt_handle_events(_endpt, &tv);
+            pj_gettimeofday(&now);
+        } while (PJ_TIME_VAL_LT(now, timeout));
+#endif
+}    
+
     bool SIPVoIPLink::pjsip_shutdown( void )
     {
+        if (_endpt) {
+            _debug("UserAgent: Shutting down...\n");
+            busy_sleep(1000);
+        }
+
+        pj_thread_destroy( thread );
+        thread = NULL;
+
         /* Destroy endpoint. */
         if (_endpt) {
             pjsip_endpt_destroy(_endpt);
diff --git a/src/sipvoiplink.h b/src/sipvoiplink.h
index 03b12e6c38ba2d0dc8eae5dd73f3a9a9916f5720..4a87f111c9d25160e947e0009f5fcea14404cac5 100644
--- a/src/sipvoiplink.h
+++ b/src/sipvoiplink.h
@@ -191,6 +191,11 @@ class SIPVoIPLink : public VoIPLink
          * Terminate every call not hangup | brutal | Protected by mutex 
          */
         void terminateSIPCall(); 
+ 
+        /**
+         * Terminate only one call
+         */
+        void terminateOneCall(const CallID& id);
 
         /**
          * Build a sip address with the number that you want to call
@@ -284,6 +289,7 @@ class SIPVoIPLink : public VoIPLink
         /* The singleton instance */
         static SIPVoIPLink* _instance;
 
+        void busy_sleep(unsigned msec);
         int getModId();
 
         /** 
diff --git a/test/Makefile.am b/test/Makefile.am
index 14411aa140bbc3264308b27f0cd418287544821c..5c684888b422490c0e15316692bc4fcee3eceb78 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,6 +1,6 @@
 include ../globals.mak
 
-bin_PROGRAMS = configurationTester
+bin_PROGRAMS = configurationTester pluginmanagerTester audiorecorderTester
 
 OBJECT_FILES= \
 	../src/sflphoned-managerimpl.o \
@@ -15,7 +15,8 @@ OBJECT_FILES= \
 	../src/sflphoned-sipaccount.o \
 	../src/sflphoned-iaxaccount.o \
 	../src/sflphoned-eventthread.o \
-	../src/sflphoned-useragent.o \
+	../src/plug-in/pluginmanager.o \
+	../src/plug-in/audiorecorder/audiorecord.o \
 	../src/sflphoned-samplerateconverter.o
 
 configurationTester_SOURCES = \
@@ -23,6 +24,17 @@ configurationTester_SOURCES = \
 		configurationTest.h \
 		TestMain.cpp
 
+pluginmanagerTester_SOURCES = \
+		pluginmanagerTest.h \
+		pluginmanagerTest.cpp \
+		TestMain.cpp
+
+audiorecorderTester_SOURCES = \
+		audiorecorderTest.h \
+		audiorecorderTest.cpp \
+		TestMain.cpp
+
+
 configurationTester_LDADD = \
 		../src/libsflphone.la  \
 		$(SFLPHONE_LIBS) $(ZEROCONFLIB) $(LIB_DNSSD) $(IAX_LIBS) \
@@ -36,4 +48,32 @@ configurationTester_LDADD = \
 		@SAMPLERATE_LIBS@ \
 		$(PJSIP_LIBS) \
 		$(OBJECT_FILES)
-				
+	
+pluginmanagerTester_LDADD = \
+		../src/libsflphone.la  \
+		$(SFLPHONE_LIBS) $(ZEROCONFLIB) $(LIB_DNSSD) $(IAX_LIBS) \
+		@ALSA_LIBS@ \
+		@PULSEAUDIO_LIBS@ \
+		@CPPUNIT_LIBS@ \
+		@CCEXT2_LIBS@ \
+		@CCGNU2_LIBS@ \
+		@CCRTP_LIBS@ \
+		@DBUSCPP_LIBS@ \
+		@SAMPLERATE_LIBS@ \
+		$(PJSIP_LIBS) \
+		$(OBJECT_FILES)
+	
+audiorecorderTester_LDADD = \
+		../src/libsflphone.la  \
+		$(SFLPHONE_LIBS) $(ZEROCONFLIB) $(LIB_DNSSD) $(IAX_LIBS) \
+		@ALSA_LIBS@ \
+		@PULSEAUDIO_LIBS@ \
+		@CPPUNIT_LIBS@ \
+		@CCEXT2_LIBS@ \
+		@CCGNU2_LIBS@ \
+		@CCRTP_LIBS@ \
+		@DBUSCPP_LIBS@ \
+		@SAMPLERATE_LIBS@ \
+		$(PJSIP_LIBS) \
+		$(OBJECT_FILES)
+							
diff --git a/test/audiorecorderTest.cpp b/test/audiorecorderTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f766d4af1d082307a256fe08c6506806810d733a
--- /dev/null
+++ b/test/audiorecorderTest.cpp
@@ -0,0 +1,55 @@
+/*
+ *  Copyright (C) 2009 Savoir-Faire Linux inc.
+ *  Author: Emmanuel Milou <emmanuel.milou@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 "audiorecorderTest.h"
+
+using std::cout;
+using std::endl;
+
+void AudioRecorderTest::setUp(){
+    // Instanciate the object
+    _ar = new AudioRecord();
+}
+
+void AudioRecorderTest::testRecordData(){
+  
+  FILE_TYPE ft = FILE_WAV;
+  SOUND_FORMAT sf = INT16;
+  _ar->setSndSamplingRate(44100);
+  _ar->openFile("theWavFile.wav",ft,sf);
+
+  cout << "file opened!\n";
+
+  SFLDataFormat buf [2];
+  for (SFLDataFormat i = -32768; i < 32767; i++ ){
+    buf[0] = i;
+    buf[1] = i;
+    _ar->recData(buf,2);
+  }
+
+  _ar->closeFile();
+}
+
+void AudioRecorderTest::tearDown(){
+    // Delete the audio recorder module
+    delete _ar; _ar = NULL;
+}
diff --git a/test/audiorecorderTest.h b/test/audiorecorderTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..216b657079562007a1eb04955f390e3263ef1c87
--- /dev/null
+++ b/test/audiorecorderTest.h
@@ -0,0 +1,73 @@
+/*
+ *  Copyright (C) 2009 Savoir-Faire Linux inc.
+ *  Author: Emmanuel Milou <emmanuel.milou@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>
+
+// Application import
+#include "plug-in/pluginmanager.h"
+#include "plug-in/audiorecorder/audiorecord.h"
+
+/*
+ * @file audiorecorderTest.cpp  
+ * @brief       Regroups unitary tests related to the plugin manager.
+ */
+
+#ifndef _AUDIORECORDER_TEST_
+#define _AUDIORECORDER_TEST_
+
+class AudioRecorderTest : public CppUnit::TestCase {
+
+    /*
+     * Use cppunit library macros to add unit test the factory
+     */
+    CPPUNIT_TEST_SUITE( AudioRecorderTest );
+        CPPUNIT_TEST( testRecordData );
+    CPPUNIT_TEST_SUITE_END();
+
+    public:
+        AudioRecorderTest() : CppUnit::TestCase("Audio Recorder 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 testRecordData();
+        
+    private:
+        AudioRecord *_ar;
+};
+
+/* Register our test module */
+CPPUNIT_TEST_SUITE_REGISTRATION( AudioRecorderTest );
+
+#endif
diff --git a/test/pluginmanagerTest.cpp b/test/pluginmanagerTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..96994b6925219cfc565906873e8d6574fcc3c238
--- /dev/null
+++ b/test/pluginmanagerTest.cpp
@@ -0,0 +1,95 @@
+/*
+ *  Copyright (C) 2009 Savoir-Faire Linux inc.
+ *  Author: Emmanuel Milou <emmanuel.milou@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 <dlfcn.h>
+
+#include "pluginmanagerTest.h"
+
+using std::cout;
+using std::endl;
+
+#define PLUGIN_TEST_DIR  "/usr/lib/sflphone/plugins/"
+#define PLUGIN_TEST_DESC  "mytest"
+#define PLUGIN_TEST_NAME  "/usr/lib/sflphone/plugins/libplugintest.so"
+
+
+void PluginManagerTest::setUp(){
+    // Instanciate the plugin manager singleton
+    _pm = PluginManager::instance();
+    library = 0;
+    plugin = 0;
+}
+
+void PluginManagerTest::testLoadDynamicLibrary(){
+    CPPUNIT_ASSERT(_pm->loadDynamicLibrary(PLUGIN_TEST_NAME) != NULL);
+}
+
+void PluginManagerTest::testUnloadDynamicLibrary(){
+    library = _pm->loadDynamicLibrary(PLUGIN_TEST_NAME);
+    CPPUNIT_ASSERT(library != NULL);
+    CPPUNIT_ASSERT(_pm->unloadDynamicLibrary(library) == 0 );
+}
+
+void PluginManagerTest::testInstanciatePlugin(){
+    library = _pm->loadDynamicLibrary (PLUGIN_TEST_NAME);
+    CPPUNIT_ASSERT(library != NULL);
+    CPPUNIT_ASSERT (_pm->instanciatePlugin (library, &plugin) == 0);
+    CPPUNIT_ASSERT (plugin!=NULL);
+}
+
+void PluginManagerTest::testInitPlugin(){
+
+    library = _pm->loadDynamicLibrary (PLUGIN_TEST_NAME);
+    CPPUNIT_ASSERT(library != NULL);
+    CPPUNIT_ASSERT (_pm->instanciatePlugin (library, &plugin) == 0);
+    CPPUNIT_ASSERT (plugin!=NULL);
+    CPPUNIT_ASSERT (plugin->getPluginName() == PLUGIN_TEST_DESC);
+}
+
+void PluginManagerTest::testRegisterPlugin(){
+    library = _pm->loadDynamicLibrary (PLUGIN_TEST_NAME);
+    CPPUNIT_ASSERT(library != NULL);
+    CPPUNIT_ASSERT (_pm->instanciatePlugin (library, &plugin) == 0);
+    CPPUNIT_ASSERT (_pm->isPluginLoaded (PLUGIN_TEST_DESC) == false);
+    CPPUNIT_ASSERT (_pm->registerPlugin (plugin, library) == 0);
+    CPPUNIT_ASSERT (_pm->isPluginLoaded (PLUGIN_TEST_DESC) == true);
+}
+
+void PluginManagerTest::testLoadPlugins (){
+    CPPUNIT_ASSERT (_pm->loadPlugins (PLUGIN_TEST_DIR) == 0);
+    CPPUNIT_ASSERT (_pm->isPluginLoaded (PLUGIN_TEST_DESC) == true);
+}
+
+void PluginManagerTest::testUnloadPlugins (){
+    CPPUNIT_ASSERT (_pm->loadPlugins (PLUGIN_TEST_DIR) == 0);
+    CPPUNIT_ASSERT (_pm->isPluginLoaded (PLUGIN_TEST_DESC) == true);
+    CPPUNIT_ASSERT (_pm->unloadPlugins () == 0);
+    CPPUNIT_ASSERT (_pm->isPluginLoaded (PLUGIN_TEST_DESC) == false);
+}
+
+void PluginManagerTest::tearDown(){
+    // Delete the plugin manager object
+    delete _pm; _pm=0;
+    if(plugin)
+        delete plugin; plugin = 0;
+    if(library)
+        delete library; library = 0;
+}
diff --git a/test/pluginmanagerTest.h b/test/pluginmanagerTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..2e421958460445c3339ea1c2a97cef767258fabc
--- /dev/null
+++ b/test/pluginmanagerTest.h
@@ -0,0 +1,94 @@
+/*
+ *  Copyright (C) 2009 Savoir-Faire Linux inc.
+ *  Author: Emmanuel Milou <emmanuel.milou@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>
+
+// Application import
+#include "plug-in/pluginmanager.h"
+#include "plug-in/librarymanager.h"
+#include "plug-in/plugin.h"
+
+/*
+ * @file pluginManagerTest.cpp  
+ * @brief       Regroups unitary tests related to the plugin manager.
+ */
+
+#ifndef _PLUGINMANAGER_TEST_
+#define _PLUGINMANAGER_TEST_
+
+class PluginManagerTest : public CppUnit::TestCase {
+
+    /*
+     * Use cppunit library macros to add unit test the factory
+     */
+    CPPUNIT_TEST_SUITE( PluginManagerTest );
+        CPPUNIT_TEST( testLoadDynamicLibrary );
+        CPPUNIT_TEST( testUnloadDynamicLibrary );
+        CPPUNIT_TEST( testInstanciatePlugin );
+        CPPUNIT_TEST( testInitPlugin );
+        CPPUNIT_TEST( testRegisterPlugin );
+        CPPUNIT_TEST( testLoadPlugins );
+        CPPUNIT_TEST( testUnloadPlugins );
+    CPPUNIT_TEST_SUITE_END();
+
+    public:
+        PluginManagerTest() : CppUnit::TestCase("Plugin Manager 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 testLoadDynamicLibrary ();
+        
+        void testUnloadDynamicLibrary ();
+
+        void testInstanciatePlugin ();
+
+        void testInitPlugin ();
+
+        void testRegisterPlugin ();
+
+        void testLoadPlugins ();
+
+        void testUnloadPlugins ();
+
+    private:
+        PluginManager *_pm;
+        LibraryManager *library;
+        Plugin *plugin;
+};
+
+/* Register our test module */
+CPPUNIT_TEST_SUITE_REGISTRATION( PluginManagerTest );
+
+#endif