[Freeswitch-trunk] [commit] r6453 - in freeswitch/trunk: libs/xmlrpc-c libs/xmlrpc-c/include/xmlrpc-c libs/xmlrpc-c/lib/abyss/src src src/include src/mod/applications/mod_dptools src/mod/applications/mod_voicemail src/mod/formats/mod_shout src/mod/xml_int/mod_xml_rpc

Freeswitch SVN anthm at freeswitch.org
Fri Nov 30 17:56:02 EST 2007


Author: anthm
Date: Fri Nov 30 17:56:01 2007
New Revision: 6453

Modified:
   freeswitch/trunk/libs/xmlrpc-c/.update
   freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/abyss.h
   freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/server.c
   freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/thread.c
   freeswitch/trunk/src/include/switch_buffer.h
   freeswitch/trunk/src/include/switch_ivr.h
   freeswitch/trunk/src/include/switch_resample.h
   freeswitch/trunk/src/include/switch_types.h
   freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c
   freeswitch/trunk/src/mod/applications/mod_voicemail/mod_voicemail.c
   freeswitch/trunk/src/mod/formats/mod_shout/mod_shout.c
   freeswitch/trunk/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c
   freeswitch/trunk/src/switch_buffer.c
   freeswitch/trunk/src/switch_core_io.c
   freeswitch/trunk/src/switch_core_state_machine.c
   freeswitch/trunk/src/switch_ivr_async.c
   freeswitch/trunk/src/switch_resample.c

Log:
these aren't the droids you're looking for, move along....

Modified: freeswitch/trunk/libs/xmlrpc-c/.update
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/.update	(original)
+++ freeswitch/trunk/libs/xmlrpc-c/.update	Fri Nov 30 17:56:01 2007
@@ -1 +1 @@
-Wed Apr 25 16:05:00 EDT 2007
+date

Modified: freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/abyss.h
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/abyss.h	(original)
+++ freeswitch/trunk/libs/xmlrpc-c/include/xmlrpc-c/abyss.h	Fri Nov 30 17:56:01 2007
@@ -48,7 +48,7 @@
 ** Maximum numer of simultaneous connections
 *********************************************************************/
 
-#define MAX_CONN    16
+#define MAX_CONN    4000
 
 /*********************************************************************
 ** Server Info Definitions
@@ -443,6 +443,7 @@
     TList defaultfilenames;
     void *defaulthandler;
     abyss_bool advertise;
+	int running;
 #ifndef _WIN32
     uid_t uid;
     gid_t gid;

Modified: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/server.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/server.c	(original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/server.c	Fri Nov 30 17:56:01 2007
@@ -770,8 +770,8 @@
         c[i].inUse = FALSE;
 
     s=srv->listensock;
-
-    while( 1 )
+	srv->running = 1;
+    while( srv->running )
     {
         /* collect all threads resources for closed connections */
         for (i=0;i<MAX_CONN;i++)

Modified: freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/thread.c
==============================================================================
--- freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/thread.c	(original)
+++ freeswitch/trunk/libs/xmlrpc-c/lib/abyss/src/thread.c	Fri Nov 30 17:56:01 2007
@@ -41,7 +41,7 @@
 #include "xmlrpc_config.h"
 
 /* 16K is the minimum size of stack on Win32 */
-#define  THREAD_STACK_SIZE    (16*1024)
+#define  THREAD_STACK_SIZE    (240*1024)
 
 /*********************************************************************
 ** Thread

Modified: freeswitch/trunk/src/include/switch_buffer.h
==============================================================================
--- freeswitch/trunk/src/include/switch_buffer.h	(original)
+++ freeswitch/trunk/src/include/switch_buffer.h	Fri Nov 30 17:56:01 2007
@@ -70,6 +70,11 @@
 SWITCH_DECLARE(switch_status_t) switch_buffer_create_dynamic(switch_buffer_t **buffer, switch_size_t blocksize, switch_size_t start_len,
 															 switch_size_t max_len);
 
+SWITCH_DECLARE(void) switch_buffer_add_mutex(switch_buffer_t *buffer, switch_mutex_t *mutex);
+SWITCH_DECLARE(void) switch_buffer_lock(switch_buffer_t *buffer);
+SWITCH_DECLARE(switch_status_t) switch_buffer_trylock(switch_buffer_t *buffer);
+SWITCH_DECLARE(void) switch_buffer_unlock(switch_buffer_t *buffer);
+
 /*! \brief Get the length of a switch_buffer_t 
  * \param buffer any buffer of type switch_buffer_t
  * \return int size of the buffer.
@@ -137,6 +142,8 @@
  */
 SWITCH_DECLARE(void) switch_buffer_destroy(switch_buffer_t **buffer);
 
+SWITCH_DECLARE(switch_size_t) switch_buffer_zwrite(switch_buffer_t *buffer, const void *data, switch_size_t datalen);
+
 /** @} */
 
 SWITCH_END_EXTERN_C

Modified: freeswitch/trunk/src/include/switch_ivr.h
==============================================================================
--- freeswitch/trunk/src/include/switch_ivr.h	(original)
+++ freeswitch/trunk/src/include/switch_ivr.h	Fri Nov 30 17:56:01 2007
@@ -204,7 +204,7 @@
   \return SWITCH_STATUS_SUCCESS if all is well
 */
 SWITCH_DECLARE(switch_status_t) switch_ivr_record_session(switch_core_session_t *session, char *file, uint32_t limit, switch_file_handle_t *fh);
-
+SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session_t *session, const char *uuid, switch_eavesdrop_flag_t flags);
 SWITCH_DECLARE(switch_status_t) switch_ivr_displace_session(switch_core_session_t *session, char *file, uint32_t limit, const char *flags);
 SWITCH_DECLARE(switch_status_t) switch_ivr_stop_displace_session(switch_core_session_t *session, const char *file);
 

Modified: freeswitch/trunk/src/include/switch_resample.h
==============================================================================
--- freeswitch/trunk/src/include/switch_resample.h	(original)
+++ freeswitch/trunk/src/include/switch_resample.h	Fri Nov 30 17:56:01 2007
@@ -165,6 +165,8 @@
 SWITCH_DECLARE(void) switch_change_sln_volume(int16_t *data, uint32_t samples, int32_t vol);
 ///\}
 
+SWITCH_DECLARE(uint32_t) switch_merge_sln(int16_t *data, uint32_t samples, int16_t *other_data, uint32_t other_samples);
+
 SWITCH_END_EXTERN_C
 #endif
 /* For Emacs:

Modified: freeswitch/trunk/src/include/switch_types.h
==============================================================================
--- freeswitch/trunk/src/include/switch_types.h	(original)
+++ freeswitch/trunk/src/include/switch_types.h	Fri Nov 30 17:56:01 2007
@@ -130,6 +130,12 @@
 typedef uint8_t switch_byte_t;
 
 typedef enum {
+	ED_MUX_READ = (1 << 0),
+	ED_MUX_WRITE = (1 << 1),
+	ED_DTMF = (1 << 2)
+} switch_eavesdrop_flag_t;
+
+typedef enum {
 	SCF_NONE = 0,
 	SCF_USE_SQL = ( 1 << 0),
 	SCF_NO_NEW_SESSIONS = (1 << 1),

Modified: freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c	(original)
+++ freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c	Fri Nov 30 17:56:01 2007
@@ -87,6 +87,29 @@
 }
 
 
+
+
+#define eavesdrop_SYNTAX "<uuid>"
+SWITCH_STANDARD_APP(eavesdrop_function)
+{
+	char *argv[4];
+	int argc;
+	char *lbuf = NULL;
+	char *uuid;
+	
+	if (data && (lbuf = switch_core_session_strdup(session, data))
+		&& (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
+		uuid = argv[0];
+		
+		switch_ivr_eavesdrop_session(session, uuid, ED_DTMF);
+		
+	} else {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", eavesdrop_SYNTAX);
+	}
+}
+
+
+
 #define SET_USER_SYNTAX "<user>@<domain>"
 SWITCH_STANDARD_APP(set_user_function)
 {
@@ -1453,6 +1476,7 @@
 	SWITCH_ADD_APP(app_interface, "sched_broadcast", SCHED_BROADCAST_DESCR, SCHED_BROADCAST_DESCR, sched_broadcast_function, "[+]<time> <path> [aleg|bleg|both]", SAF_SUPPORT_NOMEDIA);
 	SWITCH_ADD_APP(app_interface, "sched_transfer", SCHED_TRANSF_DESCR, SCHED_TRANSF_DESCR, sched_transfer_function, "[+]<time> <extension> <dialplan> <context>", SAF_SUPPORT_NOMEDIA);
 	SWITCH_ADD_APP(app_interface, "execute_extension", "Execute an extension", "Execute an extension", exe_function, EXE_SYNTAX, SAF_SUPPORT_NOMEDIA);
+	SWITCH_ADD_APP(app_interface, "eavesdrop", "eavesdrop on a uuid", "eavesdrop on a uuid", eavesdrop_function, eavesdrop_SYNTAX, SAF_NONE);
 	SWITCH_ADD_APP(app_interface, "set_user", "Set a User", "Set a User", set_user_function, SET_USER_SYNTAX, SAF_SUPPORT_NOMEDIA);
 	SWITCH_ADD_APP(app_interface, "stop_dtmf", "stop inband dtmf", "Stop detecting inband dtmf.", stop_dtmf_session_function, "", SAF_NONE);
 	SWITCH_ADD_APP(app_interface, "start_dtmf", "Detect dtmf", "Detect inband dtmf on the session", dtmf_session_function, "", SAF_NONE);

Modified: freeswitch/trunk/src/mod/applications/mod_voicemail/mod_voicemail.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_voicemail/mod_voicemail.c	(original)
+++ freeswitch/trunk/src/mod/applications/mod_voicemail/mod_voicemail.c	Fri Nov 30 17:56:01 2007
@@ -2660,6 +2660,10 @@
     char *path_info = NULL;
     int rss = 0, xarg = 0;
     
+	if (session) {
+		return SWITCH_STATUS_FALSE;
+	}
+
     if (stream->event) {
         host = switch_event_get_header(stream->event, "http-host");
         port = switch_event_get_header(stream->event, "http-port");

Modified: freeswitch/trunk/src/mod/formats/mod_shout/mod_shout.c
==============================================================================
--- freeswitch/trunk/src/mod/formats/mod_shout/mod_shout.c	(original)
+++ freeswitch/trunk/src/mod/formats/mod_shout/mod_shout.c	Fri Nov 30 17:56:01 2007
@@ -306,7 +306,7 @@
 
 	return 0;
 
-  error:
+ error:
 	switch_mutex_lock(context->audio_mutex);
 	context->err++;
 	switch_mutex_unlock(context->audio_mutex);
@@ -419,7 +419,7 @@
 
 	return realsize;
 
-  error:
+ error:
 	switch_mutex_lock(context->audio_mutex);
 	context->err++;
 	switch_mutex_unlock(context->audio_mutex);
@@ -512,7 +512,7 @@
 		switch_yield(100000);
 	}
 
-  error:
+ error:
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Thread Done\n");
 	context->thread_running = 0;
 	return NULL;
@@ -534,6 +534,7 @@
 	switch_thread_create(&thread, thd_attr, write_stream_thread, context, context->memory_pool);
 }
 
+#define TC_BUFFER_SIZE 1024 * 32
 static switch_status_t shout_file_open(switch_file_handle_t *handle, const char *path)
 {
 	shout_context_t *context;
@@ -554,7 +555,7 @@
 	context->samplerate = handle->samplerate;
 
 	if (switch_test_flag(handle, SWITCH_FILE_FLAG_READ)) {
-		if (switch_buffer_create_dynamic(&context->audio_buffer, MY_BLOCK_SIZE, MY_BUF_LEN, 0) != SWITCH_STATUS_SUCCESS) {
+		if (switch_buffer_create_dynamic(&context->audio_buffer, TC_BUFFER_SIZE, TC_BUFFER_SIZE * 2, 0) != SWITCH_STATUS_SUCCESS) {
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n");
 			goto error;
 		}
@@ -708,7 +709,7 @@
 
 	return SWITCH_STATUS_SUCCESS;
 
-  error:
+ error:
 	if (err) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: %s\n", err);
 	}
@@ -916,46 +917,431 @@
 	return SWITCH_STATUS_FALSE;
 }
 
-static switch_file_interface_t shout_file_interface = {
-	/*.interface_name */ modname,
-	/*.file_open */ shout_file_open,
-	/*.file_close */ shout_file_close,
-	/*.file_read */ shout_file_read,
-	/*.file_write */ shout_file_write,
-	/*.file_seek */ shout_file_seek,
-	/*.file_set_string */ shout_file_set_string,
-	/*.file_get_string */ shout_file_get_string,
-	/*.extens */ NULL,
-	/*.next */ NULL,
-};
 
-static switch_loadable_module_interface_t shout_module_interface = {
-	/*.module_name */ modname,
-	/*.endpoint_interface */ NULL,
-	/*.timer_interface */ NULL,
-	/*.dialplan_interface */ NULL,
-	/*.codec_interface */ NULL,
-	/*.application_interface */ NULL,
-	/*.api_interface */ NULL,
-	/*.file_interface */ &shout_file_interface,
-	/*.speech_interface */ NULL,
-	/*.directory_interface */ NULL
+static switch_bool_t telecast_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
+{
+    switch_buffer_t *buffer = (switch_buffer_t *) user_data;
+	uint8_t data[SWITCH_RECOMMENDED_BUFFER_SIZE];
+	switch_frame_t frame = { 0 };
+
+	frame.data = data;
+	frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
+
+	switch (type) {
+	case SWITCH_ABC_TYPE_INIT:
+		break;
+	case SWITCH_ABC_TYPE_CLOSE:
+		break;
+	case SWITCH_ABC_TYPE_WRITE:
+		if (buffer) {
+			if (switch_core_media_bug_read(bug, &frame) == SWITCH_STATUS_SUCCESS) {
+                switch_buffer_lock(buffer);
+                switch_buffer_write(buffer, frame.data, frame.datalen);
+                switch_buffer_unlock(buffer);
+			}
+		} else {
+            return SWITCH_FALSE;
+        }
+		break;
+	case SWITCH_ABC_TYPE_READ:
+	default:
+		break;
+	}
+
+	return SWITCH_TRUE;
+}
+
+struct holder {
+    switch_stream_handle_t *stream;
+    switch_memory_pool_t *pool;
+    char *host;
+    char *port;
+    char *uri;
 };
 
+static int web_callback(void *pArg, int argc, char **argv, char **columnNames)
+{
+    struct holder *holder = (struct holder *) pArg;
+    char title_b4[128] = "";
+    char title_aft[128*3] = "";
+    char *mp3, *m3u;
+
+
+    /*
+      0  uuid  VARCHAR(255),
+      1  created  VARCHAR(255),
+      2  name  VARCHAR(255),
+      3  state  VARCHAR(255),
+      4  cid_name  VARCHAR(255),
+      5  cid_num  VARCHAR(255),
+      6  ip_addr  VARCHAR(255),
+      7  dest  VARCHAR(255),
+      8  application  VARCHAR(255),
+      9  application_data  VARCHAR(255),
+      10 read_codec  VARCHAR(255),
+      11 read_rate  VARCHAR(255),
+      12 write_codec  VARCHAR(255),
+      13 write_rate  VARCHAR(255)
+    */
+    
+
+
+    holder->stream->write_function(holder->stream, 
+                                   "<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>", 
+                                   argv[1], argv[4], argv[5], argv[7], argv[8] ? argv[8] : "N/A", argv[9] ? argv[9] : "N/A", argv[10], argv[11]);
+    
+    snprintf(title_b4, sizeof(title_b4), "%s <%s>", argv[4], argv[5]);
+    switch_url_encode(title_b4, title_aft, sizeof(title_aft)-1);
+
+    mp3 = switch_mprintf("http://%s:%s%s/mp3/%s/%s.mp3", holder->host, holder->port, holder->uri, argv[0], argv[5]);
+    m3u = switch_mprintf("http://%s:%s%s/m3u/mp3/%s/%s.mp3.m3u", holder->host, holder->port, holder->uri, argv[0], argv[5]);
+
+    holder->stream->write_function(holder->stream, "[<a href=%s>mp3</a>] ", mp3);
+    holder->stream->write_function(holder->stream, "[<a href=%s>m3u</a>]</td></tr>\n", m3u);
+    
+    switch_safe_free(mp3);
+    switch_safe_free(m3u);
+    return 0;
+}
+
+
+void do_telecast(switch_stream_handle_t *stream)
+{
+    char *path_info = switch_event_get_header(stream->event, "http-path-info");
+    char *uuid = strdup(path_info + 4);
+    switch_core_session_t *tsession;
+    char *fname = "stream.mp3";
+
+    if ((fname = strchr(uuid, '/'))) {
+        *fname++ = '\0';
+    }
+
+    if (!(tsession = switch_core_session_locate(uuid))) {
+        char *ref = switch_event_get_header(stream->event, "http-referer");
+        stream->write_function(stream,"Content-type: text/html\r\n\r\n<h2>Not Found!</h2>\n"
+                               "<META http-equiv=\"refresh\" content=\"1;URL=%s\">",  ref);
+
+    } else {
+        switch_media_bug_t *bug = NULL;
+        switch_buffer_t *buffer;
+        switch_mutex_t *mutex;
+        switch_channel_t *channel = switch_core_session_get_channel(tsession);
+        lame_global_flags *gfp = NULL;
+        switch_codec_t *read_codec;
+        
+
+        if (!(gfp = lame_init())) {
+            switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate lame\n");
+            goto end;
+        }
+        read_codec = switch_core_session_get_read_codec(tsession);
+            
+        lame_set_num_channels(gfp, read_codec->implementation->number_of_channels);
+        lame_set_in_samplerate(gfp, read_codec->implementation->actual_samples_per_second);
+        lame_set_brate(gfp, 24);
+        lame_set_mode(gfp, 3);
+        lame_set_quality(gfp, 2);
+        lame_set_errorf(gfp, log_error);
+        lame_set_debugf(gfp, log_debug);
+        lame_set_msgf(gfp, log_msg);
+        lame_set_bWriteVbrTag(gfp, 0);
+        lame_mp3_tags_fid(gfp, NULL);
+        lame_init_params(gfp);
+        lame_print_config(gfp);
+            
+        switch_mutex_init(&mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession));
+        switch_buffer_create_dynamic(&buffer, 1024, 2048, 0);
+        switch_buffer_add_mutex(buffer, mutex);
+            
+        if (switch_core_media_bug_add(tsession, telecast_callback, buffer, 0, SMBF_READ_STREAM | SMBF_WRITE_STREAM, &bug) != SWITCH_STATUS_SUCCESS) {
+            goto end;
+        }
+
+        stream->write_function(stream, 
+                               "Content-type: audio/mpeg\r\n"
+                               "Content-Disposition: inline; filename=\"%s\"\r\n\r\n", 
+                               fname);
+            
+        while(switch_channel_ready(channel)) {
+            unsigned char mp3buf[TC_BUFFER_SIZE] = "";
+            int rlen;
+            uint8_t buf[1024];
+            switch_size_t bytes = 0;
+
+            if (switch_buffer_inuse(buffer) >= 1024) {
+                switch_buffer_lock(buffer);
+                bytes = switch_buffer_read(buffer, buf, sizeof(buf));
+                switch_buffer_unlock(buffer);
+            } else {
+                memset(buf, 0, bytes);
+            }
+
+            if ((rlen = lame_encode_buffer(gfp, (void *)buf, NULL, bytes / 2, mp3buf, sizeof(mp3buf))) < 0) {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MP3 encode error %d!\n", rlen);
+                goto end;
+            }
+
+            if (rlen) {
+                if (stream->raw_write_function(stream, mp3buf, rlen)) {
+                    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Disconnected\n");
+                    goto end;
+                }
+            }
+        }
+
+
+    end:
+
+        switch_safe_free(uuid);
+
+        if (gfp) {
+            lame_close(gfp);
+            gfp = NULL;
+        }
+            
+        if (bug) {
+            switch_core_media_bug_remove(tsession, &bug);
+        }
+
+        if (buffer) {
+            switch_buffer_destroy(&buffer);
+        }
+
+        switch_core_session_rwunlock(tsession);
+    }
+
+}
+
+
+void do_broadcast(switch_stream_handle_t *stream)
+{
+    char *path_info = switch_event_get_header(stream->event, "http-path-info");
+    char *file;
+    lame_global_flags *gfp = NULL;
+    switch_file_handle_t fh = {0};
+    unsigned char mp3buf[TC_BUFFER_SIZE] = "";
+    uint8_t buf[1024];
+    int rlen;
+    int is_local = 0;
+
+    if (strstr(path_info + 7, "://")) {
+        file = strdup(path_info + 7);
+        is_local++;
+    } else {
+        file = switch_mprintf("%s/streamfiles/%s", SWITCH_GLOBAL_dirs.base_dir, path_info + 7);
+    }
+    assert(file);
+
+	if (switch_core_file_open(&fh,
+							  file,
+							  0,
+							  0,
+							  SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
+        memset(&fh, 0, sizeof(fh));
+        stream->write_function(stream, "Content-type: text/html\r\n\r\n<h2>File not found</h2>\n");
+        goto end;
+	}
+
+    if (switch_test_flag((&fh), SWITCH_FILE_NATIVE)) {
+        stream->write_function(stream, "Content-type: text/html\r\n\r\n<h2>File format not supported</h2>\n");
+        goto end;
+    }
+
+    if (!(gfp = lame_init())) {
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate lame\n");
+        goto end;
+    }
+            
+    lame_set_num_channels(gfp, fh.channels);
+    lame_set_in_samplerate(gfp, fh.samplerate);
+    lame_set_brate(gfp, 24);
+    lame_set_mode(gfp, 3);
+    lame_set_quality(gfp, 2);
+    lame_set_errorf(gfp, log_error);
+    lame_set_debugf(gfp, log_debug);
+    lame_set_msgf(gfp, log_msg);
+    lame_set_bWriteVbrTag(gfp, 0);
+    lame_mp3_tags_fid(gfp, NULL);
+    lame_init_params(gfp);
+    lame_print_config(gfp);
+    
+    stream->write_function(stream, 
+                           "Content-type: audio/mpeg\r\n"
+                           "Content-Disposition: inline; filename=\"%s.mp3\"\r\n\r\n", 
+                           path_info + 7);
+
+
+            
+    for(;;) {
+        switch_size_t samples = sizeof(buf) / 2;
+
+        switch_core_file_read(&fh, buf, &samples);
+
+        if (is_local) {
+            switch_yield(20000);
+        }
+
+        if (!samples) {
+            break;
+        }
+
+        if ((rlen = lame_encode_buffer(gfp, (void *)buf, NULL, samples, mp3buf, sizeof(mp3buf))) < 0) {
+            switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MP3 encode error %d!\n", rlen);
+            goto end;
+        }
+        
+        if (rlen) {
+            if (stream->raw_write_function(stream, mp3buf, rlen)) {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Disconnected\n");
+                goto end;
+            }
+        }
+
+
+    }
+
+
+    while ((rlen = lame_encode_flush(gfp, mp3buf, sizeof(mp3buf))) > 0) {
+        if (stream->raw_write_function(stream, mp3buf, rlen)) {
+            switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Disconnected\n");
+            goto end;
+        }
+    }
+
+
+ end:
+
+    if (fh.channels) {
+        switch_core_file_close(&fh);
+    }
+
+    switch_safe_free(file);
+
+    if (gfp) {
+        lame_close(gfp);
+        gfp = NULL;
+    }
+            
+}
+
+
+void do_index(switch_stream_handle_t *stream)
+{
+    switch_core_db_t *db = switch_core_db_handle();
+    const char *sql = "select * from channels";
+    struct holder holder;
+    char *errmsg;
+
+    holder.host = switch_event_get_header(stream->event, "http-host");
+    holder.port = switch_event_get_header(stream->event, "http-port");
+    holder.uri = switch_event_get_header(stream->event, "http-uri");
+    holder.stream = stream;
+    
+    stream->write_function(stream, "Content-type: text/html\r\n\r\n");
+
+
+    stream->write_function(stream,
+                           "<table align=center border=1 cellpadding=6 cellspacing=0>"
+                           "<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>\n",
+                           "Created", "CID Name", "CID Num", "Ext", "App", "Data", "Codec", "Rate", "Listen"
+                           );
+    
+    switch_core_db_exec(db, sql, web_callback, &holder, &errmsg);
+    
+    stream->write_function(stream,
+                           "</table>");
+    
+    if (errmsg) {
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error [%s]\n", errmsg);    
+        switch_safe_free(errmsg);
+    }
+}
+
+#define TELECAST_SYNTAX ""
+
+SWITCH_STANDARD_API(telecast_api_function)
+{
+    char *host = NULL, *port = NULL, *uri = NULL, *path_info = NULL;
+
+    
+	if (session) {
+		return SWITCH_STATUS_FALSE;
+	}
+
+    if (stream->event) {
+        host = switch_event_get_header(stream->event, "http-host");
+        port = switch_event_get_header(stream->event, "http-port");
+        uri = switch_event_get_header(stream->event, "http-uri");
+        path_info = switch_event_get_header(stream->event, "http-path-info");
+    }
+
+    if (!path_info) {
+        return SWITCH_STATUS_FALSE;
+    } else {
+        if (!strncmp(path_info, "index", 5)) {
+            do_index(stream);
+            return SWITCH_STATUS_SUCCESS;
+        }
+
+        if (!strncmp(path_info, "m3u/", 4)) {
+            char *p;
+
+            if ((p = strstr(path_info, ".m3u"))) {
+                *p = '\0';
+            }
+
+            stream->write_function(stream, "Content-type: audio/x-mpegurl\r\n\r\nhttp://%s:%s%s/%s\n", host, port, uri, path_info + 4);
+            return SWITCH_STATUS_SUCCESS;
+        }
+
+        if (!strncmp(path_info, "mp3/", 4)) {
+            do_telecast(stream);
+            return SWITCH_STATUS_SUCCESS;
+        }
+
+        if (!strncmp(path_info, "stream/", 7)) {
+            do_broadcast(stream);
+            return SWITCH_STATUS_SUCCESS;
+        }
+    }
+    
+    stream->write_function(stream, "Content-type: text/html\r\n\r\n<h2>Invalid URL</h2>\n");
+
+    return SWITCH_STATUS_SUCCESS;
+}
+
 SWITCH_MODULE_LOAD_FUNCTION(mod_shout_load)
 {
+    switch_api_interface_t *shout_api_interface;
+    switch_file_interface_t *file_interface;
+
 	supported_formats[0] = "shout";
 	supported_formats[1] = "mp3";
-	shout_file_interface.extens = supported_formats;
 
 	curl_global_init(CURL_GLOBAL_ALL);
 
+	*module_interface = switch_loadable_module_create_module_interface(pool, modname);
+    file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE);
+    file_interface->interface_name = modname;
+    file_interface->extens = supported_formats;
+    file_interface->file_open = shout_file_open;
+    file_interface->file_close = shout_file_close;
+    file_interface->file_read = shout_file_read;
+    file_interface->file_write = shout_file_write;
+    file_interface->file_seek = shout_file_seek;
+    file_interface->file_set_string = shout_file_set_string;
+    file_interface->file_get_string = shout_file_get_string;
+
+
+
 	/* connect my internal structure to the blank pointer passed to me */
-	*module_interface = &shout_module_interface;
+	//*module_interface = &shout_module_interface;
 
 	shout_init();
 	InitMP3Constants();
 
+    SWITCH_ADD_API(shout_api_interface, "telecast", "telecast", telecast_api_function, TELECAST_SYNTAX);
+
 	/* indicate that the module should continue to be loaded */
 	return SWITCH_STATUS_SUCCESS;
 }

Modified: freeswitch/trunk/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c
==============================================================================
--- freeswitch/trunk/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c	(original)
+++ freeswitch/trunk/src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c	Fri Nov 30 17:56:01 2007
@@ -55,6 +55,7 @@
 	char *realm;
 	char *user;
 	char *pass;
+	TServer abyssServer;
 } globals;
 
 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_realm, globals.realm);
@@ -353,7 +354,7 @@
 abyss_bool handler_hook(TSession * r)
 {
 	//char *mime = "text/html";
-	char buf[512] = "HTTP/1.1 200 OK\n";
+	char buf[80] = "HTTP/1.1 200 OK\n";
 	switch_stream_handle_t stream = { 0 };
 	char *command;
 	int i, j = 0;
@@ -542,6 +543,9 @@
 
 	HTTPWrite(r, buf, (uint32_t) strlen(buf));
 
+	//HTTPWrite(r, "<pre>\n\n", 7);
+
+
 	/* generation of the date field */
 	if (DateToString(&r->date, buf)) {
 		ResponseAddField(r,"Date", buf);
@@ -559,14 +563,21 @@
 	}
 
 	
+	snprintf(buf, sizeof(buf), "Connection: close\r\n");
+	ConnWrite(r->conn, buf, (uint32_t) strlen(buf));
+	
+
 	if (switch_api_execute(command, r->query, NULL, &stream) == SWITCH_STATUS_SUCCESS) {
+		ResponseStatus(r, 200);
 		r->done = TRUE;
 	} else {
 		ResponseStatus(r, 404);
 		ResponseError(r);
 	} 
 	
-	//HTTPWriteEnd(r);
+	SocketClose(&(r->conn->socket));
+	HTTPWriteEnd(r);
+	ConnClose(r->conn);
 
  end:
 
@@ -661,7 +672,7 @@
 
 SWITCH_MODULE_RUNTIME_FUNCTION(mod_xml_rpc_runtime)
 {
-	TServer abyssServer;
+
 	xmlrpc_registry *registryP;
 	xmlrpc_env env;
 	char logfile[512];
@@ -690,22 +701,23 @@
 	}
 
 	snprintf(logfile, sizeof(logfile), "%s%s%s", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, "freeswitch_http.log");
-	ServerCreate(&abyssServer, "XmlRpcServer", globals.port, SWITCH_GLOBAL_dirs.htdocs_dir, logfile);
+	ServerCreate(&globals.abyssServer, "XmlRpcServer", globals.port, SWITCH_GLOBAL_dirs.htdocs_dir, logfile);
 
-	xmlrpc_server_abyss_set_handler(&env, &abyssServer, "/RPC2", registryP);
+	xmlrpc_server_abyss_set_handler(&env, &globals.abyssServer, "/RPC2", registryP);
 
-	if (ServerInit(&abyssServer) != TRUE) {
+	if (ServerInit(&globals.abyssServer) != TRUE) {
 		globals.running = 0;
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to start HTTP Port %d\n", globals.port);
 		return SWITCH_STATUS_TERM;
 	}
 
 
-	ServerAddHandler(&abyssServer, handler_hook);
-	ServerAddHandler(&abyssServer, auth_hook);
+	ServerAddHandler(&globals.abyssServer, handler_hook);
+	ServerAddHandler(&globals.abyssServer, auth_hook);
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Starting HTTP Port %d, DocRoot [%s]\n", globals.port, SWITCH_GLOBAL_dirs.htdocs_dir);
 	while (globals.running) {
-		ServerRunOnce2(&abyssServer, ABYSS_FOREGROUND);
+		//ServerRunOnce2(&globals.abyssServer, ABYSS_FOREGROUND);
+		ServerRun(&globals.abyssServer);
 	}
 
 
@@ -716,7 +728,9 @@
 
 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_xml_rpc_shutdown)
 {
+	globals.abyssServer.running = 0;
 	globals.running = 0;
+	
 	return SWITCH_STATUS_SUCCESS;
 }
 

Modified: freeswitch/trunk/src/switch_buffer.c
==============================================================================
--- freeswitch/trunk/src/switch_buffer.c	(original)
+++ freeswitch/trunk/src/switch_buffer.c	Fri Nov 30 17:56:01 2007
@@ -46,6 +46,7 @@
 	switch_size_t datalen;
 	switch_size_t max_len;
 	switch_size_t blocksize;
+	switch_mutex_t *mutex;
 	uint32_t flags;
 	uint32_t id;
 	int32_t loops;
@@ -95,6 +96,33 @@
 	return SWITCH_STATUS_MEMERR;
 }
 
+SWITCH_DECLARE(void) switch_buffer_add_mutex(switch_buffer_t *buffer, switch_mutex_t *mutex)
+{
+	buffer->mutex = mutex;
+}
+
+SWITCH_DECLARE(void) switch_buffer_lock(switch_buffer_t *buffer)
+{
+	if (buffer->mutex) {
+		switch_mutex_lock(buffer->mutex);
+	}
+}
+
+SWITCH_DECLARE(switch_status_t) switch_buffer_trylock(switch_buffer_t *buffer)
+{
+	if (buffer->mutex) {
+		return switch_mutex_lock(buffer->mutex);
+	}
+	return SWITCH_STATUS_FALSE;
+}
+
+SWITCH_DECLARE(void) switch_buffer_unlock(switch_buffer_t *buffer)
+{
+	if (buffer->mutex) {
+		switch_mutex_unlock(buffer->mutex);
+	}
+}
+
 SWITCH_DECLARE(switch_size_t) switch_buffer_len(switch_buffer_t *buffer)
 {
 
@@ -224,7 +252,7 @@
 	   }
 	 */
 	if (switch_test_flag(buffer, SWITCH_BUFFER_FLAG_DYNAMIC)) {
-		if (freespace < datalen) {
+		if (freespace < datalen && (!buffer->max_len || (buffer->datalen + datalen <= buffer->max_len))) {
 			switch_size_t new_size, new_block_size;
 
 			new_size = buffer->datalen + datalen;
@@ -266,6 +294,18 @@
 	buffer->head = buffer->data;
 }
 
+SWITCH_DECLARE(switch_size_t) switch_buffer_zwrite(switch_buffer_t *buffer, const void *data, switch_size_t datalen)
+{
+	switch_size_t w;
+	
+	if (!(w = switch_buffer_write(buffer, data, datalen))) {
+		switch_buffer_zero(buffer);
+		return switch_buffer_write(buffer, data, datalen);
+	}
+
+	return w;
+}
+
 SWITCH_DECLARE(void) switch_buffer_destroy(switch_buffer_t **buffer)
 {
 	if (buffer && *buffer) { 

Modified: freeswitch/trunk/src/switch_core_io.c
==============================================================================
--- freeswitch/trunk/src/switch_core_io.c	(original)
+++ freeswitch/trunk/src/switch_core_io.c	Fri Nov 30 17:56:01 2007
@@ -150,7 +150,7 @@
 		goto done;
 	}
 
-	if ((*frame)->codec->implementation->actual_samples_per_second != session->write_codec->implementation->actual_samples_per_second) {
+	if ((*frame)->codec->implementation->actual_samples_per_second != session->read_codec->implementation->actual_samples_per_second) {
 		do_resample = 1;
 	}
 
@@ -246,7 +246,9 @@
 						}
 					}
 					switch_mutex_unlock(bp->read_mutex);
-				} else if (switch_test_flag(bp, SMBF_READ_REPLACE)) {
+				} 
+
+				if (switch_test_flag(bp, SMBF_READ_REPLACE)) {
 					do_bugs = 0;
 					if (bp->callback) {
 						bp->read_replace_frame_in = read_frame;
@@ -432,7 +434,7 @@
 		need_codec = 1;
 	}
 
-	if (frame->codec->implementation->actual_samples_per_second != session->read_codec->implementation->actual_samples_per_second) {
+	if (frame->codec->implementation->actual_samples_per_second != session->write_codec->implementation->actual_samples_per_second) {
 		need_codec = 1;
 		do_resample = 1;
 	}
@@ -489,6 +491,7 @@
 				return status;
 			}
 		}
+
 		if (session->write_resampler) {
 			short *data = write_frame->data;
 
@@ -509,6 +512,12 @@
 			write_frame->rate = session->write_resampler->to_rate;
 		}
 
+		if (do_bugs) {
+			do_write = 1;
+			write_frame = frame;
+			goto done;
+		}
+
 		if (session->bugs) {
 			switch_media_bug_t *bp, *dp, *last = NULL;
 
@@ -525,7 +534,9 @@
 					if (bp->callback) {
 						ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_WRITE);
 					}
-				} else if (switch_test_flag(bp, SMBF_WRITE_REPLACE)) {
+				} 
+
+				if (switch_test_flag(bp, SMBF_WRITE_REPLACE)) {
 					do_bugs = 0;
 					if (bp->callback) {
 						bp->write_replace_frame_in = write_frame;
@@ -561,12 +572,6 @@
 			switch_thread_rwlock_unlock(session->bug_rwlock);
 		}
 
-		if (do_bugs) {
-			do_write = 1;
-			write_frame = frame;
-			goto done;
-		}
-
 		if (session->write_codec) {
 			if (write_frame->datalen == session->write_codec->implementation->bytes_per_frame) {
 				perfect = TRUE;

Modified: freeswitch/trunk/src/switch_core_state_machine.c
==============================================================================
--- freeswitch/trunk/src/switch_core_state_machine.c	(original)
+++ freeswitch/trunk/src/switch_core_state_machine.c	Fri Nov 30 17:56:01 2007
@@ -130,7 +130,8 @@
 
 	while (switch_channel_get_state(session->channel) == CS_EXECUTE && extension->current_application) {
 		char *expanded = NULL;
-
+		int nomedia = 0;
+		
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Execute %s(%s)\n",
 						  extension->current_application->application_name, switch_str_nil(extension->current_application->application_data));
 		if ((application_interface = switch_loadable_module_get_application_interface(extension->current_application->application_name)) == 0) {
@@ -138,19 +139,19 @@
 			switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
 			return;
 		}
-
-		if (switch_channel_test_flag(session->channel, CF_BYPASS_MEDIA) && !switch_test_flag(application_interface, SAF_SUPPORT_NOMEDIA)) {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Application %s Cannot be used with NO_MEDIA mode!\n",
-							  extension->current_application->application_name);
-			switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
-			return;
-		}
-
+		
 		if (!application_interface->application_function) {
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Function for %s\n", extension->current_application->application_name);
 			switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
 			return;
 		}
+		
+		if (switch_channel_test_flag(session->channel, CF_BYPASS_MEDIA) && !switch_test_flag(application_interface, SAF_SUPPORT_NOMEDIA)) {
+			switch_ivr_media(session->uuid_str, SMF_NONE);
+			nomedia++;
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Application %s Requires media!\n",
+							  extension->current_application->application_name);
+		}
 
 		if ((expanded =
 			 switch_channel_expand_variables(session->channel,
@@ -177,6 +178,12 @@
 			goto top;
 		}
 
+		if (nomedia) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Application %s Releasing media\n",
+							  extension->current_application->application_name);
+			switch_ivr_nomedia(session->uuid_str, SMF_NONE);
+		}
+
 		extension->current_application = extension->current_application->next;
 	}
 

Modified: freeswitch/trunk/src/switch_ivr_async.c
==============================================================================
--- freeswitch/trunk/src/switch_ivr_async.c	(original)
+++ freeswitch/trunk/src/switch_ivr_async.c	Fri Nov 30 17:56:01 2007
@@ -307,6 +307,274 @@
 
 }
 
+
+struct eavesdrop_pvt {
+	switch_buffer_t *buffer;
+	switch_mutex_t *mutex;
+	switch_buffer_t *r_buffer;
+	switch_mutex_t *r_mutex;
+	switch_buffer_t *w_buffer;
+	switch_mutex_t *w_mutex;
+	uint32_t flags;
+};
+
+
+static switch_bool_t eavesdrop_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
+{
+	struct eavesdrop_pvt *ep = (struct eavesdrop_pvt *) user_data;
+	uint8_t data[SWITCH_RECOMMENDED_BUFFER_SIZE];
+	switch_frame_t frame = { 0 };
+	
+	frame.data = data;
+	frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
+
+	switch (type) {
+	case SWITCH_ABC_TYPE_INIT:
+		break;
+	case SWITCH_ABC_TYPE_CLOSE:
+		break;
+	case SWITCH_ABC_TYPE_WRITE:
+		if (ep->buffer) {
+			if (switch_core_media_bug_read(bug, &frame) == SWITCH_STATUS_SUCCESS) {
+                switch_buffer_lock(ep->buffer);
+                switch_buffer_zwrite(ep->buffer, frame.data, frame.datalen);
+                switch_buffer_unlock(ep->buffer);
+			}
+		} else {
+            return SWITCH_FALSE;
+        }
+		break;
+	case SWITCH_ABC_TYPE_READ:
+		break;
+
+	case SWITCH_ABC_TYPE_READ_REPLACE:
+		{
+			if (switch_test_flag(ep, ED_MUX_READ)) {
+				switch_frame_t *frame = switch_core_media_bug_get_read_replace_frame(bug);
+			
+				if (switch_buffer_inuse(ep->r_buffer) >= frame->datalen) {
+					uint32_t bytes;
+					switch_buffer_lock(ep->r_buffer);
+					bytes = (uint32_t) switch_buffer_read(ep->r_buffer, data, frame->datalen);
+			
+					frame->datalen = switch_merge_sln(frame->data, frame->samples, (int16_t *)data, bytes / 2) * 2;
+					frame->samples = frame->datalen / 2;
+				
+					switch_buffer_unlock(ep->r_buffer);
+					switch_core_media_bug_set_read_replace_frame(bug, frame);
+				}
+			}
+		}
+		break;
+
+	case SWITCH_ABC_TYPE_WRITE_REPLACE:
+		{
+			if (switch_test_flag(ep, ED_MUX_WRITE)) {
+				switch_frame_t *frame = switch_core_media_bug_get_write_replace_frame(bug);
+			
+				if (switch_buffer_inuse(ep->w_buffer) >= frame->datalen) {
+					uint32_t bytes;
+					switch_buffer_lock(ep->w_buffer);
+					bytes = (uint32_t) switch_buffer_read(ep->w_buffer, data, frame->datalen);
+			
+					frame->datalen = switch_merge_sln(frame->data, frame->samples, (int16_t *)data, bytes / 2) * 2;
+					frame->samples = frame->datalen / 2;
+				
+					switch_buffer_unlock(ep->w_buffer);
+					switch_core_media_bug_set_write_replace_frame(bug, frame);
+				}
+			}
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	return SWITCH_TRUE;
+}
+
+
+SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session_t *session, const char *uuid, switch_eavesdrop_flag_t flags)
+{
+	switch_core_session_t *tsession;
+	switch_status_t status = SWITCH_STATUS_FALSE;
+	switch_channel_t *channel = switch_core_session_get_channel(session);
+	switch_codec_t *read_codec = switch_core_session_get_read_codec(session);
+	
+	if ((tsession = switch_core_session_locate(uuid))) {
+		struct eavesdrop_pvt ep = { 0 };
+		switch_media_bug_t *bug = NULL;
+		switch_channel_t *tchannel = switch_core_session_get_channel(tsession);
+		switch_frame_t *read_frame, write_frame = { 0 };
+		switch_codec_t codec = {0};
+		int16_t buf[1024];
+		switch_codec_t *tread_codec = switch_core_session_get_read_codec(tsession);
+		
+		
+		switch_channel_pre_answer(channel);
+		
+		if (switch_core_codec_init(&codec,
+								   "L16",
+								   NULL, 
+								   tread_codec->implementation->actual_samples_per_second,
+								   tread_codec->implementation->microseconds_per_frame / 1000,
+								   tread_codec->implementation->number_of_channels, 
+								   SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, 
+								   NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot init codec\n");
+			return status;
+		}
+		
+		switch_core_session_set_read_codec(session, &codec);
+		write_frame.codec = &codec;
+		write_frame.data = buf;
+		write_frame.buflen = sizeof(buf);
+		write_frame.rate = read_codec->implementation->actual_samples_per_second;
+		
+		ep.flags = flags;
+		switch_mutex_init(&ep.mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession));
+		switch_buffer_create_dynamic(&ep.buffer, 1024, 2048, 2048);
+		switch_buffer_add_mutex(ep.buffer, ep.mutex);
+
+		switch_mutex_init(&ep.w_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession));
+		switch_buffer_create_dynamic(&ep.w_buffer, 1024, 2048, 2048);
+		switch_buffer_add_mutex(ep.w_buffer, ep.w_mutex);
+
+		switch_mutex_init(&ep.r_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(tsession));
+		switch_buffer_create_dynamic(&ep.r_buffer, 1024, 2048, 2048);
+		switch_buffer_add_mutex(ep.r_buffer, ep.r_mutex);
+
+		
+		if (switch_core_media_bug_add(tsession, eavesdrop_callback, &ep, 0, 
+									  SMBF_READ_STREAM | SMBF_WRITE_STREAM | SMBF_READ_REPLACE | SMBF_WRITE_REPLACE, 
+									  &bug) != SWITCH_STATUS_SUCCESS) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot attach bug\n");
+			goto end;
+		}
+		
+        while(switch_channel_ready(tchannel) && switch_channel_ready(channel)) {
+			uint32_t len = sizeof(buf);
+			switch_event_t *event = NULL;
+			char *fcommand = NULL;
+			
+			status = switch_core_session_read_frame(session, &read_frame, 1000, 0);
+			
+			if (!SWITCH_READ_ACCEPTABLE(status)) {
+				goto end;
+			}
+
+			if (switch_core_session_dequeue_event(session, &event) == SWITCH_STATUS_SUCCESS) {
+				char *command = switch_event_get_header(event, "eavesdrop-command");
+				if (command) {
+					fcommand = command;
+				}
+				switch_event_destroy(&event);
+			}
+
+			if ((flags & ED_DTMF) && switch_channel_has_dtmf(channel)) {
+				char dtmf[128] = "";
+				switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
+				fcommand = dtmf;
+			}
+
+			if (fcommand) {
+				char *d;
+				for(d = fcommand; *d; d++) {
+					int z = 1;
+					
+					switch (*d) {
+					case '1':
+						switch_set_flag((&ep), ED_MUX_READ);
+						switch_clear_flag((&ep), ED_MUX_WRITE);
+						break;
+					case '2':
+						switch_set_flag((&ep), ED_MUX_WRITE);
+						switch_clear_flag((&ep), ED_MUX_READ);
+						break;
+					case '3':
+						switch_set_flag((&ep), ED_MUX_READ);
+						switch_set_flag((&ep), ED_MUX_WRITE);
+						break;
+					case '0':
+						switch_clear_flag((&ep), ED_MUX_READ);
+						switch_clear_flag((&ep), ED_MUX_WRITE);
+						break;
+					default:
+						z = 0;
+						break;
+
+					}
+					
+					if (z) {
+						switch_buffer_lock(ep.r_buffer);
+						switch_buffer_zero(ep.r_buffer);
+						switch_buffer_unlock(ep.r_buffer);
+						
+						switch_buffer_lock(ep.w_buffer);
+						switch_buffer_zero(ep.w_buffer);
+						switch_buffer_unlock(ep.w_buffer);
+					}
+				}
+			}
+
+			if (!switch_test_flag(read_frame, SFF_CNG)) {
+				switch_buffer_lock(ep.r_buffer);
+				switch_buffer_zwrite(ep.r_buffer, read_frame->data, read_frame->datalen);
+				switch_buffer_unlock(ep.r_buffer);
+
+				switch_buffer_lock(ep.w_buffer);
+				switch_buffer_zwrite(ep.w_buffer, read_frame->data, read_frame->datalen);
+				switch_buffer_unlock(ep.w_buffer);
+			}
+
+
+			if (len > tread_codec->implementation->samples_per_frame * 2) {
+				len = tread_codec->implementation->samples_per_frame * 2;
+			}
+			
+            if (switch_buffer_inuse(ep.buffer) >= len) {
+                switch_buffer_lock(ep.buffer);				
+                write_frame.datalen = switch_buffer_read(ep.buffer, buf, len);
+				write_frame.samples = write_frame.datalen / 2;
+				if (switch_core_session_write_frame(session, &write_frame, 1000, 0) != SWITCH_STATUS_SUCCESS) {
+					goto end;
+				}
+                switch_buffer_unlock(ep.buffer);
+            }
+        }
+
+
+    end:
+
+		switch_core_codec_destroy(&codec);
+
+        if (bug) {
+            switch_core_media_bug_remove(tsession, &bug);
+        }
+
+        if (ep.buffer) {
+            switch_buffer_destroy(&ep.buffer);
+        }
+
+        if (ep.r_buffer) {
+            switch_buffer_destroy(&ep.r_buffer);
+        }
+
+        if (ep.w_buffer) {
+            switch_buffer_destroy(&ep.w_buffer);
+        }
+
+        switch_core_session_rwunlock(tsession);
+		status = SWITCH_STATUS_SUCCESS;
+
+		switch_core_session_set_read_codec(session, read_codec);
+		switch_core_session_reset(session);
+    }
+	
+	return status;
+}
+
 SWITCH_DECLARE(switch_status_t) switch_ivr_record_session(switch_core_session_t *session, char *file, uint32_t limit, switch_file_handle_t *fh)
 {
 	switch_channel_t *channel;

Modified: freeswitch/trunk/src/switch_resample.c
==============================================================================
--- freeswitch/trunk/src/switch_resample.c	(original)
+++ freeswitch/trunk/src/switch_resample.c	Fri Nov 30 17:56:01 2007
@@ -215,6 +215,27 @@
 	}
 }
 
+SWITCH_DECLARE(uint32_t) switch_merge_sln(int16_t *data, uint32_t samples, int16_t *other_data, uint32_t other_samples)
+{
+	int i;
+	int32_t x, z;
+
+	if (samples > other_samples) {
+		x = other_samples;
+	} else {
+		x = samples;
+	}
+
+	for(i = 0; i < x; i++) {
+		z = data[i] + other_data[i];
+		switch_normalize_to_16bit(z);
+		data[i] = (int16_t) z;
+	}
+
+	return x;
+
+}
+
 
 SWITCH_DECLARE(void) switch_change_sln_volume(int16_t *data, uint32_t samples, int32_t vol)
 {



More information about the Freeswitch-trunk mailing list