[Freeswitch-svn] [commit] r5442 - in freeswitch/trunk/src: . include mod/languages/mod_python

Freeswitch SVN greenlizard at freeswitch.org
Fri Jun 22 15:14:54 EDT 2007


Author: greenlizard
Date: Fri Jun 22 15:14:53 2007
New Revision: 5442

Modified:
   freeswitch/trunk/src/include/switch_cpp.h
   freeswitch/trunk/src/mod/languages/mod_python/freeswitch.py
   freeswitch/trunk/src/mod/languages/mod_python/freeswitch_python.cpp
   freeswitch/trunk/src/mod/languages/mod_python/freeswitch_python.h
   freeswitch/trunk/src/mod/languages/mod_python/mod_python.c
   freeswitch/trunk/src/mod/languages/mod_python/mod_python.i
   freeswitch/trunk/src/mod/languages/mod_python/mod_python_wrap.cpp
   freeswitch/trunk/src/switch_core_file.c
   freeswitch/trunk/src/switch_cpp.cpp

Log:
implement flushEvents() flushDigits() setAutoHangup() and setHangupHook().  reworked dtmfhandler and some aspects relating to threadstate.  folded in memory pool thing from mishehu.  added more asserts to switch_core_file (coordinated w/ anthony on this)

Modified: freeswitch/trunk/src/include/switch_cpp.h
==============================================================================
--- freeswitch/trunk/src/include/switch_cpp.h	(original)
+++ freeswitch/trunk/src/include/switch_cpp.h	Fri Jun 22 15:14:53 2007
@@ -11,6 +11,50 @@
 
 #include <switch.h>
 
+//
+// C++ Interface: switch_to_cpp_mempool
+//
+// Description: This class allows for overloading the new operator to allocate from a switch_memory_pool_t
+//
+// Author: Yossi Neiman <freeswitch at cartissolutions.com>, (C) 2007
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+
+
+#ifndef SWITCHTOMEMPOOL
+#define SWITCHTOMEMPOOL
+class SwitchToMempool {
+	public:
+		SwitchToMempool() { }
+		SwitchToMempool(switch_memory_pool_t *mem) { memorypool = mem; }
+		void *operator new(switch_size_t num_bytes, switch_memory_pool_t *mem)
+		{
+			void *ptr = switch_core_alloc(mem, (switch_size_t) num_bytes);
+			return ptr;
+		}
+	protected:
+		switch_memory_pool_t *memorypool;
+};
+#endif
+
+
+/*
+
+Overview: once you create an object that inherits this class, since
+          the memory pool is then a class data member, you can continue to
+          allocate objects from the memory pool.
+          objects from within the class
+
+Notes on usage:
+
+1.  The derived class will need to also overload the ctor so that it accepts a memory pool object as a parameter.
+2.  Instantiation of a class would then look something like this:   Foo *bar = new(memory_pool) Foo(memory_pool);
+
+Note that the first parameter to the new operator is implicitly handled by c++...  not sure I like that but it's how it is...
+
+*/
+
 
 void console_log(char *level_str, char *msg);
 void console_clean_log(char *msg);
@@ -40,6 +84,12 @@
     char *funcargs;           // extra string that will be passed to callback function 
 } input_callback_state_t;
 
+typedef enum {
+	S_HUP = (1 << 0),
+	S_FREE = (1 << 1),
+	S_RDLOCK = (1 << 2)
+} session_flag_t;
+
 
 class CoreSession {
  protected:
@@ -52,6 +102,9 @@
 	char *tts_name;
 	char *voice_name;
 	void store_file_handle(switch_file_handle_t *fh);
+	void *on_hangup; // language specific callback function, cast as void * 
+
+
  public:
 	CoreSession();
 	CoreSession(char *uuid);
@@ -59,12 +112,14 @@
 	virtual ~CoreSession();
 	switch_core_session_t *session;
 	switch_channel_t *channel;
+	unsigned int flags;
 	input_callback_state cb_state; // callback state, always pointed to by the buf
                                    // field in this->args
+	switch_channel_state_t hook_state; // store hookstate for on_hangup callback
 
 	int answer();
 	int preAnswer();
-	void hangup(char *cause);
+	virtual void hangup(char *cause);
 	void setVariable(char *var, char *val);
 	char *getVariable(char *var);
 
@@ -118,19 +173,16 @@
      * is pressed by user during playFile(), streamfile(), and 
      * certain other methods are executing.
      *
-     * Note that language specific sessions might need to create
-     * their own version of this with a slightly different signature
-     * (as done in freeswitch_python.h)
-	 */
-	void setDTMFCallback(switch_input_callback_function_t cb, 
-						 void *buf, 
-						 uint32_t buflen);
+	 */
+	void setDTMFCallback(void *cbfunc, char *funcargs);
+
 
 	int speak(char *text);
 	void set_tts_parms(char *tts_name, char *voice_name);
 
 	int getDigits(char *dtmf_buf, 
-				  int len, 
+				  int buflen, 
+				  int maxdigits, 
 				  char *terminators, 
 				  char *terminator, 
 				  int timeout);
@@ -165,11 +217,26 @@
 	 */
 	int streamfile(char *file, int starting_sample_count);
 
+	/** \brief flush any pending events
+	 */
+	int flushEvents();
+
+	/** \brief flush any pending digits
+	 */
+	int flushDigits();
+
+	int setAutoHangup(bool val);
+
+	/** \brief Set the hangup callback function
+	 * \param hangup_func - language specific function ptr cast into void *
+	 */
+	void setHangupHook(void *hangup_func);
+
 	bool ready();
 
 	void execute(char *app, char *data);
-	virtual void begin_allow_threads();
-	virtual void end_allow_threads();
+	virtual bool begin_allow_threads() = 0;
+	virtual bool end_allow_threads() = 0;
 
 	/** \brief Get the uuid of this session	
 	 * \return the uuid of this session
@@ -181,6 +248,12 @@
 	 */
 	const switch_input_args_t& get_cb_args() const { return args; };
 
+	/** \brief Callback to the language specific hangup callback
+	 */
+	virtual void check_hangup_hook() = 0;
+
+	virtual switch_status_t run_dtmf_callback(void *input, 
+											  switch_input_type_t itype) = 0;
 
 };
 
@@ -200,6 +273,19 @@
 void bridge(CoreSession &session_a, CoreSession &session_b);
 
 
+/** \brief the actual hangup hook called back by freeswitch core
+ *         which in turn gets the session and calls the appropriate
+ *         instance method to complete the callback.
+ */
+switch_status_t hanguphook(switch_core_session_t *session);
+
+switch_status_t dtmf_callback(switch_core_session_t *session, 
+							  void *input, 
+							  switch_input_type_t itype, 
+							  void *buf,  
+							  unsigned int buflen);
+
+
 #ifdef __cplusplus
 }
 #endif

Modified: freeswitch/trunk/src/mod/languages/mod_python/freeswitch.py
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_python/freeswitch.py	(original)
+++ freeswitch/trunk/src/mod/languages/mod_python/freeswitch.py	Fri Jun 22 15:14:53 2007
@@ -80,16 +80,16 @@
 input_callback_state_t_swigregister = _freeswitch.input_callback_state_t_swigregister
 input_callback_state_t_swigregister(input_callback_state_t)
 
+S_HUP = _freeswitch.S_HUP
+S_FREE = _freeswitch.S_FREE
+S_RDLOCK = _freeswitch.S_RDLOCK
 class CoreSession(_object):
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, CoreSession, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, CoreSession, name)
+    def __init__(self): raise AttributeError, "No constructor defined"
     __repr__ = _swig_repr
-    def __init__(self, *args): 
-        this = _freeswitch.new_CoreSession(*args)
-        try: self.this.append(this)
-        except: self.this = this
     __swig_destroy__ = _freeswitch.delete_CoreSession
     __del__ = lambda self : None;
     __swig_setmethods__["session"] = _freeswitch.CoreSession_session_set
@@ -98,9 +98,15 @@
     __swig_setmethods__["channel"] = _freeswitch.CoreSession_channel_set
     __swig_getmethods__["channel"] = _freeswitch.CoreSession_channel_get
     if _newclass:channel = _swig_property(_freeswitch.CoreSession_channel_get, _freeswitch.CoreSession_channel_set)
+    __swig_setmethods__["flags"] = _freeswitch.CoreSession_flags_set
+    __swig_getmethods__["flags"] = _freeswitch.CoreSession_flags_get
+    if _newclass:flags = _swig_property(_freeswitch.CoreSession_flags_get, _freeswitch.CoreSession_flags_set)
     __swig_setmethods__["cb_state"] = _freeswitch.CoreSession_cb_state_set
     __swig_getmethods__["cb_state"] = _freeswitch.CoreSession_cb_state_get
     if _newclass:cb_state = _swig_property(_freeswitch.CoreSession_cb_state_get, _freeswitch.CoreSession_cb_state_set)
+    __swig_setmethods__["hook_state"] = _freeswitch.CoreSession_hook_state_set
+    __swig_getmethods__["hook_state"] = _freeswitch.CoreSession_hook_state_get
+    if _newclass:hook_state = _swig_property(_freeswitch.CoreSession_hook_state_get, _freeswitch.CoreSession_hook_state_set)
     def answer(*args): return _freeswitch.CoreSession_answer(*args)
     def preAnswer(*args): return _freeswitch.CoreSession_preAnswer(*args)
     def hangup(*args): return _freeswitch.CoreSession_hangup(*args)
@@ -117,17 +123,26 @@
     def transfer(*args): return _freeswitch.CoreSession_transfer(*args)
     def playAndGetDigits(*args): return _freeswitch.CoreSession_playAndGetDigits(*args)
     def streamfile(*args): return _freeswitch.CoreSession_streamfile(*args)
+    def flushEvents(*args): return _freeswitch.CoreSession_flushEvents(*args)
+    def flushDigits(*args): return _freeswitch.CoreSession_flushDigits(*args)
+    def setAutoHangup(*args): return _freeswitch.CoreSession_setAutoHangup(*args)
+    def setHangupHook(*args): return _freeswitch.CoreSession_setHangupHook(*args)
     def ready(*args): return _freeswitch.CoreSession_ready(*args)
     def execute(*args): return _freeswitch.CoreSession_execute(*args)
     def begin_allow_threads(*args): return _freeswitch.CoreSession_begin_allow_threads(*args)
     def end_allow_threads(*args): return _freeswitch.CoreSession_end_allow_threads(*args)
     def get_uuid(*args): return _freeswitch.CoreSession_get_uuid(*args)
     def get_cb_args(*args): return _freeswitch.CoreSession_get_cb_args(*args)
+    def check_hangup_hook(*args): return _freeswitch.CoreSession_check_hangup_hook(*args)
+    def run_dtmf_callback(*args): return _freeswitch.CoreSession_run_dtmf_callback(*args)
 CoreSession_swigregister = _freeswitch.CoreSession_swigregister
 CoreSession_swigregister(CoreSession)
 
 bridge = _freeswitch.bridge
-PythonDTMFCallback = _freeswitch.PythonDTMFCallback
+hanguphook = _freeswitch.hanguphook
+dtmf_callback = _freeswitch.dtmf_callback
+S_SWAPPED_IN = _freeswitch.S_SWAPPED_IN
+S_SWAPPED_OUT = _freeswitch.S_SWAPPED_OUT
 class PySession(CoreSession):
     __swig_setmethods__ = {}
     for _s in [CoreSession]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{}))
@@ -143,8 +158,12 @@
     __swig_destroy__ = _freeswitch.delete_PySession
     __del__ = lambda self : None;
     def setDTMFCallback(*args): return _freeswitch.PySession_setDTMFCallback(*args)
+    def setHangupHook(*args): return _freeswitch.PySession_setHangupHook(*args)
+    def check_hangup_hook(*args): return _freeswitch.PySession_check_hangup_hook(*args)
+    def hangup(*args): return _freeswitch.PySession_hangup(*args)
     def begin_allow_threads(*args): return _freeswitch.PySession_begin_allow_threads(*args)
     def end_allow_threads(*args): return _freeswitch.PySession_end_allow_threads(*args)
+    def run_dtmf_callback(*args): return _freeswitch.PySession_run_dtmf_callback(*args)
 PySession_swigregister = _freeswitch.PySession_swigregister
 PySession_swigregister(PySession)
 

Modified: freeswitch/trunk/src/mod/languages/mod_python/freeswitch_python.cpp
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_python/freeswitch_python.cpp	(original)
+++ freeswitch/trunk/src/mod/languages/mod_python/freeswitch_python.cpp	Fri Jun 22 15:14:53 2007
@@ -1,7 +1,7 @@
 #include "freeswitch_python.h"
 
 #define sanity_check(x) do { if (!session) { switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "session is not initalized\n"); return x;}} while(0)
-#define init_vars() do { caller_profile.source = "mod_python"; } while(0)
+#define init_vars() do { caller_profile.source = "mod_python"; swapstate = S_SWAPPED_IN; } while(0)
 
 PySession::PySession() : CoreSession()
 {
@@ -24,80 +24,107 @@
     sanity_check();
 
     if (!PyCallable_Check(pyfunc)) {
-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "DTMF function is not a python function.");
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "DTMF function is not a python function.\n");
+	return;
     }
-    else {
-	cb_state.funcargs = funcargs;
-	cb_state.function = (void *) pyfunc;
+    Py_XINCREF(pyfunc);  
+    CoreSession::setDTMFCallback((void *) pyfunc, funcargs);
 
-	args.buf = &cb_state; 
-	args.buflen = sizeof(cb_state);  // not sure what this is used for, copy mod_spidermonkey
-        
-	// we cannot set the actual callback to a python function, because
-	// the callback is a function pointer with a specific signature.
-	// so, set it to the following c function which will act as a proxy,
-	// finding the python callback in the args callback args structure
-	args.input_callback = PythonDTMFCallback;  // defined in mod_python.i
-	ap = &args;
 
+}
+
+void PySession::setHangupHook(PyObject *pyfunc) {
+
+    if (!PyCallable_Check(pyfunc)) {
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Hangup hook is not a python function.\n");
+	return;
     }
 
-    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "dtmf callback was set, pyfunc: %p.  cb_state: %p\n", pyfunc, &cb_state);
+    // without this Py_XINCREF, there will be segfaults.  basically the python
+    // interpreter will not know that it should not GC this object.
+    // callback example: http://docs.python.org/ext/callingPython.html
+    Py_XINCREF(pyfunc);  
+    CoreSession::setHangupHook((void *) pyfunc);
 
 }
 
 
-void PySession::begin_allow_threads(void) { 
-    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PySession::begin_allow_threads() called\n");
+void PySession::check_hangup_hook() {
+   PyObject *func;
+   PyObject *result;
+   char *resultStr;
+   bool did_swap_in = false;
 
-    // swap out threadstate and store in instance variable 
-    threadState = (void *) PyEval_SaveThread();
-    cb_state.threadState = threadState;
-    args.buf = &cb_state;     
-    ap = &args;
-}
+   switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "check_hangup_hook called\n");
 
-void PySession::end_allow_threads(void) { 
-    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PySession::end_allow_threads() called\n");
-    // swap in threadstate from instance variable saved earlier
-    PyEval_RestoreThread(((PyThreadState *)threadState));
-}
+   if (!session) {
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No valid session\n");
+	return;
+   }
 
-PySession::~PySession() {
-    // Should we do any cleanup here?
-    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PySession::~PySession desctructor\n");
-}
+   // The did_swap_in boolean was added to fix the following problem:
+   // Design flaw - we swap in threadstate based on the assumption that thread state 
+   // is currently _swapped out_ when this hangup hook is called.  However, nothing known to 
+   // guarantee that, and  if thread state is already swapped in when this is invoked, 
+   // bad things will happen.
+   switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "check hangup hook end_allow_threads\n");
+   did_swap_in = end_allow_threads();
+ 
+   if (on_hangup == NULL) {
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "on_hangup is null\n");
+       return;
+   }
 
+   func = (PyObject *) on_hangup;
 
-/* ----- functions not bound to PySession instance ------ */
+   // TODO: to match js implementation, should pass the _python_ PySession 
+   // object instance wrapping this C++ PySession instance. but how do we do that?
+   // for now, pass the uuid since its better than nothing
+   PyObject* func_arg = Py_BuildValue("(s)", uuid);
 
+   result = PyEval_CallObject(func, func_arg);
+   Py_XDECREF(func_arg);
+
+   if (result) {
+       resultStr = (char *) PyString_AsString(result);
+       // currently just ignore the result
+   }
+   else {
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to call python hangup callback\n");
+       PyErr_Print();
+       PyErr_Clear();
+   }
+
+   switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "check hangup hook begin_allow_threads\n");
+   if (did_swap_in) {
+       begin_allow_threads();
+   }
+
+   Py_XDECREF(result);
+
+}
+
+switch_status_t PySession::run_dtmf_callback(void *input, 
+					     switch_input_type_t itype) {
 
-switch_status_t PythonDTMFCallback(switch_core_session_t *session, 
-                                        void *input, 
-                                        switch_input_type_t itype, 
-                                        void *buf,  
-                                        unsigned int buflen)
-{
    PyObject *func, *arglist;
-   PyObject *result;
+   PyObject *pyresult;
    char *resultStr;
    char *funcargs;
-   input_callback_state_t *cb_state;	
    switch_file_handle_t *fh = NULL;	
-   PyThreadState *threadState = NULL;	
+   bool did_swap_in = false;
  
-   switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PythonDTMFCallback\n");	
+   switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "run_dtmf_callback\n");	
 
-   if (!buf) {
-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "buf pointer is null");	
+
+   if (!cb_state.function) {
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "cb_state->function is null\n");	
 	return SWITCH_STATUS_FALSE;
-   }	
-   
-   cb_state = (input_callback_state *) buf;   
+   }
 
-   func = (PyObject *) cb_state->function;
+   func = (PyObject *) cb_state.function;
    if (!func) {
-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cb_state->function is null\n");	
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "cb_state->function is null\n");	
 	return SWITCH_STATUS_FALSE;
    }
    else {
@@ -108,7 +135,7 @@
 	return SWITCH_STATUS_FALSE;
    }
 
-   funcargs = (char *) cb_state->funcargs;
+   funcargs = (char *) cb_state.funcargs;
 
    arglist = Py_BuildValue("(sis)", input, itype, funcargs);
    if (!arglist) {
@@ -116,38 +143,132 @@
 	return SWITCH_STATUS_FALSE;
    }
 
-   threadState = (PyThreadState *) cb_state->threadState;
-   if (!threadState) {
-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error, invalid threadstate\n");	
-	return SWITCH_STATUS_FALSE;
+   switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "run_dtmf_callback end_allow_threads\n");
+   did_swap_in = end_allow_threads();
+	
+   pyresult = PyEval_CallObject(func, arglist);    
+   
+
+   Py_XDECREF(arglist);                           // Trash arglist
+   if (pyresult && pyresult != Py_None) {                       
+       resultStr = (char *) PyString_AsString(pyresult);
+       switch_status_t cbresult = process_callback_result(resultStr, &cb_state, session);
+       return cbresult;
    }
    else {
-        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "restoring threadstate: %p\n", threadState);	
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error calling python callback\n");
+       PyErr_Print();
+       PyErr_Clear();
    }
 
-   PyEval_RestoreThread(threadState);  // nasty stuff happens when py interp has no thread state
+   switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "run_dtmf_callback begin_allow_threads\n");
+   if (did_swap_in) {
+       begin_allow_threads();
+   }
 
-   switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "restored threadstate, calling python function: %p\n", func);
-	
-   result = PyEval_CallObject(func, arglist);    
-   
-   threadState = PyEval_SaveThread();  
+   Py_XDECREF(pyresult);
 
-   switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "called python function\n");
+   return SWITCH_STATUS_SUCCESS;	
 
-   Py_DECREF(arglist);                           // Trash arglist
-   if (result && result != Py_None) {                       
-       resultStr = (char *) PyString_AsString(result);
-       Py_XDECREF(result);
-       return process_callback_result(resultStr, cb_state, session);
-   }
-   else {
-       return SWITCH_STATUS_FALSE;	
-   }
+}
+
+bool PySession::begin_allow_threads(void) { 
+    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PySession::begin_allow_threads() called\n");
+
+    // swap out threadstate and store in instance variable 
+    switch_channel_t *channel = switch_core_session_get_channel(session);
+    PyThreadState *swapin_tstate = (PyThreadState *) switch_channel_get_private(channel, "SwapInThreadState");
+    // so lets assume the thread state was swapped in when the python script was started,
+    // therefore swapin_tstate will be NULL (because there is nothing to swap in, since its 
+    // _already_ swapped in.)
+    if (swapin_tstate == NULL) {
+	// currently swapped in
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Threadstate swap-out!\n");	
+	swapin_tstate = PyEval_SaveThread();
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "swapin_tstate: %p\n", swapin_tstate);	
+	// give future swapper-inners something to actually swap in
+	switch_channel_set_private(channel, "SwapInThreadState", (void *) swapin_tstate); 
+	cb_state.threadState = threadState;  // TODO: get rid of this
+	args.buf = &cb_state;     
+	ap = &args;
+	return true;
+
+    }
+    else {
+	// currently swapped out
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Threadstate already swapd-out! Skipping\n");	
+	return false;
+    }
+
+}
+
+bool PySession::end_allow_threads(void) { 
+    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PySession::end_allow_threads() called\n");
+    // swap in threadstate from instance variable saved earlier
+    switch_channel_t *channel = switch_core_session_get_channel(session);
+    PyThreadState *swapin_tstate = (PyThreadState *) switch_channel_get_private(channel, "SwapInThreadState");
+    if (swapin_tstate == NULL) {
+	// currently swapped in
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Threadstate double swap-in! Skipping\n");	
+	return false;
+    }
+    else {
+	// currently swapped out
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Threadstate swap-in!\n");	
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "swapin_tstate: %p\n", swapin_tstate);	
+	PyEval_RestoreThread(swapin_tstate);
+	// dont give any swapper-inners the opportunity to do a double swap
+	switch_channel_set_private(channel, "SwapInThreadState", NULL);
+	return true;
+    }
 
 
 }
 
+void PySession::hangup(char *cause) {
+
+
+    // since we INCREF'd this function pointer earlier (so the py gc didnt reclaim it)
+    // we have to DECREF it, or else the PySession dtor will never get called and
+    // a zombie channel will be left over using up resources
+    
+    if (cb_state.function != NULL) {
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "xdecref on cb_state_function\n");	
+	PyObject * func = (PyObject *) cb_state.function;
+	Py_XDECREF(func);
+    }
+    else {
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "cb_state.function is null\n");	
+    }
+    
+
+    CoreSession::hangup(cause);
+
+}
+
+
+PySession::~PySession() {
+    // Should we do any cleanup here?
+    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PySession::~PySession started\n");
+
+    if (on_hangup) {
+	PyObject * func = (PyObject *) on_hangup;
+	Py_XDECREF(func);
+    }
+
+    
+    if (cb_state.function != NULL) {
+	PyObject * func = (PyObject *) cb_state.function;
+	Py_XDECREF(func);
+    }
+    
+    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PySession::~PySession finished\n");
+    
+}
+
+
+
+
 
 
 

Modified: freeswitch/trunk/src/mod/languages/mod_python/freeswitch_python.h
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_python/freeswitch_python.h	(original)
+++ freeswitch/trunk/src/mod/languages/mod_python/freeswitch_python.h	Fri Jun 22 15:14:53 2007
@@ -14,12 +14,10 @@
 
 
 
-switch_status_t PythonDTMFCallback(switch_core_session *session, 
-				   void *input, 
-				   switch_input_type_t itype, 
-				   void *buf, 
-				   unsigned int buflen);
-
+typedef enum {
+	S_SWAPPED_IN = (1 << 0),
+	S_SWAPPED_OUT = (1 << 1)
+} swap_state_t;
 
 void console_log(char *level_str, char *msg);
 void console_clean_log(char *msg);
@@ -29,14 +27,21 @@
 class PySession : public CoreSession {
  private:
     void *threadState;
+    int swapstate;
  public:
     PySession();
     PySession(char *uuid);
     PySession(switch_core_session_t *session);
     ~PySession();        
     void setDTMFCallback(PyObject *pyfunc, char *funcargs);
-    void begin_allow_threads();
-    void end_allow_threads();
+    void setHangupHook(PyObject *pyfunc);
+    void check_hangup_hook();
+    void hangup(char *cause);
+    bool begin_allow_threads();
+    bool end_allow_threads();
+
+    switch_status_t run_dtmf_callback(void *input, 
+				      switch_input_type_t itype);
 
 };
 

Modified: freeswitch/trunk/src/mod/languages/mod_python/mod_python.c
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_python/mod_python.c	(original)
+++ freeswitch/trunk/src/mod/languages/mod_python/mod_python.c	Fri Jun 22 15:14:53 2007
@@ -49,11 +49,12 @@
 void init_freeswitch(void);
 static switch_api_interface_t python_run_interface;
 
+
 SWITCH_MODULE_LOAD_FUNCTION(mod_python_load);
 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_python_shutdown);
 SWITCH_MODULE_DEFINITION(mod_python, mod_python_load, mod_python_shutdown, NULL);
 
-static void eval_some_python(char *uuid, char *args)
+static void eval_some_python(char *uuid, char *args, switch_core_session_t *session)
 {
 	PyThreadState *tstate = NULL;
 	char *dupargs = NULL;
@@ -92,6 +93,11 @@
 
 	// swap in thread state
 	PyEval_AcquireThread(tstate);
+	if (session) {
+	    // record the fact that thread state is swapped in
+	    switch_channel_t *channel = switch_core_session_get_channel(session);
+	    switch_channel_set_private(channel, "SwapInThreadState", NULL);
+	}
 	init_freeswitch(); 
 
 	// import the module
@@ -138,7 +144,9 @@
 	}
 
 	// invoke the handler 
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Call python script \n");
 	result = PyEval_CallObjectWithKeywords(function, arg, (PyObject *)NULL);
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Finished calling python script \n");
 
 	// check the result and print out any errors
 	if (!result) {
@@ -160,7 +168,29 @@
 	Py_XDECREF(result);
 
 	// swap out thread state
-	PyEval_ReleaseThread(tstate);
+	if (session) {
+	    // record the fact that thread state is swapped in
+	    switch_channel_t *channel = switch_core_session_get_channel(session);
+	    PyThreadState *swapin_tstate = (PyThreadState *) switch_channel_get_private(channel, "SwapInThreadState");
+	    // so lets assume nothing in the python script swapped any thread state in
+            // or out .. thread state will currently be swapped in, and the SwapInThreadState 
+	    // will be null
+	    if (swapin_tstate == NULL) {
+		// swap it out
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Threadstate mod_python.c swap-out! \n");
+		// PyEval_ReleaseThread(cur_tstate);
+		swapin_tstate = (void *) PyEval_SaveThread();
+		switch_channel_set_private(channel, "SwapInThreadState", (void *) swapin_tstate);
+	    }
+	    else {
+		// thread state is already swapped out, so, nothing for us to do
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "according to chan priv data, already swapped out \n");
+	    }
+ 	}
+	else {
+	    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Threadstate mod_python.c swap-out! \n");
+	    PyEval_ReleaseThread(tstate);
+	}
 
 	switch_safe_free(dupargs);
 
@@ -169,7 +199,7 @@
 
 static void python_function(switch_core_session_t *session, char *data)
 {
-	eval_some_python(switch_core_session_get_uuid(session), (char *)data);
+	eval_some_python(switch_core_session_get_uuid(session), (char *)data, session);
 	
 }
 
@@ -183,7 +213,7 @@
 	switch_memory_pool_t *pool;
 	struct switch_py_thread *pt = (struct switch_py_thread *) obj;
 
-	eval_some_python(NULL, strdup(pt->args));
+	eval_some_python(NULL, strdup(pt->args), NULL);
 
 	pool = pt->pool;
 	switch_core_destroy_memory_pool(&pool);

Modified: freeswitch/trunk/src/mod/languages/mod_python/mod_python.i
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_python/mod_python.i	(original)
+++ freeswitch/trunk/src/mod/languages/mod_python/mod_python.i	Fri Jun 22 15:14:53 2007
@@ -9,12 +9,16 @@
 %cstring_bounded_mutable(char *dtmf_buf, 128);
 %cstring_bounded_mutable(char *terminator, 8);
 
+
 /** insert the following includes into generated code so it compiles */
 %{
 #include "switch_cpp.h"
 #include "freeswitch_python.h"
 %}
 
+
+%ignore SwitchToMempool;   
+
 /**
  * tell swig to grok everything defined in these header files and
  * build all sorts of c wrappers and python shadows of the c wrappers.

Modified: freeswitch/trunk/src/mod/languages/mod_python/mod_python_wrap.cpp
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_python/mod_python_wrap.cpp	(original)
+++ freeswitch/trunk/src/mod/languages/mod_python/mod_python_wrap.cpp	Fri Jun 22 15:14:53 2007
@@ -2469,14 +2469,14 @@
 #define SWIGTYPE_p_PySession swig_types[1]
 #define SWIGTYPE_p_char swig_types[2]
 #define SWIGTYPE_p_input_callback_state swig_types[3]
-#define SWIGTYPE_p_switch_channel_t swig_types[4]
-#define SWIGTYPE_p_switch_core_session swig_types[5]
-#define SWIGTYPE_p_switch_core_session_t swig_types[6]
-#define SWIGTYPE_p_switch_input_args_t swig_types[7]
-#define SWIGTYPE_p_switch_input_callback_function_t swig_types[8]
-#define SWIGTYPE_p_switch_input_type_t swig_types[9]
-#define SWIGTYPE_p_switch_status_t swig_types[10]
-#define SWIGTYPE_p_uint32_t swig_types[11]
+#define SWIGTYPE_p_session_flag_t swig_types[4]
+#define SWIGTYPE_p_swap_state_t swig_types[5]
+#define SWIGTYPE_p_switch_channel_state_t swig_types[6]
+#define SWIGTYPE_p_switch_channel_t swig_types[7]
+#define SWIGTYPE_p_switch_core_session_t swig_types[8]
+#define SWIGTYPE_p_switch_input_args_t swig_types[9]
+#define SWIGTYPE_p_switch_input_type_t swig_types[10]
+#define SWIGTYPE_p_switch_status_t swig_types[11]
 #define SWIGTYPE_p_void swig_types[12]
 static swig_type_info *swig_types[14];
 static swig_module_info swig_module = {swig_types, 13, 0, 0, 0, 0};
@@ -2768,13 +2768,18 @@
 
 
 SWIGINTERN int
-SWIG_AsVal_long (PyObject *obj, long* val)
+SWIG_AsVal_unsigned_SS_long (PyObject *obj, unsigned long *val) 
 {
   if (PyInt_Check(obj)) {
-    if (val) *val = PyInt_AsLong(obj);
-    return SWIG_OK;
+    long v = PyInt_AsLong(obj);
+    if (v >= 0) {
+      if (val) *val = v;
+      return SWIG_OK;
+    } else {
+      return SWIG_OverflowError;
+    }
   } else if (PyLong_Check(obj)) {
-    long v = PyLong_AsLong(obj);
+    unsigned long v = PyLong_AsUnsignedLong(obj);
     if (!PyErr_Occurred()) {
       if (val) *val = v;
       return SWIG_OK;
@@ -2785,7 +2790,7 @@
 #ifdef SWIG_PYTHON_CAST_MODE
   {
     int dispatch = 0;
-    long v = PyInt_AsLong(obj);
+    unsigned long v = PyLong_AsUnsignedLong(obj);
     if (!PyErr_Occurred()) {
       if (val) *val = v;
       return SWIG_AddCast(SWIG_OK);
@@ -2795,8 +2800,8 @@
     if (!dispatch) {
       double d;
       int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d));
-      if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) {
-	if (val) *val = (long)(d);
+      if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) {
+	if (val) *val = (unsigned long)(d);
 	return res;
       }
     }
@@ -2807,41 +2812,44 @@
 
 
 SWIGINTERN int
-SWIG_AsVal_int (PyObject * obj, int *val)
+SWIG_AsVal_unsigned_SS_int (PyObject * obj, unsigned int *val)
 {
-  long v;
-  int res = SWIG_AsVal_long (obj, &v);
+  unsigned long v;
+  int res = SWIG_AsVal_unsigned_SS_long (obj, &v);
   if (SWIG_IsOK(res)) {
-    if ((v < INT_MIN || v > INT_MAX)) {
+    if ((v > UINT_MAX)) {
       return SWIG_OverflowError;
     } else {
-      if (val) *val = static_cast< int >(v);
+      if (val) *val = static_cast< unsigned int >(v);
     }
   }  
   return res;
 }
 
 
-SWIGINTERNINLINE PyObject*
-  SWIG_From_bool  (bool value)
+SWIGINTERNINLINE PyObject* 
+SWIG_From_unsigned_SS_long  (unsigned long value)
 {
-  return PyBool_FromLong(value ? 1 : 0);
+  return (value > LONG_MAX) ?
+    PyLong_FromUnsignedLong(value) : PyInt_FromLong(static_cast< long >(value)); 
+}
+
+
+SWIGINTERNINLINE PyObject *
+SWIG_From_unsigned_SS_int  (unsigned int value)
+{    
+  return SWIG_From_unsigned_SS_long  (value);
 }
 
 
 SWIGINTERN int
-SWIG_AsVal_unsigned_SS_long (PyObject *obj, unsigned long *val) 
+SWIG_AsVal_long (PyObject *obj, long* val)
 {
   if (PyInt_Check(obj)) {
-    long v = PyInt_AsLong(obj);
-    if (v >= 0) {
-      if (val) *val = v;
-      return SWIG_OK;
-    } else {
-      return SWIG_OverflowError;
-    }
+    if (val) *val = PyInt_AsLong(obj);
+    return SWIG_OK;
   } else if (PyLong_Check(obj)) {
-    unsigned long v = PyLong_AsUnsignedLong(obj);
+    long v = PyLong_AsLong(obj);
     if (!PyErr_Occurred()) {
       if (val) *val = v;
       return SWIG_OK;
@@ -2852,7 +2860,7 @@
 #ifdef SWIG_PYTHON_CAST_MODE
   {
     int dispatch = 0;
-    unsigned long v = PyLong_AsUnsignedLong(obj);
+    long v = PyInt_AsLong(obj);
     if (!PyErr_Occurred()) {
       if (val) *val = v;
       return SWIG_AddCast(SWIG_OK);
@@ -2862,8 +2870,8 @@
     if (!dispatch) {
       double d;
       int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d));
-      if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) {
-	if (val) *val = (unsigned long)(d);
+      if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) {
+	if (val) *val = (long)(d);
 	return res;
       }
     }
@@ -2874,20 +2882,45 @@
 
 
 SWIGINTERN int
-SWIG_AsVal_unsigned_SS_int (PyObject * obj, unsigned int *val)
+SWIG_AsVal_int (PyObject * obj, int *val)
 {
-  unsigned long v;
-  int res = SWIG_AsVal_unsigned_SS_long (obj, &v);
+  long v;
+  int res = SWIG_AsVal_long (obj, &v);
   if (SWIG_IsOK(res)) {
-    if ((v > UINT_MAX)) {
+    if ((v < INT_MIN || v > INT_MAX)) {
       return SWIG_OverflowError;
     } else {
-      if (val) *val = static_cast< unsigned int >(v);
+      if (val) *val = static_cast< int >(v);
     }
   }  
   return res;
 }
 
+
+SWIGINTERN int
+SWIG_AsVal_bool (PyObject *obj, bool *val)
+{
+  if (obj == Py_True) {
+    if (val) *val = true;
+    return SWIG_OK;
+  } else if (obj == Py_False) {
+    if (val) *val = false;
+    return SWIG_OK;
+  } else {
+    long v = 0;
+    int res = SWIG_AddCast(SWIG_AsVal_long (obj, val ? &v : 0));
+    if (SWIG_IsOK(res) && val) *val = v ? true : false;
+    return res;
+  }
+}
+
+
+SWIGINTERNINLINE PyObject*
+  SWIG_From_bool  (bool value)
+{
+  return PyBool_FromLong(value ? 1 : 0);
+}
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -3311,103 +3344,6 @@
   return SWIG_Py_Void();
 }
 
-SWIGINTERN PyObject *_wrap_new_CoreSession__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  CoreSession *result = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)":new_CoreSession")) SWIG_fail;
-  result = (CoreSession *)new CoreSession();
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_CoreSession, SWIG_POINTER_NEW |  0 );
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_new_CoreSession__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  char *arg1 = (char *) 0 ;
-  CoreSession *result = 0 ;
-  int res1 ;
-  char *buf1 = 0 ;
-  int alloc1 = 0 ;
-  PyObject * obj0 = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"O:new_CoreSession",&obj0)) SWIG_fail;
-  res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1);
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_CoreSession" "', argument " "1"" of type '" "char *""'");
-  }
-  arg1 = reinterpret_cast< char * >(buf1);
-  result = (CoreSession *)new CoreSession(arg1);
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_CoreSession, SWIG_POINTER_NEW |  0 );
-  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-  return resultobj;
-fail:
-  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_new_CoreSession__SWIG_2(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  switch_core_session_t *arg1 = (switch_core_session_t *) 0 ;
-  CoreSession *result = 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject * obj0 = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"O:new_CoreSession",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_switch_core_session_t, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_CoreSession" "', argument " "1"" of type '" "switch_core_session_t *""'"); 
-  }
-  arg1 = reinterpret_cast< switch_core_session_t * >(argp1);
-  result = (CoreSession *)new CoreSession(arg1);
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_CoreSession, SWIG_POINTER_NEW |  0 );
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_new_CoreSession(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[2];
-  int ii;
-  
-  if (!PyTuple_Check(args)) SWIG_fail;
-  argc = PyObject_Length(args);
-  for (ii = 0; (ii < argc) && (ii < 1); ii++) {
-    argv[ii] = PyTuple_GET_ITEM(args,ii);
-  }
-  if (argc == 0) {
-    return _wrap_new_CoreSession__SWIG_0(self, args);
-  }
-  if (argc == 1) {
-    int _v;
-    void *vptr = 0;
-    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_switch_core_session_t, 0);
-    _v = SWIG_CheckState(res);
-    if (_v) {
-      return _wrap_new_CoreSession__SWIG_2(self, args);
-    }
-  }
-  if (argc == 1) {
-    int _v;
-    int res = SWIG_AsCharPtrAndSize(argv[0], 0, NULL, 0);
-    _v = SWIG_CheckState(res);
-    if (_v) {
-      return _wrap_new_CoreSession__SWIG_1(self, args);
-    }
-  }
-  
-fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'new_CoreSession'.\n  Possible C/C++ prototypes are:\n    CoreSession()\n    CoreSession(char *)\n    CoreSession(switch_core_session_t *)\n");
-  return NULL;
-}
-
-
 SWIGINTERN PyObject *_wrap_delete_CoreSession(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   CoreSession *arg1 = (CoreSession *) 0 ;
@@ -3536,6 +3472,59 @@
 }
 
 
+SWIGINTERN PyObject *_wrap_CoreSession_flags_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  CoreSession *arg1 = (CoreSession *) 0 ;
+  unsigned int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  unsigned int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:CoreSession_flags_set",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CoreSession, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CoreSession_flags_set" "', argument " "1"" of type '" "CoreSession *""'"); 
+  }
+  arg1 = reinterpret_cast< CoreSession * >(argp1);
+  ecode2 = SWIG_AsVal_unsigned_SS_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "CoreSession_flags_set" "', argument " "2"" of type '" "unsigned int""'");
+  } 
+  arg2 = static_cast< unsigned int >(val2);
+  if (arg1) (arg1)->flags = arg2;
+  
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_CoreSession_flags_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  CoreSession *arg1 = (CoreSession *) 0 ;
+  unsigned int result;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:CoreSession_flags_get",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CoreSession, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CoreSession_flags_get" "', argument " "1"" of type '" "CoreSession *""'"); 
+  }
+  arg1 = reinterpret_cast< CoreSession * >(argp1);
+  result = (unsigned int) ((arg1)->flags);
+  resultobj = SWIG_From_unsigned_SS_int(static_cast< unsigned int >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_CoreSession_cb_state_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   CoreSession *arg1 = (CoreSession *) 0 ;
@@ -3589,6 +3578,67 @@
 }
 
 
+SWIGINTERN PyObject *_wrap_CoreSession_hook_state_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  CoreSession *arg1 = (CoreSession *) 0 ;
+  switch_channel_state_t arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 ;
+  int res2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:CoreSession_hook_state_set",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CoreSession, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CoreSession_hook_state_set" "', argument " "1"" of type '" "CoreSession *""'"); 
+  }
+  arg1 = reinterpret_cast< CoreSession * >(argp1);
+  {
+    res2 = SWIG_ConvertPtr(obj1, &argp2, SWIGTYPE_p_switch_channel_state_t,  0  | 0);
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "CoreSession_hook_state_set" "', argument " "2"" of type '" "switch_channel_state_t""'"); 
+    }  
+    if (!argp2) {
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "CoreSession_hook_state_set" "', argument " "2"" of type '" "switch_channel_state_t""'");
+    } else {
+      switch_channel_state_t * temp = reinterpret_cast< switch_channel_state_t * >(argp2);
+      arg2 = *temp;
+      if (SWIG_IsNewObj(res2)) delete temp;
+    }
+  }
+  if (arg1) (arg1)->hook_state = arg2;
+  
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_CoreSession_hook_state_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  CoreSession *arg1 = (CoreSession *) 0 ;
+  switch_channel_state_t result;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:CoreSession_hook_state_get",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CoreSession, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CoreSession_hook_state_get" "', argument " "1"" of type '" "CoreSession *""'"); 
+  }
+  arg1 = reinterpret_cast< CoreSession * >(argp1);
+  result =  ((arg1)->hook_state);
+  resultobj = SWIG_NewPointerObj((new switch_channel_state_t(static_cast< const switch_channel_state_t& >(result))), SWIGTYPE_p_switch_channel_state_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_CoreSession_answer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   CoreSession *arg1 = (CoreSession *) 0 ;
@@ -3960,61 +4010,39 @@
 SWIGINTERN PyObject *_wrap_CoreSession_setDTMFCallback(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   CoreSession *arg1 = (CoreSession *) 0 ;
-  switch_input_callback_function_t arg2 ;
-  void *arg3 = (void *) 0 ;
-  uint32_t arg4 ;
+  void *arg2 = (void *) 0 ;
+  char *arg3 = (char *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  void *argp2 ;
-  int res2 = 0 ;
+  int res2 ;
   int res3 ;
-  void *argp4 ;
-  int res4 = 0 ;
+  char *buf3 = 0 ;
+  int alloc3 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   PyObject * obj2 = 0 ;
-  PyObject * obj3 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOO:CoreSession_setDTMFCallback",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOO:CoreSession_setDTMFCallback",&obj0,&obj1,&obj2)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CoreSession, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CoreSession_setDTMFCallback" "', argument " "1"" of type '" "CoreSession *""'"); 
   }
   arg1 = reinterpret_cast< CoreSession * >(argp1);
-  {
-    res2 = SWIG_ConvertPtr(obj1, &argp2, SWIGTYPE_p_switch_input_callback_function_t,  0  | 0);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "CoreSession_setDTMFCallback" "', argument " "2"" of type '" "switch_input_callback_function_t""'"); 
-    }  
-    if (!argp2) {
-      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "CoreSession_setDTMFCallback" "', argument " "2"" of type '" "switch_input_callback_function_t""'");
-    } else {
-      switch_input_callback_function_t * temp = reinterpret_cast< switch_input_callback_function_t * >(argp2);
-      arg2 = *temp;
-      if (SWIG_IsNewObj(res2)) delete temp;
-    }
+  res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2), 0, 0);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "CoreSession_setDTMFCallback" "', argument " "2"" of type '" "void *""'"); 
   }
-  res3 = SWIG_ConvertPtr(obj2,SWIG_as_voidptrptr(&arg3), 0, 0);
+  res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
   if (!SWIG_IsOK(res3)) {
-    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "CoreSession_setDTMFCallback" "', argument " "3"" of type '" "void *""'"); 
-  }
-  {
-    res4 = SWIG_ConvertPtr(obj3, &argp4, SWIGTYPE_p_uint32_t,  0  | 0);
-    if (!SWIG_IsOK(res4)) {
-      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "CoreSession_setDTMFCallback" "', argument " "4"" of type '" "uint32_t""'"); 
-    }  
-    if (!argp4) {
-      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "CoreSession_setDTMFCallback" "', argument " "4"" of type '" "uint32_t""'");
-    } else {
-      uint32_t * temp = reinterpret_cast< uint32_t * >(argp4);
-      arg4 = *temp;
-      if (SWIG_IsNewObj(res4)) delete temp;
-    }
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "CoreSession_setDTMFCallback" "', argument " "3"" of type '" "char *""'");
   }
-  (arg1)->setDTMFCallback(arg2,arg3,arg4);
+  arg3 = reinterpret_cast< char * >(buf3);
+  (arg1)->setDTMFCallback(arg2,arg3);
   resultobj = SWIG_Py_Void();
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
   return resultobj;
 fail:
+  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
   return NULL;
 }
 
@@ -4103,9 +4131,10 @@
   CoreSession *arg1 = (CoreSession *) 0 ;
   char *arg2 = (char *) 0 ;
   int arg3 ;
-  char *arg4 = (char *) 0 ;
+  int arg4 ;
   char *arg5 = (char *) 0 ;
-  int arg6 ;
+  char *arg6 = (char *) 0 ;
+  int arg7 ;
   int result;
   void *argp1 = 0 ;
   int res1 = 0 ;
@@ -4116,24 +4145,27 @@
   int alloc2 = 0 ;
   int val3 ;
   int ecode3 = 0 ;
-  int res4 ;
-  char *buf4 = 0 ;
-  int alloc4 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
   int res5 ;
-  char temp5[8+1] ;
-  char *t5 = 0 ;
-  size_t n5 = 0 ;
+  char *buf5 = 0 ;
   int alloc5 = 0 ;
-  int val6 ;
-  int ecode6 = 0 ;
+  int res6 ;
+  char temp6[8+1] ;
+  char *t6 = 0 ;
+  size_t n6 = 0 ;
+  int alloc6 = 0 ;
+  int val7 ;
+  int ecode7 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   PyObject * obj2 = 0 ;
   PyObject * obj3 = 0 ;
   PyObject * obj4 = 0 ;
   PyObject * obj5 = 0 ;
+  PyObject * obj6 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOOOO:CoreSession_getDigits",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOOOO:CoreSession_getDigits",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CoreSession, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CoreSession_getDigits" "', argument " "1"" of type '" "CoreSession *""'"); 
@@ -4153,35 +4185,40 @@
     SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "CoreSession_getDigits" "', argument " "3"" of type '" "int""'");
   } 
   arg3 = static_cast< int >(val3);
-  res4 = SWIG_AsCharPtrAndSize(obj3, &buf4, NULL, &alloc4);
-  if (!SWIG_IsOK(res4)) {
-    SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "CoreSession_getDigits" "', argument " "4"" of type '" "char *""'");
-  }
-  arg4 = reinterpret_cast< char * >(buf4);
-  res5 = SWIG_AsCharPtrAndSize(obj4, &t5, &n5, &alloc5);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "CoreSession_getDigits" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = static_cast< int >(val4);
+  res5 = SWIG_AsCharPtrAndSize(obj4, &buf5, NULL, &alloc5);
   if (!SWIG_IsOK(res5)) {
-    SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "CoreSession_getDigits" "', argument " "5"" of type '" "char *terminator""'");
+    SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "CoreSession_getDigits" "', argument " "5"" of type '" "char *""'");
+  }
+  arg5 = reinterpret_cast< char * >(buf5);
+  res6 = SWIG_AsCharPtrAndSize(obj5, &t6, &n6, &alloc6);
+  if (!SWIG_IsOK(res6)) {
+    SWIG_exception_fail(SWIG_ArgError(res6), "in method '" "CoreSession_getDigits" "', argument " "6"" of type '" "char *terminator""'");
   }
-  if ( n5 > (size_t) 8 ) n5 = (size_t) 8;
-  memcpy(temp5, t5, sizeof(char)*n5);
-  if (alloc5 == SWIG_NEWOBJ) delete[] t5;
-  temp5[n5 - 1] = 0;                                                             
-  arg5 = (char *) temp5;
-  ecode6 = SWIG_AsVal_int(obj5, &val6);
-  if (!SWIG_IsOK(ecode6)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "CoreSession_getDigits" "', argument " "6"" of type '" "int""'");
+  if ( n6 > (size_t) 8 ) n6 = (size_t) 8;
+  memcpy(temp6, t6, sizeof(char)*n6);
+  if (alloc6 == SWIG_NEWOBJ) delete[] t6;
+  temp6[n6 - 1] = 0;                                                             
+  arg6 = (char *) temp6;
+  ecode7 = SWIG_AsVal_int(obj6, &val7);
+  if (!SWIG_IsOK(ecode7)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "CoreSession_getDigits" "', argument " "7"" of type '" "int""'");
   } 
-  arg6 = static_cast< int >(val6);
-  result = (int)(arg1)->getDigits(arg2,arg3,arg4,arg5,arg6);
+  arg7 = static_cast< int >(val7);
+  result = (int)(arg1)->getDigits(arg2,arg3,arg4,arg5,arg6,arg7);
   resultobj = SWIG_From_int(static_cast< int >(result));
   arg2[128] = 0;
   resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg2));
-  arg5[8] = 0;
-  resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg5));
-  if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
+  arg6[8] = 0;
+  resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_FromCharPtr(arg6));
+  if (alloc5 == SWIG_NEWOBJ) delete[] buf5;
   return resultobj;
 fail:
-  if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
+  if (alloc5 == SWIG_NEWOBJ) delete[] buf5;
   return NULL;
 }
 
@@ -4411,6 +4448,109 @@
 }
 
 
+SWIGINTERN PyObject *_wrap_CoreSession_flushEvents(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  CoreSession *arg1 = (CoreSession *) 0 ;
+  int result;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:CoreSession_flushEvents",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CoreSession, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CoreSession_flushEvents" "', argument " "1"" of type '" "CoreSession *""'"); 
+  }
+  arg1 = reinterpret_cast< CoreSession * >(argp1);
+  result = (int)(arg1)->flushEvents();
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_CoreSession_flushDigits(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  CoreSession *arg1 = (CoreSession *) 0 ;
+  int result;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:CoreSession_flushDigits",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CoreSession, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CoreSession_flushDigits" "', argument " "1"" of type '" "CoreSession *""'"); 
+  }
+  arg1 = reinterpret_cast< CoreSession * >(argp1);
+  result = (int)(arg1)->flushDigits();
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_CoreSession_setAutoHangup(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  CoreSession *arg1 = (CoreSession *) 0 ;
+  bool arg2 ;
+  int result;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  bool val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:CoreSession_setAutoHangup",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CoreSession, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CoreSession_setAutoHangup" "', argument " "1"" of type '" "CoreSession *""'"); 
+  }
+  arg1 = reinterpret_cast< CoreSession * >(argp1);
+  ecode2 = SWIG_AsVal_bool(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "CoreSession_setAutoHangup" "', argument " "2"" of type '" "bool""'");
+  } 
+  arg2 = static_cast< bool >(val2);
+  result = (int)(arg1)->setAutoHangup(arg2);
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_CoreSession_setHangupHook(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  CoreSession *arg1 = (CoreSession *) 0 ;
+  void *arg2 = (void *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:CoreSession_setHangupHook",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CoreSession, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CoreSession_setHangupHook" "', argument " "1"" of type '" "CoreSession *""'"); 
+  }
+  arg1 = reinterpret_cast< CoreSession * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2), 0, 0);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "CoreSession_setHangupHook" "', argument " "2"" of type '" "void *""'"); 
+  }
+  (arg1)->setHangupHook(arg2);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_CoreSession_ready(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   CoreSession *arg1 = (CoreSession *) 0 ;
@@ -4481,6 +4621,7 @@
 SWIGINTERN PyObject *_wrap_CoreSession_begin_allow_threads(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   CoreSession *arg1 = (CoreSession *) 0 ;
+  bool result;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
@@ -4491,8 +4632,8 @@
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CoreSession_begin_allow_threads" "', argument " "1"" of type '" "CoreSession *""'"); 
   }
   arg1 = reinterpret_cast< CoreSession * >(argp1);
-  (arg1)->begin_allow_threads();
-  resultobj = SWIG_Py_Void();
+  result = (bool)(arg1)->begin_allow_threads();
+  resultobj = SWIG_From_bool(static_cast< bool >(result));
   return resultobj;
 fail:
   return NULL;
@@ -4502,6 +4643,7 @@
 SWIGINTERN PyObject *_wrap_CoreSession_end_allow_threads(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   CoreSession *arg1 = (CoreSession *) 0 ;
+  bool result;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
@@ -4512,8 +4654,8 @@
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CoreSession_end_allow_threads" "', argument " "1"" of type '" "CoreSession *""'"); 
   }
   arg1 = reinterpret_cast< CoreSession * >(argp1);
-  (arg1)->end_allow_threads();
-  resultobj = SWIG_Py_Void();
+  result = (bool)(arg1)->end_allow_threads();
+  resultobj = SWIG_From_bool(static_cast< bool >(result));
   return resultobj;
 fail:
   return NULL;
@@ -4567,6 +4709,73 @@
 }
 
 
+SWIGINTERN PyObject *_wrap_CoreSession_check_hangup_hook(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  CoreSession *arg1 = (CoreSession *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:CoreSession_check_hangup_hook",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CoreSession, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CoreSession_check_hangup_hook" "', argument " "1"" of type '" "CoreSession *""'"); 
+  }
+  arg1 = reinterpret_cast< CoreSession * >(argp1);
+  (arg1)->check_hangup_hook();
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_CoreSession_run_dtmf_callback(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  CoreSession *arg1 = (CoreSession *) 0 ;
+  void *arg2 = (void *) 0 ;
+  switch_input_type_t arg3 ;
+  switch_status_t result;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  void *argp3 ;
+  int res3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO:CoreSession_run_dtmf_callback",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_CoreSession, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CoreSession_run_dtmf_callback" "', argument " "1"" of type '" "CoreSession *""'"); 
+  }
+  arg1 = reinterpret_cast< CoreSession * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2), 0, 0);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "CoreSession_run_dtmf_callback" "', argument " "2"" of type '" "void *""'"); 
+  }
+  {
+    res3 = SWIG_ConvertPtr(obj2, &argp3, SWIGTYPE_p_switch_input_type_t,  0  | 0);
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "CoreSession_run_dtmf_callback" "', argument " "3"" of type '" "switch_input_type_t""'"); 
+    }  
+    if (!argp3) {
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "CoreSession_run_dtmf_callback" "', argument " "3"" of type '" "switch_input_type_t""'");
+    } else {
+      switch_input_type_t * temp = reinterpret_cast< switch_input_type_t * >(argp3);
+      arg3 = *temp;
+      if (SWIG_IsNewObj(res3)) delete temp;
+    }
+  }
+  result = (arg1)->run_dtmf_callback(arg2,arg3);
+  resultobj = SWIG_NewPointerObj((new switch_status_t(static_cast< const switch_status_t& >(result))), SWIGTYPE_p_switch_status_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *CoreSession_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *obj;
   if (!PyArg_ParseTuple(args,(char*)"O|swigregister", &obj)) return NULL;
@@ -4610,9 +4819,31 @@
 }
 
 
-SWIGINTERN PyObject *_wrap_PythonDTMFCallback(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_hanguphook(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  switch_core_session_t *arg1 = (switch_core_session_t *) 0 ;
+  switch_status_t result;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:hanguphook",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_switch_core_session_t, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "hanguphook" "', argument " "1"" of type '" "switch_core_session_t *""'"); 
+  }
+  arg1 = reinterpret_cast< switch_core_session_t * >(argp1);
+  result = hanguphook(arg1);
+  resultobj = SWIG_NewPointerObj((new switch_status_t(static_cast< const switch_status_t& >(result))), SWIGTYPE_p_switch_status_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_dtmf_callback(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
-  switch_core_session *arg1 = (switch_core_session *) 0 ;
+  switch_core_session_t *arg1 = (switch_core_session_t *) 0 ;
   void *arg2 = (void *) 0 ;
   switch_input_type_t arg3 ;
   void *arg4 = (void *) 0 ;
@@ -4632,23 +4863,23 @@
   PyObject * obj3 = 0 ;
   PyObject * obj4 = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOOO:PythonDTMFCallback",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_switch_core_session, 0 |  0 );
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO:dtmf_callback",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_switch_core_session_t, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "PythonDTMFCallback" "', argument " "1"" of type '" "switch_core_session *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "dtmf_callback" "', argument " "1"" of type '" "switch_core_session_t *""'"); 
   }
-  arg1 = reinterpret_cast< switch_core_session * >(argp1);
+  arg1 = reinterpret_cast< switch_core_session_t * >(argp1);
   res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2), 0, 0);
   if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "PythonDTMFCallback" "', argument " "2"" of type '" "void *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "dtmf_callback" "', argument " "2"" of type '" "void *""'"); 
   }
   {
     res3 = SWIG_ConvertPtr(obj2, &argp3, SWIGTYPE_p_switch_input_type_t,  0  | 0);
     if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "PythonDTMFCallback" "', argument " "3"" of type '" "switch_input_type_t""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "dtmf_callback" "', argument " "3"" of type '" "switch_input_type_t""'"); 
     }  
     if (!argp3) {
-      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "PythonDTMFCallback" "', argument " "3"" of type '" "switch_input_type_t""'");
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "dtmf_callback" "', argument " "3"" of type '" "switch_input_type_t""'");
     } else {
       switch_input_type_t * temp = reinterpret_cast< switch_input_type_t * >(argp3);
       arg3 = *temp;
@@ -4657,14 +4888,14 @@
   }
   res4 = SWIG_ConvertPtr(obj3,SWIG_as_voidptrptr(&arg4), 0, 0);
   if (!SWIG_IsOK(res4)) {
-    SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "PythonDTMFCallback" "', argument " "4"" of type '" "void *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "dtmf_callback" "', argument " "4"" of type '" "void *""'"); 
   }
   ecode5 = SWIG_AsVal_unsigned_SS_int(obj4, &val5);
   if (!SWIG_IsOK(ecode5)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "PythonDTMFCallback" "', argument " "5"" of type '" "unsigned int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "dtmf_callback" "', argument " "5"" of type '" "unsigned int""'");
   } 
   arg5 = static_cast< unsigned int >(val5);
-  result = PythonDTMFCallback(arg1,arg2,arg3,arg4,arg5);
+  result = dtmf_callback(arg1,arg2,arg3,arg4,arg5);
   resultobj = SWIG_NewPointerObj((new switch_status_t(static_cast< const switch_status_t& >(result))), SWIGTYPE_p_switch_status_t, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
@@ -4827,9 +5058,88 @@
 }
 
 
+SWIGINTERN PyObject *_wrap_PySession_setHangupHook(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  PySession *arg1 = (PySession *) 0 ;
+  PyObject *arg2 = (PyObject *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:PySession_setHangupHook",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_PySession, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "PySession_setHangupHook" "', argument " "1"" of type '" "PySession *""'"); 
+  }
+  arg1 = reinterpret_cast< PySession * >(argp1);
+  arg2 = obj1;
+  (arg1)->setHangupHook(arg2);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_PySession_check_hangup_hook(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  PySession *arg1 = (PySession *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:PySession_check_hangup_hook",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_PySession, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "PySession_check_hangup_hook" "', argument " "1"" of type '" "PySession *""'"); 
+  }
+  arg1 = reinterpret_cast< PySession * >(argp1);
+  (arg1)->check_hangup_hook();
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_PySession_hangup(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  PySession *arg1 = (PySession *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:PySession_hangup",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_PySession, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "PySession_hangup" "', argument " "1"" of type '" "PySession *""'"); 
+  }
+  arg1 = reinterpret_cast< PySession * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "PySession_hangup" "', argument " "2"" of type '" "char *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  (arg1)->hangup(arg2);
+  resultobj = SWIG_Py_Void();
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_PySession_begin_allow_threads(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   PySession *arg1 = (PySession *) 0 ;
+  bool result;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
@@ -4840,8 +5150,8 @@
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "PySession_begin_allow_threads" "', argument " "1"" of type '" "PySession *""'"); 
   }
   arg1 = reinterpret_cast< PySession * >(argp1);
-  (arg1)->begin_allow_threads();
-  resultobj = SWIG_Py_Void();
+  result = (bool)(arg1)->begin_allow_threads();
+  resultobj = SWIG_From_bool(static_cast< bool >(result));
   return resultobj;
 fail:
   return NULL;
@@ -4851,6 +5161,7 @@
 SWIGINTERN PyObject *_wrap_PySession_end_allow_threads(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   PySession *arg1 = (PySession *) 0 ;
+  bool result;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject * obj0 = 0 ;
@@ -4861,8 +5172,54 @@
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "PySession_end_allow_threads" "', argument " "1"" of type '" "PySession *""'"); 
   }
   arg1 = reinterpret_cast< PySession * >(argp1);
-  (arg1)->end_allow_threads();
-  resultobj = SWIG_Py_Void();
+  result = (bool)(arg1)->end_allow_threads();
+  resultobj = SWIG_From_bool(static_cast< bool >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_PySession_run_dtmf_callback(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  PySession *arg1 = (PySession *) 0 ;
+  void *arg2 = (void *) 0 ;
+  switch_input_type_t arg3 ;
+  switch_status_t result;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  void *argp3 ;
+  int res3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO:PySession_run_dtmf_callback",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_PySession, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "PySession_run_dtmf_callback" "', argument " "1"" of type '" "PySession *""'"); 
+  }
+  arg1 = reinterpret_cast< PySession * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2), 0, 0);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "PySession_run_dtmf_callback" "', argument " "2"" of type '" "void *""'"); 
+  }
+  {
+    res3 = SWIG_ConvertPtr(obj2, &argp3, SWIGTYPE_p_switch_input_type_t,  0  | 0);
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "PySession_run_dtmf_callback" "', argument " "3"" of type '" "switch_input_type_t""'"); 
+    }  
+    if (!argp3) {
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "PySession_run_dtmf_callback" "', argument " "3"" of type '" "switch_input_type_t""'");
+    } else {
+      switch_input_type_t * temp = reinterpret_cast< switch_input_type_t * >(argp3);
+      arg3 = *temp;
+      if (SWIG_IsNewObj(res3)) delete temp;
+    }
+  }
+  result = (arg1)->run_dtmf_callback(arg2,arg3);
+  resultobj = SWIG_NewPointerObj((new switch_status_t(static_cast< const switch_status_t& >(result))), SWIGTYPE_p_switch_status_t, SWIG_POINTER_OWN |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -4893,14 +5250,17 @@
 	 { (char *)"new_input_callback_state_t", _wrap_new_input_callback_state_t, METH_VARARGS, NULL},
 	 { (char *)"delete_input_callback_state_t", _wrap_delete_input_callback_state_t, METH_VARARGS, NULL},
 	 { (char *)"input_callback_state_t_swigregister", input_callback_state_t_swigregister, METH_VARARGS, NULL},
-	 { (char *)"new_CoreSession", _wrap_new_CoreSession, METH_VARARGS, NULL},
 	 { (char *)"delete_CoreSession", _wrap_delete_CoreSession, METH_VARARGS, NULL},
 	 { (char *)"CoreSession_session_set", _wrap_CoreSession_session_set, METH_VARARGS, NULL},
 	 { (char *)"CoreSession_session_get", _wrap_CoreSession_session_get, METH_VARARGS, NULL},
 	 { (char *)"CoreSession_channel_set", _wrap_CoreSession_channel_set, METH_VARARGS, NULL},
 	 { (char *)"CoreSession_channel_get", _wrap_CoreSession_channel_get, METH_VARARGS, NULL},
+	 { (char *)"CoreSession_flags_set", _wrap_CoreSession_flags_set, METH_VARARGS, NULL},
+	 { (char *)"CoreSession_flags_get", _wrap_CoreSession_flags_get, METH_VARARGS, NULL},
 	 { (char *)"CoreSession_cb_state_set", _wrap_CoreSession_cb_state_set, METH_VARARGS, NULL},
 	 { (char *)"CoreSession_cb_state_get", _wrap_CoreSession_cb_state_get, METH_VARARGS, NULL},
+	 { (char *)"CoreSession_hook_state_set", _wrap_CoreSession_hook_state_set, METH_VARARGS, NULL},
+	 { (char *)"CoreSession_hook_state_get", _wrap_CoreSession_hook_state_get, METH_VARARGS, NULL},
 	 { (char *)"CoreSession_answer", _wrap_CoreSession_answer, METH_VARARGS, NULL},
 	 { (char *)"CoreSession_preAnswer", _wrap_CoreSession_preAnswer, METH_VARARGS, NULL},
 	 { (char *)"CoreSession_hangup", _wrap_CoreSession_hangup, METH_VARARGS, NULL},
@@ -4917,20 +5277,31 @@
 	 { (char *)"CoreSession_transfer", _wrap_CoreSession_transfer, METH_VARARGS, NULL},
 	 { (char *)"CoreSession_playAndGetDigits", _wrap_CoreSession_playAndGetDigits, METH_VARARGS, NULL},
 	 { (char *)"CoreSession_streamfile", _wrap_CoreSession_streamfile, METH_VARARGS, NULL},
+	 { (char *)"CoreSession_flushEvents", _wrap_CoreSession_flushEvents, METH_VARARGS, NULL},
+	 { (char *)"CoreSession_flushDigits", _wrap_CoreSession_flushDigits, METH_VARARGS, NULL},
+	 { (char *)"CoreSession_setAutoHangup", _wrap_CoreSession_setAutoHangup, METH_VARARGS, NULL},
+	 { (char *)"CoreSession_setHangupHook", _wrap_CoreSession_setHangupHook, METH_VARARGS, NULL},
 	 { (char *)"CoreSession_ready", _wrap_CoreSession_ready, METH_VARARGS, NULL},
 	 { (char *)"CoreSession_execute", _wrap_CoreSession_execute, METH_VARARGS, NULL},
 	 { (char *)"CoreSession_begin_allow_threads", _wrap_CoreSession_begin_allow_threads, METH_VARARGS, NULL},
 	 { (char *)"CoreSession_end_allow_threads", _wrap_CoreSession_end_allow_threads, METH_VARARGS, NULL},
 	 { (char *)"CoreSession_get_uuid", _wrap_CoreSession_get_uuid, METH_VARARGS, NULL},
 	 { (char *)"CoreSession_get_cb_args", _wrap_CoreSession_get_cb_args, METH_VARARGS, NULL},
+	 { (char *)"CoreSession_check_hangup_hook", _wrap_CoreSession_check_hangup_hook, METH_VARARGS, NULL},
+	 { (char *)"CoreSession_run_dtmf_callback", _wrap_CoreSession_run_dtmf_callback, METH_VARARGS, NULL},
 	 { (char *)"CoreSession_swigregister", CoreSession_swigregister, METH_VARARGS, NULL},
 	 { (char *)"bridge", _wrap_bridge, METH_VARARGS, NULL},
-	 { (char *)"PythonDTMFCallback", _wrap_PythonDTMFCallback, METH_VARARGS, NULL},
+	 { (char *)"hanguphook", _wrap_hanguphook, METH_VARARGS, NULL},
+	 { (char *)"dtmf_callback", _wrap_dtmf_callback, METH_VARARGS, NULL},
 	 { (char *)"new_PySession", _wrap_new_PySession, METH_VARARGS, NULL},
 	 { (char *)"delete_PySession", _wrap_delete_PySession, METH_VARARGS, NULL},
 	 { (char *)"PySession_setDTMFCallback", _wrap_PySession_setDTMFCallback, METH_VARARGS, NULL},
+	 { (char *)"PySession_setHangupHook", _wrap_PySession_setHangupHook, METH_VARARGS, NULL},
+	 { (char *)"PySession_check_hangup_hook", _wrap_PySession_check_hangup_hook, METH_VARARGS, NULL},
+	 { (char *)"PySession_hangup", _wrap_PySession_hangup, METH_VARARGS, NULL},
 	 { (char *)"PySession_begin_allow_threads", _wrap_PySession_begin_allow_threads, METH_VARARGS, NULL},
 	 { (char *)"PySession_end_allow_threads", _wrap_PySession_end_allow_threads, METH_VARARGS, NULL},
+	 { (char *)"PySession_run_dtmf_callback", _wrap_PySession_run_dtmf_callback, METH_VARARGS, NULL},
 	 { (char *)"PySession_swigregister", PySession_swigregister, METH_VARARGS, NULL},
 	 { NULL, NULL, 0, NULL }
 };
@@ -4945,14 +5316,14 @@
 static swig_type_info _swigt__p_PySession = {"_p_PySession", "PySession *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_char = {"_p_char", "char *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_input_callback_state = {"_p_input_callback_state", "input_callback_state *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_session_flag_t = {"_p_session_flag_t", "enum session_flag_t *|session_flag_t *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_swap_state_t = {"_p_swap_state_t", "enum swap_state_t *|swap_state_t *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_switch_channel_state_t = {"_p_switch_channel_state_t", "switch_channel_state_t *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_switch_channel_t = {"_p_switch_channel_t", "switch_channel_t *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_switch_core_session = {"_p_switch_core_session", "switch_core_session *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_switch_core_session_t = {"_p_switch_core_session_t", "switch_core_session_t *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_switch_input_args_t = {"_p_switch_input_args_t", "switch_input_args_t *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_switch_input_callback_function_t = {"_p_switch_input_callback_function_t", "switch_input_callback_function_t *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_switch_input_type_t = {"_p_switch_input_type_t", "switch_input_type_t *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_switch_status_t = {"_p_switch_status_t", "switch_status_t *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_uint32_t = {"_p_uint32_t", "uint32_t *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_void = {"_p_void", "void *", 0, 0, (void*)0, 0};
 
 static swig_type_info *swig_type_initial[] = {
@@ -4960,14 +5331,14 @@
   &_swigt__p_PySession,
   &_swigt__p_char,
   &_swigt__p_input_callback_state,
+  &_swigt__p_session_flag_t,
+  &_swigt__p_swap_state_t,
+  &_swigt__p_switch_channel_state_t,
   &_swigt__p_switch_channel_t,
-  &_swigt__p_switch_core_session,
   &_swigt__p_switch_core_session_t,
   &_swigt__p_switch_input_args_t,
-  &_swigt__p_switch_input_callback_function_t,
   &_swigt__p_switch_input_type_t,
   &_swigt__p_switch_status_t,
-  &_swigt__p_uint32_t,
   &_swigt__p_void,
 };
 
@@ -4975,14 +5346,14 @@
 static swig_cast_info _swigc__p_PySession[] = {  {&_swigt__p_PySession, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_char[] = {  {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_input_callback_state[] = {  {&_swigt__p_input_callback_state, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_session_flag_t[] = {  {&_swigt__p_session_flag_t, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_swap_state_t[] = {  {&_swigt__p_swap_state_t, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_switch_channel_state_t[] = {  {&_swigt__p_switch_channel_state_t, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_switch_channel_t[] = {  {&_swigt__p_switch_channel_t, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_switch_core_session[] = {  {&_swigt__p_switch_core_session, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_switch_core_session_t[] = {  {&_swigt__p_switch_core_session_t, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_switch_input_args_t[] = {  {&_swigt__p_switch_input_args_t, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_switch_input_callback_function_t[] = {  {&_swigt__p_switch_input_callback_function_t, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_switch_input_type_t[] = {  {&_swigt__p_switch_input_type_t, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_switch_status_t[] = {  {&_swigt__p_switch_status_t, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_uint32_t[] = {  {&_swigt__p_uint32_t, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_void[] = {  {&_swigt__p_void, 0, 0, 0},{0, 0, 0, 0}};
 
 static swig_cast_info *swig_cast_initial[] = {
@@ -4990,14 +5361,14 @@
   _swigc__p_PySession,
   _swigc__p_char,
   _swigc__p_input_callback_state,
+  _swigc__p_session_flag_t,
+  _swigc__p_swap_state_t,
+  _swigc__p_switch_channel_state_t,
   _swigc__p_switch_channel_t,
-  _swigc__p_switch_core_session,
   _swigc__p_switch_core_session_t,
   _swigc__p_switch_input_args_t,
-  _swigc__p_switch_input_callback_function_t,
   _swigc__p_switch_input_type_t,
   _swigc__p_switch_status_t,
-  _swigc__p_uint32_t,
   _swigc__p_void,
 };
 
@@ -5519,5 +5890,10 @@
   SWIG_InstallConstants(d,swig_const_table);
   
   
+  SWIG_Python_SetConstant(d, "S_HUP",SWIG_From_int(static_cast< int >(S_HUP)));
+  SWIG_Python_SetConstant(d, "S_FREE",SWIG_From_int(static_cast< int >(S_FREE)));
+  SWIG_Python_SetConstant(d, "S_RDLOCK",SWIG_From_int(static_cast< int >(S_RDLOCK)));
+  SWIG_Python_SetConstant(d, "S_SWAPPED_IN",SWIG_From_int(static_cast< int >(S_SWAPPED_IN)));
+  SWIG_Python_SetConstant(d, "S_SWAPPED_OUT",SWIG_From_int(static_cast< int >(S_SWAPPED_OUT)));
 }
 

Modified: freeswitch/trunk/src/switch_core_file.c
==============================================================================
--- freeswitch/trunk/src/switch_core_file.c	(original)
+++ freeswitch/trunk/src/switch_core_file.c	Fri Jun 22 15:14:53 2007
@@ -95,6 +95,7 @@
 SWITCH_DECLARE(switch_status_t) switch_core_file_read(switch_file_handle_t *fh, void *data, switch_size_t *len)
 {
 	assert(fh != NULL);
+	assert(fh->file_interface != NULL);
 
 	return fh->file_interface->file_read(fh, data, len);
 }
@@ -102,6 +103,7 @@
 SWITCH_DECLARE(switch_status_t) switch_core_file_write(switch_file_handle_t *fh, void *data, switch_size_t *len)
 {
 	assert(fh != NULL);
+	assert(fh->file_interface != NULL);
 
 	return fh->file_interface->file_write(fh, data, len);
 }
@@ -109,6 +111,7 @@
 SWITCH_DECLARE(switch_status_t) switch_core_file_seek(switch_file_handle_t *fh, unsigned int *cur_pos, int64_t samples, int whence)
 {
 	assert(fh != NULL);
+	assert(fh->file_interface != NULL);
 
 	switch_set_flag(fh, SWITCH_FILE_SEEK);
 	return fh->file_interface->file_seek(fh, cur_pos, samples, whence);
@@ -117,6 +120,7 @@
 SWITCH_DECLARE(switch_status_t) switch_core_file_set_string(switch_file_handle_t *fh, switch_audio_col_t col, const char *string)
 {
 	assert(fh != NULL);
+	assert(fh->file_interface != NULL);
 
 	return fh->file_interface->file_set_string(fh, col, string);
 }
@@ -124,6 +128,7 @@
 SWITCH_DECLARE(switch_status_t) switch_core_file_get_string(switch_file_handle_t *fh, switch_audio_col_t col, const char **string)
 {
 	assert(fh != NULL);
+	assert(fh->file_interface != NULL);
 
 	return fh->file_interface->file_get_string(fh, col, string);
 
@@ -132,6 +137,9 @@
 
 SWITCH_DECLARE(switch_status_t) switch_core_file_close(switch_file_handle_t *fh)
 {
+	assert(fh != NULL);
+	assert(fh->file_interface != NULL);
+
 	switch_clear_flag(fh, SWITCH_FILE_OPEN);
 	return fh->file_interface->file_close(fh);
 

Modified: freeswitch/trunk/src/switch_cpp.cpp
==============================================================================
--- freeswitch/trunk/src/switch_cpp.cpp	(original)
+++ freeswitch/trunk/src/switch_cpp.cpp	Fri Jun 22 15:14:53 2007
@@ -7,7 +7,7 @@
 
 #define sanity_check(x) do { if (!session) { switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "session is not initalized\n"); return x;}} while(0)
 #define sanity_check_noreturn do { if (!session) { switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "session is not initalized\n"); return;}} while(0)
-#define init_vars() do { session = NULL; channel = NULL; uuid = NULL; tts_name = NULL; voice_name = NULL; memset(&args, 0, sizeof(args)); ap = NULL; caller_profile.source = "mod_unknown";  caller_profile.dialplan = ""; caller_profile.context = ""; caller_profile.caller_id_name = ""; caller_profile.caller_id_number = ""; caller_profile.network_addr = ""; caller_profile.ani = ""; caller_profile.aniii = ""; caller_profile.rdnis = "";  caller_profile.username = ""; } while(0)
+#define init_vars() do { session = NULL; channel = NULL; uuid = NULL; tts_name = NULL; voice_name = NULL; memset(&args, 0, sizeof(args)); ap = NULL; caller_profile.source = "mod_unknown";  caller_profile.dialplan = ""; caller_profile.context = ""; caller_profile.caller_id_name = ""; caller_profile.caller_id_number = ""; caller_profile.network_addr = ""; caller_profile.ani = ""; caller_profile.aniii = ""; caller_profile.rdnis = "";  caller_profile.username = ""; on_hangup = NULL; cb_state.function = NULL; } while(0)
 
 
 
@@ -36,8 +36,13 @@
 CoreSession::~CoreSession()
 {
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CoreSession::~CoreSession desctructor");
+	switch_channel_t *channel = NULL;
 
 	if (session) {
+		channel = switch_core_session_get_channel(session);
+		if (channel && switch_test_flag(this, S_HUP)) {
+			switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+		}
 		switch_core_session_rwunlock(session);
 	}
 
@@ -103,30 +108,35 @@
         timer_name = NULL;
     }
 	store_file_handle(&fh);
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "playFile begin_allow_threads\n");
 	begin_allow_threads();
 	status = switch_ivr_play_file(session, &fh, file, ap);
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "playFile end_allow_threads\n");
 	end_allow_threads();
     return status == SWITCH_STATUS_SUCCESS ? 1 : 0;
 
 }
 
-void CoreSession::setDTMFCallback(switch_input_callback_function_t cb, 
-								  void *buf, 
-								  uint32_t buflen)
-{
-	sanity_check_noreturn;
-	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CoreSession::setDTMFCallback.");
-	if (cb) {
-		args.buf = buf;
-		args.buflen = buflen;
-		args.input_callback = cb;
-		ap = &args;
-	} else {
-		memset(&args, 0, sizeof(args));
-		ap = NULL;
-	}
-}
 
+void CoreSession::setDTMFCallback(void *cbfunc, char *funcargs) {
+
+	cb_state.funcargs = funcargs;
+	cb_state.function = cbfunc;
+
+	args.buf = &cb_state; 
+	args.buflen = sizeof(cb_state);  // not sure what this is used for, copy mod_spidermonkey
+
+    switch_channel_set_private(channel, "CoreSession", this);
+        
+	// we cannot set the actual callback to a python function, because
+	// the callback is a function pointer with a specific signature.
+	// so, set it to the following c function which will act as a proxy,
+	// finding the python callback in the args callback args structure
+	args.input_callback = dtmf_callback;  
+	ap = &args;
+
+
+}
 
 int CoreSession::speak(char *text)
 {
@@ -134,6 +144,12 @@
     switch_codec_t *codec;
 
 	sanity_check(-1);
+
+	// create and store an empty filehandle in callback args 
+	// to workaround a bug in the presumptuous process_callback_result()
+    switch_file_handle_t fh = { 0 };
+	store_file_handle(&fh);
+
 	if (!tts_name) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No TTS engine specified");
 		return SWITCH_STATUS_FALSE;
@@ -161,7 +177,8 @@
 }
 
 int CoreSession::getDigits(char *dtmf_buf, 
-						   int len, 
+						   int buflen, 
+						   int maxdigits, 
 						   char *terminators, 
 						   char *terminator, 
 						   int timeout)
@@ -169,13 +186,16 @@
     switch_status_t status;
 	sanity_check(-1);
 	begin_allow_threads();
+
     status = switch_ivr_collect_digits_count(session, 
 											 dtmf_buf,
-											 (uint32_t) len,
-											 (uint32_t) len, 
+											 (uint32_t) buflen,
+											 (uint32_t) maxdigits, 
 											 terminators, 
 											 terminator, 
 											 (uint32_t) timeout);
+
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "getDigits dtmf_buf: %s\n", dtmf_buf);
 	end_allow_threads();
     return status == SWITCH_STATUS_SUCCESS ? 1 : 0;
 }
@@ -213,6 +233,9 @@
 										 bad_input_audio_files, 
 										 dtmf_buf, 128, 
 										 digits_regex);
+
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "playAndGetDigits dtmf_buf: %s\n", dtmf_buf);
+
 	end_allow_threads();
     return status == SWITCH_STATUS_SUCCESS ? 1 : 0;
 }
@@ -318,6 +341,52 @@
 
 }
 
+int CoreSession::flushEvents() 
+{
+	switch_event_t *event;
+	switch_channel_t *channel;
+
+	if (!session) {
+		return SWITCH_STATUS_FALSE;
+	}
+	channel = switch_core_session_get_channel(session);
+	assert(channel != NULL);
+
+	while (switch_core_session_dequeue_event(session, &event) == SWITCH_STATUS_SUCCESS) {
+		switch_event_destroy(&event);
+	}
+	return SWITCH_STATUS_SUCCESS;
+}
+
+int CoreSession::flushDigits() 
+{
+	char buf[256];
+	switch_size_t has;
+	switch_channel_t *channel;
+
+
+	channel = switch_core_session_get_channel(session);
+	assert(channel != NULL);
+
+	while ((has = switch_channel_has_dtmf(channel))) {
+		switch_channel_dequeue_dtmf(channel, buf, sizeof(buf));
+	}
+	return SWITCH_STATUS_SUCCESS;
+}
+
+int CoreSession::setAutoHangup(bool val) 
+{
+	if (!session) {
+		return SWITCH_STATUS_FALSE;
+	}	
+	if (val) {
+		switch_set_flag(this, S_HUP);
+	} else {
+		switch_clear_flag(this, S_HUP);
+	}
+	return SWITCH_STATUS_SUCCESS;
+}
+
 void CoreSession::setCallerData(char *var, char *val) {
 
 	if (strcmp(var, "dialplan") == 0) {
@@ -350,12 +419,17 @@
 
 }
 
-void CoreSession::begin_allow_threads() { 
-    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CoreSession::begin_allow_threads() called and does nothing\n");
-}
+void CoreSession::setHangupHook(void *hangup_func) {
+
+    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CoreSession::seHangupHook, hangup_func: %p\n", hangup_func);
+    on_hangup = hangup_func;
+    switch_channel_t *channel = switch_core_session_get_channel(session);
+    assert(channel != NULL);
+
+    hook_state = switch_channel_get_state(channel);
+    switch_channel_set_private(channel, "CoreSession", this);
+    switch_core_event_hook_add_state_change(session, hanguphook);
 
-void CoreSession::end_allow_threads() { 
-    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CoreSession::end_allow_threads() called and does nothing\n");
 }
 
 /** \brief Store a file handle in the callback args
@@ -424,6 +498,64 @@
 }
 
 
+switch_status_t hanguphook(switch_core_session_t *session_hungup) 
+{
+	switch_channel_t *channel;
+	CoreSession *coresession = NULL;
+	switch_channel_state_t state;
+
+
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "hangup_hook called\n");
+	fflush(stdout);
+
+	channel = switch_core_session_get_channel(session_hungup);
+	assert(channel != NULL);
+
+	state = switch_channel_get_state(channel);
+
+	if ((coresession = (CoreSession *) switch_channel_get_private(channel, "CoreSession"))) {
+		if (coresession->hook_state != state) {
+			coresession->hook_state = state;
+			coresession->check_hangup_hook();
+		}
+	}
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
+
+switch_status_t dtmf_callback(switch_core_session_t *session_cb, 
+							  void *input, 
+							  switch_input_type_t itype, 
+							  void *buf,  
+							  unsigned int buflen) {
+	
+	switch_channel_t *channel;
+	CoreSession *coresession = NULL;
+	switch_status_t result;
+
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "dtmf_callback called\n");
+	fflush(stdout);
+
+	channel = switch_core_session_get_channel(session_cb);
+	assert(channel != NULL);
+
+	coresession = (CoreSession *) switch_channel_get_private(channel, "CoreSession");
+	if (!coresession) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid CoreSession\n");		
+		return SWITCH_STATUS_FALSE;
+	}
+
+	result = coresession->run_dtmf_callback(input, itype);
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "process_callback_result returned\n");
+	if (result) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "process_callback_result returned: %d\n", result);
+	}
+	return result;
+
+}
+
+
 
 switch_status_t process_callback_result(char *ret, 
 					struct input_callback_state *cb_state,
@@ -431,16 +563,40 @@
 {
 	
     switch_file_handle_t *fh = NULL;	   
+
+    if (!cb_state) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Process callback result aborted because cb_state is null\n");
+		return SWITCH_STATUS_FALSE;	
+    }
+
+    if (!cb_state->extra) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Process callback result aborted because cb_state->extra is null\n");
+		return SWITCH_STATUS_FALSE;	
+    }
+
     fh = (switch_file_handle_t *) cb_state->extra;    
 
     if (!fh) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Process callback result aborted because fh is null\n");
+		return SWITCH_STATUS_FALSE;	
+    }
+
+    if (!fh->file_interface) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Process callback result aborted because fh->file_interface is null\n");
 		return SWITCH_STATUS_FALSE;	
     }
 
     if (!ret) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Process callback result aborted because ret is null\n");
+		return SWITCH_STATUS_FALSE;	
+    }
+
+    if (!session) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Process callback result aborted because session is null\n");
 		return SWITCH_STATUS_FALSE;	
     }
 
+
     if (!strncasecmp(ret, "speed", 4)) {
 		char *p;
 
@@ -481,7 +637,7 @@
 		unsigned int pos = 0;
 		char *p;
 		codec = switch_core_session_get_read_codec(session);
-
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "got codec\n");
 		if ((p = strchr(ret, ':'))) {
 			p++;
 			if (*p == '+' || *p == '-') {
@@ -491,14 +647,20 @@
 				}
 				if (step > 0) {
 					samps = step * (codec->implementation->samples_per_second / 1000);
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "going to seek\n");
 					switch_core_file_seek(fh, &pos, samps, SEEK_CUR);
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "done seek\n");
 				} else {
 					samps = step * (codec->implementation->samples_per_second / 1000);
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "going to seek\n");
 					switch_core_file_seek(fh, &pos, fh->pos - samps, SEEK_SET);
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "done seek\n");
 				}
 			} else {
 				samps = atoi(p) * (codec->implementation->samples_per_second / 1000);
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "going to seek\n");
 				switch_core_file_seek(fh, &pos, samps, SEEK_SET);
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "done seek\n");
 			}
 		}
 
@@ -506,9 +668,11 @@
     }
 
     if (!strcmp(ret, "true") || !strcmp(ret, "undefined")) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "return success\n");
 		return SWITCH_STATUS_SUCCESS;
     }
 
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "no match, return false\n");
     return SWITCH_STATUS_FALSE;
 
 



More information about the Freeswitch-svn mailing list