[commit] r5366 - in freeswitch/trunk/src: . include mod/applications/mod_commands mod/applications/mod_dptools mod/applications/mod_soundtouch
Author: anthm Date: Thu Jun 14 21:47:48 2007 New Revision: 5366 Modified: freeswitch/trunk/src/include/switch_ivr.h freeswitch/trunk/src/mod/applications/mod_commands/mod_commands.c freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c freeswitch/trunk/src/mod/applications/mod_soundtouch/mod_soundtouch.cpp freeswitch/trunk/src/switch_core_codec.c freeswitch/trunk/src/switch_core_io.c freeswitch/trunk/src/switch_ivr_async.c Log: add session_displace api and app Modified: freeswitch/trunk/src/include/switch_ivr.h ============================================================================== --- freeswitch/trunk/src/include/switch_ivr.h (original) +++ freeswitch/trunk/src/include/switch_ivr.h Thu Jun 14 21:47:48 2007 @@ -200,6 +200,9 @@ */ 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_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, char *file); + /*! \brief Stop Recording a session \param session the session to stop recording Modified: freeswitch/trunk/src/mod/applications/mod_commands/mod_commands.c ============================================================================== --- freeswitch/trunk/src/mod/applications/mod_commands/mod_commands.c (original) +++ freeswitch/trunk/src/mod/applications/mod_commands/mod_commands.c Thu Jun 14 21:47:48 2007 @@ -565,7 +565,7 @@ goto usage; } - if ((argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) != 3) { + if ((argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) < 3) { goto usage; } @@ -609,6 +609,73 @@ return SWITCH_STATUS_SUCCESS; } + +SWITCH_STANDARD_API(session_displace_function) +{ + switch_core_session_t *rsession = NULL; + char *mycmd = NULL, *argv[5] = { 0 }; + char *uuid = NULL, *action = NULL, *path = NULL; + int argc = 0; + uint32_t limit = 0; + char *flags = NULL; + + if (session) { + return SWITCH_STATUS_FALSE; + } + + if (switch_strlen_zero(cmd)) { + goto usage; + } + + if (!(mycmd = strdup(cmd))) { + goto usage; + } + + if ((argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) < 3) { + goto usage; + } + + uuid = argv[0]; + action = argv[1]; + path = argv[2]; + limit = argv[3] ? atoi(argv[3]) : 0; + flags = argv[4]; + + if (!(rsession = switch_core_session_locate(uuid))) { + stream->write_function(stream, "-Error Cannot locate session!\n"); + return SWITCH_STATUS_SUCCESS; + } + + if (switch_strlen_zero(action) || switch_strlen_zero(path)) { + goto usage; + } + + if (!strcasecmp(action, "start")) { + switch_ivr_displace_session(rsession, path, limit, flags); + } else if (!strcasecmp(action, "stop")) { + switch_ivr_stop_displace_session(rsession, path); + } else { + goto usage; + } + + goto done; + + usage: + + stream->write_function(stream, "INVALID SYNTAX\n"); + switch_safe_free(mycmd); + + + done: + + if (rsession) { + switch_core_session_rwunlock(rsession); + } + + switch_safe_free(mycmd); + return SWITCH_STATUS_SUCCESS; +} + SWITCH_STANDARD_API(pause_function) { switch_core_session_t *psession = NULL; @@ -1237,12 +1304,20 @@ /*.next */ &broadcast_api_interface }; +static switch_api_interface_t session_displace_api_interface = { + /*.interface_name */ "session_displace", + /*.desc */ "session displace", + /*.function */ session_displace_function, + /*.syntax */ "<uuid> [start|stop] <path> [<limit>] [mux]", + /*.next */ &broadcast_api_interface +}; + static switch_api_interface_t uuid_bridge_api_interface = { /*.interface_name */ "uuid_bridge", /*.desc */ "uuid_bridge", /*.function */ uuid_bridge_function, /*.syntax */ "<uuid> <other_uuid>", - /*.next */ &session_record_api_interface + /*.next */ &session_displace_api_interface }; static switch_api_interface_t status_api_interface = { 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 Thu Jun 14 21:47:48 2007 @@ -789,6 +789,43 @@ } +static void displace_session_function(switch_core_session_t *session, char *data) +{ + switch_channel_t *channel; + char *path = NULL; + uint32_t limit = 0; + char *argv[6]; + int x, argc; + char *lbuf = NULL; + char *flags = NULL; + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + if (data && (lbuf = switch_core_session_strdup(session, data)) + && (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) { + path = argv[0]; + for(x = 0; x < argc; x++) { + if (strchr(argv[x], '+')) { + limit = atoi(argv[x]); + } else if (!switch_strlen_zero(argv[x])) { + flags = argv[x]; + } + } + switch_ivr_displace_session(session, path, limit, flags); + } +} + + +static void stop_displace_session_function(switch_core_session_t *session, char *data) +{ + switch_channel_t *channel; + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + switch_ivr_stop_displace_session(session, data); +} + static void record_function(switch_core_session_t *session, char *data) { @@ -995,6 +1032,26 @@ &bridge_application_interface }; +static switch_application_interface_t displace_application_interface = { + /*.interface_name */ "displace", + /*.application_function */ displace_session_function, + /* long_desc */ "Displace audio from a file to the channels input", + /* short_desc */ "Displace File", + /* syntax */ "<path> [+time_limit_ms] [mux]", + /* flags */ SAF_NONE, + &speak_application_interface +}; + +static switch_application_interface_t stop_displace_application_interface = { + /*.interface_name */ "displace", + /*.application_function */ stop_displace_session_function, + /* long_desc */ "Stop Displacing to a file", + /* short_desc */ "Stop Displace File", + /* syntax */ "<path>", + /* flags */ SAF_NONE, + &displace_application_interface +}; + static switch_application_interface_t record_application_interface = { /*.interface_name */ "record", /*.application_function */ record_function, @@ -1002,7 +1059,7 @@ /* short_desc */ "Record File", /* syntax */ "<path> [+time_limit_ms]", /* flags */ SAF_NONE, - &speak_application_interface + &stop_displace_application_interface }; Modified: freeswitch/trunk/src/mod/applications/mod_soundtouch/mod_soundtouch.cpp ============================================================================== --- freeswitch/trunk/src/mod/applications/mod_soundtouch/mod_soundtouch.cpp (original) +++ freeswitch/trunk/src/mod/applications/mod_soundtouch/mod_soundtouch.cpp Thu Jun 14 21:47:48 2007 @@ -257,8 +257,13 @@ char *lbuf = NULL; int x; - if (switch_channel_get_private(channel, "_soundtouch_")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot run 2 at once on the same channel!\n"); + if ((bug = (switch_media_bug_t *) switch_channel_get_private(channel, "_soundtouch_"))) { + if (!switch_strlen_zero(data) && !strcasecmp(data, "stop")) { + switch_channel_set_private(channel, "_soundtouch_", NULL); + switch_core_media_bug_remove(session, &bug); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot run 2 at once on the same channel!\n"); + } return; } Modified: freeswitch/trunk/src/switch_core_codec.c ============================================================================== --- freeswitch/trunk/src/switch_core_codec.c (original) +++ freeswitch/trunk/src/switch_core_codec.c Thu Jun 14 21:47:48 2007 @@ -50,6 +50,8 @@ session->read_codec = codec; session->raw_read_frame.codec = session->read_codec; session->raw_write_frame.codec = session->read_codec; + session->enc_read_frame.codec = session->read_codec; + session->enc_write_frame.codec = session->read_codec; return SWITCH_STATUS_SUCCESS; } Modified: freeswitch/trunk/src/switch_core_io.c ============================================================================== --- freeswitch/trunk/src/switch_core_io.c (original) +++ freeswitch/trunk/src/switch_core_io.c Thu Jun 14 21:47:48 2007 @@ -241,7 +241,7 @@ do_bugs = 0; if (bp->callback) { bp->read_replace_frame_in = read_frame; - bp->read_replace_frame_out = NULL; + bp->read_replace_frame_out = read_frame; if ((ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ_REPLACE)) == SWITCH_TRUE) { read_frame = bp->read_replace_frame_out; } @@ -509,7 +509,7 @@ do_bugs = 0; if (bp->callback) { bp->write_replace_frame_in = write_frame; - bp->write_replace_frame_out = NULL; + bp->write_replace_frame_out = write_frame; if ((ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_WRITE_REPLACE)) == SWITCH_TRUE) { write_frame = bp->write_replace_frame_out; } Modified: freeswitch/trunk/src/switch_ivr_async.c ============================================================================== --- freeswitch/trunk/src/switch_ivr_async.c (original) +++ freeswitch/trunk/src/switch_ivr_async.c Thu Jun 14 21:47:48 2007 @@ -96,6 +96,151 @@ } +typedef struct { + switch_file_handle_t fh; + int mux; +} displace_helper_t; + +static switch_bool_t displace_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type) +{ + displace_helper_t *dh = (displace_helper_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: + if (dh) { + switch_core_file_close(&dh->fh); + } + break; + case SWITCH_ABC_TYPE_READ_REPLACE: + { + switch_frame_t *frame = switch_core_media_bug_get_read_replace_frame(bug); + if (dh && !dh->mux) { + memset(frame->data, 255, frame->datalen); + } + switch_core_media_bug_set_read_replace_frame(bug, frame); + } + break; + case SWITCH_ABC_TYPE_WRITE_REPLACE: + if (dh) { + switch_frame_t *frame = NULL; + switch_size_t len; + + frame = switch_core_media_bug_get_write_replace_frame(bug); + len = frame->samples; + + if (dh->mux) { + int16_t buf[1024]; + int16_t *fp = frame->data; + int x; + + switch_core_file_read(&dh->fh, buf, &len); + + for(x = 0; x < len; x++) { + int32_t mixed = fp[x] + buf[x]; + switch_normalize_to_16bit(mixed); + fp[x] = (int16_t) mixed; + } + } else { + switch_core_file_read(&dh->fh, frame->data, &len); + frame->samples = len; + frame->datalen = frame->samples * 2; + } + switch_core_media_bug_set_write_replace_frame(bug, frame); + } + break; + case SWITCH_ABC_TYPE_WRITE: + default: + break; + } + + return SWITCH_TRUE; +} + +SWITCH_DECLARE(switch_status_t) switch_ivr_stop_displace_session(switch_core_session_t *session, char *file) +{ + switch_media_bug_t *bug; + switch_channel_t *channel = switch_core_session_get_channel(session); + + assert(channel != NULL); + if ((bug = switch_channel_get_private(channel, file))) { + switch_channel_set_private(channel, file, NULL); + switch_core_media_bug_remove(session, &bug); + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_FALSE; + +} + +SWITCH_DECLARE(switch_status_t) switch_ivr_displace_session(switch_core_session_t *session, char *file, uint32_t limit, const char *flags) +{ + switch_channel_t *channel; + switch_codec_t *read_codec; + switch_media_bug_t *bug; + switch_status_t status; + time_t to = 0; + displace_helper_t *dh; + + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + if ((bug = switch_channel_get_private(channel, file))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Only 1 of the same file per channel please!\n"); + return SWITCH_STATUS_FALSE; + } + + if (!(dh = switch_core_session_alloc(session, sizeof(*dh)))) { + return SWITCH_STATUS_MEMERR; + } + + + + read_codec = switch_core_session_get_read_codec(session); + assert(read_codec != NULL); + + dh->fh.channels = read_codec->implementation->number_of_channels; + dh->fh.samplerate = read_codec->implementation->samples_per_second; + + + if (switch_core_file_open(&dh->fh, + file, + read_codec->implementation->number_of_channels, + read_codec->implementation->samples_per_second, + SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, + switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { + switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + switch_core_session_reset(session); + return SWITCH_STATUS_GENERR; + } + + switch_channel_answer(channel); + + if (limit) { + to = time(NULL) + limit; + } + + if (flags && strchr(flags, 'm')) { + dh->mux++; + } + + if ((status = switch_core_media_bug_add(session, displace_callback, dh, to, SMBF_WRITE_REPLACE | SMBF_READ_REPLACE, &bug)) != SWITCH_STATUS_SUCCESS) { + switch_core_file_close(&dh->fh); + return status; + } + + switch_channel_set_private(channel, file, bug); + + return SWITCH_STATUS_SUCCESS; +} + static switch_bool_t record_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type) { @@ -158,14 +303,20 @@ switch_status_t status; time_t to = 0; + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + if ((bug = switch_channel_get_private(channel, file))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Only 1 of the same file per channel please!\n"); + return SWITCH_STATUS_FALSE; + } + if (!fh) { if (!(fh = switch_core_session_alloc(session, sizeof(*fh)))) { return SWITCH_STATUS_MEMERR; } } - channel = switch_core_session_get_channel(session); - assert(channel != NULL); read_codec = switch_core_session_get_read_codec(session); assert(read_codec != NULL);
participants (1)
-
Freeswitch SVN