Version 0.1.12 from FTP
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@465 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
parent
74d376fd37
commit
87909fa28e
63
Makefile
63
Makefile
|
@ -11,7 +11,6 @@
|
|||
# the GNU General Public License
|
||||
#
|
||||
|
||||
|
||||
.EXPORT_ALL_VARIABLES:
|
||||
|
||||
INSTALL_PREFIX=
|
||||
|
@ -22,14 +21,20 @@ AGI_DIR=$(INSTALL_PREFIX)/var/lib/asterisk/agi-bin
|
|||
# Pentium Pro Optimize
|
||||
#PROC=i686
|
||||
# Pentium Optimize
|
||||
PROC=i586
|
||||
#PROC=i586
|
||||
#PROC=k6
|
||||
#PROC=ppc
|
||||
PROC=$(shell uname -m)
|
||||
|
||||
DEBUG=-g #-pg
|
||||
INCLUDE=-Iinclude -I../include
|
||||
CFLAGS=-pipe -Wall -Wmissing-prototypes -Wmissing-declarations -O6 $(DEBUG) $(INCLUDE) -D_REENTRANT
|
||||
CFLAGS=-pipe -Wall -Wmissing-prototypes -Wmissing-declarations -O6 $(DEBUG) $(INCLUDE) -D_REENTRANT -D_GNU_SOURCE
|
||||
#CFLAGS+=-Werror
|
||||
CFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi)
|
||||
CFLAGS+=$(shell if uname -m | grep -q ppc; then echo "-fsigned-char"; fi)
|
||||
|
||||
ASTERISKVERSION=$(shell if [ -f .version ]; then cat .version; fi)
|
||||
HTTPDIR=$(shell if [ -d /var/www ]; then echo "/var/www"; else echo "/home/httpd"; fi)
|
||||
RPMVERSION=$(shell sed 's/[-\/:]/_/g' .version)
|
||||
CFLAGS+=-DASTERISK_VERSION=\"$(ASTERISKVERSION)\"
|
||||
# Optional debugging parameters
|
||||
|
@ -38,11 +43,11 @@ CFLAGS+= -DDO_CRASH -DDEBUG_THREADS
|
|||
#CLFAGS+= -DTRACE_FRAMES
|
||||
CFLAGS+=# -fomit-frame-pointer
|
||||
SUBDIRS=res channels pbx apps codecs formats agi cdr
|
||||
LIBS=-ldl -lpthread -lreadline -lncurses -lm
|
||||
LIBS=-ldl -lpthread -lreadline -lncurses -lm #-lnjamd
|
||||
OBJS=io.o sched.o logger.o frame.o loader.o config.o channel.o \
|
||||
translate.o file.o say.o pbx.o cli.o md5.o \
|
||||
translate.o file.o say.o pbx.o cli.o md5.o term.o \
|
||||
ulaw.o alaw.o callerid.o fskmodem.o image.o app.o \
|
||||
cdr.o tdd.o asterisk.o
|
||||
cdr.o tdd.o acl.o rtp.o asterisk.o
|
||||
CC=gcc
|
||||
INSTALL=install
|
||||
|
||||
|
@ -81,9 +86,10 @@ datafiles: all
|
|||
for x in sounds/digits/*; do \
|
||||
install $$x $(INSTALL_PREFIX)/var/lib/asterisk/sounds/digits ; \
|
||||
done
|
||||
for x in sounds/vm-* sounds/transfer* sounds/pbx-* sounds/ss-* sounds/beep* sounds/dir-*; do \
|
||||
for x in sounds/vm-* sounds/transfer* sounds/pbx-* sounds/ss-* sounds/beep* sounds/dir-* sounds/conf-*; do \
|
||||
install $$x $(INSTALL_PREFIX)/var/lib/asterisk/sounds ; \
|
||||
done
|
||||
mkdir -p $(INSTALL_PREFIX)/var/lib/asterisk/mohmp3
|
||||
mkdir -p $(INSTALL_PREFIX)/var/lib/asterisk/images
|
||||
for x in images/*.jpg; do \
|
||||
install $$x $(INSTALL_PREFIX)/var/lib/asterisk/images ; \
|
||||
|
@ -93,8 +99,10 @@ datafiles: all
|
|||
install: all datafiles
|
||||
mkdir -p $(MODULES_DIR)
|
||||
mkdir -p $(INSTALL_PREFIX)/usr/sbin
|
||||
mkdir -p $(INSTALL_PREFIX)/etc/asterisk
|
||||
install -m 755 asterisk $(INSTALL_PREFIX)/usr/sbin/
|
||||
install -m 755 astgenkey $(INSTALL_PREFIX)/usr/sbin/
|
||||
install -m 755 safe_asterisk $(INSTALL_PREFIX)/usr/sbin/
|
||||
for x in $(SUBDIRS); do $(MAKE) -C $$x install || exit 1 ; done
|
||||
install -d $(INSTALL_PREFIX)/usr/include/asterisk
|
||||
install include/asterisk/*.h $(INSTALL_PREFIX)/usr/include/asterisk
|
||||
|
@ -128,7 +136,15 @@ install: all datafiles
|
|||
@echo " + **Note** This requires that you have +"
|
||||
@echo " + doxygen installed on your local system +"
|
||||
@echo " +-------------------------------------------+"
|
||||
samples: all datafiles
|
||||
adsi: all
|
||||
mkdir -p /etc/asterisk
|
||||
for x in configs/*.adsi; do \
|
||||
if ! [ -f $(INSTALL_PREFIX)/etc/asterisk/$$x ]; then \
|
||||
install -m 644 $$x $(INSTALL_PREFIX)/etc/asterisk/`basename $$x` ; \
|
||||
fi ; \
|
||||
done
|
||||
|
||||
samples: all datafiles adsi
|
||||
mkdir -p $(INSTALL_PREFIX)/etc/asterisk
|
||||
for x in configs/*.sample; do \
|
||||
if [ -f $(INSTALL_PREFIX)/etc/asterisk/`basename $$x .sample` ]; then \
|
||||
|
@ -139,6 +155,9 @@ samples: all datafiles
|
|||
for x in sounds/demo-*; do \
|
||||
install $$x $(INSTALL_PREFIX)/var/lib/asterisk/sounds; \
|
||||
done
|
||||
for x in sounds/*.mp3; do \
|
||||
install $$x $(INSTALL_PREFIX)/var/lib/asterisk/mohmp3 ; \
|
||||
done
|
||||
mkdir -p $(INSTALL_PREFIX)/var/spool/asterisk/vm/1234/INBOX
|
||||
:> $(INSTALL_PREFIX)/var/lib/asterisk/sounds/vm/1234/unavail.gsm
|
||||
for x in vm-theperson digits/1 digits/2 digits/3 digits/4 vm-isunavail; do \
|
||||
|
@ -149,6 +168,24 @@ samples: all datafiles
|
|||
cat $(INSTALL_PREFIX)/var/lib/asterisk/sounds/$$x.gsm >> $(INSTALL_PREFIX)/var/lib/asterisk/sounds/vm/1234/busy.gsm ; \
|
||||
done
|
||||
|
||||
webvmail:
|
||||
@[ -d $(HTTPDIR) ] || ( echo "No HTTP directory" && exit 1 )
|
||||
@[ -d $(HTTPDIR)/html ] || ( echo "No http directory" && exit 1 )
|
||||
@[ -d $(HTTPDIR)/cgi-bin ] || ( echo "No cgi-bin directory" && exit 1 )
|
||||
install -m 4755 -o root -g root vmail.cgi $(HTTPDIR)/cgi-bin/vmail.cgi
|
||||
mkdir -p $(HTTPDIR)/html/_asterisk
|
||||
for x in images/*.gif; do \
|
||||
install -m 644 $$x $(HTTPDIR)/html/_asterisk/; \
|
||||
done
|
||||
@echo " +--------- Asterisk Web Voicemail ----------+"
|
||||
@echo " + +"
|
||||
@echo " + Asterisk Web Voicemail is installed in +"
|
||||
@echo " + your cgi-bin directory. IT USES A SETUID +"
|
||||
@echo " + ROOT PERL SCRIPT, SO IF YOU DON'T LIKE +"
|
||||
@echo " + THAT, UNINSTALL IT! +"
|
||||
@echo " + +"
|
||||
@echo " +-------------------------------------------+"
|
||||
|
||||
mailbox:
|
||||
./addmailbox
|
||||
|
||||
|
@ -171,3 +208,13 @@ __rpm: _version
|
|||
|
||||
progdocs:
|
||||
doxygen asterisk-ng-doxygen
|
||||
|
||||
config:
|
||||
if [ -d /etc/rc.d/init.d ]; then \
|
||||
install -m 755 init.asterisk /etc/rc.d/init.d/asterisk; \
|
||||
/sbin/chkconfig --add asterisk; \
|
||||
elif [ -d /etc/init.d ]; then \
|
||||
install -m 755 init.asterisk /etc/init.d/asterisk; \
|
||||
fi
|
||||
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -11,6 +11,7 @@
|
|||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
|
@ -53,10 +54,10 @@ static int skel_exec(struct ast_channel *chan, void *data)
|
|||
/* Do our thing here */
|
||||
res = system((char *)data);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to execute '%s'\n", data);
|
||||
ast_log(LOG_WARNING, "Unable to execute '%s'\n", (char *)data);
|
||||
res = -1;
|
||||
} else if (res == 127) {
|
||||
ast_log(LOG_WARNING, "Unable to execute '%s'\n", data);
|
||||
ast_log(LOG_WARNING, "Unable to execute '%s'\n", (char *)data);
|
||||
res = -1;
|
||||
} else {
|
||||
if (res && ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
|
|
449
channel.c
449
channel.c
|
@ -18,7 +18,9 @@
|
|||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h> /* For PI */
|
||||
#include <asterisk/frame.h>
|
||||
#include <asterisk/sched.h>
|
||||
#include <asterisk/options.h>
|
||||
|
@ -28,6 +30,7 @@
|
|||
#include <asterisk/file.h>
|
||||
#include <asterisk/translate.h>
|
||||
|
||||
static int shutting_down = 0;
|
||||
|
||||
/* XXX Lock appropriately in more functions XXX */
|
||||
|
||||
|
@ -62,7 +65,7 @@ struct ast_channel *channels = NULL;
|
|||
/* Protect the channel list (highly unlikely that two things would change
|
||||
it at the same time, but still! */
|
||||
|
||||
static pthread_mutex_t chlock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t chlock = AST_MUTEX_INITIALIZER;
|
||||
|
||||
int ast_check_hangup(struct ast_channel *chan)
|
||||
{
|
||||
|
@ -79,6 +82,45 @@ time_t myt;
|
|||
return 1;
|
||||
}
|
||||
|
||||
void ast_begin_shutdown(int hangup)
|
||||
{
|
||||
struct ast_channel *c;
|
||||
shutting_down = 1;
|
||||
if (hangup) {
|
||||
PTHREAD_MUTEX_LOCK(&chlock);
|
||||
c = channels;
|
||||
while(c) {
|
||||
c->softhangup = 1;
|
||||
c = c->next;
|
||||
}
|
||||
PTHREAD_MUTEX_UNLOCK(&chlock);
|
||||
}
|
||||
}
|
||||
|
||||
int ast_active_channels(void)
|
||||
{
|
||||
struct ast_channel *c;
|
||||
int cnt = 0;
|
||||
PTHREAD_MUTEX_LOCK(&chlock);
|
||||
c = channels;
|
||||
while(c) {
|
||||
cnt++;
|
||||
c = c->next;
|
||||
}
|
||||
PTHREAD_MUTEX_UNLOCK(&chlock);
|
||||
return cnt;
|
||||
}
|
||||
|
||||
void ast_cancel_shutdown(void)
|
||||
{
|
||||
shutting_down = 0;
|
||||
}
|
||||
|
||||
int ast_shutting_down(void)
|
||||
{
|
||||
return shutting_down;
|
||||
}
|
||||
|
||||
void ast_channel_setwhentohangup(struct ast_channel *chan, time_t offset)
|
||||
{
|
||||
time_t myt;
|
||||
|
@ -189,11 +231,15 @@ int ast_best_codec(int fmts)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct ast_channel *ast_channel_alloc(void)
|
||||
struct ast_channel *ast_channel_alloc(int needqueue)
|
||||
{
|
||||
struct ast_channel *tmp;
|
||||
struct ast_channel_pvt *pvt;
|
||||
int x;
|
||||
int flags;
|
||||
/* If shutting down, don't allocate any new channels */
|
||||
if (shutting_down)
|
||||
return NULL;
|
||||
PTHREAD_MUTEX_LOCK(&chlock);
|
||||
tmp = malloc(sizeof(struct ast_channel));
|
||||
memset(tmp, 0, sizeof(struct ast_channel));
|
||||
|
@ -203,24 +249,43 @@ struct ast_channel *ast_channel_alloc(void)
|
|||
memset(pvt, 0, sizeof(struct ast_channel_pvt));
|
||||
tmp->sched = sched_context_create();
|
||||
if (tmp->sched) {
|
||||
for (x=0;x<AST_MAX_FDS;x++)
|
||||
for (x=0;x<AST_MAX_FDS - 1;x++)
|
||||
tmp->fds[x] = -1;
|
||||
strncpy(tmp->name, "**Unknown**", sizeof(tmp->name)-1);
|
||||
tmp->pvt = pvt;
|
||||
tmp->state = AST_STATE_DOWN;
|
||||
tmp->stack = -1;
|
||||
tmp->streamid = -1;
|
||||
tmp->appl = NULL;
|
||||
tmp->data = NULL;
|
||||
pthread_mutex_init(&tmp->lock, NULL);
|
||||
strncpy(tmp->context, "default", sizeof(tmp->context)-1);
|
||||
strncpy(tmp->language, defaultlanguage, sizeof(tmp->language)-1);
|
||||
strncpy(tmp->exten, "s", sizeof(tmp->exten)-1);
|
||||
tmp->priority=1;
|
||||
tmp->amaflags = ast_default_amaflags;
|
||||
strncpy(tmp->accountcode, ast_default_accountcode, sizeof(tmp->accountcode)-1);
|
||||
tmp->next = channels;
|
||||
channels= tmp;
|
||||
if (needqueue &&
|
||||
pipe(pvt->alertpipe)) {
|
||||
ast_log(LOG_WARNING, "Alert pipe creation failed!\n");
|
||||
free(pvt);
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
pvt = NULL;
|
||||
} else {
|
||||
/* Make sure we've got it done right if they don't */
|
||||
if (needqueue) {
|
||||
flags = fcntl(pvt->alertpipe[0], F_GETFL);
|
||||
fcntl(pvt->alertpipe[0], F_SETFL, flags | O_NONBLOCK);
|
||||
flags = fcntl(pvt->alertpipe[1], F_GETFL);
|
||||
fcntl(pvt->alertpipe[1], F_SETFL, flags | O_NONBLOCK);
|
||||
} else
|
||||
pvt->alertpipe[0] = pvt->alertpipe[1] = -1;
|
||||
/* Always watch the alertpipe */
|
||||
tmp->fds[AST_MAX_FDS-1] = pvt->alertpipe[0];
|
||||
strncpy(tmp->name, "**Unknown**", sizeof(tmp->name)-1);
|
||||
tmp->pvt = pvt;
|
||||
tmp->state = AST_STATE_DOWN;
|
||||
tmp->stack = -1;
|
||||
tmp->streamid = -1;
|
||||
tmp->appl = NULL;
|
||||
tmp->data = NULL;
|
||||
ast_pthread_mutex_init(&tmp->lock);
|
||||
strncpy(tmp->context, "default", sizeof(tmp->context)-1);
|
||||
strncpy(tmp->language, defaultlanguage, sizeof(tmp->language)-1);
|
||||
strncpy(tmp->exten, "s", sizeof(tmp->exten)-1);
|
||||
tmp->priority=1;
|
||||
tmp->amaflags = ast_default_amaflags;
|
||||
strncpy(tmp->accountcode, ast_default_accountcode, sizeof(tmp->accountcode)-1);
|
||||
tmp->next = channels;
|
||||
channels= tmp;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Unable to create schedule context\n");
|
||||
free(tmp);
|
||||
|
@ -237,6 +302,56 @@ struct ast_channel *ast_channel_alloc(void)
|
|||
return tmp;
|
||||
}
|
||||
|
||||
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, int lock)
|
||||
{
|
||||
struct ast_frame *f;
|
||||
struct ast_frame *prev, *cur;
|
||||
int blah = 1;
|
||||
int qlen = 0;
|
||||
f = ast_frdup(fin);
|
||||
if (!f) {
|
||||
ast_log(LOG_WARNING, "Unable to duplicate frame\n");
|
||||
return -1;
|
||||
}
|
||||
if (lock)
|
||||
ast_pthread_mutex_lock(&chan->lock);
|
||||
prev = NULL;
|
||||
cur = chan->pvt->readq;
|
||||
while(cur) {
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
qlen++;
|
||||
}
|
||||
if (prev)
|
||||
prev->next = f;
|
||||
else
|
||||
chan->pvt->readq = f;
|
||||
if (chan->pvt->alertpipe[1] > -1) {
|
||||
if (write(chan->pvt->alertpipe[1], &blah, sizeof(blah)) != sizeof(blah))
|
||||
ast_log(LOG_WARNING, "Unable to write to alert pipe, frametype/subclass %d/%d (qlen = %d): %s!\n",
|
||||
f->frametype, f->subclass, qlen, strerror(errno));
|
||||
}
|
||||
if (qlen > 128) {
|
||||
ast_log(LOG_WARNING, "Exceptionally long queue length queuing to %s\n", chan->name);
|
||||
}
|
||||
if (lock)
|
||||
ast_pthread_mutex_unlock(&chan->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ast_queue_hangup(struct ast_channel *chan, int lock)
|
||||
{
|
||||
struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP };
|
||||
return ast_queue_frame(chan, &f, lock);
|
||||
}
|
||||
|
||||
int ast_queue_control(struct ast_channel *chan, int control, int lock)
|
||||
{
|
||||
struct ast_frame f = { AST_FRAME_CONTROL, };
|
||||
f.subclass = control;
|
||||
return ast_queue_frame(chan, &f, lock);
|
||||
}
|
||||
|
||||
int ast_channel_defer_dtmf(struct ast_channel *chan)
|
||||
{
|
||||
int pre = 0;
|
||||
|
@ -272,9 +387,28 @@ struct ast_channel *ast_channel_walk(struct ast_channel *prev)
|
|||
|
||||
}
|
||||
|
||||
int ast_safe_sleep(struct ast_channel *chan, int ms)
|
||||
{
|
||||
struct ast_frame *f;
|
||||
while(ms > 0) {
|
||||
ms = ast_waitfor(chan, ms);
|
||||
if (ms <0)
|
||||
return -1;
|
||||
if (ms > 0) {
|
||||
f = ast_read(chan);
|
||||
if (!f)
|
||||
return -1;
|
||||
ast_frfree(f);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ast_channel_free(struct ast_channel *chan)
|
||||
{
|
||||
struct ast_channel *last=NULL, *cur;
|
||||
int fd;
|
||||
struct ast_frame *f, *fp;
|
||||
PTHREAD_MUTEX_LOCK(&chlock);
|
||||
cur = channels;
|
||||
while(cur) {
|
||||
|
@ -306,6 +440,17 @@ void ast_channel_free(struct ast_channel *chan)
|
|||
if (chan->ani)
|
||||
free(chan->ani);
|
||||
pthread_mutex_destroy(&chan->lock);
|
||||
/* Close pipes if appropriate */
|
||||
if ((fd = chan->pvt->alertpipe[0]) > -1)
|
||||
close(fd);
|
||||
if ((fd = chan->pvt->alertpipe[1]) > -1)
|
||||
close(fd);
|
||||
f = chan->pvt->readq;
|
||||
while(f) {
|
||||
fp = f;
|
||||
f = f->next;
|
||||
ast_frfree(fp);
|
||||
}
|
||||
free(chan->pvt);
|
||||
free(chan);
|
||||
PTHREAD_MUTEX_UNLOCK(&chlock);
|
||||
|
@ -359,6 +504,11 @@ int ast_hangup(struct ast_channel *chan)
|
|||
ast_stopstream(chan);
|
||||
if (chan->sched)
|
||||
sched_context_destroy(chan->sched);
|
||||
/* Clear any tone stuff remaining */
|
||||
if (chan->generatordata)
|
||||
chan->generator->release(chan, chan->generatordata);
|
||||
chan->generatordata = NULL;
|
||||
chan->generator = NULL;
|
||||
if (chan->cdr) {
|
||||
/* End the CDR if it hasn't already */
|
||||
ast_cdr_end(chan->cdr);
|
||||
|
@ -434,6 +584,29 @@ int ast_answer(struct ast_channel *chan)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ast_deactivate_generator(struct ast_channel *chan)
|
||||
{
|
||||
if (chan->generatordata) {
|
||||
chan->generator->release(chan, chan->generatordata);
|
||||
chan->generatordata = NULL;
|
||||
chan->writeinterrupt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen, void *params)
|
||||
{
|
||||
if (chan->generatordata) {
|
||||
chan->generator->release(chan, chan->generatordata);
|
||||
chan->generatordata = NULL;
|
||||
}
|
||||
if ((chan->generatordata = gen->alloc(chan, params))) {
|
||||
chan->generator = gen;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
|
||||
{
|
||||
/* Wait for x amount of time on a file descriptor to have input. */
|
||||
|
@ -511,9 +684,10 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
|
|||
tv.tv_usec = (*ms % 1000) * 1000;
|
||||
FD_ZERO(&rfds);
|
||||
FD_ZERO(&efds);
|
||||
|
||||
for (x=0;x<n;x++) {
|
||||
for (y=0;y<AST_MAX_FDS;y++) {
|
||||
if (c[x]->fds[y] > 0) {
|
||||
if (c[x]->fds[y] > -1) {
|
||||
FD_SET(c[x]->fds[y], &rfds);
|
||||
FD_SET(c[x]->fds[y], &efds);
|
||||
if (c[x]->fds[y] > max)
|
||||
|
@ -623,12 +797,13 @@ char ast_waitfordigit(struct ast_channel *c, int ms)
|
|||
struct ast_frame *ast_read(struct ast_channel *chan)
|
||||
{
|
||||
struct ast_frame *f = NULL;
|
||||
int blah;
|
||||
static struct ast_frame null_frame =
|
||||
{
|
||||
AST_FRAME_NULL,
|
||||
};
|
||||
|
||||
pthread_mutex_lock(&chan->lock);
|
||||
ast_pthread_mutex_lock(&chan->lock);
|
||||
if (chan->masq) {
|
||||
if (ast_do_masquerade(chan)) {
|
||||
ast_log(LOG_WARNING, "Failed to perform masquerade\n");
|
||||
|
@ -644,7 +819,7 @@ struct ast_frame *ast_read(struct ast_channel *chan)
|
|||
pthread_mutex_unlock(&chan->lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if (!chan->deferdtmf && strlen(chan->dtmfq)) {
|
||||
/* We have DTMF that has been deferred. Return it now */
|
||||
chan->dtmff.frametype = AST_FRAME_DTMF;
|
||||
|
@ -655,19 +830,35 @@ struct ast_frame *ast_read(struct ast_channel *chan)
|
|||
return &chan->dtmff;
|
||||
}
|
||||
|
||||
chan->blocker = pthread_self();
|
||||
if (chan->exception) {
|
||||
if (chan->pvt->exception)
|
||||
f = chan->pvt->exception(chan);
|
||||
/* Read and ignore anything on the alertpipe, but read only
|
||||
one sizeof(blah) per frame that we send from it */
|
||||
if (chan->pvt->alertpipe[0] > -1) {
|
||||
read(chan->pvt->alertpipe[0], &blah, sizeof(blah));
|
||||
}
|
||||
|
||||
/* Check for pending read queue */
|
||||
if (chan->pvt->readq) {
|
||||
f = chan->pvt->readq;
|
||||
chan->pvt->readq = f->next;
|
||||
/* Interpret hangup and return NULL */
|
||||
if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))
|
||||
f = NULL;
|
||||
} else {
|
||||
chan->blocker = pthread_self();
|
||||
if (chan->exception) {
|
||||
if (chan->pvt->exception)
|
||||
f = chan->pvt->exception(chan);
|
||||
else
|
||||
ast_log(LOG_WARNING, "Exception flag set, but no exception handler\n");
|
||||
/* Clear the exception flag */
|
||||
chan->exception = 0;
|
||||
} else
|
||||
if (chan->pvt->read)
|
||||
f = chan->pvt->read(chan);
|
||||
else
|
||||
ast_log(LOG_WARNING, "Exception flag set, but no exception handler\n");
|
||||
/* Clear the exception flag */
|
||||
chan->exception = 0;
|
||||
} else
|
||||
if (chan->pvt->read)
|
||||
f = chan->pvt->read(chan);
|
||||
else
|
||||
ast_log(LOG_WARNING, "No read routine on channel %s\n", chan);
|
||||
ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name);
|
||||
}
|
||||
|
||||
if (f && (f->frametype == AST_FRAME_VOICE)) {
|
||||
if (chan->pvt->readtrans) {
|
||||
f = ast_translate(chan->pvt->readtrans, f, 1);
|
||||
|
@ -675,6 +866,7 @@ struct ast_frame *ast_read(struct ast_channel *chan)
|
|||
f = &null_frame;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure we always return NULL in the future */
|
||||
if (!f) {
|
||||
chan->softhangup = 1;
|
||||
|
@ -689,10 +881,26 @@ struct ast_frame *ast_read(struct ast_channel *chan)
|
|||
f = &null_frame;
|
||||
} else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_ANSWER)) {
|
||||
/* Answer the CDR */
|
||||
chan->state = AST_STATE_UP;
|
||||
ast_cdr_answer(chan->cdr);
|
||||
}
|
||||
pthread_mutex_unlock(&chan->lock);
|
||||
|
||||
/* Run any generator sitting on the line */
|
||||
if (f && (f->frametype == AST_FRAME_VOICE) && chan->generatordata) {
|
||||
/* Mask generator data temporarily */
|
||||
void *tmp;
|
||||
int res;
|
||||
tmp = chan->generatordata;
|
||||
chan->generatordata = NULL;
|
||||
res = chan->generator->generate(chan, tmp, f->datalen);
|
||||
chan->generatordata = tmp;
|
||||
if (res) {
|
||||
ast_log(LOG_DEBUG, "Auto-deactivating generator\n");
|
||||
ast_deactivate_generator(chan);
|
||||
}
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
|
@ -769,6 +977,12 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
|
|||
}
|
||||
if (chan->masqr)
|
||||
return 0;
|
||||
if (chan->generatordata) {
|
||||
if (chan->writeinterrupt)
|
||||
ast_deactivate_generator(chan);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
CHECK_BLOCKING(chan);
|
||||
switch(fr->frametype) {
|
||||
case AST_FRAME_CONTROL:
|
||||
|
@ -796,6 +1010,9 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
|
|||
}
|
||||
}
|
||||
chan->blocking = 0;
|
||||
/* Consider a write failure to force a soft hangup */
|
||||
if (res < 0)
|
||||
chan->softhangup = 1;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -899,7 +1116,7 @@ int ast_call(struct ast_channel *chan, char *addr, int timeout)
|
|||
return anyway. */
|
||||
int res = -1;
|
||||
/* Stop if we're a zombie or need a soft hangup */
|
||||
pthread_mutex_lock(&chan->lock);
|
||||
ast_pthread_mutex_lock(&chan->lock);
|
||||
if (!chan->zombie && !ast_check_hangup(chan))
|
||||
if (chan->pvt->call)
|
||||
res = chan->pvt->call(chan, addr, timeout);
|
||||
|
@ -975,19 +1192,19 @@ int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *pe
|
|||
chanf = chan->nativeformats;
|
||||
res = ast_translator_best_choice(&peerf, &chanf);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", chan, chan->nativeformats, peer, peer->nativeformats);
|
||||
ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", chan->name, chan->nativeformats, peer->name, peer->nativeformats);
|
||||
return -1;
|
||||
}
|
||||
/* Set read format on channel */
|
||||
res = ast_set_read_format(chan, peerf);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", chan, chanf);
|
||||
ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", chan->name, chanf);
|
||||
return -1;
|
||||
}
|
||||
/* Set write format on peer channel */
|
||||
res = ast_set_write_format(peer, peerf);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", peer, peerf);
|
||||
ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", peer->name, peerf);
|
||||
return -1;
|
||||
}
|
||||
/* Now we go the other way */
|
||||
|
@ -995,19 +1212,19 @@ int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *pe
|
|||
chanf = chan->nativeformats;
|
||||
res = ast_translator_best_choice(&chanf, &peerf);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", peer, peer->nativeformats, chan, chan->nativeformats);
|
||||
ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", peer->name, peer->nativeformats, chan->name, chan->nativeformats);
|
||||
return -1;
|
||||
}
|
||||
/* Set writeformat on channel */
|
||||
res = ast_set_write_format(chan, chanf);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", chan, chanf);
|
||||
ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", chan->name, chanf);
|
||||
return -1;
|
||||
}
|
||||
/* Set read format on peer channel */
|
||||
res = ast_set_read_format(peer, chanf);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", peer, peerf);
|
||||
ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", peer->name, peerf);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -1057,7 +1274,7 @@ static int ast_do_masquerade(struct ast_channel *original)
|
|||
free_translation(original);
|
||||
|
||||
/* We need the clone's lock, too */
|
||||
pthread_mutex_lock(&clone->lock);
|
||||
ast_pthread_mutex_lock(&clone->lock);
|
||||
|
||||
/* Unlink the masquerade */
|
||||
original->masq = NULL;
|
||||
|
@ -1224,7 +1441,8 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
|
|||
}
|
||||
|
||||
|
||||
if ((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat)) {
|
||||
if (((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat)) &&
|
||||
!(c0->generator || c1->generator)) {
|
||||
if (ast_channel_make_compatible(c0, c1)) {
|
||||
ast_log(LOG_WARNING, "Can't make %s and %s compatible\n", c0->name, c1->name);
|
||||
return -1;
|
||||
|
@ -1282,10 +1500,14 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
|
|||
last = who;
|
||||
#endif
|
||||
tackygoto:
|
||||
if (who == c0)
|
||||
ast_write(c1, f);
|
||||
else
|
||||
ast_write(c0, f);
|
||||
/* Don't copy packets if there is a generator on either one, since they're
|
||||
not supposed to be listening anyway */
|
||||
if (!c0->generator && !c1->generator) {
|
||||
if (who == c0)
|
||||
ast_write(c1, f);
|
||||
else
|
||||
ast_write(c0, f);
|
||||
}
|
||||
}
|
||||
ast_frfree(f);
|
||||
} else
|
||||
|
@ -1320,3 +1542,136 @@ int ast_channel_setoption(struct ast_channel *chan, int option, void *data, int
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct tonepair_def {
|
||||
int freq1;
|
||||
int freq2;
|
||||
int duration;
|
||||
int vol;
|
||||
};
|
||||
|
||||
struct tonepair_state {
|
||||
float freq1;
|
||||
float freq2;
|
||||
float vol;
|
||||
int duration;
|
||||
int pos;
|
||||
int origrfmt;
|
||||
int origwfmt;
|
||||
struct ast_frame f;
|
||||
unsigned char offset[AST_FRIENDLY_OFFSET];
|
||||
short data[4000];
|
||||
};
|
||||
|
||||
static void tonepair_release(struct ast_channel *chan, void *params)
|
||||
{
|
||||
struct tonepair_state *ts = params;
|
||||
if (chan) {
|
||||
ast_set_write_format(chan, ts->origwfmt);
|
||||
ast_set_read_format(chan, ts->origrfmt);
|
||||
}
|
||||
free(ts);
|
||||
}
|
||||
|
||||
static void * tonepair_alloc(struct ast_channel *chan, void *params)
|
||||
{
|
||||
struct tonepair_state *ts;
|
||||
struct tonepair_def *td = params;
|
||||
ts = malloc(sizeof(struct tonepair_state));
|
||||
if (!ts)
|
||||
return NULL;
|
||||
memset(ts, 0, sizeof(struct tonepair_state));
|
||||
ts->origrfmt = chan->readformat;
|
||||
ts->origwfmt = chan->writeformat;
|
||||
if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
|
||||
ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", chan->name);
|
||||
tonepair_release(NULL, ts);
|
||||
ts = NULL;
|
||||
} else if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
|
||||
ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (read)\n", chan->name);
|
||||
ast_set_write_format(chan, ts->origwfmt);
|
||||
tonepair_release(NULL, ts);
|
||||
ts = NULL;
|
||||
} else {
|
||||
ts->freq1 = td->freq1;
|
||||
ts->freq2 = td->freq2;
|
||||
ts->duration = td->duration;
|
||||
ts->vol = td->vol;
|
||||
}
|
||||
/* Let interrupts interrupt :) */
|
||||
chan->writeinterrupt = 1;
|
||||
return ts;
|
||||
}
|
||||
|
||||
static int tonepair_generator(struct ast_channel *chan, void *data, int len)
|
||||
{
|
||||
struct tonepair_state *ts = data;
|
||||
int x;
|
||||
if (len > sizeof(ts->data) / 2 - 1) {
|
||||
ast_log(LOG_WARNING, "Can't generate that much data!\n");
|
||||
return -1;
|
||||
}
|
||||
memset(&ts->f, 0, sizeof(ts->f));
|
||||
for (x=0;x<len/2;x++) {
|
||||
ts->data[x] = ts->vol * (
|
||||
sin((ts->freq1 * 2.0 * M_PI / 8000.0) * (ts->pos + x)) +
|
||||
sin((ts->freq2 * 2.0 * M_PI / 8000.0) * (ts->pos + x))
|
||||
);
|
||||
}
|
||||
ts->f.frametype = AST_FRAME_VOICE;
|
||||
ts->f.subclass = AST_FORMAT_SLINEAR;
|
||||
ts->f.datalen = len;
|
||||
ts->f.timelen = len/8;
|
||||
ts->f.offset = AST_FRIENDLY_OFFSET;
|
||||
ts->f.data = ts->data;
|
||||
ast_write(chan, &ts->f);
|
||||
ts->pos += x;
|
||||
if (ts->duration > 0) {
|
||||
if (ts->pos >= ts->duration * 8)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ast_generator tonepair = {
|
||||
alloc: tonepair_alloc,
|
||||
release: tonepair_release,
|
||||
generate: tonepair_generator,
|
||||
};
|
||||
|
||||
int ast_tonepair_start(struct ast_channel *chan, int freq1, int freq2, int duration, int vol)
|
||||
{
|
||||
struct tonepair_def d = { 0, };
|
||||
d.freq1 = freq1;
|
||||
d.freq2 = freq2;
|
||||
d.duration = duration;
|
||||
if (vol < 1)
|
||||
d.vol = 8192;
|
||||
else
|
||||
d.vol = vol;
|
||||
if (ast_activate_generator(chan, &tonepair, &d))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ast_tonepair_stop(struct ast_channel *chan)
|
||||
{
|
||||
ast_deactivate_generator(chan);
|
||||
}
|
||||
|
||||
int ast_tonepair(struct ast_channel *chan, int freq1, int freq2, int duration, int vol)
|
||||
{
|
||||
struct ast_frame *f;
|
||||
int res;
|
||||
if ((res = ast_tonepair_start(chan, freq1, freq2, duration, vol)))
|
||||
return res;
|
||||
|
||||
/* Give us some wiggle room */
|
||||
while(chan->generatordata && (ast_waitfor(chan, 100) >= 0)) {
|
||||
f = ast_read(chan);
|
||||
if (f)
|
||||
ast_frfree(f);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ struct vofr_hdr {
|
|||
u_int8_t cid; /* Channel ID */
|
||||
u_int8_t mod:4; /* Modulation */
|
||||
u_int8_t remid:4; /* Remote ID */
|
||||
#elif __BYTE__ORDER == __BIG_ENDIAN
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
u_int8_t ctag:4; /* Connect tag */
|
||||
u_int8_t dtype:4; /* Data type */
|
||||
u_int8_t vflags:4; /* Voice Routing Flags */
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/channel_pvt.h>
|
||||
#include <asterisk/config.h>
|
||||
|
@ -55,14 +56,14 @@ static int silencesupression = 0;
|
|||
|
||||
static int prefformat = AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW;
|
||||
|
||||
static pthread_mutex_t usecnt_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t usecnt_lock = AST_MUTEX_INITIALIZER;
|
||||
|
||||
/* Protect the interface list (of phone_pvt's) */
|
||||
static pthread_mutex_t iflock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t iflock = AST_MUTEX_INITIALIZER;
|
||||
|
||||
/* Protect the monitoring thread, so only one process can kill or start it, and not
|
||||
when it's doing something critical. */
|
||||
static pthread_mutex_t monlock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t monlock = AST_MUTEX_INITIALIZER;
|
||||
|
||||
/* This is the thread for the monitor which checks for input on the channels
|
||||
which are not currently in use. */
|
||||
|
@ -140,7 +141,31 @@ static int phone_digit(struct ast_channel *ast, char digit)
|
|||
static int phone_call(struct ast_channel *ast, char *dest, int timeout)
|
||||
{
|
||||
struct phone_pvt *p;
|
||||
struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_RINGING };
|
||||
|
||||
// CID stuff for the phonejack...
|
||||
|
||||
PHONE_CID cid;
|
||||
time_t UtcTime;
|
||||
struct tm *t;
|
||||
|
||||
|
||||
if (ast->callerid) {
|
||||
time(&UtcTime);
|
||||
t = localtime(&UtcTime);
|
||||
|
||||
if(t != NULL) {
|
||||
sprintf(cid.month, "%02d",(t->tm_mon + 1));
|
||||
sprintf(cid.day, "%02d", t->tm_mday);
|
||||
sprintf(cid.hour, "%02d", t->tm_hour);
|
||||
sprintf(cid.min, "%02d", t->tm_min);
|
||||
}
|
||||
strcpy(cid.name, "Unknown");
|
||||
sprintf(cid.number,"%s",ast->callerid);
|
||||
}
|
||||
|
||||
p = ast->pvt->pvt;
|
||||
|
||||
if ((ast->state != AST_STATE_DOWN) && (ast->state != AST_STATE_RESERVED)) {
|
||||
ast_log(LOG_WARNING, "phone_call called on %s, neither down nor reserved\n", ast->name);
|
||||
return -1;
|
||||
|
@ -149,7 +174,9 @@ static int phone_call(struct ast_channel *ast, char *dest, int timeout)
|
|||
ring the phone and wait for someone to answer */
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Ringing %s on %s (%d)\n", dest, ast->name, ast->fds[0]);
|
||||
ioctl(p->fd, PHONE_RING_START);
|
||||
|
||||
ioctl(p->fd, PHONE_RING_START,&cid);
|
||||
ast_queue_frame(ast, &f, 0);
|
||||
ast->state = AST_STATE_RINGING;
|
||||
return 0;
|
||||
}
|
||||
|
@ -336,7 +363,7 @@ static struct ast_frame *phone_exception(struct ast_channel *ast)
|
|||
if (phonee.bits.pstn_ring)
|
||||
ast_verbose("Unit is ringing\n");
|
||||
if (phonee.bits.caller_id) {
|
||||
ast_verbose("We have caller ID: %s\n");
|
||||
ast_verbose("We have caller ID\n");
|
||||
}
|
||||
if (phonee.bits.pstn_wink)
|
||||
ast_verbose("Detected Wink\n");
|
||||
|
@ -351,6 +378,7 @@ static struct ast_frame *phone_read(struct ast_channel *ast)
|
|||
{
|
||||
int res;
|
||||
struct phone_pvt *p = ast->pvt->pvt;
|
||||
|
||||
|
||||
/* Some nice norms */
|
||||
p->fr.datalen = 0;
|
||||
|
@ -448,14 +476,13 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
|
|||
char tmpbuf[4];
|
||||
/* Write a frame of (presumably voice) data */
|
||||
if (frame->frametype != AST_FRAME_VOICE) {
|
||||
ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
|
||||
ast_frfree(frame);
|
||||
return -1;
|
||||
if (frame->frametype != AST_FRAME_IMAGE)
|
||||
ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
|
||||
return 0;
|
||||
}
|
||||
if (!(frame->subclass &
|
||||
(AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW))) {
|
||||
ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
|
||||
ast_frfree(frame);
|
||||
return -1;
|
||||
}
|
||||
/* If we're not in up mode, go into up mode now */
|
||||
|
@ -560,17 +587,20 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
|
|||
res = phone_write_buf(p, pos, expected, maxfr);
|
||||
}
|
||||
if (res != expected) {
|
||||
if (res < 0)
|
||||
ast_log(LOG_WARNING, "Write returned error (%s)\n", strerror(errno));
|
||||
/*
|
||||
* Card is in non-blocking mode now and it works well now, but there are
|
||||
* lot of messages like this. So, this message is temporarily disabled.
|
||||
*/
|
||||
if (errno != EAGAIN) {
|
||||
if (res < 0)
|
||||
ast_log(LOG_WARNING, "Write returned error (%s)\n", strerror(errno));
|
||||
/*
|
||||
* Card is in non-blocking mode now and it works well now, but there are
|
||||
* lot of messages like this. So, this message is temporarily disabled.
|
||||
*/
|
||||
#if 0
|
||||
else
|
||||
ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frame->datalen);
|
||||
else
|
||||
ast_log(LOG_WARNING, "Only wrote %d of %d bytes\n", res, frame->datalen);
|
||||
#endif
|
||||
return -1;
|
||||
return -1;
|
||||
} else /* Pretend it worked */
|
||||
res = expected;
|
||||
}
|
||||
sofar += res;
|
||||
pos += res;
|
||||
|
@ -581,7 +611,7 @@ static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
|
|||
static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *context)
|
||||
{
|
||||
struct ast_channel *tmp;
|
||||
tmp = ast_channel_alloc();
|
||||
tmp = ast_channel_alloc(1);
|
||||
if (tmp) {
|
||||
snprintf(tmp->name, sizeof(tmp->name), "Phone/%s", i->dev + 5);
|
||||
tmp->type = type;
|
||||
|
|
|
@ -25,6 +25,8 @@ CFLAGS+=
|
|||
LIBG723=g723.1/libg723.a
|
||||
LIBG723B=g723.1b/libg723b.a
|
||||
LIBGSM=gsm/lib/libgsm.a
|
||||
LIBGSM=$(shell if uname -m | grep -q 86; then echo gsm/lib/libgsm.a; else echo "-lgsm" ; fi)
|
||||
LIBGSMT=$(shell if uname -m | grep -q 86; then echo gsm/lib/libgsm.a; fi)
|
||||
LIBMP3=mp3/libmp3.a
|
||||
LIBLPC10=lpc10/liblpc10.a
|
||||
|
||||
|
@ -44,7 +46,7 @@ clean:
|
|||
$(LIBG723):
|
||||
make -C g723.1 all
|
||||
|
||||
$(LIBGSM):
|
||||
gsm/lib/libgsm.a:
|
||||
make -C gsm lib/libgsm.a
|
||||
|
||||
$(LIBG723B):
|
||||
|
@ -65,7 +67,7 @@ codec_g723_1b.o : codec_g723_1.c
|
|||
codec_g723_1b.so : codec_g723_1b.o $(LIBG723B)
|
||||
$(CC) -shared -Xlinker -x -o $@ $< $(LIBG723B) -lm
|
||||
|
||||
codec_gsm.so: codec_gsm.o $(LIBGSM)
|
||||
codec_gsm.so: codec_gsm.o $(LIBGSMT)
|
||||
$(CC) -shared -Xlinker -x -o $@ $< $(LIBGSM)
|
||||
|
||||
codec_lpc10.so: codec_lpc10.o $(LIBLPC10)
|
||||
|
|
|
@ -22,7 +22,8 @@ LIB_TARGET_DIR = .
|
|||
#
|
||||
|
||||
WARNINGS = -Wall -Wno-comment -Wno-error
|
||||
CFLAGS = -O6 -mpentium -I$(LIB_TARGET_DIR) $(WARNINGS)
|
||||
CFLAGS = -O6 -I$(LIB_TARGET_DIR) $(WARNINGS)
|
||||
CFLAGS+= $(shell if uname -m | grep -q 86; then echo "-mpentium" ; fi)
|
||||
|
||||
LIB = $(LIB_TARGET_DIR)/liblpc10.a
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ static int jpeg_write_image(int fd, struct ast_frame *fr)
|
|||
if (fr->datalen) {
|
||||
res = write(fd, fr->data, fr->datalen);
|
||||
if (res != fr->datalen) {
|
||||
ast_log(LOG_WARNING, "Only wrote %d of %d bytes: %s\n", res, fr->datalen);
|
||||
ast_log(LOG_WARNING, "Only wrote %d of %d bytes: %s\n", res, fr->datalen, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
|
@ -51,7 +52,7 @@ struct ast_filestream {
|
|||
|
||||
|
||||
static struct ast_filestream *glist = NULL;
|
||||
static pthread_mutex_t wav_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t wav_lock = AST_MUTEX_INITIALIZER;
|
||||
static int glistcnt = 0;
|
||||
|
||||
static char *name = "wav";
|
||||
|
@ -167,7 +168,7 @@ static int check_header(int fd)
|
|||
return -1;
|
||||
}
|
||||
if (read(fd, &bisam, 2) != 2) {
|
||||
ast_log(LOG_WARNING, "Read failed (Bits Per Sample): &d\n", ltohs(bisam));
|
||||
ast_log(LOG_WARNING, "Read failed (Bits Per Sample): %d\n", ltohs(bisam));
|
||||
return -1;
|
||||
}
|
||||
/* Begin data chunk */
|
||||
|
|
|
@ -37,7 +37,8 @@ extern "C" {
|
|||
* ast_log(LOG_WHATEVER, "Problem with the %s Captain. We should get some more. Will %d be enough?", "flux capacitor", 10);
|
||||
* where WHATEVER is one of ERROR, DEBUG, EVENT, NOTICE, or WARNING depending on which log you wish to output to.
|
||||
*/
|
||||
extern void ast_log(int level, char *file, int line, char *function, char *fmt, ...);
|
||||
extern void ast_log(int level, char *file, int line, char *function, char *fmt, ...)
|
||||
__attribute__ ((format (printf, 5, 6)));
|
||||
|
||||
//! Send a verbose message (based on verbose level)
|
||||
/*!
|
||||
|
@ -47,7 +48,8 @@ extern void ast_log(int level, char *file, int line, char *function, char *fmt,
|
|||
* Note the abscence of a comma after the VERBOSE_PREFIX_3. This is important.
|
||||
* VERBOSE_PREFIX_1 through VERBOSE_PREFIX_3 are defined.
|
||||
*/
|
||||
extern void ast_verbose(char *fmt, ...);
|
||||
extern void ast_verbose(char *fmt, ...)
|
||||
__attribute__ ((format (printf, 1, 2)));
|
||||
|
||||
extern int ast_register_verbose(void (*verboser)(char *string, int opos, int replacelast, int complete));
|
||||
extern int ast_unregister_verbose(void (*verboser)(char *string, int opos, int replacelast, int complete));
|
||||
|
|
39
logger.c
39
logger.c
|
@ -15,10 +15,12 @@
|
|||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/config.h>
|
||||
#include <asterisk/term.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
@ -30,8 +32,8 @@
|
|||
|
||||
#define MAX_MSG_QUEUE 200
|
||||
|
||||
static pthread_mutex_t msglist_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t loglock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t msglist_lock = AST_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t loglock = AST_MUTEX_INITIALIZER;
|
||||
|
||||
static struct msglist {
|
||||
char *msg;
|
||||
|
@ -59,6 +61,14 @@ static char *levels[] = {
|
|||
"ERROR"
|
||||
};
|
||||
|
||||
static int colors[] = {
|
||||
COLOR_BRGREEN,
|
||||
COLOR_BRBLUE,
|
||||
COLOR_YELLOW,
|
||||
COLOR_BRRED,
|
||||
COLOR_RED
|
||||
};
|
||||
|
||||
static int make_components(char *s, int lineno)
|
||||
{
|
||||
char *w;
|
||||
|
@ -207,14 +217,21 @@ int reload_logger(void)
|
|||
extern void ast_log(int level, char *file, int line, char *function, char *fmt, ...)
|
||||
{
|
||||
char date[256];
|
||||
char tmp[80];
|
||||
char tmp2[80];
|
||||
char tmp3[80];
|
||||
char tmp4[80];
|
||||
char linestr[80];
|
||||
time_t t;
|
||||
struct tm *tm;
|
||||
struct logfile *f;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
if (!option_verbose && !option_debug && (!level))
|
||||
if (!option_verbose && !option_debug && (!level)) {
|
||||
va_end(ap);
|
||||
return;
|
||||
}
|
||||
ast_pthread_mutex_lock(&loglock);
|
||||
if (level == 1 /* Event */) {
|
||||
time(&t);
|
||||
|
@ -226,7 +243,9 @@ extern void ast_log(int level, char *file, int line, char *function, char *fmt,
|
|||
vfprintf(eventlog, fmt, ap);
|
||||
fflush(eventlog);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Unable to retrieve local time?\n");
|
||||
/** Cannot use ast_log() from locked section of ast_log()!
|
||||
ast_log(LOG_WARNING, "Unable to retrieve local time?\n"); **/
|
||||
fprintf(stderr, "ast_log: Unable to retrieve local time for %d?\n", t);
|
||||
} else {
|
||||
if (logfiles) {
|
||||
f = logfiles;
|
||||
|
@ -238,16 +257,26 @@ extern void ast_log(int level, char *file, int line, char *function, char *fmt,
|
|||
strftime(date, sizeof(date), "%b %e %T", tm);
|
||||
fprintf(f->f, "%s %s[%ld]: File %s, Line %d (%s): ", date, levels[level], pthread_self(), file, line, function);
|
||||
} else {
|
||||
fprintf(f->f, "%s[%ld]: File %s, Line %d (%s): ", levels[level], pthread_self(), file, line, function);
|
||||
sprintf(linestr, "%d", line);
|
||||
fprintf(f->f, "%s[%ld]: File %s, Line %s (%s): ",
|
||||
term_color(tmp, levels[level], colors[level], 0, sizeof(tmp)),
|
||||
pthread_self(),
|
||||
term_color(tmp2, file, COLOR_BRWHITE, 0, sizeof(tmp2)),
|
||||
term_color(tmp3, linestr, COLOR_BRWHITE, 0, sizeof(tmp3)),
|
||||
term_color(tmp4, function, COLOR_BRWHITE, 0, sizeof(tmp4)));
|
||||
}
|
||||
vfprintf(f->f, fmt, ap);
|
||||
va_start(ap, fmt);
|
||||
fflush(f->f);
|
||||
va_end(ap);
|
||||
}
|
||||
f = f->next;
|
||||
}
|
||||
} else {
|
||||
fprintf(stdout, "%s[%ld]: File %s, Line %d (%s): ", levels[level], pthread_self(), file, line, function);
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stdout, fmt, ap);
|
||||
va_end(ap);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
|
417
pbx.c
417
pbx.c
|
@ -11,7 +11,7 @@
|
|||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/cli.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/channel.h>
|
||||
|
@ -20,6 +20,7 @@
|
|||
#include <asterisk/file.h>
|
||||
#include <asterisk/callerid.h>
|
||||
#include <asterisk/cdr.h>
|
||||
#include <asterisk/term.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -71,7 +72,13 @@ struct ast_exten {
|
|||
|
||||
struct ast_include {
|
||||
char name[AST_MAX_EXTENSION];
|
||||
char rname[AST_MAX_EXTENSION];
|
||||
char *registrar;
|
||||
int hastime;
|
||||
unsigned int monthmask;
|
||||
unsigned int daymask;
|
||||
unsigned int dowmask;
|
||||
unsigned int minmask[24];
|
||||
struct ast_include *next;
|
||||
};
|
||||
|
||||
|
@ -244,14 +251,14 @@ static struct pbx_builtin {
|
|||
};
|
||||
|
||||
/* Lock for the application list */
|
||||
static pthread_mutex_t applock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t applock = AST_MUTEX_INITIALIZER;
|
||||
static struct ast_context *contexts = NULL;
|
||||
/* Lock for the ast_context list */
|
||||
static pthread_mutex_t conlock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t conlock = AST_MUTEX_INITIALIZER;
|
||||
static struct ast_app *apps = NULL;
|
||||
|
||||
/* Lock for switches */
|
||||
static pthread_mutex_t switchlock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t switchlock = AST_MUTEX_INITIALIZER;
|
||||
struct ast_switch *switches = NULL;
|
||||
|
||||
int pbx_exec(struct ast_channel *c, /* Channel */
|
||||
|
@ -342,6 +349,47 @@ static struct ast_switch *pbx_findswitch(char *sw)
|
|||
return asw;
|
||||
}
|
||||
|
||||
static inline int include_valid(struct ast_include *i)
|
||||
{
|
||||
struct tm *tm;
|
||||
time_t t;
|
||||
if (!i->hastime)
|
||||
return 1;
|
||||
time(&t);
|
||||
tm = localtime(&t);
|
||||
if (!tm) {
|
||||
ast_log(LOG_WARNING, "Failed to get local time\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If it's not the right month, return */
|
||||
if (!(i->monthmask & (1 << tm->tm_mon))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If it's not that time of the month.... */
|
||||
if (!(i->daymask & (1 << tm->tm_mday)))
|
||||
return 0;
|
||||
|
||||
/* If it's not the right day of the week */
|
||||
if (!(i->dowmask & (1 << tm->tm_wday)))
|
||||
return 0;
|
||||
|
||||
/* Sanity check the hour just to be safe */
|
||||
if ((tm->tm_hour < 0) || (tm->tm_hour > 23)) {
|
||||
ast_log(LOG_WARNING, "Insane time...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Now the tough part, we calculate if it fits
|
||||
in the right time based on min/hour */
|
||||
if (!(i->minmask[tm->tm_hour] & (1 << (tm->tm_min / 2))))
|
||||
return 0;
|
||||
|
||||
/* If we got this far, then we're good */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void pbx_destroy(struct ast_pbx *p)
|
||||
{
|
||||
free(p);
|
||||
|
@ -561,10 +609,12 @@ static struct ast_exten *pbx_find_extension(struct ast_channel *chan, char *cont
|
|||
/* Now try any includes we have in this context */
|
||||
i = tmp->includes;
|
||||
while(i) {
|
||||
if ((e = pbx_find_extension(chan, i->name, exten, priority, callerid, action, incstack, stacklen, status, swo, data)))
|
||||
return e;
|
||||
if (*swo)
|
||||
return NULL;
|
||||
if (include_valid(i)) {
|
||||
if ((e = pbx_find_extension(chan, i->rname, exten, priority, callerid, action, incstack, stacklen, status, swo, data)))
|
||||
return e;
|
||||
if (*swo)
|
||||
return NULL;
|
||||
}
|
||||
i = i->next;
|
||||
}
|
||||
}
|
||||
|
@ -584,6 +634,9 @@ static int pbx_extension_helper(struct ast_channel *c, char *context, char *exte
|
|||
int status = 0;
|
||||
char *incstack[AST_PBX_MAX_STACK];
|
||||
int stacklen = 0;
|
||||
char tmp[80];
|
||||
char tmp2[80];
|
||||
char tmp3[256];
|
||||
if (ast_pthread_mutex_lock(&conlock)) {
|
||||
ast_log(LOG_WARNING, "Unable to obtain lock\n");
|
||||
if ((action == HELPER_EXISTS) || (action == HELPER_CANMATCH))
|
||||
|
@ -614,7 +667,10 @@ static int pbx_extension_helper(struct ast_channel *c, char *context, char *exte
|
|||
ast_log(LOG_DEBUG, "Launching '%s'\n", app->name);
|
||||
else if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\") %s\n",
|
||||
app->name, c->name, (e->data ? (char *)e->data : NULL), (newstack ? "in new stack" : "in same stack"));
|
||||
term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
|
||||
term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
|
||||
term_color(tmp3, (e->data ? (char *)e->data : NULL), COLOR_BRMAGENTA, 0, sizeof(tmp3)),
|
||||
(newstack ? "in new stack" : "in same stack"));
|
||||
res = pbx_exec(c, app, e->data, newstack);
|
||||
return res;
|
||||
} else {
|
||||
|
@ -675,41 +731,6 @@ static int pbx_extension_helper(struct ast_channel *c, char *context, char *exte
|
|||
|
||||
}
|
||||
|
||||
#if 0
|
||||
int ast_pbx_longest_extension(char *context)
|
||||
{
|
||||
/* XXX Not include-aware XXX */
|
||||
struct ast_context *tmp;
|
||||
struct ast_exten *e;
|
||||
int len = 0;
|
||||
if (ast_pthread_mutex_lock(&conlock)) {
|
||||
ast_log(LOG_WARNING, "Unable to obtain lock\n");
|
||||
return -1;
|
||||
}
|
||||
tmp = contexts;
|
||||
while(tmp) {
|
||||
if (!strcasecmp(tmp->name, context)) {
|
||||
/* By locking tmp, not only can the state of its entries not
|
||||
change, but it cannot be destroyed either. */
|
||||
ast_pthread_mutex_lock(&tmp->lock);
|
||||
/* But we can relieve the conlock, as tmp will not change */
|
||||
ast_pthread_mutex_unlock(&conlock);
|
||||
e = tmp->root;
|
||||
while(e) {
|
||||
if (strlen(e->exten) > len)
|
||||
len = strlen(e->exten);
|
||||
e = e->next;
|
||||
}
|
||||
ast_pthread_mutex_unlock(&tmp->lock);
|
||||
return len;
|
||||
}
|
||||
tmp = tmp->next;
|
||||
}
|
||||
ast_log(LOG_WARNING, "No such context '%s'\n", context);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int ast_exists_extension(struct ast_channel *c, char *context, char *exten, int priority, char *callerid)
|
||||
{
|
||||
return pbx_extension_helper(c, context, exten, priority, callerid, HELPER_EXISTS);
|
||||
|
@ -736,7 +757,7 @@ int ast_pbx_run(struct ast_channel *c)
|
|||
|
||||
/* A little initial setup here */
|
||||
if (c->pbx)
|
||||
ast_log(LOG_WARNING, "%s already has PBX structure??\n");
|
||||
ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
|
||||
c->pbx = malloc(sizeof(struct ast_pbx));
|
||||
if (!c->pbx) {
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
|
@ -744,7 +765,7 @@ int ast_pbx_run(struct ast_channel *c)
|
|||
}
|
||||
if (c->amaflags) {
|
||||
if (c->cdr) {
|
||||
ast_log(LOG_WARNING, "%s already has a call record??\n");
|
||||
ast_log(LOG_WARNING, "%s already has a call record??\n", c->name);
|
||||
} else {
|
||||
c->cdr = ast_cdr_alloc();
|
||||
if (!c->cdr) {
|
||||
|
@ -890,6 +911,22 @@ int ast_pbx_run(struct ast_channel *c)
|
|||
if (firstpass)
|
||||
ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
|
||||
out:
|
||||
if (ast_exists_extension(c, c->context, "h", 1, c->callerid)) {
|
||||
strcpy(c->exten, "h");
|
||||
c->priority = 1;
|
||||
while(ast_exists_extension(c, c->context, c->exten, c->priority, c->callerid)) {
|
||||
if ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->callerid))) {
|
||||
/* Something bad happened, or a hangup has been requested. */
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
|
||||
else if (option_verbose > 1)
|
||||
ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
|
||||
break;
|
||||
}
|
||||
c->priority++;
|
||||
}
|
||||
}
|
||||
|
||||
pbx_destroy(c->pbx);
|
||||
c->pbx = NULL;
|
||||
if (res != AST_PBX_KEEPALIVE)
|
||||
|
@ -973,7 +1010,7 @@ int ast_context_remove_include2(struct ast_context *con, char *include, char *re
|
|||
{
|
||||
struct ast_include *i, *pi = NULL;
|
||||
|
||||
if (pthread_mutex_lock(&con->lock)) return -1;
|
||||
if (ast_pthread_mutex_lock(&con->lock)) return -1;
|
||||
|
||||
/* walk includes */
|
||||
i = con->includes;
|
||||
|
@ -1045,7 +1082,7 @@ int ast_context_remove_switch2(struct ast_context *con, char *sw, char *data, ch
|
|||
{
|
||||
struct ast_sw *i, *pi = NULL;
|
||||
|
||||
if (pthread_mutex_lock(&con->lock)) return -1;
|
||||
if (ast_pthread_mutex_lock(&con->lock)) return -1;
|
||||
|
||||
/* walk switchs */
|
||||
i = con->alts;
|
||||
|
@ -1215,6 +1252,7 @@ int ast_context_remove_extension2(struct ast_context *con, char *extension, int
|
|||
int ast_register_application(char *app, int (*execute)(struct ast_channel *, void *), char *synopsis, char *description)
|
||||
{
|
||||
struct ast_app *tmp;
|
||||
char tmps[80];
|
||||
if (ast_pthread_mutex_lock(&applock)) {
|
||||
ast_log(LOG_ERROR, "Unable to lock application list\n");
|
||||
return -1;
|
||||
|
@ -1230,6 +1268,7 @@ int ast_register_application(char *app, int (*execute)(struct ast_channel *, voi
|
|||
}
|
||||
tmp = malloc(sizeof(struct ast_app));
|
||||
if (tmp) {
|
||||
memset(tmp, 0, sizeof(struct ast_app));
|
||||
strncpy(tmp->name, app, sizeof(tmp->name)-1);
|
||||
tmp->execute = execute;
|
||||
tmp->synopsis = synopsis;
|
||||
|
@ -1242,7 +1281,7 @@ int ast_register_application(char *app, int (*execute)(struct ast_channel *, voi
|
|||
return -1;
|
||||
}
|
||||
if (option_verbose > 1)
|
||||
ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", tmp->name);
|
||||
ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
|
||||
ast_pthread_mutex_unlock(&applock);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1769,7 +1808,7 @@ struct ast_context *ast_context_create(char *name, char *registrar)
|
|||
tmp = malloc(sizeof(struct ast_context));
|
||||
if (tmp) {
|
||||
memset(tmp, 0, sizeof(struct ast_context));
|
||||
pthread_mutex_init(&tmp->lock, NULL);
|
||||
ast_pthread_mutex_init(&tmp->lock);
|
||||
strncpy(tmp->name, name, sizeof(tmp->name)-1);
|
||||
tmp->root = NULL;
|
||||
tmp->registrar = registrar;
|
||||
|
@ -1821,6 +1860,255 @@ int ast_context_add_include(char *context, char *include, char *registrar)
|
|||
return -1;
|
||||
}
|
||||
|
||||
#define FIND_NEXT \
|
||||
do { \
|
||||
c = info; \
|
||||
while(*c && (*c != '|')) c++; \
|
||||
if (*c) *c = '\0'; else c = NULL; \
|
||||
} while(0)
|
||||
|
||||
static void get_timerange(struct ast_include *i, char *times)
|
||||
{
|
||||
char *e;
|
||||
int x;
|
||||
int s1, s2;
|
||||
int e1, e2;
|
||||
/* Star is all times */
|
||||
if (!strlen(times) || !strcmp(times, "*")) {
|
||||
for (x=0;x<24;x++)
|
||||
i->minmask[x] = (1 << 30) - 1;
|
||||
return;
|
||||
}
|
||||
/* Otherwise expect a range */
|
||||
e = strchr(times, '-');
|
||||
if (!e) {
|
||||
ast_log(LOG_WARNING, "Time range is not valid. Assuming no time.\n");
|
||||
return;
|
||||
}
|
||||
*e = '\0';
|
||||
e++;
|
||||
while(*e && !isdigit(*e)) e++;
|
||||
if (!*e) {
|
||||
ast_log(LOG_WARNING, "Invalid time range. Assuming no time.\n");
|
||||
return;
|
||||
}
|
||||
if (sscanf(times, "%d:%d", &s1, &s2) != 2) {
|
||||
ast_log(LOG_WARNING, "%s isn't a time. Assuming no time.\n", times);
|
||||
return;
|
||||
}
|
||||
if (sscanf(e, "%d:%d", &e1, &e2) != 2) {
|
||||
ast_log(LOG_WARNING, "%s isn't a time. Assuming no time.\n", e);
|
||||
return;
|
||||
}
|
||||
s1 = s1 * 30 + s2/2;
|
||||
if ((s1 < 0) || (s1 >= 24*30)) {
|
||||
ast_log(LOG_WARNING, "%s isn't a valid star time. Assuming no time.\n", times);
|
||||
return;
|
||||
}
|
||||
e1 = e1 * 30 + e2/2;
|
||||
if ((e1 < 0) || (e2 >= 24*30)) {
|
||||
ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times);
|
||||
return;
|
||||
}
|
||||
/* Go through the time and enable each appropriate bit */
|
||||
for (x=s1;x != e1;x = (x + 1) % (24 * 30)) {
|
||||
i->minmask[x/30] |= (1 << (x % 30));
|
||||
}
|
||||
/* Do the last one */
|
||||
i->minmask[x/30] |= (1 << (x % 30));
|
||||
/* All done */
|
||||
}
|
||||
|
||||
static char *days[] =
|
||||
{
|
||||
"sun",
|
||||
"mon",
|
||||
"tue",
|
||||
"wed",
|
||||
"thu",
|
||||
"fri",
|
||||
"sat",
|
||||
};
|
||||
|
||||
static unsigned int get_dow(char *dow)
|
||||
{
|
||||
char *c;
|
||||
/* The following line is coincidence, really! */
|
||||
int s, e, x;
|
||||
unsigned mask;
|
||||
/* Check for all days */
|
||||
if (!strlen(dow) || !strcmp(dow, "*"))
|
||||
return (1 << 7) - 1;
|
||||
/* Get start and ending days */
|
||||
c = strchr(dow, '-');
|
||||
if (c) {
|
||||
*c = '\0';
|
||||
c++;
|
||||
}
|
||||
/* Find the start */
|
||||
s = 0;
|
||||
while((s < 7) && strcasecmp(dow, days[s])) s++;
|
||||
if (s >= 7) {
|
||||
ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", dow);
|
||||
return 0;
|
||||
}
|
||||
if (c) {
|
||||
e = 0;
|
||||
while((e < 7) && strcasecmp(dow, days[e])) e++;
|
||||
if (e >= 7) {
|
||||
ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
e = s;
|
||||
mask = 0;
|
||||
for (x=s;x!=e;x = (x + 1) % 7) {
|
||||
mask |= (1 << x);
|
||||
}
|
||||
/* One last one */
|
||||
mask |= (1 << x);
|
||||
return mask;
|
||||
}
|
||||
|
||||
static unsigned int get_day(char *day)
|
||||
{
|
||||
char *c;
|
||||
/* The following line is coincidence, really! */
|
||||
int s, e, x;
|
||||
unsigned int mask;
|
||||
/* Check for all days */
|
||||
if (!strlen(day) || !strcmp(day, "*")) {
|
||||
mask = (1 << 30) + ((1 << 30) - 1);
|
||||
}
|
||||
/* Get start and ending days */
|
||||
c = strchr(day, '-');
|
||||
if (c) {
|
||||
*c = '\0';
|
||||
c++;
|
||||
}
|
||||
/* Find the start */
|
||||
if (sscanf(day, "%d", &s) != 1) {
|
||||
ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day);
|
||||
return 0;
|
||||
}
|
||||
if ((s < 1) || (s > 31)) {
|
||||
ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day);
|
||||
return 0;
|
||||
}
|
||||
s--;
|
||||
if (c) {
|
||||
if (sscanf(c, "%d", &e) != 1) {
|
||||
ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
|
||||
return 0;
|
||||
}
|
||||
if ((e < 1) || (e > 31)) {
|
||||
ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
|
||||
return 0;
|
||||
}
|
||||
e--;
|
||||
} else
|
||||
e = s;
|
||||
mask = 0;
|
||||
for (x=s;x!=e;x = (x + 1) % 31) {
|
||||
mask |= (1 << x);
|
||||
}
|
||||
mask |= (1 << x);
|
||||
return mask;
|
||||
}
|
||||
|
||||
static char *months[] =
|
||||
{
|
||||
"jan",
|
||||
"feb",
|
||||
"mar",
|
||||
"apr",
|
||||
"may",
|
||||
"jun",
|
||||
"jul",
|
||||
"aug",
|
||||
"sep",
|
||||
"oct",
|
||||
"nov",
|
||||
"dec",
|
||||
};
|
||||
|
||||
static unsigned int get_month(char *mon)
|
||||
{
|
||||
char *c;
|
||||
/* The following line is coincidence, really! */
|
||||
int s, e, x;
|
||||
unsigned int mask;
|
||||
/* Check for all days */
|
||||
if (!strlen(mon) || !strcmp(mon, "*"))
|
||||
return (1 << 12) - 1;
|
||||
/* Get start and ending days */
|
||||
c = strchr(mon, '-');
|
||||
if (c) {
|
||||
*c = '\0';
|
||||
c++;
|
||||
}
|
||||
/* Find the start */
|
||||
s = 0;
|
||||
while((s < 12) && strcasecmp(mon, months[s])) s++;
|
||||
if (s >= 12) {
|
||||
ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", mon);
|
||||
return 0;
|
||||
}
|
||||
if (c) {
|
||||
e = 0;
|
||||
while((e < 12) && strcasecmp(mon, months[e])) e++;
|
||||
if (e >= 12) {
|
||||
ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", c);
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
e = s;
|
||||
mask = 0;
|
||||
for (x=s;x!=e;x = (x + 1) % 12) {
|
||||
mask |= (1 << x);
|
||||
}
|
||||
/* One last one */
|
||||
mask |= (1 << x);
|
||||
return mask;
|
||||
}
|
||||
|
||||
static void build_timing(struct ast_include *i, char *info)
|
||||
{
|
||||
char *c;
|
||||
/* Check for empty just in case */
|
||||
if (!strlen(info))
|
||||
return;
|
||||
i->hastime = 1;
|
||||
/* Assume everything except time */
|
||||
i->monthmask = (1 << 12) - 1;
|
||||
i->daymask = (1 << 30) - 1 + (1 << 30);
|
||||
i->dowmask = (1 << 7) - 1;
|
||||
/* Avoid using strtok */
|
||||
FIND_NEXT;
|
||||
|
||||
/* Info has the time range, start with that */
|
||||
get_timerange(i, info);
|
||||
info = c;
|
||||
if (!info)
|
||||
return;
|
||||
FIND_NEXT;
|
||||
/* Now check for day of week */
|
||||
i->dowmask = get_dow(info);
|
||||
|
||||
info = c;
|
||||
if (!info)
|
||||
return;
|
||||
FIND_NEXT;
|
||||
/* Now check for the day of the month */
|
||||
i->daymask = get_day(info);
|
||||
info = c;
|
||||
if (!info)
|
||||
return;
|
||||
FIND_NEXT;
|
||||
/* And finally go for the month */
|
||||
i->monthmask = get_month(info);
|
||||
}
|
||||
|
||||
/*
|
||||
* errno values
|
||||
* ENOMEM - out of memory
|
||||
|
@ -1832,6 +2120,7 @@ int ast_context_add_include2(struct ast_context *con, char *value,
|
|||
char *registrar)
|
||||
{
|
||||
struct ast_include *new_include;
|
||||
char *c;
|
||||
struct ast_include *i, *il = NULL; /* include, include_last */
|
||||
|
||||
/* allocate new include structure ... */
|
||||
|
@ -1842,7 +2131,17 @@ int ast_context_add_include2(struct ast_context *con, char *value,
|
|||
}
|
||||
|
||||
/* ... fill in this structure ... */
|
||||
memset(new_include, 0, sizeof(struct ast_include));
|
||||
strncpy(new_include->name, value, sizeof(new_include->name)-1);
|
||||
strncpy(new_include->rname, value, sizeof(new_include->rname)-1);
|
||||
c = new_include->rname;
|
||||
/* Strip off timing info */
|
||||
while(*c && (*c != '|')) c++;
|
||||
/* Process if it's there */
|
||||
if (*c) {
|
||||
build_timing(new_include, c+1);
|
||||
*c = '\0';
|
||||
}
|
||||
new_include->next = NULL;
|
||||
new_include->registrar = registrar;
|
||||
|
||||
|
@ -1932,6 +2231,7 @@ int ast_context_add_switch2(struct ast_context *con, char *value,
|
|||
}
|
||||
|
||||
/* ... fill in this structure ... */
|
||||
memset(new_sw, 0, sizeof(struct ast_sw));
|
||||
strncpy(new_sw->name, value, sizeof(new_sw->name)-1);
|
||||
if (data)
|
||||
strncpy(new_sw->data, data, sizeof(new_sw->data)-1);
|
||||
|
@ -2068,10 +2368,11 @@ int ast_context_add_ignorepat2(struct ast_context *con, char *value, char *regis
|
|||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
memset(ignorepat, 0, sizeof(struct ast_ignorepat));
|
||||
strncpy(ignorepat->pattern, value, sizeof(ignorepat->pattern)-1);
|
||||
ignorepat->next = NULL;
|
||||
ignorepat->registrar = registrar;
|
||||
pthread_mutex_lock(&con->lock);
|
||||
ast_pthread_mutex_lock(&con->lock);
|
||||
ignorepatc = con->ignorepats;
|
||||
while(ignorepatc) {
|
||||
ignorepatl = ignorepatc;
|
||||
|
@ -2194,6 +2495,7 @@ int ast_add_extension2(struct ast_context *con,
|
|||
/* Be optimistic: Build the extension structure first */
|
||||
tmp = malloc(sizeof(struct ast_exten));
|
||||
if (tmp) {
|
||||
memset(tmp, 0, sizeof(struct ast_exten));
|
||||
ext_strncpy(tmp->exten, extension, sizeof(tmp->exten));
|
||||
tmp->priority = priority;
|
||||
if (callerid) {
|
||||
|
@ -2474,21 +2776,10 @@ static int pbx_builtin_prefix(struct ast_channel *chan, void *data)
|
|||
static int pbx_builtin_wait(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int ms;
|
||||
struct ast_frame *f;
|
||||
/* Wait for "n" seconds */
|
||||
if (data && atoi((char *)data)) {
|
||||
ms = atoi((char *)data) * 1000;
|
||||
while(ms > 0) {
|
||||
ms = ast_waitfor(chan, ms);
|
||||
if (ms <0)
|
||||
return -1;
|
||||
if (ms > 0) {
|
||||
f = ast_read(chan);
|
||||
if (!f)
|
||||
return -1;
|
||||
ast_frfree(f);
|
||||
}
|
||||
}
|
||||
return ast_safe_sleep(chan, ms);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
344
res/res_adsi.c
344
res/res_adsi.c
|
@ -99,27 +99,6 @@ static int adsi_generate(unsigned char *buf, int msgtype, char *msg, int msglen,
|
|||
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int adsi_careful_send(struct ast_channel *chan, unsigned char *buf, int len, int *remainder)
|
||||
{
|
||||
int res;
|
||||
fd_set fds;
|
||||
while(len) {
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(chan->fds[0], &fds);
|
||||
select(chan->fds[0] + 1, NULL, &fds, NULL, NULL);
|
||||
res = write(chan->fds[0], buf, len);
|
||||
if (res < 1) {
|
||||
ast_log(LOG_WARNING, "Failed to write: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
buf += res;
|
||||
len -= res;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
static int adsi_careful_send(struct ast_channel *chan, unsigned char *buf, int len, int *remainder)
|
||||
{
|
||||
/* Sends carefully on a full duplex channel by using reading for
|
||||
|
@ -190,7 +169,6 @@ static int adsi_careful_send(struct ast_channel *chan, unsigned char *buf, int l
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int __adsi_transmit_messages(struct ast_channel *chan, unsigned char **msg, int *msglen, int *msgtype)
|
||||
{
|
||||
|
@ -305,7 +283,7 @@ static int __adsi_transmit_messages(struct ast_channel *chan, unsigned char **ms
|
|||
break;
|
||||
else {
|
||||
retries++;
|
||||
ast_log(LOG_DEBUG, "Retransmitting (%d), from %d\n", start + 1);
|
||||
ast_log(LOG_DEBUG, "Retransmitting (%d), from %d\n", retries, start + 1);
|
||||
}
|
||||
} else {
|
||||
retries++;
|
||||
|
@ -502,14 +480,15 @@ int adsi_download_connect(unsigned char *buf, unsigned char *service, unsigned
|
|||
/* Delimiter */
|
||||
buf[bytes++] = 0xff;
|
||||
|
||||
for (x=0;x<4;x++)
|
||||
for (x=0;x<4;x++) {
|
||||
buf[bytes++] = fdn[x];
|
||||
}
|
||||
for (x=0;x<4;x++)
|
||||
buf[bytes++] = sec[x];
|
||||
if (ver > -1)
|
||||
buf[bytes++] = ver & 0xff;
|
||||
buf[bytes++] = ver & 0xff;
|
||||
|
||||
buf[1] = bytes - 2;
|
||||
|
||||
return bytes;
|
||||
|
||||
}
|
||||
|
@ -529,6 +508,158 @@ int adsi_disconnect_session(unsigned char *buf)
|
|||
|
||||
}
|
||||
|
||||
int adsi_query_cpeid(unsigned char *buf)
|
||||
{
|
||||
int bytes = 0;
|
||||
buf[bytes++] = ADSI_QUERY_CPEID;
|
||||
/* Reserve space for length */
|
||||
bytes++;
|
||||
buf[1] = bytes - 2;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int adsi_query_cpeinfo(unsigned char *buf)
|
||||
{
|
||||
int bytes = 0;
|
||||
buf[bytes++] = ADSI_QUERY_CONFIG;
|
||||
/* Reserve space for length */
|
||||
bytes++;
|
||||
buf[1] = bytes - 2;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int adsi_read_encoded_dtmf(struct ast_channel *chan, unsigned char *buf, int maxlen)
|
||||
{
|
||||
int bytes = 0;
|
||||
int res;
|
||||
unsigned char current = 0;
|
||||
int gotstar = 0;
|
||||
int pos = 0;
|
||||
memset(buf, 0, sizeof(buf));
|
||||
while(bytes <= maxlen) {
|
||||
/* Wait up to a second for a digit */
|
||||
res = ast_waitfordigit(chan, 1000);
|
||||
if (!res)
|
||||
break;
|
||||
if (res == '*') {
|
||||
gotstar = 1;
|
||||
continue;
|
||||
}
|
||||
/* Ignore anything other than a digit */
|
||||
if ((res < '0') || (res > '9'))
|
||||
continue;
|
||||
res -= '0';
|
||||
if (gotstar)
|
||||
res += 9;
|
||||
if (pos) {
|
||||
pos = 0;
|
||||
buf[bytes++] = (res << 4) | current;
|
||||
} else {
|
||||
pos = 1;
|
||||
current = res;
|
||||
}
|
||||
gotstar = 0;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int adsi_get_cpeid(struct ast_channel *chan, unsigned char *cpeid, int voice)
|
||||
{
|
||||
char buf[256];
|
||||
int bytes = 0;
|
||||
int res;
|
||||
bytes += adsi_data_mode(buf);
|
||||
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
|
||||
|
||||
bytes = 0;
|
||||
bytes += adsi_query_cpeid(buf);
|
||||
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
|
||||
|
||||
/* Get response */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
res = adsi_read_encoded_dtmf(chan, cpeid, 4);
|
||||
if (res != 4) {
|
||||
ast_log(LOG_WARNING, "Got %d bytes back of encoded DTMF, expecting 4\n", res);
|
||||
res = 0;
|
||||
} else {
|
||||
res = 1;
|
||||
}
|
||||
|
||||
if (voice) {
|
||||
bytes = 0;
|
||||
bytes += adsi_voice_mode(buf, 0);
|
||||
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
|
||||
/* Ignore the resulting DTMF B announcing it's in voice mode */
|
||||
ast_waitfordigit(chan, 1000);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int adsi_get_cpeinfo(struct ast_channel *chan, int *width, int *height, int *buttons, int voice)
|
||||
{
|
||||
char buf[256];
|
||||
int bytes = 0;
|
||||
int res;
|
||||
bytes += adsi_data_mode(buf);
|
||||
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
|
||||
|
||||
bytes = 0;
|
||||
bytes += adsi_query_cpeinfo(buf);
|
||||
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
|
||||
|
||||
/* Get width */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
res = ast_readstring(chan, buf, 2, 1000, 500, "");
|
||||
if (res < 0)
|
||||
return res;
|
||||
if (strlen(buf) != 2) {
|
||||
ast_log(LOG_WARNING, "Got %d bytes of width, expecting 2\n", res);
|
||||
res = 0;
|
||||
} else {
|
||||
res = 1;
|
||||
}
|
||||
if (width)
|
||||
*width = atoi(buf);
|
||||
/* Get height */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
if (res) {
|
||||
res = ast_readstring(chan, buf, 2, 1000, 500, "");
|
||||
if (res < 0)
|
||||
return res;
|
||||
if (strlen(buf) != 2) {
|
||||
ast_log(LOG_WARNING, "Got %d bytes of height, expecting 2\n", res);
|
||||
res = 0;
|
||||
} else {
|
||||
res = 1;
|
||||
}
|
||||
if (height)
|
||||
*height= atoi(buf);
|
||||
}
|
||||
/* Get buttons */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
if (res) {
|
||||
res = ast_readstring(chan, buf, 1, 1000, 500, "");
|
||||
if (res < 0)
|
||||
return res;
|
||||
if (strlen(buf) != 1) {
|
||||
ast_log(LOG_WARNING, "Got %d bytes of buttons, expecting 1\n", res);
|
||||
res = 0;
|
||||
} else {
|
||||
res = 1;
|
||||
}
|
||||
if (buttons)
|
||||
*buttons = atoi(buf);
|
||||
}
|
||||
if (voice) {
|
||||
bytes = 0;
|
||||
bytes += adsi_voice_mode(buf, 0);
|
||||
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
|
||||
/* Ignore the resulting DTMF B announcing it's in voice mode */
|
||||
ast_waitfordigit(chan, 1000);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int adsi_data_mode(unsigned char *buf)
|
||||
{
|
||||
int bytes=0;
|
||||
|
@ -544,6 +675,36 @@ int adsi_data_mode(unsigned char *buf)
|
|||
|
||||
}
|
||||
|
||||
int adsi_clear_soft_keys(unsigned char *buf)
|
||||
{
|
||||
int bytes=0;
|
||||
|
||||
/* Message type */
|
||||
buf[bytes++] = ADSI_CLEAR_SOFTKEY;
|
||||
|
||||
/* Reserve space for length */
|
||||
bytes++;
|
||||
|
||||
buf[1] = bytes - 2;
|
||||
return bytes;
|
||||
|
||||
}
|
||||
|
||||
int adsi_clear_screen(unsigned char *buf)
|
||||
{
|
||||
int bytes=0;
|
||||
|
||||
/* Message type */
|
||||
buf[bytes++] = ADSI_CLEAR_SCREEN;
|
||||
|
||||
/* Reserve space for length */
|
||||
bytes++;
|
||||
|
||||
buf[1] = bytes - 2;
|
||||
return bytes;
|
||||
|
||||
}
|
||||
|
||||
int adsi_voice_mode(unsigned char *buf, int when)
|
||||
{
|
||||
int bytes=0;
|
||||
|
@ -719,86 +880,6 @@ int adsi_set_line(unsigned char *buf, int page, int line)
|
|||
static int total = 0;
|
||||
static int speeds = 0;
|
||||
|
||||
#if 0
|
||||
int adsi_channel_init(struct ast_channel *chan)
|
||||
{
|
||||
char dsp[256];
|
||||
char keys[256];
|
||||
int bytes;
|
||||
int x;
|
||||
unsigned char *msgs[3];
|
||||
unsigned char keyd[6];
|
||||
int lens[3];
|
||||
int types[3];
|
||||
memset(dsp, 0, sizeof(dsp));
|
||||
memset(keys, 0, sizeof(keys));
|
||||
memset(msgs, 0, sizeof(msgs));
|
||||
|
||||
/* Start with initial display setup */
|
||||
bytes = 0;
|
||||
bytes += adsi_connect_session(dsp, NULL, -1);
|
||||
for (x=0;x<total;x++) {
|
||||
bytes += adsi_display(dsp + bytes, ADSI_INFO_PAGE, x + 1, aligns[x], 0,
|
||||
strlen(intro[x]) ? intro[x] : " ", "");
|
||||
}
|
||||
bytes += adsi_set_line(dsp + bytes, ADSI_INFO_PAGE, 1);
|
||||
msgs[0] = dsp;
|
||||
lens[0] = bytes;
|
||||
types[0] = ADSI_MSG_DISPLAY;
|
||||
|
||||
/* Prepare key setup messages */
|
||||
|
||||
if (speeds) {
|
||||
bytes = 0;
|
||||
memset(keyd, 0, sizeof(keyd));
|
||||
for (x=0;x<speeds;x++) {
|
||||
bytes += adsi_load_soft_key(keys + bytes, ADSI_SPEED_DIAL + x,
|
||||
speeddial[x][1], speeddial[x][2], speeddial[x][0]);
|
||||
keyd[x] = ADSI_SPEED_DIAL + x;
|
||||
}
|
||||
bytes += adsi_set_keys(keys + bytes, keyd);
|
||||
msgs[1] = keys;
|
||||
lens[1] = bytes;
|
||||
types[1] = ADSI_MSG_DISPLAY;
|
||||
}
|
||||
adsi_transmit_messages(chan, msgs, lens, types);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int adsi_channel_init(struct ast_channel *chan)
|
||||
{
|
||||
char dsp[256];
|
||||
int bytes;
|
||||
int x;
|
||||
unsigned char keyd[6];
|
||||
|
||||
memset(dsp, 0, sizeof(dsp));
|
||||
|
||||
/* Start with initial display setup */
|
||||
bytes = 0;
|
||||
bytes += adsi_connect_session(dsp, NULL, -1);
|
||||
for (x=0;x<total;x++) {
|
||||
bytes += adsi_display(dsp + bytes, ADSI_INFO_PAGE, x + 1, aligns[x], 0,
|
||||
strlen(intro[x]) ? intro[x] : " ", "");
|
||||
}
|
||||
bytes += adsi_set_line(dsp + bytes, ADSI_INFO_PAGE, 1);
|
||||
|
||||
/* Prepare key setup messages */
|
||||
|
||||
if (speeds) {
|
||||
memset(keyd, 0, sizeof(keyd));
|
||||
for (x=0;x<speeds;x++) {
|
||||
bytes += adsi_load_soft_key(dsp + bytes, ADSI_SPEED_DIAL + x,
|
||||
speeddial[x][1], speeddial[x][2], speeddial[x][0], 0);
|
||||
keyd[x] = ADSI_SPEED_DIAL + x;
|
||||
}
|
||||
bytes += adsi_set_keys(dsp + bytes, keyd);
|
||||
}
|
||||
adsi_transmit_message(chan, dsp, bytes, ADSI_MSG_DISPLAY);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int adsi_channel_restore(struct ast_channel *chan)
|
||||
{
|
||||
char dsp[256];
|
||||
|
@ -826,6 +907,26 @@ int adsi_channel_restore(struct ast_channel *chan)
|
|||
|
||||
}
|
||||
|
||||
int adsi_print(struct ast_channel *chan, char **lines, int *aligns, int voice)
|
||||
{
|
||||
char buf[4096];
|
||||
int bytes=0;
|
||||
int res;
|
||||
int x;
|
||||
for(x=0;lines[x];x++)
|
||||
bytes += adsi_display(buf + bytes, ADSI_INFO_PAGE, x+1, aligns[x],0, lines[x], "");
|
||||
bytes += adsi_set_line(buf + bytes, ADSI_INFO_PAGE, 1);
|
||||
if (voice) {
|
||||
bytes += adsi_voice_mode(buf + bytes, 0);
|
||||
}
|
||||
res = adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
|
||||
if (voice) {
|
||||
/* Ignore the resulting DTMF B announcing it's in voice mode */
|
||||
ast_waitfordigit(chan, 1000);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int adsi_load_session(struct ast_channel *chan, unsigned char *app, int ver, int data)
|
||||
{
|
||||
char dsp[256];
|
||||
|
@ -845,21 +946,24 @@ int adsi_load_session(struct ast_channel *chan, unsigned char *app, int ver, int
|
|||
/* Prepare key setup messages */
|
||||
if (adsi_transmit_message(chan, dsp, bytes, ADSI_MSG_DISPLAY))
|
||||
return -1;
|
||||
res = ast_readstring(chan, resp, 1, 1200, 1200, "");
|
||||
if (res < 0)
|
||||
return -1;
|
||||
if (res) {
|
||||
ast_log(LOG_DEBUG, "No response from CPE about version. Assuming not there.\n");
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(resp, "B")) {
|
||||
ast_log(LOG_DEBUG, "CPE has script '%s' version %d already loaded\n", app, ver);
|
||||
if (app) {
|
||||
res = ast_readstring(chan, resp, 1, 1200, 1200, "");
|
||||
if (res < 0)
|
||||
return -1;
|
||||
if (res) {
|
||||
ast_log(LOG_DEBUG, "No response from CPE about version. Assuming not there.\n");
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(resp, "B")) {
|
||||
ast_log(LOG_DEBUG, "CPE has script '%s' version %d already loaded\n", app, ver);
|
||||
return 1;
|
||||
} else if (!strcmp(resp, "A")) {
|
||||
ast_log(LOG_DEBUG, "CPE hasn't script '%s' version %d already loaded\n", app, ver);
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Unexpected CPE response to script query: %s\n", resp);
|
||||
}
|
||||
} else
|
||||
return 1;
|
||||
} else if (!strcmp(resp, "A")) {
|
||||
ast_log(LOG_DEBUG, "CPE hasn't script '%s' version %d already loaded\n", app, ver);
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Unexpected CPE response to script query: %s\n", resp);
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
|
Reference in New Issue