From: Super User Date: Tue, 15 May 2007 20:59:29 +0000 (+0200) Subject: backup X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=commitdiff_plain;h=fd2045584f7084d209607f4d717a66bea9afe88e backup --- diff --git a/Makefile b/Makefile index d57816a..56f705a 100644 --- a/Makefile +++ b/Makefile @@ -9,9 +9,6 @@ #* ** #*****************************************************************************/ -WITH-PBX = 42 # MUST BE SET for now -#WITH-H323 = 42 # comment this out, if no h323 should be compiled -#WITH-OPAL = 42 # NOT SUPPORTED YET WITH-CRYPTO = 42 # comment this out, if no libcrypto should be used # note: check your location and the names of libraries. @@ -19,12 +16,8 @@ WITH-CRYPTO = 42 # comment this out, if no libcrypto should be used INSTALL_BIN = /usr/local/bin INSTALL_DATA = /usr/local/pbx -# give locations for the libraries (comment out H323_LIB and PWLIB_LIB, if they are installed on the system) +# give locations for the libraries LINUX_INCLUDE = -I/usr/src/linux/include -H323_INCLUDE = -I/usr/local/include/openh323 -#H323_LIB = -L/usr/local/lib -#PWLIB_INCLUDE = -I/usr/local/include/ptlib/unix -#PWLIB_LIB = -L/usr/local/lib # give location of the mISDN libraries MISDNUSER_INCLUDE = -I../mISDNuser/include @@ -46,28 +39,10 @@ GENRC = ./genrc GENEXT = ./genextension CFLAGS = -Wall -g -DINSTALL_DATA=\"$(INSTALL_DATA)\" CFLAGS += $(LINUX_INCLUDE) $(MISDNUSER_INCLUDE) -ifdef WITH-PBX -CFLAGS += -DPBX -endif ifdef WITH-CRYPTO CFLAGS += -DCRYPTO endif -CFLAGS_OPAL = $(CFLAGS) -CFLAGS_H323 = $(CFLAGS) LIBDIR += $(MISDNUSER_LIB) -ifdef WITH-OPAL -OPAL = opal.o opal_mgr.o opal_pbxep.o opal_pbxcon.o opal_pbxms.o -CFLAGS += -DOPAL -CFLAGS_OPAL += $(OPAL_INCLUDE) -DOPAL -LIBDIR += $(OPAL_LIB) -endif -ifdef WITH-H323 -H323 = h323.o h323_ep.o h323_con.o h323_chan.o -LIBS += -lh323_linux_x86_r -lpt_linux_x86_r -ldl -CFLAGS += -DH323 -CFLAGS_H323 += $(H323_INCLUDE) $(PWLIB_INCLUDE) -DH323INCLUDE -DH323 -D_REENTRANT -DPBYTE_ORDER=PLITTLE_ENDIAN -DP_PTHREADS -DP_HAS_SEMAPHORES -DPHAS_TEMPLATES -DP_LINUX -DPTRACING -LIBDIR += $(H323_LIB) $(PWLIB_LIB) -endif ifdef WITH-CRYPTO LIBDIR += -L/usr/local/ssl/lib CFLAGS += -I/usr/local/ssl/include @@ -92,7 +67,7 @@ all: $(PBXADMIN) $(PBX) $(GEN) $(GENW) $(GENRC) $(GENEXT) @exit main.o: main.c *.h Makefile - $(CC) -c $(CFLAGS_H323) main.c -o main.o + $(CC) -c $(CFLAGS) main.c -o main.o message.o: message.c *.h Makefile $(CC) -c $(CFLAGS) message.c -o message.o @@ -103,9 +78,6 @@ options.o: options.c *.h Makefile interface.o: interface.c *.h Makefile $(CC) -c $(CFLAGS) interface.c -o interface.o -h323conf.o: h323conf.c *.h Makefile - $(CC) -c $(CFLAGS) h323conf.c -o h323conf.o - extension.o: extension.c *.h Makefile $(CC) -c $(CFLAGS) extension.c -o extension.o @@ -184,18 +156,6 @@ tones.o: tones.c *.h Makefile crypt.o: crypt.cpp *.h Makefile $(CC) -c $(CFLAGS) crypt.cpp -o crypt.o -h323.o: h323.cpp *.h Makefile - $(CC) -c $(CFLAGS_H323) h323.cpp -o h323.o - -h323_ep.o: h323_ep.cpp *.h Makefile - $(CC) -c $(CFLAGS_H323) h323_ep.cpp -o h323_ep.o - -h323_chan.o: h323_chan.cpp *.h Makefile - $(CC) -c $(CFLAGS_H323) h323_chan.cpp -o h323_chan.o - -h323_con.o: h323_con.cpp *.h Makefile - $(CC) -c $(CFLAGS_H323) h323_con.cpp -o h323_con.o - genext.o: genext.c *.h Makefile $(CC) -c $(CFLAGS) genext.c -o genext.o @@ -210,11 +170,9 @@ admin_server.o: admin_server.c *.h Makefile # $(CC) $(LIBDIR) $(CFLAGS) -lm wizzard.c \ # -o $(WIZZARD) -$(PBX): $(H323) $(OPAL) \ - main.o \ +$(PBX): main.o \ options.o \ interface.o \ - h323conf.o \ extension.o \ cause.o \ alawulaw.o \ @@ -237,11 +195,10 @@ $(PBX): $(H323) $(OPAL) \ callpbx.o \ callchan.o \ admin_server.o - $(LD) $(LIBDIR) $(H323) $(OPAL) \ + $(LD) $(LIBDIR) \ main.o \ options.o \ interface.o \ - h323conf.o \ extension.o \ cause.o \ alawulaw.o \ @@ -318,9 +275,6 @@ install: echo "NOTE: numbering_int.conf is obsolete, please use routing." ; fi @if test -a $(INSTALL_DATA)/numbering_ext.conf ; then \ echo "NOTE: numbering_ext.conf is obsolete, please use routing." ; fi - @if test -a $(INSTALL_DATA)/h323_gateway.conf ; then \ - echo "NOTE: h323_gateway.conf already exists, not changed." ; else \ - cp -v default/h323_gateway.conf $(INSTALL_DATA) ; fi @if test -a $(INSTALL_DATA)/directory.list ; then \ echo "NOTE: directory.list already exists, not changed." ; else \ cp -v default/directory.list $(INSTALL_DATA) ; fi diff --git a/README b/README index 1a51fef..7210cee 100644 --- a/README +++ b/README @@ -334,8 +334,4 @@ Changes in Version 3.4 - Timeout condition seems to work now. - Timeout action seems to work now. -What you might expect in later versions - -> ISDN over IP (proprietary solution) - -> OPAL, with a new interface between user space audio and kernel space audio (SIP / H323) - -> (maybe later) Kernel space RTP that makes VoIP reeeeeeeeeeeeally fast! diff --git a/action.cpp b/action.cpp index 51aa8db..003dcf4 100644 --- a/action.cpp +++ b/action.cpp @@ -67,7 +67,7 @@ char *numberrize_callerinfo(char *string, int ntype) /* - * process init 'internal' / 'external' / 'h323' / 'chan' / 'vbox-record' / 'partyline'... + * process init 'internal' / 'external' / 'chan' / 'vbox-record' / 'partyline'... */ void EndpointAppPBX::_action_init_call(int chan) { @@ -374,432 +374,6 @@ void EndpointAppPBX::action_dialing_external(void) } -#ifdef H323 -/* - * process dialing h323 - */ -#define set_ip_macro \ - UNCPY(helpbuffer, address, sizeof(helpbuffer)); \ - helpbuffer[sizeof(helpbuffer)-1] = '\0'; \ - UNPRINT(helpbuffer + (int)(address - dial), sizeof(helpbuffer)-1 - (int)(address - dial), "%d.%d.%d.%d", ip_a, ip_b, ip_c, ip_d); \ - ii = strlen(helpbuffer); \ - UNCAT(helpbuffer, dial+i, sizeof(helpbuffer)-1); \ - dial = address + ii; \ - i = 0; \ - UCPY(address, helpbuffer); -#define set_port_macro \ - UNCPY(helpbuffer, address, sizeof(helpbuffer)); \ - helpbuffer[sizeof(helpbuffer)-1] = '\0'; \ - UNPRINT(helpbuffer + (int)(address - dial), sizeof(helpbuffer)-1 - (int)(address - dial), "%d", port); \ - ii = strlen(helpbuffer); \ - UNCAT(helpbuffer, dial+i, sizeof(helpbuffer)-1); \ - dial = address + ii; \ - i = 0; \ - UCPY(address, helpbuffer); -void EndpointAppPBX::action_dialing_h323(void) -{ - struct message *message; - struct dialing_info dialinginfo; - int i,j, ii; - struct port_list *portlist = ea_endpoint->ep_portlist; - char *dial; - char address_buffer[256], *address=address_buffer; - char host[128] = ""; - int ip_a=0, ip_b=0, ip_c=0, ip_d=0, port=0; - struct route_param *rparam; - char helpbuffer[128]; - - /* check if address parameter is given */ - if ((rparam = routeparam(e_action, PARAM_ADDRESS))) - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): complete address is given by parameter: '%s'\n", ea_endpoint->ep_serial, rparam->string_value); - SCPY(address_buffer, rparam->string_value); - goto address_complete; - } - - /* check for given host */ - if ((rparam = routeparam(e_action, PARAM_HOST))) - if (rparam->string_value[0]) - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): host is given by parameter: '%s'\n", ea_endpoint->ep_serial, rparam->string_value); - SCPY(host, rparam->string_value); - if ((rparam = routeparam(e_action, PARAM_PORT))) - { - if (rparam->integer_value>0 && rparam->integer_value<65536) - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): port is given with the host by parameter: %d\n", ea_endpoint->ep_serial, rparam->integer_value); - if (strlen(host)+7 < sizeof(host)) - UPRINT(host, ":%d/", rparam->integer_value); - } else - { - SCAT(host, "/"); - } - } else - { - SCAT(host, "/"); - } - } - - /* include prefix and put 'host'(port) in front */ - if ((rparam = routeparam(e_action, PARAM_PREFIX))) - { - SPRINT(address_buffer, "%s%s%s", host, rparam->string_value, e_extdialing); - } else - { - if (host[0]) - { - SPRINT(address_buffer, "%s%s", host, e_extdialing); - printf("address:%s host %s extdialing %s\n",address,host, e_extdialing); - } else { - address = e_extdialing; - } - } - dial = address; - - /* check dialing */ - /* check for ip-number only with numerical digits (can be dialed by any phone) */ - if (host[0]) - { - dial = address + strlen(host); - goto check_user; /* we have complete host (port) */ - } - i = 0; - while(i < 12) - { - if (dial[i] == '\0') - return; /* unfinished */ - if (dial[i]<'0' || dial[i]>'9') - goto check_complex; - i++; - - if (i == 3) - { - ip_a = (dial[0]-'0')*100 + (dial[1]-'0')*10 + (dial[2]-'0'); - if (ip_a > 255) - { - invalid: - printlog("%3d action H323 address '%s' is invalid.\n", ea_endpoint->ep_serial, address); - message_disconnect_port(portlist, CAUSE_INVALID, LOCATION_PRIVATE_LOCAL, ""); - new_state(EPOINT_STATE_OUT_DISCONNECT); - set_tone(portlist,"cause_1c"); - return; - } - } - if (i == 6) - { - ip_b = (dial[3]-'0')*100 + (dial[4]-'0')*10 + (dial[5]-'0'); - if (ip_b > 255) - goto invalid; - } - if (i == 9) - { - ip_c = (dial[6]-'0')*100 + (dial[7]-'0')*10 + (dial[8]-'0'); - if (ip_c > 255) - goto invalid; - } - if (i == 12) - { - ip_d = (dial[9]-'0')*100 + (dial[10]-'0')*10 + (dial[11]-'0'); - if (ip_d > 255) - goto invalid; - } - if (i==4 || i==7 || i==10) - { - if (dial[i-1] > '2') - goto invalid; - } - if (i==5 || i==8 || i==11) - { - if (dial[i-2]=='2' && dial[i-1]>'5') - goto invalid; - } - } - UPRINT(address, "%d.%d.%d.%d", ip_a, ip_b, ip_c, ip_d); - i = strlen(address); - goto address_complete; - - /* there are three stages of dialing: 1. ip, 2. port, 3. user, let's find out where we at */ - check_complex: - if (strchr(address, '@')) - { - dial = strchr(address, '\0'); - goto address_complete; - } - if (strchr(address, ':')) - { - dial = strchr(address, ':') + 1; - goto check_port; - } - if (strchr(address, '/')) - { - dial = strchr(address, '/') + 1; - goto check_user; - } - - /* get ip from ip-number */ - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): checking dialed for ip: %s\n", ea_endpoint->ep_serial, dial); - ip_a = ip_b = ip_c = ip_d = 0; - i = 0; - j = 0; - while(42) - { - if (j==4) - goto invalid; - if (ip_a > 255) - goto invalid; - if (dial[i]>='0' && dial[i]<='9') - ip_a = (ip_a*10) + dial[i]-'0'; - else if (dial[i]=='.' || dial[i]=='*') - { - dial[i] = '.'; -// if (i && dial[i-1]=='.') -// { -// /* add 0 if two dots */ -// UCPY(dial+i+1, dial+i); -// dial[i]='0'; -// i++; -// } - i++; - break; - } - else if (dial[i]=='#') - { - ip_d = ip_a; - ip_a = 0; - set_ip_macro - i++; - dial+= i; - goto address_complete; - } - else if (dial[i] == '\0') - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): ip so far: %d*\n", ea_endpoint->ep_serial, ip_a); - return; - } - else - goto invalid; - i++; - j++; - } - j = 0; - while(42) - { - if (j==4) - goto invalid; - if (ip_b > 255) - goto invalid; - if (dial[i]>='0' && dial[i]<='9') - ip_b = (ip_b*10) + dial[i]-'0'; - else if (dial[i]=='.' || dial[i]=='*') - { - dial[i] = '.'; - i++; - break; - } - else if (dial[i]=='#') - { - ip_d = ip_b; - ip_b = 0; - set_ip_macro - i++; - dial+= i; - goto address_complete; - } - else if (dial[i] == '\0') - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): ip so far: %d.%d*\n", ea_endpoint->ep_serial, ip_a, ip_b); - return; - } - else - goto invalid; - i++; - j++; - } - j = 0; - while(42) - { - if (j==4) - goto invalid; - if (ip_c > 255) - goto invalid; - if (dial[i]>='0' && dial[i]<='9') - ip_c = (ip_c*10) + dial[i]-'0'; - else if (dial[i]=='.' || dial[i]=='*') - { - dial[i] = '.'; - i++; - break; - } - else if (dial[i]=='#') - { - ip_d = ip_c; - ip_c = 0; - set_ip_macro - i++; - dial+= i; - goto address_complete; - } - else if (dial[i] == '\0') - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): ip so far: %d.%d.%d\n", ea_endpoint->ep_serial, ip_a, ip_b, ip_c); - return; - } - else - goto invalid; - i++; - j++; - } - j = 0; - while(42) - { - if (j==4) - goto invalid; - if (ip_d > 255) - goto invalid; - if (dial[i]>='0' && dial[i]<='9') - ip_d = (ip_d*10) + dial[i]-'0'; - else if (dial[i]=='*' || dial[i]==':') - { - set_ip_macro - dial[i] = ':'; - i++; - dial+= i; - goto check_port; - } - else if (dial[i]=='#') - { - set_ip_macro - i++; - dial+= i; - goto address_complete; - } - else if (dial[i] == '\0') - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): ip so far: %d.%d.%d.%d*\n", ea_endpoint->ep_serial, ip_a, ip_b, ip_c, ip_d); - return; - } - else - goto invalid; - i++; - j++; - } - - /* get port */ - check_port: - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): checking dialed for port: %s\n", ea_endpoint->ep_serial, dial); - port = 0; - i = 0; - j = 0; - while(42) - { - if (j==6) - goto invalid; - if (port > 65535) - goto invalid; - if (dial[i]>='0' && dial[i]<='9') - port = (port*10) + dial[i]-'0'; - else if (dial[i]=='*' || dial[i]=='/') - { - if (i) /* only if there is something entered */ - { - set_port_macro - dial[i] = '/'; - } else - { - i--; - UCPY(dial+i, dial+i+1); - dial[i] = '/'; - } - i++; - dial+= i; - goto check_user; - } - else if (dial[i]=='#') - { - set_port_macro - i++; - dial+= i; - goto address_complete; - } - else if (dial[i] == '\0') - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): h323 address so far: %s\n", ea_endpoint->ep_serial, address); - return; - } - else - goto invalid; - i++; - j++; - } - - /* get user */ - check_user: - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): checking dialed for user: %s\n", ea_endpoint->ep_serial, dial); - port = 0; - i = 0; - j = 0; - while(42) - { - if (dial[i]=='#') - { - dial[i] = '\0'; - /* convert to @-notation */ - SCPY(helpbuffer, strchr(address, '/')+1); - SCAT(helpbuffer, "@"); - *strchr(address, '/') = '\0'; - SCAT(helpbuffer, address); - UCPY(address, helpbuffer); - goto address_complete; - } - else if (dial[i] == '\0') - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): h323 address so far: %s\n", ea_endpoint->ep_serial, address); - return; - } - i++; - j++; - } - - address_complete: - /* send proceeding, because number is complete */ - set_tone(portlist, "proceeding"); - message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING); - message_put(message); - logmessage(message); - new_state(EPOINT_STATE_IN_PROCEEDING); - - memset(&dialinginfo, 0, sizeof(dialinginfo)); - dialinginfo.itype = INFO_ITYPE_H323; - dialinginfo.sending_complete = 1; - SPRINT(dialinginfo.number, "%s", address); - /* strip the # at the end */ - if (dialinginfo.number[0]) - if (dialinginfo.number[strlen(dialinginfo.number)-1] == '#') - dialinginfo.number[strlen(dialinginfo.number)-1] = '\0'; - - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): complete multi-dial string \"%s\"\n", ea_endpoint->ep_serial, dialinginfo.number); - - /* add or update internal call */ - printlog("%3d action H323 call to address %s.\n", ea_endpoint->ep_serial, dialinginfo.number); - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_SETUP); - memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info)); - memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info)); - memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info)); - memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info)); - message_put(message); -} -#else -void EndpointAppPBX::action_dialing_h323(void) -{ - struct port_list *portlist = ea_endpoint->ep_portlist; - - printlog("%3d action H323 stack not implemented.\n", ea_endpoint->ep_serial); - message_disconnect_port(portlist, CAUSE_UNIMPLEMENTED, LOCATION_PRIVATE_LOCAL, ""); - new_state(EPOINT_STATE_OUT_DISCONNECT); - set_tone(portlist,"cause_4f"); -} -#endif - void EndpointAppPBX::action_dialing_chan(void) { struct port_list *portlist = ea_endpoint->ep_portlist; @@ -1412,9 +986,6 @@ void EndpointAppPBX::_action_redial_reply(int in) if (!strncmp(last, "intern:", 7)) SPRINT(message->param.notifyinfo.display, "(%d) %s int", e_select+1, last+7); else - if (!strncmp(last, "h323:", 5)) - SPRINT(message->param.notifyinfo.display, "(%d) %s h323", e_select+1, last+5); - else if (!strncmp(last, "chan:", 4)) SPRINT(message->param.notifyinfo.display, "(%d) %s chan", e_select+1, last+5); else @@ -2629,13 +2200,6 @@ void EndpointAppPBX::process_dialing(void) e_action = &action_internal; goto process_action; } - /* check for h323 call */ - if (!strncmp(e_dialinginfo.number, "h323:", 5)) - { - e_extdialing = e_dialinginfo.number+5; - e_action = &action_h323; - goto process_action; - } /* check for chan call */ if (!strncmp(e_dialinginfo.number, "chan:", 5)) { @@ -2808,9 +2372,6 @@ void EndpointAppPBX::process_hangup(int cause, int location) PDEBUG(DEBUG_EPOINT, "EPOINT(%d): writing connect from %s to %s into logfile of %s\n", ea_endpoint->ep_serial, e_callerinfo.id, e_dialinginfo.number, e_terminal); switch(e_dialinginfo.itype) { - case INFO_ITYPE_H323: - SPRINT(dialingtext, "h323:%s", e_dialinginfo.number); - break; case INFO_ITYPE_CHAN: SPRINT(dialingtext, "chan:%s", e_dialinginfo.number); break; diff --git a/admin_server.c b/admin_server.c index c17620b..1d8f400 100644 --- a/admin_server.c +++ b/admin_server.c @@ -236,9 +236,6 @@ int admin_route(struct admin_queue **responsep) case ACTION_EXTERNAL: apppbx->e_action = &action_external; break; - case ACTION_H323: - apppbx->e_action = &action_h323; - break; case ACTION_CHAN: apppbx->e_action = &action_chan; break; diff --git a/apppbx.cpp b/apppbx.cpp index c00ab69..ba29919 100644 --- a/apppbx.cpp +++ b/apppbx.cpp @@ -146,6 +146,94 @@ void EndpointAppPBX::new_state(int state) } +/* screen caller id + * out==0: incomming caller id, out==1: outgoing caller id + */ +void EndpointAppPBX::screen(int out, char *id, int idsize, int *type, int *present) +{ + struct interface *interface; + + interface = interface_first; + while(interface) + { + if (!strcmp(e_callerinfo.interface, interface->name)) + { + break; + } + interface = interface->next; + } +add logging + if (interface) + { + /* screen incoming caller id */ + if (!out) + { + /* check for MSN numbers, use first MSN if no match */ + msn1 = NULL; + ifmsn = interface->ifmsn; + while(ifmns) + { + if (!msn1) + msn1 = ifmns->msn; + if (!strcmp(ifmns->mns, id)) + { + break; + } + ifmsn = ifmsn->next; + } + if (!ifmns && mns1) // not in list, first msn given + UNCPY(id, msn1, idsize); + id[idsize-1] = '\0'; + } + + /* check screen list */ + if (out) + iscreen = interface->ifscreen_out; + else + iscreen = interface->ifscreen_in; + while (ifscreen) + { + if (ifcreen->match_type==-1 || ifscreen->match_type==*type) + if (ifcreen->match_present==-1 || ifscreen->match_present==*present) + { + if (strchr(ifcreen->match_id,'%')) + { + if (!strncmp(ifscreen->match_id, id, strchr(ifscreen->match_id,'%')-ifscreen->match_id)) + break; + } else + { + if (!strcmp(ifscreen->match_id, id)) + break; + } + } + ifscreen = ifscreen->next; + } + if (ifscreen) // match + { + if (ifscren->result_type != -1) + *type = ifscreen->result_type; + if (ifscren->result_present != -1) + *present = ifscreen->result_present; + if (strchr(ifscreen->match_id,'%')) + { + SCPY(suffix, strchr(ifscreen->match_id,'%') - ifscreen->match_id + id); + UNCPY(id, ifscreen->result_id); + id[idsize-1] = '\0'; + if (strchr(ifscreen->result_id,'%')) + { + *strchr(ifscreen->result_id,'%') = '\0'; + UNCAT(id, suffix, idsize); + id[idsize-1] = '\0'; + } + } else + { + UNCPY(id, ifscreen->result_id, idsize); + id[idsize-1] = '\0'; + } + } + } +} + /* release call and port (as specified) */ void EndpointAppPBX::release(int release, int calllocation, int callcause, int portlocation, int portcause) @@ -1138,91 +1226,6 @@ void EndpointAppPBX::out_setup(void) } break; -#ifdef H323 - /* *********************** h323 call */ - case INFO_ITYPE_H323: - PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing H323: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.number); - - /* alloc port */ - if (!(port = new H323Port(PORT_TYPE_H323_OUT, "H323-out", &port_settings))) - { - PERROR("EPOINT(%d) no mem for port\n", ea_endpoint->ep_serial); - break; - } - PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name); - memset(&dialinginfo, 0, sizeof(dialinginfo)); - SCPY(dialinginfo.number, e_dialinginfo.number); - dialinginfo.itype = INFO_ITYPE_H323; - dialinginfo.ntype = e_dialinginfo.ntype; - portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, 0); - if (!portlist) - { - PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial); - delete port; - release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */ - return; - } -//printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.number); - message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP); - memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info)); - memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info)); - memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info)); - memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info)); -//terminal SCPY(message->param.setup.from_terminal, e_terminal); -//terminal if (e_dialinginfo.number) -//terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.number); - /* handle restricted caller ids */ - apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name); - apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, NULL, message->param.setup.redirinfo.voip, message->param.setup.redirinfo.intern, 0); - /* display callerid if desired for extension */ - SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name)); - message_put(message); - logmessage(message); - break; -#endif -#ifdef SIP - /* *********************** sip call */ - case INFO_ITYPE_SIP: - PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing SIP: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.number); - - /* alloc port */ - if (!(port = new Psip(PORT_TYPE_SIP_OUT, 0, 0, e_dialinginfo.number))) - { - PERROR("EPOINT(%d) no mem for port\n", ea_endpoint->ep_serial); - break; - } - PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name); - memset(&dialinginfo, 0, sizeof(dialinginfo)); - SCPY(dialinginfo.number, e_dialinginfo.number); - dialinginfo.itype = INFO_ITYPE_SIP; - dialinginfo.ntype = e_dialinginfo.ntype; - portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, 0); - if (!portlist) - { - PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial); - delete port; - release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */ - return; - } -//printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.number); - message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP); - memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info)); - memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info)); - memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info)); - memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info)); -//terminal SCPY(message->param.setup.from_terminal, e_terminal); -//terminal if (e_dialinginfo.number) -//terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.number); - /* handle restricted caller ids */ - apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name); - apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, NULL, message->param.setup.redirinfo.voip, message->param.setup.redirinfo.intern, 0); - /* display callerid if desired for extension */ - SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name)); - message_put(message); - logmessage(message); - break; -#endif - /* *********************** external call */ default: PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.number); @@ -1573,7 +1576,6 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un { struct message *message; char buffer[256]; - struct interface *interface; char extension[32]; char extension1[32]; char *p; @@ -1587,100 +1589,20 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo)); e_dtmf = param->setup.dtmf; - /* check where the call is from */ + /* screen by interface */ if (e_callerinfo.interface[0]) { - interface = interface_first; - while(interface) - { - if (!strcmp(e_callerinfo.interface, interface->name)) - { - break; - } - interface = interface->next; - } - if (interface) - { - /* check for MSN numbers, use first MSN if no match */ - msn1 = NULL; - ifmsn = interface->ifmsn; - while(ifmns) - { - if (!msn1) - msn1 = ifmns->msn; - if (!strcmp(ifmns->mns, e_callerinfo.id)) - { - break; - } - ifmsn = ifmsn->next; - } - if (!ifmns && mns1) // not in list, first msn given - SCPY(p_callerinfo.id, msn1); - - /* interface is known */ - if (interface->iftype==IF_INTERN) - { - - /* interface is internal */ - if (interface->extensions[0]) - { - hier denken - /* extensions are assigned to interface */ - p = interface->extensions; - extension1[0] = '\0'; - while(*p) - { - extension[0] = '\0'; - while(*p!=',' && *p!='\0') - SCCAT(extension, *p++); - if (*p == ',') - p++; - if (!extension1[0]) - SCPY(extension1, extension); - if (!strcmp(extension, e_callerinfo.id)) - break; - extension[0] = '\0'; /* NOTE: empty if we did not find */ - } - if (extension[0]) - { - /* id was found at extension's list */ - e_callerinfo.itype = INFO_ITYPE_INTERN; - SCPY(e_callerinfo.intern, extension); - } else - if (extension1[0]) - { - /* if was provided by default */ - e_callerinfo.itype = INFO_ITYPE_INTERN; - printlog("%3d endpoint INTERFACE Caller ID '%s' not in list for interface '%s', using first ID '%s'.\n", ea_endpoint->ep_serial, e_callerinfo.id, interface->name, extension1); - SCPY(e_callerinfo.intern, extension1); - } - } else - { - /* no extension given, so we use the caller id */ - e_callerinfo.itype = INFO_ITYPE_INTERN; - SCPY(e_callerinfo.intern, e_callerinfo.id); - } - } else - { - /* interface is external */ - e_callerinfo.intern[0] = '\0'; - } - } else - { - /* interface is unknown */ - message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, ""); - new_state(EPOINT_STATE_OUT_DISCONNECT); - set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */ - e_terminal[0] = '\0'; /* no terminal */ - return; - } + /* screen incoming caller id */ + screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present); } +colp, outclip, outcolp + /* process extension */ if (e_callerinfo.itype == INFO_ITYPE_INTERN) { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is internal\n", ea_endpoint->ep_serial); + PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial); /* port makes call from extension */ - SCPY(e_callerinfo.id, e_callerinfo.intern); + SCPY(e_callerinfo.intern, e_callerinfo.id); SCPY(e_terminal, e_callerinfo.intern); SCPY(e_terminal_interface, e_callerinfo.interface); } else @@ -1689,7 +1611,7 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un } printlog("%3d incoming %s='%s'%s%s%s%s dialing='%s'\n", ea_endpoint->ep_serial, - (e_callerinfo.intern[0])?"SETUP from intern":"SETUP from extern", + (e_callerinfo.intern[0])?"SETUP from extension":"SETUP from extern", (e_callerinfo.intern[0])?e_callerinfo.intern:e_callerinfo.id, (e_callerinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"", (e_redirinfo.id[0])?"redirected='":"", @@ -2204,6 +2126,13 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, e_start = now; + /* screen by interface */ + if (e_callerinfo.interface[0]) + { + /* screen incoming caller id */ + screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present); + } + /* screen connected name */ if (e_ext.name[0]) SCPY(e_connectinfo.name, e_ext.name); @@ -2260,18 +2189,6 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, e_connectinfo.present = INFO_PRESENT_ALLOWED; } } - if (portlist->port_type==PORT_TYPE_H323_OUT) /* h323 extension answered */ - { - SCPY(e_connectinfo.voip, port->p_dialinginfo.number); - e_connectinfo.present = INFO_PRESENT_ALLOWED; -// e_connectinfo.ntype = INFO_NTYPE_UNKNOWN; - } - if (portlist->port_type==PORT_TYPE_SIP_OUT) /* sip extension answered */ - { - SCPY(e_connectinfo.voip, port->p_dialinginfo.number); - e_connectinfo.present = INFO_PRESENT_ALLOWED; -// e_connectinfo.ntype = INFO_NTYPE_UNKNOWN; - } } message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type); memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info)); @@ -3172,6 +3089,14 @@ void EndpointAppPBX::call_connect(struct port_list *portlist, int message_type, { message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT); memcpy(&message->param, param, sizeof(union parameter)); + /* screen by interface */ + if (e_connectinfo.interface[0]) + { + /* screen incoming caller id */ + screen(1, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present); + } + memcpy(&message->param.connnectinfo, e_connectinfo); + /* screen clip if prefix is required */ if (e_terminal[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0]) { @@ -3179,19 +3104,23 @@ void EndpointAppPBX::call_connect(struct port_list *portlist, int message_type, SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype)); message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN; } + /* use internal caller id */ if (e_terminal[0] && e_connectinfo.intern[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) { SCPY(message->param.connectinfo.id, e_connectinfo.intern); message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN; } + /* handle restricted caller ids */ apply_callerid_restriction(e_ext.anon_ignore, portlist->port_type, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.voip, message->param.connectinfo.intern, message->param.connectinfo.name); /* display callerid if desired for extension */ SCPY(message->param.connectinfo.display, apply_callerid_display(message->param.connectinfo.id, message->param.connectinfo.itype, message->param.connectinfo.ntype, message->param.connectinfo.present, message->param.connectinfo.screen, message->param.connectinfo.voip, message->param.connectinfo.intern, message->param.connectinfo.name)); + /* use conp, if enabld */ if (!e_ext.centrex) message->param.connectinfo.name[0] = '\0'; + /* send connect */ message_put(message); logmessage(message); @@ -3416,6 +3345,13 @@ void EndpointAppPBX::call_setup(struct port_list *portlist, int message_type, un memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo)); memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo)); + /* screen by interface */ + if (e_callerinfo.interface[0]) + { + /* screen incoming caller id */ + screen(1, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present); + } + /* process (voice over) data calls */ if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO) { @@ -4264,32 +4200,6 @@ void EndpointAppPBX::logmessage(struct message *message) pdss1->p_m_mISDNport->portnum ); } - if (port->p_type == PORT_TYPE_H323_OUT) - { - printlog("%3d outgoing SETUP from %s='%s'%s%s%s%s to h323='%s'\n", - ea_endpoint->ep_serial, - (message->param.setup.callerinfo.intern[0])?"intern":"extern", - (message->param.setup.callerinfo.intern[0])?e_callerinfo.intern:e_callerinfo.id, - (message->param.setup.callerinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"", - (message->param.setup.redirinfo.id[0])?"redirected='":"", - message->param.setup.redirinfo.id, - (message->param.setup.redirinfo.id[0])?"'":"", - message->param.setup.dialinginfo.number - ); - } - if (port->p_type == PORT_TYPE_SIP_OUT) - { - printlog("%3d outgoing SETUP from %s='%s'%s%s%s%s to sip='%s'\n", - ea_endpoint->ep_serial, - (message->param.setup.callerinfo.intern[0])?"intern":"extern", - (message->param.setup.callerinfo.intern[0])?e_callerinfo.intern:e_callerinfo.id, - (message->param.setup.callerinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"", - (message->param.setup.redirinfo.id[0])?"redirected='":"", - message->param.setup.redirinfo.id, - (message->param.setup.redirinfo.id[0])?"'":"", - message->param.setup.dialinginfo.number - ); - } if (port->p_type == PORT_TYPE_VBOX_OUT) { printlog("%3d outgoing SETUP from %s='%s'%s%s%s%s to vbox='%s'\n", diff --git a/callpbx.cpp b/callpbx.cpp index bb644d0..39dc82b 100644 --- a/callpbx.cpp +++ b/callpbx.cpp @@ -255,7 +255,8 @@ CallPBX::CallPBX(class Endpoint *epoint) : Call(epoint) c_caller_id[0] = '\0'; c_dialed[0] = '\0'; c_todial[0] = '\0'; - c_mixer = 0; + c_pid = getpid(); + c_updatebridge = 0; c_partyline = 0; /* initialize a relation only to the calling interface */ @@ -298,23 +299,26 @@ CallPBX::~CallPBX() } -/* mixer sets the mixer of hisax bchannels - * the mixer() will set the mixer for the hisax ports which is done - * at kernel space. +/* bridge sets the audio flow of all bchannels assiociated to 'this' call + * also it changes and notifies active/hold/conference states */ -void CallPBX::mixer(void) +void CallPBX::bridge(void) { struct call_relation *relation; struct message *message; - int numconnect, relations; + int numconnect = 0, relations = 0; class Endpoint *epoint; struct port_list *portlist; class Port *port; - int nodata = 1; + int allmISDN = 0; // relations that are no mISDN relation = c_relation; while(relation) { + /* count all relations */ + relations++; + + /* check for relation's objects */ epoint = find_epoint_id(relation->epoint_id); if (!epoint) { @@ -325,7 +329,7 @@ void CallPBX::mixer(void) portlist = epoint->ep_portlist; if (!portlist) { - PDEBUG((DEBUG_CALL|DEBUG_PORT), "ignoring relation without interfaces.\n"); + PDEBUG((DEBUG_CALL|DEBUG_PORT), "ignoring relation without port object.\n"); //#warning testing: keep on hold until single audio stream available relation->channel_state = CHANNEL_STATE_HOLD; relation = relation->next; @@ -342,38 +346,44 @@ void CallPBX::mixer(void) port = find_port_id(portlist->port_id); if (!port) { - PDEBUG((DEBUG_CALL|DEBUG_PORT), "software error: relation without existing port.\n"); + PDEBUG((DEBUG_CALL|DEBUG_PORT), "ignoring relation without existing port object.\n"); relation = relation->next; continue; } - if (port->p_record) - { - PDEBUG(DEBUG_CALL|DEBUG_PORT, "mixer(): relation ep%d does recording, so we must get data from all members.\n", epoint->ep_serial); - if (nodata) - { - PDEBUG(DEBUG_CALL|DEBUG_PORT, "mixer(): at least one endpoint wants data.\n"); - nodata = 0; - } - } if ((port->p_type&PORT_CLASS_MASK)!=PORT_CLASS_mISDN) { - PDEBUG((DEBUG_CALL|DEBUG_PORT), "ignoring relation ep%d because it is not mISDN.\n", epoint->ep_serial); - if (nodata) + PDEBUG((DEBUG_CALL|DEBUG_PORT), "ignoring relation ep%d because it's port is not mISDN.\n", epoint->ep_serial); + if (allmISDN) { PDEBUG((DEBUG_CALL|DEBUG_PORT), "not all endpoints are mISDN.\n"); - nodata = 0; + allmISDN = 0; } relation = relation->next; continue; } -// remove unconnected parties from conference, also remove remotely disconnected parties so conference will not be disturbed. + relation = relation->next; + } + + /* we notify all relations about rxdata. */ + relation = c_relation; + while(relation) + { + /* count connected relations */ + if ((relation->channel_state == CHANNEL_STATE_CONNECT) + && (relation->rx_state != NOTIFY_STATE_SUSPEND) + && (relation->rx_state != NOTIFY_STATE_HOLD)) + numconnect ++; + + /* remove unconnected parties from conference, also remove remotely disconnected parties so conference will not be disturbed. */ if (relation->channel_state == CHANNEL_STATE_CONNECT && relation->rx_state != NOTIFY_STATE_HOLD - && relation->rx_state != NOTIFY_STATE_SUSPEND) + && relation->rx_state != NOTIFY_STATE_SUSPEND + && relations>1 // no conf with on party + && allmISDN) // no conf if any member is not mISDN { message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_mISDNSIGNAL); message->param.mISDNsignal.message = mISDNSIGNAL_CONF; - message->param.mISDNsignal.conf = (c_serial<<1) + 1; + message->param.mISDNsignal.conf = c_serial<<16 | c_pid; PDEBUG(DEBUG_CALL, "%s +on+ id: 0x%08x\n", port->p_name, message->param.mISDNsignal.conf); message_put(message); } else @@ -384,41 +394,31 @@ void CallPBX::mixer(void) PDEBUG(DEBUG_CALL, "%s +off+ id: 0x%08x\n", port->p_name, message->param.mISDNsignal.conf); message_put(message); } - relation = relation->next; - } - /* we notify all relations about rxdata. */ - relation = c_relation; - while(relation) - { + + /* + * request data from endpoint/port if: + * - two relations + * - any without mISDN + * in this case we bridge + */ message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_mISDNSIGNAL); - message->param.mISDNsignal.message = mISDNSIGNAL_NODATA; - message->param.mISDNsignal.nodata = nodata; - PDEBUG(DEBUG_CALL, "call %d sets alldata on port %s to %d\n", c_serial, port->p_name, nodata); + message->param.mISDNsignal.message = mISDNSIGNAL_CALLDATA; + message->param.mISDNsignal.calldata = (relnum==2 && !allmISDN); + PDEBUG(DEBUG_CALL, "call %d sets 'calldata' on port %s to %d\n", c_serial, port->p_name, calldata); message_put(message); - relation = relation->next; - } - /* count relations and states */ - relation = c_relation; - numconnect = 0; - relations = 0; - while(relation) /* count audio-connected and active relations */ - { - relations ++; - if ((relation->channel_state == CHANNEL_STATE_CONNECT) - && (relation->rx_state != NOTIFY_STATE_SUSPEND) - && (relation->rx_state != NOTIFY_STATE_HOLD)) - numconnect ++; relation = relation->next; } - if (relations==2 && !c_partyline) /* two people just exchange their states */ + /* two people just exchange their states */ + if (relations==2 && !c_partyline) { relation = c_relation; relation->tx_state = notify_state_change(c_serial, relation->epoint_id, relation->tx_state, relation->next->rx_state); relation->next->tx_state = notify_state_change(c_serial, relation->next->epoint_id, relation->next->tx_state, relation->rx_state); } else - if ((relations==1 || numconnect==1) /*&& !c_partyline*/) /* one member in a call, so we put her on hold */ + /* one member in a call, so we put her on hold */ + if (relations==1 || numconnect==1) { relation = c_relation; while(relation) @@ -444,52 +444,45 @@ void CallPBX::mixer(void) } } - -/* send audio data to endpoints which do not come from an endpoint connected - * to an isdn port and do not go to an endpoint which is connected to an - * isdn port. in this case the mixing cannot be done with kernel space +/* + * bridging is only possible with two connected endpoints */ -void CallPBX::call_mixer(unsigned long epoint_from, struct call_relation *relation_from, union parameter *param) +void CallPBX::bridge_data(unsigned long epoint_from, struct call_relation *relation_from, union parameter *param) { struct call_relation *relation_to; struct message *message; + /* if we are alone */ + if (!c_relation->next) + return; + + /* if we are more than two */ + if (c_relation->next->next) + return; + /* skip if source endpoint has NOT audio mode CONNECT */ if (relation_from->channel_state != CHANNEL_STATE_CONNECT) - { return; - } - /* loop all endpoints and skip the endpoint where the audio is from - * so we do not get a loop (echo) - */ + /* get destination relation */ relation_to = c_relation; - while(relation_to) + if (relation_to == relation_from) { - /* skip source endpoint */ - if (relation_to->epoint_id == epoint_from) - { - relation_to = relation_to->next; - continue; - } + /* oops, we are the first, so destination is: */ + relation_to = relation_to->next; + } - /* skip if destination endpoint has audio mode HOLD */ - if (relation_to->channel_state != CHANNEL_STATE_CONNECT) - { - relation_to = relation_to->next; - continue; - } + /* skip if destomatopm endpoint has NOT audio mode CONNECT */ + if (relation_to->channel_state != CHANNEL_STATE_CONNECT) + return; - /* now we may send our data to the endpoint where it - * will be delivered to the port - */ + /* now we may send our data to the endpoint where it + * will be delivered to the port + */ //PDEBUG(DEBUG_CALL, "mixing from %d to %d\n", epoint_from, relation_to->epoint_id); - message = message_create(c_serial, relation_to->epoint_id, CALL_TO_EPOINT, MESSAGE_DATA); - memcpy(&message->param, param, sizeof(union parameter)); - message_put(message); - - relation_to = relation_to->next; - } + message = message_create(c_serial, relation_to->epoint_id, CALL_TO_EPOINT, MESSAGE_DATA); + memcpy(&message->param, param, sizeof(union parameter)); + message_put(message); } @@ -527,11 +520,11 @@ void CallPBX::release(unsigned long epoint_id, int hold, int location, int cause return; } - /* remove from mixer */ + /* remove from bridge */ if (relation->channel_state != CHANNEL_STATE_HOLD) { relation->channel_state = CHANNEL_STATE_HOLD; - c_mixer = 1; /* update mixer flag */ + c_updatebridge = 1; /* update bridge flag */ } /* detach given interface */ @@ -738,7 +731,7 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa if (relation->channel_state != param->channel) { relation->channel_state = param->channel; - c_mixer = 1; /* update mixer flag */ + c_updatebridge = 1; /* update bridge flag */ if (options.deb & DEBUG_CALL) callpbx_debug(this, "Call::message_epoint{after setting new channel state}"); } @@ -758,7 +751,7 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa if (new_state != relation->rx_state) { relation->rx_state = new_state; - c_mixer = 1; + c_updatebridge = 1; if (options.deb & DEBUG_CALL) callpbx_debug(this, "Call::message_epoint{after setting new rx state}"); } @@ -782,8 +775,8 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa /* audio data */ case MESSAGE_DATA: - /* now send audio data to all endpoints connected */ - call_mixer(epoint_id, relation, param); + /* now send audio data to the other endpoint */ + bridge_data(epoint_id, relation, param); return; } @@ -795,7 +788,7 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa message = message_create(c_serial, epoint_id, CALL_TO_EPOINT, MESSAGE_CONNECT); message->param.setup.partyline = c_partyline; message_put(message); - c_mixer = 1; /* update mixer flag */ + c_updatebridge = 1; /* update bridge flag */ } if (c_partyline) { @@ -807,7 +800,7 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa message->param.disconnectinfo.cause = CAUSE_NORMAL; message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; message_put(message); -// c_mixer = 1; /* update mixer flag */ +// c_updatebridge = 1; /* update bridge flag */ return; } } @@ -880,11 +873,11 @@ int CallPBX::handler(void) // int i, j; // char *p; - /* the mixer must be updated */ - if (c_mixer) + /* the bridge must be updated */ + if (c_updatebridge) { - mixer(); - c_mixer = 0; + bridge(); + c_updatebridge = 0; return(1); } @@ -988,6 +981,6 @@ int CallPBX::out_setup(unsigned long epoint_id, int message_type, union paramete todo: beim release von einem relation_type_setup muss der cause gesammelt werden, bis keine weitere setup-relation mehr existiert beim letzten den collected cause senden -mixer kann ruhig loslegen, das aber dokumentieren -mixer überdenken: wer sendet, welche töne verfügbar sind, u.s.w +bridge kann ruhig loslegen, das aber dokumentieren +bridge überdenken: wer sendet, welche töne verfügbar sind, u.s.w diff --git a/callpbx.h b/callpbx.h index a72d171..25e3220 100644 --- a/callpbx.h +++ b/callpbx.h @@ -63,13 +63,13 @@ class CallPBX : public Call char c_dialed[1024]; /* dial string of (all) number(s) */ char c_todial[32]; /* overlap dialing (part not signalled yet) */ - int c_mixer; /* mixer must be updated */ + int c_updatebridge; /* bridge must be updated */ struct call_relation *c_relation; /* list of endpoints that are related to the call */ int c_partyline; /* if set, call is conference room */ - void mixer(void); - void call_mixer(unsigned long epoint_from, struct call_relation *relation_from, union parameter *param); + void bridge(void); + void bridge_data(unsigned long epoint_from, struct call_relation *relation_from, union parameter *param); void remove_relation(struct call_relation *relation); struct call_relation *add_relation(void); int out_setup(unsigned long epoint_id, int message, union parameter *param, char *newnumber); diff --git a/dss1.cpp b/dss1.cpp index cbfc822..290ccf4 100644 --- a/dss1.cpp +++ b/dss1.cpp @@ -459,6 +459,7 @@ void Pdss1::setup_ind(unsigned long prim, unsigned long dinfo, void *data) break; } p_callerinfo.isdn_port = p_m_portnum; + SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name); /* dialing information */ dec_ie_called_pn(setup->CALLED_PN, (Q931_info_t *)((unsigned long)data+headerlen), &type, &plan, (unsigned char *)p_dialinginfo.number, sizeof(p_dialinginfo.number)); dec_ie_keypad(setup->KEYPAD, (Q931_info_t *)((unsigned long)data+headerlen), (unsigned char *)keypad, sizeof(keypad)); @@ -844,8 +845,6 @@ void Pdss1::setup_ind(unsigned long prim, unsigned long dinfo, void *data) message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP); message->param.setup.isdn_port = p_m_portnum; message->param.setup.port_type = p_type; - p_callerinfo.isdn_port = p_m_portnum; - SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name);; memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info)); memcpy(&message->param.setup.callerinfo, &p_callerinfo, sizeof(struct caller_info)); memcpy(&message->param.setup.redirinfo, &p_redirinfo, sizeof(struct redir_info)); @@ -1162,6 +1161,7 @@ void Pdss1::connect_ind(unsigned long prim, unsigned long dinfo, void *data) break; } p_connectinfo.isdn_port = p_m_portnum; + SCPY(p_connectingo.interface, p_m_mISDNport->ifport->interface->name); #ifdef CENTREX /* te-mode: CONP (connected name identification presentation) */ if (!p_m_d_ntmode) @@ -2100,6 +2100,11 @@ void Pdss1::new_state(int state) */ int Pdss1::handler(void) { + int ret; + + if ((ret = Port::handler())) + return(ret); + /* handle destruction */ if (p_m_delete && p_m_d_l3id==0) { @@ -2108,7 +2113,7 @@ int Pdss1::handler(void) return(-1); } - return(PmISDN::handler()); + return(0); } diff --git a/extension.c b/extension.c index 83e3c35..38dfd4d 100644 --- a/extension.c +++ b/extension.c @@ -713,24 +713,6 @@ int read_extension(struct extension *ext, char *number) PDEBUG(DEBUG_CONFIG, "given display_int param unknown: %s\n", param); } } else - if (!strcmp(option,"display_voip")) - { - i=0; - while(ext_yesno[i]) - { - if (!strcasecmp(param,ext_yesno[i])) - break; - i++; - } - if (ext_yesno[i]) - { - ext->display_voip = i; - PDEBUG(DEBUG_CONFIG, "display voip %s\n", ext_yesno[i]); - } else - { - PDEBUG(DEBUG_CONFIG, "given display_voip param unknown: %s\n", param); - } - } else if (!strcmp(option,"display_fake")) { i=0; @@ -1293,10 +1275,6 @@ int write_extension(struct extension *ext, char *number) fprintf(fp,"# example: \"200 (int)\"\n"); fprintf(fp,"display_int %s\n\n",(ext->display_int)?"yes":"no"); - fprintf(fp,"# Display H323 caller ids using display override (yes or no)\n"); - fprintf(fp,"# example: \"15551212 jolly@192.168.0.3\"\n"); - fprintf(fp,"display_voip %s\n\n",(ext->display_voip)?"yes":"no"); - fprintf(fp,"# Display if calls are anonymous using display override (yes or no)\n"); fprintf(fp,"# This makes only sense if the anon-ignore feature is enabled.\n"); fprintf(fp,"# example: \"15551212 anon\"\n"); diff --git a/interface.c b/interface.c index 520ecbd..e522471 100644 --- a/interface.c +++ b/interface.c @@ -510,6 +510,8 @@ static int inter_screen(struct interface_screen **ifscreenp, struct interface *i memuse++; memset(ifscreen, 0, sizeof(struct interface_screen)); #warning handle unchanged as unchanged!! + ifscreen->match_type = -1; /* unchecked */ + ifscreen->match_present = -1; /* unchecked */ ifscreen->result_type = -1; /* unchanged */ ifscreen->result_present = -1; /* unchanged */ /* tail port */ @@ -554,7 +556,7 @@ static int inter_screen(struct interface_screen **ifscreenp, struct interface *i if (ifscreen->match_present != -1) { presenterror: - SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line, parameter); + SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line); return(-1); } ifscreen->match_present = INFO_PRESENT_ALLOWED; @@ -566,6 +568,15 @@ static int inter_screen(struct interface_screen **ifscreenp, struct interface *i ifscreen->match_present = INFO_PRESENT_RESTRICTED; } else { SCPY(ifscreen->match, el); + /* check for % at the end */ + if (strchr(el, '%')) + { + if (strchr(el, '%') != el+len(el)-1) + { + SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter); + return(-1); + } + } break; } } @@ -616,6 +627,15 @@ static int inter_screen(struct interface_screen **ifscreenp, struct interface *i ifscreen->result_present = INFO_PRESENT_RESTRICTED; } else { SCPY(ifscreen->result, el); + /* check for % at the end */ + if (strchr(el, '%')) + { + if (strchr(el, '%') != el+len(el)-1) + { + SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter); + return(-1); + } + } break; } } @@ -716,10 +736,13 @@ struct interface_param interface_param[] = { "Adds an entry for outgoing calls to the caller ID screen list.\n" "See 'screen-in' for help."}, +#if 0 +#warning todo: filter, also in the PmISDN object {"filter", &inter_filter, " [parameters]", "Adds/appends a filter. Filters are ordered in transmit direction.\n" "gain - Changes volume (-8 .. 8)\n" "blowfish - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."}, +#endif {NULL, NULL, NULL, NULL} }; diff --git a/mISDN.cpp b/mISDN.cpp index 40d5204..0226947 100644 --- a/mISDN.cpp +++ b/mISDN.cpp @@ -60,15 +60,15 @@ PmISDN::PmISDN(int type, mISDNport *mISDNport, char *portname, struct port_setti p_m_hold = 0; p_m_txvol = p_m_rxvol = 0; p_m_conf = 0; + p_m_txdata = 0; #warning set delay by routing parameter or interface config p_m_delay = 0; p_m_echo = 0; p_m_tone = 0; p_m_rxoff = 0; - p_m_txmix = 0; - p_m_txmix_on = 0; p_m_nodata = 1; /* may be 1, because call always notifies us */ p_m_dtmf = !options.nodtmf; + sollen wir daraus eine interface-option machen?: p_m_timeout = 0; p_m_timer = 0; #warning denke auch an die andere seite. also das setup sollte dies weitertragen @@ -205,6 +205,11 @@ static void bchannel_activate(struct mISDNport *mISDNport, int i) } /* configure dsp features */ + if (mISDNport->b_port[i]->p_m_txdata) + { + PDEBUG(DEBUG_BCHANNEL, "during activation, we set txdata to txdata=%d.\n", mISDNport->b_port[i]->p_m_txdata); + ph_control(mISDNport->b_addr[i], (mISDNport->b_port[i]->p_m_txdata)?CMX_TXDATA_ON:CMX_TXDATA_OFF); + } if (mISDNport->b_port[i]->p_m_delay) { PDEBUG(DEBUG_BCHANNEL, "during activation, we set delay to delay=%d.\n", mISDNport->b_port[i]->p_m_delay); @@ -241,11 +246,13 @@ static void bchannel_activate(struct mISDNport *mISDNport, int i) PDEBUG(DEBUG_BCHANNEL, "during activation, we set rxoff to rxoff=%d.\n", mISDNport->b_port[i]->p_m_rxoff); ph_control(mISDNport->b_addr[i], CMX_RECEIVE_OFF, 0); } +#if 0 if (mISDNport->b_port[i]->p_m_txmix) { PDEBUG(DEBUG_BCHANNEL, "during activation, we set txmix to txmix=%d.\n", mISDNport->b_port[i]->p_m_txmix); ph_control(mISDNport->b_addr[i], CMX_MIX_ON, 0); } +#endif if (mISDNport->b_port[i]->p_m_dtmf) { PDEBUG(DEBUG_BCHANNEL, "during activation, we set dtmf to dtmf=%d.\n", mISDNport->b_port[i]->p_m_dtmf); @@ -287,6 +294,11 @@ static void bchannel_deactivate(struct mISDNport *mISDNport, int i) { if (mISDNport->b_port[i]->p_m_delay) { + PDEBUG(DEBUG_BCHANNEL, "during deactivation, we reset txdata from txdata=%d.\n", mISDNport->b_port[i]->p_m_txdata); + ph_control(mISDNport->b_addr[i], CMX_TXDATA_OFF, 0); + } + if (mISDNport->b_port[i]->p_m_delay) + { PDEBUG(DEBUG_BCHANNEL, "during deactivation, we reset delay from delay=%d.\n", mISDNport->b_port[i]->p_m_delay); ph_control(mISDNport->b_addr[i], CMX_JITTER, 0); } @@ -320,11 +332,13 @@ static void bchannel_deactivate(struct mISDNport *mISDNport, int i) PDEBUG(DEBUG_BCHANNEL, "during deactivation, we reset rxoff from rxoff=%d.\n", mISDNport->b_port[i]->p_m_rxoff); ph_control(mISDNport->b_addr[i], CMX_RECEIVE_ON, 0); } +#if 0 if (mISDNport->b_port[i]->p_m_txmix) { PDEBUG(DEBUG_BCHANNEL, "during deactivation, we reset txmix from txmix=%d.\n", mISDNport->b_port[i]->p_m_txmix); ph_control(mISDNport->b_addr[i], CMX_MIX_OFF, 0); } +#endif if (mISDNport->b_port[i]->p_m_dtmf) { PDEBUG(DEBUG_BCHANNEL, "during deactivation, we reset dtmf from dtmf=%d.\n", mISDNport->b_port[i]->p_m_dtmf); @@ -641,6 +655,7 @@ void PmISDN::bchannel_receive(iframe_t *frm) if (newlen>0 && (p_tone_fh>=0 || p_tone_fetched || !p_m_nodata || p_m_crypt_msg_loops)) { //printf("jolly: sending.... %d %d %d %d %d\n", newlen, p_tone_fh, p_tone_fetched, p_m_nodata, p_m_crypt_msg_loops); +#if 0 if (p_m_txmix_on) { p_m_txmix_on -= newlen; @@ -653,6 +668,7 @@ void PmISDN::bchannel_receive(iframe_t *frm) ph_control(p_m_b_addr, CMX_MIX_ON, 0); } } +#endif if (p_m_crypt_msg_loops) { /* send pending message */ @@ -667,11 +683,13 @@ void PmISDN::bchannel_receive(iframe_t *frm) { p_m_crypt_msg_current = 0; p_m_crypt_msg_loops--; +#if 0 // we need to disable rxmix some time after sending the loops... if (!p_m_crypt_msg_loops && p_m_txmix) { p_m_txmix_on = 8000; /* one sec */ } +#endif } } frm->prim = frm->prim & 0xfffffffc | REQUEST; @@ -873,6 +891,16 @@ void PmISDN::message_mISDNsignal(unsigned long epoint_id, int message_id, union //if (dddebug) PDEBUG(DEBUG_ISDN, "dddebug = %d\n", dddebug->type); break; + case mISDNSIGNAL_CALLDATA: + if (p_m_calldata != param->mISDNsignal.calldata) + { + p_m_calldata = param->mISDNsignal.calldata; + PDEBUG(DEBUG_BCHANNEL, "we change to calldata=%d.\n", p_m_calldata); + auch senden + } + break; + +#if 0 case mISDNSIGNAL_NODATA: p_m_nodata = param->mISDNsignal.nodata; if (p_m_txmix == p_m_nodata) /* txmix != !nodata */ @@ -884,6 +912,7 @@ void PmISDN::message_mISDNsignal(unsigned long epoint_id, int message_id, union ph_control(p_m_b_addr, p_m_txmix?CMX_MIX_ON:CMX_MIX_OFF, 0); } break; +#endif #if 0 case mISDNSIGNAL_RXOFF: @@ -963,12 +992,14 @@ void PmISDN::message_crypt(unsigned long epoint_id, int message_id, union parame } p_m_crypt_msg_current = 0; /* reset */ p_m_crypt_msg_loops = 3; /* enable */ +#if 0 /* disable txmix, or we get corrupt data due to audio process */ if (p_m_txmix) { PDEBUG(DEBUG_BCHANNEL, "for sending CR_MESSAGE_REQ, we reset txmix from txmix=%d.\n", p_m_txmix); ph_control(p_m_b_addr, CMX_MIX_OFF, 0); } +#endif break; default: @@ -1017,6 +1048,9 @@ int mISDN_handler(void) mISDNuser_head_t *hh; int i; + if ((ret = Port::handler())) + return(ret); + /* the que avoids loopbacks when replying to stack after receiving * from stack. */ mISDNport = mISDNport_first; diff --git a/mISDN.h b/mISDN.h index 20937e4..5aba535 100644 --- a/mISDN.h +++ b/mISDN.h @@ -101,8 +101,8 @@ class PmISDN : public Port int p_m_tone; /* current kernel space tone */ int p_m_rxoff; /* rx from driver is disabled */ int p_m_nodata; /* all parties within a conf are isdn ports, so pure bridging is possible */ - int p_m_txmix; /* mix tx with conference */ - int p_m_txmix_on; /* delay for turning back on after sending a binary message, must be signed */ +// int p_m_txmix; /* mix tx with conference */ +// int p_m_txmix_on; /* delay for turning back on after sending a binary message, must be signed */ int p_m_dtmf; /* dtmf decoding is enabled */ int p_m_crypt; /* encryption is enabled */ diff --git a/main.c b/main.c index 12e43b8..1a5cb75 100644 --- a/main.c +++ b/main.c @@ -49,39 +49,6 @@ pthread_mutex_t mutexd; // debug output mutex pthread_mutex_t mutexl; // log output mutex pthread_mutex_t mutexe; // error output mutex -#ifdef H323 -PMutex mutex_h323; // mutual exclude threads when using OpenH323 -#endif - -#ifdef VOIP -class PBXMain : public PProcess -{ - PCLASSINFO(PBXMain, PProcess) - public: - PBXMain(void); - ~PBXMain(void); - void Main(); -}; - -PCREATE_PROCESS(PBXMain) - -PBXMain::PBXMain(void) : PProcess("Jolly", "LinuxPBX", 0, 1, AlphaCode, 1) -{ -} - -PBXMain::~PBXMain(void) -{ -} -#endif - -#ifdef H323 -H323_ep *h323_ep = NULL; -#endif -#ifdef OPAL -OpalManager *opal_mgr = NULL; -#endif - - int memuse = 0; int mmemuse = 0; int cmemuse = 0; @@ -277,15 +244,7 @@ int main(int argc, char *argv[]) GET_NOW(); /* show version */ -#ifdef OPAL - printf("\n** %s Version %s (with OPAL)\n\n", NAME, VERSION_STRING); -#else - #ifdef H323 - printf("\n** %s Version %s (with H323)\n\n", NAME, VERSION_STRING); - #else printf("\n** %s Version %s\n\n", NAME, VERSION_STRING); - #endif -#endif /* show options */ if (ARGC <= 1) @@ -485,39 +444,6 @@ int main(int argc, char *argv[]) goto free; } -#ifdef OPAL - /* create OPAL manager */ - opal_mgr = new PBXManager; - if (!opal_mgr) - { - fprintf(stderr, "Unable to create OPAL manager.\n"); - goto free; - } - if (opal_mgr->Initialise()) - { - todo thread kreieren... - opal_mgr->Main(); - } - -#endif - - -#ifdef H323 - // create h323 endpoint and initialize - h323_ep = new H323_ep(); - if (!h323_ep) - { - fprintf(stderr, "Unable to create h323 endpoint.\n"); - goto free; - } - if (h323_ep->Init() == FALSE) - { - fprintf(stderr, "Unable to init h323 endpoint.\n"); - goto free; - } - -#endif - /* read interfaces and open ports */ if (!read_interfaces()) { @@ -591,10 +517,6 @@ int main(int argc, char *argv[]) while(!quit) { /* all loops must be counted from the beginning since nodes might get freed during handler */ -#ifdef H323 - mutex_h323.Wait(); - debug_prefix = 0; -#endif all_idle = 1; /* handle mISDN messages from kernel */ @@ -801,12 +723,6 @@ BUDETECT GET_NOW(); #endif -#ifdef H323 - // NOTE: be carefull with this, don't do anything after unlocking except sleeping and locking! - debug_prefix = "h323"; - mutex_h323.Signal(); -#endif - /* did we do nothing? so we wait to give time to other processes */ if (all_idle) { @@ -822,7 +738,6 @@ free: /* set scheduler & priority - * we must remove realtimeshed, because h323 may lock during exit */ if (options.schedule > 1) { @@ -840,9 +755,6 @@ free: } /* destroy objects */ -#ifdef H323 - mutex_h323.Wait(); -#endif debug_prefix = "free"; while(port_first) @@ -880,37 +792,6 @@ free: PDEBUG(DEBUG_MSG, "freed %d pending messages\n", i); } -#ifdef H323 - mutex_h323.Signal(); -#endif - -#ifdef OPAL - /* destroy manager */ - if (opal_mgr) - { - todo kill an den main-thread von opal und warten... - if (options.deb & DEBUG_OPAL) - printf("->now deleting opal manager\n"); - delete opal_mgr; - if (options.deb & DEBUG_OPAL) - printf("->opal manager deleted\n"); - } - -#endif - -#ifdef H323 - /* destroy endpoint */ - if (h323_ep) - { - if (options.deb & DEBUG_H323) - printf("->now deleting endpoint\n"); - delete h323_ep; - if (options.deb & DEBUG_H323) - printf("->endpoint deleted\n"); - } - -#endif - /* free tones */ if (toneset_first) free_tones(); diff --git a/main.h b/main.h index d09239e..2519970 100644 --- a/main.h +++ b/main.h @@ -40,8 +40,6 @@ void _printerror(const char *function, int line, const char *fmt, ...); #define DEBUG_BCHANNEL 0x0008 #define DEBUG_PORT 0x0100 #define DEBUG_ISDN 0x0110 -#define DEBUG_OPAL 0x0120 -#define DEBUG_H323 0x0130 //#define DEBUG_KNOCK 0x0140 #define DEBUG_VBOX 0x0180 #define DEBUG_EPOINT 0x0200 @@ -60,30 +58,17 @@ void _printerror(const char *function, int line, const char *fmt, ...); */ #define DEBUG_LOG 0x7fff -/* audio buffer for mixer and recording. - * all partys within a call (most time two endpoints) write audio data to the buffer. this is used because - * the buffer experience jitter. if the buffer is too small, jitter will cause drops and gaps. - * if the buffer is too large, the delay is large. 768 is a good value to start with. +/* + * transmit interval for tones and announcements (or samples of all kind) + * */ -#ifdef VOIP -#warning to be removed soon -#endif -#define PORT_BUFFER 768 +#define ISDN_TRANSMIT 128 -/* keep this 0 for minimum delay */ -#ifdef VOIP -#warning to be removed soon -#endif -#define ISDN_PRELOAD 0 - -/* the jitterlimit specifies the number of samples received too fast, before - * it recognizes a stalling process. - * but should NOT be less 256. +/* + * preload transmit buffer to avoid gaps at the beginning due to jitter + * keep this 0 for minimum delay */ -#ifdef VOIP -#warning to be removed soon -#endif -#define ISDN_JITTERLIMIT 512 /* maximum samples received before dropping */ +#define ISDN_PRELOAD 0 /* give sendmail program. if not inside $PATH, give absolute path here (e.g. "/usr/sbin/sendmail") */ @@ -118,28 +103,6 @@ void _printerror(const char *function, int line, const char *fmt, ...); #define BUDETECT ; #endif -#ifdef H323 -#define VOIP -#ifdef OPAL -#error It is not allowed to use H323 and OPAL. Please disable H323, because it is included in OPAL. -#endif -#endif -#ifdef OPAL -#define VOIP -#endif - -#ifdef H323INCLUDE -#define NO_VIDEO_CAPTURE -//#include -//#include -#include -#include -#include -#include -#include -#include -#endif - #include #include #include @@ -158,7 +121,6 @@ extern "C" { #include "save.h" #include "options.h" #include "interface.h" -#include "h323conf.h" #include "extension.h" #include "message.h" #include "endpoint.h" @@ -168,12 +130,6 @@ extern "C" { #include "port.h" #include "mISDN.h" #include "dss1.h" -#ifdef H323 -#include "h323.h" -#endif -#ifdef OPAL -#include "opal.h" -#endif #include "vbox.h" #include "call.h" #include "callpbx.h" @@ -191,12 +147,4 @@ extern struct timeval now_tv; extern struct timezone now_tz; -#ifdef H323INCLUDE -#include "h323_ep.h" -#include "h323_con.h" -#include "h323_chan.h" - -extern PMutex mutex_h323; // mutual exclude for synchroniszing threads -extern H323_ep *h323_ep; -#endif diff --git a/message.c b/message.c index 97c032c..0e4fd67 100644 --- a/message.c +++ b/message.c @@ -19,10 +19,6 @@ MESSAGES struct message *message_first = NULL; struct message **messagepointer_end = &message_first; -//#ifdef H323 -//PMutex mutex_message; -//#endif - /* creates a new message with the given attributes. the message must be filled then. after filling, the message_put must be called */ struct message *message_create(int id_from, int id_to, int flow, int type) { @@ -60,11 +56,6 @@ struct message *message_create(int id_from, int id_to, int flow, int type) /* attaches a message to the end of the message chain */ void message_put(struct message *message) { - /* the mutex prevents from creating two messages at a time (h323 thread and main thread). */ -//#ifdef H323 -// mutex_message.Wait(); -//#endif - if (message->id_to == 0) { PDEBUG(DEBUG_MSG, "message %s not written, because destination is 0.\n", messages_txt[message->type]); @@ -77,10 +68,6 @@ void message_put(struct message *message) *messagepointer_end = message; messagepointer_end = &(message->next); - -//#ifdef H323 -// mutex_message.Signal(); -//#endif } @@ -89,16 +76,8 @@ struct message *message_get(void) { struct message *message; - /* the mutex prevents from getting a message while creating a messages at a time (h323 thread and main thread). */ -//#ifdef H323 -// mutex_message.Wait(); -//#endif - if (!message_first) { -//#ifdef H323 -// mutex_message.Signal(); -//#endif return(0); } @@ -107,10 +86,6 @@ struct message *message_get(void) if (!message_first) messagepointer_end = &message_first; -//#ifdef H323 -// mutex_message.Signal(); -//#endif - if ((options.deb&DEBUG_MSG) && message->type != MESSAGE_DATA) PDEBUG(DEBUG_MSG, "message %s reading from %ld to %ld (memory %x)\n", messages_txt[message->type], message->id_from, message->id_to, message); diff --git a/message.h b/message.h index e95e8e7..ce1bb76 100644 --- a/message.h +++ b/message.h @@ -120,7 +120,7 @@ enum { /* diversion types */ enum { /* isdnsignal */ mISDNSIGNAL_VOLUME, mISDNSIGNAL_CONF, - mISDNSIGNAL_NODATA, /* no data required */ + mISDNSIGNAL_CALLDATA, /* data required by call instance */ mISDNSIGNAL_ECHO, }; @@ -151,7 +151,7 @@ struct dialing_info { struct connect_info { char id[32]; /* id of caller (user number) */ char voip[64]; /* URI of voip (or gateway) */ - char intern[32]; /* internal id */ + char extension[32]; /* internal id */ char name[16]; int isdn_port; /* internal/external port (if call is isdn) */ char interfaces[128]; /* interfaces for extenal calls */ @@ -241,7 +241,6 @@ struct park_info { struct param_data { unsigned char data[512]; /* audio/hdlc data */ int len; /* audio/hdlc data */ - int compressed; /* 0 for law-data, 1 for 16-bit data */ unsigned long port_id; /* to identify the source of this data */ int port_type; /* type of the source's port */ }; @@ -266,7 +265,7 @@ struct param_mISDNsignal { int rxvol; int txvol; int conf; - int nodata; + int calldata; int tone; int echo; }; diff --git a/options.c b/options.c index bd4e002..a69dd61 100644 --- a/options.c +++ b/options.c @@ -31,12 +31,6 @@ struct options options = { "tones_american", /* directory of tones */ "", /* directories of tones to fetch */ "extensions", /* directory of extensions */ - "", /* h323 endpoint name */ - 0, /* h323 ringconnect */ - 0,4, 0,2, 0, 0, 0, 0,4, 0,4, 0,64, /* h323 codecs to use */ - 0,"",1720, /* allow incoming h323 calls */ - 0,"", /* register with h323 gatekeeper */ - 5060, 5, /* SIP port, maxqueue */ 0, /* dtmf detection on */ "", /* dummy caller id */ 0, /* use tones by dsp.o */ @@ -57,9 +51,6 @@ int read_options(void) char param[256]; unsigned int line,i; char buffer[256]; -#ifdef H323 - int codecpri = 0; -#endif SPRINT(filename, "%s/options.conf", INSTALL_DATA); @@ -189,168 +180,6 @@ int read_options(void) PDEBUG(DEBUG_CONFIG, "isdn audio type: ulaw\n"); } else - if (!strcmp(option,"h323_name")) - { -#ifdef H323 - SCPY(options.h323_name, param); - - PDEBUG(DEBUG_CONFIG, "H323 endpoint name: '%s'\n", param); -#endif - } else - if (!strcmp(option,"h323_ringconnect")) - { -#ifdef H323 - options.h323_ringconnect = 1; - - PDEBUG(DEBUG_CONFIG, "H323 ringconnect: enabled\n"); -#endif - } else - if (!strcmp(option,"h323_gsm")) - { -#ifdef H323 - codecpri ++; - options.h323_gsm_pri = codecpri; - options.h323_gsm_opt = atoi(param); - if (atoi(param)<1 && atoi(param)>7) - { - PERROR_RUNTIME("Error in %s (line %d): parameter for option %s must be in range 1..7.\n",filename,line,option); - goto error; - } - - PDEBUG(DEBUG_CONFIG, "H323 codec to use: GSM, MicrosoftGSM priority %d\n", codecpri); -#endif - } else - if (!strcmp(option,"h323_g726")) - { -#ifdef H323 - codecpri ++; - options.h323_g726_pri = codecpri; - options.h323_g726_opt = atoi(param); - if (atoi(param)<2 && atoi(param)>5) - { - PERROR_RUNTIME("Error in %s (line %d): parameter for option %s must be in range 2..5.\n",filename,line,option); - goto error; - } - - PDEBUG(DEBUG_CONFIG, "H323 codec to use: G726 priority %d\n", codecpri); -#endif - } else - if (!strcmp(option,"h323_g7231")) - { -#ifdef H323 - codecpri ++; - options.h323_g7231_pri = codecpri; - - PDEBUG(DEBUG_CONFIG, "H323 codec to use: G7231 priority %d\n", codecpri); -#endif - } else - if (!strcmp(option,"h323_g729a")) - { -#ifdef H323 - codecpri ++; - options.h323_g729a_pri = codecpri; - - PDEBUG(DEBUG_CONFIG, "H323 codec to use: G729A priority %d\n", codecpri); -#endif - } else - if (!strcmp(option,"h323_lpc10")) - { -#ifdef H323 - codecpri ++; - options.h323_lpc10_pri = codecpri; - - PDEBUG(DEBUG_CONFIG, "H323 codec to use: LPC-10 priority %d\n", codecpri); -#endif - } else - if (!strcmp(option,"h323_speex")) - { -#ifdef H323 - codecpri ++; - options.h323_speex_pri = codecpri; - options.h323_speex_opt = atoi(param); - if (atoi(param)<2 && atoi(param)>6) - { - PERROR_RUNTIME("Error in %s (line %d): parameter for option %s must be in range 2..6.\n",filename,line,option); - goto error; - } - - PDEBUG(DEBUG_CONFIG, "H323 codec to use: Speex priority %d\n", codecpri); -#endif - } else - if (!strcmp(option,"h323_xspeex")) - { -#ifdef H323 - codecpri ++; - options.h323_xspeex_pri = codecpri; - options.h323_xspeex_opt = atoi(param); - if (atoi(param)<2 && atoi(param)>6) - { - PERROR_RUNTIME("Error in %s (line %d): parameter for option %s must be in range 2..6.\n",filename,line,option); - goto error; - } - - PDEBUG(DEBUG_CONFIG, "H323 codec to use: XiphSpeex priority %d\n", codecpri); -#endif - } else - if (!strcmp(option,"h323_law")) - { -#ifdef H323 - codecpri ++; - options.h323_law_pri = codecpri; - options.h323_law_opt = atoi(param); - if (atoi(param)<10 && atoi(param)>240) - { - PERROR_RUNTIME("Error in %s (line %d): parameter for option %s must be in range 10..240.\n",filename,line,option); - goto error; - } - - PDEBUG(DEBUG_CONFIG, "H323 codec to use: Alaw, muLaw priority %d\n", codecpri); -#endif - } else - if (!strcmp(option,"h323_icall")) - { -#ifdef H323 - options.h323_icall = 1; - SCPY(options.h323_icall_prefix, param); - - PDEBUG(DEBUG_CONFIG, "process incoming H323 call with prefix '%s'\n", param); -#endif - } else - if (!strcmp(option,"h323_port")) - { -#ifdef H323 - options.h323_port = atoi(param); - - PDEBUG(DEBUG_CONFIG, "use port for incoming H323 calls: %d\n", atoi(param)); -#endif - } else - if (!strcmp(option,"sip_port")) - { -#ifdef SIP - options.sip_port = atoi(param); - - PDEBUG(DEBUG_CONFIG, "use port for incoming SIP calls: %d\n", atoi(param)); -#endif - } else - if (!strcmp(option,"sip_maxqueue")) - { -#ifdef SIP - options.sip_maxqueue = atoi(param); - - PDEBUG(DEBUG_CONFIG, "number of simultanious incoming sockets for SIP calls: %d\n", atoi(param)); -#endif - } else - if (!strcmp(option,"h323_gatekeeper")) - { -#ifdef H323 - options.h323_gatekeeper = 1; - if (param[0]) - { - SCPY(options.h323_gatekeeper_host, param); - } - PDEBUG(DEBUG_CONFIG, "register with H323 gatekeeper (%s)\n", (param[0])?param:"automatically"); -#endif - } else if (!strcmp(option,"tones_dir")) { if (param[0]==0) diff --git a/options.h b/options.h index 90270c6..ecf7e3c 100644 --- a/options.h +++ b/options.h @@ -22,28 +22,6 @@ struct options { char tones_dir[64]; /* directory of all tones/patterns */ char fetch_tones[256]; /* directories of tones to fetch */ char extensions_dir[64]; /* directory of extensions */ - char h323_name[128]; /* the name of h323 endpoint */ - int h323_ringconnect; /* connected when ringing */ - int h323_gsm_pri; /* priority to use of GSM codec (0 == don't use) */ - int h323_gsm_opt; - int h323_g726_pri; /* priority to use of G726 codec (0 == don't use) */ - int h323_g726_opt; - int h323_g7231_pri; /* priority to use of G7231 codec (0 == don't use) */ - int h323_g729a_pri; /* priority to use of G729a codec (0 == don't use) */ - int h323_lpc10_pri; /* priority to use of lpc-10 codec (0 == don't use) */ - int h323_speex_pri; /* priority to use of speex codec (0 == don't use) */ - int h323_speex_opt; - int h323_xspeex_pri; /* priority to use of xspeex codec (0 == don't use) */ - int h323_xspeex_opt; - int h323_law_pri; /* priority to use of law codec (0 == don't use) */ - int h323_law_opt; - int h323_icall; /* allow incoming h323 calls */ - char h323_icall_prefix[32]; /* the prefix */ - int h323_port; /* port for incoming calls */ - int h323_gatekeeper; /* register with h323 gatekeeper */ - char h323_gatekeeper_host[128];/* the gatekeeper host */ - int sip_port; - int sip_maxqueue; int nodtmf; /* use dtmf detection */ char dummyid[32]; /* caller id for external calls if not available */ int dsptones; /* tones will be generated via dsp.o 1=american 2=ger */ diff --git a/port.cpp b/port.cpp index a68ca59..a3a33c8 100644 --- a/port.cpp +++ b/port.cpp @@ -141,6 +141,7 @@ Port::Port(int type, char *portname, struct port_settings *settings) } SCPY(p_name, portname); SCPY(p_tone_dir, p_settings.tones_dir); // just to be sure + p_clock = 0; p_type = type; p_serial = port_serial++; p_debug_nothingtosend = 0; @@ -262,25 +263,6 @@ void Port::new_state(int state) /* - * find the port using h323 token - */ -class Port *find_port_with_token(char *name) -{ - class Port *port = port_first; - - while(port) - { -//printf("comparing: '%s' with '%s'\n", name, p_name); - if ((port->p_type==PORT_TYPE_H323_IN || port->p_type==PORT_TYPE_H323_OUT) && !strcmp(port->p_name, name)) - return(port); - port = port->next; - } - - return(NULL); -} - - -/* * find the port with port_id */ class Port *find_port_id(unsigned long port_id) @@ -298,47 +280,6 @@ class Port *find_port_id(unsigned long port_id) return(NULL); } -#if 0 -/* - * open the knock sound - */ -void Port::set_knock(char *tones_dir_epoint) -{ - char filename[128], *tones_dir; - - /* check if we have the epoint override the tones_dir of options.conf */ - tones_dir = options.tones_dir; - if (tones_dir_epoint[0]) - { - tones_dir = tones_dir_epoint; - } - - if (p_knock_fh >= 0) - { - close(p_knock_fh); - p_knock_fh = -1; - fhuse--; - } - p_knock_fetched = NULL; - - if ((p_knock_fetched=open_tone_fetched(tones_dir, "knock", &p_knock_codec, &p_knock_size, &p_knock_left))) - { - PDEBUG(DEBUG_PORT, "PORT(%s) opening fetched tone: %s\n", p_name, "knock"); - return; - } - - SPRINT(filename, "%s/%s/knock", INSTALL_DATA, tones_dir); - if ((p_knock_fh=open_tone(filename, &p_knock_codec, &p_knock_size, &p_knock_left)) >= 0) - { - PDEBUG(DEBUG_PORT, "PORT(%s) opening tone: %s\n", p_name, filename); - fhuse++; - } else - { - p_knock_fh = -1; - } -} -#endif - /* * set echotest @@ -348,6 +289,7 @@ void Port::set_echotest(int echotest) p_echotest = echotest; } + /* * set the file in the tone directory with the given name */ @@ -359,15 +301,6 @@ void Port::set_tone(char *dir, char *name) if (name == NULL) name = ""; -#if 0 - /* knocking ? */ - if (!strcmp(name, "knock")) - { - set_knock(tones_dir_epoint); - return; - } -#endif - /* no counter, no eof, normal speed */ p_tone_counter = 0; p_tone_eof = 0; @@ -518,45 +451,6 @@ void Port::set_vbox_play(char *name, int offset) /* seek */ if (p_tone_name[0]) { -//printf("\n\n\n tone_codec = %d\n\n\n\n",p_tone_codec); -#if 0 - switch(p_tone_codec) - { - case CODEC_LAW: - case CODEC_8BIT: - lseek(p_tone_fh, offset*8000L, SEEK_SET); - size = p_tone_size / 8000L; - if (offset*8000L <= p_tone_left) - p_tone_left -= offset*8000L; - break; - - case CODEC_MONO: - lseek(p_tone_fh, offset*16000L, SEEK_SET); - size = p_tone_size / 16000L; - if (offset*16000L <= p_tone_left) - p_tone_left -= offset*16000L; -//printf("\n\n\n size = %d\n\n\n\n",size); - break; - - case CODEC_STEREO: - lseek(p_tone_fh, offset*32000L, SEEK_SET); - size = p_tone_size / 32000L; - if (offset*32000L <= p_tone_left) - p_tone_left -= offset*32000L; - break; - - default: - PERROR("no codec specified! exitting...\n"); - exit(-1); - } -#else - lseek(p_tone_fh, offset*8000L, SEEK_SET); - size = p_tone_size / 8000L; - if (offset*8000L <= p_tone_left) - p_tone_left -= offset*8000L; -#endif - - /* send message with counter value */ if (p_tone_size>=0 && ACTIVE_EPOINT(p_epointlist)) { @@ -578,274 +472,30 @@ void Port::set_vbox_speed(int speed) p_tone_speed = speed; } -/* write data to port's mixer buffer - * it will be read by the port using read_audio - * synchronisation is also done when writing is too fast and buffer is full - * the mixer buffer will only mix what cannot be mixed by kernel mixer - * - * also write data to the record buffer. the record buffer will mix everything. - */ -void Port::mixer(union parameter *param) -{ - struct mixer_relation *relation, **relationpointer; - int len; - unsigned char *data; - signed short *data_16; - int writep; - signed long *buffer, *record; - int must_mix = 1; /* set, if we need to mix (not done by kernel) */ - - /* we do not mix if we have audio from ourself but we need to record - * unless we have a local echo enabled - */ - if (param->data.port_id==p_serial && !p_echotest) - must_mix = 0; - - if ((param->data.port_type&PORT_CLASS_MASK)==PORT_CLASS_mISDN - && (p_type&PORT_CLASS_MASK)==PORT_CLASS_mISDN) - { - must_mix = 0; - } - if (!p_record && !must_mix) /* if we do not record AND no need to mix */ - { - return; - } - - /* get the relation to the write pointer. if no relation exists - * for the given source port, we create one. - */ - relation = p_mixer_rel; - relationpointer = &(p_mixer_rel); - if (!relation) /* there is no relation at all */ - { - /* clear buffer to 0-volume and reset writep */ - memset(p_mixer_buffer, 0, sizeof(p_mixer_buffer)); - memset(p_record_buffer, 0, sizeof(p_record_buffer)); - memset(p_stereo_buffer, 0, sizeof(p_stereo_buffer)); - } else /* else because we do not need to run a 0-loop */ - while(relation) - { - if (relation->port_id == param->data.port_id) - break; - relationpointer = &(relation->next); - relation = relation->next; - } - if (!relation) - { - relation = *relationpointer = (struct mixer_relation *)calloc(1, sizeof(struct mixer_relation)); - if (!relation) - { - PERROR("fatal error: cannot alloc memory for port mixer relation\n"); - return; /* no mem */ - } - pmemuse++; - memset(relation, 0, sizeof(struct mixer_relation)); - relation->port_id = param->data.port_id; - /* put write buffer in front of read buffer */ -#ifndef BETTERDELAY - relation->mixer_writep = (p_mixer_readp+(PORT_BUFFER/2))%PORT_BUFFER; -#else - relation->mixer_writep = p_mixer_readp; -#endif -#ifdef MIXER_DEBUG - PDEBUG(DEBUG_PORT, "PORT(%s) Adding new mixer relation from port #%d (readp=%d, writep=%d, PORT_BUFFER=%d).\n", p_name, param->data.port_id, p_mixer_readp, relation->mixer_writep, PORT_BUFFER); -#endif - } - - /* adding remote's audio data to our mixer_buffer / record_buffer */ - len = param->data.len; - if (param->data.compressed == 0) /* in case of 16 bit data */ - len >>= 1; - if (len>PORT_BUFFER) - PERROR("fatal error: audio data from remote port #%d is larger than mixer buffer %d>%d\n", param->data.port_id, len, PORT_BUFFER); - writep = relation->mixer_writep; - buffer = p_mixer_buffer; - record = p_record_buffer; - /* if stereo should be recorded */ - if (param->data.port_id == p_serial) - if (p_record_type == CODEC_STEREO) - record = p_stereo_buffer; - /* NOTE: if read and write pointer are equal, the buffer is full */ - if ((p_mixer_readp-writep+PORT_BUFFER)%PORT_BUFFER < len) /* we would overrun the read pointer */ - { -#ifdef MIXER_DEBUG - PERROR("PORT(%s) buffer overrun, source port #%d is sending too fast. (dropping %d samples)\n", p_name, param->data.port_id, len); -#endif - // we do not resync since dropping causes slowing writepointer down anyway... - //relation->mixer_writep = (p_mixer_readp+(PORT_BUFFER/2))%PORT_BUFFER; - return; - } - - if (!p_record && must_mix) - { - /* WE MUST MIX BUT DO NOT RECORD */ - if (param->data.compressed) - { - /* compressed data */ - data = param->data.data; - if (len+writep >= PORT_BUFFER) /* data hits the buffer end */ - { - len = len+writep-PORT_BUFFER; /* rest to write in front of buffer */ - while(writep < PORT_BUFFER) /* write till buffer end */ - buffer[writep++] += audio_law_to_s32[*(data++)]; - writep = 0; - } - while(len--) /* write rest */ - buffer[writep++] += audio_law_to_s32[*(data++)]; - } else - { - /* uncompressed data */ - data_16 = (signed short *)param->data.data; - if (len+writep >= PORT_BUFFER) /* data hits the buffer end */ - { - len = len+writep-PORT_BUFFER; /* rest to write in front of buffer */ - while(writep < PORT_BUFFER) /* write till buffer end */ - buffer[writep++] += *(data_16++); - writep = 0; - } - while(len--) /* write rest */ - buffer[writep++] += *(data_16++); - } - } else /* else */ - if (p_record && !must_mix) - { - /* WE MUST RECORD BUT DO NOT MIX */ - if (param->data.compressed) - { - /* compressed data */ - data = param->data.data; - if (len+writep >= PORT_BUFFER) /* data hits the buffer end */ - { - len = len+writep-PORT_BUFFER; /* rest to write in front of buffer */ - while(writep < PORT_BUFFER) /* write till buffer end */ - record[writep++] += audio_law_to_s32[*(data++)]; - writep = 0; - } - while(len--) /* write rest */ - record[writep++] += audio_law_to_s32[*(data++)]; - } else - { - /* uncompressed data */ - data_16 = (signed short *)param->data.data; - if (len+writep >= PORT_BUFFER) /* data hits the buffer end */ - { - len = len+writep-PORT_BUFFER; /* rest to write in front of buffer */ - while(writep < PORT_BUFFER) /* write till buffer end */ - record[writep++] += *(data_16++); - writep = 0; - } - while(len--) /* write rest */ - record[writep++] += *(data_16++); - } - } else - { - /* WE MUST MIX AND MUST RECORD */ - if (param->data.compressed) - { - /* compressed data */ - data = param->data.data; - if (len+writep >= PORT_BUFFER) /* data hits the buffer end */ - { - len = len+writep-PORT_BUFFER; /* rest to write in front of buffer */ - while(writep < PORT_BUFFER) /* write till buffer end */ - { - buffer[writep] += audio_law_to_s32[*data]; - record[writep++] += audio_law_to_s32[*(data++)]; - } - writep = 0; - } - while(len--) /* write rest */ - { - buffer[writep] += audio_law_to_s32[*data]; - record[writep++] += audio_law_to_s32[*(data++)]; - } - } else - { - /* uncompressed data */ - data_16 = (signed short *)param->data.data; - if (len+writep >= PORT_BUFFER) /* data hits the buffer end */ - { - len = len+writep-PORT_BUFFER; /* rest to write in front of buffer */ - while(writep < PORT_BUFFER) /* write till buffer end */ - { - buffer[writep] += *data_16; - record[writep++] += *(data_16++); - } - writep = 0; - } - while(len--) /* write rest */ - { - buffer[writep] += *data_16; - record[writep++] += *(data_16++); - } - } - } - relation->mixer_writep = writep; /* new write pointer */ -// PDEBUG(DEBUG_PORT "written data len=%d port=%d (readp=%d, writep=%d, PORT_BUFFER=%d).\n", param->data.len, param->data.port_id, p_mixer_readp, relation->mixer_writep, PORT_BUFFER); -} - - /* * read from the given file as specified in port_set_tone and return sample data - * this data is mixed with the user space mixer (if anything mixed) and - * filled into the buffer as many as given by length. - * if compressed is true, the result in buffer is alaw/ulaw-compressed - * otherwhise it is 16 bit audio. in this case the buffer size must be twice the lenght. - * the length is the number of samples, not bytes in buffer! */ -int Port::read_audio(unsigned char *buffer, int length, int compressed) +int Port::read_audio(unsigned char *buffer, int length) { int l,len; - unsigned short temp_buffer[PORT_BUFFER]; /* buffer for up to 32 bit of data */ - int codec_in; /* current codec to use */ - unsigned char *buf_in8; /* buffer pointer for alaw/ulaw/8bit data */ - signed short *buf_in16; /* buffer pointer for alaw/ulaw/8bit data */ - signed short *buf_out16; /* buffer pointer for outgoing audio data */ - signed long *mix_buffer, *mix_buffer2, sample; /* pointer to mixer buffer */ - struct mixer_relation *relation, **relationpointer; int readp; - int nodata=0; /* to detect 0-length files */ + int nodata=0; /* to detect 0-length files and avoid endless reopen */ char filename[128]; - signed short record_buffer[PORT_BUFFER<<1], *rec_buffer; /* buffer of recorded part which will be written (*2 for stereo) */ - unsigned char *rec8_buffer; /* used to send 8-bit audio (wave-8bit, law) */ int tone_left_before; /* temp variable to determine the change in p_tone_left */ /* nothing */ if (length == 0) return(0); - /* just in case, we get too much to do */ - if (length > PORT_BUFFER-1) - length = PORT_BUFFER-1; - len = length; - buf_in8 = (unsigned char *)temp_buffer; - buf_in16 = (signed short *)temp_buffer; - codec_in = p_tone_codec; /* if there is no tone set, use silence */ if (p_tone_name[0] == 0) { - codec_in = CODEC_LAW; rest_is_silence: - switch(codec_in) - { - case CODEC_LAW: - memset(buf_in8, (options.law=='a')?0x2a:0xff, len); /* silence */ - break; - - case CODEC_MONO: - case CODEC_8BIT: - case CODEC_STEREO: - memset(buf_in16, 0, len<<1); /* silence */ - break; - - default: - PERROR("Software error: no codec during silence\n"); - exit(-1); - } - goto mix_to_buffer; + memset(buffer, (options.law=='a')?0x2a:0xff, len); /* silence */ + goto done; } /* if the file pointer is not open, we open it */ @@ -877,8 +527,6 @@ rest_is_silence: } fhuse++; } - codec_in = p_tone_codec; -//printf("\n\ncodec=%d\n\n\n", p_tone_codec); PDEBUG(DEBUG_PORT, "PORT(%s) opening %stone: %s\n", p_name, p_tone_fetched?"fetched ":"", filename); } @@ -887,69 +535,19 @@ read_more: tone_left_before = p_tone_left; if (p_tone_fh >= 0) { - switch(codec_in) - { - case CODEC_LAW: - l = read_tone(p_tone_fh, buf_in8, codec_in, len, p_tone_size, &p_tone_left, p_tone_speed); - if (l<0 || l>len) /* paranoia */ - l=0; - buf_in8 += l; - len -= l; - break; - - case CODEC_8BIT: - l = read_tone(p_tone_fh, buf_in16, codec_in, len, p_tone_size, &p_tone_left, p_tone_speed); - if (l<0 || l>len) /* paranoia */ - l=0; - buf_in16 += l; - len -= l; - break; - - case CODEC_MONO: - l = read_tone(p_tone_fh, buf_in16, codec_in, len, p_tone_size, &p_tone_left, p_tone_speed); - if (l<0 || l>len) /* paranoia */ - l=0; - buf_in16 += l; - len -= l; - break; - - case CODEC_STEREO: - l = read_tone(p_tone_fh, buf_in16, codec_in, len, p_tone_size, &p_tone_left, p_tone_speed); - if (l<0 || l>len) /* paranoia */ - l=0; - buf_in16 += l; - len -= l; - break; - - default: - PERROR("Software error: current tone reading has no codec\n"); - exit(-1); - } + l = read_tone(p_tone_fh, buffer, p_tone_codec, len, p_tone_size, &p_tone_left, p_tone_speed); + if (l<0 || l>len) /* paranoia */ + l=0; + buffer += l; + len -= l; } if (p_tone_fetched) { - switch(codec_in) - { - case CODEC_LAW: - l = read_tone_fetched(&p_tone_fetched, buf_in8, codec_in, len, p_tone_size, &p_tone_left, p_tone_speed); - if (l<0 || l>len) /* paranoia */ - l=0; - buf_in8 += l; - len -= l; - break; - - case CODEC_MONO: - l = read_tone_fetched(&p_tone_fetched, buf_in16, codec_in, len, p_tone_size, &p_tone_left, p_tone_speed); - if (l<0 || l>len) /* paranoia */ - l=0; - buf_in16 += l; - len -= l; - break; - - default: - PERROR("Software error: current tone reading has no codec\n"); - exit(-1); - } + l = read_tone_fetched(&p_tone_fetched, buffer, len, p_tone_size, &p_tone_left, p_tone_speed); + if (l<0 || l>len) /* paranoia */ + l=0; + buffer += l; + len -= l; } /* if counter is enabled, we check if we have a change */ @@ -968,7 +566,7 @@ read_more: } if (len==0) - goto mix_to_buffer; + goto done; if (p_tone_fh >= 0) { @@ -1031,690 +629,23 @@ try_loop: } fhuse++; } - codec_in = p_tone_codec; nodata++; PDEBUG(DEBUG_PORT, "PORT(%s) opening %stone: %s\n", p_name, p_tone_fetched?"fetched ":"", filename); /* now we have opened the loop */ goto read_more; - /* ********** - * now we mix - * we take the buffer content and mix the mixer_buffer to what we got - */ -mix_to_buffer: - /* release all writepointer which will underrun, since writing of - * remote port data is too slow - */ - relation = p_mixer_rel; - readp = p_mixer_readp; - relationpointer = &(p_mixer_rel); - while(relation) /* if no relation, this is skipped */ - { - /* NOTE: if writep and readp are equal, the distance ist max - * == PORT_BUFFER - */ - if (((relation->mixer_writep-readp-1+PORT_BUFFER)%PORT_BUFFER)+1 <= length) /* underrun */ - { - /* remove port relation in order to resync. - * this is also caused by ports which do not transmit - * anymore. - */ -#ifdef MIXER_DEBUG - PERROR("PORT(%s) Buffer underrun, source port is sending too slow or stopped sending, removing relation. (readp=%d, writep=%d, PORT_BUFFER=%d)\n", p_name, readp, relation->mixer_writep, PORT_BUFFER); -#endif - - *relationpointer = relation->next; - memset(relation, 0, sizeof(struct mixer_relation)); - free(relation); - pmemuse--; - relation = *relationpointer; - continue; - } - relationpointer = &(relation->next); - relation = relation->next; - } - - /* if we do recording, we write the record data and the buffer data to the record fp and increment record_count */ - if (p_record) - switch (p_record_type) - { - case CODEC_MONO: - /* convert from mixer to uncompressed 16 bit mono audio */ - switch(codec_in) - { - case CODEC_MONO: - case CODEC_STEREO: - case CODEC_8BIT: - len = length; - mix_buffer = p_record_buffer; - rec_buffer = record_buffer; - buf_in16 = (signed short *)temp_buffer; - if (len+readp >= PORT_BUFFER) /* data hits the buffer end */ - { - len = len+readp-PORT_BUFFER; /* rest to read from buffer start */ - while(readp < PORT_BUFFER) - { /* mix till buffer end */ - sample = mix_buffer[readp]+*(buf_in16++); - mix_buffer[readp++] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(rec_buffer++) = sample; - } - readp = 0; - } - while(len--) /* write rest */ - { /* mix till buffer end */ - sample = mix_buffer[readp]+*(buf_in16++); - mix_buffer[readp++] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(rec_buffer++) = sample; - } - - /* restore (changed) read pointer for further use */ - readp = p_mixer_readp; - - /* now write the rec_buffer to the file */ - if (p_record_skip) - { - p_record_skip -= length; - if (p_record_skip < 0) - p_record_skip = 0; - } else - { - fwrite(record_buffer, (length<<1), 1, p_record); - p_record_length = (length<<1) + p_record_length; - } - break; - - case CODEC_LAW: - len = length; - mix_buffer = p_record_buffer; - rec_buffer = record_buffer; - buf_in8 = (unsigned char *)temp_buffer; - if (len+readp >= PORT_BUFFER) /* data hits the buffer end */ - { - len = len+readp-PORT_BUFFER; /* rest to read from buffer start */ - while(readp < PORT_BUFFER) - { /* mix till buffer end */ - sample = mix_buffer[readp]+audio_law_to_s32[*(buf_in8++)]; - mix_buffer[readp++] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(rec_buffer++) = sample; - } - readp = 0; - } - while(len--) /* write rest */ - { /* mix till buffer end */ - sample = mix_buffer[readp]+audio_law_to_s32[*(buf_in8++)]; - mix_buffer[readp++] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(rec_buffer++) = sample; - } - - /* restore (changed) read pointer for further use */ - readp = p_mixer_readp; - - /* now write the rec_buffer to the file */ - if (p_record_skip) - { - p_record_skip -= length; - if (p_record_skip < 0) - p_record_skip = 0; - } else - { - fwrite(record_buffer, (length<<1), 1, p_record); - p_record_length = (length<<1) + p_record_length; - } - break; - - } - break; - - case CODEC_STEREO: - /* convert from mixer to uncompressed 16 bit stereo audio */ - switch(codec_in) - { - case CODEC_MONO: - case CODEC_STEREO: - case CODEC_8BIT: - len = length; - mix_buffer = p_record_buffer; - mix_buffer2 = p_stereo_buffer; - rec_buffer = record_buffer; - buf_in16 = (signed short *)temp_buffer; - if (len+readp >= PORT_BUFFER) /* data hits the buffer end */ - { - len = len+readp-PORT_BUFFER; /* rest to read from buffer start */ - while(readp < PORT_BUFFER) - { /* mix till buffer end */ - sample = mix_buffer[readp]+*(buf_in16++); - mix_buffer[readp] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(rec_buffer++) = sample; - - *(rec_buffer++) = mix_buffer2[readp]; - mix_buffer2[readp++] = 0; - } - readp = 0; - } - while(len--) /* write rest */ - { /* mix till buffer end */ - sample = mix_buffer[readp]+*(buf_in16++); - mix_buffer[readp] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(rec_buffer++) = sample; - *(rec_buffer++) = mix_buffer2[readp]; - mix_buffer2[readp++] = 0; - } - - /* restore (changed) read pointer for further use */ - readp = p_mixer_readp; - - /* now write the rec_buffer to the file */ - if (p_record_skip) - { - p_record_skip -= length; - if (p_record_skip < 0) - p_record_skip = 0; - } else - { - fwrite(record_buffer, (length<<2), 1, p_record); - p_record_length = (length<<2) + p_record_length; - } - break; - - case CODEC_LAW: - len = length; - mix_buffer = p_record_buffer; - mix_buffer2 = p_stereo_buffer; - rec_buffer = record_buffer; - buf_in8 = (unsigned char *)temp_buffer; - if (len+readp >= PORT_BUFFER) /* data hits the buffer end */ - { - len = len+readp-PORT_BUFFER; /* rest to read from buffer start */ - while(readp < PORT_BUFFER) - { /* mix till buffer end */ - sample = mix_buffer[readp]+audio_law_to_s32[*(buf_in8++)]; - mix_buffer[readp] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(rec_buffer++) = sample; - - *(rec_buffer++) = mix_buffer2[readp]; - mix_buffer2[readp++] = 0; - } - readp = 0; - } - while(len--) /* write rest */ - { /* mix till buffer end */ - sample = mix_buffer[readp]+audio_law_to_s32[*(buf_in8++)]; - mix_buffer[readp] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(rec_buffer++) = sample; - *(rec_buffer++) = mix_buffer2[readp]; - mix_buffer2[readp++] = 0; - } - - /* restore (changed) read pointer for further use */ - readp = p_mixer_readp; - - /* now write the rec_buffer to the file */ - if (p_record_skip) - { - p_record_skip -= length; - if (p_record_skip < 0) - p_record_skip = 0; - } else - { - fwrite(record_buffer, (length<<2), 1, p_record); - p_record_length = (length<<2) + p_record_length; - } - break; - } - break; - - case CODEC_8BIT: - /* convert from mixer to uncompressed 8 bit mono audio */ - switch(codec_in) - { - case CODEC_MONO: - case CODEC_STEREO: - case CODEC_8BIT: - len = length; - mix_buffer = p_record_buffer; - rec8_buffer = (unsigned char *)record_buffer; - buf_in16 = (signed short *)temp_buffer; - if (len+readp >= PORT_BUFFER) /* data hits the buffer end */ - { - len = len+readp-PORT_BUFFER; /* rest to read from buffer start */ - while(readp < PORT_BUFFER) - { /* mix till buffer end */ - sample = mix_buffer[readp]+*(buf_in16++); - mix_buffer[readp++] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(rec8_buffer++) = (sample>>8)+0x80; - } - readp = 0; - } - while(len--) /* write rest */ - { /* mix till buffer end */ - sample = mix_buffer[readp]+*(buf_in16++); - mix_buffer[readp++] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(rec8_buffer++) = (sample>>8)+0x80; - } - - /* restore (changed) read pointer for further use */ - readp = p_mixer_readp; - - /* now write the rec_buffer to the file */ - if (p_record_skip) - { - p_record_skip -= length; - if (p_record_skip < 0) - p_record_skip = 0; - } else - { - fwrite(record_buffer, (length), 1, p_record); - p_record_length = (length) + p_record_length; - } - break; - - case CODEC_LAW: - len = length; - mix_buffer = p_record_buffer; - rec8_buffer = (unsigned char *)record_buffer; - buf_in8 = (unsigned char *)temp_buffer; - if (len+readp >= PORT_BUFFER) /* data hits the buffer end */ - { - len = len+readp-PORT_BUFFER; /* rest to read from buffer start */ - while(readp < PORT_BUFFER) - { /* mix till buffer end */ - sample = mix_buffer[readp]+audio_law_to_s32[*(buf_in8++)]; - mix_buffer[readp++] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(rec8_buffer++) = (sample>>8)+0x80; - } - readp = 0; - } - while(len--) /* write rest */ - { /* mix till buffer end */ - sample = mix_buffer[readp]+audio_law_to_s32[*(buf_in8++)]; - mix_buffer[readp++] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(rec8_buffer++) = (sample>>8)+0x80; - } - - /* restore (changed) read pointer for further use */ - readp = p_mixer_readp; - - /* now write the rec_buffer to the file */ - if (p_record_skip) - { - p_record_skip -= length; - if (p_record_skip < 0) - p_record_skip = 0; - } else - { - fwrite(record_buffer, (length), 1, p_record); - p_record_length = (length) + p_record_length; - } - break; - - } - break; - - case CODEC_LAW: - case CODEC_OFF: /* if no codec is specified, the recorded data will be stored as LAW */ - /* convert from mixer to law */ - switch(codec_in) - { - case CODEC_MONO: - case CODEC_STEREO: - case CODEC_8BIT: - len = length; - mix_buffer = p_record_buffer; - rec8_buffer = (unsigned char *)record_buffer; - buf_in16 = (signed short *)temp_buffer; - if (len+readp >= PORT_BUFFER) /* data hits the buffer end */ - { - len = len+readp-PORT_BUFFER; /* rest to read from buffer start */ - while(readp < PORT_BUFFER) - { /* mix till buffer end */ - sample = mix_buffer[readp]+*(buf_in16++); - mix_buffer[readp++] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(rec8_buffer++) = audio_s16_to_law[sample & 0xffff]; - } - readp = 0; - } - while(len--) /* write rest */ - { /* mix till buffer end */ - sample = mix_buffer[readp]+*(buf_in16++); - mix_buffer[readp++] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(rec8_buffer++) = audio_s16_to_law[sample & 0xffff]; - } - - /* restore (changed) read pointer for further use */ - readp = p_mixer_readp; - - /* now write the rec_buffer to the file */ - if (p_record_skip) - { - p_record_skip -= length; - if (p_record_skip < 0) - p_record_skip = 0; - } else - { - fwrite(record_buffer, (length), 1, p_record); - p_record_length = (length) + p_record_length; - } - break; - - case CODEC_LAW: - len = length; - mix_buffer = p_record_buffer; - rec8_buffer = (unsigned char *)record_buffer; - buf_in8 = (unsigned char *)temp_buffer; - if (len+readp >= PORT_BUFFER) /* data hits the buffer end */ - { - len = len+readp-PORT_BUFFER; /* rest to read from buffer start */ - while(readp < PORT_BUFFER) - { /* mix till buffer end */ - sample = mix_buffer[readp]+audio_law_to_s32[*(buf_in8++)]; - mix_buffer[readp++] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(rec8_buffer++) = audio_s16_to_law[sample & 0xffff]; - } - readp = 0; - } - while(len--) /* write rest */ - { /* mix till buffer end */ - sample = mix_buffer[readp]+audio_law_to_s32[*(buf_in8++)]; - mix_buffer[readp++] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(rec8_buffer++) = audio_s16_to_law[sample & 0xffff]; - } - - /* restore (changed) read pointer for further use */ - readp = p_mixer_readp; - - /* now write the rec_buffer to the file */ - if (p_record_skip) - { - p_record_skip -= length; - if (p_record_skip < 0) - p_record_skip = 0; - } else - { - fwrite(record_buffer, (length), 1, p_record); - p_record_length = (length) + p_record_length; - } - break; - } - break; - } - - /* if we have no transmitting relation, we do not need read mixer */ - if (!p_mixer_rel) - { /* nothing mixed to(no rel), so we are just done */ - if (compressed) - { - /* compress to law */ - len = length; - buf_in8 = (unsigned char *)temp_buffer; - buf_in16 = (signed short *)temp_buffer; - buf_out16 = (signed short *)buffer; - switch(codec_in) - { - case CODEC_MONO: - case CODEC_STEREO: - case CODEC_8BIT: - while(len--) - *(buffer++) = audio_s16_to_law[*(buf_in16++) & 0xffff]; - break; - - case CODEC_LAW: - memcpy(buffer, temp_buffer, length); - break; - - default: - PERROR("Software error: current tone for unmixed & uncompressed, has no codec\n"); - exit(-1); - } - } else - { - /* uncompress law files */ - len = length; - buf_in8 = (unsigned char *)temp_buffer; - buf_in16 = (signed short *)temp_buffer; - buf_out16 = (signed short *)buffer; - switch(codec_in) - { - case CODEC_MONO: - case CODEC_STEREO: - case CODEC_8BIT: - while(len--) - (*(buf_out16++)) = *(buf_in16++); - break; - - case CODEC_LAW: - while(len--) - (*(buf_out16++)) = audio_law_to_s32[*(buf_in8++)]; - break; - - default: - PERROR("Software error: current tone for unmixed & uncompressed, has no codec\n"); - exit(-1); - } - } - return(length); - } - -// PDEBUG(DEBUG_PORT, "PORT(%s) mixing %d bytes. (readp=%d, PORT_BUFFER=%d)\n", p_name, length, readp, PORT_BUFFER); - /* now we got our stuff and we'll mix it baby */ - - len = length; - mix_buffer = p_mixer_buffer; - if (compressed) - { - /* convert from mixer to compressed law data */ - switch(codec_in) - { - case CODEC_MONO: - case CODEC_STEREO: - case CODEC_8BIT: - buf_in16 = (signed short *)temp_buffer; - if (len+readp >= PORT_BUFFER) /* data hits the buffer end */ - { - len = len+readp-PORT_BUFFER; /* rest to read from buffer start */ - while(readp < PORT_BUFFER) - { /* mix till buffer end */ - sample = mix_buffer[readp]+*(buf_in16++); - mix_buffer[readp++] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(buffer++) = audio_s16_to_law[sample & 0xffff]; - } - readp = 0; - } - while(len--) /* write rest */ - { /* mix till buffer end */ - sample = mix_buffer[readp]+*(buf_in16++); - mix_buffer[readp++] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(buffer++) = audio_s16_to_law[sample & 0xffff]; - } - break; - - case CODEC_LAW: - buf_in8 = (unsigned char *)temp_buffer; - if (len+readp >= PORT_BUFFER) /* data hits the buffer end */ - { - len = len+readp-PORT_BUFFER; /* rest to read from buffer start */ - while(readp < PORT_BUFFER) - { /* mix till buffer end */ - sample = mix_buffer[readp]+audio_law_to_s32[*(buf_in8++)]; - mix_buffer[readp++] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(buffer++) = audio_s16_to_law[sample & 0xffff]; - } - readp = 0; - } - while(len--) /* write rest */ - { /* mix till buffer end */ - sample = mix_buffer[readp]+audio_law_to_s32[*(buf_in8++)]; - mix_buffer[readp++] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(buffer++) = audio_s16_to_law[sample & 0xffff]; - } - break; - - default: - PERROR("Software error: current tone for compressed data has no codec\n"); - exit(-1); - } - } else - { - /* convert from mixer to uncompressed 16 bit audio */ - switch(codec_in) - { - case CODEC_MONO: - case CODEC_STEREO: - case CODEC_8BIT: - buf_in16 = (signed short *)temp_buffer; - buf_out16 = (signed short *)buffer; - if (len+readp >= PORT_BUFFER) /* data hits the buffer end */ - { - len = len+readp-PORT_BUFFER; /* rest to read from buffer start */ - while(readp < PORT_BUFFER) - { /* mix till buffer end */ - sample = mix_buffer[readp]+*(buf_in16++); - mix_buffer[readp++] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(buf_out16++) = sample; - } - readp = 0; - } - while(len--) /* write rest */ - { /* mix till buffer end */ - sample = mix_buffer[readp]+*(buf_in16++); - mix_buffer[readp++] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(buf_out16++) = sample; - } - break; - - case CODEC_LAW: - buf_in8 = (unsigned char *)temp_buffer; - buf_out16 = (signed short *)buffer; - if (len+readp >= PORT_BUFFER) /* data hits the buffer end */ - { - len = len+readp-PORT_BUFFER; /* rest to read from buffer start */ - while(readp < PORT_BUFFER) - { /* mix till buffer end */ - sample = mix_buffer[readp]+audio_law_to_s32[*(buf_in8++)]; - mix_buffer[readp++] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(buf_out16++) = sample; - } - readp = 0; - } - while(len--) /* write rest */ - { /* mix till buffer end */ - sample = mix_buffer[readp]+audio_law_to_s32[*(buf_in8++)]; - mix_buffer[readp++] = 0; - if (sample < -32767) - sample = -32767; - if (sample > 32767) - sample = 32767; - *(buf_out16++) = sample; - } - break; - - default: - PERROR("Software error: current tone for uncompressed data has no codec\n"); - exit(-1); - } - } - - p_mixer_readp = readp; /* new read pointer */ - +done: return(length); } -/* dummy handler */ +/* port handler: + * process transmission clock */ int Port::handler(void) { + port + return(0); } diff --git a/port.h b/port.h index 688faa6..bb93479 100644 --- a/port.h +++ b/port.h @@ -24,12 +24,6 @@ /* te-mode */ #define PORT_TYPE_DSS1_TE_IN 0x0113 #define PORT_TYPE_DSS1_TE_OUT 0x0114 - /* sip */ -#define PORT_TYPE_SIP_IN 0x0121 -#define PORT_TYPE_SIP_OUT 0x0122 - /* h323 */ -#define PORT_TYPE_H323_IN 0x0211 -#define PORT_TYPE_H323_OUT 0x0212 /* answering machine */ #define PORT_TYPE_VBOX_OUT 0x0311 @@ -172,16 +166,6 @@ class Port void set_vbox_play(char *name, int offset); /* sample of answ. */ void set_vbox_speed(int speed); /* speed of answ. */ - /* user space mixer buffer */ - signed long p_mixer_buffer[PORT_BUFFER]; /* mixer buffer */ - signed long p_record_buffer[PORT_BUFFER]; /* record buffer */ - signed long p_stereo_buffer[PORT_BUFFER]; /* record buffer for stereo (user only) */ - struct mixer_relation *p_mixer_rel; /* list of mixer relations */ - int p_mixer_readp; /* read pointer in buffer */ - - /* methods */ - void mixer(union parameter *param); - /* identification */ unsigned long p_serial; /* serial unique id of port */ char p_name[128]; /* name of port or token (h323) */ diff --git a/route.c b/route.c index 38f1f7e..b39d2e0 100644 --- a/route.c +++ b/route.c @@ -20,16 +20,10 @@ struct route_ruleset *ruleset_first; /* first entry */ struct route_ruleset *ruleset_main; /* pointer to main ruleset */ struct cond_defs cond_defs[] = { -#ifdef PBX { "extern", MATCH_EXTERN, COND_TYPE_NULL, - "extern", "Matches if call is from external port."}, - { "intern", MATCH_INTERN, COND_TYPE_NULL, - "intern", "Matches if call is from internal port."}, -#endif - { "h323", MATCH_H323, COND_TYPE_NULL, - "h323", "Matches if call is received via H.323."}, -// { "ip", MATCH_IP, COND_TYPE_IP, -// "ip=[-|/][,...]", "Matches if caller matches given source IP address(es) / range(s) / block(s)."}, + "extern", "Matches if call is from external port (no extension)."}, + { "intern", MATCH_INTERN,COND_TYPE_NULL, + "intern", "Matches if call is from an extension."}, { "port", MATCH_PORT, COND_TYPE_INTEGER, "port=[-][,...]", "Matches if call is received from given port(s). NOT INTERFACE!"}, { "interface", MATCH_INTERFACE,COND_TYPE_STRING, @@ -111,14 +105,12 @@ struct param_defs param_defs[] = { { PARAM_CONNECT, "connect", PARAM_TYPE_NULL, "connect", "Will complete the call before processing the action. Audio path for external calls will be established."}, -#ifdef PBX { PARAM_EXTENSION, "extension", PARAM_TYPE_STRING, "extension=", "Give extension name (digits) to relate this action to."}, { PARAM_EXTENSIONS, "extensions", PARAM_TYPE_STRING, "extensions=[,[,...]]", "One or more extensions may be given."}, -#endif { PARAM_PREFIX, "prefix", PARAM_TYPE_STRING, "prefix=", "Add prefix in front of the dialed number."}, @@ -170,11 +162,9 @@ struct param_defs param_defs[] = { { PARAM_SAMPLE, "sample", PARAM_TYPE_STRING, "sample=", "Filename of sample (current tone's dir) or full path to sample. ('.wav'/'.wave'/'.isdn' is added automatically."}, -#ifdef PBX { PARAM_ANNOUNCEMENT, "announcement",PARAM_TYPE_STRING, "announcement=", "Filename of announcement (inside vbox recording dir) or full path to sample. ('.wav'/'.wave'/'.isdn' is added automatically."}, -#endif { PARAM_RULESET, "ruleset", PARAM_TYPE_STRING, "ruleset=", "Ruleset to go to."}, @@ -229,11 +219,9 @@ struct param_defs param_defs[] = { { PARAM_TIMEOUT, "timeout", PARAM_TYPE_INTEGER, "timeout=", "Timeout before continue with next action."}, -#ifdef PBX { PARAM_NOPASSWORD, "nopassword", PARAM_TYPE_NULL, "nopassword", "Don't ask for password. Be sure to authenticate right via real caller ID."}, -#endif { 0, NULL, 0, NULL, NULL} }; @@ -250,10 +238,6 @@ struct action_defs action_defs[] = { "outdial", &EndpointAppPBX::action_init_call, &EndpointAppPBX::action_dialing_external, &EndpointAppPBX::action_hangup_call, PARAM_CONNECT | PARAM_PREFIX | PARAM_COMPLETE | PARAM_TYPE | PARAM_CAPA | PARAM_BMODE | PARAM_INFO1 | PARAM_HLC | PARAM_EXTHLC | PARAM_PRESENT | PARAM_INTERFACES | PARAM_CALLERID | PARAM_CALLERIDTYPE | PARAM_TIMEOUT, "Same as 'extern'"}, - { ACTION_H323, - "h323", &EndpointAppPBX::action_init_call, &EndpointAppPBX::action_dialing_h323, &EndpointAppPBX::action_hangup_call, - PARAM_CONNECT | PARAM_PREFIX | PARAM_HOST | PARAM_PORT | PARAM_ADDRESS | PARAM_TIMEOUT, - "Call is routed to H.323 host/gateway."}, { ACTION_CHAN, "asterisk", &EndpointAppPBX::action_init_chan, &EndpointAppPBX::action_dialing_chan, &EndpointAppPBX::action_hangup_call, PARAM_CONNECT | PARAM_TIMEOUT, @@ -2038,13 +2022,6 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset) istrue = 1; break; - case MATCH_H323: -// printf("\n\n\nport-type %x\n\n\n\n", ea_endpoint->ep_portlist->port_type); - if (ea_endpoint->ep_portlist) - if (ea_endpoint->ep_portlist->port_type == PORT_TYPE_H323_IN) - istrue = 1; - break; - case MATCH_PORT: if (ea_endpoint->ep_portlist) if ((ea_endpoint->ep_portlist->port_type & PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1) @@ -2481,14 +2458,6 @@ struct route_action action_internal = { 0, }; -struct route_action action_h323 = { - NULL, - NULL, - ACTION_H323, - 0, - 0, -}; - struct route_action action_chan = { NULL, NULL, diff --git a/route.h b/route.h index c4da1b4..7ed536d 100644 --- a/route.h +++ b/route.h @@ -36,12 +36,8 @@ enum { /* how to parse text file during startup */ }; enum { /* what to check during runtime */ -#ifdef PBX MATCH_EXTERN, MATCH_INTERN, -#endif - MATCH_H323, -// MATCH_IP, MATCH_PORT, MATCH_INTERFACE, MATCH_CALLERID, @@ -96,10 +92,8 @@ enum { /* how to parse text file during startup */ #define PARAM_PROCEEDING 1LL #define PARAM_ALERTING (1LL<<1) #define PARAM_CONNECT (1LL<<2) -#ifdef PBX #define PARAM_EXTENSION (1LL<<3) #define PARAM_EXTENSIONS (1LL<<4) -#endif #define PARAM_PREFIX (1LL<<5) #define PARAM_CAPA (1LL<<6) #define PARAM_BMODE (1LL<<7) @@ -149,37 +143,36 @@ enum { /* how to parse text file during startup */ #define ACTION_EXTERNAL 0 #define ACTION_INTERNAL 1 #define ACTION_OUTDIAL 2 -#define ACTION_H323 3 -#define ACTION_CHAN 4 -#define ACTION_VBOX_RECORD 5 -#define ACTION_PARTYLINE 6 -#define ACTION_LOGIN 7 -#define ACTION_CALLERID 8 -#define ACTION_CALLERIDNEXT 9 -#define ACTION_FORWARD 10 -#define ACTION_REDIAL 11 -#define ACTION_REPLY 12 -#define ACTION_POWERDIAL 13 -#define ACTION_CALLBACK 14 -#define ACTION_ABBREV 15 -#define ACTION_TEST 16 -#define ACTION_PLAY 17 -#define ACTION_VBOX_PLAY 18 -#define ACTION_CALCULATOR 19 -#define ACTION_TIMER 20 -#define ACTION_GOTO 21 -#define ACTION_MENU 22 -#define ACTION_DISCONNECT 23 -#define ACTION_HELP 24 -#define ACTION_DEFLECT 25 -#define ACTION_SETFORWARD 26 -#define ACTION_EXECUTE 27 -#define ACTION_FILE 28 -#define ACTION_PICK 29 -#define ACTION_PASSWORD 30 -#define ACTION_PASSWORD_WRITE 31 -#define ACTION_NOTHING 32 -#define ACTION_EFI 33 +#define ACTION_CHAN 3 +#define ACTION_VBOX_RECORD 4 +#define ACTION_PARTYLINE 5 +#define ACTION_LOGIN 6 +#define ACTION_CALLERID 7 +#define ACTION_CALLERIDNEXT 8 +#define ACTION_FORWARD 9 +#define ACTION_REDIAL 10 +#define ACTION_REPLY 11 +#define ACTION_POWERDIAL 12 +#define ACTION_CALLBACK 13 +#define ACTION_ABBREV 14 +#define ACTION_TEST 15 +#define ACTION_PLAY 16 +#define ACTION_VBOX_PLAY 17 +#define ACTION_CALCULATOR 18 +#define ACTION_TIMER 19 +#define ACTION_GOTO 20 +#define ACTION_MENU 21 +#define ACTION_DISCONNECT 22 +#define ACTION_HELP 23 +#define ACTION_DEFLECT 24 +#define ACTION_SETFORWARD 25 +#define ACTION_EXECUTE 26 +#define ACTION_FILE 27 +#define ACTION_PICK 28 +#define ACTION_PASSWORD 29 +#define ACTION_PASSWORD_WRITE 30 +#define ACTION_NOTHING 31 +#define ACTION_EFI 32 struct route_cond { /* an item */ struct route_cond *next; /* next entry */ @@ -263,7 +256,6 @@ extern struct route_ruleset *ruleset_first; extern struct route_ruleset *ruleset_main; extern struct route_action action_external; extern struct route_action action_internal; -extern struct route_action action_h323; extern struct route_action action_chan; extern struct route_action action_vbox; extern struct route_action action_partyline; diff --git a/todo.txt b/todo.txt index 131a13c..ad0b9fc 100644 --- a/todo.txt +++ b/todo.txt @@ -3,7 +3,7 @@ define and change dsp conference ids make asterisk call implementation -new interface.conf +new interface.conf (add remove ports by admin) reduce mixer @@ -20,10 +20,9 @@ trace with layers and filters - application process (action) - bchannel control (tones, dsp, filter, activation/deactivation) -sip raus, h323 raus - avoid disconnect-collision (release if disconnect from both sides) +display message during nothing/play diff --git a/tones.c b/tones.c index 45c05c9..5d64125 100644 --- a/tones.c +++ b/tones.c @@ -276,6 +276,7 @@ int open_tone(char *file, int *codec, signed long *length, signed long *left) /* * read from tone, check size * the len must be the number of samples, NOT for the bytes to read!! + * the data returned is law-code */ int read_tone(int fh, void *buffer, int codec, int len, signed long size, signed long *left, int speed) { @@ -319,15 +320,29 @@ int read_tone(int fh, void *buffer, int codec, int len, signed long size, signed break; case CODEC_MONO: - l = read(fh, buffer, len<<1); /* as is */ - if (l>0) - l = l>>1; + signed short buffer16[len], *buf16 = buffer16; + signed long sample; + int i = 0; + l = read(fh, buf16, len<<1); + if (l>0) + { + l = l>>1; + while(i < l) + { + sample = *buf16++; + if (sample < -32767) + sample = -32767; + if (sample > 32767) + sample = 32767; + *buffer++ = audio_s16_to_law[sample & 0xffff]; + i++; + } + } break; case CODEC_STEREO: { signed short buffer32[len<<1], *buf32 = buffer32; - signed short *buf16 = (signed short *)buffer; signed long sample; int i = 0; l = read(fh, buf32, len<<2); @@ -341,7 +356,7 @@ int read_tone(int fh, void *buffer, int codec, int len, signed long size, signed sample = -32767; if (sample > 32767) sample = 32767; - *buf16++ = sample; + *buffer++ = audio_s16_to_law[sample & 0xffff]; i++; } } @@ -351,14 +366,13 @@ int read_tone(int fh, void *buffer, int codec, int len, signed long size, signed case CODEC_8BIT: { unsigned char buffer8[len], *buf8 = buffer8; - signed short *buf16 = (signed short *)buffer; int i = 0; l = read(fh, buf8, len); if (l>0) { while(i < l) { - *buf16++ = (((*buf8++) << 8) - 0x8000) & 0xffff; + *buffer++ = audio_s16_to_law[(((*buf8++)<<8)-0x8000) & 0xffff]; i++; } } @@ -366,7 +380,7 @@ int read_tone(int fh, void *buffer, int codec, int len, signed long size, signed break; default: - PERROR("codec %d is not specified or supported, exitting...\n", codec); + PERROR("codec %d is not supported, exitting...\n", codec); exit(-1); } @@ -420,7 +434,7 @@ int fetch_tones(void) char filename[256], name[256]; int fh; int tone_codec; - signed long tone_size, tone_left, real_size; + signed long tone_size, tone_left; unsigned long memory = 0; int samples = 0; @@ -515,32 +529,8 @@ int fetch_tones(void) continue; } - /* real size */ - switch(tone_codec) - { - case CODEC_LAW: - real_size = tone_size; - break; - - case CODEC_MONO: - real_size = tone_size << 1; - break; - - case CODEC_STEREO: - real_size = tone_size << 1; - break; - - case CODEC_8BIT: - real_size = tone_size << 1; - break; - - default: - PERROR("codec %d is not specified or supported, exitting...\n", tone_codec); - exit(-1); - } - /* allocate tone */ - *tonesettone_nextpointer = (struct tonesettone *)calloc(1, sizeof(struct tonesettone)+real_size); + *tonesettone_nextpointer = (struct tonesettone *)calloc(1, sizeof(struct tonesettone)+tone_size); if (*toneset_nextpointer == NULL) { PERROR("No memory for tone set: '%s'\n",p); @@ -550,8 +540,8 @@ int fetch_tones(void) } memuse++; //printf("tone:%s, %ld bytes\n", name, tone_size); - memset(*tonesettone_nextpointer, 0 , sizeof(struct tonesettone)+real_size); - memory += sizeof(struct tonesettone)+real_size; + memset(*tonesettone_nextpointer, 0 , sizeof(struct tonesettone)+tone_size); + memory += sizeof(struct tonesettone)+tone_size; samples ++; /* load tone */ @@ -629,7 +619,7 @@ void *open_tone_fetched(char *dir, char *file, int *codec, signed long *length, * read from fetched tone, check size * the len must be the number of samples, NOT for the bytes to read!! */ -int read_tone_fetched(void **fetched, void *buffer, int codec, int len, signed long size, signed long *left, int speed) +int read_tone_fetched(void **fetched, void *buffer, int len, signed long size, signed long *left, int speed) { int l; //printf("left=%ld\n",*left); @@ -643,24 +633,10 @@ int read_tone_fetched(void **fetched, void *buffer, int codec, int len, signed l if (*left < len) len = *left; - switch(codec) - { - case CODEC_LAW: - memcpy(buffer, *fetched, len); - *((char **)fetched) += len; - l = len; - break; - - case CODEC_MONO: - memcpy(buffer, *fetched, len<<1); - *((char **)fetched) += len<<1; - l = len; - break; - default: - PERROR("codec %d is not specified or supported, exitting...\n", codec); - exit(-1); - } + memcpy(buffer, *fetched, len); + *((char **)fetched) += len; + l = len; if (l>0 && left) *left -= l; diff --git a/vbox.cpp b/vbox.cpp index 2a96962..a059898 100644 --- a/vbox.cpp +++ b/vbox.cpp @@ -62,9 +62,13 @@ int VBoxPort::handler(void) { struct message *message; unsigned long tosend; - signed short buffer[128<<1]; + signed short buffer[128]; time_t currenttime; class Endpoint *epoint; + int ret; + + if ((ret = Port::handler())) + return(ret); if (p_vbox_record_start && p_vbox_record_limit) { @@ -98,7 +102,7 @@ int VBoxPort::handler(void) /* wait for more */ if (tosend < 32) - return(0); + return(Port::handler()); /* too many samples, so we just process 128 bytes until the next call of handler() */ if (tosend > 128) @@ -113,23 +117,7 @@ int VBoxPort::handler(void) /* if announcement is currently played, send audio data */ if (p_vbox_announce_fh >=0) { - /* read from announcement file */ - switch(p_vbox_announce_codec) - { - case CODEC_LAW: - tosend = read_tone(p_vbox_announce_fh, buffer, p_vbox_announce_codec, tosend, p_vbox_announce_size, &p_vbox_announce_left, 1); - break; - - case CODEC_MONO: - case CODEC_STEREO: - case CODEC_8BIT: - tosend = read_tone(p_vbox_announce_fh, buffer, p_vbox_announce_codec, tosend, p_vbox_announce_size, &p_vbox_announce_left, 1); - break; - - default: - PERROR("correct codec not given.\n"); - exit(-1); - } + tosend = read_tone(p_vbox_announce_fh, buffer, p_vbox_announce_codec, tosend, p_vbox_announce_size, &p_vbox_announce_left, 1); if (tosend <= 0) { /* end of file */ @@ -175,34 +163,12 @@ int VBoxPort::handler(void) } } else { - switch(p_vbox_announce_codec) - { - case CODEC_LAW: - message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DATA); - message->param.data.compressed = 1; - message->param.data.port_type = p_type; - message->param.data.port_id = p_serial; - message->param.data.len = tosend; - memcpy(message->param.data.data, buffer, tosend); - message_put(message); - break; - - case CODEC_MONO: - case CODEC_STEREO: - case CODEC_8BIT: - message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DATA); - message->param.data.compressed = 0; - message->param.data.port_type = p_type; - message->param.data.port_id = p_serial; - message->param.data.len = tosend<<1; - memcpy(message->param.data.data, buffer, tosend<<1); - message_put(message); - break; - - default: - PERROR("correct announce_codec not given.\n"); - exit(-1); - } + message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DATA); + message->param.data.port_type = p_type; + message->param.data.port_id = p_serial; + message->param.data.len = tosend; + memcpy(message->param.data.data, buffer, tosend); + message_put(message); } } @@ -221,6 +187,9 @@ int VBoxPort::message_epoint(unsigned long epoint_id, int message_id, union para char filename[256], *c; class EndpointAppPBX *eapp; + if (Port::message_epoint(epoint_id, message_id, param)) + return(1); + epoint = find_epoint_id(epoint_id); if (!epoint) { @@ -228,9 +197,6 @@ int VBoxPort::message_epoint(unsigned long epoint_id, int message_id, union para return(0); } - if (Port::message_epoint(epoint_id, message_id, param)) - return(1); - switch(message_id) { case MESSAGE_DISCONNECT: /* call has been disconnected */