]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
add session_displace api and app
authorAnthony Minessale <anthony.minessale@gmail.com>
Fri, 15 Jun 2007 01:47:48 +0000 (01:47 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Fri, 15 Jun 2007 01:47:48 +0000 (01:47 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@5366 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/include/switch_ivr.h
src/mod/applications/mod_commands/mod_commands.c
src/mod/applications/mod_dptools/mod_dptools.c
src/mod/applications/mod_soundtouch/mod_soundtouch.cpp
src/switch_core_codec.c
src/switch_core_io.c
src/switch_ivr_async.c

index 73e8d02dda518c22ffb622b637eac1d7cd0dc326..d4e8b51b5dd05f9117ca878567e55efad76d60c2 100644 (file)
@@ -200,6 +200,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_unload_grammar(switch_c
 */
 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
index 2773fb71bea01040964ee46dfd1c2b818310c629..c130332cf39fa6919bfcc0a759e96fe8b78d47c7 100644 (file)
@@ -565,7 +565,7 @@ SWITCH_STANDARD_API(session_record_function)
                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 @@ SWITCH_STANDARD_API(session_record_function)
        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 @@ static switch_api_interface_t session_record_api_interface = {
        /*.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 = {
index 80941fd42b8fe1a11fba5241e61c30f32ecc2420..babfc9937edfc9ed3b09edfbdf9c0470de605de3 100644 (file)
@@ -789,6 +789,43 @@ static void playback_function(switch_core_session_t *session, char *data)
 
 }
 
+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 @@ static switch_application_interface_t speak_application_interface = {
        &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 @@ static switch_application_interface_t record_application_interface = {
        /* short_desc */ "Record File",
        /* syntax */ "<path> [+time_limit_ms]",
        /* flags */ SAF_NONE,
-       &speak_application_interface
+       &stop_displace_application_interface
 };
 
 
index 62816f274ec0ef795eda4b89bb238f4073f1cb4d..2bb1e03c4aa79d6acdd4ea8ba5dce49ff207f22b 100644 (file)
@@ -257,8 +257,13 @@ static void soundtouch_start_function(switch_core_session_t *session, char *data
        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;
     }
 
index 770e11ff3ac17197e01d8aaeb74b0b38587313c2..3b840a354dd2697efe75100f71f33f686bd7479b 100644 (file)
@@ -50,6 +50,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_set_read_codec(switch_core_s
        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;
 }
index fc827bb4d5215800486ce58241a9e5da7e7d07b5..ea46448f81a7e05631462b0c92f72672a12d8cc7 100644 (file)
@@ -241,7 +241,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
                                        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 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
                                        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;
                                                }
index e081667e8bc2312abe57d34154982cc7b8e3dbe0..537eeb945a348f969b4b3ad2bdb3d644ee49c72d 100644 (file)
@@ -96,6 +96,151 @@ SWITCH_DECLARE(void) switch_ivr_session_echo(switch_core_session_t *session)
 }
 
 
+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_DECLARE(switch_status_t) switch_ivr_record_session(switch_core_session_t
        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);