fixup
[lcr.git] / chan_lcr.c
index 302716e..a396013 100644 (file)
@@ -238,6 +238,8 @@ void chan_lcr_log(int type, const char *file, int line, const char *function, st
        char ast_text[128] = "NULL";
        va_list args;
 
+       if (!option_debug) return;
+
        ast_mutex_lock(&log_lock);
 
        va_start(args,fmt);
@@ -255,8 +257,8 @@ void chan_lcr_log(int type, const char *file, int line, const char *function, st
 #endif
        ast_text[sizeof(ast_text)-1] = '\0';
 
-//     ast_log(type, file, line, function, "[call=%s ast=%s] %s", call_text, ast_text, buffer);
-       printf("[call=%s ast=%s line=%d] %s", call_text, ast_text, line, buffer);
+       ast_log(type, file, line, function, "[call=%s ast=%s] %s", call_text, ast_text, buffer);
+//     printf("[call=%s ast=%s line=%d] %s", call_text, ast_text, line, buffer);
 
        ast_mutex_unlock(&log_lock);
 }
@@ -331,6 +333,10 @@ struct chan_call *alloc_call(void)
        }
        fcntl((*callp)->pipe[0], F_SETFL, O_NONBLOCK);
        CDEBUG(*callp, NULL, "Call instance allocated.\n");
+
+       /* unset dtmf (default, use option 'd' to enable) */
+       (*callp)->dsp_dtmf = 0;
+
        return *callp;
 }
 
@@ -426,13 +432,13 @@ void apply_opt(struct chan_call *call, char *data)
                                send_message(MESSAGE_NOTIFY, call->ref, &newparam);
                        }
                        break;
-               case 'n':
+               case 'D':
                        if (opt[1] != '\0') {
-                               CERROR(call, call->ast, "Option 'n' (no DTMF) expects no parameter.\n", opt);
+                               CERROR(call, call->ast, "Option 'D' (DTMF) expects no parameter.\n", opt);
                                break;
                        }
-                       CDEBUG(call, call->ast, "Option 'n' (no DTMF).\n");
-                       call->dsp_dtmf = 0;
+                       CDEBUG(call, call->ast, "Option 'D' (DTMF).\n");
+                       call->dsp_dtmf = 1;
                        break;
 #if 0
                case 'c':
@@ -513,43 +519,22 @@ void apply_opt(struct chan_call *call, char *data)
                        break;
 #endif
                case 'f':
-                       if (opt[1] == '\0') {
-                               CERROR(call, call->ast, "Option 'f' (faxdetect) expects parameter.\n", opt);
+                       if (opt[1] != '\0') {
+                               CERROR(call, call->ast, "Option 'f' (faxdetect) expects no parameter.\n", opt);
                                break;
                        }
-                       call->faxdetect=atoi(opt+1);
-                       if (!call->dsp)
-                               call->dsp=ast_dsp_new();
-                       if (call->dsp) {
-                               #ifdef LCR_FOR_CALLWEAVER
-                               ast_dsp_set_features(call->dsp, DSP_FEATURE_DTMF_DETECT| DSP_FEATURE_FAX_CNG_DETECT);
-                               #endif
-                               #ifdef LCR_FOR_ASTERISK
-                               #ifdef DSP_FEATURE_DTMF_DETECT
-                               ast_dsp_set_features(call->dsp, DSP_FEATURE_DTMF_DETECT| DSP_FEATURE_FAX_DETECT);
-                               #else
-                               ast_dsp_set_features(call->dsp, DSP_FEATURE_DIGIT_DETECT| DSP_FEATURE_FAX_DETECT);
-                               #endif
-
-                               #endif
-                               if (!call->trans) {
-                                       #ifdef LCR_FOR_CALLWEAVER
-                                       call->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, 8000, (options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW, 8000);
-                                       #endif
-                                       #ifdef LCR_FOR_ASTERISK
-                                       #if ASTERISK_VERSION_NUM < 100000
-                                       call->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, (options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW);
-                                       #else
-                                       struct ast_format src;
-                                       struct ast_format dst;
-                                       ast_format_set(&dst, AST_FORMAT_SLINEAR, 0);
-                                       ast_format_set(&dst,(options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW , 0);
-                                       call->trans=ast_translator_build_path(&dst, &src);
-                                       #endif
-                                       #endif
-                               }
+                       call->faxdetect = 1;
+                       call->dsp_dtmf = 0;
+                       CDEBUG(call, call->ast, "Option 'f' (faxdetect).\n");
+                       break;
+               case 'a':
+                       if (opt[1] != '\0') {
+                               CERROR(call, call->ast, "Option 'a' (asterisk DTMF) expects no parameter.\n", opt);
+                               break;
                        }
-                       CDEBUG(call, call->ast, "Option 'f' (faxdetect) with config '%s'.\n", call->faxdetect);
+                       call->ast_dsp = 1;
+                       call->dsp_dtmf = 0;
+                       CDEBUG(call, call->ast, "Option 'a' (Asterisk DTMF detection).\n");
                        break;
                case 'r':
                        if (opt[1] != '\0') {
@@ -604,6 +589,40 @@ void apply_opt(struct chan_call *call, char *data)
                        CERROR(call, call->ast, "Option '%s' unknown.\n", opt);
                }
        }
+
+       if (call->faxdetect || call->ast_dsp) {
+               if (!call->dsp)
+                       call->dsp=ast_dsp_new();
+               if (call->dsp) {
+                       #ifdef LCR_FOR_CALLWEAVER
+                       ast_dsp_set_features(call->dsp, DSP_FEATURE_DTMF_DETECT | ((call->faxdetect) ? DSP_FEATURE_FAX_CNG_DETECT : 0));
+                       #endif
+                       #ifdef LCR_FOR_ASTERISK
+                       #ifdef DSP_FEATURE_DTMF_DETECT
+                       ast_dsp_set_features(call->dsp, DSP_FEATURE_DTMF_DETECT | ((call->faxdetect) ? DSP_FEATURE_FAX_DETECT : 0));
+                       #else
+                       ast_dsp_set_features(call->dsp, DSP_FEATURE_DIGIT_DETECT | ((call->faxdetect) ? DSP_FEATURE_FAX_DETECT : 0));
+                       #endif
+
+                       #endif
+                       if (!call->trans) {
+                               #ifdef LCR_FOR_CALLWEAVER
+                               call->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, 8000, (options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW, 8000);
+                               #endif
+                               #ifdef LCR_FOR_ASTERISK
+                               #if ASTERISK_VERSION_NUM < 100000
+                               call->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, (options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW);
+//                             #else
+//                             struct ast_format src;
+//                             struct ast_format dst;
+//                             ast_format_set(&dst, AST_FORMAT_SLINEAR, 0);
+//                             ast_format_set(&dst,(options.law=='a')?AST_FORMAT_ALAW:AST_FORMAT_ULAW , 0);
+//                             call->trans=ast_translator_build_path(&dst, &src);
+                               #endif
+                               #endif
+                       }
+               }
+       }
 }
 
 /*
@@ -633,8 +652,6 @@ static void send_setup_to_lcr(struct chan_call *call)
                strncpy(newparam.setup.dialinginfo.keypad, call->dialstring, sizeof(newparam.setup.dialinginfo.keypad)-1);
        else
                strncpy(newparam.setup.dialinginfo.id, call->dialstring, sizeof(newparam.setup.dialinginfo.id)-1);
-       if (!!strcmp(call->interface, "pbx"))
-               strncpy(newparam.setup.dialinginfo.interfaces, call->interface, sizeof(newparam.setup.dialinginfo.interfaces)-1);
        newparam.setup.callerinfo.itype = INFO_ITYPE_CHAN;
        newparam.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
        strncpy(newparam.setup.callerinfo.display, call->display, sizeof(newparam.setup.callerinfo.display)-1);
@@ -989,8 +1006,8 @@ static void lcr_in_setup(struct chan_call *call, int message_type, union paramet
                strncpy(ast->context, param->setup.callerinfo.interface, AST_MAX_CONTEXT-1);
 #else
                ast_channel_exten_set(ast, param->setup.dialinginfo.id);
-       if (param->setup.context[0])
-               ast_channel_context_set(ast, param->setup.context);
+       if (param->setup.dialinginfo.context[0])
+               ast_channel_context_set(ast, param->setup.dialinginfo.context);
        else
                ast_channel_context_set(ast, param->setup.callerinfo.interface);
 #endif
@@ -1401,7 +1418,9 @@ static void lcr_in_information(struct chan_call *call, int message_type, union p
 #if ASTERISK_VERSION_NUM < 110000
                strncat(ast->exten, param->information.id, AST_MAX_EXTENSION-1);
 #else
-               ast_channel_exten_set(ast, param->information.id);
+               char *tmp[AST_MAX_EXTENSION];
+               snprintf(tmp,AST_MAX_EXTENSION,"%s%s",ast_channel_exten(ast),param->information.id);
+               ast_channel_exten_set(ast, tmp);
 #endif
                lcr_start_pbx(call, ast, param->information.sending_complete);
                return;
@@ -1427,8 +1446,21 @@ static void lcr_in_information(struct chan_call *call, int message_type, union p
 
        /* use bridge to forware message not supported by asterisk */
        if (call->state == CHAN_LCR_STATE_CONNECT) {
-               CDEBUG(call, call->ast, "Call is connected, bridging.\n");
-               bridge_message_if_bridged(call, message_type, param);
+               if (call->bridge_call) {
+                       CDEBUG(call, call->ast, "Call is connected, bridging.\n");
+                       bridge_message_if_bridged(call, message_type, param);
+               } else {
+                       if (call->dsp_dtmf) {
+                               if (!wake_global) {
+                                       wake_global = 1;
+                                       char byte = 0;
+                                       int rc;
+                                       rc = write(wake_pipe[1], &byte, 1);
+                               }
+                               strncat(call->queue_string, param->information.id, sizeof(call->queue_string)-1);
+                       } else
+                               CDEBUG(call, call->ast, "LCR's DTMF detection is disabled.\n");
+               }
        }
 }
 
@@ -1505,7 +1537,7 @@ void lcr_in_dtmf(struct chan_call *call, int val)
                return;
 
        if (!call->dsp_dtmf) {
-               CDEBUG(call, call->ast, "Recognised DTMF digit '%c', but ignoring. This is fixed in later mISDN driver.\n", val);
+               CDEBUG(call, call->ast, "Recognised DTMF digit '%c' by LCR, but ignoring. (disabled by option)\n", val);
                return;
        }
 
@@ -1548,8 +1580,6 @@ int receive_message(int message_type, unsigned int ref, union parameter *param)
                        /* set ref */
                        call->ref = ref;
                        call->ref_was_assigned = 1;
-                       /* set dtmf (default, use option 'n' to disable */
-                       call->dsp_dtmf = 1;
                        /* wait for setup (or release from asterisk) */
                } else {
                        /* new ref, as requested from this remote application */
@@ -1563,8 +1593,6 @@ int receive_message(int message_type, unsigned int ref, union parameter *param)
                        /* store new ref */
                        call->ref = ref;
                        call->ref_was_assigned = 1;
-                       /* set dtmf (default, use option 'n' to disable */
-                       call->dsp_dtmf = 1;
                        /* send pending setup info */
                        if (call->state == CHAN_LCR_STATE_OUT_PREPARE)
                                send_setup_to_lcr(call);
@@ -1580,6 +1608,7 @@ int receive_message(int message_type, unsigned int ref, union parameter *param)
                                return 0;
                        }
                }
+               send_message(MESSAGE_ENABLEKEYPAD, call->ref, &newparam);
                return 0;
        }
 
@@ -1659,6 +1688,10 @@ int receive_message(int message_type, unsigned int ref, union parameter *param)
                rc = write(call->pipe[1], param->traffic.data, param->traffic.len);
                break;
 
+               case MESSAGE_DTMF:
+               lcr_in_dtmf(call, param->dtmf);
+               break;
+
                default:
                CDEBUG(call, call->ast, "Message %d from LCR unhandled.\n", message_type);
                break;
@@ -2394,6 +2427,7 @@ static int lcr_call(struct ast_channel *ast, char *dest, int timeout)
        /* send MESSAGE_NEWREF */
        memset(&newparam, 0, sizeof(union parameter));
        newparam.newref.direction = 0; /* request from app */
+       strncpy(newparam.newref.interface, call->interface, sizeof(newparam.newref.interface) - 1);
        send_message(MESSAGE_NEWREF, 0, &newparam);
 
        /* set hdlc if capability requires hdlc */
@@ -2750,12 +2784,13 @@ static int lcr_write(struct ast_channel *ast, struct ast_frame *fr)
 #else
        call = ast_channel_tech_pvt(ast);
 #endif
-       if (!call) {
+       if (!call || !call->ref) {
+               /* drop the frame, if no ref exists, but return successfull delivery, or asterisk will abort connection */
                ast_mutex_unlock(&chan_lock);
                if (f != fr) {
                        ast_frfree(f);
                }
-               return -1;
+               return 0;
        }
        len = f->samples;
        p = *((unsigned char **)&(f->data));
@@ -2781,6 +2816,7 @@ static struct ast_frame *lcr_read(struct ast_channel *ast)
 {
        struct chan_call *call;
        int len = 0;
+       struct ast_frame *f = NULL;
 
        ast_mutex_lock(&chan_lock);
 #if ASTERISK_VERSION_NUM < 110000
@@ -2860,8 +2896,21 @@ static struct ast_frame *lcr_read(struct ast_channel *ast)
        }
        call->read_fr.delivery = ast_tv(0,0);
        *((unsigned char **)&(call->read_fr.data)) = call->read_buff;
+
+       if (call->dsp)
+               f = ast_dsp_process(ast, call->dsp, &call->read_fr);
+       if (f && f->frametype == AST_FRAME_DTMF)
+#ifdef AST_1_8_OR_HIGHER
+               CDEBUG(call, ast, "Asterisk detected inband DTMF: %c.\n", f->subclass.integer);
+#else
+               CDEBUG(call, ast, "Asterisk detected inband DTMF: %c.\n", f->subclass);
+#endif
+
        ast_mutex_unlock(&chan_lock);
 
+       if (f && f->frametype == AST_FRAME_DTMF)
+               return f;
+
        return &call->read_fr;
 }
 
@@ -2965,6 +3014,15 @@ static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, siz
                        break;
                case AST_CONTROL_PROGRESS:
                        CDEBUG(call, ast, "Received indicate AST_CONTROL_PROGRESS from Asterisk.\n");
+                       if (call->state == CHAN_LCR_STATE_IN_SETUP
+                        || call->state == CHAN_LCR_STATE_IN_DIALING) {
+                               CDEBUG(call, ast, "Changing to proceeding state, because no more dialing possible.\n");
+                               /* send message to lcr */
+                               memset(&newparam, 0, sizeof(union parameter));
+                               send_message(MESSAGE_PROCEEDING, call->ref, &newparam);
+                               /* change state */
+                               call->state = CHAN_LCR_STATE_IN_PROCEEDING;
+                       }
                        /* request bchannel */
                        CDEBUG(call, ast, "Requesting audio path.\n");
                        memset(&newparam, 0, sizeof(union parameter));
@@ -3404,7 +3462,7 @@ static int lcr_config_exec(struct ast_channel *ast, void *data, char **argv)
                        break;
                call = call->next;
        }
-       if (call)
+       if (call) {
 
                #ifdef LCR_FOR_ASTERISK
                apply_opt(call, (char *)data);
@@ -3422,7 +3480,7 @@ static int lcr_config_exec(struct ast_channel *ast, void *data, char **argv)
                        newparam.queue = call->tx_queue * 8;
                        send_message(MESSAGE_DISABLE_DEJITTER, call->ref, &newparam);
                }
-       else
+       else
                CERROR(NULL, ast, "lcr_config app not called by chan_lcr channel.\n");
 
        ast_mutex_unlock(&chan_lock);
@@ -3495,18 +3553,18 @@ int load_module(void)
                                 "\n"
                                 "The available options are:\n"
                                 "    d - Send display text on called phone, text is the optarg.\n"
-                                "    n - Don't detect dtmf tones on called channel.\n"
+                                "    D - Forward detected dtmf tones from LCR.\n"
                                 "    h - Force data call (HDLC).\n"
                                 "    q - Add queue to make fax stream seamless (required for fax app).\n"
                                 "        Use queue size in miliseconds for optarg. (try 250)\n"
-                                "    f - Adding fax detection. It it timeouts, mISDN_dsp is used.\n"
-                                "        Use time to detect for optarg.\n"
+                                "    a - Adding DTMF detection.\n"
+                                "    f - Adding fax detection.\n"
 #if 0
                                 "    c - Make crypted outgoing call, optarg is keyindex.\n"
                                 "    e - Perform echo cancelation on this channel.\n"
 #endif
                                 "        Takes mISDN pipeline option as optarg.\n"
-                                "    s - Send Non Inband DTMF as inband.\n"
+                                "    s - Send Non Inband DTMF as inband. (disables LCR's DTMF)\n"
                                 "    r - re-buffer packets (160 bytes). Required for some SIP-phones and fax applications.\n"
 #if 0
                                 "   vr - rxgain control\n"