[Freeswitch-branches] [commit] r4788 - in freeswitch/branches/mikej/sofiasip-upgrade: . src src/include src/mod/applications/mod_commands src/mod/applications/mod_conference src/mod/applications/mod_dptools src/mod/applications/mod_ivrtest src/mod/event_handlers/mod_cdr

Freeswitch SVN mikej at freeswitch.org
Thu Mar 29 00:30:19 EDT 2007


Author: mikej
Date: Thu Mar 29 00:30:19 2007
New Revision: 4788

Modified:
   freeswitch/branches/mikej/sofiasip-upgrade/Makefile.am
   freeswitch/branches/mikej/sofiasip-upgrade/configure.in
   freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_am_config.h.in
   freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_core.h
   freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_ivr.h
   freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_platform.h
   freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_types.h
   freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_commands/mod_commands.c
   freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_conference/mod_conference.c
   freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_dptools/mod_dptools.c
   freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_ivrtest/mod_ivrtest.c
   freeswitch/branches/mikej/sofiasip-upgrade/src/mod/event_handlers/mod_cdr/Makefile.am
   freeswitch/branches/mikej/sofiasip-upgrade/src/switch_channel.c
   freeswitch/branches/mikej/sofiasip-upgrade/src/switch_core.c
   freeswitch/branches/mikej/sofiasip-upgrade/src/switch_ivr.c
   freeswitch/branches/mikej/sofiasip-upgrade/src/switch_resample.c

Log:
merged changes from trunk revisions 4781-4787.

Modified: freeswitch/branches/mikej/sofiasip-upgrade/Makefile.am
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/Makefile.am	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/Makefile.am	Thu Mar 29 00:30:19 2007
@@ -80,12 +80,12 @@
 CORE_CFLAGS    += -I$(switch_srcdir)/libs/pcre
 CORE_CFLAGS    += -I$(switch_srcdir)/libs/srtp/include
 CORE_CFLAGS    += -I$(switch_srcdir)/libs/srtp/crypto/include
-CORE_CFLAGS    += -I$(switch_srcdir)/libs/libresample/include
+CORE_CFLAGS    += $(RESAMPLE_CFLAGS)
 CORE_CFLAGS    += -I$(switch_srcdir)/libs/libteletone/src
 
 CORE_LIBS      = libs/apr/libapr-1.la libs/apr-util/libaprutil-1.la
 CORE_LIBS     += libs/sqlite/libsqlite3.la libs/pcre/libpcre.la
-CORE_LIBS     += libs/srtp/libsrtp.la libs/libresample/libresample.la
+CORE_LIBS     += libs/srtp/libsrtp.la $(RESAMPLE_LIB)
 
 lib_LTLIBRARIES	          = libfreeswitch.la
 libfreeswitch_la_CFLAGS   = $(CORE_CFLAGS) $(AM_CFLAGS)
@@ -171,9 +171,11 @@
 	@cd libs/srtp && $(MAKE)
 	@$(TOUCH_TARGET)
 
+if USE_INTREE_RESAMPLE
 libs/libresample/libresample.la: libs/libresample libs/libresample/.update
 	@cd libs/libresample && $(MAKE)
 	@$(TOUCH_TARGET)
+endif
 
 core:  libfreeswitch.la  
 

Modified: freeswitch/branches/mikej/sofiasip-upgrade/configure.in
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/configure.in	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/configure.in	Thu Mar 29 00:30:19 2007
@@ -57,9 +57,29 @@
 
 AM_CONDITIONAL([WANT_DEBUG],[test "${enable_debug}" = "yes"])
 
+# Optional Features
+
+AC_ARG_ENABLE(resample,
+[AC_HELP_STRING([--enable-resample],[build with embedded resamper])],[enable_resample="$enable_resample"],[enable_resample="yes"])
+
+# We should add checking for out of tree libresample here
+RESAMPLE_LIB=
+RESAMPLE_CFLAGS=
+if test "${enable_resample}" = "yes"; then
+       RESAMPLE_LIB="libs/libresample/libresample.la"
+       RESAMPLE_CFLAGS="-I${switch_srcdir}/libs/libresample/include"
+else
+        AC_DEFINE([DISABLE_RESAMPLE],[],[Disable the embedded resampler])
+fi
+
+AC_SUBST(RESAMPLE_LIB)
+AC_SUBST(RESAMPLE_CFLAGS)
+
+AM_CONDITIONAL([USE_INTREE_RESAMPLE],[test "${enable_resample}" = "yes"])
+
 # set defaults for use on all platforms
-SWITCH_AM_CFLAGS="-I${switch_srcdir}/src/include -I${prefix}/include"
-SWITCH_AM_CXXFLAGS="-I${switch_srcdir}/src/include -I${prefix}/include"
+SWITCH_AM_CFLAGS="-I${switch_srcdir}/src/include"
+SWITCH_AM_CXXFLAGS="-I${switch_srcdir}/src/include"
 SWITCH_AM_LDFLAGS="-lm -L/usr/local/lib"
 
 #set SOLINK variable based on compiler and host
@@ -151,6 +171,7 @@
 AC_CHECK_SIZEOF(long, 4)
 AC_CHECK_SIZEOF(short, 2)
 AC_CHECK_SIZEOF(long long, 8)
+AC_CHECK_SIZEOF(time_t, 4)
 AC_TYPE_SIZE_T
 AC_CHECK_TYPE(ssize_t, int)
 
@@ -226,6 +247,16 @@
     size_t_fmt='#error Can not determine the proper size for size_t'
 fi
 
+if test "$ac_cv_sizeof_time_t" = "$ac_cv_sizeof_int"; then
+   time_t_fmt='#define TIME_T_FMT "d"' 
+elif  test "$ac_cv_sizeof_time_t" = "$ac_cv_sizeof_long"; then
+   time_t_fmt='#define TIME_T_FMT "ld"'
+elif  test "$ac_cv_sizeof_time_t" = "$ac_cv_sizeof_long_long"; then
+   time_t_fmt='#define TIME_T_FMT "lld"'
+else
+    time_t_fmt='#error Can not determine the proper format specifier for time_t of size $ac_cv_sizeof_time_t'
+fi
+
 # Basically, we have tried to figure out the correct format strings
 # for SWITCH types which vary between platforms, but we don't always get 
 # it right.  If you find that we don't get it right for your platform, 
@@ -274,8 +305,7 @@
 AC_SUBST(uint64_t_fmt) 
 AC_SUBST(ssize_t_fmt) 
 AC_SUBST(size_t_fmt)
-
-
+AC_SUBST(time_t_fmt)
 
 AC_PATH_PROGS(ZCAT, gunzip gzcat gzip zcat)
 AC_PATH_PROGS(TAR, gtar tar)

Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_am_config.h.in
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_am_config.h.in	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_am_config.h.in	Thu Mar 29 00:30:19 2007
@@ -15,5 +15,6 @@
 @size_t_fmt@
 @int64_t_fmt@
 @uint64_t_fmt@
+ at time_t_fmt@
 
 #endif

Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_core.h
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_core.h	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_core.h	Thu Mar 29 00:30:19 2007
@@ -104,17 +104,68 @@
 struct switch_core_runtime;
 struct switch_core_port_allocator;
 
+struct switch_core_scheduler_task {
+	time_t created;
+	time_t runtime;
+	uint32_t cmd_id;
+	char *group;
+	void *cmd_arg;
+	uint32_t task_id;
+};
+
+
 /*!
   \defgroup core1 Core Library 
   \ingroup FREESWITCH
   \{ 
 */
 
-
 ///\defgroup mb1 Media Bugs
 ///\ingroup core1
 ///\{
 
+
+///\defgroup sched1 Scheduler
+///\ingroup core1
+///\{
+
+
+/*!
+  \brief Schedule a task in the future
+  \param runtime the time in epoch seconds to execute the task.
+  \param func the callback function to execute when the task is executed.
+  \param desc an arbitrary description of the task.
+  \param group a group id tag to link multiple tasks to a single entity.
+  \param cmd_id an arbitrary index number be used in the callback.
+  \param cmd_arg user data to be passed to the callback.
+  \param flags flags to alter behaviour 
+  \return the id of the task
+*/
+SWITCH_DECLARE(uint32_t) switch_core_scheduler_add_task(time_t task_runtime,
+														switch_core_scheduler_func_t func,
+														char *desc,
+														char *group,
+														uint32_t cmd_id,
+														void *cmd_arg,
+														switch_scheduler_flag_t flags);
+
+/*!
+  \brief Delete a scheduled task
+  \param task_id the id of the task
+  \return SWITCH_STATUS_SUCCESS if the task was deleted.
+*/
+SWITCH_DECLARE(switch_status_t) switch_core_scheduler_del_task_id(uint32_t task_id);
+
+/*!
+  \brief Delete a scheduled task based on the group name
+  \param group the group name
+  \return SWITCH_STATUS_SUCCESS if any tasks were deleted
+*/
+SWITCH_DECLARE(switch_status_t) switch_core_scheduler_del_task_group(char *group);
+
+
+///\}
+
 /*!
   \brief Add a media bug to the session
   \param session the session to add the bug to

Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_ivr.h
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_ivr.h	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_ivr.h	Thu Mar 29 00:30:19 2007
@@ -332,6 +332,28 @@
 SWITCH_DECLARE(switch_status_t) switch_ivr_session_transfer(switch_core_session_t *session, char *extension, char *dialplan, char *context);
 
 /*!
+  \brief Transfer an existing session to another location in the future
+  \param runtime the time (int epoch seconds) to transfer the call
+  \param uuid the uuid of the session to transfer
+  \param extension the new extension
+  \param dialplan the new dialplan (OPTIONAL, may be NULL)
+  \param context the new context (OPTIONAL, may be NULL)
+  \return the id of the task
+*/
+SWITCH_DECLARE(uint32_t) switch_ivr_schedule_transfer(time_t runtime, char *uuid, char *extension, char *dialplan, char *context);
+
+
+/*!
+  \brief Hangup an existing session in the future
+  \param runtime the time (int epoch seconds) to transfer the call
+  \param uuid the uuid of the session to hangup
+  \param cause the hanup cause code
+  \param bleg hangup up the B-Leg if possible
+  \return the id of the task
+*/
+SWITCH_DECLARE(uint32_t) switch_ivr_schedule_hangup(time_t runtime, char *uuid, switch_call_cause_t cause, switch_bool_t bleg);
+
+/*!
   \brief Bridge two existing sessions
   \param originator_uuid the uuid of the originator
   \param originatee_uuid the uuid of the originator
@@ -384,6 +406,16 @@
 SWITCH_DECLARE(switch_status_t) switch_ivr_unhold(switch_core_session_t *session);
 
 /*!
+  \brief Signal the session to broadcast audio in the future
+  \param runtime when (in epoch time) to run the broadcast
+  \param uuid the uuid of the session to broadcast on
+  \param path the path data of the broadcast "/path/to/file.wav [<timer name>]" or "speak:<engine>|<voice>|<Text to say>"
+  \param flags flags to send to the request (SMF_ECHO_BRIDGED to send the broadcast to both sides of the call)
+  \return the id of the task
+*/
+SWITCH_DECLARE(uint32_t) switch_ivr_schedule_broadcast(time_t runtime, char *uuid, char *path, switch_media_flag_t flags);
+
+/*!
   \brief Signal the session to broadcast audio
   \param uuid the uuid of the session to broadcast on
   \param path the path data of the broadcast "/path/to/file.wav [<timer name>]" or "speak:<engine>|<voice>|<Text to say>"

Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_platform.h
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_platform.h	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_platform.h	Thu Mar 29 00:30:19 2007
@@ -213,6 +213,12 @@
 #define SWITCH_INT64_T_FMT          "I64d"
 #define SWITCH_UINT64_T_FMT         "I64u"
 
+#ifdef _USE_32BIT_TIME_T
+#define TIME_T_FMT "d"
+#else
+#define TIME_T_FMT SWITCH_INT64_T_FMT
+#endif
+
 #else
 #ifndef SWITCH_SSIZE_T_FMT
 #define SWITCH_SSIZE_T_FMT          (sizeof (switch_ssize_t) == sizeof (long) ? "ld" : sizeof (switch_ssize_t) == sizeof (int) ? "d" : "lld")
@@ -230,6 +236,10 @@
 #define SWITCH_UINT64_T_FMT         (sizeof (long) == 8 ? "lu" : "llu")
 #endif
 
+#ifndef TIME_T_FMT
+#define TIME_T_FMT "ld"
+#endif
+
 #endif
 
 #define SWITCH_TIME_T_FMT SWITCH_INT64_T_FMT

Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_types.h
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_types.h	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/src/include/switch_types.h	Thu Mar 29 00:30:19 2007
@@ -168,6 +168,12 @@
 } switch_management_action_t;
 
 typedef enum {
+	SSHF_NONE = 0,
+	SSHF_OWN_THREAD = (1 << 0),
+	SSHF_FREE_ARG = (1 << 1)
+} switch_scheduler_flag_t;
+
+typedef enum {
 	SMF_NONE = 0,
 	SMF_REBRIDGE = (1 << 0),
 	SMF_ECHO_ALEG = (1 << 1),
@@ -910,7 +916,8 @@
 	SWITCH_CAUSE_LOSE_RACE = 502,
 	SWITCH_CAUSE_MANAGER_REQUEST = 503,
 	SWITCH_CAUSE_BLIND_TRANSFER = 600,
-	SWITCH_CAUSE_ATTENDED_TRANSFER = 601
+	SWITCH_CAUSE_ATTENDED_TRANSFER = 601,
+	SWITCH_CAUSE_ALLOTTED_TIMEOUT = 602
 } switch_call_cause_t;
 
 typedef enum {
@@ -979,6 +986,8 @@
 typedef void (*switch_application_function_t)(switch_core_session_t *, char *);
 typedef void (*switch_event_callback_t)(switch_event_t *);
 typedef switch_caller_extension_t *(*switch_dialplan_hunt_function_t)(switch_core_session_t *, void *);
+typedef struct switch_core_scheduler_task switch_core_scheduler_task_t;
+typedef void (*switch_core_scheduler_func_t)(switch_core_scheduler_task_t *task);
 typedef switch_status_t (*switch_state_handler_t)(switch_core_session_t *);
 typedef switch_status_t (*switch_outgoing_channel_hook_t)(switch_core_session_t *, switch_caller_profile_t *, switch_core_session_t *);
 typedef switch_status_t (*switch_answer_channel_hook_t)(switch_core_session_t *);

Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_commands/mod_commands.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_commands/mod_commands.c	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_commands/mod_commands.c	Thu Mar 29 00:30:19 2007
@@ -51,6 +51,9 @@
 static switch_api_interface_t media_api_interface;
 static switch_api_interface_t hold_api_interface;
 static switch_api_interface_t broadcast_api_interface;
+static switch_api_interface_t sched_broadcast_api_interface;
+static switch_api_interface_t sched_transfer_api_interface;
+static switch_api_interface_t sched_hangup_api_interface;
 
 static switch_status_t status_function(char *cmd, switch_core_session_t *session, switch_stream_handle_t *stream)
 {
@@ -245,6 +248,89 @@
 	return SWITCH_STATUS_SUCCESS;
 }
 
+
+static switch_status_t sched_transfer_function(char *cmd, switch_core_session_t *isession, switch_stream_handle_t *stream)
+{
+	switch_core_session_t *session = NULL;
+	char *argv[6] = {0};
+	int argc = 0;
+
+	if (isession) {
+		return SWITCH_STATUS_FALSE;
+	}
+	
+	argc = switch_separate_string(cmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+
+	if (switch_strlen_zero(cmd) || argc < 2 || argc > 5) {
+		stream->write_function(stream, "USAGE: %s\n", sched_transfer_api_interface.syntax);
+	} else {
+		char *uuid = argv[1];
+		char *dest = argv[2];
+		char *dp = argv[3];
+		char *context = argv[4];
+		time_t when;
+		
+		if (*argv[0] == '+') {
+			when = time (NULL) + atol(argv[0] + 1);
+		} else {
+			when = atol(argv[0]);
+		}
+
+		if ((session = switch_core_session_locate(uuid))) {
+			switch_ivr_schedule_transfer(when, uuid, dest, dp, context);
+			stream->write_function(stream, "OK\n");
+			switch_core_session_rwunlock(session);
+		} else {
+			stream->write_function(stream, "No Such Channel!\n");
+		}
+	}
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t sched_hangup_function(char *cmd, switch_core_session_t *isession, switch_stream_handle_t *stream)
+{
+	switch_core_session_t *session = NULL;
+	char *argv[4] = {0};
+	int argc = 0;
+
+	if (isession) {
+		return SWITCH_STATUS_FALSE;
+	}
+	
+	argc = switch_separate_string(cmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+
+	if (switch_strlen_zero(cmd) || argc < 1) {
+		stream->write_function(stream, "USAGE: %s\n", sched_hangup_api_interface.syntax);
+	} else {
+		char *uuid = argv[1];
+		char *cause_str = argv[2];
+		time_t when;
+		switch_call_cause_t cause = SWITCH_CAUSE_ALLOTTED_TIMEOUT;
+
+		if (*argv[0] == '+') {
+			when = time (NULL) + atol(argv[0] + 1);
+		} else {
+			when = atol(argv[0]);
+		}
+
+		if (cause_str) {
+			cause = switch_channel_str2cause(cause_str);
+		}
+
+		if ((session = switch_core_session_locate(uuid))) {
+			switch_ivr_schedule_hangup(when, uuid, cause, SWITCH_FALSE);
+			stream->write_function(stream, "OK\n");
+			switch_core_session_rwunlock(session);
+		} else {
+			stream->write_function(stream, "No Such Channel!\n");
+		}
+	}
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
+
 static switch_status_t uuid_media_function(char *cmd, switch_core_session_t *isession, switch_stream_handle_t *stream)
 {
 	char *argv[4] = {0};
@@ -313,6 +399,50 @@
 	return SWITCH_STATUS_SUCCESS;
 }
 
+
+static switch_status_t sched_broadcast_function(char *cmd, switch_core_session_t *isession, switch_stream_handle_t *stream)
+{
+	char *argv[4] = {0};
+	int argc = 0;
+	switch_status_t status = SWITCH_STATUS_FALSE;
+
+	if (isession) {
+		return status;
+	}
+	
+	argc = switch_separate_string(cmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+
+	if (switch_strlen_zero(cmd) || argc < 3) {
+		stream->write_function(stream, "USAGE: %s\n", sched_broadcast_api_interface.syntax);
+	} else {
+		switch_media_flag_t flags = SMF_NONE;
+		time_t when;
+
+		if (*argv[0] == '+') {
+			when = time (NULL) + atol(argv[0] + 1);
+		} else {
+			when = atol(argv[0]);
+		}
+
+		if (argv[3]) {
+			if (!strcmp(argv[3], "both")) {
+				flags |= (SMF_ECHO_ALEG | SMF_ECHO_BLEG);
+			} else if (!strcmp(argv[3], "aleg")) {
+				flags |= SMF_ECHO_ALEG;
+			} else if (!strcmp(argv[3], "bleg")) {
+				flags |= SMF_ECHO_BLEG;
+			}
+		} else {
+			flags |= SMF_ECHO_ALEG;
+		}
+		
+		status = switch_ivr_schedule_broadcast(when, argv[1], argv[2], flags);
+		stream->write_function(stream, "+OK Message Scheduled\n");
+	}
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
 static switch_status_t uuid_hold_function(char *cmd, switch_core_session_t *isession, switch_stream_handle_t *stream)
 {
 	char *argv[4] = {0};
@@ -707,12 +837,36 @@
 	return SWITCH_STATUS_SUCCESS;
 }
 
+static switch_api_interface_t sched_transfer_api_interface = {
+	/*.interface_name */ "sched_transfer",
+	/*.desc */ "Schedule a broadcast event to a running call",
+	/*.function */ sched_transfer_function,
+	/*.syntax */ "[+]<time> <uuid> <extension> [<dialplan>] [<context>]",
+	/*.next */ NULL
+};
+
+static switch_api_interface_t sched_broadcast_api_interface = {
+	/*.interface_name */ "sched_broadcast",
+	/*.desc */ "Schedule a broadcast event to a running call",
+	/*.function */ sched_broadcast_function,
+	/*.syntax */ "[+]<time> <uuid> <path> [aleg|bleg|both]",
+	/*.next */ &sched_transfer_api_interface
+};
+
+static switch_api_interface_t sched_hangup_api_interface = {
+	/*.interface_name */ "sched_hangup",
+	/*.desc */ "Schedule a running call to hangup",
+	/*.function */ sched_hangup_function,
+	/*.syntax */ "[+]<time> <uuid> [<cause>]",
+	/*.next */ &sched_broadcast_api_interface
+};
+
 static switch_api_interface_t version_api_interface = {
 	/*.interface_name */ "version",
 	/*.desc */ "Show version of the switch",
 	/*.function */ version_function,
 	/*.syntax */ "",
-	/*.next */ NULL
+	/*.next */ &sched_hangup_api_interface
 };
 
 static switch_api_interface_t help_api_interface = {

Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_conference/mod_conference.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_conference/mod_conference.c	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_conference/mod_conference.c	Thu Mar 29 00:30:19 2007
@@ -4070,12 +4070,15 @@
         switch_audio_resampler_t **resampler = read_codec->implementation->samples_per_second > conference->rate ? 
             &member.read_resampler : &member.mux_resampler;
 
-        switch_resample_create(resampler, 
+        if (switch_resample_create(resampler, 
                                read_codec->implementation->samples_per_second, 
                                read_codec->implementation->samples_per_second * 20, 
                                conference->rate, 
                                conference->rate * 20, 
-                               member.pool);
+							   member.pool) != SWITCH_STATUS_SUCCESS){
+            switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to crete resampler!\n");
+            goto done;
+		}
 
         /* Setup an audio buffer for the resampled audio */
         if (switch_buffer_create_dynamic(&member.resample_buffer, CONF_DBLOCK_SIZE, CONF_DBUFFER_SIZE, CONF_DBUFFER_MAX) != SWITCH_STATUS_SUCCESS) {

Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_dptools/mod_dptools.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_dptools/mod_dptools.c	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_dptools/mod_dptools.c	Thu Mar 29 00:30:19 2007
@@ -96,6 +96,99 @@
 	}
 }
 
+static void sched_transfer_function(switch_core_session_t *session, char *data)
+{
+	int argc;
+	char *argv[4] = {0};
+	char *mydata;
+	
+	if (data && (mydata = switch_core_session_strdup(session, data))) {
+		if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) >= 2) {
+			time_t when;
+
+			if (*argv[0] == '+') {
+				when = time (NULL) + atol(argv[0] + 1);
+			} else {
+				when = atol(argv[0]);
+			}
+
+			switch_ivr_schedule_transfer(when, switch_core_session_get_uuid(session), argv[1], argv[2], argv[3]);
+		} else {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Args\n");
+		}
+	}
+}
+
+static void sched_hangup_function(switch_core_session_t *session, char *data)
+{
+	int argc;
+	char *argv[5] = {0};
+	char *mydata;
+
+	if (data && (mydata = switch_core_session_strdup(session, data))) {
+		if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) >= 1) {
+			time_t when;
+			switch_call_cause_t cause = SWITCH_CAUSE_ALLOTTED_TIMEOUT;
+			switch_bool_t bleg = SWITCH_FALSE;
+
+			if (*argv[0] == '+') {
+				when = time (NULL) + atol(argv[0] + 1);
+			} else {
+				when = atol(argv[0]);
+			}
+			
+			if (argv[1]) {
+				cause = switch_channel_str2cause(argv[1]);
+			}
+
+			if (argv[2] && !strcasecmp(argv[2], "bleg")) {
+				bleg = SWITCH_TRUE;
+			}
+
+			switch_ivr_schedule_hangup(when, switch_core_session_get_uuid(session), cause, bleg);
+		} else {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No time specified.\n");
+		}
+	}
+}
+
+
+static void sched_broadcast_function(switch_core_session_t *session, char *data)
+{
+	int argc;
+	char *argv[6] = {0};
+	char *mydata;
+
+	if (data && (mydata = switch_core_session_strdup(session, data))) {
+		if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) >= 2) {
+			time_t when;
+			switch_media_flag_t flags = SMF_NONE;
+			
+			if (*argv[0] == '+') {
+				when = time (NULL) + atol(argv[0] + 1);
+			} else {
+				when = atol(argv[0]);
+			}
+			
+			if (argv[2]) {
+				if (!strcmp(argv[2], "both")) {
+					flags |= (SMF_ECHO_ALEG | SMF_ECHO_BLEG);
+				} else if (!strcmp(argv[2], "aleg")) {
+					flags |= SMF_ECHO_ALEG;
+				} else if (!strcmp(argv[2], "bleg")) {
+					flags |= SMF_ECHO_BLEG;
+				}
+			} else {
+				flags |= SMF_ECHO_ALEG;
+			}
+
+			switch_ivr_schedule_broadcast(when, switch_core_session_get_uuid(session), argv[1], flags);
+		} else {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Args\n");
+		}
+	}
+}
+
 static void sleep_function(switch_core_session_t *session, char *data)
 {
 
@@ -509,6 +602,7 @@
 	}
 }
 
+
 static switch_api_interface_t strepoch_api_interface = {
 	/*.interface_name */ "strepoch",
 	/*.desc */ "Convert a date string into epoch time",
@@ -541,6 +635,39 @@
 	/*.next */ &dptools_api_interface
 };
 
+
+
+static switch_application_interface_t sched_transfer_application_interface = {
+	/*.interface_name */ "sched_transfer",
+	/*.application_function */ sched_transfer_function,
+	/*.long_desc */ "Schedule a transfer in the future",
+	/*.short_desc */ "Schedule a transfer in the future",
+	/*.syntax */ "[+]<time> <extension> <dialplan> <context>",
+	/* flags */ SAF_SUPPORT_NOMEDIA,
+	/*.next */ NULL
+};
+
+static switch_application_interface_t sched_broadcast_application_interface = {
+	/*.interface_name */ "sched_broadcast",
+	/*.application_function */ sched_broadcast_function,
+	/*.long_desc */ "Schedule a broadcast in the future",
+	/*.short_desc */ "Schedule a broadcast in the future",
+	/*.syntax */ "[+]<time> <path> [aleg|bleg|both]",
+	/* flags */ SAF_SUPPORT_NOMEDIA,
+	/*.next */ &sched_transfer_application_interface
+};
+
+static switch_application_interface_t sched_hangup_application_interface = {
+	/*.interface_name */ "sched_hangup",
+	/*.application_function */ sched_hangup_function,
+	/*.long_desc */ "Schedule a hangup in the future",
+	/*.short_desc */ "Schedule a hangup in the future",
+	/*.syntax */ "[+]<time> [<cause>]",
+	/* flags */ SAF_SUPPORT_NOMEDIA,
+	/*.next */ &sched_broadcast_application_interface
+};
+
+
 static const switch_application_interface_t queuedtmf_application_interface = {
 	/*.interface_name */ "queue_dtmf",
 	/*.application_function */ queue_dtmf_function,	
@@ -548,7 +675,7 @@
 	/* short_desc */ "Queue dtmf to be sent",
 	/* syntax */ "<dtmf_data>",
 	/* flags */ SAF_SUPPORT_NOMEDIA,
-	/*.next */ NULL
+	/*.next */ &sched_hangup_application_interface
 };
 
 static const switch_application_interface_t redirect_application_interface = {

Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_ivrtest/mod_ivrtest.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_ivrtest/mod_ivrtest.c	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/src/mod/applications/mod_ivrtest/mod_ivrtest.c	Thu Mar 29 00:30:19 2007
@@ -233,6 +233,7 @@
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Done\n");
 }
 
+#ifdef BUGTEST
 static switch_bool_t bug_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
 {
     switch_frame_t *frame;
@@ -249,9 +250,11 @@
 
 	return SWITCH_TRUE;
 }
+#endif
 
 static void bugtest_function(switch_core_session_t *session, char *data)
 {
+#ifdef BUGTEST
 	switch_media_bug_t *bug;
 	switch_channel_t *channel = switch_core_session_get_channel(session);
     switch_status_t status;
@@ -264,6 +267,11 @@
 		switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
         return;
 	}
+#endif
+	//switch_ivr_schedule_broadcast(time(NULL) + 10, switch_core_session_get_uuid(session), "/Users/anthm/sr8k.wav", SMF_ECHO_ALEG);
+	//switch_ivr_schedule_transfer(time(NULL) + 10, switch_core_session_get_uuid(session), "2000", NULL, NULL);
+	//switch_ivr_schedule_hangup(time(NULL) + 10, switch_core_session_get_uuid(session), SWITCH_CAUSE_ALLOTTED_TIMEOUT);
+
     switch_ivr_play_file(session, NULL, data, NULL);
 }
 

Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/mod/event_handlers/mod_cdr/Makefile.am
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/src/mod/event_handlers/mod_cdr/Makefile.am	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/src/mod/event_handlers/mod_cdr/Makefile.am	Thu Mar 29 00:30:19 2007
@@ -1,7 +1,16 @@
 #we should set all these vars from configure, no reason to have these in each Makefile.am
-LIBTOOL=`if test -z "$(VERBOSE)" ; then echo $(SHELL) $(switch_builddir)/quiet_libtool ;else echo $(switch_builddir)/libtool;  fi;`
+#LIBTOOL = compile=`echo $<|grep .c`;link=`echo $@|grep .la;echo $@|grep .so;echo $@|grep .dll`; if test -n "$$compile"; then echo Compiling $<;fi; if test -n "$$link"; then echo Creating $@;fi; `if test -z "$(VERBOSE)" ; then echo $(SHELL) $(switch_builddir)/quiet_libtool ;else echo $(switch_builddir)/libtool;  fi;`
+#LIBTOOL=`if test -z "$(VERBOSE)" ; then echo $(SHELL) $(switch_builddir)/quiet_libtool ;else echo $(switch_builddir)/libtool;  fi;`
+LIBTOOL = 	link=`echo $@|grep .la;echo $@|grep .so;echo $@|grep .dll`; \
+		if test -n "$$link"; then echo Creating $@;fi; \
+		`if test -z "$(VERBOSE)" ; \
+		then echo $(SHELL) $(switch_builddir)/quiet_libtool ;\
+		else echo $(switch_builddir)/libtool;  fi;`
+
 AM_MAKEFLAGS=`test -n "$(VERBOSE)" || echo -s`
-LINK_OUTPUT_REDIR=> $(MODNAME).log || error="yes" ; \
+
+# Dirty trick to override the link output
+LIBS+=> $(MODNAME).log || error="yes" ; \
 			if test -n "$(VERBOSE)" -o "$$error" = "yes"; then \
 			  cat $(MODNAME).log ; \
 			fi ;\
@@ -11,8 +20,6 @@
 
 moddir=$(prefix)/mod
 
-
-
 MODNAME=mod_cdr
 mod_LTLIBRARIES = mod_cdr.la
 mod_cdr_la_SOURCES = mod_cdr.cpp cdrcontainer.cpp basecdr.cpp baseregistry.cpp pddcdr.cpp csvcdr.cpp xmlcdr.cpp sqlitecdr.cpp
@@ -30,12 +37,6 @@
 #mod_cdr_la_CFLAGS  += -DSWITCH_QUEUE_ENHANCED
 #mod_cdr_la_LDFLAGS += -lcurl
 
-#Override link target so we can control the output
-
-$(MODNAME).la: $(mod_cdr_la_OBJECTS) $(mod_cdr_la_DEPENDENCIES)
-	@echo Creating $(MODNAME).$(DYNAMIC_LIB_EXTEN)...
-	@$(CXXLINK) -rpath $(moddir) $(mod_cdr_la_LDFLAGS) $(mod_cdr_la_OBJECTS) $(mod_cdr_la_LIBADD) $(LIBS) $(LINK_OUTPUT_REDIR)
-
 #Override the linstall target so we just install the .so/.dylib
 
 install-data-am: $(DESTDIR)$(PREFIX)/$(moddir)/$(MODNAME).$(DYNAMIC_LIB_EXTEN)

Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/switch_channel.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/src/switch_channel.c	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/src/switch_channel.c	Thu Mar 29 00:30:19 2007
@@ -95,6 +95,7 @@
 	{ "MANAGER_REQUEST", SWITCH_CAUSE_MANAGER_REQUEST },
 	{ "BLIND_TRANSFER", SWITCH_CAUSE_BLIND_TRANSFER },
 	{ "ATTENDED_TRANSFER", SWITCH_CAUSE_ATTENDED_TRANSFER },
+	{ "ALLOTTED_TIMEOUT", SWITCH_CAUSE_ALLOTTED_TIMEOUT},
 	{ NULL, 0 }
 };
 

Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/switch_core.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/src/switch_core.c	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/src/switch_core.c	Thu Mar 29 00:30:19 2007
@@ -147,6 +147,19 @@
 
 SWITCH_DECLARE_DATA switch_directories SWITCH_GLOBAL_dirs = {0};
 
+struct switch_core_scheduler_task_container {
+	switch_core_scheduler_task_t task;
+	time_t executed;
+	int in_thread;
+	int destroyed;
+	switch_core_scheduler_func_t func;
+	switch_memory_pool_t *pool;
+	uint32_t flags;
+	char *desc;
+	struct switch_core_scheduler_task_container *next;
+};
+typedef struct switch_core_scheduler_task_container switch_core_scheduler_task_container_t;
+
 struct switch_core_runtime {
 	switch_time_t initiated;
 	uint32_t session_id;
@@ -169,6 +182,10 @@
 	uint32_t shutting_down;
 	uint8_t running;
 	char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
+	switch_core_scheduler_task_container_t *task_list;
+	switch_mutex_t *task_mutex;
+	uint32_t task_id;
+	int task_thread_running;
 };
 
 /* Prototypes */
@@ -196,6 +213,238 @@
 	}
 }
 
+static void send_heartbeat(void)
+{
+	switch_event_t *event;
+	switch_core_time_duration_t duration;
+
+	switch_core_measure_time(switch_core_uptime(), &duration);
+	
+	if (switch_event_create(&event, SWITCH_EVENT_HEARTBEAT) == SWITCH_STATUS_SUCCESS) {
+		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Ready");
+		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Up-Time", 
+								"%u year%s, "
+								"%u day%s, "
+								"%u hour%s, "
+								"%u minute%s, "
+								"%u second%s, "
+								"%u millisecond%s, "
+								"%u microsecond%s\n",
+								duration.yr, duration.yr == 1 ? "" : "s",
+								duration.day, duration.day == 1 ? "" : "s",
+								duration.hr, duration.hr == 1 ? "" : "s",
+								duration.min, duration.min == 1 ? "" : "s",
+								duration.sec, duration.sec == 1 ? "" : "s",
+								duration.ms, duration.ms == 1 ? "" : "s",
+								duration.mms, duration.mms == 1 ? "" : "s"
+								);
+
+		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Count", "%u", switch_core_session_count());
+		switch_event_fire(&event);
+	}
+}
+
+static void heartbeat_callback(switch_core_scheduler_task_t *task)
+{
+	send_heartbeat();
+
+	/* reschedule this task */
+	task->runtime += 20;
+}
+
+static void switch_core_scheduler_execute(switch_core_scheduler_task_container_t *tp)
+{
+	//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Executing task %u %s (%s)\n", tp->task.task_id, tp->desc, switch_str_nil(tp->task.group));
+	
+	tp->func(&tp->task);
+
+	if (tp->task.runtime > tp->executed) {
+		tp->executed = 0;
+	} else {
+		tp->destroyed = 1;
+	}
+}
+
+static void *SWITCH_THREAD_FUNC task_own_thread(switch_thread_t *thread, void *obj)
+{
+	switch_core_scheduler_task_container_t *tp = (switch_core_scheduler_task_container_t *) obj;
+	switch_memory_pool_t *pool;
+
+	pool = tp->pool;
+	tp->pool = NULL;
+	
+	switch_core_scheduler_execute(tp);
+	switch_core_destroy_memory_pool(&pool);
+	tp->in_thread = 0;
+
+	return NULL;
+}
+
+static int task_thread_loop(int done)
+{
+	switch_core_scheduler_task_container_t *tofree, *tp, *last = NULL;
+
+
+	switch_mutex_lock(runtime.task_mutex);
+	for (tp = runtime.task_list; tp; tp = tp->next) {
+		if (done) {
+			tp->destroyed = 1;
+		} else {
+			time_t now = time(NULL);
+			if (now >= tp->task.runtime && !tp->in_thread) {
+				tp->executed = now;
+				if (switch_test_flag(tp, SSHF_OWN_THREAD)) {
+					switch_thread_t *thread;
+					switch_threadattr_t *thd_attr;
+					assert(switch_core_new_memory_pool(&tp->pool) == SWITCH_STATUS_SUCCESS);
+					switch_threadattr_create(&thd_attr, tp->pool);
+					switch_threadattr_detach_set(thd_attr, 1);
+					tp->in_thread = 1;
+					switch_thread_create(&thread, thd_attr, task_own_thread, tp, tp->pool);
+				} else {
+					switch_core_scheduler_execute(tp);
+				}
+			}
+		}
+	}
+	switch_mutex_unlock(runtime.task_mutex);
+	switch_mutex_lock(runtime.task_mutex);
+	for (tp = runtime.task_list; tp; ) {
+		if (tp->destroyed && !tp->in_thread) {
+			tofree = tp;
+			tp = tp->next;
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Deleting task %u %s (%s)\n", 
+							  tofree->task.task_id, tofree->desc, switch_str_nil(tofree->task.group));
+			if (last) {
+				last->next = tofree->next;
+			} else {
+				runtime.task_list = tofree->next;
+			}
+			switch_safe_free(tofree->task.group);
+			if (tofree->task.cmd_arg && switch_test_flag(tofree, SSHF_FREE_ARG)) {
+				free(tofree->task.cmd_arg);
+			}
+			switch_safe_free(tofree->desc);
+			free(tofree);
+		} else {
+			last = tp;
+			tp = tp->next;
+		}
+	}
+	switch_mutex_unlock(runtime.task_mutex);
+
+	return done;
+}
+
+static void *SWITCH_THREAD_FUNC switch_core_task_thread(switch_thread_t *thread, void *obj)
+{
+
+	runtime.task_thread_running = 1;
+
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Starting task thread\n");
+	while(runtime.task_thread_running == 1) {
+		if (task_thread_loop(0)) {
+			break;
+		}
+		switch_yield(500000);
+	}
+
+	task_thread_loop(1);
+
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Task thread ending\n");
+	runtime.task_thread_running = 0;
+	
+	return NULL;
+}
+
+static void switch_core_task_thread_launch(void) 
+{
+	switch_thread_t *thread;
+	switch_threadattr_t *thd_attr;
+	switch_threadattr_create(&thd_attr, runtime.memory_pool);
+	switch_threadattr_detach_set(thd_attr, 1);
+	switch_thread_create(&thread, thd_attr, switch_core_task_thread, NULL, runtime.memory_pool);
+}
+
+SWITCH_DECLARE(uint32_t) switch_core_scheduler_add_task(time_t task_runtime,
+														switch_core_scheduler_func_t func,
+														char *desc,
+														char *group,
+														uint32_t cmd_id,
+														void *cmd_arg,
+														switch_scheduler_flag_t flags)
+{
+	switch_core_scheduler_task_container_t *container, *tp;
+	
+	switch_mutex_lock(runtime.task_mutex);
+	assert((container = malloc(sizeof(*container))));
+	memset(container, 0, sizeof(*container));
+	assert(func);
+	container->func = func;	
+	time(&container->task.created);
+	container->task.runtime = task_runtime;
+	container->task.group = strdup(group ? group : "none");
+	container->task.cmd_id = cmd_id;
+	container->task.cmd_arg = cmd_arg;
+	container->flags = flags;
+	container->desc = strdup(desc ? desc : "none");
+	
+	for (tp = runtime.task_list; tp && tp->next; tp = tp->next);
+
+	if (tp) {
+		tp->next = container;
+	} else {
+		runtime.task_list = container;
+	}
+
+	for (container->task.task_id = 0; !container->task.task_id; container->task.task_id = ++runtime.task_id);
+
+	switch_mutex_unlock(runtime.task_mutex);
+	
+	tp = container;
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Added task %u %s (%s) to run at %"TIME_T_FMT"\n", 
+					  tp->task.task_id, tp->desc, switch_str_nil(tp->task.group), task_runtime);
+
+	
+	return container->task.task_id;
+}
+
+SWITCH_DECLARE(switch_status_t) switch_core_scheduler_del_task_id(uint32_t task_id)
+{
+	switch_core_scheduler_task_container_t *tp;
+	switch_status_t status = SWITCH_STATUS_FALSE;
+	
+	switch_mutex_lock(runtime.task_mutex);
+    for (tp = runtime.task_list; tp; tp = tp->next) {
+		if (tp->task.task_id == task_id) {
+			tp->destroyed++;
+			status = SWITCH_STATUS_SUCCESS;
+			break;
+		}
+	}
+	switch_mutex_unlock(runtime.task_mutex);
+
+	return status;
+}
+
+SWITCH_DECLARE(switch_status_t) switch_core_scheduler_del_task_group(char *group)
+{
+	switch_core_scheduler_task_container_t *tp;
+	switch_status_t status = SWITCH_STATUS_FALSE;
+	
+	switch_mutex_lock(runtime.task_mutex);
+    for (tp = runtime.task_list; tp; tp = tp->next) {
+		if (!strcmp(tp->task.group, group)) {
+			tp->destroyed++;
+			status = SWITCH_STATUS_SUCCESS;
+		}
+	}
+	switch_mutex_unlock(runtime.task_mutex);
+
+	return status;
+}
+
+
 static void switch_core_media_bug_destroy(switch_media_bug_t *bug)
 {
 	switch_buffer_destroy(&bug->raw_read_buffer);
@@ -2148,7 +2397,8 @@
 	}
 
 	if (!session->read_codec && (*frame)->codec) {
-		need_codec = TRUE;
+		status = SWITCH_STATUS_FALSE;
+        goto done;
 	}
 
 	if (session->bugs && !need_codec) {
@@ -2174,11 +2424,15 @@
 			switch (status) {
 			case SWITCH_STATUS_RESAMPLE:
 				if (!session->read_resampler) {
-					switch_resample_create(&session->read_resampler,
+					if (switch_resample_create(&session->read_resampler,
 										   read_frame->codec->implementation->samples_per_second,
 										   read_frame->codec->implementation->bytes_per_frame * 20,
 										   session->read_codec->implementation->samples_per_second,
-										   session->read_codec->implementation->bytes_per_frame * 20, session->pool);
+										   session->read_codec->implementation->bytes_per_frame * 20, session->pool) != SWITCH_STATUS_SUCCESS) {
+						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to allocate resampler\n");
+						status = SWITCH_STATUS_FALSE;
+						goto done;
+					}
 				}
 			case SWITCH_STATUS_SUCCESS:
 				session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t);
@@ -2418,7 +2672,7 @@
 	}
 
 	if (!session->write_codec && frame->codec) {
-		need_codec = TRUE;
+		return SWITCH_STATUS_FALSE;
 	}
 
 	if (session->bugs && !need_codec) {
@@ -2448,6 +2702,9 @@
 													session->write_codec->implementation->samples_per_second,
 													session->write_codec->implementation->bytes_per_frame * 20,
 													session->pool);
+					if (status != SWITCH_STATUS_SUCCESS) {
+						goto done;
+					}
 				}
 				break;
 			case SWITCH_STATUS_SUCCESS:
@@ -2652,6 +2909,9 @@
 																	session->write_codec->implementation->samples_per_second,
 																	session->write_codec->implementation->bytes_per_frame * 20,
 																	session->pool);
+									if (status != SWITCH_STATUS_SUCCESS) {
+										goto done;
+									}
 								}
 								break;
 							case SWITCH_STATUS_SUCCESS:
@@ -3143,11 +3403,10 @@
 	switch_event_t *event;
 	const switch_application_interface_t *application_interface;
 
-
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Standard EXECUTE\n");
+
 	if ((extension = switch_channel_get_caller_extension(session->channel)) == 0) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Extension!\n");
-		switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+		switch_channel_hangup(session->channel, SWITCH_CAUSE_NORMAL_CLEARING);
 		return;
 	}
 
@@ -3721,6 +3980,8 @@
 	switch_event_t *event;
 
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Close Channel %s\n", switch_channel_get_name((*session)->channel));
+	
+	switch_core_scheduler_del_task_group((*session)->uuid_str);
 
 	switch_mutex_lock(runtime.session_table_mutex);
 	switch_core_hash_delete(runtime.session_table, (*session)->uuid_str);
@@ -4133,7 +4394,6 @@
 	char *sqlbuf = (char *) malloc(sql_len);
 	char *sql;
 	switch_size_t newlen;
-	uint32_t loops = 0;
 	
 	if (!runtime.event_db) {
 		runtime.event_db = switch_core_db_handle();
@@ -4188,38 +4448,6 @@
 			*sqlbuf = '\0';
 		}
 
-		if (loops++ >= 5000) {
-			switch_event_t *event;
-			switch_core_time_duration_t duration;
-
-			switch_core_measure_time(switch_core_uptime(), &duration);
-
-			if (switch_event_create(&event, SWITCH_EVENT_HEARTBEAT) == SWITCH_STATUS_SUCCESS) {
-				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Ready");
-				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Up-Time", 
-										"%u year%s, "
-										"%u day%s, "
-										"%u hour%s, "
-										"%u minute%s, "
-										"%u second%s, "
-										"%u millisecond%s, "
-										"%u microsecond%s\n",
-										duration.yr, duration.yr == 1 ? "" : "s",
-										duration.day, duration.day == 1 ? "" : "s",
-										duration.hr, duration.hr == 1 ? "" : "s",
-										duration.min, duration.min == 1 ? "" : "s",
-										duration.sec, duration.sec == 1 ? "" : "s",
-										duration.ms, duration.ms == 1 ? "" : "s",
-										duration.mms, duration.mms == 1 ? "" : "s"
-										);
-
-				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Count", "%u", switch_core_session_count());
-				switch_event_fire(&event);
-			}
-			
-			loops = 0;
-		}
-		
 		if (nothing_in_queue) {
 			switch_yield(1000);
 		}
@@ -4662,11 +4890,17 @@
 	runtime.running = 1;
 	switch_core_hash_init(&runtime.session_table, runtime.memory_pool);
 	switch_mutex_init(&runtime.session_table_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);
+	switch_mutex_init(&runtime.task_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);
 #ifdef CRASH_PROT
 	switch_core_hash_init(&runtime.stack_table, runtime.memory_pool);
 #endif
+
+	
+	switch_core_task_thread_launch();
 	runtime.initiated = switch_time_now();
 
+	switch_core_scheduler_add_task(time(NULL), heartbeat_callback, "heartbeat", "core", 0, NULL, SSHF_NONE); 
+	
 
 	switch_uuid_get(&uuid);
 	switch_uuid_format(runtime.uuid_str, &uuid);
@@ -4826,11 +5060,28 @@
 	while (switch_queue_size(runtime.sql_queue) > 0) {
 		switch_yield(10000);
 	}
+
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Stopping Task Thread\n");
+	if (runtime.task_thread_running == 1) {
+		int sanity = 0;
+		
+		runtime.task_thread_running = -1;
+
+		while(runtime.task_thread_running) {
+			switch_yield(100000);
+			if (++sanity > 10) {
+				break;
+			}
+		}
+	}
+
 	switch_core_db_close(runtime.db);
 	switch_core_db_close(runtime.event_db);
 	switch_xml_destroy();
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Finalizing Shutdown.\n");
 	switch_log_shutdown();
+
+
 	
 	if(runtime.console != stdout && runtime.console != stderr) {
 		fclose(runtime.console);

Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/switch_ivr.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/src/switch_ivr.c	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/src/switch_ivr.c	Thu Mar 29 00:30:19 2007
@@ -130,7 +130,7 @@
         if (cause_name) {
             cause = switch_channel_str2cause(cause_name);
         }
-
+		
         switch_channel_hangup(channel, cause);
     } else if (cmd_hash == CMD_NOMEDIA) {
         char *uuid = switch_event_get_header(event, "nomedia-uuid");
@@ -3240,6 +3240,157 @@
 	return SWITCH_STATUS_SUCCESS;
 }
 
+struct hangup_helper {
+	char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
+	switch_bool_t bleg;
+	switch_call_cause_t cause;
+};
+
+static void sch_hangup_callback(switch_core_scheduler_task_t *task)
+{
+	struct hangup_helper *helper;
+	switch_core_session_t *session, *other_session;
+	char *other_uuid;
+
+	assert(task);
+
+	helper = (struct hangup_helper *) task->cmd_arg;
+	
+	if ((session = switch_core_session_locate(helper->uuid_str))) {
+		switch_channel_t *channel = switch_core_session_get_channel(session);
+
+		if (helper->bleg) {
+			if ((other_uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE)) &&
+				(other_session = switch_core_session_locate(other_uuid))) {
+				switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
+				switch_channel_hangup(other_channel, helper->cause);
+				switch_core_session_rwunlock(other_session);
+			} else {
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No channel to hangup\n");
+			}
+		} else {
+			switch_channel_hangup(channel, helper->cause);
+		}
+
+		switch_core_session_rwunlock(session);
+	}
+}
+
+SWITCH_DECLARE(uint32_t) switch_ivr_schedule_hangup(time_t runtime, char *uuid, switch_call_cause_t cause, switch_bool_t bleg)
+{
+	struct hangup_helper *helper;
+	size_t len = sizeof(*helper);
+
+	assert((helper = malloc(len)));
+	memset(helper, 0, len);
+	
+	switch_copy_string(helper->uuid_str, uuid, sizeof(helper->uuid_str));
+	helper->cause = cause;
+	helper->bleg = bleg;
+	
+	return switch_core_scheduler_add_task(runtime, sch_hangup_callback, (char *)__SWITCH_FUNC__, uuid, 0, helper, SSHF_FREE_ARG); 
+}
+
+struct transfer_helper {
+	char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
+	char *extension;
+	char *dialplan;
+	char *context;
+};
+
+static void sch_transfer_callback(switch_core_scheduler_task_t *task)
+{
+	struct transfer_helper *helper;
+	switch_core_session_t *session;
+
+	assert(task);
+
+	helper = (struct transfer_helper *) task->cmd_arg;
+	
+	if ((session = switch_core_session_locate(helper->uuid_str))) {
+		switch_ivr_session_transfer(session, helper->extension, helper->dialplan, helper->context);
+		switch_core_session_rwunlock(session);
+	}
+
+}
+
+SWITCH_DECLARE(uint32_t) switch_ivr_schedule_transfer(time_t runtime, char *uuid, char *extension, char *dialplan, char *context)
+{
+	struct transfer_helper *helper;
+	size_t len = sizeof(*helper);
+	char *cur = NULL;
+
+	if (extension) {
+		len += strlen(extension) + 1;
+	}
+
+	if (dialplan) {
+		len += strlen(dialplan) + 1;
+	}
+
+	if (context) {
+		len += strlen(context) + 1;
+	}
+
+	assert((helper = malloc(len)));
+	memset(helper, 0, len);
+	
+	switch_copy_string(helper->uuid_str, uuid, sizeof(helper->uuid_str));
+	
+	cur = (char *) helper + sizeof(*helper);
+
+	if (extension) {
+		helper->extension = cur;
+		switch_copy_string(helper->extension, extension, strlen(extension) + 1);
+		cur += strlen(helper->extension) + 1;
+	}
+
+	if (dialplan) {
+		helper->dialplan = cur;
+		switch_copy_string(helper->dialplan, dialplan, strlen(dialplan) + 1);
+		cur += strlen(helper->dialplan) + 1;
+	}
+
+	if (context) {
+		helper->context = cur;
+		switch_copy_string(helper->context, context, strlen(context)+1);
+	}
+	
+	return switch_core_scheduler_add_task(runtime, sch_transfer_callback, (char *)__SWITCH_FUNC__, uuid, 0, helper, SSHF_FREE_ARG); 
+}
+
+
+struct broadcast_helper {
+	char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
+	char *path;
+	switch_media_flag_t flags;
+};
+
+static void sch_broadcast_callback(switch_core_scheduler_task_t *task)
+{
+	struct broadcast_helper *helper;
+	assert(task);
+
+	helper = (struct broadcast_helper *) task->cmd_arg;
+	switch_ivr_broadcast(helper->uuid_str, helper->path, helper->flags);
+}
+
+SWITCH_DECLARE(uint32_t) switch_ivr_schedule_broadcast(time_t runtime, char *uuid, char *path, switch_media_flag_t flags)
+{
+	struct broadcast_helper *helper;
+	size_t len = sizeof(*helper) + strlen(path) + 1;
+
+	assert((helper = malloc(len)));
+	memset(helper, 0, len);
+	
+	switch_copy_string(helper->uuid_str, uuid, sizeof(helper->uuid_str));
+	helper->flags = flags;
+	helper->path = (char *) helper + sizeof(*helper);
+	switch_copy_string(helper->path, path, len - sizeof(helper));
+
+	
+	return switch_core_scheduler_add_task(runtime, sch_broadcast_callback, (char *)__SWITCH_FUNC__, uuid, 0, helper, SSHF_FREE_ARG); 
+}
 
 SWITCH_DECLARE(switch_status_t) switch_ivr_broadcast(char *uuid, char *path, switch_media_flag_t flags)
 {
@@ -3249,9 +3400,15 @@
 	switch_event_t *event;
 	switch_core_session_t *other_session = NULL;
 	char *other_uuid = NULL;
+	char *app = "playback";
+
+	assert(path);
 
 	if ((session = switch_core_session_locate(uuid))) {
-		char *app;
+		char *cause = NULL;
+		char *mypath = strdup(path);
+		char *p;
+		
 		master = session;
 
 		channel = switch_core_session_get_channel(session);
@@ -3261,11 +3418,17 @@
 			switch_ivr_media(uuid, SMF_REBRIDGE);
 		}
 		
-		if (!strncasecmp(path, "speak:", 6)) {
-			path += 6;
-			app = "speak";
-		} else {
-			app = "playback";
+		if ((p = strchr(mypath, ':'))) {
+			app = mypath;
+			*p++ = '\0';
+			path = p;
+		}
+		
+		if ((cause = strchr(app, '!'))) {
+			*cause++ = '\0';
+			if (!cause) {
+				cause = "normal_clearing";
+			}
 		}
 		
 		if ((flags & SMF_ECHO_BLEG) && (other_uuid = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE))
@@ -3299,8 +3462,21 @@
 			}
 		}
 		
+		if (cause) {
+			if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) {
+				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "call-command", "execute");
+				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "execute-app-name", "hangup");
+				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "execute-app-arg", "%s", cause);
+
+				switch_core_session_queue_private_event(session, &event);
+			}
+		}
+
 		switch_core_session_rwunlock(session);
+		switch_safe_free(mypath);
 	}
+
+
 	return SWITCH_STATUS_SUCCESS;
 	
 }
@@ -3449,11 +3625,16 @@
 		switch_channel_set_variable(channel, SWITCH_BRIDGE_VARIABLE, NULL);
 		switch_channel_set_variable(other_channel, SWITCH_BRIDGE_VARIABLE, NULL);
 
-		switch_channel_hangup(other_channel, switch_channel_get_cause(channel));
+		if (switch_channel_get_state(other_channel) < CS_HANGUP && 
+			switch_true(switch_channel_get_variable(other_channel, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE))) {
+			switch_channel_hangup(other_channel, switch_channel_get_cause(channel));
+		} else {
+			switch_channel_set_state(other_channel, CS_EXECUTE);
+		}
 		switch_core_session_rwunlock(other_session);
 	}
 
-
+	
 	return SWITCH_STATUS_SUCCESS;
 }
 

Modified: freeswitch/branches/mikej/sofiasip-upgrade/src/switch_resample.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/src/switch_resample.c	(original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/src/switch_resample.c	Thu Mar 29 00:30:19 2007
@@ -31,7 +31,12 @@
  */
 #include <switch.h>
 #include <switch_resample.h>
+#ifndef WIN32
+#include <switch_private.h>
+#endif
+#ifndef DISABLE_RESAMPLE
 #include <libresample.h>
+#endif
 #define NORMFACT (float)0x8000
 #define MAXSAMPLE (float)0x7FFF
 #define MAXSAMPLEC (char)0x7F
@@ -52,6 +57,10 @@
 													 switch_size_t from_size,
 													 int to_rate, uint32_t to_size, switch_memory_pool_t *pool)
 {
+#ifdef DISABLE_RESAMPLE
+	*new_resampler = NULL;
+	return SWITCH_STATUS_NOTIMPL;
+#else
 	switch_audio_resampler_t *resampler;
 	double lto_rate, lfrom_rate;
 
@@ -75,12 +84,16 @@
 
 	*new_resampler = resampler;
 	return SWITCH_STATUS_SUCCESS;
+#endif
 }
 
 
 SWITCH_DECLARE(uint32_t) switch_resample_process(switch_audio_resampler_t *resampler, float *src, int srclen, float *dst,
 											uint32_t dstlen, int last)
 {
+#ifdef DISABLE_RESAMPLE
+	return 0;
+#else
 	int o = 0, srcused = 0, srcpos = 0, out = 0;
 
 	for (;;) {
@@ -99,11 +112,14 @@
 		}
 	}
 	return out;
+#endif
 }
 
 SWITCH_DECLARE(void) switch_resample_destroy(switch_audio_resampler_t *resampler)
 {
+#ifndef DISABLE_RESAMPLE
 	resample_close(resampler->resampler);
+#endif
 }
 
 



More information about the Freeswitch-branches mailing list