]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
upgrade fax_detect to tone_detect
authorAnthony Minessale <anthony.minessale@gmail.com>
Sat, 16 Jun 2007 02:25:40 +0000 (02:25 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Sat, 16 Jun 2007 02:25:40 +0000 (02:25 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@5379 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/include/switch_ivr.h
src/include/switch_types.h
src/mod/applications/mod_commands/mod_commands.c
src/mod/applications/mod_dptools/mod_dptools.c
src/switch_event.c
src/switch_ivr_async.c

index d4e8b51b5dd05f9117ca878567e55efad76d60c2..52b7f6f9e657be974fc5405c2930e04bd2722e61 100644 (file)
@@ -233,18 +233,27 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_stop_inband_dtmf_session(switch_core_
 SWITCH_DECLARE(void) switch_ivr_session_echo(switch_core_session_t *session);
 
 /*!
-  \brief Stop looking for FAX CNG
+  \brief Stop looking for TONES
   \param session the session to stop looking
   \return SWITCH_STATUS_SUCCESS if all is well
 */
-SWITCH_DECLARE(switch_status_t) switch_ivr_stop_fax_detect_session(switch_core_session_t *session);
+SWITCH_DECLARE(switch_status_t) switch_ivr_stop_tone_detect_session(switch_core_session_t *session);
 
 /*!
-  \brief Start looking for FAX CNG
+  \brief Start looking for TONES
   \param session the session to start looking
+  \param key the name of the tone.
+  \param tone_spec comma sep list of tone freqs
+  \param flags one or both of 'r' and 'w'
+  \param timeout timeout
+  \param app optional application to execute when tone is found
+  \param data optional data for appliaction
   \return SWITCH_STATUS_SUCCESS if all is well
 */
-SWITCH_DECLARE(switch_status_t) switch_ivr_fax_detect_session(switch_core_session_t *session);
+SWITCH_DECLARE(switch_status_t) switch_ivr_tone_detect_session(switch_core_session_t *session, 
+                                                                                                                          const char *key, const char *tone_spec,
+                                                                                                                          const char *flags, time_t timeout,
+                                                                                                                          const char *app, const char *data);
 
 
 
index 129c5da7c1d832a5868df0320b765c573c3ee4f2..9a0b5774e6997bb9d70b6f80bf902545a372efcb 100644 (file)
@@ -852,7 +852,7 @@ typedef enum {
        SWITCH_EVENT_CODEC                              - Codec Change
        SWITCH_EVENT_BACKGROUND_JOB             - Background Job
        SWITCH_EVENT_DETECTED_SPEECH    - Detected Speech
-       SWITCH_EVENT_DETECTED_FAX       - Detected Fax CNG Tone
+       SWITCH_EVENT_DETECTED_TONE      - Detected Tone
        SWITCH_EVENT_PRIVATE_COMMAND    - A private command event 
        SWITCH_EVENT_HEARTBEAT                  - Machine is alive
        SWITCH_EVENT_TRAP                               - Error Trap
@@ -902,7 +902,7 @@ typedef enum {
        SWITCH_EVENT_CODEC,
        SWITCH_EVENT_BACKGROUND_JOB,
        SWITCH_EVENT_DETECTED_SPEECH,
-       SWITCH_EVENT_DETECTED_FAX,
+       SWITCH_EVENT_DETECTED_TONE,
        SWITCH_EVENT_PRIVATE_COMMAND,
        SWITCH_EVENT_HEARTBEAT,
        SWITCH_EVENT_TRAP,
index c130332cf39fa6919bfcc0a759e96fe8b78d47c7..14f8216d7912f88067b5e298664b6a2278332d86 100644 (file)
@@ -276,6 +276,51 @@ done:
        return SWITCH_STATUS_SUCCESS;
 }
 
+SWITCH_STANDARD_API(tone_detect_session_function)
+{
+       char *argv[6] = { 0 };
+       int argc;
+       char *mydata = NULL;
+       time_t to = 0;
+       switch_core_session_t *rsession;
+       
+       mydata = switch_core_session_strdup(session, cmd);
+       if ((argc = switch_separate_string(mydata, ' ', argv, sizeof(argv) / sizeof(argv[0]))) < 3) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "INVALID ARGS!\n");
+       }
+
+       if (!(rsession = switch_core_session_locate(argv[0]))) {
+               stream->write_function(stream, "-Error Cannot locate session!\n");
+               return SWITCH_STATUS_SUCCESS;
+       }
+
+       if (argv[4]) {
+               uint32_t mto;
+               if (*argv[2] == '+') {
+                       if ((mto = atoi(argv[3]+1)) > 0) {
+                               to = time(NULL) + mto;
+                       } else {
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "INVALID Timeout!\n");
+                               goto done;
+                       }
+               } else {
+                       if ((to = atoi(argv[3])) < time(NULL)) {
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "INVALID Timeout!\n");
+                               to = 0;
+                               goto done;
+                       }
+               }
+       }
+
+       switch_ivr_tone_detect_session(rsession, argv[1], argv[2], argv[3], to, argv[5], argv[6]);
+       stream->write_function(stream, "Enabling tone detection '%s' '%s' '%s'\n", argv[1], argv[2], argv[3]);
+
+ done:
+
+       switch_core_session_rwunlock(rsession);
+
+       return SWITCH_STATUS_SUCCESS;
+}
 
 SWITCH_STANDARD_API(sched_transfer_function)
 {
@@ -1385,13 +1430,22 @@ static switch_api_interface_t kill_api_interface = {
        /*.next */ &reload_api_interface
 };
 
+static switch_api_interface_t tone_detect_session_interface = {
+       /*.interface_name */ "tone_Detect",
+       /*.desc */ "Start Tone Detection on a channel",
+       /*.function */ tone_detect_session_function,
+       /*.syntax */
+       "<uuid> <key> <tone_spec> [<flags> <timeout> <app> <args>]",
+       /*.next */ &kill_api_interface
+};
+
 static switch_api_interface_t originate_api_interface = {
        /*.interface_name */ "originate",
        /*.desc */ "Originate a Call",
        /*.function */ originate_function,
        /*.syntax */
        "<call url> <exten>|&<application_name>(<app_args>) [<dialplan>] [<context>] [<cid_name>] [<cid_num>] [<timeout_sec>]",
-       /*.next */ &kill_api_interface
+       /*.next */ &tone_detect_session_interface
 };
 
 static switch_loadable_module_interface_t commands_module_interface = {
index 27267ea9946ad8c26feb01feec4433dbb9d00afa..6e970b66657cb6f33f547d771f53868c56243bde 100644 (file)
@@ -664,20 +664,45 @@ static void stop_dtmf_session_function(switch_core_session_t *session, char *dat
 
 static void fax_detect_session_function(switch_core_session_t *session, char *data)
 {
-       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Enabling fax detection\n");
-       switch_ivr_fax_detect_session(session);
+       switch_ivr_tone_detect_session(session, "fax", "1100.0", "r", 0, NULL, NULL);
 }
 
-static void system_session_function(switch_core_session_t *session, char *data)
+static void tone_detect_session_function(switch_core_session_t *session, char *data)
 {
-    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Executing command: %s\n",data);
-    system(data);
+       char *argv[6] = { 0 };
+       int argc;
+       char *mydata = NULL;
+       time_t to = 0;
+
+       mydata = switch_core_session_strdup(session, data);
+       if ((argc = switch_separate_string(mydata, ' ', argv, sizeof(argv) / sizeof(argv[0]))) < 2) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "INVALID ARGS!\n");
+       }
+       if (argv[3]) {
+               uint32_t mto;
+               if (*argv[2] == '+') {
+                       if ((mto = atoi(argv[2]+1)) > 0) {
+                               to = time(NULL) + mto;
+                       } else {
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "INVALID Timeout!\n");
+                       }
+               } else {
+                       if ((to = atoi(argv[2])) < time(NULL)) {
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "INVALID Timeout!\n");
+                               to = 0;
+                       }
+               }
+       }
+
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Enabling tone detection '%s' '%s'\n", argv[0], argv[1]);
+       
+       switch_ivr_tone_detect_session(session, argv[0], argv[1], argv[2], to, argv[4], argv[5]);
 }
 
 static void stop_fax_detect_session_function(switch_core_session_t *session, char *data)
 {
-       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Disabling fax detection\n");
-       switch_ivr_stop_fax_detect_session(session);
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Disabling tone detection\n");
+       switch_ivr_stop_tone_detect_session(session);
 }
 
 static void echo_function(switch_core_session_t *session, char *data)
@@ -1018,15 +1043,6 @@ static switch_api_interface_t presence_api_interface = {
        /*.next */ &dptools_api_interface
 };
 
-static switch_application_interface_t system_application_interface = {
-    /*.interface_name */ "system",
-    /*.application_function */ system_session_function,
-    /* long_desc */ "Execute a system command",
-    /* short_desc */ "Execute a system command",
-    /* syntax */ "<command>",
-    /* flags */ SAF_NONE,
-    /*.next */ NULL
-};
 
 static switch_application_interface_t bridge_application_interface = {
        /*.interface_name */ "bridge",
@@ -1034,8 +1050,7 @@ static switch_application_interface_t bridge_application_interface = {
        /* long_desc */ "Bridge the audio between two sessions",
        /* short_desc */ "Bridge Audio",
        /* syntax */ "<channel_url>",
-       /* flags */ SAF_SUPPORT_NOMEDIA,
-       /* next */ &system_application_interface
+       /* flags */ SAF_SUPPORT_NOMEDIA
 };
 
 static switch_application_interface_t speak_application_interface = {
@@ -1129,6 +1144,17 @@ static switch_application_interface_t echo_application_interface = {
        /*.next */ &park_application_interface
 };
 
+
+static switch_application_interface_t tone_detect_application_interface = {
+       /*.interface_name */ "tone_detect",
+       /*.application_function */ tone_detect_session_function,
+       /* long_desc */ "Detect tones",
+       /* short_desc */ "Detect tones",
+       /* syntax */ "",
+       /* flags */ SAF_NONE,
+       /*.next */ &echo_application_interface
+};
+
 static switch_application_interface_t fax_detect_application_interface = {
        /*.interface_name */ "fax_detect",
        /*.application_function */ fax_detect_session_function,
@@ -1136,14 +1162,14 @@ static switch_application_interface_t fax_detect_application_interface = {
        /* short_desc */ "Detect faxes",
        /* syntax */ "",
        /* flags */ SAF_NONE,
-       /*.next */ &echo_application_interface
+       /*.next */ &tone_detect_application_interface
 };
 
-static switch_application_interface_t stop_fax_detect_application_interface = {
-       /*.interface_name */ "stop_fax_detect",
+static switch_application_interface_t stop_tone_detect_application_interface = {
+       /*.interface_name */ "stop_tone_detect",
        /*.application_function */ stop_fax_detect_session_function,
-       /* long_desc */ "Stop detecting fax send tones",
-       /* short_desc */ "stop detecting faxes",
+       /* long_desc */ "Stop detecting tones",
+       /* short_desc */ "stop detecting tones",
        /* syntax */ "",
        /* flags */ SAF_NONE,
        /* next */ &fax_detect_application_interface
@@ -1156,7 +1182,7 @@ static switch_application_interface_t dtmf_application_interface = {
        /* short_desc */ "Detect dtmf",
        /* syntax */ "",
        /* flags */ SAF_NONE,
-       /* next */ &stop_fax_detect_application_interface
+       /* next */ &stop_tone_detect_application_interface
 };
 
 static switch_application_interface_t stop_dtmf_application_interface = {
index 7a408108f8a6f36e744d4461da86806f3e09f8b7..3390b46989e28e1e63acf3448b8b526f95153d2d 100644 (file)
@@ -133,7 +133,7 @@ static char *EVENT_NAMES[] = {
        "CODEC",
        "BACKGROUND_JOB",
        "DETECTED_SPEECH",
-       "DETECTED_FAX",
+       "DETECTED_TONE",
        "PRIVATE_COMMAND",
        "HEARTBEAT",
        "TRAP",
index afc1780dc50f3a8dc9efbe43ba924571016610f4..0ed4c4da64f27b832485b3ea96f62508af813592 100644 (file)
@@ -138,18 +138,18 @@ static switch_bool_t displace_callback(switch_media_bug_t *bug, void *user_data,
                        if (dh->mux) {
                                int16_t buf[1024];
                                int16_t *fp = frame->data;
-                               int x;
+                               uint32_t x;
                                
                                switch_core_file_read(&dh->fh, buf, &len);
                                
-                               for(x = 0; x < len; x++) {
+                               for(x = 0; x < (uint32_t) 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->samples = (uint32_t) len;
                                frame->datalen = frame->samples * 2;
                        }
                        switch_core_media_bug_set_write_replace_frame(bug, frame);
@@ -477,117 +477,211 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_inband_dtmf_session(switch_core_sessi
 }
 
 
+#define MAX_TONES 16
 typedef struct {
-  switch_core_session_t *session;
-  teletone_multi_tone_t mt;
-} switch_fax_detect_t;
+       teletone_multi_tone_t mt;
+       char *app;
+       char *data;
+       char *key;
+       teletone_tone_map_t map;
+       int up;
+} switch_tone_detect_t;
+
+
+typedef struct {
+       switch_tone_detect_t list[MAX_TONES+1];
+       int index;
+       switch_media_bug_t *bug;
+       switch_core_session_t *session;
+} switch_tone_container_t;
 
-static switch_bool_t fax_detect_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
+static switch_bool_t tone_detect_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
 {
-  switch_fax_detect_t *pvt = (switch_fax_detect_t *) user_data;
-  uint8_t data[SWITCH_RECOMMENDED_BUFFER_SIZE];
-  switch_frame_t frame = { 0 };
-  //  switch_channel_t *channel = switch_core_session_get_channel(pvt->session);
-
-  //  assert(channel != NULL);
-  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_READ:
-    if (switch_core_media_bug_read(bug, &frame) == SWITCH_STATUS_SUCCESS) {
-      if(teletone_multi_tone_detect(&pvt->mt, frame.data, frame.samples)) {
-       switch_event_t *event;
+       switch_tone_container_t *cont = (switch_tone_container_t *) user_data;
+       switch_frame_t *frame = NULL;
+       int i = 0;
+
+       switch (type) {
+       case SWITCH_ABC_TYPE_INIT:
+               break;
+       case SWITCH_ABC_TYPE_CLOSE:
+               break;
+       case SWITCH_ABC_TYPE_READ_REPLACE:
+               frame = switch_core_media_bug_get_read_replace_frame(bug);
+       case SWITCH_ABC_TYPE_WRITE_REPLACE:
+               {
 
-       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FAX CNG DETECTED\n");
+                       if (!frame) {
+                               frame = switch_core_media_bug_get_write_replace_frame(bug);
+                       }
+                       
+                       for (i = 0 ; i < cont->index; cont++) {
+                               if (cont->list[i].up && teletone_multi_tone_detect(&cont->list[i].mt, frame->data, frame->samples)) {
+                                       switch_event_t *event;
+                                       
+                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "TONE %s DETECTED\n", cont->list[i].key);
+
+                                       if (cont->list[i].app) {
+                                               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", "%s", cont->list[i].app);
+                                                       switch_event_add_header(event, SWITCH_STACK_BOTTOM, "execute-app-arg", "%s", cont->list[i].data);
+                                                       switch_event_add_header(event, SWITCH_STACK_BOTTOM, "lead-frames", "%d", 5);
+                                                       switch_core_session_queue_private_event(cont->session, &event);
+                                               }
+                                       }
 
-       if (switch_event_create(&event, SWITCH_EVENT_DETECTED_FAX) == SWITCH_STATUS_SUCCESS) {
-         switch_event_t *dup;
+                                       cont->list[cont->index].up = 0;
 
-         switch_event_add_header(event, SWITCH_STACK_BOTTOM, "fax", "detected");
-           
-         if (switch_event_dup(&dup, event) == SWITCH_STATUS_SUCCESS) {
-           switch_event_fire(&dup);
-         }
+                                       if (switch_event_create(&event, SWITCH_EVENT_DETECTED_TONE) == SWITCH_STATUS_SUCCESS) {
+                                               switch_event_t *dup;
+                                               switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Detected-Tone", "%s", cont->list[i].key);
+                                               
+                                               if (switch_event_dup(&dup, event) == SWITCH_STATUS_SUCCESS) {
+                                                       switch_event_fire(&dup);
+                                               }
            
-
-         if (switch_core_session_queue_event(pvt->session, &event) != SWITCH_STATUS_SUCCESS) {
-           switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Event queue failed!\n");
-           switch_event_add_header(event, SWITCH_STACK_BOTTOM, "delivery-failure", "true");
-           switch_event_fire(&event);
-         }
+                                               if (switch_core_session_queue_event(cont->session, &event) != SWITCH_STATUS_SUCCESS) {
+                                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Event queue failed!\n");
+                                                       switch_event_add_header(event, SWITCH_STACK_BOTTOM, "delivery-failure", "true");
+                                                       switch_event_fire(&event);
+                                               }
+                                       }
+                               }
+                       }
+               }
+               break;
+       case SWITCH_ABC_TYPE_WRITE:
+       default:
+               break;
        }
-      }
-    }
-    break;
-  case SWITCH_ABC_TYPE_WRITE:
-  default:
-    break;
-  }
-  return SWITCH_TRUE;
+       return SWITCH_TRUE;
 }
 
-SWITCH_DECLARE(switch_status_t) switch_ivr_stop_fax_detect_session(switch_core_session_t *session)
+SWITCH_DECLARE(switch_status_t) switch_ivr_stop_tone_detect_session(switch_core_session_t *session)
 {
-  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, "fax"))) {
-    switch_channel_set_private(channel, "fax", NULL);
-    switch_core_media_bug_remove(session, &bug);
-    return SWITCH_STATUS_SUCCESS;
-  }
-
-  return SWITCH_STATUS_FALSE;
+       switch_channel_t *channel = switch_core_session_get_channel(session);
+       switch_tone_container_t *cont;
+       
+       assert(channel != NULL);
+       if ((cont = switch_channel_get_private(channel, "_tone_detect_"))) {
+               switch_channel_set_private(channel, "_tone_detect_", NULL);
+               switch_core_media_bug_remove(session, &cont->bug);
+               return SWITCH_STATUS_SUCCESS;
+       }
 
+       return SWITCH_STATUS_FALSE;
+       
 }
 
-SWITCH_DECLARE(switch_status_t) switch_ivr_fax_detect_session(switch_core_session_t *session)
+SWITCH_DECLARE(switch_status_t) switch_ivr_tone_detect_session(switch_core_session_t *session, 
+                                                                                                                          const char *key, const char *tone_spec,
+                                                                                                                          const char *flags, time_t timeout,
+                                                                                                                          const char *app, const char *data)
 {
   switch_channel_t *channel;
   switch_codec_t *read_codec;
-  switch_media_bug_t *bug;
   switch_status_t status;
-  switch_fax_detect_t *pvt;
-  teletone_tone_map_t *map;
-  int i;
+  switch_tone_container_t *cont = NULL;
+  char *p, *next;
+  int i = 0, ok = 0;
+
+  switch_media_bug_flag_t bflags = 0;
 
   channel = switch_core_session_get_channel(session);
   assert(channel != NULL);
 
-
   read_codec = switch_core_session_get_read_codec(session);
   assert(read_codec != NULL);
+  
+  if (switch_strlen_zero(key)) {
+         switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Key Specified!\n");
+         return SWITCH_STATUS_FALSE;
+  }
+  
+  if ((cont = switch_channel_get_private(channel, "_tone_detect_"))) {
+         if (cont->index >= MAX_TONES) {
+                 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Max Tones Reached!\n");
+                 return SWITCH_STATUS_FALSE;
+         }
 
-  if (!(pvt = switch_core_session_alloc(session, sizeof(*pvt)))) {
-    return SWITCH_STATUS_MEMERR;
+         for(i = 0; i < cont->index; i++) {
+                 if (!strcasecmp(key, cont->list[cont->index].key )) {
+                         switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Renabling %s\n", key);
+                         cont->list[cont->index].up = 1;
+                         teletone_multi_tone_init(&cont->list[i].mt, &cont->list[i].map);
+                         return SWITCH_STATUS_SUCCESS;
+                 }
+         }
   }
 
-  if (!(map = switch_core_session_alloc(session, sizeof(*map)))) {
-    return SWITCH_STATUS_MEMERR;
+  if (switch_strlen_zero(tone_spec)) {
+         switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Spec Specified!\n");
+         return SWITCH_STATUS_FALSE;
   }
 
-  for(i=0;i<TELETONE_MAX_TONES;i++) {
-    map->freqs[i] = 1100.0;
+  if (!cont && !(cont = switch_core_session_alloc(session, sizeof(*cont)))) {
+         return SWITCH_STATUS_MEMERR;
   }
-  pvt->mt.sample_rate = read_codec->implementation->samples_per_second;
-  pvt->session = session;
 
-  teletone_multi_tone_init(&pvt->mt, map);
+  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Adding tone spec %s index %d\n", tone_spec, cont->index);
 
-  switch_channel_answer(channel);
+  i = 0;
+  p = (char *) tone_spec;
+
+  do {
+         teletone_process_t this;
+         next = strchr(p, ',');
+         while(*p == ' ') p++;
+         if ((this = (teletone_process_t) atof(p))) {
+                 ok++;
+                 cont->list[cont->index].map.freqs[i++] = this;
+         }
+         if (next) {
+                 p = next + 1;
+         }
+  } while (next);
+
+  if (!ok) {
+         switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid tone spec!\n");
+         return SWITCH_STATUS_FALSE;
 
-  if ((status = switch_core_media_bug_add(session, fax_detect_callback, pvt, 0, SMBF_READ_STREAM, &bug)) != SWITCH_STATUS_SUCCESS) {
-    return status;
   }
 
-  switch_channel_set_private(channel, "fax", bug);
+  cont->list[cont->index].key = switch_core_session_strdup(session, key);
+
+  if (app) {
+         cont->list[cont->index].app = switch_core_session_strdup(session, app);
+  }
+  
+  if (data) {
+         cont->list[cont->index].data = switch_core_session_strdup(session, data);
+  }
+
+  cont->list[cont->index].up = 1;
+  cont->list[cont->index].mt.sample_rate = read_codec->implementation->samples_per_second;
+  teletone_multi_tone_init(&cont->list[cont->index].mt, &cont->list[cont->index].map);
+  cont->session = session;
+  
+  switch_channel_answer(channel);
+  
+  if (switch_strlen_zero(flags)) {
+         bflags = SMBF_READ_REPLACE;
+  } else {
+         if (strchr(flags, 'r')) {
+                 bflags |= SMBF_READ_REPLACE;
+         } else if (strchr(flags, 'w')) {
+                 bflags |= SMBF_WRITE_REPLACE;
+         }
+  }
+
+  if ((status = switch_core_media_bug_add(session, tone_detect_callback, cont, timeout, bflags, &cont->bug)) != SWITCH_STATUS_SUCCESS) {
+         return status;
+  }
 
+  switch_channel_set_private(channel, "_tone_detect_", cont);
+  cont->index++;
+  
   return SWITCH_STATUS_SUCCESS;
 }