diff --git a/daemon/tools/dringctl/__init__.py b/daemon/tools/dringctl/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..991f029774f57b1a8a354ae702efe5c7e5855e03
--- /dev/null
+++ b/daemon/tools/dringctl/__init__.py
@@ -0,0 +1,29 @@
+#
+# Copyright (C) 2015 Savoir-Faire Linux Inc.
+# Author: Guillaume Roguez <guillaume.roguez@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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+#
+# Additional permission under GNU GPL version 3 section 7:
+#
+# If you modify this program, or any covered work, by linking or
+# combining it with the OpenSSL project's OpenSSL library (or a
+# modified version of that library), containing parts covered by the
+# terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
+# grants you additional permission to convey the resulting work.
+# Corresponding Source for a non-source form of such a combination
+# shall include the source code for the parts of OpenSSL used as well
+# as that of the covered work.
+#
diff --git a/daemon/tools/dringctl/controler.py b/daemon/tools/dringctl/controler.py
new file mode 100644
index 0000000000000000000000000000000000000000..9d8f08d4781adec8affea14b2071141297e996ab
--- /dev/null
+++ b/daemon/tools/dringctl/controler.py
@@ -0,0 +1,592 @@
+#
+# Copyright (C) 2015 Savoir-Faire Linux Inc.
+# Author: Guillaume Roguez <guillaume.roguez@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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+#
+# Additional permission under GNU GPL version 3 section 7:
+#
+# If you modify this program, or any covered work, by linking or
+# combining it with the OpenSSL project's OpenSSL library (or a
+# modified version of that library), containing parts covered by the
+# terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
+# grants you additional permission to convey the resulting work.
+# Corresponding Source for a non-source form of such a combination
+# shall include the source code for the parts of OpenSSL used as well
+# as that of the covered work.
+#
+
+"""DRing controling class through DBUS"""
+
+import os
+import random
+import time
+import hashlib
+
+from threading import Thread
+from functools import partial
+
+from gi.repository import GObject
+
+from errors import *
+
+try:
+    import dbus
+    from dbus.mainloop.glib import DBusGMainLoop
+except ImportError as e:
+    raise DRingCtrlError("No python3-dbus module found")
+
+
+DBUS_DEAMON_OBJECT = 'cx.ring.Ring'
+DBUS_DEAMON_PATH = '/cx/ring/Ring'
+
+
+class DRingCtrl(Thread):
+    def __init__(self, name):
+        super().__init__()
+
+        self.activeCalls = {}  # list of active calls (known by the client)
+        self.activeConferences = {}  # list of active conferences
+        self.account = None  # current active account
+        self.name = name # client name
+
+        self.currentCallId = ""
+        self.currentConfId = ""
+
+        self.isStop = False
+
+        # Glib MainLoop for processing callbacks
+        self.loop = GObject.MainLoop()
+
+        GObject.threads_init()
+
+        # client registered to sflphoned ?
+        self.registered = False
+        self.register()
+
+    def __del__(self):
+        if self.registered:
+            self.unregister()
+        self.loop.quit()
+
+    def stopThread(self):
+        self.isStop = True
+
+    def register(self):
+        if self.registered:
+            return
+
+        try:
+            # register the main loop for d-bus events
+            DBusGMainLoop(set_as_default=True)
+            bus = dbus.SessionBus()
+
+        except dbus.DBusException as e:
+            raise DRingCtrlDBusError("Unable to connect DBUS session bus")
+
+        if not bus.name_has_owner(DBUS_DEAMON_OBJECT) :
+            raise DRingCtrlDBusError(("Unable to find %s in DBUS." % DBUS_DEAMON_OBJECT)
+                                     + " Check if dring is running")
+
+        try:
+            proxy_instance = bus.get_object(DBUS_DEAMON_OBJECT,
+                DBUS_DEAMON_PATH+'/Instance', introspect=False)
+            proxy_callmgr = bus.get_object(DBUS_DEAMON_OBJECT,
+                DBUS_DEAMON_PATH+'/CallManager', introspect=False)
+            proxy_confmgr = bus.get_object(DBUS_DEAMON_OBJECT,
+                DBUS_DEAMON_PATH+'/ConfigurationManager', introspect=False)
+
+            self.instance = dbus.Interface(proxy_instance,
+                DBUS_DEAMON_OBJECT+'.Instance')
+            self.callmanager = dbus.Interface(proxy_callmgr,
+                DBUS_DEAMON_OBJECT+'.CallManager')
+            self.configurationmanager = dbus.Interface(proxy_confmgr,
+                DBUS_DEAMON_OBJECT+'.ConfigurationManager')
+
+        except dbus.DBusException as e:
+            raise DRingCtrlDBusError("Unable to bind to dring DBus API")
+
+        try:
+            self.instance.Register(os.getpid(), self.name)
+            self.registered = True
+
+        except:
+            raise DRingCtrlDeamonError("Client registration failed")
+
+        try:
+            proxy_callmgr.connect_to_signal('incomingCall', self.onIncomingCall)
+            proxy_callmgr.connect_to_signal('callStateChanged', self.onCallStateChanged)
+            proxy_callmgr.connect_to_signal('conferenceCreated', self.onConferenceCreated)
+
+        except dbus.DBusException as e:
+            raise DRingCtrlDBusError("Unable to connect to dring DBus signals")
+
+
+    def unregister(self):
+        if not self.registered:
+            return
+
+        try:
+            self.instance.Unregister(os.getpid())
+            self.registered = False
+
+        except:
+            raise DRingCtrlDeamonError("Client unregistration failed")
+
+
+    def isRegistered(self):
+        return self.registered
+
+    #
+    # Signal handling
+    #
+
+    def onIncomingCall_cb(self):
+        pass
+
+    def onCallHangup_cb(self, callId):
+        pass
+
+    def onCallRinging_cb(self):
+        pass
+
+    def onCallHold_cb(self):
+        pass
+
+    def onCallCurrent_cb(self):
+        pass
+
+    def onCallBusy_cb(self):
+        pass
+
+    def onCallFailure_cb(self):
+        pass
+
+    def onIncomingCall(self, account, callid, to):
+        """ On incoming call event, add the call to the list of active calls """
+
+        self.activeCalls[callid] = {'Account': account,
+                                         'To': to,
+                                      'State': ''}
+        self.currentCallId = callid
+        self.onIncomingCall_cb()
+
+
+    def onCallHangUp(self, callid):
+        """ Remove callid from call list """
+
+        self.onCallHangup_cb(callid)
+        self.currentCallId = ""
+        del self.activeCalls[callid]
+
+
+    def onCallRinging(self, callid, state):
+        """ Update state for this call to Ringing """
+
+        self.activeCalls[callid]['State'] = state
+        self.onCallRinging_cb()
+
+
+    def onCallHold(self, callid, state):
+        """ Update state for this call to Hold """
+
+        self.activeCalls[callid]['State'] = state
+        self.onCallHold_cb()
+
+
+    def onCallCurrent(self, callid, state):
+        """ Update state for this call to current """
+
+        self.activeCalls[callid]['State'] = state
+        self.onCallCurrent_cb()
+
+
+    def onCallBusy(self, callid, state):
+        """ Update state for this call to busy """
+
+        self.activeCalls[callid]['State'] = state
+        self.onCallBusy_cb()
+
+
+    def onCallFailure(self, callid, state):
+        """ Handle call failure """
+
+        self.onCallFailure_cb()
+        del self.activeCalls[callid]
+
+
+    def onCallStateChanged(self, callid, state):
+        """ On call state changed event, set the values for new calls,
+        or delete the call from the list of active calls
+        """
+
+        print(("On call state changed " + callid + " " + state))
+
+        if callid not in self.activeCalls:
+            print("This call didn't exist!: " + callid + ". Adding it to the list.")
+            callDetails = self.getCallDetails(callid)
+            self.activeCalls[callid] = {'Account': callDetails['ACCOUNTID'],
+                                             'To': callDetails['PEER_NUMBER'],
+                                          'State': state }
+
+
+        self.currentCallId = callid
+
+        if state == "HUNGUP":
+            self.onCallHangUp(callid)
+        elif state == "RINGING":
+            self.onCallRinging(callid, state)
+        elif state == "CURRENT":
+            self.onCallCurrent(callid, state)
+        elif state == "HOLD":
+            self.onCallHold(callid, state)
+        elif state == "BUSY":
+            self.onCallBusy(callid, state)
+        elif state == "FAILURE":
+            self.onCallFailure(callid, state)
+        else:
+            print("unknown state")
+
+    def onConferenceCreated_cb(self):
+        pass
+
+    def onConferenceCreated(self, confId):
+        self.currentConfId = confId
+        self.onConferenceCreated_cb()
+
+    #
+    # Account management
+    #
+
+    def _valid_account(self, account):
+        account = account or self.account
+        if account is None:
+            raise DRingCtrlError("No provided or current account!")
+        return account
+
+    def isAccountExists(self, account):
+        """ Checks if the account exists"""
+
+        return account in self.getAllAccounts()
+
+    def isAccountEnable(self, account=None):
+        """Return True if the account is enabled. If no account is provided, active account is used"""
+
+        return self.getAccountDetails(self._valid_account(account))['Account.enable'] == "true"
+
+    def isAccountRegistered(self, account=None):
+        """Return True if the account is registered. If no account is provided, active account is used"""
+
+        return self.getAccountDetails(self._valid_account(account))['Account.registrationStatus'] in ('READY', 'REGISTERED')
+
+    def isAccountOfType(self, account_type, account=None):
+        """Return True if the account type is the given one. If no account is provided, active account is used"""
+
+        return self.getAccountDetails(self._valid_account(account))['Account.type'] == account_type
+
+    def getAllAccounts(self, account_type=None):
+        """Return a list with all accounts"""
+
+        acclist =  map(str, self.configurationmanager.getAccountList())
+        if account_type:
+            acclist = filter(partial(self.isAccountOfType, account_type), acclist)
+        return list(acclist)
+
+    def getAllEnabledAccounts(self):
+        """Return a list with all enabled-only accounts"""
+
+        return [x for x in self.getAllAccounts() if self.isAccountEnable(x)]
+
+    def getAllRegisteredAccounts(self):
+        """Return a list with all registered-only accounts"""
+
+        return [x for x in self.getAllAccounts() if self.isAccountRegistered(x)]
+
+    def getAccountDetails(self, account=None):
+        """Return a list of string. If no account is provided, active account is used"""
+
+        account = self._valid_account(account)
+        if self.isAccountExists(account):
+            return self.configurationmanager.getAccountDetails(account)
+        return []
+
+    def setActiveCodecList(self, account=None, codec_list=''):
+        """Activate given codecs on an account. If no account is provided, active account is used"""
+
+        account = self._valid_account(account)
+        if self.isAccountExists(account):
+            codec_list = [dbus.UInt32(x) for x in codec_list.split(',')]
+            self.configurationmanager.setActiveCodecList(account, codec_list)
+
+    def addAccount(self, details=None):
+        """Add a new account account
+
+        Add a new account to the SFLphone-daemon. Default parameters are \
+        used for missing account configuration field.
+
+        Required parameters are type, alias, hostname, username and password
+
+        input details
+        """
+
+        if details is None:
+            raise DRingCtrlAccountError("Must specifies type, alias, hostname, \
+                                  username and password in \
+                                  order to create a new account")
+
+        return self.configurationmanager.addAccount(details)
+
+    def removeAccount(self, accountID=None):
+        """Remove an account from internal list"""
+
+        if accountID is None:
+            raise DRingCtrlAccountError("Account ID must be specified")
+
+        self.configurationmanager.removeAccount(accountID)
+
+    def setAccountByAlias(self, alias):
+        """Define as active the first account who match with the alias"""
+
+        for testedaccount in self.getAllAccounts():
+            details = self.getAccountDetails(testedaccount)
+            if (details['Account.enable'] == 'true' and
+                details['Account.alias'] == alias):
+                self.account = testedaccount
+                return
+        raise DRingCtrlAccountError("No enabled account matched with alias")
+
+    def getAccountByAlias(self, alias):
+        """Get account name having its alias"""
+
+        for account in self.getAllAccounts():
+            details = self.getAccountDetails(account)
+            if details['Account.alias'] == alias:
+                return account
+
+        raise DRingCtrlAccountError("No account matched with alias")
+
+    def setAccount(self, account):
+        """Define the active account
+
+        The active account will be used when sending a new call
+        """
+
+        if account in self.getAllAccounts():
+            self.account = account
+        else:
+            print(account)
+            raise DRingCtrlAccountError("Not a valid account")
+
+    def setFirstRegisteredAccount(self):
+        """Find the first enabled account and define it as active"""
+
+        rAccounts = self.getAllRegisteredAccounts()
+        if 0 == len(rAccounts):
+            raise DRingCtrlAccountError("No registered account !")
+        self.account = rAccounts[0]
+
+    def setFirstActiveAccount(self):
+        """Find the first enabled account and define it as active"""
+
+        aAccounts = self.getAllEnabledAccounts()
+        if 0 == len(aAccounts):
+            raise DRingCtrlAccountError("No active account !")
+        self.account = aAccounts[0]
+
+    def getAccount(self):
+        """Return the active account"""
+
+        return self.account
+
+    def setAccountEnable(self, account=None, enable=False):
+        """Set account enabled"""
+
+        account = self._valid_account(account)
+        if enable == True:
+            details = self.getAccountDetails(account)
+            details['Account.enable'] = "true"
+            self.configurationmanager.setAccountDetails(account, details)
+        else:
+            details = self.getAccountDetails(account)
+            details['Account.enable'] = "false"
+            self.configurationmanager.setAccountDetails(account, details)
+
+    def setAccountRegistered(self, account=None, register=False):
+        """ Tries to register the account"""
+
+        account = self._valid_account(account)
+        self.configurationmanager.sendRegister(account, register)
+
+    #
+    # Codec manager
+    #
+
+    def getAllCodecs(self):
+        """ Return all codecs"""
+
+        return [int(x) for x in self.configurationmanager.getCodecList()]
+
+    #
+    # Call management
+    #
+
+    def getCallDetails(self, callid):
+        """Return informations on this call if exists"""
+
+        return self.callmanager.getCallDetails(callid)
+
+    def printClientCallList(self):
+        print("Client active call list:")
+        print("------------------------")
+        for call in self.activeCalls:
+            print("\t" + call)
+
+    def Call(self, dest):
+        """Start a call and return a CallID
+
+        Use the current account previously set using setAccount().
+        If no account specified, first registered one in account list is used.
+
+        return callID Newly generated callidentifier for this call
+        """
+
+        if dest is None or dest == "":
+            raise SflPhoneError("Invalid call destination")
+
+        # Set the account to be used for this call
+        if not self.account:
+            self.setFirstRegisteredAccount()
+
+        if self.account is not "IP2IP" and not self.isAccountRegistered():
+            raise DRingCtrlAccountError("Can't place a call without a registered account")
+
+        # Send the request to the CallManager
+        callid = self.callmanager.placeCall(self.account, dest)
+        if callid:
+            # Add the call to the list of active calls and set status to SENT
+            self.activeCalls[callid] = {'Account': self.account, 'To': dest, 'State': 'SENT' }
+
+        return callid
+
+
+    def HangUp(self, callid):
+        """End a call identified by a CallID"""
+
+        if not self.account:
+            self.setFirstRegisteredAccount()
+
+        if callid is None or callid == "":
+            pass # just to see
+
+        self.callmanager.hangUp(callid)
+
+
+    def Transfer(self, callid, to):
+        """Transfert a call identified by a CallID"""
+
+        if callid is None or callid == "":
+            raise DRingCtrlError("Invalid callID")
+
+        self.callmanager.transfert(callid, to)
+
+
+    def Refuse(self, callid):
+        """Refuse an incoming call identified by a CallID"""
+
+        print("Refuse call " + callid)
+
+        if callid is None or callid == "":
+            raise DRingCtrlError("Invalid callID")
+
+        self.callmanager.refuse(callid)
+
+
+    def Accept(self, callid):
+        """Accept an incoming call identified by a CallID"""
+
+        print("Accept call " + callid)
+        if not self.account:
+            self.setFirstRegisteredAccount()
+
+        if not self.isAccountRegistered():
+            raise DRingCtrlAccountError("Can't accept a call without a registered account")
+
+        if callid is None or callid == "":
+            raise DRingCtrlError("Invalid callID")
+
+        self.callmanager.accept(callid)
+
+
+    def Hold(self, callid):
+        """Hold a call identified by a CallID"""
+
+        if callid is None or callid == "":
+            raise DRingCtrlError("Invalid callID")
+
+        self.callmanager.hold(callid)
+
+
+    def UnHold(self, callid):
+        """Unhold an incoming call identified by a CallID"""
+
+        if callid is None or callid == "":
+            raise DRingCtrlError("Invalid callID")
+
+        self.callmanager.unhold(callid)
+
+
+    def Dtmf(self, key):
+        """Send a DTMF"""
+
+        self.callmanager.playDTMF(key)
+
+
+    def _GenerateCallID(self):
+        """Generate Call ID"""
+
+        m = hashlib.md5()
+        t = int( time.time() * 1000 )
+        r = int( random.random()*100000000000000000 )
+        m.update(str(t) + str(r))
+        callid = m.hexdigest()
+        return callid
+
+
+    def createConference(self, call1Id, call2Id):
+        """ Create a conference given the two call ids """
+
+        self.callmanager.joinParticipant(call1Id, call2Id)
+
+
+    def hangupConference(self, confId):
+        """ Hang up each call for this conference """
+
+        self.callmanager.hangUpConference(confId)
+
+
+    def run(self):
+        """Processing method for this thread"""
+
+        context = self.loop.get_context()
+
+        while True:
+            context.iteration(True)
+
+            if self.isStop:
+                print("++++++++++++++++++++++++++++++++++++++++")
+                print("++++++++++++++++++++++++++++++++++++++++")
+                print("++++++++++++++++++++++++++++++++++++++++")
+                print("++++++++++++++++++++++++++++++++++++++++")
+                return
diff --git a/tools/pysflphone/sflphoned.functest.yml b/daemon/tools/dringctl/dring.functest.yml
similarity index 100%
rename from tools/pysflphone/sflphoned.functest.yml
rename to daemon/tools/dringctl/dring.functest.yml
diff --git a/daemon/tools/dringctl/dringctl.py b/daemon/tools/dringctl/dringctl.py
new file mode 100755
index 0000000000000000000000000000000000000000..2413ea89949947980f44be2851f941e64ec22be5
--- /dev/null
+++ b/daemon/tools/dringctl/dringctl.py
@@ -0,0 +1,259 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2015 Savoir-Faire Linux Inc.
+# Author: Guillaume Roguez <guillaume.roguez@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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+#
+# Additional permission under GNU GPL version 3 section 7:
+#
+# If you modify this program, or any covered work, by linking or
+# combining it with the OpenSSL project's OpenSSL library (or a
+# modified version of that library), containing parts covered by the
+# terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
+# grants you additional permission to convey the resulting work.
+# Corresponding Source for a non-source form of such a combination
+# shall include the source code for the parts of OpenSSL used as well
+# as that of the covered work.
+#
+
+import sys
+import os
+import random
+import time
+import argparse
+
+from gi.repository import GObject
+
+from errors import *
+from controler import DRingCtrl
+
+def printAccountDetails(account):
+    details = ctrl.getAccountDetails(account)
+    print(account)
+    for k in sorted(details.keys()):
+        print("  %s: %s" % (k, details[k]))
+    print()
+
+if __name__ == "__main__":
+    parser = argparse.ArgumentParser()
+    parser.add_argument('--gaa', help='Get all accounts (of optionaly given type)',
+                        nargs='?', metavar='<type>', type=str, default=argparse.SUPPRESS)
+    parser.add_argument('--gara', help='Get all registered accounts', action='store_true')
+    parser.add_argument('--gaea', help='Get all enabled accounts', action='store_true')
+    parser.add_argument('--gaad', help='Get all account details', action='store_true')
+
+    parser.add_argument('--gac', help='Get all codecs', action='store_true')
+
+    parser.add_argument('--gad', help='Get account details',
+                        metavar='<account>', type=str)
+
+    group = parser.add_mutually_exclusive_group()
+    group.add_argument('--enable', help='Enable the account',
+                       metavar='<account>', type=str)
+    group.add_argument('--disable', help='Disable the account',
+                       metavar='<account>', type=str)
+
+    group = parser.add_mutually_exclusive_group()
+    group.add_argument('--register', help='Register the account',
+                       metavar='<account>', type=str)
+    group.add_argument('--unregister', help='Unregister the account',
+                       metavar='<account>', type=str)
+
+    parser.add_argument('--sac', help='Set active account',
+                        metavar='<account>', type=str)
+
+    parser.add_argument('--sacl', help='Set active codecs for active account',
+                        metavar='<codec list>', type=str)
+
+    #parser.add_argument('--gcc', help='Get current callid', action='store_true')
+    parser.add_argument('--gcl', help='Get call list', action='store_true')
+
+    group = parser.add_mutually_exclusive_group()
+    group.add_argument('--call', help='Call to number', metavar='<destination>')
+    #group.add_argument('--transfer', help='Transfer active call', metavar='<destination>')
+
+    group = parser.add_mutually_exclusive_group()
+    group.add_argument('--accept', help='Accept the call', metavar='<account>')
+    group.add_argument('--hangup', help='Hangup the call', metavar='<account>')
+    group.add_argument('--refuse', help='Refuse the call', metavar='<account>')
+
+    group = parser.add_mutually_exclusive_group()
+    group.add_argument('--hold', help='Hold the call', metavar='<call>')
+    group.add_argument('--unhold', help='Unhold the call', metavar='<call>')
+
+    parser.add_argument('--dtmf', help='Send DTMF', metavar='<key>')
+
+    args = parser.parse_args()
+
+    ctrl = DRingCtrl(sys.argv[0])
+
+    if len(sys.argv) == 1:
+        ctrl.run()
+        sys.exit(0)
+
+    if args.gac:
+        print(ctrl.getAllCodecs())
+
+    if hasattr(args, 'gaa'):
+        for account in ctrl.getAllAccounts(args.gaa):
+            print(account)
+
+    if args.gara:
+        for account in ctrl.getAllRegisteredAccounts():
+            print(account)
+
+    if args.gaea:
+        for account in ctrl.getAllEnabledAccounts():
+            print(account)
+
+    if args.gaad:
+        for account in ctrl.getAllAccounts():
+            printAccountDetails(account)
+
+    if args.sac:
+        ctrl.setAccount(args.sac)
+
+    if args.gad:
+        printAccountDetails(args.gad)
+
+    if args.sacl:
+        ctrl.setActiveCodecList(codec_list=args.sacl)
+
+    if args.enable:
+        ctrl.setAccountEnable(args.enable, True)
+
+    if args.disable:
+        ctrl.setAccountEnable(args.enable, False)
+
+    if args.register:
+        ctrl.setAccountRegistered(args.register, True)
+
+    if args.unregister:
+        ctrl.setAccountRegistered(args.unregister, False)
+
+    if args.gcl:
+        for call in ctrl.getAllCalls():
+            print(call)
+
+    if args.call:
+        ctrl.Call(args.call)
+
+    if args.accept:
+        ctrl.Accept(args.accept)
+
+    if args.refuse:
+        ctrl.Refuse(args.refuse)
+
+    if args.hangup:
+        ctrl.HangUp(args.hangup)
+
+    if args.hold:
+        ctrl.Hold(args.hold)
+
+    if args.unhold:
+        ctrl.UnHold(args.unhold)
+
+    if args.dtmf:
+        sflphone.Dtmf(dtmf)
+
+"""
+
+		# Get call details
+		elif opt == "--gcd":
+			if arg == "current": arg = sflphone.getCurrentCallID()
+
+			details = sflphone.getCallDetails(arg)
+			if details:
+				print "Call: " + arg
+				print "Account: " + details['ACCOUNTID']
+				print "Peer: " + details['PEER_NAME'] + "<" + details['PEER_NUMBER'] + ">"
+
+		elif opt == "--sac":
+			if arg is "":
+			    print "Must specifies the accout to be set"
+			else:
+                            sflphone.setAccount(arg)
+
+		# Unhold a call
+		elif opt == "--unhold":
+			if arg == "current": arg = sflphone.getCurrentCallID()
+			sflphone.UnHold(arg)
+
+		# Transfer the current call
+		elif opt == "--transfer":
+			call = sflphone.callmanager.getCurrentCallID()
+			sflphone.Transfert(call, arg)
+
+		# Send DTMF
+		elif opt == "--dtmf":
+			sflphone.Dtmf(arg)
+
+
+		#
+		# account options
+		#
+
+		# Register an account
+		elif opt == "--register":
+			if not sflphone.checkAccountExists(arg):
+				print "Account " + arg + ": no such account."
+
+			elif arg  in sflphone.getAllRegisteredAccounts():
+				print "Account " + arg + ": already registered."
+
+			else:
+				sflphone.setAccountRegistered(arg, True)
+				print arg + ": Sent register request."
+
+		# Unregister an account
+		elif opt == "--unregister":
+			if not sflphone.checkAccountExists(arg):
+				print "Account " + arg + ": no such account."
+
+			elif arg not in sflphone.getAllRegisteredAccounts():
+				print "Account " + arg + ": is not registered."
+
+			else:
+				sflphone.setAccountRegistered(arg, False)
+				print arg + ": Sent unregister request."
+
+		# Enable an account
+		elif opt == "--enable":
+			if not sflphone.checkAccountExists(arg):
+				print "Account " + arg + ": no such account."
+
+			elif sflphone.isAccountEnable(arg):
+				print "Account " + arg + ": already enabled."
+
+			else:
+				sflphone.setAccountEnable(arg, True)
+				print arg + ": Account enabled."
+
+		# Disable an account
+		elif opt == "--disable":
+			if not sflphone.checkAccountExists(arg):
+				print "Account " + arg + ": no such account."
+
+			elif not sflphone.isAccountEnable(arg):
+				print "Account " + arg + ": already disabled."
+
+			else:
+				sflphone.setAccountRegistered(arg, False)
+				sflphone.setAccountEnable(arg, False)
+				print arg + ": Account disabled."
+
+
+"""
diff --git a/tools/pysflphone/pysflphone_testdbus.py b/daemon/tools/dringctl/dringctl_testdbus.py
similarity index 99%
rename from tools/pysflphone/pysflphone_testdbus.py
rename to daemon/tools/dringctl/dringctl_testdbus.py
index 05b341a569b709be600c56b8f65a276f92d48462..fc2bc668350201978b2dcf3d074036611ee924ff 100644
--- a/tools/pysflphone/pysflphone_testdbus.py
+++ b/daemon/tools/dringctl/dringctl_testdbus.py
@@ -74,7 +74,7 @@ class SflPhoneTests():
 	HOSTNAME = "hostname"
 	USERNAME = "username"
 	PASSWORD = "password"
-	
+
         accDetails = {CONFIG_ACCOUNT_TYPE:"SIP", CONFIG_ACCOUNT_ALIAS:"testsuiteaccount",
                       HOSTNAME:"192.168.50.79", USERNAME:"31416",
                       PASSWORD:"1234"}
diff --git a/daemon/tools/dringctl/errors.py b/daemon/tools/dringctl/errors.py
new file mode 100644
index 0000000000000000000000000000000000000000..685ef11f645ec0332f3eeddd26e7dd8ddf49be9f
--- /dev/null
+++ b/daemon/tools/dringctl/errors.py
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2015 Savoir-Faire Linux Inc.
+# Author: Guillaume Roguez <guillaume.roguez@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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+#
+# Additional permission under GNU GPL version 3 section 7:
+#
+# If you modify this program, or any covered work, by linking or
+# combining it with the OpenSSL project's OpenSSL library (or a
+# modified version of that library), containing parts covered by the
+# terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
+# grants you additional permission to convey the resulting work.
+# Corresponding Source for a non-source form of such a combination
+# shall include the source code for the parts of OpenSSL used as well
+# as that of the covered work.
+#
+
+"""Internal exceptions"""
+
+__all__ = ['DRingCtrlError',
+           'DRingCtrlDBusError',
+           'DRingCtrlDeamonError']
+
+class DRingCtrlError(Exception):
+    """Base class for all our exceptions."""
+
+    def __init__(self, help=None):
+        self.help = str(help)
+
+    def __str__(self):
+        return self.help
+
+class DRingCtrlDBusError(DRingCtrlError):
+    """General error for dbus communication"""
+
+class DRingCtrlDeamonError(DRingCtrlError):
+    """General error for daemon communication"""
+
+class DRingCtrlAccountError(DRingCtrlError):
+    """General error for account handling"""
diff --git a/tools/pysflphone/sippwrap.py b/daemon/tools/dringctl/sippwrap.py
similarity index 100%
rename from tools/pysflphone/sippwrap.py
rename to daemon/tools/dringctl/sippwrap.py
diff --git a/tools/pysflphone/test_sflphone_dbus_interface.py b/daemon/tools/dringctl/test_dring_dbus_interface.py
similarity index 100%
rename from tools/pysflphone/test_sflphone_dbus_interface.py
rename to daemon/tools/dringctl/test_dring_dbus_interface.py
diff --git a/tools/pysflphone/Errors.py b/tools/pysflphone/Errors.py
deleted file mode 100644
index 2a1e6b38693f22073d4073edb11d9656ecaa06af..0000000000000000000000000000000000000000
--- a/tools/pysflphone/Errors.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright (C) 2008 by the Free Software Foundation, Inc.
-#
-# 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 2
-# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-"""Our own Errors exceptions"""
-
-class SflPhoneError(Exception):
-    """Base class for all SflPhone exceptions."""
-    def __init__(self, help=None):
-        self.help=help
-    def __str__(self):
-        return repr(self.help)
-
-
-class SPdbusError(SflPhoneError):
-    """General error for dbus communication"""
-
-class SPdaemonError(SflPhoneError):
-    """General error for daemon communication"""
-
-class SPserverError(SflPhoneError):
-    """General error for server communication"""
-
-class SPconfigurationError(SflPhoneError):
-    """General error for configuration"""
-
-class SPaccountError(SflPhoneError):
-    """General error for account handling"""
diff --git a/tools/pysflphone/__init__.py b/tools/pysflphone/__init__.py
deleted file mode 100644
index 94ffb667d0fe679dc40c0db3b26216748a8ea362..0000000000000000000000000000000000000000
--- a/tools/pysflphone/__init__.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright (C) 2008 by the Free Software Foundation, Inc.
-#
-# 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 2
-# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-
diff --git a/tools/pysflphone/pysflphone.py b/tools/pysflphone/pysflphone.py
deleted file mode 100644
index b4a43ef50c293c7a55bed5211e6e7947b82732b7..0000000000000000000000000000000000000000
--- a/tools/pysflphone/pysflphone.py
+++ /dev/null
@@ -1,279 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2009 by the Free Software Foundation, Inc.
-#
-# 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 2
-# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-
-
-import sys
-import os
-import random
-from traceback import print_exc
-
-import gobject
-from gobject import GObject
-
-import getopt
-
-import time
-
-from threading import Thread
-
-from Errors import *
-
-try:
-	import dbus
-	from dbus.mainloop.glib import DBusGMainLoop
-except ImportError, e:
-	raise SflPhoneError("No python-dbus module found")
-
-
-from sflphonectrl import SflPhoneCtrl
-
-#
-# Main application
-#
-
-
-def printHelp():
-	"""Print help"""
-	print sys.argv[0] + " usage:\n\
-\n\
-	--help                             Print this help.\n\
-\n\
-	--gaa                              Get all accounts.\n\
-	--gara                             Get all registered accounts.  \n\
-	--gaea                             Get all enabled accounts.     \n\
-	--gasa                             Get all SIP accounts.         \n\
-	--gaia                             Get all IAX accounts.         \n\
-	--gcc                              Get current callid.           \n\
-	--gacl                             Get active codec list.        \n\
-        --sac                              Set accout for next call      \n\
-                                                                         \n\
-	--gad        <account>             Get account details .         \n\
-	--enable     <account>             Enable the account.           \n\
-	--disable    <account>             Disable the account.          \n\
-	--register   <account>             Register the account.         \n\
-	--unregister <account>             Unregister the account.       \n\
-	                                                                 \n\
-	--call       <destination>         Call to number                \n\
-	--transfer   <destination>         Transfer active call          \n\
-\n\
-	--gcd        <callid|\"current\">    Get call details.           \n\
-	--accept     <callid|\"current\">    Accept the call             \n\
-	--hangup     <callid|\"current\">    Hangup the call             \n\
-	--refuse     <callid|\"current\">    Refuse the call             \n\
-	--hold       <callid|\"current\">    Hold the call               \n\
-	--unhold     <callid|\"current\">    Unhold the call             \n\
-	--dtmf       <key>                 Send DTMF\n"
-	
-
-
-# Option definition
-try:
-    opts, args =  getopt.getopt(sys.argv[1:],"",
-				[  "help", "gaa", "gal", "gara", "gaea", "gasa", "gaia",
-				   "gacl", "gac", "gcc", "hangup=", "refuse=", "hold",
-				   "unhold=", "transfer=","dtmf=", "accept=", "gcd=",
-				   "gad=", "register=", "unregister=", "enable=", "disable=",
-				   "call=", "sac=" ])
-except getopt.GetoptError,err:
-    print str(err)
-    sys.exit(2)
-
-
-# SFLPhone instance.
-sflphone = SflPhoneCtrl()
-
-# If no arguments, run the d-bus event loop.
-if len(sys.argv) == 1:
-	loop = gobject.MainLoop()
-	loop.run()
-
-# Parse all arguments
-else:
-	for opt, arg in opts:	
-
-		if opt == "--help":
-			printHelp()
-
-		#
-		# info options
-		#
-
-		# Get all accounts
-		elif opt == "--gaa":
-			for account in sflphone.getAllAccounts():
-				print account
-
-		# Get all registered accounts
-		elif opt == "--gara":
-			for account in sflphone.getAllRegisteredAccounts():
-				print account
-
-		# Get all enabled accounts
-		elif opt == "--gaea":
-			for account in sflphone.getAllEnabledAccounts():
-				print account
-
-		# Get all SIP accounts
-		elif opt == "--gasa":
-			for account in sflphone.getAllSipAccounts():
-				print account
-
-		# Get all IAX accounts
-		elif opt == "--gaia":
-			for account in sflphone.getAllIaxAccounts():
-				print account
-
-		# Get current call
-		elif opt == "--gcc":
-			call = sflphone.getCurrentCallID()
-			if call:
-				print call
-			else:
-				print "No current call."
-
-		# Get account details
-		elif opt == "--gad":
-			if sflphone.checkAccountExists(arg):
-				details = sflphone.getAccountDetails(arg)
-				for var in details:
-					print var + ": " + details[var]
-			else:
-				print "No such account: " + arg
-
-		# Get active codec list
-		elif opt == "--gacl":
-			print "Not implemented."
-
-		# Get call details
-		elif opt == "--gcd":
-			if arg == "current": arg = sflphone.getCurrentCallID()
-
-			details = sflphone.getCallDetails(arg)
-			if details:
-				print "Call: " + arg
-				print "Account: " + details['ACCOUNTID']
-				print "Peer: " + details['PEER_NAME'] + "<" + details['PEER_NUMBER'] + ">"
-
-		elif opt == "--sac":
-			if arg is "":
-			    print "Must specifies the accout to be set"
-			else:
-                            sflphone.setAccount(arg)
-
-
-		#
-		# call options
-		#
-
-		# Make a call
-		elif opt == "--call":
-			sflphone.Call(arg)
-
-		# Hangup a call
-		elif opt == "--hangup":
-			if arg == "current":
-				arg = sflphone.getCurrentCallID()
-
-			if arg:
-				sflphone.HangUp(arg)
-
-		# Refuse a call
-		elif opt == "--refuse":
-			if arg == "current": arg = sflphone.getCurrentCallID()
-			sflphone.Refuse(arg)
-
-		# Hold a call
-		elif opt == "--hold":
-			if arg == "current": arg = sflphone.getCurrentCallID()
-			sflphone.Hold(arg)
-
-		# Unhold a call
-		elif opt == "--unhold":
-			if arg == "current": arg = sflphone.getCurrentCallID()
-			sflphone.UnHold(arg)
-
-		# Transfer the current call
-		elif opt == "--transfer":
-			call = sflphone.callmanager.getCurrentCallID()
-			sflphone.Transfert(call, arg)
-
-		# Send DTMF
-		elif opt == "--dtmf":
-			sflphone.Dtmf(arg)
-
-		# Accept a call
-		elif opt == "--accept":
-			if arg == "current": arg = sflphone.getCurrentCallID()
-			sflphone.Accept(arg)
-
-
-		#
-		# account options
-		#
-
-		# Register an account
-		elif opt == "--register":
-			if not sflphone.checkAccountExists(arg):
-				print "Account " + arg + ": no such account."
-
-			elif arg  in sflphone.getAllRegisteredAccounts():
-				print "Account " + arg + ": already registered."
-
-			else:
-				sflphone.setAccountRegistered(arg, True)
-				print arg + ": Sent register request."
-
-		# Unregister an account
-		elif opt == "--unregister":
-			if not sflphone.checkAccountExists(arg):
-				print "Account " + arg + ": no such account."
-
-			elif arg not in sflphone.getAllRegisteredAccounts():
-				print "Account " + arg + ": is not registered."
-
-			else:
-				sflphone.setAccountRegistered(arg, False)
-				print arg + ": Sent unregister request."
-
-		# Enable an account
-		elif opt == "--enable":
-			if not sflphone.checkAccountExists(arg):
-				print "Account " + arg + ": no such account."
-
-			elif sflphone.isAccountEnable(arg):
-				print "Account " + arg + ": already enabled."
-
-			else:
-				sflphone.setAccountEnable(arg, True)
-				print arg + ": Account enabled."
-
-		# Disable an account
-		elif opt == "--disable":
-			if not sflphone.checkAccountExists(arg):
-				print "Account " + arg + ": no such account."
-
-			elif not sflphone.isAccountEnable(arg):
-				print "Account " + arg + ": already disabled."
-
-			else:
-				sflphone.setAccountRegistered(arg, False)
-				sflphone.setAccountEnable(arg, False)
-				print arg + ": Account disabled."
-
-
diff --git a/tools/pysflphone/sflphonectrl.py b/tools/pysflphone/sflphonectrl.py
deleted file mode 100755
index b6a17226a21ec1a38df9699caf08fb740ec6408b..0000000000000000000000000000000000000000
--- a/tools/pysflphone/sflphonectrl.py
+++ /dev/null
@@ -1,705 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2009 by the Free Software Foundation, 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 2
-# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-"""Simple class for controlling SflPhoned through DBUS"""
-
-import sys
-import os
-import random
-from traceback import print_exc
-
-import gtk
-import gobject
-from gobject import GObject
-from gobject import MainLoop
-
-import getopt
-
-import time
-import hashlib
-
-from threading import Thread
-from threading import Event
-
-from Errors import *
-
-try:
-	import dbus
-	from dbus.mainloop.glib import DBusGMainLoop
-except ImportError, e:
-	raise SflPhoneError("No python-dbus module found")
-
-
-class SflPhoneCtrl(Thread):
-    """ class for controlling SflPhoned through DBUS
-
-    Classes deriving this class should reimplement signal handlers,
-    more especially:
-	onIncomingCall_cb
-        onCallHangup_cb
-        onCallRinging_cb
-        onCallHold_cb
-        onCallCurrent_cb
-        onCallBusy_cb
-        onCallFailure_cb
-        onConferenceCreated_cb
-    """
-
-    # list of active calls (known by the client)
-    activeCalls = {}
-
-    # list of active conferences
-    activeConferences = {}
-
-    def __init__(self, name=sys.argv[0]):
-        Thread.__init__(self)
-
-        # current active account
-        self.account = None
-
-        # client name
-        self.name = name
-
-	self.currentCallId = ""
-        self.currentConfId = ""
-
-	self.isStop = False
-
-        # client registered to sflphoned ?
-        self.registered = False
-        self.register()
-
-        # Glib MainLoop for processing callbacks
-	self.loop = MainLoop()
-
-	gobject.threads_init()
-
-
-    def __del__(self):
-        if self.registered:
-            self.unregister()
-	self.loop.quit()
-
-
-    def stopThread(self):
-        self.isStop = True
-
-
-    def register(self):
-        if self.registered:
-            return
-
-        try:
-            # register the main loop for d-bus events
-            DBusGMainLoop(set_as_default=True)
-            self.bus = dbus.SessionBus()
-        except dbus.DBusException, e:
-            raise SPdbusError("Unable to connect DBUS session bus")
-
-        dbus_objects = dbus.Interface(self.bus.get_object(
-              'org.freedesktop.DBus', '/org/freedesktop/DBus'),
-                      'org.freedesktop.DBus').ListNames()
-
-        if not "org.sflphone.SFLphone" in dbus_objects:
-            raise SPdbusError("Unable to find org.sflphone.SFLphone in DBUS. Check if sflphoned is running")
-
-        try:
-            proxy_instance = self.bus.get_object("org.sflphone.SFLphone",
-		 "/org/sflphone/SFLphone/Instance", introspect=False)
-            proxy_callmgr = self.bus.get_object("org.sflphone.SFLphone",
-		 "/org/sflphone/SFLphone/CallManager", introspect=False)
-            proxy_confmgr = self.bus.get_object("org.sflphone.SFLphone",
-                 "/org/sflphone/SFLphone/ConfigurationManager",
-                        introspect=False)
-
-            self.instance = dbus.Interface(proxy_instance,
-                          "org.sflphone.SFLphone.Instance")
-            self.callmanager = dbus.Interface(proxy_callmgr,
-		          "org.sflphone.SFLphone.CallManager")
-            self.configurationmanager = dbus.Interface(proxy_confmgr,
-			  "org.sflphone.SFLphone.ConfigurationManager")
-
-        except dbus.DBusException, e:
-
-            raise SPdbusError("Unable to bind to sflphoned api, ask core-dev team to implement getVersion method and start to pray.")
-
-        try:
-            self.instance.Register(os.getpid(), self.name)
-            self.registered = True
-        except:
-            raise SPdaemonError("Client registration failed")
-
-        try:
-            print "Adding Incoming call method"
-            proxy_callmgr.connect_to_signal('incomingCall', self.onIncomingCall)
-            proxy_callmgr.connect_to_signal('callStateChanged', self.onCallStateChanged)
-            proxy_callmgr.connect_to_signal('conferenceCreated', self.onConferenceCreated)
-        except dbus.DBusException, e:
-            print e
-
-
-    def unregister(self):
-
-        if not self.registered:
-            return
-        try:
-            self.instance.Unregister(os.getpid())
-            self.registered = False
-        except:
-            raise SPdaemonError("Client unregistration failed")
-
-
-    def isRegistered(self):
-        return self.registered
-
-
-    #
-    # Signal handling
-    #
-
-    def onIncomingCall_cb(self):
-        pass
-
-    def onCallHangup_cb(self, callId):
-        pass
-
-    def onCallRinging_cb(self):
-        pass
-
-    def onCallHold_cb(self):
-        pass
-
-    def onCallCurrent_cb(self):
-        pass
-
-    def onCallBusy_cb(self):
-        pass
-
-    def onCallFailure_cb(self):
-        pass
-
-    def onIncomingCall(self, account, callid, to):
-        """ On incoming call event, add the call to the list of active calls """
-
-        self.activeCalls[callid] = {'Account': account,
-                                         'To': to,
-                                      'State': ''}
-	self.currentCallId = callid
-	self.onIncomingCall_cb()
-
-
-    def onCallHangUp(self, callid):
-        """ Remove callid from call list """
-
-        self.onCallHangup_cb(callid)
-	self.currentCallId = ""
-        del self.activeCalls[callid]
-
-
-    def onCallRinging(self, callid, state):
-        """ Update state for this call to Ringing """
-
-        self.activeCalls[callid]['State'] = state
-        self.onCallRinging_cb()
-
-
-    def onCallHold(self, callid, state):
-        """ Update state for this call to Hold """
-
-        self.activeCalls[callid]['State'] = state
-        self.onCallHold_cb()
-
-
-    def onCallCurrent(self, callid, state):
-        """ Update state for this call to current """
-
-        self.activeCalls[callid]['State'] = state
-        self.onCallCurrent_cb()
-
-
-    def onCallBusy(self, callid, state):
-        """ Update state for this call to busy """
-
-        self.activeCalls[callid]['State'] = state
-        self.onCallBusy_cb()
-
-
-    def onCallFailure(self, callid, state):
-        """ Handle call failure """
-
-        self.onCallFailure_cb(self)
-        del self.activeCalls[callid]
-
-
-    def onCallStateChanged(self, callid, state):
-        """ On call state changed event, set the values for new calls,
-        or delete the call from the list of active calls
-        """
-
-        print "On call state changed " + callid + " " + state
-
-        if callid not in self.activeCalls:
-            print "This call didn't exist!: " + callid + ". Adding it to the list."
-            callDetails = self.getCallDetails(callid)
-            self.activeCalls[callid] = {'Account': callDetails['ACCOUNTID'],
-                                             'To': callDetails['PEER_NUMBER'],
-                                          'State': state }
-
-
-        self.currentCallId = callid
-
-        if state == "HUNGUP":
-            self.onCallHangUp(callid)
-        elif state == "RINGING":
-            self.onCallRinging(callid, state)
-        elif state == "CURRENT":
-            self.onCallCurrent(callid, state)
-        elif state == "HOLD":
-            self.onCallHold(callid, state)
-        elif state == "BUSY":
-            self.onCallBusy(callid, state)
-        elif state == "FAILURE":
-            self.onCallFailure(self, callid, state)
-        else:
-            print "unknown state"
-
-    def onConferenceCreated_cb(self):
-        pass
-
-    def onConferenceCreated(self, confId):
-        self.currentConfId = confId
-        self.onConferenceCreated_cb()
-
-    #
-    # Account management
-    #
-    def addAccount(self, details=None):
-        """Add a new account account
-
-	Add a new account to the SFLphone-daemon. Default parameters are \
-	used for missing account configuration field.
-
-	Required parameters are type, alias, hostname, username and password
-
-	input details
-
-	"""
-
-	if details is None:
-            raise SPaccountError("Must specifies type, alias, hostname, \
-                                  username and password in \
-                                  order to create a new account")
-
-	return self.configurationmanager.addAccount(details)
-
-
-    def removeAccount(self, accountID=None):
-        """Remove an account from internal list"""
-
-	if accountID is None:
-            raise SPaccountError("Account ID must be specified")
-
-        self.configurationmanager.removeAccount(accountID)
-
-
-    def getAllAccounts(self):
-        """Return a list with all accounts"""
-
-        return self.configurationmanager.getAccountList()
-
-
-    def getAllEnabledAccounts(self):
-        """Return a list with all enabled accounts"""
-
-        accounts = self.getAllAccounts()
-        activeaccounts = []
-        for testedaccount in accounts:
-            if self.isAccountEnable(testedaccount):
-                activeaccounts.append(testedaccount)
-        return activeaccounts
-
-
-    def getAccountDetails(self, account=None):
-        """Return a list of string. If no account is provided, active account is used"""
-
-        if account is None:
-            if self.account is None:
-                raise SflPhoneError("No provided or current account !")
-                if checkAccountExists(self.account):
-                    return self.configurationmanager.getAccountDetails(self.account)
-        else:
-            if self.checkAccountExists(account):
-
-                return self.configurationmanager.getAccountDetails(account)
-
-
-    def setAccountByAlias(self, alias):
-        """Define as active the first account who match with the alias"""
-
-        for testedaccount in self.getAllAccounts():
-            details = self.getAccountDetails(testedaccount)
-            if ( details['Account.enable'] == "TRUE" and
-                              details['Account.alias'] == alias ):
-                self.account = testedaccount
-                return
-        raise SPaccountError("No enabled account matched with alias")
-
-
-    def getAccountByAlias(self, alias):
-        """Get account name having its alias"""
-
-        for account in self.getAllAccounts():
-            details = self.getAccountDetails(account)
-            if details['Account.alias'] == alias:
-                return account
-
-        raise SPaccountError("No account matched with alias")
-
-
-    def setAccount(self, account):
-        """Define the active account
-
-	The active account will be used when sending a new call
-	"""
-
-        if account in self.getAllAccounts():
-            self.account = account
-        else:
-            print account
-            raise SflPhoneError("Not a valid account")
-
-
-    def setFirstRegisteredAccount(self):
-        """Find the first enabled account and define it as active"""
-
-        rAccounts = self.getAllRegisteredAccounts()
-        if 0 == len(rAccounts):
-            raise SflPhoneError("No registered account !")
-        self.account = rAccounts[0]
-
-
-    def setFirstActiveAccount(self):
-        """Find the first enabled account and define it as active"""
-
-        aAccounts = self.getAllEnabledAccounts()
-        if 0 == len(aAccounts):
-            raise SflPhoneError("No active account !")
-        self.account = aAccounts[0]
-
-
-    def getAccount(self):
-        """Return the active account"""
-
-        return self.account
-
-
-    def isAccountRegistered(self, account=None):
-        """Return True if the account is registered. If no account is provided, active account is used"""
-
-        if account is None:
-                if self.account is None:
-                        raise SflPhoneError("No provided or current account !")
-                account = self.account
-        return self.getAccountDetails(account)['Registration.Status'] == "REGISTERED"
-
-
-    def isAccountEnable(self, account=None):
-        """Return True if the account is enabled. If no account is provided, active account is used"""
-
-        if account is None:
-            if self.account is None:
-                raise SflPhoneError("No provided or current account !")
-                account = self.account
-        return self.getAccountDetails(account)['Account.enable'] == "TRUE"
-
-
-    def setAccountEnable(self, account=None, enable=False):
-        """Set account enabled"""
-        if account is None:
-            if self.account is None:
-                raise SflPhoneError("No provided or current account !")
-                account = self.account
-
-        if enable == True:
-	    details = self.getAccountDetails(account)
-            details['Account.enable'] = "true"
-            self.configurationmanager.setAccountDetails(account, details)
-        else:
-            details = self.getAccountDetails(account)
-            details['Account.enable'] = "false"
-            self.configurationmanager.setAccountDetails(account, details)
-
-
-    def checkAccountExists(self, account=None):
-        """ Checks if the account exists """
-
-        if account is None:
-            raise SflPhoneError("No provided or current account !")
-        return account in self.getAllAccounts()
-
-
-    def getAllRegisteredAccounts(self):
-        """Return a list of registered accounts"""
-
-        registeredAccountsList = []
-        for account in self.getAllAccounts():
-            if self.isAccountRegistered(account):
-                registeredAccountsList.append(account)
-
-        return registeredAccountsList
-
-
-    def getAllEnabledAccounts(self):
-        """Return a list of enabled accounts"""
-
-        enabledAccountsList = []
-        for accountName in self.getAllAccounts():
-            if self.getAccountDetails(accountName)['Account.enable'] == "TRUE":
-                 enabledAccountsList.append(accountName)
-
-        return enabledAccountsList
-
-
-    def getAllSipAccounts(self):
-        """Return a list of SIP accounts"""
-
-        sipAccountsList = []
-        for accountName in self.getAllAccounts():
-            if  self.getAccountDetails(accountName)['Account.type'] == "SIP":
-                sipAccountsList.append(accountName)
-
-        return sipAccountsList
-
-
-    def getAllIaxAccounts(self):
-        """Return a list of IAX accounts"""
-
-        iaxAccountsList = []
-        for accountName in self.getAllAccounts():
-            if  self.getAccountDetails(accountName)['Account.type'] == "IAX":
-                iaxAccountsList.append(accountName)
-
-        return iaxAccountsList
-
-
-    def setAccountRegistered(self, account=None, register=False):
-        """ Tries to register the account """
-
-        if account is None:
-            if self.account is None:
-                raise SflPhoneError("No provided or current account !")
-            account = self.account
-
-        try:
-            if register:
-                self.configurationmanager.sendRegister(account, int(1))
-            else:
-                self.configurationmanager.sendRegister(account, int(0))
-        except SflPhoneError, e:
-            print e
-
-    #
-    # Codec manager
-    #
-
-    def getCodecList(self):
-        """ Return the codec list """
-
-        return self.configurationmanager.getCodecList()
-
-
-    def getActiveCodecList(self):
-        """ Return the active codec list """
-
-        return self.configurationmanager.getActiveCodecList()
-
-
-    #
-    # Call management
-    #
-
-    def getCurrentCallID(self):
-        """Return the callID of the current call if any"""
-
-        return self.callmanager.getCurrentCallID()
-
-
-    def getCurrentCallDetails(self):
-        """Return informations on the current call if any"""
-
-        return self.callmanager.getCallDetails(self.getCurrentCallID())
-
-    def getCallDetails(self, callid):
-        """Return informations on this call if exists"""
-
-        return self.callmanager.getCallDetails(callid)
-
-    def printClientCallList(self):
-        print "Client active call list:"
-        print "------------------------"
-        for call in self.activeCalls:
-            print "\t" + call
-
-    def Call(self, dest):
-        """Start a call and return a CallID
-
-	Use the current account previously set using setAccount().
-	If no account specified, first registered one in account list is used.
-
-	For phone number prefixed using SIP scheme (i.e. sip: or sips:),
-	IP2IP profile is automatically selected and set as the default account
-
-	return callID Newly generated callidentifier for this call
-	"""
-
-	if dest is None or dest == "":
-            raise SflPhoneError("Invalid call destination")
-
-        # Set the account to be used for this call
-	if dest.find('sip:') is 0 or dest.find('sips:') is 0:
-            print "Ip 2 IP call"
-	    self.setAccount("IP2IP")
-	elif not self.account:
-            self.setFirstRegisteredAccount()
-
-        if self.account is "IP2IP" and self.isAccountRegistered():
-            raise SflPhoneError("Can't place a call without a registered account")
-
-        # Generate a call ID for this call
-        callid = self.GenerateCallID()
-
-        # Add the call to the list of active calls and set status to SENT
-        self.activeCalls[callid] = {'Account': self.account, 'To': dest, 'State': 'SENT' }
-
-        # Send the request to the CallManager
-        self.callmanager.placeCall(self.account, callid, dest)
-
-        return callid
-
-
-    def HangUp(self, callid):
-        """End a call identified by a CallID"""
-
-        if not self.account:
-            self.setFirstRegisteredAccount()
-
-        if callid is None or callid == "":
-            pass # just to see
-
-	self.callmanager.hangUp(callid)
-
-
-    def Transfer(self, callid, to):
-        """Transfert a call identified by a CallID"""
-
-        if callid is None or callid == "":
-            raise SflPhoneError("Invalid callID")
-
-        self.callmanager.transfert(callid, to)
-
-
-    def Refuse(self, callid):
-        """Refuse an incoming call identified by a CallID"""
-
-	print "Refuse call " + callid
-
-        if callid is None or callid == "":
-            raise SflPhoneError("Invalid callID")
-
-        self.callmanager.refuse(callid)
-
-
-    def Accept(self, callid):
-        """Accept an incoming call identified by a CallID"""
-
-	print "Accept call " + callid
-        if not self.account:
-            self.setFirstRegisteredAccount()
-
-        if not self.isAccountRegistered():
-            raise SflPhoneError("Can't accept a call without a registered account")
-
-        if callid is None or callid == "":
-            raise SflPhoneError("Invalid callID")
-
-        self.callmanager.accept(callid)
-
-
-    def Hold(self, callid):
-        """Hold a call identified by a CallID"""
-
-        if callid is None or callid == "":
-            raise SflPhoneError("Invalid callID")
-
-        self.callmanager.hold(callid)
-
-
-    def UnHold(self, callid):
-        """Unhold an incoming call identified by a CallID"""
-
-        if callid is None or callid == "":
-            raise SflPhoneError("Invalid callID")
-
-        self.callmanager.unhold(callid)
-
-
-    def Dtmf(self, key):
-        """Send a DTMF"""
-
-        self.callmanager.playDTMF(key)
-
-
-    def GenerateCallID(self):
-        """Generate Call ID"""
-
-	m = hashlib.md5()
-        t = long( time.time() * 1000 )
-        r = long( random.random()*100000000000000000L )
-        m.update(str(t) + str(r))
-        callid = m.hexdigest()
-	return callid
-
-
-    def createConference(self, call1Id, call2Id):
-        """ Create a conference given the two call ids """
-
-        self.callmanager.joinParticipant(call1Id, call2Id)
-
-
-    def hangupConference(self, confId):
-        """ Hang up each call for this conference """
-
-        self.callmanager.hangUpConference(confId)
-
-
-    def run(self):
-        """Processing method for this thread"""
-
-        context = self.loop.get_context()
-
-	while True:
-            context.iteration(True)
-
-	    if self.isStop:
-                print "++++++++++++++++++++++++++++++++++++++++"
-                print "++++++++++++++++++++++++++++++++++++++++"
-                print "++++++++++++++++++++++++++++++++++++++++"
-                print "++++++++++++++++++++++++++++++++++++++++"
-                return